1 /*-------------------------------------------------------------------------
2 SDCCgen51.c - source file for code generation for 8051
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
27 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
28 Made everything static
29 -------------------------------------------------------------------------*/
38 #include "SDCCglobl.h"
42 #include "SDCCpeeph.h"
46 char *aopLiteral (value * val, int offset);
47 char *aopLiteralLong (value * val, int offset, int size);
50 /* this is the down and dirty file with all kinds of
51 kludgy & hacky stuff. This is what it is all about
52 CODE GENERATION for a specific MCU . some of the
53 routines may be reusable, will have to see */
55 static char *zero = "#0x00";
56 static char *one = "#0x01";
60 {"dpl", "dph", "b", "a"};
61 unsigned fReturnSizeMCS51 = 4; /* shared with ralloc.c */
62 char **fReturn = fReturn8051;
63 static char *accUse[] =
66 static unsigned short rbank = -1;
68 #define AOP(op) op->aop
69 #define AOP_TYPE(op) AOP(op)->type
70 #define AOP_SIZE(op) AOP(op)->size
71 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
72 AOP_TYPE(x) == AOP_R0))
74 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
75 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
77 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
78 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
79 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
82 #define SYM_BP(sym) (SPEC_OCLS (sym->etype)->paged ? "_bpx" : "_bp")
84 #define R0INB _G.bu.bs.r0InB
85 #define R1INB _G.bu.bs.r1InB
86 #define OPINB _G.bu.bs.OpInB
87 #define BINUSE _G.bu.BInUse
97 short r0InB : 2;//2 so we can see it overflow
98 short r1InB : 2;//2 so we can see it overflow
99 short OpInB : 2;//2 so we can see it overflow
108 iCode *current_iCode;
113 static char *rb1regs[] = {
114 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7",
115 "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7"
118 extern int mcs51_ptrRegReq;
119 extern int mcs51_nRegs;
120 extern FILE *codeOutFile;
121 static void saveRBank (int, iCode *, bool);
123 #define RESULTONSTACK(x) \
124 (IC_RESULT(x) && IC_RESULT(x)->aop && \
125 IC_RESULT(x)->aop->type == AOP_STK )
127 #define MOVA(x) mova(x) /* use function to avoid multiple eval */
128 #define CLRC emitcode("clr","c")
129 #define SETC emitcode("setb","c")
131 static lineNode *lineHead = NULL;
132 static lineNode *lineCurr = NULL;
134 static unsigned char SLMask[] =
135 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
136 0xE0, 0xC0, 0x80, 0x00};
137 static unsigned char SRMask[] =
138 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
139 0x07, 0x03, 0x01, 0x00};
146 /*-----------------------------------------------------------------*/
147 /* emitcode - writes the code into a file : for now it is simple */
148 /*-----------------------------------------------------------------*/
150 emitcode (char *inst, const char *fmt,...)
153 char lb[INITIAL_INLINEASM];
161 SNPRINTF (lb, sizeof(lb), "%s\t", inst);
163 SNPRINTF (lb, sizeof(lb), "%s", inst);
164 tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb), fmt, ap);
167 tvsprintf (lb, sizeof(lb), fmt, ap);
169 while (isspace ((unsigned char)*lbp))
173 lineCurr = (lineCurr ?
174 connectLine (lineCurr, newLineNode (lb)) :
175 (lineHead = newLineNode (lb)));
176 lineCurr->isInline = _G.inLine;
177 lineCurr->isDebug = _G.debugLine;
178 lineCurr->ic = _G.current_iCode;
179 lineCurr->isComment = (*lbp==';');
183 /*-----------------------------------------------------------------*/
184 /* mcs51_emitDebuggerSymbol - associate the current code location */
185 /* with a debugger symbol */
186 /*-----------------------------------------------------------------*/
188 mcs51_emitDebuggerSymbol (char * debugSym)
191 emitcode ("", "%s ==.", debugSym);
195 /*-----------------------------------------------------------------*/
196 /* mova - moves specified value into accumulator */
197 /*-----------------------------------------------------------------*/
201 /* do some early peephole optimization */
202 if (!strncmp(x, "a", 2) || !strncmp(x, "acc", 4))
205 emitcode("mov","a,%s", x);
208 /*-----------------------------------------------------------------*/
209 /* movc - moves specified value into the carry */
210 /*-----------------------------------------------------------------*/
218 else if (strcmp (s, "c"))
219 {/* it's not in carry already */
221 /* set C, if a >= 1 */
222 emitcode ("add", "a,#0xff");
226 /*-----------------------------------------------------------------*/
227 /* pushB - saves register B if necessary */
228 /*-----------------------------------------------------------------*/
232 bool pushedB = FALSE;
236 emitcode ("push", "b");
237 // printf("B was in use !\n");
247 /*-----------------------------------------------------------------*/
248 /* popB - restores value of register B if necessary */
249 /*-----------------------------------------------------------------*/
255 emitcode ("pop", "b");
263 /*-----------------------------------------------------------------*/
264 /* pushReg - saves register */
265 /*-----------------------------------------------------------------*/
267 pushReg (int index, bool bits_pushed)
269 regs * reg = mcs51_regWithIdx (index);
270 if (reg->type == REG_BIT)
273 emitcode ("push", "%s", reg->base);
277 emitcode ("push", "%s", reg->dname);
281 /*-----------------------------------------------------------------*/
282 /* popReg - restores register */
283 /*-----------------------------------------------------------------*/
285 popReg (int index, bool bits_popped)
287 regs * reg = mcs51_regWithIdx (index);
288 if (reg->type == REG_BIT)
291 emitcode ("pop", "%s", reg->base);
295 emitcode ("pop", "%s", reg->dname);
299 /*-----------------------------------------------------------------*/
300 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
301 /*-----------------------------------------------------------------*/
303 getFreePtr (iCode * ic, asmop ** aopp, bool result)
308 /* the logic: if r0 & r1 used in the instruction
309 then we are in trouble otherwise */
311 /* first check if r0 & r1 are used by this
312 instruction, in which case we are in trouble */
313 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
314 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
319 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
320 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
322 /* if no usage of r0 then return it */
325 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
326 (*aopp)->type = AOP_R0;
328 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
331 /* if no usage of r1 then return it */
334 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
335 (*aopp)->type = AOP_R1;
337 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
340 /* now we know they both have usage */
341 /* if r0 not used in this instruction */
344 /* push it if not already pushed */
347 emitcode ("mov", "b,%s",
348 mcs51_regWithIdx (R0_IDX)->dname);
351 else if (!_G.r0Pushed)
353 emitcode ("push", "%s",
354 mcs51_regWithIdx (R0_IDX)->dname);
358 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
359 (*aopp)->type = AOP_R0;
361 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
364 /* if r1 not used then */
368 /* push it if not already pushed */
371 emitcode ("mov", "b,%s",
372 mcs51_regWithIdx (R1_IDX)->dname);
375 else if (!_G.r1Pushed)
377 emitcode ("push", "%s",
378 mcs51_regWithIdx (R1_IDX)->dname);
382 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
383 (*aopp)->type = AOP_R1;
384 return mcs51_regWithIdx (R1_IDX);
387 /* I said end of world, but not quite end of world yet */
389 /* we can push it on the stack */
390 (*aopp)->type = AOP_STK;
393 /* in the case that result AND left AND right needs a pointer reg
394 we can safely use the result's */
395 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX)) {
396 (*aopp)->type = AOP_R0;
397 return mcs51_regWithIdx (R0_IDX);
399 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX)) {
400 (*aopp)->type = AOP_R1;
401 return mcs51_regWithIdx (R1_IDX);
405 /* now this is REALLY the end of the world */
406 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
407 "getFreePtr should never reach here");
412 /*-----------------------------------------------------------------*/
413 /* getTempRegs - initialize an array of pointers to GPR registers */
414 /* that are not in use. Returns 1 if the requested */
415 /* number of registers were available, 0 otherwise. */
416 /*-----------------------------------------------------------------*/
418 getTempRegs(regs **tempRegs, int size, iCode *ic)
425 ic = _G.current_iCode;
431 freeRegs = newBitVect(8);
432 bitVectSetBit (freeRegs, R2_IDX);
433 bitVectSetBit (freeRegs, R3_IDX);
434 bitVectSetBit (freeRegs, R4_IDX);
435 bitVectSetBit (freeRegs, R5_IDX);
436 bitVectSetBit (freeRegs, R6_IDX);
437 bitVectSetBit (freeRegs, R7_IDX);
439 if (IFFUNC_CALLEESAVES(_G.currentFunc->type))
441 bitVect * newfreeRegs;
442 newfreeRegs = bitVectIntersect (freeRegs, _G.currentFunc->regsUsed);
443 freeBitVect(freeRegs);
444 freeRegs = newfreeRegs;
446 freeRegs = bitVectCplAnd (freeRegs, ic->rMask);
449 for (i=0; i<freeRegs->size; i++)
451 if (bitVectBitValue(freeRegs,i))
452 tempRegs[offset++] = mcs51_regWithIdx(i);
455 freeBitVect(freeRegs);
460 freeBitVect(freeRegs);
465 /*-----------------------------------------------------------------*/
466 /* newAsmop - creates a new asmOp */
467 /*-----------------------------------------------------------------*/
469 newAsmop (short type)
473 aop = Safe_calloc (1, sizeof (asmop));
478 /*-----------------------------------------------------------------*/
479 /* pointerCode - returns the code for a pointer type */
480 /*-----------------------------------------------------------------*/
482 pointerCode (sym_link * etype)
485 return PTR_TYPE (SPEC_OCLS (etype));
489 /*-----------------------------------------------------------------*/
490 /* leftRightUseAcc - returns size of accumulator use by operands */
491 /*-----------------------------------------------------------------*/
493 leftRightUseAcc(iCode *ic)
502 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
503 "null iCode pointer");
510 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
513 size = getSize (OP_SYMBOL (op)->type);
518 else if (ic->op == JUMPTABLE)
521 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
524 size = getSize (OP_SYMBOL (op)->type);
532 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
535 size = getSize (OP_SYMBOL (op)->type);
540 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
543 size = getSize (OP_SYMBOL (op)->type);
555 /*-----------------------------------------------------------------*/
556 /* aopForSym - for a true symbol */
557 /*-----------------------------------------------------------------*/
559 aopForSym (iCode * ic, symbol * sym, bool result)
564 wassertl (ic != NULL, "Got a null iCode");
565 wassertl (sym != NULL, "Got a null symbol");
567 space = SPEC_OCLS (sym->etype);
569 /* if already has one */
573 /* assign depending on the storage class */
574 /* if it is on the stack or indirectly addressable */
575 /* space we need to assign either r0 or r1 to it */
576 if (sym->onStack || sym->iaccess)
578 sym->aop = aop = newAsmop (0);
579 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
580 aop->size = getSize (sym->type);
582 /* now assign the address of the variable to
583 the pointer register */
584 if (aop->type != AOP_STK)
589 char offset = ((sym->stack < 0) ?
590 ((char) (sym->stack - _G.nRegsSaved)) :
591 ((char) sym->stack)) & 0xff;
593 if ((offset >= -3) && (offset <= 3))
595 emitcode ("mov", "%s,%s",
596 aop->aopu.aop_ptr->name, SYM_BP (sym));
599 emitcode ("dec", aop->aopu.aop_ptr->name);
604 emitcode ("inc", aop->aopu.aop_ptr->name);
610 if (_G.accInUse || leftRightUseAcc (ic))
611 emitcode ("push", "acc");
612 emitcode ("mov", "a,%s", SYM_BP (sym));
613 emitcode ("add", "a,#0x%02x", offset);
614 emitcode ("mov", "%s,a",
615 aop->aopu.aop_ptr->name);
616 if (_G.accInUse || leftRightUseAcc (ic))
617 emitcode ("pop", "acc");
621 emitcode ("mov", "%s,#%s",
622 aop->aopu.aop_ptr->name,
624 aop->paged = space->paged;
627 aop->aopu.aop_stk = sym->stack;
631 /* if in bit space */
632 if (IN_BITSPACE (space))
634 sym->aop = aop = newAsmop (AOP_CRY);
635 aop->aopu.aop_dir = sym->rname;
636 aop->size = getSize (sym->type);
639 /* if it is in direct space */
640 if (IN_DIRSPACE (space))
642 //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
643 //printTypeChainRaw(sym->type, NULL);
644 //printf("space = %s\n", space ? space->sname : "NULL");
645 sym->aop = aop = newAsmop (AOP_DIR);
646 aop->aopu.aop_dir = sym->rname;
647 aop->size = getSize (sym->type);
651 /* special case for a function */
652 if (IS_FUNC (sym->type))
654 sym->aop = aop = newAsmop (AOP_IMMD);
655 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
656 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
657 aop->size = getSize (sym->type);
661 /* only remaining is far space */
662 /* in which case DPTR gets the address */
663 sym->aop = aop = newAsmop (AOP_DPTR);
664 emitcode ("mov", "dptr,#%s", sym->rname);
665 aop->size = getSize (sym->type);
667 /* if it is in code space */
668 if (IN_CODESPACE (space))
674 /*-----------------------------------------------------------------*/
675 /* aopForRemat - rematerialzes an object */
676 /*-----------------------------------------------------------------*/
678 aopForRemat (symbol * sym)
680 iCode *ic = sym->rematiCode;
681 asmop *aop = newAsmop (AOP_IMMD);
688 val += (int) operandLitValue (IC_RIGHT (ic));
689 else if (ic->op == '-')
690 val -= (int) operandLitValue (IC_RIGHT (ic));
691 else if (IS_CAST_ICODE(ic)) {
692 sym_link *from_type = operandType(IC_RIGHT(ic));
693 aop->aopu.aop_immd.from_cast_remat = 1;
694 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
695 ptr_type = pointerTypeToGPByte (DCL_TYPE(from_type), NULL, NULL);
699 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
703 sprintf (buffer, "(%s %c 0x%04x)",
704 OP_SYMBOL (IC_LEFT (ic))->rname,
705 val >= 0 ? '+' : '-',
708 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
710 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
711 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
712 /* set immd2 field if required */
713 if (aop->aopu.aop_immd.from_cast_remat) {
714 sprintf(buffer,"#0x%02x",ptr_type);
715 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
716 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
722 /*-----------------------------------------------------------------*/
723 /* regsInCommon - two operands have some registers in common */
724 /*-----------------------------------------------------------------*/
726 regsInCommon (operand * op1, operand * op2)
731 /* if they have registers in common */
732 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
735 sym1 = OP_SYMBOL (op1);
736 sym2 = OP_SYMBOL (op2);
738 if (sym1->nRegs == 0 || sym2->nRegs == 0)
741 for (i = 0; i < sym1->nRegs; i++)
747 for (j = 0; j < sym2->nRegs; j++)
752 if (sym2->regs[j] == sym1->regs[i])
760 /*-----------------------------------------------------------------*/
761 /* operandsEqu - equivalent */
762 /*-----------------------------------------------------------------*/
764 operandsEqu (operand * op1, operand * op2)
768 /* if they're not symbols */
769 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
772 sym1 = OP_SYMBOL (op1);
773 sym2 = OP_SYMBOL (op2);
775 /* if both are itemps & one is spilt
776 and the other is not then false */
777 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
778 sym1->isspilt != sym2->isspilt)
781 /* if they are the same */
785 /* if they have the same rname */
786 if (sym1->rname[0] && sym2->rname[0] &&
787 strcmp (sym1->rname, sym2->rname) == 0 &&
788 !(IS_PARM (op2) && IS_ITEMP (op1)))
791 /* if left is a tmp & right is not */
792 if (IS_ITEMP (op1) &&
795 (sym1->usl.spillLoc == sym2))
798 if (IS_ITEMP (op2) &&
802 (sym2->usl.spillLoc == sym1))
808 /*-----------------------------------------------------------------*/
809 /* sameRegs - two asmops have the same registers */
810 /*-----------------------------------------------------------------*/
812 sameRegs (asmop * aop1, asmop * aop2)
819 if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
822 if (aop1->type != aop2->type)
825 if (aop1->size != aop2->size)
828 for (i = 0; i < aop1->size; i++)
829 if (aop1->aopu.aop_reg[i] !=
830 aop2->aopu.aop_reg[i])
836 /*-----------------------------------------------------------------*/
837 /* aopOp - allocates an asmop for an operand : */
838 /*-----------------------------------------------------------------*/
840 aopOp (operand * op, iCode * ic, bool result)
849 /* if this a literal */
850 if (IS_OP_LITERAL (op))
852 op->aop = aop = newAsmop (AOP_LIT);
853 aop->aopu.aop_lit = op->operand.valOperand;
854 aop->size = getSize (operandType (op));
858 /* if already has a asmop then continue */
862 /* if the underlying symbol has a aop */
863 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
865 op->aop = OP_SYMBOL (op)->aop;
869 /* if this is a true symbol */
870 if (IS_TRUE_SYMOP (op))
872 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
876 /* this is a temporary : this has
882 e) can be a return use only */
884 sym = OP_SYMBOL (op);
886 /* if the type is a conditional */
887 if (sym->regType == REG_CND)
889 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
894 /* if it is spilt then two situations
896 b) has a spill location */
897 if (sym->isspilt || sym->nRegs == 0)
900 /* rematerialize it NOW */
903 sym->aop = op->aop = aop =
905 aop->size = getSize (sym->type);
912 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
913 aop->size = getSize (sym->type);
914 for (i = 0; i < 2; i++)
915 aop->aopu.aop_str[i] = accUse[i];
923 aop = op->aop = sym->aop = newAsmop (AOP_STR);
924 aop->size = getSize (sym->type);
925 for (i = 0; i < fReturnSizeMCS51; i++)
926 aop->aopu.aop_str[i] = fReturn[i];
930 if (sym->usl.spillLoc)
932 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
934 /* force a new aop if sizes differ */
935 sym->usl.spillLoc->aop = NULL;
937 sym->aop = op->aop = aop =
938 aopForSym (ic, sym->usl.spillLoc, result);
939 aop->size = getSize (sym->type);
943 /* else must be a dummy iTemp */
944 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
945 aop->size = getSize (sym->type);
949 /* if the type is a bit register */
950 if (sym->regType == REG_BIT)
952 sym->aop = op->aop = aop = newAsmop (AOP_CRY);
953 aop->size = sym->nRegs;//1???
954 aop->aopu.aop_reg[0] = sym->regs[0];
955 aop->aopu.aop_dir = sym->regs[0]->name;
959 /* must be in a register */
960 sym->aop = op->aop = aop = newAsmop (AOP_REG);
961 aop->size = sym->nRegs;
962 for (i = 0; i < sym->nRegs; i++)
963 aop->aopu.aop_reg[i] = sym->regs[i];
966 /*-----------------------------------------------------------------*/
967 /* freeAsmop - free up the asmop given to an operand */
968 /*----------------------------------------------------------------*/
970 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
987 /* depending on the asmop type only three cases need work AOP_RO
988 , AOP_R1 && AOP_STK */
994 emitcode ("mov", "r0,b");
997 else if (_G.r0Pushed)
1001 emitcode ("pop", "ar0");
1005 bitVectUnSetBit (ic->rUsed, R0_IDX);
1011 emitcode ("mov", "r1,b");
1018 emitcode ("pop", "ar1");
1022 bitVectUnSetBit (ic->rUsed, R1_IDX);
1028 int stk = aop->aopu.aop_stk + aop->size - 1;
1029 bitVectUnSetBit (ic->rUsed, R0_IDX);
1030 bitVectUnSetBit (ic->rUsed, R1_IDX);
1032 getFreePtr (ic, &aop, FALSE);
1036 emitcode ("mov", "a,_bp");
1037 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1038 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1042 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1047 emitcode ("pop", "acc");
1048 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1051 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1054 freeAsmop (op, NULL, ic, TRUE);
1057 emitcode ("pop", "ar1");
1063 emitcode ("pop", "ar0");
1070 /* all other cases just dealloc */
1076 OP_SYMBOL (op)->aop = NULL;
1077 /* if the symbol has a spill */
1079 SPIL_LOC (op)->aop = NULL;
1084 /*------------------------------------------------------------------*/
1085 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
1086 /* pop r0 or r1 off stack if pushed */
1087 /*------------------------------------------------------------------*/
1089 freeForBranchAsmop (operand * op)
1109 emitcode ("mov", "r0,b");
1111 else if (_G.r0Pushed)
1113 emitcode ("pop", "ar0");
1120 emitcode ("mov", "r1,b");
1122 else if (_G.r1Pushed)
1124 emitcode ("pop", "ar1");
1131 int stk = aop->aopu.aop_stk + aop->size - 1;
1133 emitcode ("mov", "b,r0");
1136 emitcode ("mov", "a,_bp");
1137 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1138 emitcode ("mov", "r0,a");
1142 emitcode ("mov", "r0,_bp");
1147 emitcode ("pop", "acc");
1148 emitcode ("mov", "@r0,a");
1151 emitcode ("dec", "r0");
1153 emitcode ("mov", "r0,b");
1159 /*-----------------------------------------------------------------*/
1160 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
1161 /* clobber the accumulator */
1162 /*-----------------------------------------------------------------*/
1164 aopGetUsesAcc (operand * oper, int offset)
1166 asmop * aop = AOP (oper);
1168 if (offset > (aop->size - 1))
1186 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1197 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1203 /* Error case --- will have been caught already */
1209 /*-----------------------------------------------------------------*/
1210 /* aopGet - for fetching value of the aop */
1211 /*-----------------------------------------------------------------*/
1213 aopGet (operand * oper, int offset, bool bit16, bool dname)
1217 asmop * aop = AOP (oper);
1219 /* offset is greater than
1221 if (offset > (aop->size - 1) &&
1222 aop->type != AOP_LIT)
1225 /* depending on type */
1233 /* if we need to increment it */
1234 while (offset > aop->coff)
1236 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1240 while (offset < aop->coff)
1242 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1249 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1250 return (dname ? "acc" : "a");
1252 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1253 rs = Safe_calloc (1, strlen (s) + 1);
1258 if (aop->code && aop->coff==0 && offset>=1) {
1259 emitcode ("mov", "a,#0x%02x", offset);
1260 emitcode ("movc", "a,@a+dptr");
1261 return (dname ? "acc" : "a");
1264 while (offset > aop->coff)
1266 emitcode ("inc", "dptr");
1270 while (offset < aop->coff)
1272 emitcode ("lcall", "__decdptr");
1279 emitcode ("clr", "a");
1280 emitcode ("movc", "a,@a+dptr");
1284 emitcode ("movx", "a,@dptr");
1286 return (dname ? "acc" : "a");
1290 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1291 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1293 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1295 sprintf (s, "#(%s >> %d)",
1296 aop->aopu.aop_immd.aop_immd1,
1300 aop->aopu.aop_immd.aop_immd1);
1301 rs = Safe_calloc (1, strlen (s) + 1);
1306 if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
1307 sprintf (s, "(%s >> %d)",
1308 aop->aopu.aop_dir, offset * 8);
1310 sprintf (s, "(%s + %d)",
1314 sprintf (s, "%s", aop->aopu.aop_dir);
1315 rs = Safe_calloc (1, strlen (s) + 1);
1321 return aop->aopu.aop_reg[offset]->dname;
1323 return aop->aopu.aop_reg[offset]->name;
1326 emitcode ("clr", "a");
1327 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1328 emitcode ("rlc", "a");
1329 return (dname ? "acc" : "a");
1332 if (!offset && dname)
1334 return aop->aopu.aop_str[offset];
1337 return aopLiteral (aop->aopu.aop_lit, offset);
1341 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1345 return aop->aopu.aop_str[offset];
1349 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1350 "aopget got unsupported aop->type");
1353 /*-----------------------------------------------------------------*/
1354 /* aopPut - puts a string for a aop and indicates if acc is in use */
1355 /*-----------------------------------------------------------------*/
1357 aopPut (operand * result, const char *s, int offset, bool bvolatile)
1360 bool accuse = FALSE;
1361 asmop * aop = AOP (result);
1363 if (aop->size && offset > (aop->size - 1))
1365 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1366 "aopPut got offset > aop->size");
1370 /* will assign value to value */
1371 /* depending on where it is ofcourse */
1375 MOVA (s); /* read s in case it was volatile */
1380 if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1381 sprintf (d, "(%s >> %d)",
1382 aop->aopu.aop_dir, offset * 8);
1384 sprintf (d, "(%s + %d)",
1385 aop->aopu.aop_dir, offset);
1387 sprintf (d, "%s", aop->aopu.aop_dir);
1389 if (strcmp (d, s) ||
1391 emitcode ("mov", "%s,%s", d, s);
1392 if (!strcmp (d, "acc"))
1398 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1399 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1402 strcmp (s, "r0") == 0 ||
1403 strcmp (s, "r1") == 0 ||
1404 strcmp (s, "r2") == 0 ||
1405 strcmp (s, "r3") == 0 ||
1406 strcmp (s, "r4") == 0 ||
1407 strcmp (s, "r5") == 0 ||
1408 strcmp (s, "r6") == 0 ||
1409 strcmp (s, "r7") == 0)
1410 emitcode ("mov", "%s,%s",
1411 aop->aopu.aop_reg[offset]->dname, s);
1413 emitcode ("mov", "%s,%s",
1414 aop->aopu.aop_reg[offset]->name, s);
1421 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1422 "aopPut writing to code space");
1426 while (offset > aop->coff)
1429 emitcode ("inc", "dptr");
1432 while (offset < aop->coff)
1435 emitcode ("lcall", "__decdptr");
1440 /* if not in accumulator */
1443 emitcode ("movx", "@dptr,a");
1448 while (offset > aop->coff)
1451 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1453 while (offset < aop->coff)
1456 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1463 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1469 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1471 else if (strcmp (s, "r0") == 0 ||
1472 strcmp (s, "r1") == 0 ||
1473 strcmp (s, "r2") == 0 ||
1474 strcmp (s, "r3") == 0 ||
1475 strcmp (s, "r4") == 0 ||
1476 strcmp (s, "r5") == 0 ||
1477 strcmp (s, "r6") == 0 ||
1478 strcmp (s, "r7") == 0)
1481 sprintf (buffer, "a%s", s);
1482 emitcode ("mov", "@%s,%s",
1483 aop->aopu.aop_ptr->name, buffer);
1486 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1491 if (strcmp (s, "a") == 0)
1492 emitcode ("push", "acc");
1496 emitcode ("push", "acc");
1498 emitcode ("push", s);
1504 /* if not bit variable */
1505 if (!aop->aopu.aop_dir)
1507 /* inefficient: move carry into A and use jz/jnz */
1508 emitcode ("clr", "a");
1509 emitcode ("rlc", "a");
1515 emitcode ("clr", "%s", aop->aopu.aop_dir);
1517 emitcode ("setb", "%s", aop->aopu.aop_dir);
1518 else if (!strcmp (s, "c"))
1519 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1520 else if (strcmp (s, aop->aopu.aop_dir))
1523 /* set C, if a >= 1 */
1524 emitcode ("add", "a,#0xff");
1525 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1532 if (strcmp (aop->aopu.aop_str[offset], s) ||
1534 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1540 if (!offset && (strcmp (s, "acc") == 0) &&
1544 if (strcmp (aop->aopu.aop_str[offset], s) &&
1546 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1550 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1551 "aopPut got unsupported aop->type");
1560 /*-----------------------------------------------------------------*/
1561 /* pointToEnd :- points to the last byte of the operand */
1562 /*-----------------------------------------------------------------*/
1564 pointToEnd (asmop * aop)
1570 aop->coff = count = (aop->size - 1);
1576 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1580 emitcode ("inc", "dptr");
1587 /*-----------------------------------------------------------------*/
1588 /* reAdjustPreg - points a register back to where it should */
1589 /*-----------------------------------------------------------------*/
1591 reAdjustPreg (asmop * aop)
1593 if ((aop->coff==0) || aop->size <= 1)
1601 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1606 emitcode ("lcall", "__decdptr");
1613 /*-----------------------------------------------------------------*/
1614 /* opIsGptr: returns non-zero if the passed operand is */
1615 /* a generic pointer type. */
1616 /*-----------------------------------------------------------------*/
1618 opIsGptr (operand * op)
1620 sym_link *type = operandType (op);
1622 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1629 /*-----------------------------------------------------------------*/
1630 /* getDataSize - get the operand data size */
1631 /*-----------------------------------------------------------------*/
1633 getDataSize (operand * op)
1636 size = AOP_SIZE (op);
1637 if (size == GPTRSIZE)
1639 sym_link *type = operandType (op);
1640 if (IS_GENPTR (type))
1642 /* generic pointer; arithmetic operations
1643 * should ignore the high byte (pointer type).
1651 /*-----------------------------------------------------------------*/
1652 /* outAcc - output Acc */
1653 /*-----------------------------------------------------------------*/
1655 outAcc (operand * result)
1658 size = getDataSize (result);
1661 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
1664 /* unsigned or positive */
1667 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
1672 /*-----------------------------------------------------------------*/
1673 /* outBitC - output a bit C */
1674 /*-----------------------------------------------------------------*/
1676 outBitC (operand * result)
1678 /* if the result is bit */
1679 if (AOP_TYPE (result) == AOP_CRY)
1680 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
1683 emitcode ("clr", "a");
1684 emitcode ("rlc", "a");
1689 /*-----------------------------------------------------------------*/
1690 /* toBoolean - emit code for orl a,operator(sizeop) */
1691 /*-----------------------------------------------------------------*/
1693 toBoolean (operand * oper)
1695 int size = AOP_SIZE (oper) - 1;
1697 bool AccUsed = FALSE;
1700 while (!AccUsed && size--)
1702 AccUsed |= aopGetUsesAcc(oper, offset++);
1705 size = AOP_SIZE (oper) - 1;
1707 MOVA (aopGet (oper, 0, FALSE, FALSE));
1708 if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1711 emitcode("mov", "b,a");
1714 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1715 emitcode ("orl", "b,a");
1717 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1718 emitcode ("orl", "a,b");
1725 emitcode ("orl", "a,%s", aopGet (oper, offset++, FALSE, FALSE));
1731 /*-----------------------------------------------------------------*/
1732 /* genNot - generate code for ! operation */
1733 /*-----------------------------------------------------------------*/
1739 D(emitcode ("; genNot",""));
1741 /* assign asmOps to operand & result */
1742 aopOp (IC_LEFT (ic), ic, FALSE);
1743 aopOp (IC_RESULT (ic), ic, TRUE);
1745 /* if in bit space then a special case */
1746 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1748 /* if left==result then cpl bit */
1749 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1751 emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1755 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1756 emitcode ("cpl", "c");
1757 outBitC (IC_RESULT (ic));
1762 toBoolean (IC_LEFT (ic));
1764 /* set C, if a == 0 */
1765 tlbl = newiTempLabel (NULL);
1766 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1767 emitcode ("", "%05d$:", tlbl->key + 100);
1768 outBitC (IC_RESULT (ic));
1771 /* release the aops */
1772 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1773 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1777 /*-----------------------------------------------------------------*/
1778 /* genCpl - generate code for complement */
1779 /*-----------------------------------------------------------------*/
1786 sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
1788 D(emitcode (";", "genCpl"));
1790 /* assign asmOps to operand & result */
1791 aopOp (IC_LEFT (ic), ic, FALSE);
1792 aopOp (IC_RESULT (ic), ic, TRUE);
1794 /* special case if in bit space */
1795 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1799 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
1800 (SPEC_USIGN (letype) && IS_CHAR (letype)))
1802 /* promotion rules are responsible for this strange result:
1803 bit -> int -> ~int -> bit
1804 uchar -> int -> ~int -> bit
1806 werror(W_COMPLEMENT);
1807 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
1811 tlbl=newiTempLabel(NULL);
1812 l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
1813 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
1814 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1815 IS_AOP_PREG (IC_LEFT (ic)))
1817 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
1822 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
1824 emitcode ("", "%05d$:", tlbl->key + 100);
1825 outBitC (IC_RESULT(ic));
1829 size = AOP_SIZE (IC_RESULT (ic));
1832 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
1834 emitcode ("cpl", "a");
1835 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1840 /* release the aops */
1841 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1842 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1845 /*-----------------------------------------------------------------*/
1846 /* genUminusFloat - unary minus for floating points */
1847 /*-----------------------------------------------------------------*/
1849 genUminusFloat (operand * op, operand * result)
1851 int size, offset = 0;
1854 D(emitcode ("; genUminusFloat",""));
1856 /* for this we just copy and then flip the bit */
1858 size = AOP_SIZE (op) - 1;
1863 aopGet (op, offset, FALSE, FALSE),
1865 isOperandVolatile (result, FALSE));
1869 l = aopGet (op, offset, FALSE, FALSE);
1873 emitcode ("cpl", "acc.7");
1874 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
1877 /*-----------------------------------------------------------------*/
1878 /* genUminus - unary minus code generation */
1879 /*-----------------------------------------------------------------*/
1881 genUminus (iCode * ic)
1884 sym_link *optype, *rtype;
1887 D(emitcode ("; genUminus",""));
1890 aopOp (IC_LEFT (ic), ic, FALSE);
1891 aopOp (IC_RESULT (ic), ic, TRUE);
1893 /* if both in bit space then special
1895 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1896 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1899 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1900 emitcode ("cpl", "c");
1901 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1905 optype = operandType (IC_LEFT (ic));
1906 rtype = operandType (IC_RESULT (ic));
1908 /* if float then do float stuff */
1909 if (IS_FLOAT (optype))
1911 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1915 /* otherwise subtract from zero */
1916 size = AOP_SIZE (IC_LEFT (ic));
1921 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
1922 if (!strcmp (l, "a"))
1926 emitcode ("cpl", "a");
1927 emitcode ("addc", "a,#0");
1933 emitcode ("clr", "a");
1934 emitcode ("subb", "a,%s", l);
1936 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1939 /* if any remaining bytes in the result */
1940 /* we just need to propagate the sign */
1941 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1943 emitcode ("rlc", "a");
1944 emitcode ("subb", "a,acc");
1946 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1950 /* release the aops */
1951 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1952 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1955 /*-----------------------------------------------------------------*/
1956 /* saveRegisters - will look for a call and save the registers */
1957 /*-----------------------------------------------------------------*/
1959 saveRegisters (iCode * lic)
1966 for (ic = lic; ic; ic = ic->next)
1967 if (ic->op == CALL || ic->op == PCALL)
1972 fprintf (stderr, "found parameter push with no function call\n");
1976 /* if the registers have been saved already or don't need to be then
1980 if (IS_SYMOP(IC_LEFT(ic)) &&
1981 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1982 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
1985 /* save the registers in use at this time but skip the
1986 ones for the result */
1987 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1988 mcs51_rUmaskForOp (IC_RESULT(ic)));
1991 if (options.useXstack)
1993 int count = bitVectnBitsOn (rsave);
1997 regs * reg = mcs51_regWithIdx (bitVectFirstBit (rsave));
1998 if (reg->type == REG_BIT)
2000 emitcode ("mov", "a,%s", reg->base);
2004 emitcode ("mov", "a,%s", reg->name);
2006 emitcode ("mov", "r0,%s", spname);
2007 emitcode ("inc", "%s", spname);// allocate before use
2008 emitcode ("movx", "@r0,a");
2009 if (bitVectBitValue (rsave, R0_IDX))
2010 emitcode ("mov", "r0,a");
2012 else if (count != 0)
2014 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2015 int nBits = bitVectnBitsOn (rsavebits);
2019 count = count - nBits + 1;
2020 /* remove all but the first bits as they are pushed all at once */
2021 rsave = bitVectCplAnd (rsave, rsavebits);
2022 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2025 if (bitVectBitValue (rsave, R0_IDX))
2027 emitcode ("push", "%s", mcs51_regWithIdx (R0_IDX)->dname);
2029 emitcode ("mov", "r0,%s", spname);
2031 emitcode ("add", "a,#%d", count);
2032 emitcode ("mov", "%s,a", spname);
2033 for (i = 0; i < mcs51_nRegs; i++)
2035 if (bitVectBitValue (rsave, i))
2037 regs * reg = mcs51_regWithIdx (i);
2040 emitcode ("pop", "acc");
2041 emitcode ("push", "acc");
2043 else if (reg->type == REG_BIT)
2045 emitcode ("mov", "a,%s", reg->base);
2049 emitcode ("mov", "a,%s", reg->name);
2051 emitcode ("movx", "@r0,a");
2054 emitcode ("inc", "r0");
2058 if (bitVectBitValue (rsave, R0_IDX))
2060 emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
2066 bool bits_pushed = FALSE;
2067 for (i = 0; i < mcs51_nRegs; i++)
2069 if (bitVectBitValue (rsave, i))
2071 bits_pushed = pushReg (i, bits_pushed);
2077 /*-----------------------------------------------------------------*/
2078 /* unsaveRegisters - pop the pushed registers */
2079 /*-----------------------------------------------------------------*/
2081 unsaveRegisters (iCode * ic)
2086 /* restore the registers in use at this time but skip the
2087 ones for the result */
2088 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2089 mcs51_rUmaskForOp (IC_RESULT(ic)));
2091 if (options.useXstack)
2093 int count = bitVectnBitsOn (rsave);
2097 regs * reg = mcs51_regWithIdx (bitVectFirstBit (rsave));
2098 emitcode ("mov", "r0,%s", spname);
2099 emitcode ("dec", "r0");
2100 emitcode ("movx", "a,@r0");
2101 if (reg->type == REG_BIT)
2103 emitcode ("mov", "%s,a", reg->base);
2107 emitcode ("mov", "%s,a", reg->name);
2109 emitcode ("dec", "%s", spname);
2111 else if (count != 0)
2113 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2114 int nBits = bitVectnBitsOn (rsavebits);
2118 count = count - nBits + 1;
2119 /* remove all but the first bits as they are popped all at once */
2120 rsave = bitVectCplAnd (rsave, rsavebits);
2121 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2124 emitcode ("mov", "r0,%s", spname);
2125 for (i = mcs51_nRegs; i >= 0; i--)
2127 if (bitVectBitValue (rsave, i))
2129 regs * reg = mcs51_regWithIdx (i);
2130 emitcode ("dec", "r0");
2131 emitcode ("movx", "a,@r0");
2134 emitcode ("push", "acc");
2136 else if (reg->type == REG_BIT)
2138 emitcode ("mov", "%s,a", reg->base);
2142 emitcode ("mov", "%s,a", reg->name);
2146 emitcode ("mov", "%s,r0", spname);
2147 if (bitVectBitValue (rsave, R0_IDX))
2149 emitcode ("pop", "ar0");
2155 bool bits_popped = FALSE;
2156 for (i = mcs51_nRegs; i >= 0; i--)
2158 if (bitVectBitValue (rsave, i))
2160 bits_popped = popReg (i, bits_popped);
2167 /*-----------------------------------------------------------------*/
2169 /*-----------------------------------------------------------------*/
2171 pushSide (operand * oper, int size)
2176 char *l = aopGet (oper, offset++, FALSE, TRUE);
2177 if (AOP_TYPE (oper) != AOP_REG &&
2178 AOP_TYPE (oper) != AOP_DIR &&
2182 emitcode ("push", "acc");
2186 emitcode ("push", "%s", l);
2191 /*-----------------------------------------------------------------*/
2192 /* assignResultValue - also indicates if acc is in use afterwards */
2193 /*-----------------------------------------------------------------*/
2195 assignResultValue (operand * oper, operand * func)
2198 int size = AOP_SIZE (oper);
2199 bool accuse = FALSE;
2201 if (func && IS_BIT (OP_SYM_ETYPE (func)))
2209 accuse |= aopPut (oper, fReturn[offset], offset, isOperandVolatile (oper, FALSE));
2216 /*-----------------------------------------------------------------*/
2217 /* genXpush - pushes onto the external stack */
2218 /*-----------------------------------------------------------------*/
2220 genXpush (iCode * ic)
2222 asmop *aop = newAsmop (0);
2224 int size, offset = 0;
2226 D(emitcode ("; genXpush",""));
2228 aopOp (IC_LEFT (ic), ic, FALSE);
2229 r = getFreePtr (ic, &aop, FALSE);
2231 size = AOP_SIZE (IC_LEFT (ic));
2235 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2236 emitcode ("mov", "%s,%s", r->name, spname);
2237 emitcode ("inc", "%s", spname); // allocate space first
2238 emitcode ("movx", "@%s,a", r->name);
2242 // allocate space first
2243 emitcode ("mov", "%s,%s", r->name, spname);
2245 emitcode ("add", "a,#%d", size);
2246 emitcode ("mov", "%s,a", spname);
2250 MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2251 emitcode ("movx", "@%s,a", r->name);
2252 emitcode ("inc", "%s", r->name);
2256 freeAsmop (NULL, aop, ic, TRUE);
2257 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2260 /*-----------------------------------------------------------------*/
2261 /* genIpush - generate code for pushing this gets a little complex */
2262 /*-----------------------------------------------------------------*/
2264 genIpush (iCode * ic)
2266 int size, offset = 0;
2270 D(emitcode ("; genIpush",""));
2272 /* if this is not a parm push : ie. it is spill push
2273 and spill push is always done on the local stack */
2277 /* and the item is spilt then do nothing */
2278 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2281 aopOp (IC_LEFT (ic), ic, FALSE);
2282 size = AOP_SIZE (IC_LEFT (ic));
2283 /* push it on the stack */
2286 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2292 emitcode ("push", "%s", l);
2297 /* this is a parameter push: in this case we call
2298 the routine to find the call and save those
2299 registers that need to be saved */
2302 /* if use external stack then call the external
2303 stack pushing routine */
2304 if (options.useXstack)
2310 /* then do the push */
2311 aopOp (IC_LEFT (ic), ic, FALSE);
2313 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2314 size = AOP_SIZE (IC_LEFT (ic));
2318 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2319 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2320 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2323 if (strcmp (l, prev) || *l == '@')
2325 emitcode ("push", "acc");
2329 emitcode ("push", "%s", l);
2334 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2337 /*-----------------------------------------------------------------*/
2338 /* genIpop - recover the registers: can happen only for spilling */
2339 /*-----------------------------------------------------------------*/
2341 genIpop (iCode * ic)
2345 D(emitcode ("; genIpop",""));
2347 /* if the temp was not pushed then */
2348 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2351 aopOp (IC_LEFT (ic), ic, FALSE);
2352 size = AOP_SIZE (IC_LEFT (ic));
2353 offset = (size - 1);
2355 emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2358 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2361 /*-----------------------------------------------------------------*/
2362 /* saveRBank - saves an entire register bank on the stack */
2363 /*-----------------------------------------------------------------*/
2365 saveRBank (int bank, iCode * ic, bool pushPsw)
2368 int count = mcs51_nRegs + (pushPsw ? 1 : 0);
2372 if (options.useXstack)
2376 /* Assume r0 is available for use. */
2377 r = mcs51_regWithIdx (R0_IDX);;
2382 r = getFreePtr (ic, &aop, FALSE);
2384 // allocate space first
2385 emitcode ("mov", "%s,%s", r->name, spname);
2387 emitcode ("add", "a,#%d", count);
2388 emitcode ("mov", "%s,a", spname);
2391 for (i = 0; i < mcs51_nRegs; i++)
2393 if (options.useXstack)
2395 emitcode ("mov", "a,(%s+%d)",
2396 regs8051[i].base, 8 * bank + regs8051[i].offset);
2397 emitcode ("movx", "@%s,a", r->name);
2399 emitcode ("inc", "%s", r->name);
2402 emitcode ("push", "(%s+%d)",
2403 regs8051[i].base, 8 * bank + regs8051[i].offset);
2408 if (options.useXstack)
2410 emitcode ("mov", "a,psw");
2411 emitcode ("movx", "@%s,a", r->name);
2416 emitcode ("push", "psw");
2419 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2424 freeAsmop (NULL, aop, ic, TRUE);
2433 /*-----------------------------------------------------------------*/
2434 /* unsaveRBank - restores the register bank from stack */
2435 /*-----------------------------------------------------------------*/
2437 unsaveRBank (int bank, iCode * ic, bool popPsw)
2443 if (options.useXstack)
2447 /* Assume r0 is available for use. */
2448 r = mcs51_regWithIdx (R0_IDX);;
2453 r = getFreePtr (ic, &aop, FALSE);
2455 emitcode ("mov", "%s,%s", r->name, spname);
2460 if (options.useXstack)
2462 emitcode ("dec", "%s", r->name);
2463 emitcode ("movx", "a,@%s", r->name);
2464 emitcode ("mov", "psw,a");
2468 emitcode ("pop", "psw");
2472 for (i = (mcs51_nRegs - 1); i >= 0; i--)
2474 if (options.useXstack)
2476 emitcode ("dec", "%s", r->name);
2477 emitcode ("movx", "a,@%s", r->name);
2478 emitcode ("mov", "(%s+%d),a",
2479 regs8051[i].base, 8 * bank + regs8051[i].offset);
2483 emitcode ("pop", "(%s+%d)",
2484 regs8051[i].base, 8 * bank + regs8051[i].offset);
2488 if (options.useXstack)
2490 emitcode ("mov", "%s,%s", spname, r->name);
2495 freeAsmop (NULL, aop, ic, TRUE);
2499 /*-----------------------------------------------------------------*/
2500 /* genSend - gen code for SEND */
2501 /*-----------------------------------------------------------------*/
2502 static void genSend(set *sendSet)
2507 /* first we do all bit parameters */
2508 for (sic = setFirstItem (sendSet); sic;
2509 sic = setNextItem (sendSet))
2511 aopOp (IC_LEFT (sic), sic, FALSE);
2513 if (sic->argreg > 12)
2515 int bit = sic->argreg-13;
2517 /* if left is a literal then
2518 we know what the value is */
2519 if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2521 if (((int) operandLitValue (IC_LEFT (sic))))
2522 emitcode ("setb", "b[%d]", bit);
2524 emitcode ("clr", "b[%d]", bit);
2526 else if (AOP_TYPE (IC_LEFT (sic)) == AOP_CRY)
2528 char *l = AOP (IC_LEFT (sic))->aopu.aop_dir;
2529 if (strcmp (l, "c"))
2530 emitcode ("mov", "c,%s", l);
2531 emitcode ("mov", "b[%d],c", bit);
2536 toBoolean (IC_LEFT (sic));
2537 /* set C, if a >= 1 */
2538 emitcode ("add", "a,#0xff");
2539 emitcode ("mov", "b[%d],c", bit);
2544 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2549 saveRegisters (setFirstItem (sendSet));
2550 emitcode ("mov", "bits,b");
2553 /* then we do all other parameters */
2554 for (sic = setFirstItem (sendSet); sic;
2555 sic = setNextItem (sendSet))
2557 int size, offset = 0;
2558 aopOp (IC_LEFT (sic), sic, FALSE);
2559 size = AOP_SIZE (IC_LEFT (sic));
2561 if (sic->argreg == 1)
2565 char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2566 if (strcmp (l, fReturn[offset]))
2567 emitcode ("mov", "%s,%s", fReturn[offset], l);
2571 else if (sic->argreg <= 12)
2575 emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2576 aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2580 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2584 /*-----------------------------------------------------------------*/
2585 /* selectRegBank - emit code to select the register bank */
2586 /*-----------------------------------------------------------------*/
2588 selectRegBank (short bank, bool keepFlags)
2590 /* if f.e. result is in carry */
2593 emitcode ("anl", "psw,#0xE7");
2595 emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2599 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2603 /*-----------------------------------------------------------------*/
2604 /* genCall - generates a call statement */
2605 /*-----------------------------------------------------------------*/
2607 genCall (iCode * ic)
2611 // bool restoreBank = FALSE;
2612 bool swapBanks = FALSE;
2613 bool accuse = FALSE;
2614 bool accPushed = FALSE;
2615 bool resultInF0 = FALSE;
2617 D(emitcode("; genCall",""));
2619 dtype = operandType (IC_LEFT (ic));
2620 etype = getSpec(dtype);
2621 /* if send set is not empty then assign */
2624 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2625 genSend(reverseSet(_G.sendSet));
2627 genSend(_G.sendSet);
2633 /* if we are calling a not _naked function that is not using
2634 the same register bank then we need to save the
2635 destination registers on the stack */
2636 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2637 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2638 !IFFUNC_ISISR (dtype))
2643 /* if caller saves & we have not saved then */
2649 emitcode ("mov", "psw,#0x%02x",
2650 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2654 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2656 if (IFFUNC_CALLEESAVES(dtype))
2658 werror (E_BANKED_WITH_CALLEESAVES);
2662 char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2663 OP_SYMBOL (IC_LEFT (ic))->rname :
2664 OP_SYMBOL (IC_LEFT (ic))->name);
2666 emitcode ("mov", "r0,#%s", l);
2667 emitcode ("mov", "r1,#(%s >> 8)", l);
2668 emitcode ("mov", "r2,#(%s >> 16)", l);
2669 emitcode ("lcall", "__sdcc_banked_call");
2674 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2675 OP_SYMBOL (IC_LEFT (ic))->rname :
2676 OP_SYMBOL (IC_LEFT (ic))->name));
2681 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2684 /* if we need assign a result value */
2685 if ((IS_ITEMP (IC_RESULT (ic)) &&
2686 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2687 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2688 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2689 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2690 IS_TRUE_SYMOP (IC_RESULT (ic)))
2694 aopOp (IC_RESULT (ic), ic, FALSE);
2697 accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2699 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2702 /* adjust the stack for parameters if required */
2706 if (ic->parmBytes > 3)
2710 emitcode ("push", "acc");
2713 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2714 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
2716 emitcode ("mov", "F0,c");
2720 emitcode ("mov", "a,%s", spname);
2721 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2722 emitcode ("mov", "%s,a", spname);
2724 /* unsaveRegisters from xstack needs acc, but */
2725 /* unsaveRegisters from stack needs this popped */
2726 if (accPushed && !options.useXstack)
2728 emitcode ("pop", "acc");
2733 for (i = 0; i < ic->parmBytes; i++)
2734 emitcode ("dec", "%s", spname);
2737 /* if we had saved some registers then unsave them */
2738 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2740 if (accuse && !accPushed && options.useXstack)
2742 /* xstack needs acc, but doesn't touch normal stack */
2743 emitcode ("push", "acc");
2746 unsaveRegisters (ic);
2749 // /* if register bank was saved then pop them */
2751 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2753 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
2756 emitcode ("mov", "c,F0");
2758 aopOp (IC_RESULT (ic), ic, FALSE);
2759 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2760 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2764 emitcode ("pop", "acc");
2767 /*-----------------------------------------------------------------*/
2768 /* -10l - generates a call by pointer statement */
2769 /*-----------------------------------------------------------------*/
2771 genPcall (iCode * ic)
2775 symbol *rlbl = newiTempLabel (NULL);
2776 // bool restoreBank=FALSE;
2777 bool swapBanks = FALSE;
2778 bool resultInF0 = FALSE;
2780 D(emitcode("; genPCall",""));
2782 dtype = operandType (IC_LEFT (ic))->next;
2783 etype = getSpec(dtype);
2784 /* if caller saves & we have not saved then */
2788 /* if we are calling a not _naked function that is not using
2789 the same register bank then we need to save the
2790 destination registers on the stack */
2791 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2792 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2793 !IFFUNC_ISISR (dtype))
2795 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2796 // restoreBank=TRUE;
2798 // need caution message to user here
2801 if (IS_LITERAL(etype))
2803 /* if send set is not empty then assign */
2806 genSend(reverseSet(_G.sendSet));
2812 emitcode ("mov", "psw,#0x%02x",
2813 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2816 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2818 if (IFFUNC_CALLEESAVES(dtype))
2820 werror (E_BANKED_WITH_CALLEESAVES);
2824 char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
2826 emitcode ("mov", "r0,#%s", l);
2827 emitcode ("mov", "r1,#(%s >> 8)", l);
2828 emitcode ("mov", "r2,#(%s >> 16)", l);
2829 emitcode ("lcall", "__sdcc_banked_call");
2834 emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
2839 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2841 if (IFFUNC_CALLEESAVES(dtype))
2843 werror (E_BANKED_WITH_CALLEESAVES);
2847 aopOp (IC_LEFT (ic), ic, FALSE);
2851 emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
2852 emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
2853 emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
2857 int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
2858 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
2859 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
2860 emitcode ("mov", "0x%02x,%s", reg, aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
2863 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2865 /* if send set is not empty then assign */
2868 genSend(reverseSet(_G.sendSet));
2874 emitcode ("mov", "psw,#0x%02x",
2875 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2879 emitcode ("lcall", "__sdcc_banked_call");
2884 /* push the return address on to the stack */
2885 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2886 emitcode ("push", "acc");
2887 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2888 emitcode ("push", "acc");
2890 /* now push the calling address */
2891 aopOp (IC_LEFT (ic), ic, FALSE);
2893 pushSide (IC_LEFT (ic), FPTRSIZE);
2895 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2897 /* if send set is not empty the assign */
2900 genSend(reverseSet(_G.sendSet));
2906 emitcode ("mov", "psw,#0x%02x",
2907 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2911 emitcode ("ret", "");
2912 emitcode ("", "%05d$:", (rlbl->key + 100));
2917 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2920 /* if we need assign a result value */
2921 if ((IS_ITEMP (IC_RESULT (ic)) &&
2922 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2923 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2924 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2925 IS_TRUE_SYMOP (IC_RESULT (ic)))
2929 aopOp (IC_RESULT (ic), ic, FALSE);
2932 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2934 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2937 /* adjust the stack for parameters if required */
2941 if (ic->parmBytes > 3)
2943 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2944 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
2946 emitcode ("mov", "F0,c");
2950 emitcode ("mov", "a,%s", spname);
2951 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2952 emitcode ("mov", "%s,a", spname);
2955 for (i = 0; i < ic->parmBytes; i++)
2956 emitcode ("dec", "%s", spname);
2960 // /* if register bank was saved then unsave them */
2962 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2964 /* if we had saved some registers then unsave them */
2965 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2966 unsaveRegisters (ic);
2968 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
2971 emitcode ("mov", "c,F0");
2973 aopOp (IC_RESULT (ic), ic, FALSE);
2974 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2975 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2979 /*-----------------------------------------------------------------*/
2980 /* resultRemat - result is rematerializable */
2981 /*-----------------------------------------------------------------*/
2983 resultRemat (iCode * ic)
2985 if (SKIP_IC (ic) || ic->op == IFX)
2988 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2990 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2991 if (sym->remat && !POINTER_SET (ic))
2998 #if defined(__BORLANDC__) || defined(_MSC_VER)
2999 #define STRCASECMP stricmp
3001 #define STRCASECMP strcasecmp
3004 /*-----------------------------------------------------------------*/
3005 /* inExcludeList - return 1 if the string is in exclude Reg list */
3006 /*-----------------------------------------------------------------*/
3008 regsCmp(void *p1, void *p2)
3010 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3014 inExcludeList (char *s)
3016 const char *p = setFirstItem(options.excludeRegsSet);
3018 if (p == NULL || STRCASECMP(p, "none") == 0)
3022 return isinSetWith(options.excludeRegsSet, s, regsCmp);
3025 /*-----------------------------------------------------------------*/
3026 /* genFunction - generated code for function entry */
3027 /*-----------------------------------------------------------------*/
3029 genFunction (iCode * ic)
3031 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3033 bool switchedPSW = FALSE;
3034 int calleesaves_saved_register = -1;
3035 int stackAdjust = sym->stack;
3036 int accIsFree = sym->recvSize < 4;
3037 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3038 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3041 /* create the function header */
3042 emitcode (";", "-----------------------------------------");
3043 emitcode (";", " function %s", sym->name);
3044 emitcode (";", "-----------------------------------------");
3046 emitcode ("", "%s:", sym->rname);
3047 ftype = operandType (IC_LEFT (ic));
3048 _G.currentFunc = sym;
3050 if (IFFUNC_ISNAKED(ftype))
3052 emitcode(";", "naked function: no prologue.");
3056 /* here we need to generate the equates for the
3057 register bank if required */
3058 if (FUNC_REGBANK (ftype) != rbank)
3062 rbank = FUNC_REGBANK (ftype);
3063 for (i = 0; i < mcs51_nRegs; i++)
3065 if (regs8051[i].type != REG_BIT)
3067 if (strcmp (regs8051[i].base, "0") == 0)
3068 emitcode ("", "%s = 0x%02x",
3070 8 * rbank + regs8051[i].offset);
3072 emitcode ("", "%s = %s + 0x%02x",
3075 8 * rbank + regs8051[i].offset);
3080 /* if this is an interrupt service routine then
3081 save acc, b, dpl, dph */
3082 if (IFFUNC_ISISR (sym->type))
3085 if (!inExcludeList ("acc"))
3086 emitcode ("push", "acc");
3087 if (!inExcludeList ("b"))
3088 emitcode ("push", "b");
3089 if (!inExcludeList ("dpl"))
3090 emitcode ("push", "dpl");
3091 if (!inExcludeList ("dph"))
3092 emitcode ("push", "dph");
3093 /* if this isr has no bank i.e. is going to
3094 run with bank 0 , then we need to save more
3096 if (!FUNC_REGBANK (sym->type))
3099 /* if this function does not call any other
3100 function then we can be economical and
3101 save only those registers that are used */
3102 if (!IFFUNC_HASFCALL(sym->type))
3106 /* if any registers used */
3109 bool bits_pushed = FALSE;
3110 /* save the registers used */
3111 for (i = 0; i < sym->regsUsed->size; i++)
3113 if (bitVectBitValue (sym->regsUsed, i))
3114 bits_pushed = pushReg (i, bits_pushed);
3121 /* this function has a function call. We cannot
3122 determines register usage so we will have to push the
3124 saveRBank (0, ic, FALSE);
3125 if (options.parms_in_bank1) {
3127 for (i=0; i < 8 ; i++ ) {
3128 emitcode ("push","%s",rb1regs[i]);
3135 /* This ISR uses a non-zero bank.
3137 * We assume that the bank is available for our
3140 * However, if this ISR calls a function which uses some
3141 * other bank, we must save that bank entirely.
3143 unsigned long banksToSave = 0;
3145 if (IFFUNC_HASFCALL(sym->type))
3148 #define MAX_REGISTER_BANKS 4
3153 for (i = ic; i; i = i->next)
3155 if (i->op == ENDFUNCTION)
3157 /* we got to the end OK. */
3165 dtype = operandType (IC_LEFT(i));
3167 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3169 /* Mark this bank for saving. */
3170 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3172 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3176 banksToSave |= (1 << FUNC_REGBANK(dtype));
3179 /* And note that we don't need to do it in
3187 /* This is a mess; we have no idea what
3188 * register bank the called function might
3191 * The only thing I can think of to do is
3192 * throw a warning and hope.
3194 werror(W_FUNCPTR_IN_USING_ISR);
3198 if (banksToSave && options.useXstack)
3200 /* Since we aren't passing it an ic,
3201 * saveRBank will assume r0 is available to abuse.
3203 * So switch to our (trashable) bank now, so
3204 * the caller's R0 isn't trashed.
3206 emitcode ("push", "psw");
3207 emitcode ("mov", "psw,#0x%02x",
3208 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3212 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3214 if (banksToSave & (1 << ix))
3216 saveRBank(ix, NULL, FALSE);
3220 // TODO: this needs a closer look
3221 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3224 /* Set the register bank to the desired value if nothing else */
3225 /* has done so yet. */
3228 emitcode ("push", "psw");
3229 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3234 /* This is a non-ISR function. The caller has already switched register */
3235 /* banks, if necessary, so just handle the callee-saves option. */
3237 /* if callee-save to be used for this function
3238 then save the registers being used in this function */
3239 if (IFFUNC_CALLEESAVES(sym->type))
3243 /* if any registers used */
3246 bool bits_pushed = FALSE;
3247 /* save the registers used */
3248 for (i = 0; i < sym->regsUsed->size; i++)
3250 if (bitVectBitValue (sym->regsUsed, i))
3252 /* remember one saved register for later usage */
3253 if (calleesaves_saved_register < 0)
3254 calleesaves_saved_register = i;
3255 bits_pushed = pushReg (i, bits_pushed);
3266 if (options.useXstack)
3268 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3270 emitcode ("mov", "r0,%s", spname);
3271 emitcode ("inc", "%s", spname);
3272 emitcode ("xch", "a,_bpx");
3273 emitcode ("movx", "@r0,a");
3274 emitcode ("inc", "r0");
3275 emitcode ("mov", "a,r0");
3276 emitcode ("xch", "a,_bpx");
3280 emitcode ("push", "_bp"); /* save the callers stack */
3281 emitcode ("mov", "_bp,sp");
3286 if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3288 /* set up the stack */
3289 emitcode ("push", "_bp"); /* save the callers stack */
3290 emitcode ("mov", "_bp,sp");
3295 /* For some cases it is worthwhile to perform a RECEIVE iCode */
3296 /* before setting up the stack frame completely. */
3297 if (ric && ric->argreg == 1 && IC_RESULT (ric))
3299 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3303 if (rsym && rsym->regType == REG_CND)
3305 if (rsym && (rsym->accuse || rsym->ruonly))
3307 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3308 rsym = rsym->usl.spillLoc;
3311 /* If the RECEIVE operand immediately spills to the first entry on the */
3312 /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3313 /* rather than the usual @r0/r1 machinations. */
3314 if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3318 _G.current_iCode = ric;
3319 D(emitcode ("; genReceive",""));
3320 for (ofs=0; ofs < sym->recvSize; ofs++)
3322 if (!strcmp (fReturn[ofs], "a"))
3323 emitcode ("push", "acc");
3325 emitcode ("push", fReturn[ofs]);
3327 stackAdjust -= sym->recvSize;
3330 assert (stackAdjust>=0);
3333 _G.current_iCode = ic;
3337 /* If the RECEIVE operand is 4 registers, we can do the moves now */
3338 /* to free up the accumulator. */
3339 else if (rsym && rsym->nRegs && sym->recvSize == 4)
3343 _G.current_iCode = ric;
3344 D(emitcode ("; genReceive",""));
3345 for (ofs=0; ofs < sym->recvSize; ofs++)
3347 emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3349 _G.current_iCode = ic;
3355 /* adjust the stack for the function */
3358 int i = stackAdjust;
3360 werror (W_STACK_OVERFLOW, sym->name);
3362 if (i > 3 && accIsFree)
3364 emitcode ("mov", "a,sp");
3365 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3366 emitcode ("mov", "sp,a");
3370 /* The accumulator is not free, so we will need another register */
3371 /* to clobber. No need to worry about a possible conflict with */
3372 /* the above early RECEIVE optimizations since they would have */
3373 /* freed the accumulator if they were generated. */
3375 if (IFFUNC_CALLEESAVES(sym->type))
3377 /* if it's a callee-saves function we need a saved register */
3378 if (calleesaves_saved_register >= 0)
3380 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
3381 emitcode ("mov", "a,sp");
3382 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3383 emitcode ("mov", "sp,a");
3384 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
3387 /* do it the hard way */
3389 emitcode ("inc", "sp");
3393 /* not callee-saves, we can clobber r0 */
3394 emitcode ("mov", "r0,a");
3395 emitcode ("mov", "a,sp");
3396 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3397 emitcode ("mov", "sp,a");
3398 emitcode ("mov", "a,r0");
3403 emitcode ("inc", "sp");
3408 char i = ((char) sym->xstack & 0xff);
3410 if (i > 3 && accIsFree)
3412 emitcode ("mov", "a,_spx");
3413 emitcode ("add", "a,#0x%02x", i);
3414 emitcode ("mov", "_spx,a");
3418 emitcode ("push", "acc");
3419 emitcode ("mov", "a,_spx");
3420 emitcode ("add", "a,#0x%02x", i);
3421 emitcode ("mov", "_spx,a");
3422 emitcode ("pop", "acc");
3427 emitcode ("inc", "_spx");
3431 /* if critical function then turn interrupts off */
3432 if (IFFUNC_ISCRITICAL (ftype))
3434 symbol *tlbl = newiTempLabel (NULL);
3435 emitcode ("setb", "c");
3436 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3437 emitcode ("clr", "c");
3438 emitcode ("", "%05d$:", (tlbl->key + 100));
3439 emitcode ("push", "psw"); /* save old ea via c in psw */
3443 /*-----------------------------------------------------------------*/
3444 /* genEndFunction - generates epilogue for functions */
3445 /*-----------------------------------------------------------------*/
3447 genEndFunction (iCode * ic)
3449 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3450 lineNode *lnp = lineCurr;
3452 bitVect *regsUsedPrologue;
3453 bitVect *regsUnneeded;
3456 _G.currentFunc = NULL;
3457 if (IFFUNC_ISNAKED(sym->type))
3459 emitcode(";", "naked function: no epilogue.");
3460 if (options.debug && currFunc)
3461 debugFile->writeEndFunction (currFunc, ic, 0);
3465 if (IFFUNC_ISCRITICAL (sym->type))
3467 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3469 emitcode ("rlc", "a"); /* save c in a */
3470 emitcode ("pop", "psw"); /* restore ea via c in psw */
3471 emitcode ("mov", "ea,c");
3472 emitcode ("rrc", "a"); /* restore c from a */
3476 emitcode ("pop", "psw"); /* restore ea via c in psw */
3477 emitcode ("mov", "ea,c");
3481 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3483 if (options.useXstack)
3487 emitcode ("mov", "sp,_bp");
3488 emitcode ("pop", "_bp");
3490 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3492 emitcode ("xch", "a,_bpx");
3493 emitcode ("mov", "r0,a");
3494 emitcode ("dec", "r0");
3495 emitcode ("movx", "a,@r0");
3496 emitcode ("xch", "a,_bpx");
3497 emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3500 else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3502 emitcode ("mov", "sp,_bp");
3503 emitcode ("pop", "_bp");
3507 /* restore the register bank */
3508 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3510 if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
3511 || !options.useXstack)
3513 /* Special case of ISR using non-zero bank with useXstack
3516 emitcode ("pop", "psw");
3520 if (IFFUNC_ISISR (sym->type))
3523 /* now we need to restore the registers */
3524 /* if this isr has no bank i.e. is going to
3525 run with bank 0 , then we need to save more
3527 if (!FUNC_REGBANK (sym->type))
3529 /* if this function does not call any other
3530 function then we can be economical and
3531 save only those registers that are used */
3532 if (!IFFUNC_HASFCALL(sym->type))
3536 /* if any registers used */
3539 bool bits_popped = FALSE;
3540 /* save the registers used */
3541 for (i = sym->regsUsed->size; i >= 0; i--)
3543 if (bitVectBitValue (sym->regsUsed, i))
3544 bits_popped = popReg (i, bits_popped);
3550 if (options.parms_in_bank1) {
3552 for (i = 7 ; i >= 0 ; i-- ) {
3553 emitcode ("pop","%s",rb1regs[i]);
3556 /* this function has a function call cannot
3557 determines register usage so we will have to pop the
3559 unsaveRBank (0, ic, FALSE);
3564 /* This ISR uses a non-zero bank.
3566 * Restore any register banks saved by genFunction
3569 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3572 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3574 if (savedBanks & (1 << ix))
3576 unsaveRBank(ix, NULL, FALSE);
3580 if (options.useXstack)
3582 /* Restore bank AFTER calling unsaveRBank,
3583 * since it can trash r0.
3585 emitcode ("pop", "psw");
3589 if (!inExcludeList ("dph"))
3590 emitcode ("pop", "dph");
3591 if (!inExcludeList ("dpl"))
3592 emitcode ("pop", "dpl");
3593 if (!inExcludeList ("b"))
3594 emitcode ("pop", "b");
3595 if (!inExcludeList ("acc"))
3596 emitcode ("pop", "acc");
3598 /* if debug then send end of function */
3599 if (options.debug && currFunc)
3601 debugFile->writeEndFunction (currFunc, ic, 1);
3604 emitcode ("reti", "");
3608 if (IFFUNC_CALLEESAVES(sym->type))
3612 /* if any registers used */
3615 /* save the registers used */
3616 for (i = sym->regsUsed->size; i >= 0; i--)
3618 if (bitVectBitValue (sym->regsUsed, i) ||
3619 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3620 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
3623 else if (mcs51_ptrRegReq)
3625 emitcode ("pop", "%s", mcs51_regWithIdx (R1_IDX)->dname);
3626 emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
3631 /* if debug then send end of function */
3632 if (options.debug && currFunc)
3634 debugFile->writeEndFunction (currFunc, ic, 1);
3637 if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3639 emitcode ("ljmp", "__sdcc_banked_ret");
3643 emitcode ("ret", "");
3647 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3650 /* If this was an interrupt handler using bank 0 that called another */
3651 /* function, then all registers must be saved; nothing to optimized. */
3652 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3653 && !FUNC_REGBANK(sym->type))
3656 /* There are no push/pops to optimize if not callee-saves or ISR */
3657 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3660 /* If there were stack parameters, we cannot optimize without also */
3661 /* fixing all of the stack offsets; this is too dificult to consider. */
3662 if (FUNC_HASSTACKPARM(sym->type))
3665 /* Compute the registers actually used */
3666 regsUsed = newBitVect (mcs51_nRegs);
3667 regsUsedPrologue = newBitVect (mcs51_nRegs);
3670 if (lnp->ic && lnp->ic->op == FUNCTION)
3671 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3673 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3675 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3676 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3683 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3684 && !bitVectBitValue (regsUsed, CND_IDX))
3686 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3687 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3688 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3689 bitVectUnSetBit (regsUsed, CND_IDX);
3692 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3694 /* If this was an interrupt handler that called another function */
3695 /* function, then assume A, B, DPH, & DPL may be modified by it. */
3696 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3698 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3699 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3700 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3701 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3702 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3705 /* Remove the unneeded push/pops */
3706 regsUnneeded = newBitVect (mcs51_nRegs);
3709 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3711 if (!strncmp(lnp->line, "push", 4))
3713 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3714 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3716 connectLine (lnp->prev, lnp->next);
3717 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3720 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3722 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3723 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3725 connectLine (lnp->prev, lnp->next);
3726 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3733 for (idx = 0; idx < regsUnneeded->size; idx++)
3734 if (bitVectBitValue (regsUnneeded, idx))
3735 emitcode ("", ";\teliminated unneeded push/pop %s", mcs51_regWithIdx (idx)->dname);
3737 freeBitVect (regsUnneeded);
3738 freeBitVect (regsUsed);
3739 freeBitVect (regsUsedPrologue);
3742 /*-----------------------------------------------------------------*/
3743 /* genRet - generate code for return statement */
3744 /*-----------------------------------------------------------------*/
3748 int size, offset = 0, pushed = 0;
3750 D(emitcode ("; genRet",""));
3752 /* if we have no return value then
3753 just generate the "ret" */
3757 /* we have something to return then
3758 move the return value into place */
3759 aopOp (IC_LEFT (ic), ic, FALSE);
3760 size = AOP_SIZE (IC_LEFT (ic));
3763 if (IS_BIT(_G.currentFunc->etype))
3765 movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
3772 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3775 l = aopGet (IC_LEFT (ic), offset++,
3777 emitcode ("push", "%s", l);
3782 l = aopGet (IC_LEFT (ic), offset,
3784 if (strcmp (fReturn[offset], l))
3785 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3792 if (strcmp (fReturn[pushed], "a"))
3793 emitcode ("pop", fReturn[pushed]);
3795 emitcode ("pop", "acc");
3797 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3800 /* generate a jump to the return label
3801 if the next is not the return statement */
3802 if (!(ic->next && ic->next->op == LABEL &&
3803 IC_LABEL (ic->next) == returnLabel))
3805 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3809 /*-----------------------------------------------------------------*/
3810 /* genLabel - generates a label */
3811 /*-----------------------------------------------------------------*/
3813 genLabel (iCode * ic)
3815 /* special case never generate */
3816 if (IC_LABEL (ic) == entryLabel)
3819 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3822 /*-----------------------------------------------------------------*/
3823 /* genGoto - generates a ljmp */
3824 /*-----------------------------------------------------------------*/
3826 genGoto (iCode * ic)
3828 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3831 /*-----------------------------------------------------------------*/
3832 /* findLabelBackwards: walks back through the iCode chain looking */
3833 /* for the given label. Returns number of iCode instructions */
3834 /* between that label and given ic. */
3835 /* Returns zero if label not found. */
3836 /*-----------------------------------------------------------------*/
3838 findLabelBackwards (iCode * ic, int key)
3847 /* If we have any pushes or pops, we cannot predict the distance.
3848 I don't like this at all, this should be dealt with in the
3850 if (ic->op == IPUSH || ic->op == IPOP) {
3854 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3863 /*-----------------------------------------------------------------*/
3864 /* genPlusIncr :- does addition with increment if possible */
3865 /*-----------------------------------------------------------------*/
3867 genPlusIncr (iCode * ic)
3869 unsigned int icount;
3870 unsigned int size = getDataSize (IC_RESULT (ic));
3872 /* will try to generate an increment */
3873 /* if the right side is not a literal
3875 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3878 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3880 D(emitcode ("; genPlusIncr",""));
3882 /* if increment >=16 bits in register or direct space */
3883 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
3884 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3885 !isOperandVolatile (IC_RESULT (ic), FALSE) &&
3893 /* If the next instruction is a goto and the goto target
3894 * is < 10 instructions previous to this, we can generate
3895 * jumps straight to that target.
3897 if (ic->next && ic->next->op == GOTO
3898 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3899 && labelRange <= 10)
3901 emitcode (";", "tail increment optimized");
3902 tlbl = IC_LABEL (ic->next);
3907 tlbl = newiTempLabel (NULL);
3910 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
3911 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3912 IS_AOP_PREG (IC_RESULT (ic)))
3913 emitcode ("cjne", "%s,#0x00,%05d$",
3914 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
3918 emitcode ("clr", "a");
3919 emitcode ("cjne", "a,%s,%05d$",
3920 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
3924 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
3927 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3928 IS_AOP_PREG (IC_RESULT (ic)))
3929 emitcode ("cjne", "%s,#0x00,%05d$",
3930 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
3933 emitcode ("cjne", "a,%s,%05d$",
3934 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
3937 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
3941 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3942 IS_AOP_PREG (IC_RESULT (ic)))
3943 emitcode ("cjne", "%s,#0x00,%05d$",
3944 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
3948 emitcode ("cjne", "a,%s,%05d$",
3949 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
3952 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
3957 emitcode ("", "%05d$:", tlbl->key + 100);
3962 /* if result is dptr */
3963 if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
3964 (AOP_SIZE (IC_RESULT (ic)) == 2) &&
3965 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
3966 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
3968 if (aopGetUsesAcc (IC_LEFT (ic), 0))
3974 if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
3977 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0, FALSE);
3978 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1, FALSE);
3980 emitcode ("inc", "dptr");
3985 /* if the literal value of the right hand side
3986 is greater than 4 then it is not worth it */
3990 /* if the sizes are greater than 1 then we cannot */
3991 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3992 AOP_SIZE (IC_LEFT (ic)) > 1)
3995 /* we can if the aops of the left & result match or
3996 if they are in registers and the registers are the
3998 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4003 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4004 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4005 aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4011 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4020 /*-----------------------------------------------------------------*/
4021 /* outBitAcc - output a bit in acc */
4022 /*-----------------------------------------------------------------*/
4024 outBitAcc (operand * result)
4026 symbol *tlbl = newiTempLabel (NULL);
4027 /* if the result is a bit */
4028 if (AOP_TYPE (result) == AOP_CRY)
4030 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4034 emitcode ("jz", "%05d$", tlbl->key + 100);
4035 emitcode ("mov", "a,%s", one);
4036 emitcode ("", "%05d$:", tlbl->key + 100);
4041 /*-----------------------------------------------------------------*/
4042 /* genPlusBits - generates code for addition of two bits */
4043 /*-----------------------------------------------------------------*/
4045 genPlusBits (iCode * ic)
4047 D(emitcode ("; genPlusBits",""));
4049 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4051 symbol *lbl = newiTempLabel (NULL);
4052 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4053 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4054 emitcode ("cpl", "c");
4055 emitcode ("", "%05d$:", (lbl->key + 100));
4056 outBitC (IC_RESULT (ic));
4060 emitcode ("clr", "a");
4061 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4062 emitcode ("rlc", "a");
4063 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4064 emitcode ("addc", "a,#0x00");
4065 outAcc (IC_RESULT (ic));
4070 /* This is the original version of this code.
4072 * This is being kept around for reference,
4073 * because I am not entirely sure I got it right...
4076 adjustArithmeticResult (iCode * ic)
4078 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4079 AOP_SIZE (IC_LEFT (ic)) == 3 &&
4080 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4081 aopPut (IC_RESULT (ic),
4082 aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4084 isOperandVolatile (IC_RESULT (ic), FALSE));
4086 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4087 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4088 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4089 aopPut (IC_RESULT (ic),
4090 aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4092 isOperandVolatile (IC_RESULT (ic), FALSE));
4094 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4095 AOP_SIZE (IC_LEFT (ic)) < 3 &&
4096 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4097 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4098 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4101 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4102 aopPut (IC_RESULT (ic), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
4106 /* This is the pure and virtuous version of this code.
4107 * I'm pretty certain it's right, but not enough to toss the old
4111 adjustArithmeticResult (iCode * ic)
4113 if (opIsGptr (IC_RESULT (ic)) &&
4114 opIsGptr (IC_LEFT (ic)) &&
4115 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4117 aopPut (IC_RESULT (ic),
4118 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4120 isOperandVolatile (IC_RESULT (ic), FALSE));
4123 if (opIsGptr (IC_RESULT (ic)) &&
4124 opIsGptr (IC_RIGHT (ic)) &&
4125 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4127 aopPut (IC_RESULT (ic),
4128 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4130 isOperandVolatile (IC_RESULT (ic), FALSE));
4133 if (opIsGptr (IC_RESULT (ic)) &&
4134 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4135 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4136 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4137 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4140 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4141 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
4146 /*-----------------------------------------------------------------*/
4147 /* genPlus - generates code for addition */
4148 /*-----------------------------------------------------------------*/
4150 genPlus (iCode * ic)
4152 int size, offset = 0;
4155 operand *leftOp, *rightOp;
4158 /* special cases :- */
4160 D(emitcode ("; genPlus",""));
4162 aopOp (IC_LEFT (ic), ic, FALSE);
4163 aopOp (IC_RIGHT (ic), ic, FALSE);
4164 aopOp (IC_RESULT (ic), ic, TRUE);
4166 /* if literal, literal on the right or
4167 if left requires ACC or right is already
4169 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4170 (AOP_NEEDSACC (IC_LEFT (ic))) ||
4171 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4173 operand *t = IC_RIGHT (ic);
4174 IC_RIGHT (ic) = IC_LEFT (ic);
4178 /* if both left & right are in bit
4180 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4181 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4187 /* if left in bit space & right literal */
4188 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4189 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4191 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4192 /* if result in bit space */
4193 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4195 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4196 emitcode ("cpl", "c");
4197 outBitC (IC_RESULT (ic));
4201 size = getDataSize (IC_RESULT (ic));
4204 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4205 emitcode ("addc", "a,#00");
4206 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4212 /* if I can do an increment instead
4213 of add then GOOD for ME */
4214 if (genPlusIncr (ic) == TRUE)
4217 size = getDataSize (IC_RESULT (ic));
4218 leftOp = IC_LEFT(ic);
4219 rightOp = IC_RIGHT(ic);
4222 /* if this is an add for an array access
4223 at a 256 byte boundary */
4225 && AOP_TYPE (op) == AOP_IMMD
4227 && IS_SPEC (OP_SYM_ETYPE (op))
4228 && SPEC_ABSA (OP_SYM_ETYPE (op))
4229 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4232 D(emitcode ("; genPlus aligned array",""));
4233 aopPut (IC_RESULT (ic),
4234 aopGet (rightOp, 0, FALSE, FALSE),
4236 isOperandVolatile (IC_RESULT (ic), FALSE));
4238 if( 1 == getDataSize (IC_RIGHT (ic)) )
4240 aopPut (IC_RESULT (ic),
4241 aopGet (leftOp, 1, FALSE, FALSE),
4243 isOperandVolatile (IC_RESULT (ic), FALSE));
4247 MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4248 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4249 aopPut (IC_RESULT (ic), "a", 1, isOperandVolatile (IC_RESULT (ic), FALSE));
4254 /* if the lower bytes of a literal are zero skip the addition */
4255 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4257 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4258 (skip_bytes+1 < size))
4263 D(emitcode ("; genPlus shortcut",""));
4268 if( offset >= skip_bytes )
4270 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4273 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4275 emitcode("xch", "a,b");
4276 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4277 emitcode (add, "a,b");
4280 else if (aopGetUsesAcc (leftOp, offset))
4282 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4283 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4287 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4288 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4290 aopPut (IC_RESULT (ic), "a", offset, isOperandVolatile (IC_RESULT (ic), FALSE));
4291 add = "addc"; /* further adds must propagate carry */
4295 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4296 isOperandVolatile (IC_RESULT (ic), FALSE))
4299 aopPut (IC_RESULT (ic),
4300 aopGet (leftOp, offset, FALSE, FALSE),
4302 isOperandVolatile (IC_RESULT (ic), FALSE));
4308 adjustArithmeticResult (ic);
4311 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4312 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4313 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4316 /*-----------------------------------------------------------------*/
4317 /* genMinusDec :- does subtraction with decrement if possible */
4318 /*-----------------------------------------------------------------*/
4320 genMinusDec (iCode * ic)
4322 unsigned int icount;
4323 unsigned int size = getDataSize (IC_RESULT (ic));
4325 /* will try to generate an increment */
4326 /* if the right side is not a literal
4328 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4331 /* if the literal value of the right hand side
4332 is greater than 4 then it is not worth it */
4333 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4336 D(emitcode ("; genMinusDec",""));
4338 /* if decrement >=16 bits in register or direct space */
4339 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
4340 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4348 /* If the next instruction is a goto and the goto target
4349 * is <= 10 instructions previous to this, we can generate
4350 * jumps straight to that target.
4352 if (ic->next && ic->next->op == GOTO
4353 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4354 && labelRange <= 10)
4356 emitcode (";", "tail decrement optimized");
4357 tlbl = IC_LABEL (ic->next);
4362 tlbl = newiTempLabel (NULL);
4366 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4367 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4368 IS_AOP_PREG (IC_RESULT (ic)))
4369 emitcode ("cjne", "%s,#0xff,%05d$"
4370 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4374 emitcode ("mov", "a,#0xff");
4375 emitcode ("cjne", "a,%s,%05d$"
4376 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4379 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4382 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4383 IS_AOP_PREG (IC_RESULT (ic)))
4384 emitcode ("cjne", "%s,#0xff,%05d$"
4385 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4389 emitcode ("cjne", "a,%s,%05d$"
4390 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4393 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4397 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4398 IS_AOP_PREG (IC_RESULT (ic)))
4399 emitcode ("cjne", "%s,#0xff,%05d$"
4400 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4404 emitcode ("cjne", "a,%s,%05d$"
4405 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4408 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4412 emitcode ("", "%05d$:", tlbl->key + 100);
4417 /* if the sizes are greater than 1 then we cannot */
4418 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4419 AOP_SIZE (IC_LEFT (ic)) > 1)
4422 /* we can if the aops of the left & result match or
4423 if they are in registers and the registers are the
4425 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4429 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4437 /*-----------------------------------------------------------------*/
4438 /* addSign - complete with sign */
4439 /*-----------------------------------------------------------------*/
4441 addSign (operand * result, int offset, int sign)
4443 int size = (getDataSize (result) - offset);
4448 emitcode ("rlc", "a");
4449 emitcode ("subb", "a,acc");
4451 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
4455 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
4459 /*-----------------------------------------------------------------*/
4460 /* genMinusBits - generates code for subtraction of two bits */
4461 /*-----------------------------------------------------------------*/
4463 genMinusBits (iCode * ic)
4465 symbol *lbl = newiTempLabel (NULL);
4467 D(emitcode ("; genMinusBits",""));
4469 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4471 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4472 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4473 emitcode ("cpl", "c");
4474 emitcode ("", "%05d$:", (lbl->key + 100));
4475 outBitC (IC_RESULT (ic));
4479 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4480 emitcode ("subb", "a,acc");
4481 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4482 emitcode ("inc", "a");
4483 emitcode ("", "%05d$:", (lbl->key + 100));
4484 aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4485 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4489 /*-----------------------------------------------------------------*/
4490 /* genMinus - generates code for subtraction */
4491 /*-----------------------------------------------------------------*/
4493 genMinus (iCode * ic)
4495 int size, offset = 0;
4497 D(emitcode ("; genMinus",""));
4499 aopOp (IC_LEFT (ic), ic, FALSE);
4500 aopOp (IC_RIGHT (ic), ic, FALSE);
4501 aopOp (IC_RESULT (ic), ic, TRUE);
4503 /* special cases :- */
4504 /* if both left & right are in bit space */
4505 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4506 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4512 /* if I can do an decrement instead
4513 of subtract then GOOD for ME */
4514 if (genMinusDec (ic) == TRUE)
4517 size = getDataSize (IC_RESULT (ic));
4519 /* if literal, add a,#-lit, else normal subb */
4520 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4522 unsigned long lit = 0L;
4523 bool useCarry = FALSE;
4525 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4530 if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4532 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4533 if (!offset && !size && lit== (unsigned long) -1)
4535 emitcode ("dec", "a");
4539 /* first add without previous c */
4540 emitcode ("add", "a,#0x%02x",
4541 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4546 emitcode ("addc", "a,#0x%02x",
4547 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4549 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4553 /* no need to add zeroes */
4554 if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4556 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4557 offset, isOperandVolatile (IC_RESULT (ic), FALSE));
4565 operand *leftOp, *rightOp;
4567 leftOp = IC_LEFT(ic);
4568 rightOp = IC_RIGHT(ic);
4572 if (aopGetUsesAcc(rightOp, offset)) {
4573 if (aopGetUsesAcc(leftOp, offset)) {
4576 MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4578 emitcode ("mov", "b,a");
4581 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4582 emitcode ("subb", "a,b");
4585 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4586 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4588 emitcode( "setb", "c");
4590 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4591 emitcode("cpl", "a");
4594 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4597 emitcode ("subb", "a,%s",
4598 aopGet(rightOp, offset, FALSE, TRUE));
4601 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4606 adjustArithmeticResult (ic);
4609 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4610 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4611 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4615 /*-----------------------------------------------------------------*/
4616 /* genMultbits :- multiplication of bits */
4617 /*-----------------------------------------------------------------*/
4619 genMultbits (operand * left,
4623 D(emitcode ("; genMultbits",""));
4625 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4626 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4630 /*-----------------------------------------------------------------*/
4631 /* genMultOneByte : 8*8=8/16 bit multiplication */
4632 /*-----------------------------------------------------------------*/
4634 genMultOneByte (operand * left,
4639 int size = AOP_SIZE (result);
4640 bool runtimeSign, compiletimeSign;
4641 bool lUnsigned, rUnsigned, pushedB;
4643 D(emitcode ("; genMultOneByte",""));
4645 if (size < 1 || size > 2)
4647 /* this should never happen */
4648 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4649 AOP_SIZE(result), __FILE__, lineno);
4653 /* (if two literals: the value is computed before) */
4654 /* if one literal, literal on the right */
4655 if (AOP_TYPE (left) == AOP_LIT)
4660 /* emitcode (";", "swapped left and right"); */
4662 /* if no literal, unsigned on the right: shorter code */
4663 if ( AOP_TYPE (right) != AOP_LIT
4664 && SPEC_USIGN (getSpec (operandType (left))))
4671 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4672 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4676 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4677 no need to take care about the signedness! */
4678 || (lUnsigned && rUnsigned))
4680 /* just an unsigned 8 * 8 = 8 multiply
4682 /* emitcode (";","unsigned"); */
4683 /* TODO: check for accumulator clash between left & right aops? */
4685 if (AOP_TYPE (right) == AOP_LIT)
4687 /* moving to accumulator first helps peepholes */
4688 MOVA (aopGet (left, 0, FALSE, FALSE));
4689 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4693 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4694 MOVA (aopGet (left, 0, FALSE, FALSE));
4697 emitcode ("mul", "ab");
4698 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4700 aopPut (result, "b", 1, isOperandVolatile (result, FALSE));
4706 /* we have to do a signed multiply */
4707 /* emitcode (";", "signed"); */
4709 /* now sign adjust for both left & right */
4711 /* let's see what's needed: */
4712 /* apply negative sign during runtime */
4713 runtimeSign = FALSE;
4714 /* negative sign from literals */
4715 compiletimeSign = FALSE;
4719 if (AOP_TYPE(left) == AOP_LIT)
4721 /* signed literal */
4722 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4724 compiletimeSign = TRUE;
4727 /* signed but not literal */
4733 if (AOP_TYPE(right) == AOP_LIT)
4735 /* signed literal */
4736 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4738 compiletimeSign ^= TRUE;
4741 /* signed but not literal */
4745 /* initialize F0, which stores the runtime sign */
4748 if (compiletimeSign)
4749 emitcode ("setb", "F0"); /* set sign flag */
4751 emitcode ("clr", "F0"); /* reset sign flag */
4754 /* save the signs of the operands */
4755 if (AOP_TYPE(right) == AOP_LIT)
4757 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4759 if (!rUnsigned && val < 0)
4760 emitcode ("mov", "b,#0x%02x", -val);
4762 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4764 else /* ! literal */
4766 if (rUnsigned) /* emitcode (";", "signed"); */
4768 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4771 MOVA (aopGet (right, 0, FALSE, FALSE));
4772 lbl = newiTempLabel (NULL);
4773 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4774 emitcode ("cpl", "F0"); /* complement sign flag */
4775 emitcode ("cpl", "a"); /* 2's complement */
4776 emitcode ("inc", "a");
4777 emitcode ("", "%05d$:", (lbl->key + 100));
4778 emitcode ("mov", "b,a");
4782 if (AOP_TYPE(left) == AOP_LIT)
4784 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4786 if (!lUnsigned && val < 0)
4787 emitcode ("mov", "a,#0x%02x", -val);
4789 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4791 else /* ! literal */
4793 MOVA (aopGet (left, 0, FALSE, FALSE));
4797 lbl = newiTempLabel (NULL);
4798 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4799 emitcode ("cpl", "F0"); /* complement sign flag */
4800 emitcode ("cpl", "a"); /* 2's complement */
4801 emitcode ("inc", "a");
4802 emitcode ("", "%05d$:", (lbl->key + 100));
4806 /* now the multiplication */
4807 emitcode ("mul", "ab");
4808 if (runtimeSign || compiletimeSign)
4810 lbl = newiTempLabel (NULL);
4812 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4813 emitcode ("cpl", "a"); /* lsb 2's complement */
4815 emitcode ("inc", "a"); /* inc doesn't set carry flag */
4818 emitcode ("add", "a,#1"); /* this sets carry flag */
4819 emitcode ("xch", "a,b");
4820 emitcode ("cpl", "a"); /* msb 2's complement */
4821 emitcode ("addc", "a,#0");
4822 emitcode ("xch", "a,b");
4824 emitcode ("", "%05d$:", (lbl->key + 100));
4826 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4828 aopPut (result, "b", 1, isOperandVolatile (result, FALSE));
4833 /*-----------------------------------------------------------------*/
4834 /* genMult - generates code for multiplication */
4835 /*-----------------------------------------------------------------*/
4837 genMult (iCode * ic)
4839 operand *left = IC_LEFT (ic);
4840 operand *right = IC_RIGHT (ic);
4841 operand *result = IC_RESULT (ic);
4843 D(emitcode ("; genMult",""));
4845 /* assign the amsops */
4846 aopOp (left, ic, FALSE);
4847 aopOp (right, ic, FALSE);
4848 aopOp (result, ic, TRUE);
4850 /* special cases first */
4852 if (AOP_TYPE (left) == AOP_CRY &&
4853 AOP_TYPE (right) == AOP_CRY)
4855 genMultbits (left, right, result);
4859 /* if both are of size == 1 */
4860 #if 0 // one of them can be a sloc shared with the result
4861 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
4863 if (getSize(operandType(left)) == 1 &&
4864 getSize(operandType(right)) == 1)
4867 genMultOneByte (left, right, result);
4871 /* should have been converted to function call */
4872 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
4873 getSize(OP_SYMBOL(right)->type));
4877 freeAsmop (result, NULL, ic, TRUE);
4878 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4879 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4882 /*-----------------------------------------------------------------*/
4883 /* genDivbits :- division of bits */
4884 /*-----------------------------------------------------------------*/
4886 genDivbits (operand * left,
4893 D(emitcode ("; genDivbits",""));
4897 /* the result must be bit */
4898 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4899 l = aopGet (left, 0, FALSE, FALSE);
4903 emitcode ("div", "ab");
4904 emitcode ("rrc", "a");
4908 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
4911 /*-----------------------------------------------------------------*/
4912 /* genDivOneByte : 8 bit division */
4913 /*-----------------------------------------------------------------*/
4915 genDivOneByte (operand * left,
4919 bool lUnsigned, rUnsigned, pushedB;
4920 bool runtimeSign, compiletimeSign;
4924 D(emitcode ("; genDivOneByte",""));
4926 /* Why is it necessary that genDivOneByte() can return an int result?
4929 volatile unsigned char uc;
4930 volatile signed char sc1, sc2;
4943 In all cases a one byte result would overflow, the following cast to int
4944 would return the wrong result.
4946 Two possible solution:
4947 a) cast operands to int, if ((unsigned) / (signed)) or
4948 ((signed) / (signed))
4949 b) return an 16 bit signed int; this is what we're doing here!
4952 size = AOP_SIZE (result) - 1;
4954 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4955 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4959 /* signed or unsigned */
4960 if (lUnsigned && rUnsigned)
4962 /* unsigned is easy */
4963 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4964 MOVA (aopGet (left, 0, FALSE, FALSE));
4965 emitcode ("div", "ab");
4966 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4968 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
4974 /* signed is a little bit more difficult */
4976 /* now sign adjust for both left & right */
4978 /* let's see what's needed: */
4979 /* apply negative sign during runtime */
4980 runtimeSign = FALSE;
4981 /* negative sign from literals */
4982 compiletimeSign = FALSE;
4986 if (AOP_TYPE(left) == AOP_LIT)
4988 /* signed literal */
4989 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4991 compiletimeSign = TRUE;
4994 /* signed but not literal */
5000 if (AOP_TYPE(right) == AOP_LIT)
5002 /* signed literal */
5003 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5005 compiletimeSign ^= TRUE;
5008 /* signed but not literal */
5012 /* initialize F0, which stores the runtime sign */
5015 if (compiletimeSign)
5016 emitcode ("setb", "F0"); /* set sign flag */
5018 emitcode ("clr", "F0"); /* reset sign flag */
5021 /* save the signs of the operands */
5022 if (AOP_TYPE(right) == AOP_LIT)
5024 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5026 if (!rUnsigned && val < 0)
5027 emitcode ("mov", "b,#0x%02x", -val);
5029 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5031 else /* ! literal */
5034 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5037 MOVA (aopGet (right, 0, FALSE, FALSE));
5038 lbl = newiTempLabel (NULL);
5039 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5040 emitcode ("cpl", "F0"); /* complement sign flag */
5041 emitcode ("cpl", "a"); /* 2's complement */
5042 emitcode ("inc", "a");
5043 emitcode ("", "%05d$:", (lbl->key + 100));
5044 emitcode ("mov", "b,a");
5048 if (AOP_TYPE(left) == AOP_LIT)
5050 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5052 if (!lUnsigned && val < 0)
5053 emitcode ("mov", "a,#0x%02x", -val);
5055 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5057 else /* ! literal */
5059 MOVA (aopGet (left, 0, FALSE, FALSE));
5063 lbl = newiTempLabel (NULL);
5064 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5065 emitcode ("cpl", "F0"); /* complement sign flag */
5066 emitcode ("cpl", "a"); /* 2's complement */
5067 emitcode ("inc", "a");
5068 emitcode ("", "%05d$:", (lbl->key + 100));
5072 /* now the division */
5073 emitcode ("div", "ab");
5075 if (runtimeSign || compiletimeSign)
5077 lbl = newiTempLabel (NULL);
5079 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5080 emitcode ("cpl", "a"); /* lsb 2's complement */
5081 emitcode ("inc", "a");
5082 emitcode ("", "%05d$:", (lbl->key + 100));
5084 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5087 /* msb is 0x00 or 0xff depending on the sign */
5090 emitcode ("mov", "c,F0");
5091 emitcode ("subb", "a,acc");
5093 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
5095 else /* compiletimeSign */
5097 aopPut (result, "#0xff", offset++, isOperandVolatile (result, FALSE));
5102 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5104 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5110 /*-----------------------------------------------------------------*/
5111 /* genDiv - generates code for division */
5112 /*-----------------------------------------------------------------*/
5116 operand *left = IC_LEFT (ic);
5117 operand *right = IC_RIGHT (ic);
5118 operand *result = IC_RESULT (ic);
5120 D(emitcode ("; genDiv",""));
5122 /* assign the amsops */
5123 aopOp (left, ic, FALSE);
5124 aopOp (right, ic, FALSE);
5125 aopOp (result, ic, TRUE);
5127 /* special cases first */
5129 if (AOP_TYPE (left) == AOP_CRY &&
5130 AOP_TYPE (right) == AOP_CRY)
5132 genDivbits (left, right, result);
5136 /* if both are of size == 1 */
5137 if (AOP_SIZE (left) == 1 &&
5138 AOP_SIZE (right) == 1)
5140 genDivOneByte (left, right, result);
5144 /* should have been converted to function call */
5147 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5148 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5149 freeAsmop (result, NULL, ic, TRUE);
5152 /*-----------------------------------------------------------------*/
5153 /* genModbits :- modulus of bits */
5154 /*-----------------------------------------------------------------*/
5156 genModbits (operand * left,
5163 D(emitcode ("; genModbits",""));
5167 /* the result must be bit */
5168 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5169 l = aopGet (left, 0, FALSE, FALSE);
5173 emitcode ("div", "ab");
5174 emitcode ("mov", "a,b");
5175 emitcode ("rrc", "a");
5179 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
5182 /*-----------------------------------------------------------------*/
5183 /* genModOneByte : 8 bit modulus */
5184 /*-----------------------------------------------------------------*/
5186 genModOneByte (operand * left,
5190 bool lUnsigned, rUnsigned, pushedB;
5191 bool runtimeSign, compiletimeSign;
5195 D(emitcode ("; genModOneByte",""));
5197 size = AOP_SIZE (result) - 1;
5199 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5200 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5202 /* if right is a literal, check it for 2^n */
5203 if (AOP_TYPE(right) == AOP_LIT)
5205 unsigned char val = abs((int) operandLitValue(right));
5206 symbol *lbl2 = NULL;
5210 case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5219 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5220 "modulus of unsigned char by 2^n literal shouldn't be processed here");
5221 /* because iCode should have been changed to genAnd */
5222 /* see file "SDCCopt.c", function "convertToFcall()" */
5224 MOVA (aopGet (left, 0, FALSE, FALSE));
5225 emitcode ("mov", "c,acc.7");
5226 emitcode ("anl", "a,#0x%02x", val - 1);
5227 lbl = newiTempLabel (NULL);
5228 emitcode ("jz", "%05d$", (lbl->key + 100));
5229 emitcode ("jnc", "%05d$", (lbl->key + 100));
5230 emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5236 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5238 aopPut (result, "#0xff", offs2++, isOperandVolatile (result, FALSE));
5239 lbl2 = newiTempLabel (NULL);
5240 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5242 emitcode ("", "%05d$:", (lbl->key + 100));
5243 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5245 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5248 emitcode ("", "%05d$:", (lbl2->key + 100));
5259 /* signed or unsigned */
5260 if (lUnsigned && rUnsigned)
5262 /* unsigned is easy */
5263 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5264 MOVA (aopGet (left, 0, FALSE, FALSE));
5265 emitcode ("div", "ab");
5266 aopPut (result, "b", 0, isOperandVolatile (result, FALSE));
5268 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5274 /* signed is a little bit more difficult */
5276 /* now sign adjust for both left & right */
5278 /* modulus: sign of the right operand has no influence on the result! */
5279 if (AOP_TYPE(right) == AOP_LIT)
5281 signed char val = (char) operandLitValue(right);
5283 if (!rUnsigned && val < 0)
5284 emitcode ("mov", "b,#0x%02x", -val);
5286 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5288 else /* not literal */
5291 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5294 MOVA (aopGet (right, 0, FALSE, FALSE));
5295 lbl = newiTempLabel (NULL);
5296 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5297 emitcode ("cpl", "a"); /* 2's complement */
5298 emitcode ("inc", "a");
5299 emitcode ("", "%05d$:", (lbl->key + 100));
5300 emitcode ("mov", "b,a");
5304 /* let's see what's needed: */
5305 /* apply negative sign during runtime */
5306 runtimeSign = FALSE;
5307 /* negative sign from literals */
5308 compiletimeSign = FALSE;
5310 /* sign adjust left side */
5311 if (AOP_TYPE(left) == AOP_LIT)
5313 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5315 if (!lUnsigned && val < 0)
5317 compiletimeSign = TRUE; /* set sign flag */
5318 emitcode ("mov", "a,#0x%02x", -val);
5321 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5323 else /* ! literal */
5325 MOVA (aopGet (left, 0, FALSE, FALSE));
5330 emitcode ("clr", "F0"); /* clear sign flag */
5332 lbl = newiTempLabel (NULL);
5333 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5334 emitcode ("setb", "F0"); /* set sign flag */
5335 emitcode ("cpl", "a"); /* 2's complement */
5336 emitcode ("inc", "a");
5337 emitcode ("", "%05d$:", (lbl->key + 100));
5341 /* now the modulus */
5342 emitcode ("div", "ab");
5344 if (runtimeSign || compiletimeSign)
5346 emitcode ("mov", "a,b");
5347 lbl = newiTempLabel (NULL);
5349 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5350 emitcode ("cpl", "a"); /* 2's complement */
5351 emitcode ("inc", "a");
5352 emitcode ("", "%05d$:", (lbl->key + 100));
5354 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5357 /* msb is 0x00 or 0xff depending on the sign */
5360 emitcode ("mov", "c,F0");
5361 emitcode ("subb", "a,acc");
5363 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
5365 else /* compiletimeSign */
5367 aopPut (result, "#0xff", offset++, isOperandVolatile (result, FALSE));
5372 aopPut (result, "b", 0, isOperandVolatile (result, FALSE));
5374 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5380 /*-----------------------------------------------------------------*/
5381 /* genMod - generates code for division */
5382 /*-----------------------------------------------------------------*/
5386 operand *left = IC_LEFT (ic);
5387 operand *right = IC_RIGHT (ic);
5388 operand *result = IC_RESULT (ic);
5390 D(emitcode ("; genMod",""));
5392 /* assign the asmops */
5393 aopOp (left, ic, FALSE);
5394 aopOp (right, ic, FALSE);
5395 aopOp (result, ic, TRUE);
5397 /* special cases first */
5399 if (AOP_TYPE (left) == AOP_CRY &&
5400 AOP_TYPE (right) == AOP_CRY)
5402 genModbits (left, right, result);
5406 /* if both are of size == 1 */
5407 if (AOP_SIZE (left) == 1 &&
5408 AOP_SIZE (right) == 1)
5410 genModOneByte (left, right, result);
5414 /* should have been converted to function call */
5418 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5419 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5420 freeAsmop (result, NULL, ic, TRUE);
5423 /*-----------------------------------------------------------------*/
5424 /* genIfxJump :- will create a jump depending on the ifx */
5425 /*-----------------------------------------------------------------*/
5427 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5430 symbol *tlbl = newiTempLabel (NULL);
5433 D(emitcode ("; genIfxJump",""));
5435 /* if true label then we jump if condition
5439 jlbl = IC_TRUE (ic);
5440 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5441 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5445 /* false label is present */
5446 jlbl = IC_FALSE (ic);
5447 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5448 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5450 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5451 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5453 emitcode (inst, "%05d$", tlbl->key + 100);
5454 freeForBranchAsmop (result);
5455 freeForBranchAsmop (right);
5456 freeForBranchAsmop (left);
5457 emitcode ("ljmp", "%05d$", jlbl->key + 100);
5458 emitcode ("", "%05d$:", tlbl->key + 100);
5460 /* mark the icode as generated */
5464 /*-----------------------------------------------------------------*/
5465 /* genCmp :- greater or less than comparison */
5466 /*-----------------------------------------------------------------*/
5468 genCmp (operand * left, operand * right,
5469 operand * result, iCode * ifx, int sign, iCode *ic)
5471 int size, offset = 0;
5472 unsigned long lit = 0L;
5475 D(emitcode ("; genCmp",""));
5477 /* if left & right are bit variables */
5478 if (AOP_TYPE (left) == AOP_CRY &&
5479 AOP_TYPE (right) == AOP_CRY)
5481 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5482 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5486 /* subtract right from left if at the
5487 end the carry flag is set then we know that
5488 left is greater than right */
5489 size = max (AOP_SIZE (left), AOP_SIZE (right));
5491 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5492 if ((size == 1) && !sign &&
5493 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5495 symbol *lbl = newiTempLabel (NULL);
5496 emitcode ("cjne", "%s,%s,%05d$",
5497 aopGet (left, offset, FALSE, FALSE),
5498 aopGet (right, offset, FALSE, FALSE),
5500 emitcode ("", "%05d$:", lbl->key + 100);
5504 if (AOP_TYPE (right) == AOP_LIT)
5506 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5507 /* optimize if(x < 0) or if(x >= 0) */
5516 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5517 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5519 genIfxJump (ifx, "acc.7", left, right, result);
5520 freeAsmop (right, NULL, ic, TRUE);
5521 freeAsmop (left, NULL, ic, TRUE);
5526 emitcode ("rlc", "a");
5534 bool pushedB = FALSE;
5535 rightInB = aopGetUsesAcc(right, offset);
5539 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5541 MOVA (aopGet (left, offset, FALSE, FALSE));
5542 if (sign && size == 0)
5544 emitcode ("xrl", "a,#0x80");
5545 if (AOP_TYPE (right) == AOP_LIT)
5547 unsigned long lit = (unsigned long)
5548 floatFromVal (AOP (right)->aopu.aop_lit);
5549 emitcode ("subb", "a,#0x%02x",
5550 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5558 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5560 emitcode ("xrl", "b,#0x80");
5561 emitcode ("subb", "a,b");
5567 emitcode ("subb", "a,b");
5569 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5579 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5580 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5581 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5587 /* if the result is used in the next
5588 ifx conditional branch then generate
5589 code a little differently */
5591 genIfxJump (ifx, "c", NULL, NULL, result);
5594 /* leave the result in acc */
5598 /*-----------------------------------------------------------------*/
5599 /* genCmpGt :- greater than comparison */
5600 /*-----------------------------------------------------------------*/
5602 genCmpGt (iCode * ic, iCode * ifx)
5604 operand *left, *right, *result;
5605 sym_link *letype, *retype;
5608 D(emitcode ("; genCmpGt",""));
5610 left = IC_LEFT (ic);
5611 right = IC_RIGHT (ic);
5612 result = IC_RESULT (ic);
5614 letype = getSpec (operandType (left));
5615 retype = getSpec (operandType (right));
5616 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5617 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5618 /* assign the amsops */
5619 aopOp (left, ic, FALSE);
5620 aopOp (right, ic, FALSE);
5621 aopOp (result, ic, TRUE);
5623 genCmp (right, left, result, ifx, sign, ic);
5625 freeAsmop (result, NULL, ic, TRUE);
5628 /*-----------------------------------------------------------------*/
5629 /* genCmpLt - less than comparisons */
5630 /*-----------------------------------------------------------------*/
5632 genCmpLt (iCode * ic, iCode * ifx)
5634 operand *left, *right, *result;
5635 sym_link *letype, *retype;
5638 D(emitcode ("; genCmpLt",""));
5640 left = IC_LEFT (ic);
5641 right = IC_RIGHT (ic);
5642 result = IC_RESULT (ic);
5644 letype = getSpec (operandType (left));
5645 retype = getSpec (operandType (right));
5646 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5647 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5648 /* assign the amsops */
5649 aopOp (left, ic, FALSE);
5650 aopOp (right, ic, FALSE);
5651 aopOp (result, ic, TRUE);
5653 genCmp (left, right, result, ifx, sign, ic);
5655 freeAsmop (result, NULL, ic, TRUE);
5658 /*-----------------------------------------------------------------*/
5659 /* gencjneshort - compare and jump if not equal */
5660 /*-----------------------------------------------------------------*/
5662 gencjneshort (operand * left, operand * right, symbol * lbl)
5664 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5666 unsigned long lit = 0L;
5668 /* if the left side is a literal or
5669 if the right is in a pointer register and left
5671 if ((AOP_TYPE (left) == AOP_LIT) ||
5672 (AOP_TYPE (left) == AOP_IMMD) ||
5673 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5680 if (AOP_TYPE (right) == AOP_LIT)
5681 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5683 /* if the right side is a literal then anything goes */
5684 if (AOP_TYPE (right) == AOP_LIT &&
5685 AOP_TYPE (left) != AOP_DIR &&
5686 AOP_TYPE (left) != AOP_IMMD)
5690 emitcode ("cjne", "%s,%s,%05d$",
5691 aopGet (left, offset, FALSE, FALSE),
5692 aopGet (right, offset, FALSE, FALSE),
5698 /* if the right side is in a register or in direct space or
5699 if the left is a pointer register & right is not */
5700 else if (AOP_TYPE (right) == AOP_REG ||
5701 AOP_TYPE (right) == AOP_DIR ||
5702 AOP_TYPE (right) == AOP_LIT ||
5703 AOP_TYPE (right) == AOP_IMMD ||
5704 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5705 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5709 MOVA (aopGet (left, offset, FALSE, FALSE));
5710 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5711 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5712 emitcode ("jnz", "%05d$", lbl->key + 100);
5714 emitcode ("cjne", "a,%s,%05d$",
5715 aopGet (right, offset, FALSE, TRUE),
5722 /* right is a pointer reg need both a & b */
5726 //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
5727 wassertl(!BINUSE, "B was in use");
5728 l = aopGet (left, offset, FALSE, FALSE);
5729 if (strcmp (l, "b"))
5730 emitcode ("mov", "b,%s", l);
5731 MOVA (aopGet (right, offset, FALSE, FALSE));
5732 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5738 /*-----------------------------------------------------------------*/
5739 /* gencjne - compare and jump if not equal */
5740 /*-----------------------------------------------------------------*/
5742 gencjne (operand * left, operand * right, symbol * lbl)
5744 symbol *tlbl = newiTempLabel (NULL);
5746 gencjneshort (left, right, lbl);
5748 emitcode ("mov", "a,%s", one);
5749 emitcode ("sjmp", "%05d$", tlbl->key + 100);
5750 emitcode ("", "%05d$:", lbl->key + 100);
5751 emitcode ("clr", "a");
5752 emitcode ("", "%05d$:", tlbl->key + 100);
5755 /*-----------------------------------------------------------------*/
5756 /* genCmpEq - generates code for equal to */
5757 /*-----------------------------------------------------------------*/
5759 genCmpEq (iCode * ic, iCode * ifx)
5761 operand *left, *right, *result;
5763 D(emitcode ("; genCmpEq",""));
5765 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5766 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5767 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5769 /* if literal, literal on the right or
5770 if the right is in a pointer register and left
5772 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5773 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5775 operand *t = IC_RIGHT (ic);
5776 IC_RIGHT (ic) = IC_LEFT (ic);
5780 if (ifx && !AOP_SIZE (result))
5783 /* if they are both bit variables */
5784 if (AOP_TYPE (left) == AOP_CRY &&
5785 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5787 if (AOP_TYPE (right) == AOP_LIT)
5789 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5792 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5793 emitcode ("cpl", "c");
5797 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5801 emitcode ("clr", "c");
5803 /* AOP_TYPE(right) == AOP_CRY */
5807 symbol *lbl = newiTempLabel (NULL);
5808 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5809 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5810 emitcode ("cpl", "c");
5811 emitcode ("", "%05d$:", (lbl->key + 100));
5813 /* if true label then we jump if condition
5815 tlbl = newiTempLabel (NULL);
5818 emitcode ("jnc", "%05d$", tlbl->key + 100);
5819 freeForBranchAsmop (result);
5820 freeForBranchAsmop (right);
5821 freeForBranchAsmop (left);
5822 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5826 emitcode ("jc", "%05d$", tlbl->key + 100);
5827 freeForBranchAsmop (result);
5828 freeForBranchAsmop (right);
5829 freeForBranchAsmop (left);
5830 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5832 emitcode ("", "%05d$:", tlbl->key + 100);
5836 tlbl = newiTempLabel (NULL);
5837 gencjneshort (left, right, tlbl);
5840 freeForBranchAsmop (result);
5841 freeForBranchAsmop (right);
5842 freeForBranchAsmop (left);
5843 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5844 emitcode ("", "%05d$:", tlbl->key + 100);
5848 symbol *lbl = newiTempLabel (NULL);
5849 emitcode ("sjmp", "%05d$", lbl->key + 100);
5850 emitcode ("", "%05d$:", tlbl->key + 100);
5851 freeForBranchAsmop (result);
5852 freeForBranchAsmop (right);
5853 freeForBranchAsmop (left);
5854 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5855 emitcode ("", "%05d$:", lbl->key + 100);
5858 /* mark the icode as generated */
5863 /* if they are both bit variables */
5864 if (AOP_TYPE (left) == AOP_CRY &&
5865 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5867 if (AOP_TYPE (right) == AOP_LIT)
5869 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5872 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5873 emitcode ("cpl", "c");
5877 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5881 emitcode ("clr", "c");
5883 /* AOP_TYPE(right) == AOP_CRY */
5887 symbol *lbl = newiTempLabel (NULL);
5888 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5889 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5890 emitcode ("cpl", "c");
5891 emitcode ("", "%05d$:", (lbl->key + 100));
5894 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5901 genIfxJump (ifx, "c", left, right, result);
5904 /* if the result is used in an arithmetic operation
5905 then put the result in place */
5910 gencjne (left, right, newiTempLabel (NULL));
5911 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5913 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5918 genIfxJump (ifx, "a", left, right, result);
5921 /* if the result is used in an arithmetic operation
5922 then put the result in place */
5923 if (AOP_TYPE (result) != AOP_CRY)
5925 /* leave the result in acc */
5929 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5930 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5931 freeAsmop (result, NULL, ic, TRUE);
5934 /*-----------------------------------------------------------------*/
5935 /* ifxForOp - returns the icode containing the ifx for operand */
5936 /*-----------------------------------------------------------------*/
5938 ifxForOp (operand * op, iCode * ic)
5940 /* if true symbol then needs to be assigned */
5941 if (IS_TRUE_SYMOP (op))
5944 /* if this has register type condition and
5945 the next instruction is ifx with the same operand
5946 and live to of the operand is upto the ifx only then */
5948 ic->next->op == IFX &&
5949 IC_COND (ic->next)->key == op->key &&
5950 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5956 /*-----------------------------------------------------------------*/
5957 /* hasInc - operand is incremented before any other use */
5958 /*-----------------------------------------------------------------*/
5960 hasInc (operand *op, iCode *ic,int osize)
5962 sym_link *type = operandType(op);
5963 sym_link *retype = getSpec (type);
5964 iCode *lic = ic->next;
5967 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5968 if (!IS_SYMOP(op)) return NULL;
5970 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5971 if (IS_AGGREGATE(type->next)) return NULL;
5972 if (osize != (isize = getSize(type->next))) return NULL;
5975 /* if operand of the form op = op + <sizeof *op> */
5976 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5977 isOperandEqual(IC_RESULT(lic),op) &&
5978 isOperandLiteral(IC_RIGHT(lic)) &&
5979 operandLitValue(IC_RIGHT(lic)) == isize) {
5982 /* if the operand used or deffed */
5983 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
5986 /* if GOTO or IFX */
5987 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5993 /*-----------------------------------------------------------------*/
5994 /* genAndOp - for && operation */
5995 /*-----------------------------------------------------------------*/
5997 genAndOp (iCode * ic)
5999 operand *left, *right, *result;
6002 D(emitcode ("; genAndOp",""));
6004 /* note here that && operations that are in an
6005 if statement are taken away by backPatchLabels
6006 only those used in arthmetic operations remain */
6007 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6008 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6009 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6011 /* if both are bit variables */
6012 if (AOP_TYPE (left) == AOP_CRY &&
6013 AOP_TYPE (right) == AOP_CRY)
6015 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6016 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6021 tlbl = newiTempLabel (NULL);
6023 emitcode ("jz", "%05d$", tlbl->key + 100);
6025 emitcode ("", "%05d$:", tlbl->key + 100);
6029 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6030 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6031 freeAsmop (result, NULL, ic, TRUE);
6035 /*-----------------------------------------------------------------*/
6036 /* genOrOp - for || operation */
6037 /*-----------------------------------------------------------------*/
6039 genOrOp (iCode * ic)
6041 operand *left, *right, *result;
6044 D(emitcode ("; genOrOp",""));
6046 /* note here that || operations that are in an
6047 if statement are taken away by backPatchLabels
6048 only those used in arthmetic operations remain */
6049 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6050 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6051 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6053 /* if both are bit variables */
6054 if (AOP_TYPE (left) == AOP_CRY &&
6055 AOP_TYPE (right) == AOP_CRY)
6057 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6058 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6063 tlbl = newiTempLabel (NULL);
6065 emitcode ("jnz", "%05d$", tlbl->key + 100);
6067 emitcode ("", "%05d$:", tlbl->key + 100);
6071 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6072 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6073 freeAsmop (result, NULL, ic, TRUE);
6076 /*-----------------------------------------------------------------*/
6077 /* isLiteralBit - test if lit == 2^n */
6078 /*-----------------------------------------------------------------*/
6080 isLiteralBit (unsigned long lit)
6082 unsigned long pw[32] =
6083 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6084 0x100L, 0x200L, 0x400L, 0x800L,
6085 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6086 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6087 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6088 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6089 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6092 for (idx = 0; idx < 32; idx++)
6098 /*-----------------------------------------------------------------*/
6099 /* continueIfTrue - */
6100 /*-----------------------------------------------------------------*/
6102 continueIfTrue (iCode * ic)
6105 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6109 /*-----------------------------------------------------------------*/
6111 /*-----------------------------------------------------------------*/
6113 jumpIfTrue (iCode * ic)
6116 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6120 /*-----------------------------------------------------------------*/
6121 /* jmpTrueOrFalse - */
6122 /*-----------------------------------------------------------------*/
6124 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6126 // ugly but optimized by peephole
6129 symbol *nlbl = newiTempLabel (NULL);
6130 emitcode ("sjmp", "%05d$", nlbl->key + 100);
6131 emitcode ("", "%05d$:", tlbl->key + 100);
6132 freeForBranchAsmop (result);
6133 freeForBranchAsmop (right);
6134 freeForBranchAsmop (left);
6135 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6136 emitcode ("", "%05d$:", nlbl->key + 100);
6140 freeForBranchAsmop (result);
6141 freeForBranchAsmop (right);
6142 freeForBranchAsmop (left);
6143 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6144 emitcode ("", "%05d$:", tlbl->key + 100);
6149 /*-----------------------------------------------------------------*/
6150 /* genAnd - code for and */
6151 /*-----------------------------------------------------------------*/
6153 genAnd (iCode * ic, iCode * ifx)
6155 operand *left, *right, *result;
6156 int size, offset = 0;
6157 unsigned long lit = 0L;
6161 D(emitcode ("; genAnd",""));
6163 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6164 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6165 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6168 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6170 AOP_TYPE (left), AOP_TYPE (right));
6171 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6173 AOP_SIZE (left), AOP_SIZE (right));
6176 /* if left is a literal & right is not then exchange them */
6177 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6178 AOP_NEEDSACC (left))
6180 operand *tmp = right;
6185 /* if result = right then exchange left and right */
6186 if (sameRegs (AOP (result), AOP (right)))
6188 operand *tmp = right;
6193 /* if right is bit then exchange them */
6194 if (AOP_TYPE (right) == AOP_CRY &&
6195 AOP_TYPE (left) != AOP_CRY)
6197 operand *tmp = right;
6201 if (AOP_TYPE (right) == AOP_LIT)
6202 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6204 size = AOP_SIZE (result);
6207 // result = bit & yy;
6208 if (AOP_TYPE (left) == AOP_CRY)
6210 // c = bit & literal;
6211 if (AOP_TYPE (right) == AOP_LIT)
6215 if (size && sameRegs (AOP (result), AOP (left)))
6218 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6223 if (size && (AOP_TYPE (result) == AOP_CRY))
6225 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6228 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6233 emitcode ("clr", "c");
6238 if (AOP_TYPE (right) == AOP_CRY)
6241 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6242 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6247 MOVA (aopGet (right, 0, FALSE, FALSE));
6249 emitcode ("rrc", "a");
6250 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6258 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6259 genIfxJump (ifx, "c", left, right, result);
6263 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6264 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6265 if ((AOP_TYPE (right) == AOP_LIT) &&
6266 (AOP_TYPE (result) == AOP_CRY) &&
6267 (AOP_TYPE (left) != AOP_CRY))
6269 int posbit = isLiteralBit (lit);
6274 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6278 switch (posbit & 0x07)
6280 case 0: emitcode ("rrc", "a");
6282 case 7: emitcode ("rlc", "a");
6284 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6293 SNPRINTF (buffer, sizeof(buffer),
6294 "acc.%d", posbit & 0x07);
6295 genIfxJump (ifx, buffer, left, right, result);
6298 {// what is this case? just found it in ds390/gen.c
6299 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6306 symbol *tlbl = newiTempLabel (NULL);
6307 int sizel = AOP_SIZE (left);
6309 emitcode ("setb", "c");
6312 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6314 MOVA (aopGet (left, offset, FALSE, FALSE));
6316 if ((posbit = isLiteralBit (bytelit)) != 0)
6317 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6320 if (bytelit != 0x0FFL)
6321 emitcode ("anl", "a,%s",
6322 aopGet (right, offset, FALSE, TRUE));
6323 emitcode ("jnz", "%05d$", tlbl->key + 100);
6328 // bit = left & literal
6331 emitcode ("clr", "c");
6332 emitcode ("", "%05d$:", tlbl->key + 100);
6334 // if(left & literal)
6338 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6340 emitcode ("", "%05d$:", tlbl->key + 100);
6348 /* if left is same as result */
6349 if (sameRegs (AOP (result), AOP (left)))
6351 for (; size--; offset++)
6353 if (AOP_TYPE (right) == AOP_LIT)
6355 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6356 if (bytelit == 0x0FF)
6358 /* dummy read of volatile operand */
6359 if (isOperandVolatile (left, FALSE))
6360 MOVA (aopGet (left, offset, FALSE, FALSE));
6364 else if (bytelit == 0)
6366 aopPut (result, zero, offset, isOperandVolatile (result, FALSE));
6368 else if (IS_AOP_PREG (result))
6370 MOVA (aopGet (left, offset, FALSE, TRUE));
6371 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6372 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6375 emitcode ("anl", "%s,%s",
6376 aopGet (left, offset, FALSE, TRUE),
6377 aopGet (right, offset, FALSE, FALSE));
6381 if (AOP_TYPE (left) == AOP_ACC && offset == 0)
6383 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6387 MOVA (aopGet (right, offset, FALSE, FALSE));
6388 if (IS_AOP_PREG (result))
6390 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6391 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6394 emitcode ("anl", "%s,a",
6395 aopGet (left, offset, FALSE, TRUE));
6402 // left & result in different registers
6403 if (AOP_TYPE (result) == AOP_CRY)
6406 // if(size), result in bit
6407 // if(!size && ifx), conditional oper: if(left & right)
6408 symbol *tlbl = newiTempLabel (NULL);
6409 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6411 emitcode ("setb", "c");
6414 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6415 && AOP_TYPE(left)==AOP_ACC)
6418 emitcode("mov", "a,b");
6419 emitcode ("anl", "a,%s",
6420 aopGet (right, offset, FALSE, FALSE));
6422 if (AOP_TYPE(left)==AOP_ACC)
6426 bool pushedB = pushB ();
6427 emitcode("mov", "b,a");
6428 MOVA (aopGet (right, offset, FALSE, FALSE));
6429 emitcode("anl", "a,b");
6434 MOVA (aopGet (right, offset, FALSE, FALSE));
6435 emitcode("anl", "a,b");
6438 MOVA (aopGet (right, offset, FALSE, FALSE));
6439 emitcode ("anl", "a,%s",
6440 aopGet (left, offset, FALSE, FALSE));
6443 emitcode ("jnz", "%05d$", tlbl->key + 100);
6449 emitcode ("", "%05d$:", tlbl->key + 100);
6453 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6455 emitcode ("", "%05d$:", tlbl->key + 100);
6459 for (; (size--); offset++)
6462 // result = left & right
6463 if (AOP_TYPE (right) == AOP_LIT)
6465 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6466 if (bytelit == 0x0FF)
6469 aopGet (left, offset, FALSE, FALSE),
6471 isOperandVolatile (result, FALSE));
6474 else if (bytelit == 0)
6476 /* dummy read of volatile operand */
6477 if (isOperandVolatile (left, FALSE))
6478 MOVA (aopGet (left, offset, FALSE, FALSE));
6479 aopPut (result, zero, offset, isOperandVolatile (result, FALSE));
6482 else if (AOP_TYPE (left) == AOP_ACC)
6486 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6487 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6492 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6493 aopPut (result, "b", offset, isOperandVolatile (result, FALSE));
6498 // faster than result <- left, anl result,right
6499 // and better if result is SFR
6500 if (AOP_TYPE (left) == AOP_ACC)
6503 emitcode("mov", "a,b");
6504 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6508 MOVA (aopGet (right, offset, FALSE, FALSE));
6509 emitcode ("anl", "a,%s",
6510 aopGet (left, offset, FALSE, FALSE));
6512 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6518 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6519 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6520 freeAsmop (result, NULL, ic, TRUE);
6523 /*-----------------------------------------------------------------*/
6524 /* genOr - code for or */
6525 /*-----------------------------------------------------------------*/
6527 genOr (iCode * ic, iCode * ifx)
6529 operand *left, *right, *result;
6530 int size, offset = 0;
6531 unsigned long lit = 0L;
6534 D(emitcode ("; genOr",""));
6536 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6537 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6538 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6541 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6543 AOP_TYPE (left), AOP_TYPE (right));
6544 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6546 AOP_SIZE (left), AOP_SIZE (right));
6549 /* if left is a literal & right is not then exchange them */
6550 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6551 AOP_NEEDSACC (left))
6553 operand *tmp = right;
6558 /* if result = right then exchange them */
6559 if (sameRegs (AOP (result), AOP (right)))
6561 operand *tmp = right;
6566 /* if right is bit then exchange them */
6567 if (AOP_TYPE (right) == AOP_CRY &&
6568 AOP_TYPE (left) != AOP_CRY)
6570 operand *tmp = right;
6574 if (AOP_TYPE (right) == AOP_LIT)
6575 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6577 size = AOP_SIZE (result);
6581 if (AOP_TYPE (left) == AOP_CRY)
6583 if (AOP_TYPE (right) == AOP_LIT)
6585 // c = bit | literal;
6588 // lit != 0 => result = 1
6589 if (AOP_TYPE (result) == AOP_CRY)
6592 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6594 continueIfTrue (ifx);
6597 emitcode ("setb", "c");
6601 // lit == 0 => result = left
6602 if (size && sameRegs (AOP (result), AOP (left)))
6604 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6609 if (AOP_TYPE (right) == AOP_CRY)
6612 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6613 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6618 symbol *tlbl = newiTempLabel (NULL);
6619 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6620 emitcode ("setb", "c");
6621 emitcode ("jb", "%s,%05d$",
6622 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6624 emitcode ("jnz", "%05d$", tlbl->key + 100);
6625 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6627 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6633 emitcode ("", "%05d$:", tlbl->key + 100);
6642 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6643 genIfxJump (ifx, "c", left, right, result);
6647 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6648 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6649 if ((AOP_TYPE (right) == AOP_LIT) &&
6650 (AOP_TYPE (result) == AOP_CRY) &&
6651 (AOP_TYPE (left) != AOP_CRY))
6657 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6659 continueIfTrue (ifx);
6664 // lit = 0, result = boolean(left)
6666 emitcode ("setb", "c");
6670 symbol *tlbl = newiTempLabel (NULL);
6671 emitcode ("jnz", "%05d$", tlbl->key + 100);
6673 emitcode ("", "%05d$:", tlbl->key + 100);
6677 genIfxJump (ifx, "a", left, right, result);
6685 /* if left is same as result */
6686 if (sameRegs (AOP (result), AOP (left)))
6688 for (; size--; offset++)
6690 if (AOP_TYPE (right) == AOP_LIT)
6692 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6695 /* dummy read of volatile operand */
6696 if (isOperandVolatile (left, FALSE))
6697 MOVA (aopGet (left, offset, FALSE, FALSE));
6701 else if (bytelit == 0x0FF)
6703 aopPut (result, "#0xFF", offset, isOperandVolatile (result, FALSE));
6705 else if (IS_AOP_PREG (left))
6707 MOVA (aopGet (left, offset, FALSE, TRUE));
6708 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6709 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6713 emitcode ("orl", "%s,%s",
6714 aopGet (left, offset, FALSE, TRUE),
6715 aopGet (right, offset, FALSE, FALSE));
6720 if (AOP_TYPE (left) == AOP_ACC)
6723 emitcode("mov", "a,b");
6724 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6728 MOVA (aopGet (right, offset, FALSE, FALSE));
6729 if (IS_AOP_PREG (left))
6731 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6732 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6736 emitcode ("orl", "%s,a",
6737 aopGet (left, offset, FALSE, TRUE));
6745 // left & result in different registers
6746 if (AOP_TYPE (result) == AOP_CRY)
6749 // if(size), result in bit
6750 // if(!size && ifx), conditional oper: if(left | right)
6751 symbol *tlbl = newiTempLabel (NULL);
6752 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6754 emitcode ("setb", "c");
6757 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6759 emitcode("mov", "a,b");
6760 emitcode ("orl", "a,%s",
6761 aopGet (right, offset, FALSE, FALSE));
6763 MOVA (aopGet (right, offset, FALSE, FALSE));
6764 emitcode ("orl", "a,%s",
6765 aopGet (left, offset, FALSE, FALSE));
6767 emitcode ("jnz", "%05d$", tlbl->key + 100);
6773 emitcode ("", "%05d$:", tlbl->key + 100);
6777 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6779 emitcode ("", "%05d$:", tlbl->key + 100);
6783 for (; (size--); offset++)
6786 // result = left | right
6787 if (AOP_TYPE (right) == AOP_LIT)
6789 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6793 aopGet (left, offset, FALSE, FALSE),
6795 isOperandVolatile (result, FALSE));
6798 else if (bytelit == 0x0FF)
6800 /* dummy read of volatile operand */
6801 if (isOperandVolatile (left, FALSE))
6802 MOVA (aopGet (left, offset, FALSE, FALSE));
6803 aopPut (result, "#0xFF", offset, isOperandVolatile (result, FALSE));
6807 // faster than result <- left, anl result,right
6808 // and better if result is SFR
6809 if (AOP_TYPE (left) == AOP_ACC)
6812 emitcode("mov", "a,b");
6813 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6817 MOVA (aopGet (right, offset, FALSE, FALSE));
6818 emitcode ("orl", "a,%s",
6819 aopGet (left, offset, FALSE, FALSE));
6821 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6827 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6828 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6829 freeAsmop (result, NULL, ic, TRUE);
6832 /*-----------------------------------------------------------------*/
6833 /* genXor - code for xclusive or */
6834 /*-----------------------------------------------------------------*/
6836 genXor (iCode * ic, iCode * ifx)
6838 operand *left, *right, *result;
6839 int size, offset = 0;
6840 unsigned long lit = 0L;
6843 D(emitcode ("; genXor",""));
6845 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6846 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6847 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6850 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6852 AOP_TYPE (left), AOP_TYPE (right));
6853 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6855 AOP_SIZE (left), AOP_SIZE (right));
6858 /* if left is a literal & right is not ||
6859 if left needs acc & right does not */
6860 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6861 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
6863 operand *tmp = right;
6868 /* if result = right then exchange them */
6869 if (sameRegs (AOP (result), AOP (right)))
6871 operand *tmp = right;
6876 /* if right is bit then exchange them */
6877 if (AOP_TYPE (right) == AOP_CRY &&
6878 AOP_TYPE (left) != AOP_CRY)
6880 operand *tmp = right;
6884 if (AOP_TYPE (right) == AOP_LIT)
6885 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6887 size = AOP_SIZE (result);
6891 if (AOP_TYPE (left) == AOP_CRY)
6893 if (AOP_TYPE (right) == AOP_LIT)
6895 // c = bit & literal;
6898 // lit>>1 != 0 => result = 1
6899 if (AOP_TYPE (result) == AOP_CRY)
6902 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6904 continueIfTrue (ifx);
6907 emitcode ("setb", "c");
6914 // lit == 0, result = left
6915 if (size && sameRegs (AOP (result), AOP (left)))
6917 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6921 // lit == 1, result = not(left)
6922 if (size && sameRegs (AOP (result), AOP (left)))
6924 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6929 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6930 emitcode ("cpl", "c");
6939 symbol *tlbl = newiTempLabel (NULL);
6940 if (AOP_TYPE (right) == AOP_CRY)
6943 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6947 int sizer = AOP_SIZE (right);
6949 // if val>>1 != 0, result = 1
6950 emitcode ("setb", "c");
6953 MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
6955 // test the msb of the lsb
6956 emitcode ("anl", "a,#0xfe");
6957 emitcode ("jnz", "%05d$", tlbl->key + 100);
6961 emitcode ("rrc", "a");
6963 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6964 emitcode ("cpl", "c");
6965 emitcode ("", "%05d$:", (tlbl->key + 100));
6972 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6973 genIfxJump (ifx, "c", left, right, result);
6977 /* if left is same as result */
6978 if (sameRegs (AOP (result), AOP (left)))
6980 for (; size--; offset++)
6982 if (AOP_TYPE (right) == AOP_LIT)
6984 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6987 /* dummy read of volatile operand */
6988 if (isOperandVolatile (left, FALSE))
6989 MOVA (aopGet (left, offset, FALSE, FALSE));
6993 else if (IS_AOP_PREG (left))
6995 MOVA (aopGet (left, offset, FALSE, TRUE));
6996 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6997 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7001 emitcode ("xrl", "%s,%s",
7002 aopGet (left, offset, FALSE, TRUE),
7003 aopGet (right, offset, FALSE, FALSE));
7008 if (AOP_TYPE (left) == AOP_ACC)
7011 emitcode("mov", "a,b");
7012 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7016 MOVA (aopGet (right, offset, FALSE, FALSE));
7017 if (IS_AOP_PREG (left))
7019 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7020 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7023 emitcode ("xrl", "%s,a",
7024 aopGet (left, offset, FALSE, TRUE));
7031 // left & result in different registers
7032 if (AOP_TYPE (result) == AOP_CRY)
7035 // if(size), result in bit
7036 // if(!size && ifx), conditional oper: if(left ^ right)
7037 symbol *tlbl = newiTempLabel (NULL);
7038 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7040 emitcode ("setb", "c");
7043 if ((AOP_TYPE (right) == AOP_LIT) &&
7044 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7046 MOVA (aopGet (left, offset, FALSE, FALSE));
7050 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7052 emitcode("mov", "a,b");
7053 emitcode ("xrl", "a,%s",
7054 aopGet (right, offset, FALSE, FALSE));
7056 MOVA (aopGet (right, offset, FALSE, FALSE));
7057 emitcode ("xrl", "a,%s",
7058 aopGet (left, offset, FALSE, FALSE));
7061 emitcode ("jnz", "%05d$", tlbl->key + 100);
7067 emitcode ("", "%05d$:", tlbl->key + 100);
7071 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7075 for (; (size--); offset++)
7078 // result = left & right
7079 if (AOP_TYPE (right) == AOP_LIT)
7081 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7085 aopGet (left, offset, FALSE, FALSE),
7087 isOperandVolatile (result, FALSE));
7091 // faster than result <- left, anl result,right
7092 // and better if result is SFR
7093 if (AOP_TYPE (left) == AOP_ACC)
7096 emitcode("mov", "a,b");
7097 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7101 MOVA (aopGet (right, offset, FALSE, FALSE));
7102 emitcode ("xrl", "a,%s",
7103 aopGet (left, offset, FALSE, TRUE));
7105 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7111 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7112 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7113 freeAsmop (result, NULL, ic, TRUE);
7116 /*-----------------------------------------------------------------*/
7117 /* genInline - write the inline code out */
7118 /*-----------------------------------------------------------------*/
7120 genInline (iCode * ic)
7122 char *buffer, *bp, *bp1;
7124 D(emitcode ("; genInline",""));
7126 _G.inLine += (!options.asmpeep);
7128 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
7129 strcpy (buffer, IC_INLINE (ic));
7131 /* emit each line as a code */
7142 /* Add \n for labels, not dirs such as c:\mydir */
7143 if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
7157 /* emitcode("",buffer); */
7158 _G.inLine -= (!options.asmpeep);
7161 /*-----------------------------------------------------------------*/
7162 /* genRRC - rotate right with carry */
7163 /*-----------------------------------------------------------------*/
7167 operand *left, *result;
7168 int size, offset = 0;
7171 D(emitcode ("; genRRC",""));
7173 /* rotate right with carry */
7174 left = IC_LEFT (ic);
7175 result = IC_RESULT (ic);
7176 aopOp (left, ic, FALSE);
7177 aopOp (result, ic, FALSE);
7179 /* move it to the result */
7180 size = AOP_SIZE (result);
7182 if (size == 1) { /* special case for 1 byte */
7183 l = aopGet (left, offset, FALSE, FALSE);
7185 emitcode ("rr", "a");
7188 /* no need to clear carry, bit7 will be written later */
7191 l = aopGet (left, offset, FALSE, FALSE);
7193 emitcode ("rrc", "a");
7194 if (AOP_SIZE (result) > 1)
7195 aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
7197 /* now we need to put the carry into the
7198 highest order byte of the result */
7199 if (AOP_SIZE (result) > 1)
7201 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7204 emitcode ("mov", "acc.7,c");
7206 aopPut (result, "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
7207 freeAsmop (left, NULL, ic, TRUE);
7208 freeAsmop (result, NULL, ic, TRUE);
7211 /*-----------------------------------------------------------------*/
7212 /* genRLC - generate code for rotate left with carry */
7213 /*-----------------------------------------------------------------*/
7217 operand *left, *result;
7218 int size, offset = 0;
7221 D(emitcode ("; genRLC",""));
7223 /* rotate right with carry */
7224 left = IC_LEFT (ic);
7225 result = IC_RESULT (ic);
7226 aopOp (left, ic, FALSE);
7227 aopOp (result, ic, FALSE);
7229 /* move it to the result */
7230 size = AOP_SIZE (result);
7234 l = aopGet (left, offset, FALSE, FALSE);
7236 if (size == 0) { /* special case for 1 byte */
7240 emitcode("rlc","a"); /* bit0 will be written later */
7241 if (AOP_SIZE (result) > 1)
7242 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
7245 l = aopGet (left, offset, FALSE, FALSE);
7247 emitcode ("rlc", "a");
7248 if (AOP_SIZE (result) > 1)
7249 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
7252 /* now we need to put the carry into the
7253 highest order byte of the result */
7254 if (AOP_SIZE (result) > 1)
7256 l = aopGet (result, 0, FALSE, FALSE);
7259 emitcode ("mov", "acc.0,c");
7261 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
7262 freeAsmop (left, NULL, ic, TRUE);
7263 freeAsmop (result, NULL, ic, TRUE);
7266 /*-----------------------------------------------------------------*/
7267 /* genGetHbit - generates code get highest order bit */
7268 /*-----------------------------------------------------------------*/
7270 genGetHbit (iCode * ic)
7272 operand *left, *result;
7274 D(emitcode ("; genGetHbit",""));
7276 left = IC_LEFT (ic);
7277 result = IC_RESULT (ic);
7278 aopOp (left, ic, FALSE);
7279 aopOp (result, ic, FALSE);
7281 /* get the highest order byte into a */
7282 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7283 if (AOP_TYPE (result) == AOP_CRY)
7285 emitcode ("rlc", "a");
7290 emitcode ("rl", "a");
7291 emitcode ("anl", "a,#0x01");
7296 freeAsmop (left, NULL, ic, TRUE);
7297 freeAsmop (result, NULL, ic, TRUE);
7300 /*-----------------------------------------------------------------*/
7301 /* genGetAbit - generates code get a single bit */
7302 /*-----------------------------------------------------------------*/
7304 genGetAbit (iCode * ic)
7306 operand *left, *right, *result;
7309 D(emitcode ("; genGetAbit",""));
7311 left = IC_LEFT (ic);
7312 right = IC_RIGHT (ic);
7313 result = IC_RESULT (ic);
7314 aopOp (left, ic, FALSE);
7315 aopOp (right, ic, FALSE);
7316 aopOp (result, ic, FALSE);
7318 shCount = (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7320 /* get the needed byte into a */
7321 MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7323 if (AOP_TYPE (result) == AOP_CRY)
7326 emitcode ("rlc", "a");
7327 else if ((shCount) == 0)
7328 emitcode ("rrc", "a");
7330 emitcode ("mov", "c,acc[%d]", shCount);
7338 emitcode ("rr", "a");
7341 emitcode ("rr", "a");
7344 emitcode ("anl", "a,#0x01");
7348 emitcode ("mov", "c,acc[%d]", shCount);
7349 emitcode ("clr", "a");
7350 emitcode ("rlc", "a");
7353 emitcode ("swap", "a");
7354 emitcode ("anl", "a,#0x01");
7357 emitcode ("rl", "a");
7360 emitcode ("rl", "a");
7361 emitcode ("anl", "a,#0x01");
7367 freeAsmop (left, NULL, ic, TRUE);
7368 freeAsmop (right, NULL, ic, TRUE);
7369 freeAsmop (result, NULL, ic, TRUE);
7372 /*-----------------------------------------------------------------*/
7373 /* genGetByte - generates code get a single byte */
7374 /*-----------------------------------------------------------------*/
7376 genGetByte (iCode * ic)
7378 operand *left, *right, *result;
7381 D(emitcode ("; genGetByte",""));
7383 left = IC_LEFT (ic);
7384 right = IC_RIGHT (ic);
7385 result = IC_RESULT (ic);
7386 aopOp (left, ic, FALSE);
7387 aopOp (right, ic, FALSE);
7388 aopOp (result, ic, FALSE);
7390 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7392 aopGet (left, offset, FALSE, FALSE),
7394 isOperandVolatile (result, FALSE));
7396 freeAsmop (left, NULL, ic, TRUE);
7397 freeAsmop (right, NULL, ic, TRUE);
7398 freeAsmop (result, NULL, ic, TRUE);
7401 /*-----------------------------------------------------------------*/
7402 /* genGetWord - generates code get two bytes */
7403 /*-----------------------------------------------------------------*/
7405 genGetWord (iCode * ic)
7407 operand *left, *right, *result;
7410 D(emitcode ("; genGetWord",""));
7412 left = IC_LEFT (ic);
7413 right = IC_RIGHT (ic);
7414 result = IC_RESULT (ic);
7415 aopOp (left, ic, FALSE);
7416 aopOp (right, ic, FALSE);
7417 aopOp (result, ic, FALSE);
7419 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7421 aopGet (left, offset, FALSE, FALSE),
7423 isOperandVolatile (result, FALSE));
7425 aopGet (left, offset+1, FALSE, FALSE),
7427 isOperandVolatile (result, FALSE));
7429 freeAsmop (left, NULL, ic, TRUE);
7430 freeAsmop (right, NULL, ic, TRUE);
7431 freeAsmop (result, NULL, ic, TRUE);
7434 /*-----------------------------------------------------------------*/
7435 /* genSwap - generates code to swap nibbles or bytes */
7436 /*-----------------------------------------------------------------*/
7438 genSwap (iCode * ic)
7440 operand *left, *result;
7442 D(emitcode ("; genSwap",""));
7444 left = IC_LEFT (ic);
7445 result = IC_RESULT (ic);
7446 aopOp (left, ic, FALSE);
7447 aopOp (result, ic, FALSE);
7449 switch (AOP_SIZE (left))
7451 case 1: /* swap nibbles in byte */
7452 MOVA (aopGet (left, 0, FALSE, FALSE));
7453 emitcode ("swap", "a");
7454 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
7456 case 2: /* swap bytes in word */
7457 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7459 MOVA (aopGet (left, 0, FALSE, FALSE));
7460 aopPut (result, aopGet (left, 1, FALSE, FALSE),
7461 0, isOperandVolatile (result, FALSE));
7462 aopPut (result, "a", 1, isOperandVolatile (result, FALSE));
7464 else if (operandsEqu (left, result))
7467 bool pushedB = FALSE, leftInB = FALSE;
7469 MOVA (aopGet (left, 0, FALSE, FALSE));
7470 if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
7473 emitcode ("mov", "b,a");
7477 aopPut (result, aopGet (left, 1, FALSE, FALSE),
7478 0, isOperandVolatile (result, FALSE));
7479 aopPut (result, reg, 1, isOperandVolatile (result, FALSE));
7486 aopPut (result, aopGet (left, 1, FALSE, FALSE),
7487 0, isOperandVolatile (result, FALSE));
7488 aopPut (result, aopGet (left, 0, FALSE, FALSE),
7489 1, isOperandVolatile (result, FALSE));
7493 wassertl(FALSE, "unsupported SWAP operand size");
7496 freeAsmop (left, NULL, ic, TRUE);
7497 freeAsmop (result, NULL, ic, TRUE);
7501 /*-----------------------------------------------------------------*/
7502 /* AccRol - rotate left accumulator by known count */
7503 /*-----------------------------------------------------------------*/
7505 AccRol (int shCount)
7507 shCount &= 0x0007; // shCount : 0..7
7514 emitcode ("rl", "a");
7517 emitcode ("rl", "a");
7518 emitcode ("rl", "a");
7521 emitcode ("swap", "a");
7522 emitcode ("rr", "a");
7525 emitcode ("swap", "a");
7528 emitcode ("swap", "a");
7529 emitcode ("rl", "a");
7532 emitcode ("rr", "a");
7533 emitcode ("rr", "a");
7536 emitcode ("rr", "a");
7541 /*-----------------------------------------------------------------*/
7542 /* AccLsh - left shift accumulator by known count */
7543 /*-----------------------------------------------------------------*/
7545 AccLsh (int shCount)
7550 emitcode ("add", "a,acc");
7551 else if (shCount == 2)
7553 emitcode ("add", "a,acc");
7554 emitcode ("add", "a,acc");
7558 /* rotate left accumulator */
7560 /* and kill the lower order bits */
7561 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
7566 /*-----------------------------------------------------------------*/
7567 /* AccRsh - right shift accumulator by known count */
7568 /*-----------------------------------------------------------------*/
7570 AccRsh (int shCount)
7577 emitcode ("rrc", "a");
7581 /* rotate right accumulator */
7582 AccRol (8 - shCount);
7583 /* and kill the higher order bits */
7584 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7589 /*-----------------------------------------------------------------*/
7590 /* AccSRsh - signed right shift accumulator by known count */
7591 /*-----------------------------------------------------------------*/
7593 AccSRsh (int shCount)
7600 emitcode ("mov", "c,acc.7");
7601 emitcode ("rrc", "a");
7603 else if (shCount == 2)
7605 emitcode ("mov", "c,acc.7");
7606 emitcode ("rrc", "a");
7607 emitcode ("mov", "c,acc.7");
7608 emitcode ("rrc", "a");
7612 tlbl = newiTempLabel (NULL);
7613 /* rotate right accumulator */
7614 AccRol (8 - shCount);
7615 /* and kill the higher order bits */
7616 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7617 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7618 emitcode ("orl", "a,#0x%02x",
7619 (unsigned char) ~SRMask[shCount]);
7620 emitcode ("", "%05d$:", tlbl->key + 100);
7625 /*-----------------------------------------------------------------*/
7626 /* shiftR1Left2Result - shift right one byte from left to result */
7627 /*-----------------------------------------------------------------*/
7629 shiftR1Left2Result (operand * left, int offl,
7630 operand * result, int offr,
7631 int shCount, int sign)
7633 MOVA (aopGet (left, offl, FALSE, FALSE));
7634 /* shift right accumulator */
7639 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7642 /*-----------------------------------------------------------------*/
7643 /* shiftL1Left2Result - shift left one byte from left to result */
7644 /*-----------------------------------------------------------------*/
7646 shiftL1Left2Result (operand * left, int offl,
7647 operand * result, int offr, int shCount)
7650 l = aopGet (left, offl, FALSE, FALSE);
7652 /* shift left accumulator */
7654 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7657 /*-----------------------------------------------------------------*/
7658 /* movLeft2Result - move byte from left to result */
7659 /*-----------------------------------------------------------------*/
7661 movLeft2Result (operand * left, int offl,
7662 operand * result, int offr, int sign)
7665 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7667 l = aopGet (left, offl, FALSE, FALSE);
7669 if (*l == '@' && (IS_AOP_PREG (result)))
7671 emitcode ("mov", "a,%s", l);
7672 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7677 aopPut (result, l, offr, isOperandVolatile (result, FALSE));
7680 /* MSB sign in acc.7 ! */
7681 if (getDataSize (left) == offl + 1)
7683 emitcode ("mov", "a,%s", l);
7684 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7691 /*-----------------------------------------------------------------*/
7692 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7693 /*-----------------------------------------------------------------*/
7697 emitcode ("rrc", "a");
7698 emitcode ("xch", "a,%s", x);
7699 emitcode ("rrc", "a");
7700 emitcode ("xch", "a,%s", x);
7703 /*-----------------------------------------------------------------*/
7704 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7705 /*-----------------------------------------------------------------*/
7709 emitcode ("xch", "a,%s", x);
7710 emitcode ("rlc", "a");
7711 emitcode ("xch", "a,%s", x);
7712 emitcode ("rlc", "a");
7715 /*-----------------------------------------------------------------*/
7716 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7717 /*-----------------------------------------------------------------*/
7721 emitcode ("xch", "a,%s", x);
7722 emitcode ("add", "a,acc");
7723 emitcode ("xch", "a,%s", x);
7724 emitcode ("rlc", "a");
7727 /*-----------------------------------------------------------------*/
7728 /* AccAXLsh - left shift a:x by known count (0..7) */
7729 /*-----------------------------------------------------------------*/
7731 AccAXLsh (char *x, int shCount)
7746 case 5: // AAAAABBB:CCCCCDDD
7748 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7750 emitcode ("anl", "a,#0x%02x",
7751 SLMask[shCount]); // BBB00000:CCCCCDDD
7753 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7755 AccRol (shCount); // DDDCCCCC:BBB00000
7757 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7759 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7761 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7763 emitcode ("anl", "a,#0x%02x",
7764 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7766 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7768 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7771 case 6: // AAAAAABB:CCCCCCDD
7772 emitcode ("anl", "a,#0x%02x",
7773 SRMask[shCount]); // 000000BB:CCCCCCDD
7774 emitcode ("mov", "c,acc.0"); // c = B
7775 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7777 AccAXRrl1 (x); // BCCCCCCD:D000000B
7778 AccAXRrl1 (x); // BBCCCCCC:DD000000
7780 emitcode("rrc","a");
7781 emitcode("xch","a,%s", x);
7782 emitcode("rrc","a");
7783 emitcode("mov","c,acc.0"); //<< get correct bit
7784 emitcode("xch","a,%s", x);
7786 emitcode("rrc","a");
7787 emitcode("xch","a,%s", x);
7788 emitcode("rrc","a");
7789 emitcode("xch","a,%s", x);
7792 case 7: // a:x <<= 7
7794 emitcode ("anl", "a,#0x%02x",
7795 SRMask[shCount]); // 0000000B:CCCCCCCD
7797 emitcode ("mov", "c,acc.0"); // c = B
7799 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7801 AccAXRrl1 (x); // BCCCCCCC:D0000000
7809 /*-----------------------------------------------------------------*/
7810 /* AccAXRsh - right shift a:x known count (0..7) */
7811 /*-----------------------------------------------------------------*/
7813 AccAXRsh (char *x, int shCount)
7821 AccAXRrl1 (x); // 0->a:x
7826 AccAXRrl1 (x); // 0->a:x
7829 AccAXRrl1 (x); // 0->a:x
7834 case 5: // AAAAABBB:CCCCCDDD = a:x
7836 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7838 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7840 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7842 emitcode ("anl", "a,#0x%02x",
7843 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7845 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7847 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7849 emitcode ("anl", "a,#0x%02x",
7850 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7852 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7854 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7856 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7859 case 6: // AABBBBBB:CCDDDDDD
7861 emitcode ("mov", "c,acc.7");
7862 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7864 emitcode ("mov", "c,acc.7");
7865 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7867 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7869 emitcode ("anl", "a,#0x%02x",
7870 SRMask[shCount]); // 000000AA:BBBBBBCC
7873 case 7: // ABBBBBBB:CDDDDDDD
7875 emitcode ("mov", "c,acc.7"); // c = A
7877 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7879 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7881 emitcode ("anl", "a,#0x%02x",
7882 SRMask[shCount]); // 0000000A:BBBBBBBC
7890 /*-----------------------------------------------------------------*/
7891 /* AccAXRshS - right shift signed a:x known count (0..7) */
7892 /*-----------------------------------------------------------------*/
7894 AccAXRshS (char *x, int shCount)
7902 emitcode ("mov", "c,acc.7");
7903 AccAXRrl1 (x); // s->a:x
7907 emitcode ("mov", "c,acc.7");
7908 AccAXRrl1 (x); // s->a:x
7910 emitcode ("mov", "c,acc.7");
7911 AccAXRrl1 (x); // s->a:x
7916 case 5: // AAAAABBB:CCCCCDDD = a:x
7918 tlbl = newiTempLabel (NULL);
7919 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7921 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7923 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7925 emitcode ("anl", "a,#0x%02x",
7926 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7928 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7930 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7932 emitcode ("anl", "a,#0x%02x",
7933 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7935 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7937 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7939 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7941 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7942 emitcode ("orl", "a,#0x%02x",
7943 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7945 emitcode ("", "%05d$:", tlbl->key + 100);
7946 break; // SSSSAAAA:BBBCCCCC
7948 case 6: // AABBBBBB:CCDDDDDD
7950 tlbl = newiTempLabel (NULL);
7951 emitcode ("mov", "c,acc.7");
7952 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7954 emitcode ("mov", "c,acc.7");
7955 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7957 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7959 emitcode ("anl", "a,#0x%02x",
7960 SRMask[shCount]); // 000000AA:BBBBBBCC
7962 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7963 emitcode ("orl", "a,#0x%02x",
7964 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7966 emitcode ("", "%05d$:", tlbl->key + 100);
7968 case 7: // ABBBBBBB:CDDDDDDD
7970 tlbl = newiTempLabel (NULL);
7971 emitcode ("mov", "c,acc.7"); // c = A
7973 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7975 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7977 emitcode ("anl", "a,#0x%02x",
7978 SRMask[shCount]); // 0000000A:BBBBBBBC
7980 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7981 emitcode ("orl", "a,#0x%02x",
7982 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7984 emitcode ("", "%05d$:", tlbl->key + 100);
7991 /*-----------------------------------------------------------------*/
7992 /* shiftL2Left2Result - shift left two bytes from left to result */
7993 /*-----------------------------------------------------------------*/
7995 shiftL2Left2Result (operand * left, int offl,
7996 operand * result, int offr, int shCount)
7998 if (sameRegs (AOP (result), AOP (left)) &&
7999 ((offl + MSB16) == offr))
8001 /* don't crash result[offr] */
8002 MOVA (aopGet (left, offl, FALSE, FALSE));
8003 emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8007 movLeft2Result (left, offl, result, offr, 0);
8008 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8010 /* ax << shCount (x = lsb(result)) */
8011 AccAXLsh (aopGet (result, offr, FALSE, FALSE), shCount);
8012 aopPut (result, "a", offr + MSB16, isOperandVolatile (result, FALSE));
8016 /*-----------------------------------------------------------------*/
8017 /* shiftR2Left2Result - shift right two bytes from left to result */
8018 /*-----------------------------------------------------------------*/
8020 shiftR2Left2Result (operand * left, int offl,
8021 operand * result, int offr,
8022 int shCount, int sign)
8024 if (sameRegs (AOP (result), AOP (left)) &&
8025 ((offl + MSB16) == offr))
8027 /* don't crash result[offr] */
8028 MOVA (aopGet (left, offl, FALSE, FALSE));
8029 emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8033 movLeft2Result (left, offl, result, offr, 0);
8034 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8036 /* a:x >> shCount (x = lsb(result)) */
8038 AccAXRshS (aopGet (result, offr, FALSE, FALSE), shCount);
8040 AccAXRsh (aopGet (result, offr, FALSE, FALSE), shCount);
8041 if (getDataSize (result) > 1)
8042 aopPut (result, "a", offr + MSB16, isOperandVolatile (result, FALSE));
8045 /*-----------------------------------------------------------------*/
8046 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8047 /*-----------------------------------------------------------------*/
8049 shiftLLeftOrResult (operand * left, int offl,
8050 operand * result, int offr, int shCount)
8052 MOVA (aopGet (left, offl, FALSE, FALSE));
8053 /* shift left accumulator */
8055 /* or with result */
8056 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8057 /* back to result */
8058 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
8061 /*-----------------------------------------------------------------*/
8062 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8063 /*-----------------------------------------------------------------*/
8065 shiftRLeftOrResult (operand * left, int offl,
8066 operand * result, int offr, int shCount)
8068 MOVA (aopGet (left, offl, FALSE, FALSE));
8069 /* shift right accumulator */
8071 /* or with result */
8072 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8073 /* back to result */
8074 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
8077 /*-----------------------------------------------------------------*/
8078 /* genlshOne - left shift a one byte quantity by known count */
8079 /*-----------------------------------------------------------------*/
8081 genlshOne (operand * result, operand * left, int shCount)
8083 D(emitcode ("; genlshOne",""));
8085 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8088 /*-----------------------------------------------------------------*/
8089 /* genlshTwo - left shift two bytes by known amount != 0 */
8090 /*-----------------------------------------------------------------*/
8092 genlshTwo (operand * result, operand * left, int shCount)
8096 D(emitcode ("; genlshTwo",""));
8098 size = getDataSize (result);
8100 /* if shCount >= 8 */
8108 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8110 movLeft2Result (left, LSB, result, MSB16, 0);
8112 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8115 /* 1 <= shCount <= 7 */
8119 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8121 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8125 /*-----------------------------------------------------------------*/
8126 /* shiftLLong - shift left one long from left to result */
8127 /* offl = LSB or MSB16 */
8128 /*-----------------------------------------------------------------*/
8130 shiftLLong (operand * left, operand * result, int offr)
8133 int size = AOP_SIZE (result);
8135 if (size >= LSB + offr)
8137 l = aopGet (left, LSB, FALSE, FALSE);
8139 emitcode ("add", "a,acc");
8140 if (sameRegs (AOP (left), AOP (result)) &&
8141 size >= MSB16 + offr && offr != LSB)
8142 emitcode ("xch", "a,%s",
8143 aopGet (left, LSB + offr, FALSE, FALSE));
8145 aopPut (result, "a", LSB + offr, isOperandVolatile (result, FALSE));
8148 if (size >= MSB16 + offr)
8150 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8152 l = aopGet (left, MSB16, FALSE, FALSE);
8155 emitcode ("rlc", "a");
8156 if (sameRegs (AOP (left), AOP (result)) &&
8157 size >= MSB24 + offr && offr != LSB)
8158 emitcode ("xch", "a,%s",
8159 aopGet (left, MSB16 + offr, FALSE, FALSE));
8161 aopPut (result, "a", MSB16 + offr, isOperandVolatile (result, FALSE));
8164 if (size >= MSB24 + offr)
8166 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8168 l = aopGet (left, MSB24, FALSE, FALSE);
8171 emitcode ("rlc", "a");
8172 if (sameRegs (AOP (left), AOP (result)) &&
8173 size >= MSB32 + offr && offr != LSB)
8174 emitcode ("xch", "a,%s",
8175 aopGet (left, MSB24 + offr, FALSE, FALSE));
8177 aopPut (result, "a", MSB24 + offr, isOperandVolatile (result, FALSE));
8180 if (size > MSB32 + offr)
8182 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8184 l = aopGet (left, MSB32, FALSE, FALSE);
8187 emitcode ("rlc", "a");
8188 aopPut (result, "a", MSB32 + offr, isOperandVolatile (result, FALSE));
8191 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8194 /*-----------------------------------------------------------------*/
8195 /* genlshFour - shift four byte by a known amount != 0 */
8196 /*-----------------------------------------------------------------*/
8198 genlshFour (operand * result, operand * left, int shCount)
8202 D(emitcode ("; genlshFour",""));
8204 size = AOP_SIZE (result);
8206 /* if shifting more that 3 bytes */
8211 /* lowest order of left goes to the highest
8212 order of the destination */
8213 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8215 movLeft2Result (left, LSB, result, MSB32, 0);
8216 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8217 aopPut (result, zero, MSB16, isOperandVolatile (result, FALSE));
8218 aopPut (result, zero, MSB24, isOperandVolatile (result, FALSE));
8222 /* more than two bytes */
8223 else if (shCount >= 16)
8225 /* lower order two bytes goes to higher order two bytes */
8227 /* if some more remaining */
8229 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8232 movLeft2Result (left, MSB16, result, MSB32, 0);
8233 movLeft2Result (left, LSB, result, MSB24, 0);
8235 aopPut (result, zero, MSB16, isOperandVolatile (result, FALSE));
8236 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8240 /* if more than 1 byte */
8241 else if (shCount >= 8)
8243 /* lower order three bytes goes to higher order three bytes */
8248 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8250 movLeft2Result (left, LSB, result, MSB16, 0);
8256 movLeft2Result (left, MSB24, result, MSB32, 0);
8257 movLeft2Result (left, MSB16, result, MSB24, 0);
8258 movLeft2Result (left, LSB, result, MSB16, 0);
8259 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8261 else if (shCount == 1)
8262 shiftLLong (left, result, MSB16);
8265 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8266 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8267 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8268 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8273 /* 1 <= shCount <= 7 */
8274 else if (shCount <= 2)
8276 shiftLLong (left, result, LSB);
8278 shiftLLong (result, result, LSB);
8280 /* 3 <= shCount <= 7, optimize */
8283 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8284 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8285 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8289 /*-----------------------------------------------------------------*/
8290 /* genLeftShiftLiteral - left shifting by known count */
8291 /*-----------------------------------------------------------------*/
8293 genLeftShiftLiteral (operand * left,
8298 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8301 D(emitcode ("; genLeftShiftLiteral",""));
8303 freeAsmop (right, NULL, ic, TRUE);
8305 aopOp (left, ic, FALSE);
8306 aopOp (result, ic, FALSE);
8308 size = getSize (operandType (result));
8311 emitcode ("; shift left ", "result %d, left %d", size,
8315 /* I suppose that the left size >= result size */
8320 movLeft2Result (left, size, result, size, 0);
8324 else if (shCount >= (size * 8))
8326 aopPut (result, zero, size, isOperandVolatile (result, FALSE));
8332 genlshOne (result, left, shCount);
8336 genlshTwo (result, left, shCount);
8340 genlshFour (result, left, shCount);
8343 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8344 "*** ack! mystery literal shift!\n");
8348 freeAsmop (left, NULL, ic, TRUE);
8349 freeAsmop (result, NULL, ic, TRUE);
8352 /*-----------------------------------------------------------------*/
8353 /* genLeftShift - generates code for left shifting */
8354 /*-----------------------------------------------------------------*/
8356 genLeftShift (iCode * ic)
8358 operand *left, *right, *result;
8361 symbol *tlbl, *tlbl1;
8364 D(emitcode ("; genLeftShift",""));
8366 right = IC_RIGHT (ic);
8367 left = IC_LEFT (ic);
8368 result = IC_RESULT (ic);
8370 aopOp (right, ic, FALSE);
8372 /* if the shift count is known then do it
8373 as efficiently as possible */
8374 if (AOP_TYPE (right) == AOP_LIT)
8376 genLeftShiftLiteral (left, right, result, ic);
8380 /* shift count is unknown then we have to form
8381 a loop get the loop count in B : Note: we take
8382 only the lower order byte since shifting
8383 more that 32 bits make no sense anyway, ( the
8384 largest size of an object can be only 32 bits ) */
8387 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
8388 emitcode ("inc", "b");
8389 freeAsmop (right, NULL, ic, TRUE);
8390 aopOp (left, ic, FALSE);
8391 aopOp (result, ic, FALSE);
8393 /* now move the left to the result if they are not the same */
8394 if (!sameRegs (AOP (left), AOP (result)) &&
8395 AOP_SIZE (result) > 1)
8398 size = AOP_SIZE (result);
8402 l = aopGet (left, offset, FALSE, TRUE);
8403 if (*l == '@' && (IS_AOP_PREG (result)))
8406 emitcode ("mov", "a,%s", l);
8407 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
8410 aopPut (result, l, offset, isOperandVolatile (result, FALSE));
8415 tlbl = newiTempLabel (NULL);
8416 size = AOP_SIZE (result);
8418 tlbl1 = newiTempLabel (NULL);
8420 /* if it is only one byte then */
8423 symbol *tlbl1 = newiTempLabel (NULL);
8425 l = aopGet (left, 0, FALSE, FALSE);
8427 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8428 emitcode ("", "%05d$:", tlbl->key + 100);
8429 emitcode ("add", "a,acc");
8430 emitcode ("", "%05d$:", tlbl1->key + 100);
8431 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8433 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
8437 reAdjustPreg (AOP (result));
8439 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8440 emitcode ("", "%05d$:", tlbl->key + 100);
8441 l = aopGet (result, offset, FALSE, FALSE);
8443 emitcode ("add", "a,acc");
8444 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8447 l = aopGet (result, offset, FALSE, FALSE);
8449 emitcode ("rlc", "a");
8450 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8452 reAdjustPreg (AOP (result));
8454 emitcode ("", "%05d$:", tlbl1->key + 100);
8455 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8458 freeAsmop (left, NULL, ic, TRUE);
8459 freeAsmop (result, NULL, ic, TRUE);
8462 /*-----------------------------------------------------------------*/
8463 /* genrshOne - right shift a one byte quantity by known count */
8464 /*-----------------------------------------------------------------*/
8466 genrshOne (operand * result, operand * left,
8467 int shCount, int sign)
8469 D(emitcode ("; genrshOne",""));
8471 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8474 /*-----------------------------------------------------------------*/
8475 /* genrshTwo - right shift two bytes by known amount != 0 */
8476 /*-----------------------------------------------------------------*/
8478 genrshTwo (operand * result, operand * left,
8479 int shCount, int sign)
8481 D(emitcode ("; genrshTwo",""));
8483 /* if shCount >= 8 */
8488 shiftR1Left2Result (left, MSB16, result, LSB,
8491 movLeft2Result (left, MSB16, result, LSB, sign);
8492 addSign (result, MSB16, sign);
8495 /* 1 <= shCount <= 7 */
8497 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8500 /*-----------------------------------------------------------------*/
8501 /* shiftRLong - shift right one long from left to result */
8502 /* offl = LSB or MSB16 */
8503 /*-----------------------------------------------------------------*/
8505 shiftRLong (operand * left, int offl,
8506 operand * result, int sign)
8508 int isSameRegs=sameRegs(AOP(left),AOP(result));
8510 if (isSameRegs && offl>1) {
8511 // we are in big trouble, but this shouldn't happen
8512 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8515 MOVA (aopGet (left, MSB32, FALSE, FALSE));
8520 emitcode ("rlc", "a");
8521 emitcode ("subb", "a,acc");
8523 emitcode ("xch", "a,%s", aopGet (left, MSB32, FALSE, FALSE));
8525 aopPut (result, "a", MSB32, isOperandVolatile (result, FALSE));
8526 MOVA (aopGet (left, MSB32, FALSE, FALSE));
8529 aopPut (result, zero, MSB32, isOperandVolatile (result, FALSE));
8534 emitcode ("clr", "c");
8536 emitcode ("mov", "c,acc.7");
8539 emitcode ("rrc", "a");
8541 if (isSameRegs && offl==MSB16) {
8542 emitcode ("xch", "a,%s",aopGet (left, MSB24, FALSE, FALSE));
8544 aopPut (result, "a", MSB32-offl, isOperandVolatile (result, FALSE));
8545 MOVA (aopGet (left, MSB24, FALSE, FALSE));
8548 emitcode ("rrc", "a");
8549 if (isSameRegs && offl==1) {
8550 emitcode ("xch", "a,%s",aopGet (left, MSB16, FALSE, FALSE));
8552 aopPut (result, "a", MSB24-offl, isOperandVolatile (result, FALSE));
8553 MOVA (aopGet (left, MSB16, FALSE, FALSE));
8555 emitcode ("rrc", "a");
8556 aopPut (result, "a", MSB16 - offl, isOperandVolatile (result, FALSE));
8560 MOVA (aopGet (left, LSB, FALSE, FALSE));
8561 emitcode ("rrc", "a");
8562 aopPut (result, "a", LSB, isOperandVolatile (result, FALSE));
8566 /*-----------------------------------------------------------------*/
8567 /* genrshFour - shift four byte by a known amount != 0 */
8568 /*-----------------------------------------------------------------*/
8570 genrshFour (operand * result, operand * left,
8571 int shCount, int sign)
8573 D(emitcode ("; genrshFour",""));
8575 /* if shifting more that 3 bytes */
8580 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8582 movLeft2Result (left, MSB32, result, LSB, sign);
8583 addSign (result, MSB16, sign);
8585 else if (shCount >= 16)
8589 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8592 movLeft2Result (left, MSB24, result, LSB, 0);
8593 movLeft2Result (left, MSB32, result, MSB16, sign);
8595 addSign (result, MSB24, sign);
8597 else if (shCount >= 8)
8601 shiftRLong (left, MSB16, result, sign);
8602 else if (shCount == 0)
8604 movLeft2Result (left, MSB16, result, LSB, 0);
8605 movLeft2Result (left, MSB24, result, MSB16, 0);
8606 movLeft2Result (left, MSB32, result, MSB24, sign);
8607 addSign (result, MSB32, sign);
8611 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8612 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8613 /* the last shift is signed */
8614 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8615 addSign (result, MSB32, sign);
8619 { /* 1 <= shCount <= 7 */
8622 shiftRLong (left, LSB, result, sign);
8624 shiftRLong (result, LSB, result, sign);
8628 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8629 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8630 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8635 /*-----------------------------------------------------------------*/
8636 /* genRightShiftLiteral - right shifting by known count */
8637 /*-----------------------------------------------------------------*/
8639 genRightShiftLiteral (operand * left,
8645 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8648 D(emitcode ("; genRightShiftLiteral",""));
8650 freeAsmop (right, NULL, ic, TRUE);
8652 aopOp (left, ic, FALSE);
8653 aopOp (result, ic, FALSE);
8656 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8660 size = getDataSize (left);
8661 /* test the LEFT size !!! */
8663 /* I suppose that the left size >= result size */
8666 size = getDataSize (result);
8668 movLeft2Result (left, size, result, size, 0);
8671 else if (shCount >= (size * 8))
8674 /* get sign in acc.7 */
8675 MOVA (aopGet (left, size - 1, FALSE, FALSE));
8677 addSign (result, LSB, sign);
8684 genrshOne (result, left, shCount, sign);
8688 genrshTwo (result, left, shCount, sign);
8692 genrshFour (result, left, shCount, sign);
8698 freeAsmop (left, NULL, ic, TRUE);
8699 freeAsmop (result, NULL, ic, TRUE);
8702 /*-----------------------------------------------------------------*/
8703 /* genSignedRightShift - right shift of signed number */
8704 /*-----------------------------------------------------------------*/
8706 genSignedRightShift (iCode * ic)
8708 operand *right, *left, *result;
8711 symbol *tlbl, *tlbl1;
8714 D(emitcode ("; genSignedRightShift",""));
8716 /* we do it the hard way put the shift count in b
8717 and loop thru preserving the sign */
8719 right = IC_RIGHT (ic);
8720 left = IC_LEFT (ic);
8721 result = IC_RESULT (ic);
8723 aopOp (right, ic, FALSE);
8726 if (AOP_TYPE (right) == AOP_LIT)
8728 genRightShiftLiteral (left, right, result, ic, 1);
8731 /* shift count is unknown then we have to form
8732 a loop get the loop count in B : Note: we take
8733 only the lower order byte since shifting
8734 more that 32 bits make no sense anyway, ( the
8735 largest size of an object can be only 32 bits ) */
8738 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
8739 emitcode ("inc", "b");
8740 freeAsmop (right, NULL, ic, TRUE);
8741 aopOp (left, ic, FALSE);
8742 aopOp (result, ic, FALSE);
8744 /* now move the left to the result if they are not the
8746 if (!sameRegs (AOP (left), AOP (result)) &&
8747 AOP_SIZE (result) > 1)
8750 size = AOP_SIZE (result);
8754 l = aopGet (left, offset, FALSE, TRUE);
8755 if (*l == '@' && IS_AOP_PREG (result))
8758 emitcode ("mov", "a,%s", l);
8759 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
8762 aopPut (result, l, offset, isOperandVolatile (result, FALSE));
8767 /* mov the highest order bit to OVR */
8768 tlbl = newiTempLabel (NULL);
8769 tlbl1 = newiTempLabel (NULL);
8771 size = AOP_SIZE (result);
8773 MOVA (aopGet (left, offset, FALSE, FALSE));
8774 emitcode ("rlc", "a");
8775 emitcode ("mov", "ov,c");
8776 /* if it is only one byte then */
8779 l = aopGet (left, 0, FALSE, FALSE);
8781 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8782 emitcode ("", "%05d$:", tlbl->key + 100);
8783 emitcode ("mov", "c,ov");
8784 emitcode ("rrc", "a");
8785 emitcode ("", "%05d$:", tlbl1->key + 100);
8786 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8788 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
8792 reAdjustPreg (AOP (result));
8793 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8794 emitcode ("", "%05d$:", tlbl->key + 100);
8795 emitcode ("mov", "c,ov");
8798 l = aopGet (result, offset, FALSE, FALSE);
8800 emitcode ("rrc", "a");
8801 aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
8803 reAdjustPreg (AOP (result));
8804 emitcode ("", "%05d$:", tlbl1->key + 100);
8805 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8809 freeAsmop (left, NULL, ic, TRUE);
8810 freeAsmop (result, NULL, ic, TRUE);
8813 /*-----------------------------------------------------------------*/
8814 /* genRightShift - generate code for right shifting */
8815 /*-----------------------------------------------------------------*/
8817 genRightShift (iCode * ic)
8819 operand *right, *left, *result;
8823 symbol *tlbl, *tlbl1;
8826 D(emitcode ("; genRightShift",""));
8828 /* if signed then we do it the hard way preserve the
8829 sign bit moving it inwards */
8830 letype = getSpec (operandType (IC_LEFT (ic)));
8832 if (!SPEC_USIGN (letype))
8834 genSignedRightShift (ic);
8838 /* signed & unsigned types are treated the same : i.e. the
8839 signed is NOT propagated inwards : quoting from the
8840 ANSI - standard : "for E1 >> E2, is equivalent to division
8841 by 2**E2 if unsigned or if it has a non-negative value,
8842 otherwise the result is implementation defined ", MY definition
8843 is that the sign does not get propagated */
8845 right = IC_RIGHT (ic);
8846 left = IC_LEFT (ic);
8847 result = IC_RESULT (ic);
8849 aopOp (right, ic, FALSE);
8851 /* if the shift count is known then do it
8852 as efficiently as possible */
8853 if (AOP_TYPE (right) == AOP_LIT)
8855 genRightShiftLiteral (left, right, result, ic, 0);
8859 /* shift count is unknown then we have to form
8860 a loop get the loop count in B : Note: we take
8861 only the lower order byte since shifting
8862 more that 32 bits make no sense anyway, ( the
8863 largest size of an object can be only 32 bits ) */
8866 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
8867 emitcode ("inc", "b");
8868 freeAsmop (right, NULL, ic, TRUE);
8869 aopOp (left, ic, FALSE);
8870 aopOp (result, ic, FALSE);
8872 /* now move the left to the result if they are not the
8874 if (!sameRegs (AOP (left), AOP (result)) &&
8875 AOP_SIZE (result) > 1)
8878 size = AOP_SIZE (result);
8882 l = aopGet (left, offset, FALSE, TRUE);
8883 if (*l == '@' && IS_AOP_PREG (result))
8886 emitcode ("mov", "a,%s", l);
8887 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
8890 aopPut (result, l, offset, isOperandVolatile (result, FALSE));
8895 tlbl = newiTempLabel (NULL);
8896 tlbl1 = newiTempLabel (NULL);
8897 size = AOP_SIZE (result);
8900 /* if it is only one byte then */
8903 l = aopGet (left, 0, FALSE, FALSE);
8905 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8906 emitcode ("", "%05d$:", tlbl->key + 100);
8908 emitcode ("rrc", "a");
8909 emitcode ("", "%05d$:", tlbl1->key + 100);
8910 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8912 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
8916 reAdjustPreg (AOP (result));
8917 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8918 emitcode ("", "%05d$:", tlbl->key + 100);
8922 l = aopGet (result, offset, FALSE, FALSE);
8924 emitcode ("rrc", "a");
8925 aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
8927 reAdjustPreg (AOP (result));
8929 emitcode ("", "%05d$:", tlbl1->key + 100);
8930 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8934 freeAsmop (left, NULL, ic, TRUE);
8935 freeAsmop (result, NULL, ic, TRUE);
8938 /*-----------------------------------------------------------------*/
8939 /* emitPtrByteGet - emits code to get a byte into A through a */
8940 /* pointer register (R0, R1, or DPTR). The */
8941 /* original value of A can be preserved in B. */
8942 /*-----------------------------------------------------------------*/
8944 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
8951 emitcode ("mov", "b,a");
8952 emitcode ("mov", "a,@%s", rname);
8957 emitcode ("mov", "b,a");
8958 emitcode ("movx", "a,@%s", rname);
8963 emitcode ("mov", "b,a");
8964 emitcode ("movx", "a,@dptr");
8969 emitcode ("mov", "b,a");
8970 emitcode ("clr", "a");
8971 emitcode ("movc", "a,@a+dptr");
8977 emitcode ("push", "b");
8978 emitcode ("push", "acc");
8980 emitcode ("lcall", "__gptrget");
8982 emitcode ("pop", "b");
8987 /*-----------------------------------------------------------------*/
8988 /* emitPtrByteSet - emits code to set a byte from src through a */
8989 /* pointer register (R0, R1, or DPTR). */
8990 /*-----------------------------------------------------------------*/
8992 emitPtrByteSet (char *rname, int p_type, char *src)
9001 emitcode ("mov", "@%s,a", rname);
9004 emitcode ("mov", "@%s,%s", rname, src);
9009 emitcode ("movx", "@%s,a", rname);
9014 emitcode ("movx", "@dptr,a");
9019 emitcode ("lcall", "__gptrput");
9024 /*-----------------------------------------------------------------*/
9025 /* genUnpackBits - generates code for unpacking bits */
9026 /*-----------------------------------------------------------------*/
9028 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9030 int offset = 0; /* result byte offset */
9031 int rsize; /* result size */
9032 int rlen = 0; /* remaining bitfield length */
9033 sym_link *etype; /* bitfield type information */
9034 int blen; /* bitfield length */
9035 int bstr; /* bitfield starting bit within byte */
9038 D(emitcode ("; genUnpackBits",""));
9040 etype = getSpec (operandType (result));
9041 rsize = getSize (operandType (result));
9042 blen = SPEC_BLEN (etype);
9043 bstr = SPEC_BSTR (etype);
9045 if (ifx && blen <= 8)
9047 emitPtrByteGet (rname, ptype, FALSE);
9050 SNPRINTF (buffer, sizeof(buffer),
9052 genIfxJump (ifx, buffer, NULL, NULL, NULL);
9057 emitcode ("anl", "a,#0x%02x",
9058 (((unsigned char) -1) >> (8 - blen)) << bstr);
9059 genIfxJump (ifx, "a", NULL, NULL, NULL);
9065 /* If the bitfield length is less than a byte */
9068 emitPtrByteGet (rname, ptype, FALSE);
9070 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9071 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9075 /* Bit field did not fit in a byte. Copy all
9076 but the partial byte at the end. */
9077 for (rlen=blen;rlen>=8;rlen-=8)
9079 emitPtrByteGet (rname, ptype, FALSE);
9080 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9082 emitcode ("inc", "%s", rname);
9085 /* Handle the partial byte at the end */
9088 emitPtrByteGet (rname, ptype, FALSE);
9089 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9090 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9098 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
9103 /*-----------------------------------------------------------------*/
9104 /* genDataPointerGet - generates code when ptr offset is known */
9105 /*-----------------------------------------------------------------*/
9107 genDataPointerGet (operand * left,
9113 int size, offset = 0;
9115 D(emitcode ("; genDataPointerGet",""));
9117 aopOp (result, ic, TRUE);
9119 /* get the string representation of the name */
9120 l = aopGet (left, 0, FALSE, TRUE);
9121 size = AOP_SIZE (result);
9125 sprintf (buffer, "(%s + %d)", l + 1, offset);
9127 sprintf (buffer, "%s", l + 1);
9128 aopPut (result, buffer, offset++, isOperandVolatile (result, FALSE));
9131 freeAsmop (left, NULL, ic, TRUE);
9132 freeAsmop (result, NULL, ic, TRUE);
9135 /*-----------------------------------------------------------------*/
9136 /* genNearPointerGet - emitcode for near pointer fetch */
9137 /*-----------------------------------------------------------------*/
9139 genNearPointerGet (operand * left,
9148 sym_link *rtype, *retype;
9149 sym_link *ltype = operandType (left);
9152 D(emitcode ("; genNearPointerGet",""));
9154 rtype = operandType (result);
9155 retype = getSpec (rtype);
9157 aopOp (left, ic, FALSE);
9159 /* if left is rematerialisable and
9160 result is not bitfield variable type and
9161 the left is pointer to data space i.e
9162 lower 128 bytes of space */
9163 if (AOP_TYPE (left) == AOP_IMMD &&
9164 !IS_BITFIELD (retype) &&
9165 DCL_TYPE (ltype) == POINTER)
9167 genDataPointerGet (left, result, ic);
9171 /* if the value is already in a pointer register
9172 then don't need anything more */
9173 if (!AOP_INPREG (AOP (left)))
9175 if (IS_AOP_PREG (left))
9177 // Aha, it is a pointer, just in disguise.
9178 rname = aopGet (left, 0, FALSE, FALSE);
9181 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9182 __FILE__, __LINE__);
9187 emitcode ("mov", "a%s,%s", rname + 1, rname);
9188 rname++; // skip the '@'.
9193 /* otherwise get a free pointer register */
9195 preg = getFreePtr (ic, &aop, FALSE);
9196 emitcode ("mov", "%s,%s",
9198 aopGet (left, 0, FALSE, TRUE));
9203 rname = aopGet (left, 0, FALSE, FALSE);
9205 //aopOp (result, ic, FALSE);
9206 aopOp (result, ic, result?TRUE:FALSE);
9208 /* if bitfield then unpack the bits */
9209 if (IS_BITFIELD (retype))
9210 genUnpackBits (result, rname, POINTER, ifx);
9213 /* we have can just get the values */
9214 int size = AOP_SIZE (result);
9219 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9222 emitcode ("mov", "a,@%s", rname);
9224 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9228 sprintf (buffer, "@%s", rname);
9229 aopPut (result, buffer, offset, isOperandVolatile (result, FALSE));
9233 emitcode ("inc", "%s", rname);
9237 /* now some housekeeping stuff */
9238 if (aop) /* we had to allocate for this iCode */
9240 if (pi) { /* post increment present */
9241 aopPut (left, rname, 0, isOperandVolatile (left, FALSE));
9243 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9247 /* we did not allocate which means left
9248 already in a pointer register, then
9249 if size > 0 && this could be used again
9250 we have to point it back to where it
9252 if ((AOP_SIZE (result) > 1 &&
9253 !OP_SYMBOL (left)->remat &&
9254 (OP_SYMBOL (left)->liveTo > ic->seq ||
9258 int size = AOP_SIZE (result) - 1;
9260 emitcode ("dec", "%s", rname);
9264 if (ifx && !ifx->generated)
9266 genIfxJump (ifx, "a", left, NULL, result);
9270 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9271 freeAsmop (left, NULL, ic, TRUE);
9272 if (pi) pi->generated = 1;
9275 /*-----------------------------------------------------------------*/
9276 /* genPagedPointerGet - emitcode for paged pointer fetch */
9277 /*-----------------------------------------------------------------*/
9279 genPagedPointerGet (operand * left,
9288 sym_link *rtype, *retype;
9290 D(emitcode ("; genPagedPointerGet",""));
9292 rtype = operandType (result);
9293 retype = getSpec (rtype);
9295 aopOp (left, ic, FALSE);
9297 /* if the value is already in a pointer register
9298 then don't need anything more */
9299 if (!AOP_INPREG (AOP (left)))
9301 /* otherwise get a free pointer register */
9303 preg = getFreePtr (ic, &aop, FALSE);
9304 emitcode ("mov", "%s,%s",
9306 aopGet (left, 0, FALSE, TRUE));
9310 rname = aopGet (left, 0, FALSE, FALSE);
9312 aopOp (result, ic, FALSE);
9314 /* if bitfield then unpack the bits */
9315 if (IS_BITFIELD (retype))
9316 genUnpackBits (result, rname, PPOINTER, ifx);
9319 /* we have can just get the values */
9320 int size = AOP_SIZE (result);
9326 emitcode ("movx", "a,@%s", rname);
9328 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9333 emitcode ("inc", "%s", rname);
9337 /* now some housekeeping stuff */
9338 if (aop) /* we had to allocate for this iCode */
9340 if (pi) aopPut (left, rname, 0, isOperandVolatile (left, FALSE));
9341 freeAsmop (NULL, aop, ic, TRUE);
9345 /* we did not allocate which means left
9346 already in a pointer register, then
9347 if size > 0 && this could be used again
9348 we have to point it back to where it
9350 if ((AOP_SIZE (result) > 1 &&
9351 !OP_SYMBOL (left)->remat &&
9352 (OP_SYMBOL (left)->liveTo > ic->seq ||
9356 int size = AOP_SIZE (result) - 1;
9358 emitcode ("dec", "%s", rname);
9362 if (ifx && !ifx->generated)
9364 genIfxJump (ifx, "a", left, NULL, result);
9368 freeAsmop (left, NULL, ic, TRUE);
9369 freeAsmop (result, NULL, ic, TRUE);
9370 if (pi) pi->generated = 1;
9374 /*--------------------------------------------------------------------*/
9375 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
9376 /*--------------------------------------------------------------------*/
9378 loadDptrFromOperand (operand *op, bool loadBToo)
9380 if (AOP_TYPE (op) != AOP_STR)
9382 /* if this is rematerializable */
9383 if (AOP_TYPE (op) == AOP_IMMD)
9385 emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
9388 if (AOP(op)->aopu.aop_immd.from_cast_remat)
9389 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
9392 wassertl(FALSE, "need pointerCode");
9393 emitcode ("", "; mov b,???");
9394 /* genPointerGet and genPointerSet originally did different
9395 ** things for this case. Both seem wrong.
9396 ** from genPointerGet:
9397 ** emitcode ("mov", "b,#%d", pointerCode (retype));
9398 ** from genPointerSet:
9399 ** emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
9404 else if (AOP_TYPE (op) == AOP_DPTR)
9408 MOVA (aopGet (op, 0, FALSE, FALSE));
9409 emitcode ("push", "acc");
9410 MOVA (aopGet (op, 1, FALSE, FALSE));
9411 emitcode ("push", "acc");
9412 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9413 emitcode ("pop", "dph");
9414 emitcode ("pop", "dpl");
9418 MOVA (aopGet (op, 0, FALSE, FALSE));
9419 emitcode ("push", "acc");
9420 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9421 emitcode ("pop", "dpl");
9425 { /* we need to get it byte by byte */
9426 emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
9427 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9429 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9434 /*-----------------------------------------------------------------*/
9435 /* genFarPointerGet - gget value from far space */
9436 /*-----------------------------------------------------------------*/
9438 genFarPointerGet (operand * left,
9439 operand * result, iCode * ic, iCode * pi, iCode * ifx)
9442 sym_link *retype = getSpec (operandType (result));
9444 D(emitcode ("; genFarPointerGet",""));
9446 aopOp (left, ic, FALSE);
9447 loadDptrFromOperand (left, FALSE);
9449 /* so dptr now contains the address */
9450 aopOp (result, ic, FALSE);
9452 /* if bit then unpack */
9453 if (IS_BITFIELD (retype))
9454 genUnpackBits (result, "dptr", FPOINTER, ifx);
9457 size = AOP_SIZE (result);
9462 emitcode ("movx", "a,@dptr");
9464 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9466 emitcode ("inc", "dptr");
9470 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9472 aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9473 aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9477 if (ifx && !ifx->generated)
9479 genIfxJump (ifx, "a", left, NULL, result);
9482 freeAsmop (left, NULL, ic, TRUE);
9483 freeAsmop (result, NULL, ic, TRUE);
9486 /*-----------------------------------------------------------------*/
9487 /* genCodePointerGet - gget value from code space */
9488 /*-----------------------------------------------------------------*/
9490 genCodePointerGet (operand * left,
9491 operand * result, iCode * ic, iCode *pi, iCode *ifx)
9494 sym_link *retype = getSpec (operandType (result));
9496 D(emitcode ("; genCodePointerGet",""));
9498 aopOp (left, ic, FALSE);
9499 loadDptrFromOperand (left, FALSE);
9501 /* so dptr now contains the address */
9502 aopOp (result, ic, FALSE);
9504 /* if bit then unpack */
9505 if (IS_BITFIELD (retype))
9506 genUnpackBits (result, "dptr", CPOINTER, ifx);
9509 size = AOP_SIZE (result);
9516 emitcode ("clr", "a");
9517 emitcode ("movc", "a,@a+dptr");
9519 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9520 emitcode ("inc", "dptr");
9524 emitcode ("mov", "a,#0x%02x", offset);
9525 emitcode ("movc", "a,@a+dptr");
9527 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9532 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9534 aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9535 aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9539 if (ifx && !ifx->generated)
9541 genIfxJump (ifx, "a", left, NULL, result);
9544 freeAsmop (left, NULL, ic, TRUE);
9545 freeAsmop (result, NULL, ic, TRUE);
9548 /*-----------------------------------------------------------------*/
9549 /* genGenPointerGet - gget value from generic pointer space */
9550 /*-----------------------------------------------------------------*/
9552 genGenPointerGet (operand * left,
9553 operand * result, iCode * ic, iCode *pi, iCode *ifx)
9556 sym_link *retype = getSpec (operandType (result));
9558 D(emitcode ("; genGenPointerGet",""));
9560 aopOp (left, ic, FALSE);
9561 loadDptrFromOperand (left, TRUE);
9563 /* so dptr know contains the address */
9564 aopOp (result, ic, FALSE);
9566 /* if bit then unpack */
9567 if (IS_BITFIELD (retype))
9568 genUnpackBits (result, "dptr", GPOINTER, ifx);
9571 size = AOP_SIZE (result);
9576 emitcode ("lcall", "__gptrget");
9578 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9580 emitcode ("inc", "dptr");
9584 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9586 aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9587 aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9591 if (ifx && !ifx->generated)
9593 genIfxJump (ifx, "a", left, NULL, result);
9597 freeAsmop (left, NULL, ic, TRUE);
9598 freeAsmop (result, NULL, ic, TRUE);
9601 /*-----------------------------------------------------------------*/
9602 /* genPointerGet - generate code for pointer get */
9603 /*-----------------------------------------------------------------*/
9605 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
9607 operand *left, *result;
9608 sym_link *type, *etype;
9611 D(emitcode ("; genPointerGet",""));
9613 left = IC_LEFT (ic);
9614 result = IC_RESULT (ic);
9616 if (getSize (operandType (result))>1)
9619 /* depending on the type of pointer we need to
9620 move it to the correct pointer register */
9621 type = operandType (left);
9622 etype = getSpec (type);
9623 /* if left is of type of pointer then it is simple */
9624 if (IS_PTR (type) && !IS_FUNC (type->next))
9625 p_type = DCL_TYPE (type);
9628 /* we have to go by the storage class */
9629 p_type = PTR_TYPE (SPEC_OCLS (etype));
9632 /* special case when cast remat */
9633 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9634 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9635 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9636 type = operandType (left);
9637 p_type = DCL_TYPE (type);
9639 /* now that we have the pointer type we assign
9640 the pointer values */
9646 genNearPointerGet (left, result, ic, pi, ifx);
9650 genPagedPointerGet (left, result, ic, pi, ifx);
9654 genFarPointerGet (left, result, ic, pi, ifx);
9658 genCodePointerGet (left, result, ic, pi, ifx);
9662 genGenPointerGet (left, result, ic, pi, ifx);
9670 /*-----------------------------------------------------------------*/
9671 /* genPackBits - generates code for packed bit storage */
9672 /*-----------------------------------------------------------------*/
9674 genPackBits (sym_link * etype,
9676 char *rname, int p_type)
9678 int offset = 0; /* source byte offset */
9679 int rlen = 0; /* remaining bitfield length */
9680 int blen; /* bitfield length */
9681 int bstr; /* bitfield starting bit within byte */
9682 int litval; /* source literal value (if AOP_LIT) */
9683 unsigned char mask; /* bitmask within current byte */
9685 D(emitcode ("; genPackBits",""));
9687 blen = SPEC_BLEN (etype);
9688 bstr = SPEC_BSTR (etype);
9690 /* If the bitfield length is less than a byte */
9693 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9694 (unsigned char) (0xFF >> (8 - bstr)));
9696 if (AOP_TYPE (right) == AOP_LIT)
9698 /* Case with a bitfield length <8 and literal source
9700 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9702 litval &= (~mask) & 0xff;
9703 emitPtrByteGet (rname, p_type, FALSE);
9704 if ((mask|litval)!=0xff)
9705 emitcode ("anl","a,#0x%02x", mask);
9707 emitcode ("orl","a,#0x%02x", litval);
9711 if ((blen==1) && (p_type!=GPOINTER))
9713 /* Case with a bitfield length == 1 and no generic pointer
9715 if (AOP_TYPE (right) == AOP_CRY)
9716 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9719 MOVA (aopGet (right, 0, FALSE, FALSE));
9720 emitcode ("rrc","a");
9722 emitPtrByteGet (rname, p_type, FALSE);
9723 emitcode ("mov","acc.%d,c",bstr);
9728 /* Case with a bitfield length < 8 and arbitrary source
9730 MOVA (aopGet (right, 0, FALSE, FALSE));
9731 /* shift and mask source value */
9733 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9736 /* transfer A to B and get next byte */
9737 emitPtrByteGet (rname, p_type, TRUE);
9739 emitcode ("anl", "a,#0x%02x", mask);
9740 emitcode ("orl", "a,b");
9741 if (p_type == GPOINTER)
9742 emitcode ("pop", "b");
9748 emitPtrByteSet (rname, p_type, "a");
9752 /* Bit length is greater than 7 bits. In this case, copy */
9753 /* all except the partial byte at the end */
9754 for (rlen=blen;rlen>=8;rlen-=8)
9756 emitPtrByteSet (rname, p_type,
9757 aopGet (right, offset++, FALSE, TRUE) );
9759 emitcode ("inc", "%s", rname);
9762 /* If there was a partial byte at the end */
9765 mask = (((unsigned char) -1 << rlen) & 0xff);
9767 if (AOP_TYPE (right) == AOP_LIT)
9769 /* Case with partial byte and literal source
9771 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9772 litval >>= (blen-rlen);
9773 litval &= (~mask) & 0xff;
9774 emitPtrByteGet (rname, p_type, FALSE);
9775 if ((mask|litval)!=0xff)
9776 emitcode ("anl","a,#0x%02x", mask);
9778 emitcode ("orl","a,#0x%02x", litval);
9783 /* Case with partial byte and arbitrary source
9785 MOVA (aopGet (right, offset++, FALSE, FALSE));
9786 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9789 /* transfer A to B and get next byte */
9790 emitPtrByteGet (rname, p_type, TRUE);
9792 emitcode ("anl", "a,#0x%02x", mask);
9793 emitcode ("orl", "a,b");
9794 if (p_type == GPOINTER)
9795 emitcode ("pop", "b");
9799 emitPtrByteSet (rname, p_type, "a");
9805 /*-----------------------------------------------------------------*/
9806 /* genDataPointerSet - remat pointer to data space */
9807 /*-----------------------------------------------------------------*/
9809 genDataPointerSet (operand * right,
9813 int size, offset = 0;
9814 char *l, buffer[256];
9816 D(emitcode ("; genDataPointerSet",""));
9818 aopOp (right, ic, FALSE);
9820 l = aopGet (result, 0, FALSE, TRUE);
9821 size = AOP_SIZE (right);
9825 sprintf (buffer, "(%s + %d)", l + 1, offset);
9827 sprintf (buffer, "%s", l + 1);
9828 emitcode ("mov", "%s,%s", buffer,
9829 aopGet (right, offset++, FALSE, FALSE));
9832 freeAsmop (right, NULL, ic, TRUE);
9833 freeAsmop (result, NULL, ic, TRUE);
9836 /*-----------------------------------------------------------------*/
9837 /* genNearPointerSet - emitcode for near pointer put */
9838 /*-----------------------------------------------------------------*/
9840 genNearPointerSet (operand * right,
9848 sym_link *retype, *letype;
9849 sym_link *ptype = operandType (result);
9851 D(emitcode ("; genNearPointerSet",""));
9853 retype = getSpec (operandType (right));
9854 letype = getSpec (ptype);
9855 aopOp (result, ic, FALSE);
9857 /* if the result is rematerializable &
9858 in data space & not a bit variable */
9859 if (AOP_TYPE (result) == AOP_IMMD &&
9860 DCL_TYPE (ptype) == POINTER &&
9861 !IS_BITVAR (retype) &&
9862 !IS_BITVAR (letype))
9864 genDataPointerSet (right, result, ic);
9868 /* if the value is already in a pointer register
9869 then don't need anything more */
9870 if (!AOP_INPREG (AOP (result)))
9873 //AOP_TYPE (result) == AOP_STK
9877 // Aha, it is a pointer, just in disguise.
9878 rname = aopGet (result, 0, FALSE, FALSE);
9881 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9882 __FILE__, __LINE__);
9887 emitcode ("mov", "a%s,%s", rname + 1, rname);
9888 rname++; // skip the '@'.
9893 /* otherwise get a free pointer register */
9895 preg = getFreePtr (ic, &aop, FALSE);
9896 emitcode ("mov", "%s,%s",
9898 aopGet (result, 0, FALSE, TRUE));
9904 rname = aopGet (result, 0, FALSE, FALSE);
9907 aopOp (right, ic, FALSE);
9909 /* if bitfield then unpack the bits */
9910 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9911 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
9914 /* we have can just get the values */
9915 int size = AOP_SIZE (right);
9920 l = aopGet (right, offset, FALSE, TRUE);
9924 emitcode ("mov", "@%s,a", rname);
9927 emitcode ("mov", "@%s,%s", rname, l);
9929 emitcode ("inc", "%s", rname);
9934 /* now some housekeeping stuff */
9935 if (aop) /* we had to allocate for this iCode */
9938 aopPut (result, rname, 0, isOperandVolatile (result, FALSE));
9939 freeAsmop (NULL, aop, ic, TRUE);
9943 /* we did not allocate which means left
9944 already in a pointer register, then
9945 if size > 0 && this could be used again
9946 we have to point it back to where it
9948 if ((AOP_SIZE (right) > 1 &&
9949 !OP_SYMBOL (result)->remat &&
9950 (OP_SYMBOL (result)->liveTo > ic->seq ||
9954 int size = AOP_SIZE (right) - 1;
9956 emitcode ("dec", "%s", rname);
9961 if (pi) pi->generated = 1;
9962 freeAsmop (result, NULL, ic, TRUE);
9963 freeAsmop (right, NULL, ic, TRUE);
9966 /*-----------------------------------------------------------------*/
9967 /* genPagedPointerSet - emitcode for Paged pointer put */
9968 /*-----------------------------------------------------------------*/
9970 genPagedPointerSet (operand * right,
9978 sym_link *retype, *letype;
9980 D(emitcode ("; genPagedPointerSet",""));
9982 retype = getSpec (operandType (right));
9983 letype = getSpec (operandType (result));
9985 aopOp (result, ic, FALSE);
9987 /* if the value is already in a pointer register
9988 then don't need anything more */
9989 if (!AOP_INPREG (AOP (result)))
9991 /* otherwise get a free pointer register */
9993 preg = getFreePtr (ic, &aop, FALSE);
9994 emitcode ("mov", "%s,%s",
9996 aopGet (result, 0, FALSE, TRUE));
10000 rname = aopGet (result, 0, FALSE, FALSE);
10002 aopOp (right, ic, FALSE);
10004 /* if bitfield then unpack the bits */
10005 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10006 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10009 /* we have can just get the values */
10010 int size = AOP_SIZE (right);
10015 l = aopGet (right, offset, FALSE, TRUE);
10018 emitcode ("movx", "@%s,a", rname);
10021 emitcode ("inc", "%s", rname);
10027 /* now some housekeeping stuff */
10028 if (aop) /* we had to allocate for this iCode */
10031 aopPut (result, rname, 0, isOperandVolatile (result, FALSE));
10032 freeAsmop (NULL, aop, ic, TRUE);
10036 /* we did not allocate which means left
10037 already in a pointer register, then
10038 if size > 0 && this could be used again
10039 we have to point it back to where it
10041 if (AOP_SIZE (right) > 1 &&
10042 !OP_SYMBOL (result)->remat &&
10043 (OP_SYMBOL (result)->liveTo > ic->seq ||
10046 int size = AOP_SIZE (right) - 1;
10048 emitcode ("dec", "%s", rname);
10053 if (pi) pi->generated = 1;
10054 freeAsmop (result, NULL, ic, TRUE);
10055 freeAsmop (right, NULL, ic, TRUE);
10060 /*-----------------------------------------------------------------*/
10061 /* genFarPointerSet - set value from far space */
10062 /*-----------------------------------------------------------------*/
10064 genFarPointerSet (operand * right,
10065 operand * result, iCode * ic, iCode * pi)
10068 sym_link *retype = getSpec (operandType (right));
10069 sym_link *letype = getSpec (operandType (result));
10071 D(emitcode ("; genFarPointerSet",""));
10073 aopOp (result, ic, FALSE);
10074 loadDptrFromOperand (result, FALSE);
10076 /* so dptr know contains the address */
10077 aopOp (right, ic, FALSE);
10079 /* if bit then unpack */
10080 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10081 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10084 size = AOP_SIZE (right);
10089 char *l = aopGet (right, offset++, FALSE, FALSE);
10091 emitcode ("movx", "@dptr,a");
10093 emitcode ("inc", "dptr");
10096 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10097 aopPut (result, "dpl", 0, isOperandVolatile (result, FALSE));
10098 aopPut (result, "dph", 1, isOperandVolatile (result, FALSE));
10101 freeAsmop (result, NULL, ic, TRUE);
10102 freeAsmop (right, NULL, ic, TRUE);
10105 /*-----------------------------------------------------------------*/
10106 /* genGenPointerSet - set value from generic pointer space */
10107 /*-----------------------------------------------------------------*/
10109 genGenPointerSet (operand * right,
10110 operand * result, iCode * ic, iCode * pi)
10113 sym_link *retype = getSpec (operandType (right));
10114 sym_link *letype = getSpec (operandType (result));
10116 D(emitcode ("; genGenPointerSet",""));
10118 aopOp (result, ic, FALSE);
10119 loadDptrFromOperand (result, TRUE);
10121 /* so dptr know contains the address */
10122 aopOp (right, ic, FALSE);
10124 /* if bit then unpack */
10125 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10126 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10129 size = AOP_SIZE (right);
10134 char *l = aopGet (right, offset++, FALSE, FALSE);
10136 emitcode ("lcall", "__gptrput");
10138 emitcode ("inc", "dptr");
10142 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10143 aopPut (result, "dpl", 0, isOperandVolatile (result, FALSE));
10144 aopPut (result, "dph", 1, isOperandVolatile (result, FALSE));
10147 freeAsmop (result, NULL, ic, TRUE);
10148 freeAsmop (right, NULL, ic, TRUE);
10151 /*-----------------------------------------------------------------*/
10152 /* genPointerSet - stores the value into a pointer location */
10153 /*-----------------------------------------------------------------*/
10155 genPointerSet (iCode * ic, iCode *pi)
10157 operand *right, *result;
10158 sym_link *type, *etype;
10161 D(emitcode ("; genPointerSet",""));
10163 right = IC_RIGHT (ic);
10164 result = IC_RESULT (ic);
10166 /* depending on the type of pointer we need to
10167 move it to the correct pointer register */
10168 type = operandType (result);
10169 etype = getSpec (type);
10170 /* if left is of type of pointer then it is simple */
10171 if (IS_PTR (type) && !IS_FUNC (type->next))
10173 p_type = DCL_TYPE (type);
10177 /* we have to go by the storage class */
10178 p_type = PTR_TYPE (SPEC_OCLS (etype));
10181 /* special case when cast remat */
10182 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10183 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10184 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10185 type = operandType (result);
10186 p_type = DCL_TYPE (type);
10188 /* now that we have the pointer type we assign
10189 the pointer values */
10195 genNearPointerSet (right, result, ic, pi);
10199 genPagedPointerSet (right, result, ic, pi);
10203 genFarPointerSet (right, result, ic, pi);
10207 genGenPointerSet (right, result, ic, pi);
10211 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10212 "genPointerSet: illegal pointer type");
10217 /*-----------------------------------------------------------------*/
10218 /* genIfx - generate code for Ifx statement */
10219 /*-----------------------------------------------------------------*/
10221 genIfx (iCode * ic, iCode * popIc)
10223 operand *cond = IC_COND (ic);
10227 D(emitcode ("; genIfx",""));
10229 aopOp (cond, ic, FALSE);
10231 /* get the value into acc */
10232 if (AOP_TYPE (cond) != AOP_CRY)
10237 if (AOP(cond)->aopu.aop_dir)
10238 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10240 /* the result is now in the accumulator or a directly addressable bit */
10241 freeAsmop (cond, NULL, ic, TRUE);
10243 /* if there was something to be popped then do it */
10247 /* if the condition is a bit variable */
10249 genIfxJump(ic, dup, NULL, NULL, NULL);
10250 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10251 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10252 else if (isbit && !IS_ITEMP (cond))
10253 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10255 genIfxJump (ic, "a", NULL, NULL, NULL);
10260 /*-----------------------------------------------------------------*/
10261 /* genAddrOf - generates code for address of */
10262 /*-----------------------------------------------------------------*/
10264 genAddrOf (iCode * ic)
10266 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10269 D(emitcode ("; genAddrOf",""));
10271 aopOp (IC_RESULT (ic), ic, FALSE);
10273 /* if the operand is on the stack then we
10274 need to get the stack offset of this
10278 /* if it has an offset then we need to compute
10282 emitcode ("mov", "a,%s", SYM_BP (sym));
10283 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
10284 ((char) (sym->stack - _G.nRegsSaved)) :
10285 ((char) sym->stack)) & 0xff);
10286 aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10290 /* we can just move _bp */
10291 aopPut (IC_RESULT (ic), SYM_BP (sym), 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10293 /* fill the result with zero */
10294 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10299 aopPut (IC_RESULT (ic), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10305 /* object not on stack then we need the name */
10306 size = AOP_SIZE (IC_RESULT (ic));
10311 char s[SDCC_NAME_MAX];
10313 sprintf (s, "#(%s >> %d)",
10317 sprintf (s, "#%s", sym->rname);
10318 aopPut (IC_RESULT (ic), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10322 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10326 /*-----------------------------------------------------------------*/
10327 /* genFarFarAssign - assignment when both are in far space */
10328 /*-----------------------------------------------------------------*/
10330 genFarFarAssign (operand * result, operand * right, iCode * ic)
10332 int size = AOP_SIZE (right);
10336 D(emitcode ("; genFarFarAssign",""));
10338 /* first push the right side on to the stack */
10341 l = aopGet (right, offset++, FALSE, FALSE);
10343 emitcode ("push", "acc");
10346 freeAsmop (right, NULL, ic, FALSE);
10347 /* now assign DPTR to result */
10348 aopOp (result, ic, FALSE);
10349 size = AOP_SIZE (result);
10352 emitcode ("pop", "acc");
10353 aopPut (result, "a", --offset, isOperandVolatile (result, FALSE));
10355 freeAsmop (result, NULL, ic, FALSE);
10359 /*-----------------------------------------------------------------*/
10360 /* genAssign - generate code for assignment */
10361 /*-----------------------------------------------------------------*/
10363 genAssign (iCode * ic)
10365 operand *result, *right;
10367 unsigned long lit = 0L;
10369 D(emitcode("; genAssign",""));
10371 result = IC_RESULT (ic);
10372 right = IC_RIGHT (ic);
10374 /* if they are the same */
10375 if (operandsEqu (result, right) &&
10376 !isOperandVolatile (result, FALSE) &&
10377 !isOperandVolatile (right, FALSE))
10380 aopOp (right, ic, FALSE);
10382 /* special case both in far space */
10383 if (AOP_TYPE (right) == AOP_DPTR &&
10384 IS_TRUE_SYMOP (result) &&
10385 isOperandInFarSpace (result))
10388 genFarFarAssign (result, right, ic);
10392 aopOp (result, ic, TRUE);
10394 /* if they are the same registers */
10395 if (sameRegs (AOP (right), AOP (result)) &&
10396 !isOperandVolatile (result, FALSE) &&
10397 !isOperandVolatile (right, FALSE))
10400 /* if the result is a bit */
10401 if (AOP_TYPE (result) == AOP_CRY)
10404 /* if the right size is a literal then
10405 we know what the value is */
10406 if (AOP_TYPE (right) == AOP_LIT)
10408 if (((int) operandLitValue (right)))
10409 aopPut (result, one, 0, isOperandVolatile (result, FALSE));
10411 aopPut (result, zero, 0, isOperandVolatile (result, FALSE));
10415 /* the right is also a bit variable */
10416 if (AOP_TYPE (right) == AOP_CRY)
10418 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10419 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
10423 /* we need to or */
10425 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
10429 /* bit variables done */
10431 size = AOP_SIZE (result);
10433 if (AOP_TYPE (right) == AOP_LIT)
10434 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10436 (AOP_TYPE (result) != AOP_REG) &&
10437 (AOP_TYPE (right) == AOP_LIT) &&
10438 !IS_FLOAT (operandType (right)) &&
10441 while ((size) && (lit))
10444 aopGet (right, offset, FALSE, FALSE),
10446 isOperandVolatile (result, FALSE));
10451 emitcode ("clr", "a");
10454 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
10463 aopGet (right, offset, FALSE, FALSE),
10465 isOperandVolatile (result, FALSE));
10471 freeAsmop (right, NULL, ic, TRUE);
10472 freeAsmop (result, NULL, ic, TRUE);
10475 /*-----------------------------------------------------------------*/
10476 /* genJumpTab - generates code for jump table */
10477 /*-----------------------------------------------------------------*/
10479 genJumpTab (iCode * ic)
10481 symbol *jtab,*jtablo,*jtabhi;
10483 unsigned int count;
10485 D(emitcode ("; genJumpTab",""));
10487 count = elementsInSet( IC_JTLABELS (ic) );
10491 /* this algorithm needs 9 cycles and 7 + 3*n bytes
10492 if the switch argument is in a register.
10493 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
10494 /* (MB) What if peephole converts ljmp to sjmp or ret ???
10495 How will multiply by three be updated ???*/
10496 aopOp (IC_JTCOND (ic), ic, FALSE);
10497 /* get the condition into accumulator */
10498 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10500 /* multiply by three */
10501 emitcode ("add", "a,acc");
10502 emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
10503 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10505 jtab = newiTempLabel (NULL);
10506 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
10507 emitcode ("jmp", "@a+dptr");
10508 emitcode ("", "%05d$:", jtab->key + 100);
10509 /* now generate the jump labels */
10510 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10511 jtab = setNextItem (IC_JTLABELS (ic)))
10512 emitcode ("ljmp", "%05d$", jtab->key + 100);
10516 /* this algorithm needs 14 cycles and 13 + 2*n bytes
10517 if the switch argument is in a register.
10518 For n>6 this algorithm may be more compact */
10519 jtablo = newiTempLabel (NULL);
10520 jtabhi = newiTempLabel (NULL);
10522 /* get the condition into accumulator.
10523 Using b as temporary storage, if register push/pop is needed */
10524 aopOp (IC_JTCOND (ic), ic, FALSE);
10525 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10526 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
10527 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
10529 // (MB) what if B is in use???
10530 wassertl(!BINUSE, "B was in use");
10531 emitcode ("mov", "b,%s", l);
10534 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10538 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
10539 emitcode ("movc", "a,@a+pc");
10540 emitcode ("push", "acc");
10543 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
10544 emitcode ("movc", "a,@a+pc");
10545 emitcode ("push", "acc");
10549 /* this scales up to n<=255, but needs two more bytes
10550 and changes dptr */
10551 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
10552 emitcode ("movc", "a,@a+dptr");
10553 emitcode ("push", "acc");
10556 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
10557 emitcode ("movc", "a,@a+dptr");
10558 emitcode ("push", "acc");
10561 emitcode ("ret", "");
10563 /* now generate jump table, LSB */
10564 emitcode ("", "%05d$:", jtablo->key + 100);
10565 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10566 jtab = setNextItem (IC_JTLABELS (ic)))
10567 emitcode (".db", "%05d$", jtab->key + 100);
10569 /* now generate jump table, MSB */
10570 emitcode ("", "%05d$:", jtabhi->key + 100);
10571 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10572 jtab = setNextItem (IC_JTLABELS (ic)))
10573 emitcode (".db", "%05d$>>8", jtab->key + 100);
10577 /*-----------------------------------------------------------------*/
10578 /* genCast - gen code for casting */
10579 /*-----------------------------------------------------------------*/
10581 genCast (iCode * ic)
10583 operand *result = IC_RESULT (ic);
10584 sym_link *ctype = operandType (IC_LEFT (ic));
10585 sym_link *rtype = operandType (IC_RIGHT (ic));
10586 operand *right = IC_RIGHT (ic);
10589 D(emitcode("; genCast",""));
10591 /* if they are equivalent then do nothing */
10592 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10595 aopOp (right, ic, FALSE);
10596 aopOp (result, ic, FALSE);
10598 /* if the result is a bit (and not a bitfield) */
10599 // if (AOP_TYPE (result) == AOP_CRY)
10600 if (IS_BITVAR (OP_SYMBOL (result)->type)
10601 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
10603 /* if the right size is a literal then
10604 we know what the value is */
10605 if (AOP_TYPE (right) == AOP_LIT)
10607 if (((int) operandLitValue (right)))
10608 aopPut (result, one, 0, isOperandVolatile (result, FALSE));
10610 aopPut (result, zero, 0, isOperandVolatile (result, FALSE));
10615 /* the right is also a bit variable */
10616 if (AOP_TYPE (right) == AOP_CRY)
10618 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10619 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
10623 /* we need to or */
10625 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
10630 /* if they are the same size : or less */
10631 if (AOP_SIZE (result) <= AOP_SIZE (right))
10634 /* if they are in the same place */
10635 if (sameRegs (AOP (right), AOP (result)))
10638 /* if they in different places then copy */
10639 size = AOP_SIZE (result);
10644 aopGet (right, offset, FALSE, FALSE),
10646 isOperandVolatile (result, FALSE));
10653 /* if the result is of type pointer */
10654 if (IS_PTR (ctype))
10658 sym_link *type = operandType (right);
10659 sym_link *etype = getSpec (type);
10661 /* pointer to generic pointer */
10662 if (IS_GENPTR (ctype))
10665 p_type = DCL_TYPE (type);
10668 if (SPEC_SCLS(etype)==S_REGISTER) {
10669 // let's assume it is a generic pointer
10672 /* we have to go by the storage class */
10673 p_type = PTR_TYPE (SPEC_OCLS (etype));
10677 /* the first two bytes are known */
10678 size = GPTRSIZE - 1;
10683 aopGet (right, offset, FALSE, FALSE),
10685 isOperandVolatile (result, FALSE));
10688 /* the last byte depending on type */
10690 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
10695 // pointerTypeToGPByte will have bitched.
10699 sprintf(gpValStr, "#0x%x", gpVal);
10700 aopPut (result, gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
10705 /* just copy the pointers */
10706 size = AOP_SIZE (result);
10711 aopGet (right, offset, FALSE, FALSE),
10713 isOperandVolatile (result, FALSE));
10719 /* so we now know that the size of destination is greater
10720 than the size of the source */
10721 /* we move to result for the size of source */
10722 size = AOP_SIZE (right);
10727 aopGet (right, offset, FALSE, FALSE),
10729 isOperandVolatile (result, FALSE));
10733 /* now depending on the sign of the source && destination */
10734 size = AOP_SIZE (result) - AOP_SIZE (right);
10735 /* if unsigned or not an integral type */
10736 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
10739 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
10743 /* we need to extend the sign :{ */
10744 char *l = aopGet (right, AOP_SIZE (right) - 1,
10747 emitcode ("rlc", "a");
10748 emitcode ("subb", "a,acc");
10750 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
10753 /* we are done hurray !!!! */
10756 freeAsmop (right, NULL, ic, TRUE);
10757 freeAsmop (result, NULL, ic, TRUE);
10761 /*-----------------------------------------------------------------*/
10762 /* genDjnz - generate decrement & jump if not zero instrucion */
10763 /*-----------------------------------------------------------------*/
10765 genDjnz (iCode * ic, iCode * ifx)
10767 symbol *lbl, *lbl1;
10771 D(emitcode ("; genDjnz",""));
10773 /* if the if condition has a false label
10774 then we cannot save */
10775 if (IC_FALSE (ifx))
10778 /* if the minus is not of the form
10780 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10781 !IS_OP_LITERAL (IC_RIGHT (ic)))
10784 if (operandLitValue (IC_RIGHT (ic)) != 1)
10787 /* if the size of this greater than one then no
10789 if (getSize (operandType (IC_RESULT (ic))) > 1)
10792 /* otherwise we can save BIG */
10793 lbl = newiTempLabel (NULL);
10794 lbl1 = newiTempLabel (NULL);
10796 aopOp (IC_RESULT (ic), ic, FALSE);
10798 if (AOP_NEEDSACC(IC_RESULT(ic)))
10800 /* If the result is accessed indirectly via
10801 * the accumulator, we must explicitly write
10802 * it back after the decrement.
10804 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
10806 if (strcmp(rByte, "a"))
10808 /* Something is hopelessly wrong */
10809 fprintf(stderr, "*** warning: internal error at %s:%d\n",
10810 __FILE__, __LINE__);
10811 /* We can just give up; the generated code will be inefficient,
10812 * but what the hey.
10814 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10817 emitcode ("dec", "%s", rByte);
10818 aopPut (IC_RESULT (ic), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10819 emitcode ("jnz", "%05d$", lbl->key + 100);
10821 else if (IS_AOP_PREG (IC_RESULT (ic)))
10823 emitcode ("dec", "%s",
10824 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
10825 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
10826 emitcode ("jnz", "%05d$", lbl->key + 100);
10830 emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
10833 emitcode ("sjmp", "%05d$", lbl1->key + 100);
10834 emitcode ("", "%05d$:", lbl->key + 100);
10835 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
10836 emitcode ("", "%05d$:", lbl1->key + 100);
10838 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10839 ifx->generated = 1;
10843 /*-----------------------------------------------------------------*/
10844 /* genReceive - generate code for a receive iCode */
10845 /*-----------------------------------------------------------------*/
10847 genReceive (iCode * ic)
10849 int size = getSize (operandType (IC_RESULT (ic)));
10852 D(emitcode ("; genReceive",""));
10854 if (ic->argreg == 1)
10855 { /* first parameter */
10856 if (isOperandInFarSpace (IC_RESULT (ic)) &&
10857 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10858 IS_TRUE_SYMOP (IC_RESULT (ic))))
10861 int receivingA = 0;
10864 for (offset = 0; offset<size; offset++)
10865 if (!strcmp (fReturn[offset], "a"))
10870 if (size==1 || getTempRegs(tempRegs, size-1, ic))
10872 for (offset = size-1; offset>0; offset--)
10873 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
10874 emitcode("mov","a,%s", fReturn[0]);
10876 aopOp (IC_RESULT (ic), ic, FALSE);
10878 aopPut (IC_RESULT (ic), "a", offset,
10879 isOperandVolatile (IC_RESULT (ic), FALSE));
10880 for (offset = 1; offset<size; offset++)
10881 aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset,
10882 isOperandVolatile (IC_RESULT (ic), FALSE));
10888 if (getTempRegs(tempRegs, size, ic))
10890 for (offset = 0; offset<size; offset++)
10891 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
10892 aopOp (IC_RESULT (ic), ic, FALSE);
10893 for (offset = 0; offset<size; offset++)
10894 aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset,
10895 isOperandVolatile (IC_RESULT (ic), FALSE));
10900 offset = fReturnSizeMCS51 - size;
10903 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
10904 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
10907 aopOp (IC_RESULT (ic), ic, FALSE);
10908 size = AOP_SIZE (IC_RESULT (ic));
10912 emitcode ("pop", "acc");
10913 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10919 aopOp (IC_RESULT (ic), ic, FALSE);
10921 assignResultValue (IC_RESULT (ic), NULL);
10924 else if (ic->argreg > 12)
10925 { /* bit parameters */
10926 if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
10928 aopOp (IC_RESULT (ic), ic, FALSE);
10929 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
10930 outBitC(IC_RESULT (ic));
10934 { /* other parameters */
10936 aopOp (IC_RESULT (ic), ic, FALSE);
10937 rb1off = ic->argreg;
10940 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10945 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10948 /*-----------------------------------------------------------------*/
10949 /* genDummyRead - generate code for dummy read of volatiles */
10950 /*-----------------------------------------------------------------*/
10952 genDummyRead (iCode * ic)
10957 D(emitcode("; genDummyRead",""));
10959 op = IC_RIGHT (ic);
10960 if (op && IS_SYMOP (op))
10962 aopOp (op, ic, FALSE);
10964 /* if the result is a bit */
10965 if (AOP_TYPE (op) == AOP_CRY)
10966 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
10969 /* bit variables done */
10971 size = AOP_SIZE (op);
10975 MOVA (aopGet (op, offset, FALSE, FALSE));
10980 freeAsmop (op, NULL, ic, TRUE);
10984 if (op && IS_SYMOP (op))
10986 aopOp (op, ic, FALSE);
10988 /* if the result is a bit */
10989 if (AOP_TYPE (op) == AOP_CRY)
10990 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
10993 /* bit variables done */
10995 size = AOP_SIZE (op);
10999 MOVA (aopGet (op, offset, FALSE, FALSE));
11004 freeAsmop (op, NULL, ic, TRUE);
11008 /*-----------------------------------------------------------------*/
11009 /* genCritical - generate code for start of a critical sequence */
11010 /*-----------------------------------------------------------------*/
11012 genCritical (iCode *ic)
11014 symbol *tlbl = newiTempLabel (NULL);
11016 D(emitcode("; genCritical",""));
11018 if (IC_RESULT (ic))
11020 aopOp (IC_RESULT (ic), ic, TRUE);
11021 aopPut (IC_RESULT (ic), one, 0, 0);
11022 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11023 aopPut (IC_RESULT (ic), zero, 0, 0);
11024 emitcode ("", "%05d$:", (tlbl->key + 100));
11025 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11029 emitcode ("setb", "c");
11030 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11031 emitcode ("clr", "c");
11032 emitcode ("", "%05d$:", (tlbl->key + 100));
11033 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11037 /*-----------------------------------------------------------------*/
11038 /* genEndCritical - generate code for end of a critical sequence */
11039 /*-----------------------------------------------------------------*/
11041 genEndCritical (iCode *ic)
11043 D(emitcode("; genEndCritical",""));
11047 aopOp (IC_RIGHT (ic), ic, FALSE);
11048 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11050 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11051 emitcode ("mov", "ea,c");
11055 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11056 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11057 emitcode ("rrc", "a");
11058 emitcode ("mov", "ea,c");
11060 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11064 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11065 emitcode ("mov", "ea,c");
11069 /*-----------------------------------------------------------------*/
11070 /* gen51Code - generate code for 8051 based controllers */
11071 /*-----------------------------------------------------------------*/
11073 gen51Code (iCode * lic)
11077 /* int cseq = 0; */
11079 _G.currentFunc = NULL;
11080 lineHead = lineCurr = NULL;
11082 /* print the allocation information */
11083 if (allocInfo && currFunc)
11084 printAllocInfo (currFunc, codeOutFile);
11085 /* if debug information required */
11086 if (options.debug && currFunc)
11088 debugFile->writeFunction (currFunc, lic);
11090 /* stack pointer name */
11091 if (options.useXstack)
11097 for (ic = lic; ic; ic = ic->next)
11099 _G.current_iCode = ic;
11101 if (ic->lineno && cln != ic->lineno)
11105 debugFile->writeCLine (ic);
11107 if (!options.noCcodeInAsm) {
11108 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
11109 printCLine(ic->filename, ic->lineno));
11114 if (ic->seqPoint && ic->seqPoint != cseq)
11116 emitcode ("", "; sequence point %d", ic->seqPoint);
11117 cseq = ic->seqPoint;
11120 if (options.iCodeInAsm) {
11121 char regsInUse[80];
11124 for (i=0; i<8; i++) {
11125 sprintf (®sInUse[i],
11126 "%c", ic->riu & (1<<i) ? i+'0' : '-');
11129 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
11131 /* if the result is marked as
11132 spilt and rematerializable or code for
11133 this has already been generated then
11135 if (resultRemat (ic) || ic->generated)
11138 /* depending on the operation */
11158 /* IPOP happens only when trying to restore a
11159 spilt live range, if there is an ifx statement
11160 following this pop then the if statement might
11161 be using some of the registers being popped which
11162 would destory the contents of the register so
11163 we need to check for this condition and handle it */
11165 ic->next->op == IFX &&
11166 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11167 genIfx (ic->next, ic);
11185 genEndFunction (ic);
11205 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11222 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11226 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11233 /* note these two are xlated by algebraic equivalence
11234 during parsing SDCC.y */
11235 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11236 "got '>=' or '<=' shouldn't have come here");
11240 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11252 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11256 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11260 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11296 genRightShift (ic);
11299 case GET_VALUE_AT_ADDRESS:
11301 hasInc (IC_LEFT (ic), ic,
11302 getSize (operandType (IC_RESULT (ic)))),
11303 ifxForOp (IC_RESULT (ic), ic) );
11307 if (POINTER_SET (ic))
11308 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
11334 addSet (&_G.sendSet, ic);
11337 case DUMMY_READ_VOLATILE:
11346 genEndCritical (ic);
11358 _G.current_iCode = NULL;
11360 /* now we are ready to call the
11361 peep hole optimizer */
11362 if (!options.nopeep)
11363 peepHole (&lineHead);
11365 /* now do the actual printing */
11366 printLine (lineHead, codeOutFile);