1 /*-------------------------------------------------------------------------
2 SDCCgen51.c - source file for code generation for 8051
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
27 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
28 Made everything static
29 -------------------------------------------------------------------------*/
38 #include "SDCCglobl.h"
42 #include "SDCCpeeph.h"
46 char *aopLiteral (value * val, int offset);
47 char *aopLiteralLong (value * val, int offset, int size);
50 /* this is the down and dirty file with all kinds of
51 kludgy & hacky stuff. This is what it is all about
52 CODE GENERATION for a specific MCU . some of the
53 routines may be reusable, will have to see */
55 static char *zero = "#0x00";
56 static char *one = "#0x01";
60 {"dpl", "dph", "b", "a"};
61 unsigned fReturnSizeMCS51 = 4; /* shared with ralloc.c */
62 char **fReturn = fReturn8051;
63 static char *accUse[] =
66 static unsigned short rbank = -1;
68 #define AOP(op) op->aop
69 #define AOP_TYPE(op) AOP(op)->type
70 #define AOP_SIZE(op) AOP(op)->size
71 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
72 AOP_TYPE(x) == AOP_R0))
74 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
75 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
77 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
78 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
79 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
82 #define SYM_BP(sym) (SPEC_OCLS (sym->etype)->paged ? "_bpx" : "_bp")
84 #define R0INB _G.bu.bs.r0InB
85 #define R1INB _G.bu.bs.r1InB
86 #define OPINB _G.bu.bs.OpInB
87 #define BINUSE _G.bu.BInUse
97 short r0InB : 2;//2 so we can see it overflow
98 short r1InB : 2;//2 so we can see it overflow
99 short OpInB : 2;//2 so we can see it overflow
108 iCode *current_iCode;
113 static char *rb1regs[] = {
114 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7",
115 "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7"
118 extern int mcs51_ptrRegReq;
119 extern int mcs51_nRegs;
120 extern FILE *codeOutFile;
121 static void saveRBank (int, iCode *, bool);
123 #define RESULTONSTACK(x) \
124 (IC_RESULT(x) && IC_RESULT(x)->aop && \
125 IC_RESULT(x)->aop->type == AOP_STK )
127 #define MOVA(x) mova(x) /* use function to avoid multiple eval */
128 #define CLRC emitcode("clr","c")
129 #define SETC emitcode("setb","c")
131 static lineNode *lineHead = NULL;
132 static lineNode *lineCurr = NULL;
134 static unsigned char SLMask[] =
135 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
136 0xE0, 0xC0, 0x80, 0x00};
137 static unsigned char SRMask[] =
138 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
139 0x07, 0x03, 0x01, 0x00};
146 /*-----------------------------------------------------------------*/
147 /* emitcode - writes the code into a file : for now it is simple */
148 /*-----------------------------------------------------------------*/
150 emitcode (char *inst, const char *fmt,...)
153 char lb[INITIAL_INLINEASM];
161 SNPRINTF (lb, sizeof(lb), "%s\t", inst);
163 SNPRINTF (lb, sizeof(lb), "%s", inst);
164 tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb), fmt, ap);
167 tvsprintf (lb, sizeof(lb), fmt, ap);
169 while (isspace ((unsigned char)*lbp))
173 lineCurr = (lineCurr ?
174 connectLine (lineCurr, newLineNode (lb)) :
175 (lineHead = newLineNode (lb)));
176 lineCurr->isInline = _G.inLine;
177 lineCurr->isDebug = _G.debugLine;
178 lineCurr->ic = _G.current_iCode;
179 lineCurr->isComment = (*lbp==';');
183 /*-----------------------------------------------------------------*/
184 /* mcs51_emitDebuggerSymbol - associate the current code location */
185 /* with a debugger symbol */
186 /*-----------------------------------------------------------------*/
188 mcs51_emitDebuggerSymbol (char * debugSym)
191 emitcode ("", "%s ==.", debugSym);
195 /*-----------------------------------------------------------------*/
196 /* mova - moves specified value into accumulator */
197 /*-----------------------------------------------------------------*/
201 /* do some early peephole optimization */
202 if (!strncmp(x, "a", 2) || !strncmp(x, "acc", 4))
205 emitcode("mov","a,%s", x);
208 /*-----------------------------------------------------------------*/
209 /* movc - moves specified value into the carry */
210 /*-----------------------------------------------------------------*/
218 else if (strcmp (s, "c"))
219 {/* it's not in carry already */
221 /* set C, if a >= 1 */
222 emitcode ("add", "a,#0xff");
226 /*-----------------------------------------------------------------*/
227 /* pushB - saves register B if necessary */
228 /*-----------------------------------------------------------------*/
232 bool pushedB = FALSE;
236 emitcode ("push", "b");
237 // printf("B was in use !\n");
247 /*-----------------------------------------------------------------*/
248 /* popB - restores value of register B if necessary */
249 /*-----------------------------------------------------------------*/
255 emitcode ("pop", "b");
263 /*-----------------------------------------------------------------*/
264 /* pushReg - saves register */
265 /*-----------------------------------------------------------------*/
267 pushReg (int index, bool bits_pushed)
269 regs * reg = mcs51_regWithIdx (index);
270 if (reg->type == REG_BIT)
273 emitcode ("push", "%s", reg->base);
277 emitcode ("push", "%s", reg->dname);
281 /*-----------------------------------------------------------------*/
282 /* popReg - restores register */
283 /*-----------------------------------------------------------------*/
285 popReg (int index, bool bits_popped)
287 regs * reg = mcs51_regWithIdx (index);
288 if (reg->type == REG_BIT)
291 emitcode ("pop", "%s", reg->base);
295 emitcode ("pop", "%s", reg->dname);
299 /*-----------------------------------------------------------------*/
300 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
301 /*-----------------------------------------------------------------*/
303 getFreePtr (iCode * ic, asmop ** aopp, bool result)
308 /* the logic: if r0 & r1 used in the instruction
309 then we are in trouble otherwise */
311 /* first check if r0 & r1 are used by this
312 instruction, in which case we are in trouble */
313 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
314 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
319 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
320 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
322 /* if no usage of r0 then return it */
325 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
326 (*aopp)->type = AOP_R0;
328 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
331 /* if no usage of r1 then return it */
334 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
335 (*aopp)->type = AOP_R1;
337 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
340 /* now we know they both have usage */
341 /* if r0 not used in this instruction */
344 /* push it if not already pushed */
347 emitcode ("mov", "b,%s",
348 mcs51_regWithIdx (R0_IDX)->dname);
351 else if (!_G.r0Pushed)
353 emitcode ("push", "%s",
354 mcs51_regWithIdx (R0_IDX)->dname);
358 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
359 (*aopp)->type = AOP_R0;
361 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
364 /* if r1 not used then */
368 /* push it if not already pushed */
371 emitcode ("mov", "b,%s",
372 mcs51_regWithIdx (R1_IDX)->dname);
375 else if (!_G.r1Pushed)
377 emitcode ("push", "%s",
378 mcs51_regWithIdx (R1_IDX)->dname);
382 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
383 (*aopp)->type = AOP_R1;
384 return mcs51_regWithIdx (R1_IDX);
387 /* I said end of world, but not quite end of world yet */
389 /* we can push it on the stack */
390 (*aopp)->type = AOP_STK;
393 /* in the case that result AND left AND right needs a pointer reg
394 we can safely use the result's */
395 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX)) {
396 (*aopp)->type = AOP_R0;
397 return mcs51_regWithIdx (R0_IDX);
399 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX)) {
400 (*aopp)->type = AOP_R1;
401 return mcs51_regWithIdx (R1_IDX);
405 /* now this is REALLY the end of the world */
406 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
407 "getFreePtr should never reach here");
412 /*-----------------------------------------------------------------*/
413 /* getTempRegs - initialize an array of pointers to GPR registers */
414 /* that are not in use. Returns 1 if the requested */
415 /* number of registers were available, 0 otherwise. */
416 /*-----------------------------------------------------------------*/
418 getTempRegs(regs **tempRegs, int size, iCode *ic)
425 ic = _G.current_iCode;
431 freeRegs = newBitVect(8);
432 bitVectSetBit (freeRegs, R2_IDX);
433 bitVectSetBit (freeRegs, R3_IDX);
434 bitVectSetBit (freeRegs, R4_IDX);
435 bitVectSetBit (freeRegs, R5_IDX);
436 bitVectSetBit (freeRegs, R6_IDX);
437 bitVectSetBit (freeRegs, R7_IDX);
439 if (IFFUNC_CALLEESAVES(_G.currentFunc->type))
441 bitVect * newfreeRegs;
442 newfreeRegs = bitVectIntersect (freeRegs, _G.currentFunc->regsUsed);
443 freeBitVect(freeRegs);
444 freeRegs = newfreeRegs;
446 freeRegs = bitVectCplAnd (freeRegs, ic->rMask);
449 for (i=0; i<freeRegs->size; i++)
451 if (bitVectBitValue(freeRegs,i))
452 tempRegs[offset++] = mcs51_regWithIdx(i);
455 freeBitVect(freeRegs);
460 freeBitVect(freeRegs);
465 /*-----------------------------------------------------------------*/
466 /* newAsmop - creates a new asmOp */
467 /*-----------------------------------------------------------------*/
469 newAsmop (short type)
473 aop = Safe_calloc (1, sizeof (asmop));
478 /*-----------------------------------------------------------------*/
479 /* pointerCode - returns the code for a pointer type */
480 /*-----------------------------------------------------------------*/
482 pointerCode (sym_link * etype)
485 return PTR_TYPE (SPEC_OCLS (etype));
489 /*-----------------------------------------------------------------*/
490 /* leftRightUseAcc - returns size of accumulator use by operands */
491 /*-----------------------------------------------------------------*/
493 leftRightUseAcc(iCode *ic)
502 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
503 "null iCode pointer");
510 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
513 size = getSize (OP_SYMBOL (op)->type);
518 else if (ic->op == JUMPTABLE)
521 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
524 size = getSize (OP_SYMBOL (op)->type);
532 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
535 size = getSize (OP_SYMBOL (op)->type);
540 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
543 size = getSize (OP_SYMBOL (op)->type);
555 /*-----------------------------------------------------------------*/
556 /* aopForSym - for a true symbol */
557 /*-----------------------------------------------------------------*/
559 aopForSym (iCode * ic, symbol * sym, bool result)
564 wassertl (ic != NULL, "Got a null iCode");
565 wassertl (sym != NULL, "Got a null symbol");
567 space = SPEC_OCLS (sym->etype);
569 /* if already has one */
573 /* assign depending on the storage class */
574 /* if it is on the stack or indirectly addressable */
575 /* space we need to assign either r0 or r1 to it */
576 if (sym->onStack || sym->iaccess)
578 sym->aop = aop = newAsmop (0);
579 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
580 aop->size = getSize (sym->type);
582 /* now assign the address of the variable to
583 the pointer register */
584 if (aop->type != AOP_STK)
589 char offset = ((sym->stack < 0) ?
590 ((char) (sym->stack - _G.nRegsSaved)) :
591 ((char) sym->stack)) & 0xff;
593 if ((offset >= -3) && (offset <= 3))
595 emitcode ("mov", "%s,%s",
596 aop->aopu.aop_ptr->name, SYM_BP (sym));
599 emitcode ("dec", aop->aopu.aop_ptr->name);
604 emitcode ("inc", aop->aopu.aop_ptr->name);
610 if (_G.accInUse || leftRightUseAcc (ic))
611 emitcode ("push", "acc");
612 emitcode ("mov", "a,%s", SYM_BP (sym));
613 emitcode ("add", "a,#0x%02x", offset);
614 emitcode ("mov", "%s,a",
615 aop->aopu.aop_ptr->name);
616 if (_G.accInUse || leftRightUseAcc (ic))
617 emitcode ("pop", "acc");
621 emitcode ("mov", "%s,#%s",
622 aop->aopu.aop_ptr->name,
624 aop->paged = space->paged;
627 aop->aopu.aop_stk = sym->stack;
631 /* if in bit space */
632 if (IN_BITSPACE (space))
634 sym->aop = aop = newAsmop (AOP_CRY);
635 aop->aopu.aop_dir = sym->rname;
636 aop->size = getSize (sym->type);
639 /* if it is in direct space */
640 if (IN_DIRSPACE (space))
642 //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
643 //printTypeChainRaw(sym->type, NULL);
644 //printf("space = %s\n", space ? space->sname : "NULL");
645 sym->aop = aop = newAsmop (AOP_DIR);
646 aop->aopu.aop_dir = sym->rname;
647 aop->size = getSize (sym->type);
651 /* special case for a function */
652 if (IS_FUNC (sym->type))
654 sym->aop = aop = newAsmop (AOP_IMMD);
655 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
656 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
657 aop->size = getSize (sym->type);
661 /* only remaining is far space */
662 /* in which case DPTR gets the address */
663 sym->aop = aop = newAsmop (AOP_DPTR);
664 emitcode ("mov", "dptr,#%s", sym->rname);
665 aop->size = getSize (sym->type);
667 /* if it is in code space */
668 if (IN_CODESPACE (space))
674 /*-----------------------------------------------------------------*/
675 /* aopForRemat - rematerialzes an object */
676 /*-----------------------------------------------------------------*/
678 aopForRemat (symbol * sym)
680 iCode *ic = sym->rematiCode;
681 asmop *aop = newAsmop (AOP_IMMD);
688 val += (int) operandLitValue (IC_RIGHT (ic));
689 else if (ic->op == '-')
690 val -= (int) operandLitValue (IC_RIGHT (ic));
691 else if (IS_CAST_ICODE(ic)) {
692 sym_link *from_type = operandType(IC_RIGHT(ic));
693 aop->aopu.aop_immd.from_cast_remat = 1;
694 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
695 ptr_type = pointerTypeToGPByte (DCL_TYPE(from_type), NULL, NULL);
699 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
703 sprintf (buffer, "(%s %c 0x%04x)",
704 OP_SYMBOL (IC_LEFT (ic))->rname,
705 val >= 0 ? '+' : '-',
708 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
710 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
711 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
712 /* set immd2 field if required */
713 if (aop->aopu.aop_immd.from_cast_remat) {
714 sprintf(buffer,"#0x%02x",ptr_type);
715 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
716 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
722 /*-----------------------------------------------------------------*/
723 /* regsInCommon - two operands have some registers in common */
724 /*-----------------------------------------------------------------*/
726 regsInCommon (operand * op1, operand * op2)
731 /* if they have registers in common */
732 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
735 sym1 = OP_SYMBOL (op1);
736 sym2 = OP_SYMBOL (op2);
738 if (sym1->nRegs == 0 || sym2->nRegs == 0)
741 for (i = 0; i < sym1->nRegs; i++)
747 for (j = 0; j < sym2->nRegs; j++)
752 if (sym2->regs[j] == sym1->regs[i])
760 /*-----------------------------------------------------------------*/
761 /* operandsEqu - equivalent */
762 /*-----------------------------------------------------------------*/
764 operandsEqu (operand * op1, operand * op2)
768 /* if they're not symbols */
769 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
772 sym1 = OP_SYMBOL (op1);
773 sym2 = OP_SYMBOL (op2);
775 /* if both are itemps & one is spilt
776 and the other is not then false */
777 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
778 sym1->isspilt != sym2->isspilt)
781 /* if they are the same */
785 /* if they have the same rname */
786 if (sym1->rname[0] && sym2->rname[0] &&
787 strcmp (sym1->rname, sym2->rname) == 0 &&
788 !(IS_PARM (op2) && IS_ITEMP (op1)))
791 /* if left is a tmp & right is not */
792 if (IS_ITEMP (op1) &&
795 (sym1->usl.spillLoc == sym2))
798 if (IS_ITEMP (op2) &&
802 (sym2->usl.spillLoc == sym1))
808 /*-----------------------------------------------------------------*/
809 /* sameRegs - two asmops have the same registers */
810 /*-----------------------------------------------------------------*/
812 sameRegs (asmop * aop1, asmop * aop2)
819 if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
822 if (aop1->type != aop2->type)
825 if (aop1->size != aop2->size)
828 for (i = 0; i < aop1->size; i++)
829 if (aop1->aopu.aop_reg[i] !=
830 aop2->aopu.aop_reg[i])
836 /*-----------------------------------------------------------------*/
837 /* aopOp - allocates an asmop for an operand : */
838 /*-----------------------------------------------------------------*/
840 aopOp (operand * op, iCode * ic, bool result)
849 /* if this a literal */
850 if (IS_OP_LITERAL (op))
852 op->aop = aop = newAsmop (AOP_LIT);
853 aop->aopu.aop_lit = op->operand.valOperand;
854 aop->size = getSize (operandType (op));
858 /* if already has a asmop then continue */
862 /* if the underlying symbol has a aop */
863 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
865 op->aop = OP_SYMBOL (op)->aop;
869 /* if this is a true symbol */
870 if (IS_TRUE_SYMOP (op))
872 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
876 /* this is a temporary : this has
882 e) can be a return use only */
884 sym = OP_SYMBOL (op);
886 /* if the type is a conditional */
887 if (sym->regType == REG_CND)
889 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
894 /* if it is spilt then two situations
896 b) has a spill location */
897 if (sym->isspilt || sym->nRegs == 0)
900 /* rematerialize it NOW */
903 sym->aop = op->aop = aop =
905 aop->size = getSize (sym->type);
912 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
913 aop->size = getSize (sym->type);
914 for (i = 0; i < 2; i++)
915 aop->aopu.aop_str[i] = accUse[i];
923 aop = op->aop = sym->aop = newAsmop (AOP_STR);
924 aop->size = getSize (sym->type);
925 for (i = 0; i < fReturnSizeMCS51; i++)
926 aop->aopu.aop_str[i] = fReturn[i];
930 if (sym->usl.spillLoc)
932 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
934 /* force a new aop if sizes differ */
935 sym->usl.spillLoc->aop = NULL;
937 sym->aop = op->aop = aop =
938 aopForSym (ic, sym->usl.spillLoc, result);
939 aop->size = getSize (sym->type);
943 /* else must be a dummy iTemp */
944 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
945 aop->size = getSize (sym->type);
949 /* if the type is a bit register */
950 if (sym->regType == REG_BIT)
952 sym->aop = op->aop = aop = newAsmop (AOP_CRY);
953 aop->size = sym->nRegs;//1???
954 aop->aopu.aop_reg[0] = sym->regs[0];
955 aop->aopu.aop_dir = sym->regs[0]->name;
959 /* must be in a register */
960 sym->aop = op->aop = aop = newAsmop (AOP_REG);
961 aop->size = sym->nRegs;
962 for (i = 0; i < sym->nRegs; i++)
963 aop->aopu.aop_reg[i] = sym->regs[i];
966 /*-----------------------------------------------------------------*/
967 /* freeAsmop - free up the asmop given to an operand */
968 /*----------------------------------------------------------------*/
970 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
987 /* depending on the asmop type only three cases need work AOP_RO
988 , AOP_R1 && AOP_STK */
994 emitcode ("mov", "r0,b");
997 else if (_G.r0Pushed)
1001 emitcode ("pop", "ar0");
1005 bitVectUnSetBit (ic->rUsed, R0_IDX);
1011 emitcode ("mov", "r1,b");
1018 emitcode ("pop", "ar1");
1022 bitVectUnSetBit (ic->rUsed, R1_IDX);
1028 int stk = aop->aopu.aop_stk + aop->size - 1;
1029 bitVectUnSetBit (ic->rUsed, R0_IDX);
1030 bitVectUnSetBit (ic->rUsed, R1_IDX);
1032 getFreePtr (ic, &aop, FALSE);
1036 emitcode ("mov", "a,_bp");
1037 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1038 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1042 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1047 emitcode ("pop", "acc");
1048 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1051 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1054 freeAsmop (op, NULL, ic, TRUE);
1057 emitcode ("pop", "ar1");
1063 emitcode ("pop", "ar0");
1070 /* all other cases just dealloc */
1076 OP_SYMBOL (op)->aop = NULL;
1077 /* if the symbol has a spill */
1079 SPIL_LOC (op)->aop = NULL;
1084 /*------------------------------------------------------------------*/
1085 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
1086 /* pop r0 or r1 off stack if pushed */
1087 /*------------------------------------------------------------------*/
1089 freeForBranchAsmop (operand * op)
1109 emitcode ("mov", "r0,b");
1111 else if (_G.r0Pushed)
1113 emitcode ("pop", "ar0");
1120 emitcode ("mov", "r1,b");
1122 else if (_G.r1Pushed)
1124 emitcode ("pop", "ar1");
1131 int stk = aop->aopu.aop_stk + aop->size - 1;
1133 emitcode ("mov", "b,r0");
1136 emitcode ("mov", "a,_bp");
1137 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1138 emitcode ("mov", "r0,a");
1142 emitcode ("mov", "r0,_bp");
1147 emitcode ("pop", "acc");
1148 emitcode ("mov", "@r0,a");
1151 emitcode ("dec", "r0");
1153 emitcode ("mov", "r0,b");
1159 /*-----------------------------------------------------------------*/
1160 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
1161 /* clobber the accumulator */
1162 /*-----------------------------------------------------------------*/
1164 aopGetUsesAcc (operand * oper, int offset)
1166 asmop * aop = AOP (oper);
1168 if (offset > (aop->size - 1))
1186 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1197 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1203 /* Error case --- will have been caught already */
1209 /*-----------------------------------------------------------------*/
1210 /* aopGet - for fetching value of the aop */
1211 /*-----------------------------------------------------------------*/
1213 aopGet (operand * oper, int offset, bool bit16, bool dname)
1217 asmop * aop = AOP (oper);
1219 /* offset is greater than
1221 if (offset > (aop->size - 1) &&
1222 aop->type != AOP_LIT)
1225 /* depending on type */
1233 /* if we need to increment it */
1234 while (offset > aop->coff)
1236 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1240 while (offset < aop->coff)
1242 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1249 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1250 return (dname ? "acc" : "a");
1252 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1253 rs = Safe_calloc (1, strlen (s) + 1);
1258 if (aop->code && aop->coff==0 && offset>=1) {
1259 emitcode ("mov", "a,#0x%02x", offset);
1260 emitcode ("movc", "a,@a+dptr");
1261 return (dname ? "acc" : "a");
1264 while (offset > aop->coff)
1266 emitcode ("inc", "dptr");
1270 while (offset < aop->coff)
1272 emitcode ("lcall", "__decdptr");
1279 emitcode ("clr", "a");
1280 emitcode ("movc", "a,@a+dptr");
1284 emitcode ("movx", "a,@dptr");
1286 return (dname ? "acc" : "a");
1290 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1291 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1293 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1295 sprintf (s, "#(%s >> %d)",
1296 aop->aopu.aop_immd.aop_immd1,
1300 aop->aopu.aop_immd.aop_immd1);
1301 rs = Safe_calloc (1, strlen (s) + 1);
1306 if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
1307 sprintf (s, "(%s >> %d)",
1308 aop->aopu.aop_dir, offset * 8);
1310 sprintf (s, "(%s + %d)",
1314 sprintf (s, "%s", aop->aopu.aop_dir);
1315 rs = Safe_calloc (1, strlen (s) + 1);
1321 return aop->aopu.aop_reg[offset]->dname;
1323 return aop->aopu.aop_reg[offset]->name;
1326 emitcode ("clr", "a");
1327 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1328 emitcode ("rlc", "a");
1329 return (dname ? "acc" : "a");
1332 if (!offset && dname)
1334 return aop->aopu.aop_str[offset];
1337 return aopLiteral (aop->aopu.aop_lit, offset);
1341 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1345 return aop->aopu.aop_str[offset];
1349 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1350 "aopget got unsupported aop->type");
1353 /*-----------------------------------------------------------------*/
1354 /* aopPut - puts a string for a aop and indicates if acc is in use */
1355 /*-----------------------------------------------------------------*/
1357 aopPut (operand * result, const char *s, int offset, bool bvolatile)
1360 bool accuse = FALSE;
1361 asmop * aop = AOP (result);
1363 if (aop->size && offset > (aop->size - 1))
1365 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1366 "aopPut got offset > aop->size");
1370 /* will assign value to value */
1371 /* depending on where it is ofcourse */
1375 MOVA (s); /* read s in case it was volatile */
1380 if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1381 sprintf (d, "(%s >> %d)",
1382 aop->aopu.aop_dir, offset * 8);
1384 sprintf (d, "(%s + %d)",
1385 aop->aopu.aop_dir, offset);
1387 sprintf (d, "%s", aop->aopu.aop_dir);
1389 if (strcmp (d, s) ||
1391 emitcode ("mov", "%s,%s", d, s);
1392 if (!strcmp (d, "acc"))
1398 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1399 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1402 strcmp (s, "r0") == 0 ||
1403 strcmp (s, "r1") == 0 ||
1404 strcmp (s, "r2") == 0 ||
1405 strcmp (s, "r3") == 0 ||
1406 strcmp (s, "r4") == 0 ||
1407 strcmp (s, "r5") == 0 ||
1408 strcmp (s, "r6") == 0 ||
1409 strcmp (s, "r7") == 0)
1410 emitcode ("mov", "%s,%s",
1411 aop->aopu.aop_reg[offset]->dname, s);
1413 emitcode ("mov", "%s,%s",
1414 aop->aopu.aop_reg[offset]->name, s);
1421 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1422 "aopPut writing to code space");
1426 while (offset > aop->coff)
1429 emitcode ("inc", "dptr");
1432 while (offset < aop->coff)
1435 emitcode ("lcall", "__decdptr");
1440 /* if not in accumulator */
1443 emitcode ("movx", "@dptr,a");
1448 while (offset > aop->coff)
1451 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1453 while (offset < aop->coff)
1456 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1463 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1469 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1471 else if (strcmp (s, "r0") == 0 ||
1472 strcmp (s, "r1") == 0 ||
1473 strcmp (s, "r2") == 0 ||
1474 strcmp (s, "r3") == 0 ||
1475 strcmp (s, "r4") == 0 ||
1476 strcmp (s, "r5") == 0 ||
1477 strcmp (s, "r6") == 0 ||
1478 strcmp (s, "r7") == 0)
1481 sprintf (buffer, "a%s", s);
1482 emitcode ("mov", "@%s,%s",
1483 aop->aopu.aop_ptr->name, buffer);
1486 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1491 if (strcmp (s, "a") == 0)
1492 emitcode ("push", "acc");
1496 emitcode ("push", "acc");
1498 emitcode ("push", s);
1504 /* if not bit variable */
1505 if (!aop->aopu.aop_dir)
1507 /* inefficient: move carry into A and use jz/jnz */
1508 emitcode ("clr", "a");
1509 emitcode ("rlc", "a");
1515 emitcode ("clr", "%s", aop->aopu.aop_dir);
1517 emitcode ("setb", "%s", aop->aopu.aop_dir);
1518 else if (!strcmp (s, "c"))
1519 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1520 else if (strcmp (s, aop->aopu.aop_dir))
1523 /* set C, if a >= 1 */
1524 emitcode ("add", "a,#0xff");
1525 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1532 if (strcmp (aop->aopu.aop_str[offset], s) ||
1534 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1540 if (!offset && (strcmp (s, "acc") == 0) &&
1544 if (strcmp (aop->aopu.aop_str[offset], s) &&
1546 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1550 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1551 "aopPut got unsupported aop->type");
1560 /*-----------------------------------------------------------------*/
1561 /* pointToEnd :- points to the last byte of the operand */
1562 /*-----------------------------------------------------------------*/
1564 pointToEnd (asmop * aop)
1570 aop->coff = count = (aop->size - 1);
1576 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1580 emitcode ("inc", "dptr");
1587 /*-----------------------------------------------------------------*/
1588 /* reAdjustPreg - points a register back to where it should */
1589 /*-----------------------------------------------------------------*/
1591 reAdjustPreg (asmop * aop)
1593 if ((aop->coff==0) || aop->size <= 1)
1601 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1606 emitcode ("lcall", "__decdptr");
1613 /*-----------------------------------------------------------------*/
1614 /* opIsGptr: returns non-zero if the passed operand is */
1615 /* a generic pointer type. */
1616 /*-----------------------------------------------------------------*/
1618 opIsGptr (operand * op)
1620 sym_link *type = operandType (op);
1622 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1629 /*-----------------------------------------------------------------*/
1630 /* getDataSize - get the operand data size */
1631 /*-----------------------------------------------------------------*/
1633 getDataSize (operand * op)
1636 size = AOP_SIZE (op);
1637 if (size == GPTRSIZE)
1639 sym_link *type = operandType (op);
1640 if (IS_GENPTR (type))
1642 /* generic pointer; arithmetic operations
1643 * should ignore the high byte (pointer type).
1651 /*-----------------------------------------------------------------*/
1652 /* outAcc - output Acc */
1653 /*-----------------------------------------------------------------*/
1655 outAcc (operand * result)
1658 size = getDataSize (result);
1661 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
1664 /* unsigned or positive */
1667 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
1672 /*-----------------------------------------------------------------*/
1673 /* outBitC - output a bit C */
1674 /*-----------------------------------------------------------------*/
1676 outBitC (operand * result)
1678 /* if the result is bit */
1679 if (AOP_TYPE (result) == AOP_CRY)
1680 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
1683 emitcode ("clr", "a");
1684 emitcode ("rlc", "a");
1689 /*-----------------------------------------------------------------*/
1690 /* toBoolean - emit code for orl a,operator(sizeop) */
1691 /*-----------------------------------------------------------------*/
1693 toBoolean (operand * oper)
1695 int size = AOP_SIZE (oper) - 1;
1697 bool AccUsed = FALSE;
1700 while (!AccUsed && size--)
1702 AccUsed |= aopGetUsesAcc(oper, offset++);
1705 size = AOP_SIZE (oper) - 1;
1707 MOVA (aopGet (oper, 0, FALSE, FALSE));
1708 if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1711 emitcode("mov", "b,a");
1714 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1715 emitcode ("orl", "b,a");
1717 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1718 emitcode ("orl", "a,b");
1725 emitcode ("orl", "a,%s", aopGet (oper, offset++, FALSE, FALSE));
1731 /*-----------------------------------------------------------------*/
1732 /* genNot - generate code for ! operation */
1733 /*-----------------------------------------------------------------*/
1739 D(emitcode ("; genNot",""));
1741 /* assign asmOps to operand & result */
1742 aopOp (IC_LEFT (ic), ic, FALSE);
1743 aopOp (IC_RESULT (ic), ic, TRUE);
1745 /* if in bit space then a special case */
1746 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1748 /* if left==result then cpl bit */
1749 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1751 emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1755 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1756 emitcode ("cpl", "c");
1757 outBitC (IC_RESULT (ic));
1762 toBoolean (IC_LEFT (ic));
1764 /* set C, if a == 0 */
1765 tlbl = newiTempLabel (NULL);
1766 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1767 emitcode ("", "%05d$:", tlbl->key + 100);
1768 outBitC (IC_RESULT (ic));
1771 /* release the aops */
1772 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1773 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1777 /*-----------------------------------------------------------------*/
1778 /* genCpl - generate code for complement */
1779 /*-----------------------------------------------------------------*/
1786 sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
1788 D(emitcode (";", "genCpl"));
1790 /* assign asmOps to operand & result */
1791 aopOp (IC_LEFT (ic), ic, FALSE);
1792 aopOp (IC_RESULT (ic), ic, TRUE);
1794 /* special case if in bit space */
1795 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1799 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
1800 (SPEC_USIGN (letype) && IS_CHAR (letype)))
1802 /* promotion rules are responsible for this strange result:
1803 bit -> int -> ~int -> bit
1804 uchar -> int -> ~int -> bit
1806 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
1810 tlbl=newiTempLabel(NULL);
1811 l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
1812 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
1813 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1814 IS_AOP_PREG (IC_LEFT (ic)))
1816 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
1821 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
1823 emitcode ("", "%05d$:", tlbl->key + 100);
1824 outBitC (IC_RESULT(ic));
1828 size = AOP_SIZE (IC_RESULT (ic));
1831 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
1833 emitcode ("cpl", "a");
1834 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1839 /* release the aops */
1840 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1841 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1844 /*-----------------------------------------------------------------*/
1845 /* genUminusFloat - unary minus for floating points */
1846 /*-----------------------------------------------------------------*/
1848 genUminusFloat (operand * op, operand * result)
1850 int size, offset = 0;
1853 D(emitcode ("; genUminusFloat",""));
1855 /* for this we just copy and then flip the bit */
1857 size = AOP_SIZE (op) - 1;
1862 aopGet (op, offset, FALSE, FALSE),
1864 isOperandVolatile (result, FALSE));
1868 l = aopGet (op, offset, FALSE, FALSE);
1872 emitcode ("cpl", "acc.7");
1873 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
1876 /*-----------------------------------------------------------------*/
1877 /* genUminus - unary minus code generation */
1878 /*-----------------------------------------------------------------*/
1880 genUminus (iCode * ic)
1883 sym_link *optype, *rtype;
1886 D(emitcode ("; genUminus",""));
1889 aopOp (IC_LEFT (ic), ic, FALSE);
1890 aopOp (IC_RESULT (ic), ic, TRUE);
1892 /* if both in bit space then special
1894 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1895 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1898 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1899 emitcode ("cpl", "c");
1900 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1904 optype = operandType (IC_LEFT (ic));
1905 rtype = operandType (IC_RESULT (ic));
1907 /* if float then do float stuff */
1908 if (IS_FLOAT (optype))
1910 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1914 /* otherwise subtract from zero */
1915 size = AOP_SIZE (IC_LEFT (ic));
1920 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
1921 if (!strcmp (l, "a"))
1925 emitcode ("cpl", "a");
1926 emitcode ("addc", "a,#0");
1932 emitcode ("clr", "a");
1933 emitcode ("subb", "a,%s", l);
1935 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1938 /* if any remaining bytes in the result */
1939 /* we just need to propagate the sign */
1940 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1942 emitcode ("rlc", "a");
1943 emitcode ("subb", "a,acc");
1945 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1949 /* release the aops */
1950 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1951 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1954 /*-----------------------------------------------------------------*/
1955 /* saveRegisters - will look for a call and save the registers */
1956 /*-----------------------------------------------------------------*/
1958 saveRegisters (iCode * lic)
1965 for (ic = lic; ic; ic = ic->next)
1966 if (ic->op == CALL || ic->op == PCALL)
1971 fprintf (stderr, "found parameter push with no function call\n");
1975 /* if the registers have been saved already or don't need to be then
1979 if (IS_SYMOP(IC_LEFT(ic)) &&
1980 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1981 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
1984 /* save the registers in use at this time but skip the
1985 ones for the result */
1986 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1987 mcs51_rUmaskForOp (IC_RESULT(ic)));
1990 if (options.useXstack)
1992 int count = bitVectnBitsOn (rsave);
1996 regs * reg = mcs51_regWithIdx (bitVectFirstBit (rsave));
1997 if (reg->type == REG_BIT)
1999 emitcode ("mov", "a,%s", reg->base);
2003 emitcode ("mov", "a,%s", reg->name);
2005 emitcode ("mov", "r0,%s", spname);
2006 emitcode ("inc", "%s", spname);// allocate before use
2007 emitcode ("movx", "@r0,a");
2008 if (bitVectBitValue (rsave, R0_IDX))
2009 emitcode ("mov", "r0,a");
2011 else if (count != 0)
2013 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2014 int nBits = bitVectnBitsOn (rsavebits);
2018 count = count - nBits + 1;
2019 /* remove all but the first bits as they are pushed all at once */
2020 rsave = bitVectCplAnd (rsave, rsavebits);
2021 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2024 if (bitVectBitValue (rsave, R0_IDX))
2026 emitcode ("push", "%s", mcs51_regWithIdx (R0_IDX)->dname);
2028 emitcode ("mov", "r0,%s", spname);
2030 emitcode ("add", "a,#%d", count);
2031 emitcode ("mov", "%s,a", spname);
2032 for (i = 0; i < mcs51_nRegs; i++)
2034 if (bitVectBitValue (rsave, i))
2036 regs * reg = mcs51_regWithIdx (i);
2039 emitcode ("pop", "acc");
2040 emitcode ("push", "acc");
2042 else if (reg->type == REG_BIT)
2044 emitcode ("mov", "a,%s", reg->base);
2048 emitcode ("mov", "a,%s", reg->name);
2050 emitcode ("movx", "@r0,a");
2053 emitcode ("inc", "r0");
2057 if (bitVectBitValue (rsave, R0_IDX))
2059 emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
2065 bool bits_pushed = FALSE;
2066 for (i = 0; i < mcs51_nRegs; i++)
2068 if (bitVectBitValue (rsave, i))
2070 bits_pushed = pushReg (i, bits_pushed);
2076 /*-----------------------------------------------------------------*/
2077 /* unsaveRegisters - pop the pushed registers */
2078 /*-----------------------------------------------------------------*/
2080 unsaveRegisters (iCode * ic)
2085 /* restore the registers in use at this time but skip the
2086 ones for the result */
2087 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2088 mcs51_rUmaskForOp (IC_RESULT(ic)));
2090 if (options.useXstack)
2092 int count = bitVectnBitsOn (rsave);
2096 regs * reg = mcs51_regWithIdx (bitVectFirstBit (rsave));
2097 emitcode ("mov", "r0,%s", spname);
2098 emitcode ("dec", "r0");
2099 emitcode ("movx", "a,@r0");
2100 if (reg->type == REG_BIT)
2102 emitcode ("mov", "%s,a", reg->base);
2106 emitcode ("mov", "%s,a", reg->name);
2108 emitcode ("dec", "%s", spname);
2110 else if (count != 0)
2112 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2113 int nBits = bitVectnBitsOn (rsavebits);
2117 count = count - nBits + 1;
2118 /* remove all but the first bits as they are popped all at once */
2119 rsave = bitVectCplAnd (rsave, rsavebits);
2120 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2123 emitcode ("mov", "r0,%s", spname);
2124 for (i = mcs51_nRegs; i >= 0; i--)
2126 if (bitVectBitValue (rsave, i))
2128 regs * reg = mcs51_regWithIdx (i);
2129 emitcode ("dec", "r0");
2130 emitcode ("movx", "a,@r0");
2133 emitcode ("push", "acc");
2135 else if (reg->type == REG_BIT)
2137 emitcode ("mov", "%s,a", reg->base);
2141 emitcode ("mov", "%s,a", reg->name);
2145 emitcode ("mov", "%s,r0", spname);
2146 if (bitVectBitValue (rsave, R0_IDX))
2148 emitcode ("pop", "ar0");
2154 bool bits_popped = FALSE;
2155 for (i = mcs51_nRegs; i >= 0; i--)
2157 if (bitVectBitValue (rsave, i))
2159 bits_popped = popReg (i, bits_popped);
2166 /*-----------------------------------------------------------------*/
2168 /*-----------------------------------------------------------------*/
2170 pushSide (operand * oper, int size)
2175 char *l = aopGet (oper, offset++, FALSE, TRUE);
2176 if (AOP_TYPE (oper) != AOP_REG &&
2177 AOP_TYPE (oper) != AOP_DIR &&
2181 emitcode ("push", "acc");
2185 emitcode ("push", "%s", l);
2190 /*-----------------------------------------------------------------*/
2191 /* assignResultValue - also indicates if acc is in use afterwards */
2192 /*-----------------------------------------------------------------*/
2194 assignResultValue (operand * oper, operand * func)
2197 int size = AOP_SIZE (oper);
2198 bool accuse = FALSE;
2200 if (func && IS_BIT (OP_SYM_ETYPE (func)))
2208 accuse |= aopPut (oper, fReturn[offset], offset, isOperandVolatile (oper, FALSE));
2215 /*-----------------------------------------------------------------*/
2216 /* genXpush - pushes onto the external stack */
2217 /*-----------------------------------------------------------------*/
2219 genXpush (iCode * ic)
2221 asmop *aop = newAsmop (0);
2223 int size, offset = 0;
2225 D(emitcode ("; genXpush",""));
2227 aopOp (IC_LEFT (ic), ic, FALSE);
2228 r = getFreePtr (ic, &aop, FALSE);
2230 size = AOP_SIZE (IC_LEFT (ic));
2234 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2235 emitcode ("mov", "%s,%s", r->name, spname);
2236 emitcode ("inc", "%s", spname); // allocate space first
2237 emitcode ("movx", "@%s,a", r->name);
2241 // allocate space first
2242 emitcode ("mov", "%s,%s", r->name, spname);
2244 emitcode ("add", "a,#%d", size);
2245 emitcode ("mov", "%s,a", spname);
2249 MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2250 emitcode ("movx", "@%s,a", r->name);
2251 emitcode ("inc", "%s", r->name);
2255 freeAsmop (NULL, aop, ic, TRUE);
2256 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2259 /*-----------------------------------------------------------------*/
2260 /* genIpush - generate code for pushing this gets a little complex */
2261 /*-----------------------------------------------------------------*/
2263 genIpush (iCode * ic)
2265 int size, offset = 0;
2269 D(emitcode ("; genIpush",""));
2271 /* if this is not a parm push : ie. it is spill push
2272 and spill push is always done on the local stack */
2276 /* and the item is spilt then do nothing */
2277 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2280 aopOp (IC_LEFT (ic), ic, FALSE);
2281 size = AOP_SIZE (IC_LEFT (ic));
2282 /* push it on the stack */
2285 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2291 emitcode ("push", "%s", l);
2296 /* this is a parameter push: in this case we call
2297 the routine to find the call and save those
2298 registers that need to be saved */
2301 /* if use external stack then call the external
2302 stack pushing routine */
2303 if (options.useXstack)
2309 /* then do the push */
2310 aopOp (IC_LEFT (ic), ic, FALSE);
2312 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2313 size = AOP_SIZE (IC_LEFT (ic));
2317 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2318 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2319 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2322 if (strcmp (l, prev) || *l == '@')
2324 emitcode ("push", "acc");
2328 emitcode ("push", "%s", l);
2333 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2336 /*-----------------------------------------------------------------*/
2337 /* genIpop - recover the registers: can happen only for spilling */
2338 /*-----------------------------------------------------------------*/
2340 genIpop (iCode * ic)
2344 D(emitcode ("; genIpop",""));
2346 /* if the temp was not pushed then */
2347 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2350 aopOp (IC_LEFT (ic), ic, FALSE);
2351 size = AOP_SIZE (IC_LEFT (ic));
2352 offset = (size - 1);
2354 emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2357 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2360 /*-----------------------------------------------------------------*/
2361 /* saveRBank - saves an entire register bank on the stack */
2362 /*-----------------------------------------------------------------*/
2364 saveRBank (int bank, iCode * ic, bool pushPsw)
2367 int count = mcs51_nRegs + (pushPsw ? 1 : 0);
2371 if (options.useXstack)
2375 /* Assume r0 is available for use. */
2376 r = mcs51_regWithIdx (R0_IDX);;
2381 r = getFreePtr (ic, &aop, FALSE);
2383 // allocate space first
2384 emitcode ("mov", "%s,%s", r->name, spname);
2386 emitcode ("add", "a,#%d", count);
2387 emitcode ("mov", "%s,a", spname);
2390 for (i = 0; i < mcs51_nRegs; i++)
2392 if (options.useXstack)
2394 emitcode ("mov", "a,(%s+%d)",
2395 regs8051[i].base, 8 * bank + regs8051[i].offset);
2396 emitcode ("movx", "@%s,a", r->name);
2398 emitcode ("inc", "%s", r->name);
2401 emitcode ("push", "(%s+%d)",
2402 regs8051[i].base, 8 * bank + regs8051[i].offset);
2407 if (options.useXstack)
2409 emitcode ("mov", "a,psw");
2410 emitcode ("movx", "@%s,a", r->name);
2415 emitcode ("push", "psw");
2418 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2423 freeAsmop (NULL, aop, ic, TRUE);
2432 /*-----------------------------------------------------------------*/
2433 /* unsaveRBank - restores the register bank from stack */
2434 /*-----------------------------------------------------------------*/
2436 unsaveRBank (int bank, iCode * ic, bool popPsw)
2442 if (options.useXstack)
2446 /* Assume r0 is available for use. */
2447 r = mcs51_regWithIdx (R0_IDX);;
2452 r = getFreePtr (ic, &aop, FALSE);
2454 emitcode ("mov", "%s,%s", r->name, spname);
2459 if (options.useXstack)
2461 emitcode ("dec", "%s", r->name);
2462 emitcode ("movx", "a,@%s", r->name);
2463 emitcode ("mov", "psw,a");
2467 emitcode ("pop", "psw");
2471 for (i = (mcs51_nRegs - 1); i >= 0; i--)
2473 if (options.useXstack)
2475 emitcode ("dec", "%s", r->name);
2476 emitcode ("movx", "a,@%s", r->name);
2477 emitcode ("mov", "(%s+%d),a",
2478 regs8051[i].base, 8 * bank + regs8051[i].offset);
2482 emitcode ("pop", "(%s+%d)",
2483 regs8051[i].base, 8 * bank + regs8051[i].offset);
2487 if (options.useXstack)
2489 emitcode ("mov", "%s,%s", spname, r->name);
2494 freeAsmop (NULL, aop, ic, TRUE);
2498 /*-----------------------------------------------------------------*/
2499 /* genSend - gen code for SEND */
2500 /*-----------------------------------------------------------------*/
2501 static void genSend(set *sendSet)
2506 /* first we do all bit parameters */
2507 for (sic = setFirstItem (sendSet); sic;
2508 sic = setNextItem (sendSet))
2510 aopOp (IC_LEFT (sic), sic, FALSE);
2512 if (sic->argreg > 12)
2514 int bit = sic->argreg-13;
2516 /* if left is a literal then
2517 we know what the value is */
2518 if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2520 if (((int) operandLitValue (IC_LEFT (sic))))
2521 emitcode ("setb", "b[%d]", bit);
2523 emitcode ("clr", "b[%d]", bit);
2525 else if (AOP_TYPE (IC_LEFT (sic)) == AOP_CRY)
2527 char *l = AOP (IC_LEFT (sic))->aopu.aop_dir;
2528 if (strcmp (l, "c"))
2529 emitcode ("mov", "c,%s", l);
2530 emitcode ("mov", "b[%d],c", bit);
2535 toBoolean (IC_LEFT (sic));
2536 /* set C, if a >= 1 */
2537 emitcode ("add", "a,#0xff");
2538 emitcode ("mov", "b[%d],c", bit);
2543 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2548 saveRegisters (setFirstItem (sendSet));
2549 emitcode ("mov", "bits,b");
2552 /* then we do all other parameters */
2553 for (sic = setFirstItem (sendSet); sic;
2554 sic = setNextItem (sendSet))
2556 int size, offset = 0;
2557 aopOp (IC_LEFT (sic), sic, FALSE);
2558 size = AOP_SIZE (IC_LEFT (sic));
2560 if (sic->argreg == 1)
2564 char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2565 if (strcmp (l, fReturn[offset]))
2566 emitcode ("mov", "%s,%s", fReturn[offset], l);
2570 else if (sic->argreg <= 12)
2574 emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2575 aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2579 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2583 /*-----------------------------------------------------------------*/
2584 /* selectRegBank - emit code to select the register bank */
2585 /*-----------------------------------------------------------------*/
2587 selectRegBank (short bank, bool keepFlags)
2589 /* if f.e. result is in carry */
2592 emitcode ("anl", "psw,#0xE7");
2594 emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2598 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2602 /*-----------------------------------------------------------------*/
2603 /* genCall - generates a call statement */
2604 /*-----------------------------------------------------------------*/
2606 genCall (iCode * ic)
2610 // bool restoreBank = FALSE;
2611 bool swapBanks = FALSE;
2612 bool accuse = FALSE;
2613 bool accPushed = FALSE;
2614 bool resultInF0 = FALSE;
2616 D(emitcode("; genCall",""));
2618 dtype = operandType (IC_LEFT (ic));
2619 etype = getSpec(dtype);
2620 /* if send set is not empty then assign */
2623 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2624 genSend(reverseSet(_G.sendSet));
2626 genSend(_G.sendSet);
2632 /* if we are calling a not _naked function that is not using
2633 the same register bank then we need to save the
2634 destination registers on the stack */
2635 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2636 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2637 !IFFUNC_ISISR (dtype))
2642 /* if caller saves & we have not saved then */
2648 emitcode ("mov", "psw,#0x%02x",
2649 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2653 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2655 if (IFFUNC_CALLEESAVES(dtype))
2657 werror (E_BANKED_WITH_CALLEESAVES);
2661 char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2662 OP_SYMBOL (IC_LEFT (ic))->rname :
2663 OP_SYMBOL (IC_LEFT (ic))->name);
2665 emitcode ("mov", "r0,#%s", l);
2666 emitcode ("mov", "r1,#(%s >> 8)", l);
2667 emitcode ("mov", "r2,#(%s >> 16)", l);
2668 emitcode ("lcall", "__sdcc_banked_call");
2673 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2674 OP_SYMBOL (IC_LEFT (ic))->rname :
2675 OP_SYMBOL (IC_LEFT (ic))->name));
2680 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2683 /* if we need assign a result value */
2684 if ((IS_ITEMP (IC_RESULT (ic)) &&
2685 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2686 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2687 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2688 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2689 IS_TRUE_SYMOP (IC_RESULT (ic)))
2693 aopOp (IC_RESULT (ic), ic, FALSE);
2696 accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2698 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2701 /* adjust the stack for parameters if required */
2705 if (ic->parmBytes > 3)
2709 emitcode ("push", "acc");
2712 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2713 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
2715 emitcode ("mov", "F0,c");
2719 emitcode ("mov", "a,%s", spname);
2720 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2721 emitcode ("mov", "%s,a", spname);
2723 /* unsaveRegisters from xstack needs acc, but */
2724 /* unsaveRegisters from stack needs this popped */
2725 if (accPushed && !options.useXstack)
2727 emitcode ("pop", "acc");
2732 for (i = 0; i < ic->parmBytes; i++)
2733 emitcode ("dec", "%s", spname);
2736 /* if we had saved some registers then unsave them */
2737 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2739 if (accuse && !accPushed && options.useXstack)
2741 /* xstack needs acc, but doesn't touch normal stack */
2742 emitcode ("push", "acc");
2745 unsaveRegisters (ic);
2748 // /* if register bank was saved then pop them */
2750 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2752 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
2755 emitcode ("mov", "c,F0");
2757 aopOp (IC_RESULT (ic), ic, FALSE);
2758 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2759 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2763 emitcode ("pop", "acc");
2766 /*-----------------------------------------------------------------*/
2767 /* -10l - generates a call by pointer statement */
2768 /*-----------------------------------------------------------------*/
2770 genPcall (iCode * ic)
2774 symbol *rlbl = newiTempLabel (NULL);
2775 // bool restoreBank=FALSE;
2776 bool swapBanks = FALSE;
2777 bool resultInF0 = FALSE;
2779 D(emitcode("; genPCall",""));
2781 dtype = operandType (IC_LEFT (ic))->next;
2782 etype = getSpec(dtype);
2783 /* if caller saves & we have not saved then */
2787 /* if we are calling a not _naked function that is not using
2788 the same register bank then we need to save the
2789 destination registers on the stack */
2790 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2791 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2792 !IFFUNC_ISISR (dtype))
2794 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2795 // restoreBank=TRUE;
2797 // need caution message to user here
2800 if (IS_LITERAL(etype))
2802 /* if send set is not empty then assign */
2805 genSend(reverseSet(_G.sendSet));
2811 emitcode ("mov", "psw,#0x%02x",
2812 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2815 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2817 if (IFFUNC_CALLEESAVES(dtype))
2819 werror (E_BANKED_WITH_CALLEESAVES);
2823 char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
2825 emitcode ("mov", "r0,#%s", l);
2826 emitcode ("mov", "r1,#(%s >> 8)", l);
2827 emitcode ("mov", "r2,#(%s >> 16)", l);
2828 emitcode ("lcall", "__sdcc_banked_call");
2833 emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
2838 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2840 if (IFFUNC_CALLEESAVES(dtype))
2842 werror (E_BANKED_WITH_CALLEESAVES);
2846 aopOp (IC_LEFT (ic), ic, FALSE);
2850 emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
2851 emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
2852 emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
2856 int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
2857 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
2858 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
2859 emitcode ("mov", "0x%02x,%s", reg, aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
2862 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2864 /* if send set is not empty then assign */
2867 genSend(reverseSet(_G.sendSet));
2873 emitcode ("mov", "psw,#0x%02x",
2874 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2878 emitcode ("lcall", "__sdcc_banked_call");
2883 /* push the return address on to the stack */
2884 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2885 emitcode ("push", "acc");
2886 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2887 emitcode ("push", "acc");
2889 /* now push the calling address */
2890 aopOp (IC_LEFT (ic), ic, FALSE);
2892 pushSide (IC_LEFT (ic), FPTRSIZE);
2894 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2896 /* if send set is not empty the assign */
2899 genSend(reverseSet(_G.sendSet));
2905 emitcode ("mov", "psw,#0x%02x",
2906 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2910 emitcode ("ret", "");
2911 emitcode ("", "%05d$:", (rlbl->key + 100));
2916 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2919 /* if we need assign a result value */
2920 if ((IS_ITEMP (IC_RESULT (ic)) &&
2921 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2922 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2923 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2924 IS_TRUE_SYMOP (IC_RESULT (ic)))
2928 aopOp (IC_RESULT (ic), ic, FALSE);
2931 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2933 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2936 /* adjust the stack for parameters if required */
2940 if (ic->parmBytes > 3)
2942 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2943 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
2945 emitcode ("mov", "F0,c");
2949 emitcode ("mov", "a,%s", spname);
2950 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2951 emitcode ("mov", "%s,a", spname);
2954 for (i = 0; i < ic->parmBytes; i++)
2955 emitcode ("dec", "%s", spname);
2959 // /* if register bank was saved then unsave them */
2961 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2963 /* if we had saved some registers then unsave them */
2964 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2965 unsaveRegisters (ic);
2967 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
2970 emitcode ("mov", "c,F0");
2972 aopOp (IC_RESULT (ic), ic, FALSE);
2973 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2974 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2978 /*-----------------------------------------------------------------*/
2979 /* resultRemat - result is rematerializable */
2980 /*-----------------------------------------------------------------*/
2982 resultRemat (iCode * ic)
2984 if (SKIP_IC (ic) || ic->op == IFX)
2987 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2989 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2990 if (sym->remat && !POINTER_SET (ic))
2997 #if defined(__BORLANDC__) || defined(_MSC_VER)
2998 #define STRCASECMP stricmp
3000 #define STRCASECMP strcasecmp
3003 /*-----------------------------------------------------------------*/
3004 /* inExcludeList - return 1 if the string is in exclude Reg list */
3005 /*-----------------------------------------------------------------*/
3007 regsCmp(void *p1, void *p2)
3009 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3013 inExcludeList (char *s)
3015 const char *p = setFirstItem(options.excludeRegsSet);
3017 if (p == NULL || STRCASECMP(p, "none") == 0)
3021 return isinSetWith(options.excludeRegsSet, s, regsCmp);
3024 /*-----------------------------------------------------------------*/
3025 /* genFunction - generated code for function entry */
3026 /*-----------------------------------------------------------------*/
3028 genFunction (iCode * ic)
3030 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3032 bool switchedPSW = FALSE;
3033 int calleesaves_saved_register = -1;
3034 int stackAdjust = sym->stack;
3035 int accIsFree = sym->recvSize < 4;
3036 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3037 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3040 /* create the function header */
3041 emitcode (";", "-----------------------------------------");
3042 emitcode (";", " function %s", sym->name);
3043 emitcode (";", "-----------------------------------------");
3045 emitcode ("", "%s:", sym->rname);
3046 ftype = operandType (IC_LEFT (ic));
3047 _G.currentFunc = sym;
3049 if (IFFUNC_ISNAKED(ftype))
3051 emitcode(";", "naked function: no prologue.");
3055 /* here we need to generate the equates for the
3056 register bank if required */
3057 if (FUNC_REGBANK (ftype) != rbank)
3061 rbank = FUNC_REGBANK (ftype);
3062 for (i = 0; i < mcs51_nRegs; i++)
3064 if (regs8051[i].type != REG_BIT)
3066 if (strcmp (regs8051[i].base, "0") == 0)
3067 emitcode ("", "%s = 0x%02x",
3069 8 * rbank + regs8051[i].offset);
3071 emitcode ("", "%s = %s + 0x%02x",
3074 8 * rbank + regs8051[i].offset);
3079 /* if this is an interrupt service routine then
3080 save acc, b, dpl, dph */
3081 if (IFFUNC_ISISR (sym->type))
3084 if (!inExcludeList ("acc"))
3085 emitcode ("push", "acc");
3086 if (!inExcludeList ("b"))
3087 emitcode ("push", "b");
3088 if (!inExcludeList ("dpl"))
3089 emitcode ("push", "dpl");
3090 if (!inExcludeList ("dph"))
3091 emitcode ("push", "dph");
3092 /* if this isr has no bank i.e. is going to
3093 run with bank 0 , then we need to save more
3095 if (!FUNC_REGBANK (sym->type))
3098 /* if this function does not call any other
3099 function then we can be economical and
3100 save only those registers that are used */
3101 if (!IFFUNC_HASFCALL(sym->type))
3105 /* if any registers used */
3108 bool bits_pushed = FALSE;
3109 /* save the registers used */
3110 for (i = 0; i < sym->regsUsed->size; i++)
3112 if (bitVectBitValue (sym->regsUsed, i))
3113 bits_pushed = pushReg (i, bits_pushed);
3120 /* this function has a function call. We cannot
3121 determines register usage so we will have to push the
3123 saveRBank (0, ic, FALSE);
3124 if (options.parms_in_bank1) {
3126 for (i=0; i < 8 ; i++ ) {
3127 emitcode ("push","%s",rb1regs[i]);
3134 /* This ISR uses a non-zero bank.
3136 * We assume that the bank is available for our
3139 * However, if this ISR calls a function which uses some
3140 * other bank, we must save that bank entirely.
3142 unsigned long banksToSave = 0;
3144 if (IFFUNC_HASFCALL(sym->type))
3147 #define MAX_REGISTER_BANKS 4
3152 for (i = ic; i; i = i->next)
3154 if (i->op == ENDFUNCTION)
3156 /* we got to the end OK. */
3164 dtype = operandType (IC_LEFT(i));
3166 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3168 /* Mark this bank for saving. */
3169 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3171 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3175 banksToSave |= (1 << FUNC_REGBANK(dtype));
3178 /* And note that we don't need to do it in
3186 /* This is a mess; we have no idea what
3187 * register bank the called function might
3190 * The only thing I can think of to do is
3191 * throw a warning and hope.
3193 werror(W_FUNCPTR_IN_USING_ISR);
3197 if (banksToSave && options.useXstack)
3199 /* Since we aren't passing it an ic,
3200 * saveRBank will assume r0 is available to abuse.
3202 * So switch to our (trashable) bank now, so
3203 * the caller's R0 isn't trashed.
3205 emitcode ("push", "psw");
3206 emitcode ("mov", "psw,#0x%02x",
3207 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3211 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3213 if (banksToSave & (1 << ix))
3215 saveRBank(ix, NULL, FALSE);
3219 // TODO: this needs a closer look
3220 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3223 /* Set the register bank to the desired value if nothing else */
3224 /* has done so yet. */
3227 emitcode ("push", "psw");
3228 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3233 /* This is a non-ISR function. The caller has already switched register */
3234 /* banks, if necessary, so just handle the callee-saves option. */
3236 /* if callee-save to be used for this function
3237 then save the registers being used in this function */
3238 if (IFFUNC_CALLEESAVES(sym->type))
3242 /* if any registers used */
3245 bool bits_pushed = FALSE;
3246 /* save the registers used */
3247 for (i = 0; i < sym->regsUsed->size; i++)
3249 if (bitVectBitValue (sym->regsUsed, i))
3251 /* remember one saved register for later usage */
3252 if (calleesaves_saved_register < 0)
3253 calleesaves_saved_register = i;
3254 bits_pushed = pushReg (i, bits_pushed);
3265 if (options.useXstack)
3267 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3269 emitcode ("mov", "r0,%s", spname);
3270 emitcode ("inc", "%s", spname);
3271 emitcode ("xch", "a,_bpx");
3272 emitcode ("movx", "@r0,a");
3273 emitcode ("inc", "r0");
3274 emitcode ("mov", "a,r0");
3275 emitcode ("xch", "a,_bpx");
3279 emitcode ("push", "_bp"); /* save the callers stack */
3280 emitcode ("mov", "_bp,sp");
3285 if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3287 /* set up the stack */
3288 emitcode ("push", "_bp"); /* save the callers stack */
3289 emitcode ("mov", "_bp,sp");
3294 /* For some cases it is worthwhile to perform a RECEIVE iCode */
3295 /* before setting up the stack frame completely. */
3296 if (ric && ric->argreg == 1 && IC_RESULT (ric))
3298 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3302 if (rsym && rsym->regType == REG_CND)
3304 if (rsym && (rsym->accuse || rsym->ruonly))
3306 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3307 rsym = rsym->usl.spillLoc;
3310 /* If the RECEIVE operand immediately spills to the first entry on the */
3311 /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3312 /* rather than the usual @r0/r1 machinations. */
3313 if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3317 _G.current_iCode = ric;
3318 D(emitcode ("; genReceive",""));
3319 for (ofs=0; ofs < sym->recvSize; ofs++)
3321 if (!strcmp (fReturn[ofs], "a"))
3322 emitcode ("push", "acc");
3324 emitcode ("push", fReturn[ofs]);
3326 stackAdjust -= sym->recvSize;
3329 assert (stackAdjust>=0);
3332 _G.current_iCode = ic;
3336 /* If the RECEIVE operand is 4 registers, we can do the moves now */
3337 /* to free up the accumulator. */
3338 else if (rsym && rsym->nRegs && sym->recvSize == 4)
3342 _G.current_iCode = ric;
3343 D(emitcode ("; genReceive",""));
3344 for (ofs=0; ofs < sym->recvSize; ofs++)
3346 emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3348 _G.current_iCode = ic;
3354 /* adjust the stack for the function */
3357 int i = stackAdjust;
3359 werror (W_STACK_OVERFLOW, sym->name);
3361 if (i > 3 && accIsFree)
3363 emitcode ("mov", "a,sp");
3364 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3365 emitcode ("mov", "sp,a");
3369 /* The accumulator is not free, so we will need another register */
3370 /* to clobber. No need to worry about a possible conflict with */
3371 /* the above early RECEIVE optimizations since they would have */
3372 /* freed the accumulator if they were generated. */
3374 if (IFFUNC_CALLEESAVES(sym->type))
3376 /* if it's a callee-saves function we need a saved register */
3377 if (calleesaves_saved_register >= 0)
3379 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
3380 emitcode ("mov", "a,sp");
3381 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3382 emitcode ("mov", "sp,a");
3383 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
3386 /* do it the hard way */
3388 emitcode ("inc", "sp");
3392 /* not callee-saves, we can clobber r0 */
3393 emitcode ("mov", "r0,a");
3394 emitcode ("mov", "a,sp");
3395 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3396 emitcode ("mov", "sp,a");
3397 emitcode ("mov", "a,r0");
3402 emitcode ("inc", "sp");
3407 char i = ((char) sym->xstack & 0xff);
3409 if (i > 3 && accIsFree)
3411 emitcode ("mov", "a,_spx");
3412 emitcode ("add", "a,#0x%02x", i);
3413 emitcode ("mov", "_spx,a");
3417 emitcode ("push", "acc");
3418 emitcode ("mov", "a,_spx");
3419 emitcode ("add", "a,#0x%02x", i);
3420 emitcode ("mov", "_spx,a");
3421 emitcode ("pop", "acc");
3426 emitcode ("inc", "_spx");
3430 /* if critical function then turn interrupts off */
3431 if (IFFUNC_ISCRITICAL (ftype))
3433 symbol *tlbl = newiTempLabel (NULL);
3434 emitcode ("setb", "c");
3435 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3436 emitcode ("clr", "c");
3437 emitcode ("", "%05d$:", (tlbl->key + 100));
3438 emitcode ("push", "psw"); /* save old ea via c in psw */
3442 /*-----------------------------------------------------------------*/
3443 /* genEndFunction - generates epilogue for functions */
3444 /*-----------------------------------------------------------------*/
3446 genEndFunction (iCode * ic)
3448 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3449 lineNode *lnp = lineCurr;
3451 bitVect *regsUsedPrologue;
3452 bitVect *regsUnneeded;
3455 _G.currentFunc = NULL;
3456 if (IFFUNC_ISNAKED(sym->type))
3458 emitcode(";", "naked function: no epilogue.");
3459 if (options.debug && currFunc)
3460 debugFile->writeEndFunction (currFunc, ic, 0);
3464 if (IFFUNC_ISCRITICAL (sym->type))
3466 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3468 emitcode ("rlc", "a"); /* save c in a */
3469 emitcode ("pop", "psw"); /* restore ea via c in psw */
3470 emitcode ("mov", "ea,c");
3471 emitcode ("rrc", "a"); /* restore c from a */
3475 emitcode ("pop", "psw"); /* restore ea via c in psw */
3476 emitcode ("mov", "ea,c");
3480 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3482 if (options.useXstack)
3486 emitcode ("mov", "sp,_bp");
3487 emitcode ("pop", "_bp");
3489 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3491 emitcode ("xch", "a,_bpx");
3492 emitcode ("mov", "r0,a");
3493 emitcode ("dec", "r0");
3494 emitcode ("movx", "a,@r0");
3495 emitcode ("xch", "a,_bpx");
3496 emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3499 else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3501 emitcode ("mov", "sp,_bp");
3502 emitcode ("pop", "_bp");
3506 /* restore the register bank */
3507 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3509 if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
3510 || !options.useXstack)
3512 /* Special case of ISR using non-zero bank with useXstack
3515 emitcode ("pop", "psw");
3519 if (IFFUNC_ISISR (sym->type))
3522 /* now we need to restore the registers */
3523 /* if this isr has no bank i.e. is going to
3524 run with bank 0 , then we need to save more
3526 if (!FUNC_REGBANK (sym->type))
3528 /* if this function does not call any other
3529 function then we can be economical and
3530 save only those registers that are used */
3531 if (!IFFUNC_HASFCALL(sym->type))
3535 /* if any registers used */
3538 bool bits_popped = FALSE;
3539 /* save the registers used */
3540 for (i = sym->regsUsed->size; i >= 0; i--)
3542 if (bitVectBitValue (sym->regsUsed, i))
3543 bits_popped = popReg (i, bits_popped);
3549 if (options.parms_in_bank1) {
3551 for (i = 7 ; i >= 0 ; i-- ) {
3552 emitcode ("pop","%s",rb1regs[i]);
3555 /* this function has a function call cannot
3556 determines register usage so we will have to pop the
3558 unsaveRBank (0, ic, FALSE);
3563 /* This ISR uses a non-zero bank.
3565 * Restore any register banks saved by genFunction
3568 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3571 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3573 if (savedBanks & (1 << ix))
3575 unsaveRBank(ix, NULL, FALSE);
3579 if (options.useXstack)
3581 /* Restore bank AFTER calling unsaveRBank,
3582 * since it can trash r0.
3584 emitcode ("pop", "psw");
3588 if (!inExcludeList ("dph"))
3589 emitcode ("pop", "dph");
3590 if (!inExcludeList ("dpl"))
3591 emitcode ("pop", "dpl");
3592 if (!inExcludeList ("b"))
3593 emitcode ("pop", "b");
3594 if (!inExcludeList ("acc"))
3595 emitcode ("pop", "acc");
3597 /* if debug then send end of function */
3598 if (options.debug && currFunc)
3600 debugFile->writeEndFunction (currFunc, ic, 1);
3603 emitcode ("reti", "");
3607 if (IFFUNC_CALLEESAVES(sym->type))
3611 /* if any registers used */
3614 /* save the registers used */
3615 for (i = sym->regsUsed->size; i >= 0; i--)
3617 if (bitVectBitValue (sym->regsUsed, i) ||
3618 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3619 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
3622 else if (mcs51_ptrRegReq)
3624 emitcode ("pop", "%s", mcs51_regWithIdx (R1_IDX)->dname);
3625 emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
3630 /* if debug then send end of function */
3631 if (options.debug && currFunc)
3633 debugFile->writeEndFunction (currFunc, ic, 1);
3636 if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3638 emitcode ("ljmp", "__sdcc_banked_ret");
3642 emitcode ("ret", "");
3646 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3649 /* If this was an interrupt handler using bank 0 that called another */
3650 /* function, then all registers must be saved; nothing to optimized. */
3651 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3652 && !FUNC_REGBANK(sym->type))
3655 /* There are no push/pops to optimize if not callee-saves or ISR */
3656 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3659 /* If there were stack parameters, we cannot optimize without also */
3660 /* fixing all of the stack offsets; this is too dificult to consider. */
3661 if (FUNC_HASSTACKPARM(sym->type))
3664 /* Compute the registers actually used */
3665 regsUsed = newBitVect (mcs51_nRegs);
3666 regsUsedPrologue = newBitVect (mcs51_nRegs);
3669 if (lnp->ic && lnp->ic->op == FUNCTION)
3670 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3672 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3674 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3675 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3682 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3683 && !bitVectBitValue (regsUsed, CND_IDX))
3685 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3686 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3687 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3688 bitVectUnSetBit (regsUsed, CND_IDX);
3691 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3693 /* If this was an interrupt handler that called another function */
3694 /* function, then assume A, B, DPH, & DPL may be modified by it. */
3695 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3697 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3698 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3699 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3700 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3701 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3704 /* Remove the unneeded push/pops */
3705 regsUnneeded = newBitVect (mcs51_nRegs);
3708 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3710 if (!strncmp(lnp->line, "push", 4))
3712 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3713 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3715 connectLine (lnp->prev, lnp->next);
3716 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3719 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3721 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3722 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3724 connectLine (lnp->prev, lnp->next);
3725 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3732 for (idx = 0; idx < regsUnneeded->size; idx++)
3733 if (bitVectBitValue (regsUnneeded, idx))
3734 emitcode ("", ";\teliminated unneeded push/pop %s", mcs51_regWithIdx (idx)->dname);
3736 freeBitVect (regsUnneeded);
3737 freeBitVect (regsUsed);
3738 freeBitVect (regsUsedPrologue);
3741 /*-----------------------------------------------------------------*/
3742 /* genRet - generate code for return statement */
3743 /*-----------------------------------------------------------------*/
3747 int size, offset = 0, pushed = 0;
3749 D(emitcode ("; genRet",""));
3751 /* if we have no return value then
3752 just generate the "ret" */
3756 /* we have something to return then
3757 move the return value into place */
3758 aopOp (IC_LEFT (ic), ic, FALSE);
3759 size = AOP_SIZE (IC_LEFT (ic));
3762 if (IS_BIT(_G.currentFunc->etype))
3764 movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
3771 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3774 l = aopGet (IC_LEFT (ic), offset++,
3776 emitcode ("push", "%s", l);
3781 l = aopGet (IC_LEFT (ic), offset,
3783 if (strcmp (fReturn[offset], l))
3784 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3791 if (strcmp (fReturn[pushed], "a"))
3792 emitcode ("pop", fReturn[pushed]);
3794 emitcode ("pop", "acc");
3796 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3799 /* generate a jump to the return label
3800 if the next is not the return statement */
3801 if (!(ic->next && ic->next->op == LABEL &&
3802 IC_LABEL (ic->next) == returnLabel))
3804 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3808 /*-----------------------------------------------------------------*/
3809 /* genLabel - generates a label */
3810 /*-----------------------------------------------------------------*/
3812 genLabel (iCode * ic)
3814 /* special case never generate */
3815 if (IC_LABEL (ic) == entryLabel)
3818 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3821 /*-----------------------------------------------------------------*/
3822 /* genGoto - generates a ljmp */
3823 /*-----------------------------------------------------------------*/
3825 genGoto (iCode * ic)
3827 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3830 /*-----------------------------------------------------------------*/
3831 /* findLabelBackwards: walks back through the iCode chain looking */
3832 /* for the given label. Returns number of iCode instructions */
3833 /* between that label and given ic. */
3834 /* Returns zero if label not found. */
3835 /*-----------------------------------------------------------------*/
3837 findLabelBackwards (iCode * ic, int key)
3846 /* If we have any pushes or pops, we cannot predict the distance.
3847 I don't like this at all, this should be dealt with in the
3849 if (ic->op == IPUSH || ic->op == IPOP) {
3853 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3862 /*-----------------------------------------------------------------*/
3863 /* genPlusIncr :- does addition with increment if possible */
3864 /*-----------------------------------------------------------------*/
3866 genPlusIncr (iCode * ic)
3868 unsigned int icount;
3869 unsigned int size = getDataSize (IC_RESULT (ic));
3871 /* will try to generate an increment */
3872 /* if the right side is not a literal
3874 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3877 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3879 D(emitcode ("; genPlusIncr",""));
3881 /* if increment >=16 bits in register or direct space */
3882 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
3883 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3884 !isOperandVolatile (IC_RESULT (ic), FALSE) &&
3892 /* If the next instruction is a goto and the goto target
3893 * is < 10 instructions previous to this, we can generate
3894 * jumps straight to that target.
3896 if (ic->next && ic->next->op == GOTO
3897 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3898 && labelRange <= 10)
3900 emitcode (";", "tail increment optimized");
3901 tlbl = IC_LABEL (ic->next);
3906 tlbl = newiTempLabel (NULL);
3909 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
3910 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3911 IS_AOP_PREG (IC_RESULT (ic)))
3912 emitcode ("cjne", "%s,#0x00,%05d$",
3913 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
3917 emitcode ("clr", "a");
3918 emitcode ("cjne", "a,%s,%05d$",
3919 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
3923 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
3926 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3927 IS_AOP_PREG (IC_RESULT (ic)))
3928 emitcode ("cjne", "%s,#0x00,%05d$",
3929 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
3932 emitcode ("cjne", "a,%s,%05d$",
3933 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
3936 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
3940 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3941 IS_AOP_PREG (IC_RESULT (ic)))
3942 emitcode ("cjne", "%s,#0x00,%05d$",
3943 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
3947 emitcode ("cjne", "a,%s,%05d$",
3948 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
3951 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
3956 emitcode ("", "%05d$:", tlbl->key + 100);
3961 /* if result is dptr */
3962 if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
3963 (AOP_SIZE (IC_RESULT (ic)) == 2) &&
3964 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
3965 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
3967 if (aopGetUsesAcc (IC_LEFT (ic), 0))
3973 if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
3976 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0, FALSE);
3977 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1, FALSE);
3979 emitcode ("inc", "dptr");
3984 /* if the literal value of the right hand side
3985 is greater than 4 then it is not worth it */
3989 /* if the sizes are greater than 1 then we cannot */
3990 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3991 AOP_SIZE (IC_LEFT (ic)) > 1)
3994 /* we can if the aops of the left & result match or
3995 if they are in registers and the registers are the
3997 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4002 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4003 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4004 aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4010 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4019 /*-----------------------------------------------------------------*/
4020 /* outBitAcc - output a bit in acc */
4021 /*-----------------------------------------------------------------*/
4023 outBitAcc (operand * result)
4025 symbol *tlbl = newiTempLabel (NULL);
4026 /* if the result is a bit */
4027 if (AOP_TYPE (result) == AOP_CRY)
4029 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4033 emitcode ("jz", "%05d$", tlbl->key + 100);
4034 emitcode ("mov", "a,%s", one);
4035 emitcode ("", "%05d$:", tlbl->key + 100);
4040 /*-----------------------------------------------------------------*/
4041 /* genPlusBits - generates code for addition of two bits */
4042 /*-----------------------------------------------------------------*/
4044 genPlusBits (iCode * ic)
4046 D(emitcode ("; genPlusBits",""));
4048 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4050 symbol *lbl = newiTempLabel (NULL);
4051 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4052 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4053 emitcode ("cpl", "c");
4054 emitcode ("", "%05d$:", (lbl->key + 100));
4055 outBitC (IC_RESULT (ic));
4059 emitcode ("clr", "a");
4060 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4061 emitcode ("rlc", "a");
4062 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4063 emitcode ("addc", "a,#0x00");
4064 outAcc (IC_RESULT (ic));
4069 /* This is the original version of this code.
4071 * This is being kept around for reference,
4072 * because I am not entirely sure I got it right...
4075 adjustArithmeticResult (iCode * ic)
4077 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4078 AOP_SIZE (IC_LEFT (ic)) == 3 &&
4079 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4080 aopPut (IC_RESULT (ic),
4081 aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4083 isOperandVolatile (IC_RESULT (ic), FALSE));
4085 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4086 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4087 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4088 aopPut (IC_RESULT (ic),
4089 aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4091 isOperandVolatile (IC_RESULT (ic), FALSE));
4093 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4094 AOP_SIZE (IC_LEFT (ic)) < 3 &&
4095 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4096 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4097 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4100 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4101 aopPut (IC_RESULT (ic), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
4105 /* This is the pure and virtuous version of this code.
4106 * I'm pretty certain it's right, but not enough to toss the old
4110 adjustArithmeticResult (iCode * ic)
4112 if (opIsGptr (IC_RESULT (ic)) &&
4113 opIsGptr (IC_LEFT (ic)) &&
4114 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4116 aopPut (IC_RESULT (ic),
4117 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4119 isOperandVolatile (IC_RESULT (ic), FALSE));
4122 if (opIsGptr (IC_RESULT (ic)) &&
4123 opIsGptr (IC_RIGHT (ic)) &&
4124 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4126 aopPut (IC_RESULT (ic),
4127 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4129 isOperandVolatile (IC_RESULT (ic), FALSE));
4132 if (opIsGptr (IC_RESULT (ic)) &&
4133 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4134 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4135 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4136 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4139 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4140 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
4145 /*-----------------------------------------------------------------*/
4146 /* genPlus - generates code for addition */
4147 /*-----------------------------------------------------------------*/
4149 genPlus (iCode * ic)
4151 int size, offset = 0;
4154 operand *leftOp, *rightOp;
4157 /* special cases :- */
4159 D(emitcode ("; genPlus",""));
4161 aopOp (IC_LEFT (ic), ic, FALSE);
4162 aopOp (IC_RIGHT (ic), ic, FALSE);
4163 aopOp (IC_RESULT (ic), ic, TRUE);
4165 /* if literal, literal on the right or
4166 if left requires ACC or right is already
4168 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4169 (AOP_NEEDSACC (IC_LEFT (ic))) ||
4170 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4172 operand *t = IC_RIGHT (ic);
4173 IC_RIGHT (ic) = IC_LEFT (ic);
4177 /* if both left & right are in bit
4179 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4180 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4186 /* if left in bit space & right literal */
4187 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4188 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4190 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4191 /* if result in bit space */
4192 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4194 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4195 emitcode ("cpl", "c");
4196 outBitC (IC_RESULT (ic));
4200 size = getDataSize (IC_RESULT (ic));
4203 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4204 emitcode ("addc", "a,#00");
4205 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4211 /* if I can do an increment instead
4212 of add then GOOD for ME */
4213 if (genPlusIncr (ic) == TRUE)
4216 size = getDataSize (IC_RESULT (ic));
4217 leftOp = IC_LEFT(ic);
4218 rightOp = IC_RIGHT(ic);
4221 /* if this is an add for an array access
4222 at a 256 byte boundary */
4224 && AOP_TYPE (op) == AOP_IMMD
4226 && IS_SPEC (OP_SYM_ETYPE (op))
4227 && SPEC_ABSA (OP_SYM_ETYPE (op))
4228 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4231 D(emitcode ("; genPlus aligned array",""));
4232 aopPut (IC_RESULT (ic),
4233 aopGet (rightOp, 0, FALSE, FALSE),
4235 isOperandVolatile (IC_RESULT (ic), FALSE));
4237 if( 1 == getDataSize (IC_RIGHT (ic)) )
4239 aopPut (IC_RESULT (ic),
4240 aopGet (leftOp, 1, FALSE, FALSE),
4242 isOperandVolatile (IC_RESULT (ic), FALSE));
4246 MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4247 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4248 aopPut (IC_RESULT (ic), "a", 1, isOperandVolatile (IC_RESULT (ic), FALSE));
4253 /* if the lower bytes of a literal are zero skip the addition */
4254 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4256 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4257 (skip_bytes+1 < size))
4262 D(emitcode ("; genPlus shortcut",""));
4267 if( offset >= skip_bytes )
4269 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4272 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4274 emitcode("xch", "a,b");
4275 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4276 emitcode (add, "a,b");
4279 else if (aopGetUsesAcc (leftOp, offset))
4281 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4282 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4286 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4287 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4289 aopPut (IC_RESULT (ic), "a", offset, isOperandVolatile (IC_RESULT (ic), FALSE));
4290 add = "addc"; /* further adds must propagate carry */
4294 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4295 isOperandVolatile (IC_RESULT (ic), FALSE))
4298 aopPut (IC_RESULT (ic),
4299 aopGet (leftOp, offset, FALSE, FALSE),
4301 isOperandVolatile (IC_RESULT (ic), FALSE));
4307 adjustArithmeticResult (ic);
4310 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4311 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4312 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4315 /*-----------------------------------------------------------------*/
4316 /* genMinusDec :- does subtraction with decrement if possible */
4317 /*-----------------------------------------------------------------*/
4319 genMinusDec (iCode * ic)
4321 unsigned int icount;
4322 unsigned int size = getDataSize (IC_RESULT (ic));
4324 /* will try to generate an increment */
4325 /* if the right side is not a literal
4327 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4330 /* if the literal value of the right hand side
4331 is greater than 4 then it is not worth it */
4332 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4335 D(emitcode ("; genMinusDec",""));
4337 /* if decrement >=16 bits in register or direct space */
4338 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
4339 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4347 /* If the next instruction is a goto and the goto target
4348 * is <= 10 instructions previous to this, we can generate
4349 * jumps straight to that target.
4351 if (ic->next && ic->next->op == GOTO
4352 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4353 && labelRange <= 10)
4355 emitcode (";", "tail decrement optimized");
4356 tlbl = IC_LABEL (ic->next);
4361 tlbl = newiTempLabel (NULL);
4365 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4366 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4367 IS_AOP_PREG (IC_RESULT (ic)))
4368 emitcode ("cjne", "%s,#0xff,%05d$"
4369 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4373 emitcode ("mov", "a,#0xff");
4374 emitcode ("cjne", "a,%s,%05d$"
4375 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4378 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4381 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4382 IS_AOP_PREG (IC_RESULT (ic)))
4383 emitcode ("cjne", "%s,#0xff,%05d$"
4384 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4388 emitcode ("cjne", "a,%s,%05d$"
4389 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4392 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4396 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4397 IS_AOP_PREG (IC_RESULT (ic)))
4398 emitcode ("cjne", "%s,#0xff,%05d$"
4399 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4403 emitcode ("cjne", "a,%s,%05d$"
4404 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4407 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4411 emitcode ("", "%05d$:", tlbl->key + 100);
4416 /* if the sizes are greater than 1 then we cannot */
4417 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4418 AOP_SIZE (IC_LEFT (ic)) > 1)
4421 /* we can if the aops of the left & result match or
4422 if they are in registers and the registers are the
4424 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4428 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4436 /*-----------------------------------------------------------------*/
4437 /* addSign - complete with sign */
4438 /*-----------------------------------------------------------------*/
4440 addSign (operand * result, int offset, int sign)
4442 int size = (getDataSize (result) - offset);
4447 emitcode ("rlc", "a");
4448 emitcode ("subb", "a,acc");
4450 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
4454 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
4458 /*-----------------------------------------------------------------*/
4459 /* genMinusBits - generates code for subtraction of two bits */
4460 /*-----------------------------------------------------------------*/
4462 genMinusBits (iCode * ic)
4464 symbol *lbl = newiTempLabel (NULL);
4466 D(emitcode ("; genMinusBits",""));
4468 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4470 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4471 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4472 emitcode ("cpl", "c");
4473 emitcode ("", "%05d$:", (lbl->key + 100));
4474 outBitC (IC_RESULT (ic));
4478 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4479 emitcode ("subb", "a,acc");
4480 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4481 emitcode ("inc", "a");
4482 emitcode ("", "%05d$:", (lbl->key + 100));
4483 aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4484 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4488 /*-----------------------------------------------------------------*/
4489 /* genMinus - generates code for subtraction */
4490 /*-----------------------------------------------------------------*/
4492 genMinus (iCode * ic)
4494 int size, offset = 0;
4496 D(emitcode ("; genMinus",""));
4498 aopOp (IC_LEFT (ic), ic, FALSE);
4499 aopOp (IC_RIGHT (ic), ic, FALSE);
4500 aopOp (IC_RESULT (ic), ic, TRUE);
4502 /* special cases :- */
4503 /* if both left & right are in bit space */
4504 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4505 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4511 /* if I can do an decrement instead
4512 of subtract then GOOD for ME */
4513 if (genMinusDec (ic) == TRUE)
4516 size = getDataSize (IC_RESULT (ic));
4518 /* if literal, add a,#-lit, else normal subb */
4519 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4521 unsigned long lit = 0L;
4522 bool useCarry = FALSE;
4524 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4529 if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4531 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4532 if (!offset && !size && lit== (unsigned long) -1)
4534 emitcode ("dec", "a");
4538 /* first add without previous c */
4539 emitcode ("add", "a,#0x%02x",
4540 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4545 emitcode ("addc", "a,#0x%02x",
4546 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4548 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4552 /* no need to add zeroes */
4553 if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4555 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4556 offset, isOperandVolatile (IC_RESULT (ic), FALSE));
4564 operand *leftOp, *rightOp;
4566 leftOp = IC_LEFT(ic);
4567 rightOp = IC_RIGHT(ic);
4571 if (aopGetUsesAcc(rightOp, offset)) {
4572 if (aopGetUsesAcc(leftOp, offset)) {
4575 MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4577 emitcode ("mov", "b,a");
4580 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4581 emitcode ("subb", "a,b");
4584 /* reverse subtraction with 2's complement */
4586 emitcode( "setb", "c");
4588 emitcode( "cpl", "c");
4589 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4590 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4591 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4592 emitcode("cpl", "a");
4593 if (size) /* skip if last byte */
4594 emitcode( "cpl", "c");
4597 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4600 emitcode ("subb", "a,%s",
4601 aopGet(rightOp, offset, FALSE, TRUE));
4604 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4609 adjustArithmeticResult (ic);
4612 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4613 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4614 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4618 /*-----------------------------------------------------------------*/
4619 /* genMultbits :- multiplication of bits */
4620 /*-----------------------------------------------------------------*/
4622 genMultbits (operand * left,
4626 D(emitcode ("; genMultbits",""));
4628 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4629 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4633 /*-----------------------------------------------------------------*/
4634 /* genMultOneByte : 8*8=8/16 bit multiplication */
4635 /*-----------------------------------------------------------------*/
4637 genMultOneByte (operand * left,
4642 int size = AOP_SIZE (result);
4643 bool runtimeSign, compiletimeSign;
4644 bool lUnsigned, rUnsigned, pushedB;
4646 D(emitcode ("; genMultOneByte",""));
4648 if (size < 1 || size > 2)
4650 /* this should never happen */
4651 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4652 AOP_SIZE(result), __FILE__, lineno);
4656 /* (if two literals: the value is computed before) */
4657 /* if one literal, literal on the right */
4658 if (AOP_TYPE (left) == AOP_LIT)
4663 /* emitcode (";", "swapped left and right"); */
4665 /* if no literal, unsigned on the right: shorter code */
4666 if ( AOP_TYPE (right) != AOP_LIT
4667 && SPEC_USIGN (getSpec (operandType (left))))
4674 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4675 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4679 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4680 no need to take care about the signedness! */
4681 || (lUnsigned && rUnsigned))
4683 /* just an unsigned 8 * 8 = 8 multiply
4685 /* emitcode (";","unsigned"); */
4686 /* TODO: check for accumulator clash between left & right aops? */
4688 if (AOP_TYPE (right) == AOP_LIT)
4690 /* moving to accumulator first helps peepholes */
4691 MOVA (aopGet (left, 0, FALSE, FALSE));
4692 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4696 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4697 MOVA (aopGet (left, 0, FALSE, FALSE));
4700 emitcode ("mul", "ab");
4701 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4703 aopPut (result, "b", 1, isOperandVolatile (result, FALSE));
4709 /* we have to do a signed multiply */
4710 /* emitcode (";", "signed"); */
4712 /* now sign adjust for both left & right */
4714 /* let's see what's needed: */
4715 /* apply negative sign during runtime */
4716 runtimeSign = FALSE;
4717 /* negative sign from literals */
4718 compiletimeSign = FALSE;
4722 if (AOP_TYPE(left) == AOP_LIT)
4724 /* signed literal */
4725 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4727 compiletimeSign = TRUE;
4730 /* signed but not literal */
4736 if (AOP_TYPE(right) == AOP_LIT)
4738 /* signed literal */
4739 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4741 compiletimeSign ^= TRUE;
4744 /* signed but not literal */
4748 /* initialize F0, which stores the runtime sign */
4751 if (compiletimeSign)
4752 emitcode ("setb", "F0"); /* set sign flag */
4754 emitcode ("clr", "F0"); /* reset sign flag */
4757 /* save the signs of the operands */
4758 if (AOP_TYPE(right) == AOP_LIT)
4760 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4762 if (!rUnsigned && val < 0)
4763 emitcode ("mov", "b,#0x%02x", -val);
4765 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4767 else /* ! literal */
4769 if (rUnsigned) /* emitcode (";", "signed"); */
4771 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4774 MOVA (aopGet (right, 0, FALSE, FALSE));
4775 lbl = newiTempLabel (NULL);
4776 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4777 emitcode ("cpl", "F0"); /* complement sign flag */
4778 emitcode ("cpl", "a"); /* 2's complement */
4779 emitcode ("inc", "a");
4780 emitcode ("", "%05d$:", (lbl->key + 100));
4781 emitcode ("mov", "b,a");
4785 if (AOP_TYPE(left) == AOP_LIT)
4787 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4789 if (!lUnsigned && val < 0)
4790 emitcode ("mov", "a,#0x%02x", -val);
4792 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4794 else /* ! literal */
4796 MOVA (aopGet (left, 0, FALSE, FALSE));
4800 lbl = newiTempLabel (NULL);
4801 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4802 emitcode ("cpl", "F0"); /* complement sign flag */
4803 emitcode ("cpl", "a"); /* 2's complement */
4804 emitcode ("inc", "a");
4805 emitcode ("", "%05d$:", (lbl->key + 100));
4809 /* now the multiplication */
4810 emitcode ("mul", "ab");
4811 if (runtimeSign || compiletimeSign)
4813 lbl = newiTempLabel (NULL);
4815 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4816 emitcode ("cpl", "a"); /* lsb 2's complement */
4818 emitcode ("inc", "a"); /* inc doesn't set carry flag */
4821 emitcode ("add", "a,#1"); /* this sets carry flag */
4822 emitcode ("xch", "a,b");
4823 emitcode ("cpl", "a"); /* msb 2's complement */
4824 emitcode ("addc", "a,#0");
4825 emitcode ("xch", "a,b");
4827 emitcode ("", "%05d$:", (lbl->key + 100));
4829 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4831 aopPut (result, "b", 1, isOperandVolatile (result, FALSE));
4836 /*-----------------------------------------------------------------*/
4837 /* genMult - generates code for multiplication */
4838 /*-----------------------------------------------------------------*/
4840 genMult (iCode * ic)
4842 operand *left = IC_LEFT (ic);
4843 operand *right = IC_RIGHT (ic);
4844 operand *result = IC_RESULT (ic);
4846 D(emitcode ("; genMult",""));
4848 /* assign the amsops */
4849 aopOp (left, ic, FALSE);
4850 aopOp (right, ic, FALSE);
4851 aopOp (result, ic, TRUE);
4853 /* special cases first */
4855 if (AOP_TYPE (left) == AOP_CRY &&
4856 AOP_TYPE (right) == AOP_CRY)
4858 genMultbits (left, right, result);
4862 /* if both are of size == 1 */
4863 #if 0 // one of them can be a sloc shared with the result
4864 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
4866 if (getSize(operandType(left)) == 1 &&
4867 getSize(operandType(right)) == 1)
4870 genMultOneByte (left, right, result);
4874 /* should have been converted to function call */
4875 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
4876 getSize(OP_SYMBOL(right)->type));
4880 freeAsmop (result, NULL, ic, TRUE);
4881 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4882 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4885 /*-----------------------------------------------------------------*/
4886 /* genDivbits :- division of bits */
4887 /*-----------------------------------------------------------------*/
4889 genDivbits (operand * left,
4896 D(emitcode ("; genDivbits",""));
4900 /* the result must be bit */
4901 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4902 l = aopGet (left, 0, FALSE, FALSE);
4906 emitcode ("div", "ab");
4907 emitcode ("rrc", "a");
4911 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
4914 /*-----------------------------------------------------------------*/
4915 /* genDivOneByte : 8 bit division */
4916 /*-----------------------------------------------------------------*/
4918 genDivOneByte (operand * left,
4922 bool lUnsigned, rUnsigned, pushedB;
4923 bool runtimeSign, compiletimeSign;
4927 D(emitcode ("; genDivOneByte",""));
4929 /* Why is it necessary that genDivOneByte() can return an int result?
4932 volatile unsigned char uc;
4933 volatile signed char sc1, sc2;
4946 In all cases a one byte result would overflow, the following cast to int
4947 would return the wrong result.
4949 Two possible solution:
4950 a) cast operands to int, if ((unsigned) / (signed)) or
4951 ((signed) / (signed))
4952 b) return an 16 bit signed int; this is what we're doing here!
4955 size = AOP_SIZE (result) - 1;
4957 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4958 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4962 /* signed or unsigned */
4963 if (lUnsigned && rUnsigned)
4965 /* unsigned is easy */
4966 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4967 MOVA (aopGet (left, 0, FALSE, FALSE));
4968 emitcode ("div", "ab");
4969 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4971 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
4977 /* signed is a little bit more difficult */
4979 /* now sign adjust for both left & right */
4981 /* let's see what's needed: */
4982 /* apply negative sign during runtime */
4983 runtimeSign = FALSE;
4984 /* negative sign from literals */
4985 compiletimeSign = FALSE;
4989 if (AOP_TYPE(left) == AOP_LIT)
4991 /* signed literal */
4992 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4994 compiletimeSign = TRUE;
4997 /* signed but not literal */
5003 if (AOP_TYPE(right) == AOP_LIT)
5005 /* signed literal */
5006 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5008 compiletimeSign ^= TRUE;
5011 /* signed but not literal */
5015 /* initialize F0, which stores the runtime sign */
5018 if (compiletimeSign)
5019 emitcode ("setb", "F0"); /* set sign flag */
5021 emitcode ("clr", "F0"); /* reset sign flag */
5024 /* save the signs of the operands */
5025 if (AOP_TYPE(right) == AOP_LIT)
5027 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5029 if (!rUnsigned && val < 0)
5030 emitcode ("mov", "b,#0x%02x", -val);
5032 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5034 else /* ! literal */
5037 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5040 MOVA (aopGet (right, 0, FALSE, FALSE));
5041 lbl = newiTempLabel (NULL);
5042 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5043 emitcode ("cpl", "F0"); /* complement sign flag */
5044 emitcode ("cpl", "a"); /* 2's complement */
5045 emitcode ("inc", "a");
5046 emitcode ("", "%05d$:", (lbl->key + 100));
5047 emitcode ("mov", "b,a");
5051 if (AOP_TYPE(left) == AOP_LIT)
5053 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5055 if (!lUnsigned && val < 0)
5056 emitcode ("mov", "a,#0x%02x", -val);
5058 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5060 else /* ! literal */
5062 MOVA (aopGet (left, 0, FALSE, FALSE));
5066 lbl = newiTempLabel (NULL);
5067 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5068 emitcode ("cpl", "F0"); /* complement sign flag */
5069 emitcode ("cpl", "a"); /* 2's complement */
5070 emitcode ("inc", "a");
5071 emitcode ("", "%05d$:", (lbl->key + 100));
5075 /* now the division */
5076 emitcode ("div", "ab");
5078 if (runtimeSign || compiletimeSign)
5080 lbl = newiTempLabel (NULL);
5082 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5083 emitcode ("cpl", "a"); /* lsb 2's complement */
5084 emitcode ("inc", "a");
5085 emitcode ("", "%05d$:", (lbl->key + 100));
5087 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5090 /* msb is 0x00 or 0xff depending on the sign */
5093 emitcode ("mov", "c,F0");
5094 emitcode ("subb", "a,acc");
5096 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
5098 else /* compiletimeSign */
5100 aopPut (result, "#0xff", offset++, isOperandVolatile (result, FALSE));
5105 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5107 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5113 /*-----------------------------------------------------------------*/
5114 /* genDiv - generates code for division */
5115 /*-----------------------------------------------------------------*/
5119 operand *left = IC_LEFT (ic);
5120 operand *right = IC_RIGHT (ic);
5121 operand *result = IC_RESULT (ic);
5123 D(emitcode ("; genDiv",""));
5125 /* assign the amsops */
5126 aopOp (left, ic, FALSE);
5127 aopOp (right, ic, FALSE);
5128 aopOp (result, ic, TRUE);
5130 /* special cases first */
5132 if (AOP_TYPE (left) == AOP_CRY &&
5133 AOP_TYPE (right) == AOP_CRY)
5135 genDivbits (left, right, result);
5139 /* if both are of size == 1 */
5140 if (AOP_SIZE (left) == 1 &&
5141 AOP_SIZE (right) == 1)
5143 genDivOneByte (left, right, result);
5147 /* should have been converted to function call */
5150 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5151 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5152 freeAsmop (result, NULL, ic, TRUE);
5155 /*-----------------------------------------------------------------*/
5156 /* genModbits :- modulus of bits */
5157 /*-----------------------------------------------------------------*/
5159 genModbits (operand * left,
5166 D(emitcode ("; genModbits",""));
5170 /* the result must be bit */
5171 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5172 l = aopGet (left, 0, FALSE, FALSE);
5176 emitcode ("div", "ab");
5177 emitcode ("mov", "a,b");
5178 emitcode ("rrc", "a");
5182 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
5185 /*-----------------------------------------------------------------*/
5186 /* genModOneByte : 8 bit modulus */
5187 /*-----------------------------------------------------------------*/
5189 genModOneByte (operand * left,
5193 bool lUnsigned, rUnsigned, pushedB;
5194 bool runtimeSign, compiletimeSign;
5198 D(emitcode ("; genModOneByte",""));
5200 size = AOP_SIZE (result) - 1;
5202 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5203 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5205 /* if right is a literal, check it for 2^n */
5206 if (AOP_TYPE(right) == AOP_LIT)
5208 unsigned char val = abs((int) operandLitValue(right));
5209 symbol *lbl2 = NULL;
5213 case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5222 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5223 "modulus of unsigned char by 2^n literal shouldn't be processed here");
5224 /* because iCode should have been changed to genAnd */
5225 /* see file "SDCCopt.c", function "convertToFcall()" */
5227 MOVA (aopGet (left, 0, FALSE, FALSE));
5228 emitcode ("mov", "c,acc.7");
5229 emitcode ("anl", "a,#0x%02x", val - 1);
5230 lbl = newiTempLabel (NULL);
5231 emitcode ("jz", "%05d$", (lbl->key + 100));
5232 emitcode ("jnc", "%05d$", (lbl->key + 100));
5233 emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5239 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5241 aopPut (result, "#0xff", offs2++, isOperandVolatile (result, FALSE));
5242 lbl2 = newiTempLabel (NULL);
5243 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5245 emitcode ("", "%05d$:", (lbl->key + 100));
5246 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5248 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5251 emitcode ("", "%05d$:", (lbl2->key + 100));
5262 /* signed or unsigned */
5263 if (lUnsigned && rUnsigned)
5265 /* unsigned is easy */
5266 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5267 MOVA (aopGet (left, 0, FALSE, FALSE));
5268 emitcode ("div", "ab");
5269 aopPut (result, "b", 0, isOperandVolatile (result, FALSE));
5271 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5277 /* signed is a little bit more difficult */
5279 /* now sign adjust for both left & right */
5281 /* modulus: sign of the right operand has no influence on the result! */
5282 if (AOP_TYPE(right) == AOP_LIT)
5284 signed char val = (char) operandLitValue(right);
5286 if (!rUnsigned && val < 0)
5287 emitcode ("mov", "b,#0x%02x", -val);
5289 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5291 else /* not literal */
5294 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5297 MOVA (aopGet (right, 0, FALSE, FALSE));
5298 lbl = newiTempLabel (NULL);
5299 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5300 emitcode ("cpl", "a"); /* 2's complement */
5301 emitcode ("inc", "a");
5302 emitcode ("", "%05d$:", (lbl->key + 100));
5303 emitcode ("mov", "b,a");
5307 /* let's see what's needed: */
5308 /* apply negative sign during runtime */
5309 runtimeSign = FALSE;
5310 /* negative sign from literals */
5311 compiletimeSign = FALSE;
5313 /* sign adjust left side */
5314 if (AOP_TYPE(left) == AOP_LIT)
5316 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5318 if (!lUnsigned && val < 0)
5320 compiletimeSign = TRUE; /* set sign flag */
5321 emitcode ("mov", "a,#0x%02x", -val);
5324 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5326 else /* ! literal */
5328 MOVA (aopGet (left, 0, FALSE, FALSE));
5333 emitcode ("clr", "F0"); /* clear sign flag */
5335 lbl = newiTempLabel (NULL);
5336 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5337 emitcode ("setb", "F0"); /* set sign flag */
5338 emitcode ("cpl", "a"); /* 2's complement */
5339 emitcode ("inc", "a");
5340 emitcode ("", "%05d$:", (lbl->key + 100));
5344 /* now the modulus */
5345 emitcode ("div", "ab");
5347 if (runtimeSign || compiletimeSign)
5349 emitcode ("mov", "a,b");
5350 lbl = newiTempLabel (NULL);
5352 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5353 emitcode ("cpl", "a"); /* 2's complement */
5354 emitcode ("inc", "a");
5355 emitcode ("", "%05d$:", (lbl->key + 100));
5357 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5360 /* msb is 0x00 or 0xff depending on the sign */
5363 emitcode ("mov", "c,F0");
5364 emitcode ("subb", "a,acc");
5366 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
5368 else /* compiletimeSign */
5370 aopPut (result, "#0xff", offset++, isOperandVolatile (result, FALSE));
5375 aopPut (result, "b", 0, isOperandVolatile (result, FALSE));
5377 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5383 /*-----------------------------------------------------------------*/
5384 /* genMod - generates code for division */
5385 /*-----------------------------------------------------------------*/
5389 operand *left = IC_LEFT (ic);
5390 operand *right = IC_RIGHT (ic);
5391 operand *result = IC_RESULT (ic);
5393 D(emitcode ("; genMod",""));
5395 /* assign the asmops */
5396 aopOp (left, ic, FALSE);
5397 aopOp (right, ic, FALSE);
5398 aopOp (result, ic, TRUE);
5400 /* special cases first */
5402 if (AOP_TYPE (left) == AOP_CRY &&
5403 AOP_TYPE (right) == AOP_CRY)
5405 genModbits (left, right, result);
5409 /* if both are of size == 1 */
5410 if (AOP_SIZE (left) == 1 &&
5411 AOP_SIZE (right) == 1)
5413 genModOneByte (left, right, result);
5417 /* should have been converted to function call */
5421 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5422 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5423 freeAsmop (result, NULL, ic, TRUE);
5426 /*-----------------------------------------------------------------*/
5427 /* genIfxJump :- will create a jump depending on the ifx */
5428 /*-----------------------------------------------------------------*/
5430 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5433 symbol *tlbl = newiTempLabel (NULL);
5436 D(emitcode ("; genIfxJump",""));
5438 /* if true label then we jump if condition
5442 jlbl = IC_TRUE (ic);
5443 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5444 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5448 /* false label is present */
5449 jlbl = IC_FALSE (ic);
5450 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5451 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5453 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5454 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5456 emitcode (inst, "%05d$", tlbl->key + 100);
5457 freeForBranchAsmop (result);
5458 freeForBranchAsmop (right);
5459 freeForBranchAsmop (left);
5460 emitcode ("ljmp", "%05d$", jlbl->key + 100);
5461 emitcode ("", "%05d$:", tlbl->key + 100);
5463 /* mark the icode as generated */
5467 /*-----------------------------------------------------------------*/
5468 /* genCmp :- greater or less than comparison */
5469 /*-----------------------------------------------------------------*/
5471 genCmp (operand * left, operand * right,
5472 operand * result, iCode * ifx, int sign, iCode *ic)
5474 int size, offset = 0;
5475 unsigned long lit = 0L;
5478 D(emitcode ("; genCmp",""));
5480 /* if left & right are bit variables */
5481 if (AOP_TYPE (left) == AOP_CRY &&
5482 AOP_TYPE (right) == AOP_CRY)
5484 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5485 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5489 /* subtract right from left if at the
5490 end the carry flag is set then we know that
5491 left is greater than right */
5492 size = max (AOP_SIZE (left), AOP_SIZE (right));
5494 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5495 if ((size == 1) && !sign &&
5496 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5498 symbol *lbl = newiTempLabel (NULL);
5499 emitcode ("cjne", "%s,%s,%05d$",
5500 aopGet (left, offset, FALSE, FALSE),
5501 aopGet (right, offset, FALSE, FALSE),
5503 emitcode ("", "%05d$:", lbl->key + 100);
5507 if (AOP_TYPE (right) == AOP_LIT)
5509 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5510 /* optimize if(x < 0) or if(x >= 0) */
5519 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5520 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5522 genIfxJump (ifx, "acc.7", left, right, result);
5523 freeAsmop (right, NULL, ic, TRUE);
5524 freeAsmop (left, NULL, ic, TRUE);
5529 emitcode ("rlc", "a");
5537 bool pushedB = FALSE;
5538 rightInB = aopGetUsesAcc(right, offset);
5542 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5544 MOVA (aopGet (left, offset, FALSE, FALSE));
5545 if (sign && size == 0)
5547 emitcode ("xrl", "a,#0x80");
5548 if (AOP_TYPE (right) == AOP_LIT)
5550 unsigned long lit = (unsigned long)
5551 floatFromVal (AOP (right)->aopu.aop_lit);
5552 emitcode ("subb", "a,#0x%02x",
5553 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5561 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5563 emitcode ("xrl", "b,#0x80");
5564 emitcode ("subb", "a,b");
5570 emitcode ("subb", "a,b");
5572 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5582 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5583 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5584 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5590 /* if the result is used in the next
5591 ifx conditional branch then generate
5592 code a little differently */
5594 genIfxJump (ifx, "c", NULL, NULL, result);
5597 /* leave the result in acc */
5601 /*-----------------------------------------------------------------*/
5602 /* genCmpGt :- greater than comparison */
5603 /*-----------------------------------------------------------------*/
5605 genCmpGt (iCode * ic, iCode * ifx)
5607 operand *left, *right, *result;
5608 sym_link *letype, *retype;
5611 D(emitcode ("; genCmpGt",""));
5613 left = IC_LEFT (ic);
5614 right = IC_RIGHT (ic);
5615 result = IC_RESULT (ic);
5617 letype = getSpec (operandType (left));
5618 retype = getSpec (operandType (right));
5619 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5620 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5621 /* assign the amsops */
5622 aopOp (left, ic, FALSE);
5623 aopOp (right, ic, FALSE);
5624 aopOp (result, ic, TRUE);
5626 genCmp (right, left, result, ifx, sign, ic);
5628 freeAsmop (result, NULL, ic, TRUE);
5631 /*-----------------------------------------------------------------*/
5632 /* genCmpLt - less than comparisons */
5633 /*-----------------------------------------------------------------*/
5635 genCmpLt (iCode * ic, iCode * ifx)
5637 operand *left, *right, *result;
5638 sym_link *letype, *retype;
5641 D(emitcode ("; genCmpLt",""));
5643 left = IC_LEFT (ic);
5644 right = IC_RIGHT (ic);
5645 result = IC_RESULT (ic);
5647 letype = getSpec (operandType (left));
5648 retype = getSpec (operandType (right));
5649 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5650 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5651 /* assign the amsops */
5652 aopOp (left, ic, FALSE);
5653 aopOp (right, ic, FALSE);
5654 aopOp (result, ic, TRUE);
5656 genCmp (left, right, result, ifx, sign, ic);
5658 freeAsmop (result, NULL, ic, TRUE);
5661 /*-----------------------------------------------------------------*/
5662 /* gencjneshort - compare and jump if not equal */
5663 /*-----------------------------------------------------------------*/
5665 gencjneshort (operand * left, operand * right, symbol * lbl)
5667 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5669 unsigned long lit = 0L;
5671 /* if the left side is a literal or
5672 if the right is in a pointer register and left
5674 if ((AOP_TYPE (left) == AOP_LIT) ||
5675 (AOP_TYPE (left) == AOP_IMMD) ||
5676 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5683 if (AOP_TYPE (right) == AOP_LIT)
5684 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5686 /* if the right side is a literal then anything goes */
5687 if (AOP_TYPE (right) == AOP_LIT &&
5688 AOP_TYPE (left) != AOP_DIR &&
5689 AOP_TYPE (left) != AOP_IMMD)
5693 emitcode ("cjne", "%s,%s,%05d$",
5694 aopGet (left, offset, FALSE, FALSE),
5695 aopGet (right, offset, FALSE, FALSE),
5701 /* if the right side is in a register or in direct space or
5702 if the left is a pointer register & right is not */
5703 else if (AOP_TYPE (right) == AOP_REG ||
5704 AOP_TYPE (right) == AOP_DIR ||
5705 AOP_TYPE (right) == AOP_LIT ||
5706 AOP_TYPE (right) == AOP_IMMD ||
5707 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5708 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5712 MOVA (aopGet (left, offset, FALSE, FALSE));
5713 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5714 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5715 emitcode ("jnz", "%05d$", lbl->key + 100);
5717 emitcode ("cjne", "a,%s,%05d$",
5718 aopGet (right, offset, FALSE, TRUE),
5725 /* right is a pointer reg need both a & b */
5729 //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
5730 wassertl(!BINUSE, "B was in use");
5731 l = aopGet (left, offset, FALSE, FALSE);
5732 if (strcmp (l, "b"))
5733 emitcode ("mov", "b,%s", l);
5734 MOVA (aopGet (right, offset, FALSE, FALSE));
5735 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5741 /*-----------------------------------------------------------------*/
5742 /* gencjne - compare and jump if not equal */
5743 /*-----------------------------------------------------------------*/
5745 gencjne (operand * left, operand * right, symbol * lbl)
5747 symbol *tlbl = newiTempLabel (NULL);
5749 gencjneshort (left, right, lbl);
5751 emitcode ("mov", "a,%s", one);
5752 emitcode ("sjmp", "%05d$", tlbl->key + 100);
5753 emitcode ("", "%05d$:", lbl->key + 100);
5754 emitcode ("clr", "a");
5755 emitcode ("", "%05d$:", tlbl->key + 100);
5758 /*-----------------------------------------------------------------*/
5759 /* genCmpEq - generates code for equal to */
5760 /*-----------------------------------------------------------------*/
5762 genCmpEq (iCode * ic, iCode * ifx)
5764 operand *left, *right, *result;
5766 D(emitcode ("; genCmpEq",""));
5768 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5769 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5770 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5772 /* if literal, literal on the right or
5773 if the right is in a pointer register and left
5775 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5776 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5778 operand *t = IC_RIGHT (ic);
5779 IC_RIGHT (ic) = IC_LEFT (ic);
5783 if (ifx && !AOP_SIZE (result))
5786 /* if they are both bit variables */
5787 if (AOP_TYPE (left) == AOP_CRY &&
5788 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5790 if (AOP_TYPE (right) == AOP_LIT)
5792 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5795 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5796 emitcode ("cpl", "c");
5800 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5804 emitcode ("clr", "c");
5806 /* AOP_TYPE(right) == AOP_CRY */
5810 symbol *lbl = newiTempLabel (NULL);
5811 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5812 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5813 emitcode ("cpl", "c");
5814 emitcode ("", "%05d$:", (lbl->key + 100));
5816 /* if true label then we jump if condition
5818 tlbl = newiTempLabel (NULL);
5821 emitcode ("jnc", "%05d$", tlbl->key + 100);
5822 freeForBranchAsmop (result);
5823 freeForBranchAsmop (right);
5824 freeForBranchAsmop (left);
5825 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5829 emitcode ("jc", "%05d$", tlbl->key + 100);
5830 freeForBranchAsmop (result);
5831 freeForBranchAsmop (right);
5832 freeForBranchAsmop (left);
5833 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5835 emitcode ("", "%05d$:", tlbl->key + 100);
5839 tlbl = newiTempLabel (NULL);
5840 gencjneshort (left, right, tlbl);
5843 freeForBranchAsmop (result);
5844 freeForBranchAsmop (right);
5845 freeForBranchAsmop (left);
5846 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5847 emitcode ("", "%05d$:", tlbl->key + 100);
5851 symbol *lbl = newiTempLabel (NULL);
5852 emitcode ("sjmp", "%05d$", lbl->key + 100);
5853 emitcode ("", "%05d$:", tlbl->key + 100);
5854 freeForBranchAsmop (result);
5855 freeForBranchAsmop (right);
5856 freeForBranchAsmop (left);
5857 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5858 emitcode ("", "%05d$:", lbl->key + 100);
5861 /* mark the icode as generated */
5866 /* if they are both bit variables */
5867 if (AOP_TYPE (left) == AOP_CRY &&
5868 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5870 if (AOP_TYPE (right) == AOP_LIT)
5872 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5875 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5876 emitcode ("cpl", "c");
5880 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5884 emitcode ("clr", "c");
5886 /* AOP_TYPE(right) == AOP_CRY */
5890 symbol *lbl = newiTempLabel (NULL);
5891 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5892 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5893 emitcode ("cpl", "c");
5894 emitcode ("", "%05d$:", (lbl->key + 100));
5897 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5904 genIfxJump (ifx, "c", left, right, result);
5907 /* if the result is used in an arithmetic operation
5908 then put the result in place */
5913 gencjne (left, right, newiTempLabel (NULL));
5914 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5916 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5921 genIfxJump (ifx, "a", left, right, result);
5924 /* if the result is used in an arithmetic operation
5925 then put the result in place */
5926 if (AOP_TYPE (result) != AOP_CRY)
5928 /* leave the result in acc */
5932 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5933 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5934 freeAsmop (result, NULL, ic, TRUE);
5937 /*-----------------------------------------------------------------*/
5938 /* ifxForOp - returns the icode containing the ifx for operand */
5939 /*-----------------------------------------------------------------*/
5941 ifxForOp (operand * op, iCode * ic)
5943 /* if true symbol then needs to be assigned */
5944 if (IS_TRUE_SYMOP (op))
5947 /* if this has register type condition and
5948 the next instruction is ifx with the same operand
5949 and live to of the operand is upto the ifx only then */
5951 ic->next->op == IFX &&
5952 IC_COND (ic->next)->key == op->key &&
5953 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5959 /*-----------------------------------------------------------------*/
5960 /* hasInc - operand is incremented before any other use */
5961 /*-----------------------------------------------------------------*/
5963 hasInc (operand *op, iCode *ic,int osize)
5965 sym_link *type = operandType(op);
5966 sym_link *retype = getSpec (type);
5967 iCode *lic = ic->next;
5970 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5971 if (!IS_SYMOP(op)) return NULL;
5973 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5974 if (IS_AGGREGATE(type->next)) return NULL;
5975 if (osize != (isize = getSize(type->next))) return NULL;
5978 /* if operand of the form op = op + <sizeof *op> */
5979 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5980 isOperandEqual(IC_RESULT(lic),op) &&
5981 isOperandLiteral(IC_RIGHT(lic)) &&
5982 operandLitValue(IC_RIGHT(lic)) == isize) {
5985 /* if the operand used or deffed */
5986 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
5989 /* if GOTO or IFX */
5990 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5996 /*-----------------------------------------------------------------*/
5997 /* genAndOp - for && operation */
5998 /*-----------------------------------------------------------------*/
6000 genAndOp (iCode * ic)
6002 operand *left, *right, *result;
6005 D(emitcode ("; genAndOp",""));
6007 /* note here that && operations that are in an
6008 if statement are taken away by backPatchLabels
6009 only those used in arthmetic operations remain */
6010 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6011 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6012 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6014 /* if both are bit variables */
6015 if (AOP_TYPE (left) == AOP_CRY &&
6016 AOP_TYPE (right) == AOP_CRY)
6018 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6019 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6024 tlbl = newiTempLabel (NULL);
6026 emitcode ("jz", "%05d$", tlbl->key + 100);
6028 emitcode ("", "%05d$:", tlbl->key + 100);
6032 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6033 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6034 freeAsmop (result, NULL, ic, TRUE);
6038 /*-----------------------------------------------------------------*/
6039 /* genOrOp - for || operation */
6040 /*-----------------------------------------------------------------*/
6042 genOrOp (iCode * ic)
6044 operand *left, *right, *result;
6047 D(emitcode ("; genOrOp",""));
6049 /* note here that || operations that are in an
6050 if statement are taken away by backPatchLabels
6051 only those used in arthmetic operations remain */
6052 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6053 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6054 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6056 /* if both are bit variables */
6057 if (AOP_TYPE (left) == AOP_CRY &&
6058 AOP_TYPE (right) == AOP_CRY)
6060 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6061 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6066 tlbl = newiTempLabel (NULL);
6068 emitcode ("jnz", "%05d$", tlbl->key + 100);
6070 emitcode ("", "%05d$:", tlbl->key + 100);
6074 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6075 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6076 freeAsmop (result, NULL, ic, TRUE);
6079 /*-----------------------------------------------------------------*/
6080 /* isLiteralBit - test if lit == 2^n */
6081 /*-----------------------------------------------------------------*/
6083 isLiteralBit (unsigned long lit)
6085 unsigned long pw[32] =
6086 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6087 0x100L, 0x200L, 0x400L, 0x800L,
6088 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6089 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6090 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6091 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6092 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6095 for (idx = 0; idx < 32; idx++)
6101 /*-----------------------------------------------------------------*/
6102 /* continueIfTrue - */
6103 /*-----------------------------------------------------------------*/
6105 continueIfTrue (iCode * ic)
6108 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6112 /*-----------------------------------------------------------------*/
6114 /*-----------------------------------------------------------------*/
6116 jumpIfTrue (iCode * ic)
6119 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6123 /*-----------------------------------------------------------------*/
6124 /* jmpTrueOrFalse - */
6125 /*-----------------------------------------------------------------*/
6127 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6129 // ugly but optimized by peephole
6132 symbol *nlbl = newiTempLabel (NULL);
6133 emitcode ("sjmp", "%05d$", nlbl->key + 100);
6134 emitcode ("", "%05d$:", tlbl->key + 100);
6135 freeForBranchAsmop (result);
6136 freeForBranchAsmop (right);
6137 freeForBranchAsmop (left);
6138 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6139 emitcode ("", "%05d$:", nlbl->key + 100);
6143 freeForBranchAsmop (result);
6144 freeForBranchAsmop (right);
6145 freeForBranchAsmop (left);
6146 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6147 emitcode ("", "%05d$:", tlbl->key + 100);
6152 /*-----------------------------------------------------------------*/
6153 /* genAnd - code for and */
6154 /*-----------------------------------------------------------------*/
6156 genAnd (iCode * ic, iCode * ifx)
6158 operand *left, *right, *result;
6159 int size, offset = 0;
6160 unsigned long lit = 0L;
6164 D(emitcode ("; genAnd",""));
6166 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6167 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6168 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6171 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6173 AOP_TYPE (left), AOP_TYPE (right));
6174 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6176 AOP_SIZE (left), AOP_SIZE (right));
6179 /* if left is a literal & right is not then exchange them */
6180 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6181 AOP_NEEDSACC (left))
6183 operand *tmp = right;
6188 /* if result = right then exchange left and right */
6189 if (sameRegs (AOP (result), AOP (right)))
6191 operand *tmp = right;
6196 /* if right is bit then exchange them */
6197 if (AOP_TYPE (right) == AOP_CRY &&
6198 AOP_TYPE (left) != AOP_CRY)
6200 operand *tmp = right;
6204 if (AOP_TYPE (right) == AOP_LIT)
6205 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6207 size = AOP_SIZE (result);
6210 // result = bit & yy;
6211 if (AOP_TYPE (left) == AOP_CRY)
6213 // c = bit & literal;
6214 if (AOP_TYPE (right) == AOP_LIT)
6218 if (size && sameRegs (AOP (result), AOP (left)))
6221 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6226 if (size && (AOP_TYPE (result) == AOP_CRY))
6228 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6231 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6236 emitcode ("clr", "c");
6241 if (AOP_TYPE (right) == AOP_CRY)
6244 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6245 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6250 MOVA (aopGet (right, 0, FALSE, FALSE));
6252 emitcode ("rrc", "a");
6253 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6261 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6262 genIfxJump (ifx, "c", left, right, result);
6266 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6267 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6268 if ((AOP_TYPE (right) == AOP_LIT) &&
6269 (AOP_TYPE (result) == AOP_CRY) &&
6270 (AOP_TYPE (left) != AOP_CRY))
6272 int posbit = isLiteralBit (lit);
6277 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6281 switch (posbit & 0x07)
6283 case 0: emitcode ("rrc", "a");
6285 case 7: emitcode ("rlc", "a");
6287 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6296 SNPRINTF (buffer, sizeof(buffer),
6297 "acc.%d", posbit & 0x07);
6298 genIfxJump (ifx, buffer, left, right, result);
6301 {// what is this case? just found it in ds390/gen.c
6302 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6309 symbol *tlbl = newiTempLabel (NULL);
6310 int sizel = AOP_SIZE (left);
6312 emitcode ("setb", "c");
6315 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6317 MOVA (aopGet (left, offset, FALSE, FALSE));
6319 if ((posbit = isLiteralBit (bytelit)) != 0)
6320 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6323 if (bytelit != 0x0FFL)
6324 emitcode ("anl", "a,%s",
6325 aopGet (right, offset, FALSE, TRUE));
6326 emitcode ("jnz", "%05d$", tlbl->key + 100);
6331 // bit = left & literal
6334 emitcode ("clr", "c");
6335 emitcode ("", "%05d$:", tlbl->key + 100);
6337 // if(left & literal)
6341 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6343 emitcode ("", "%05d$:", tlbl->key + 100);
6351 /* if left is same as result */
6352 if (sameRegs (AOP (result), AOP (left)))
6354 for (; size--; offset++)
6356 if (AOP_TYPE (right) == AOP_LIT)
6358 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6359 if (bytelit == 0x0FF)
6361 /* dummy read of volatile operand */
6362 if (isOperandVolatile (left, FALSE))
6363 MOVA (aopGet (left, offset, FALSE, FALSE));
6367 else if (bytelit == 0)
6369 aopPut (result, zero, offset, isOperandVolatile (result, FALSE));
6371 else if (IS_AOP_PREG (result))
6373 MOVA (aopGet (left, offset, FALSE, TRUE));
6374 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6375 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6378 emitcode ("anl", "%s,%s",
6379 aopGet (left, offset, FALSE, TRUE),
6380 aopGet (right, offset, FALSE, FALSE));
6384 if (AOP_TYPE (left) == AOP_ACC && offset == 0)
6386 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6390 MOVA (aopGet (right, offset, FALSE, FALSE));
6391 if (IS_AOP_PREG (result))
6393 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6394 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6397 emitcode ("anl", "%s,a",
6398 aopGet (left, offset, FALSE, TRUE));
6405 // left & result in different registers
6406 if (AOP_TYPE (result) == AOP_CRY)
6409 // if(size), result in bit
6410 // if(!size && ifx), conditional oper: if(left & right)
6411 symbol *tlbl = newiTempLabel (NULL);
6412 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6414 emitcode ("setb", "c");
6417 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6418 && AOP_TYPE(left)==AOP_ACC)
6421 emitcode("mov", "a,b");
6422 emitcode ("anl", "a,%s",
6423 aopGet (right, offset, FALSE, FALSE));
6425 if (AOP_TYPE(left)==AOP_ACC)
6429 bool pushedB = pushB ();
6430 emitcode("mov", "b,a");
6431 MOVA (aopGet (right, offset, FALSE, FALSE));
6432 emitcode("anl", "a,b");
6437 MOVA (aopGet (right, offset, FALSE, FALSE));
6438 emitcode("anl", "a,b");
6441 MOVA (aopGet (right, offset, FALSE, FALSE));
6442 emitcode ("anl", "a,%s",
6443 aopGet (left, offset, FALSE, FALSE));
6446 emitcode ("jnz", "%05d$", tlbl->key + 100);
6452 emitcode ("", "%05d$:", tlbl->key + 100);
6456 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6458 emitcode ("", "%05d$:", tlbl->key + 100);
6462 for (; (size--); offset++)
6465 // result = left & right
6466 if (AOP_TYPE (right) == AOP_LIT)
6468 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6469 if (bytelit == 0x0FF)
6472 aopGet (left, offset, FALSE, FALSE),
6474 isOperandVolatile (result, FALSE));
6477 else if (bytelit == 0)
6479 /* dummy read of volatile operand */
6480 if (isOperandVolatile (left, FALSE))
6481 MOVA (aopGet (left, offset, FALSE, FALSE));
6482 aopPut (result, zero, offset, isOperandVolatile (result, FALSE));
6485 else if (AOP_TYPE (left) == AOP_ACC)
6489 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6490 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6495 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6496 aopPut (result, "b", offset, isOperandVolatile (result, FALSE));
6501 // faster than result <- left, anl result,right
6502 // and better if result is SFR
6503 if (AOP_TYPE (left) == AOP_ACC)
6506 emitcode("mov", "a,b");
6507 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6511 MOVA (aopGet (right, offset, FALSE, FALSE));
6512 emitcode ("anl", "a,%s",
6513 aopGet (left, offset, FALSE, FALSE));
6515 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6521 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6522 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6523 freeAsmop (result, NULL, ic, TRUE);
6526 /*-----------------------------------------------------------------*/
6527 /* genOr - code for or */
6528 /*-----------------------------------------------------------------*/
6530 genOr (iCode * ic, iCode * ifx)
6532 operand *left, *right, *result;
6533 int size, offset = 0;
6534 unsigned long lit = 0L;
6537 D(emitcode ("; genOr",""));
6539 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6540 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6541 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6544 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6546 AOP_TYPE (left), AOP_TYPE (right));
6547 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6549 AOP_SIZE (left), AOP_SIZE (right));
6552 /* if left is a literal & right is not then exchange them */
6553 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6554 AOP_NEEDSACC (left))
6556 operand *tmp = right;
6561 /* if result = right then exchange them */
6562 if (sameRegs (AOP (result), AOP (right)))
6564 operand *tmp = right;
6569 /* if right is bit then exchange them */
6570 if (AOP_TYPE (right) == AOP_CRY &&
6571 AOP_TYPE (left) != AOP_CRY)
6573 operand *tmp = right;
6577 if (AOP_TYPE (right) == AOP_LIT)
6578 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6580 size = AOP_SIZE (result);
6584 if (AOP_TYPE (left) == AOP_CRY)
6586 if (AOP_TYPE (right) == AOP_LIT)
6588 // c = bit | literal;
6591 // lit != 0 => result = 1
6592 if (AOP_TYPE (result) == AOP_CRY)
6595 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6597 continueIfTrue (ifx);
6600 emitcode ("setb", "c");
6604 // lit == 0 => result = left
6605 if (size && sameRegs (AOP (result), AOP (left)))
6607 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6612 if (AOP_TYPE (right) == AOP_CRY)
6615 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6616 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6621 symbol *tlbl = newiTempLabel (NULL);
6622 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6623 emitcode ("setb", "c");
6624 emitcode ("jb", "%s,%05d$",
6625 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6627 emitcode ("jnz", "%05d$", tlbl->key + 100);
6628 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6630 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6636 emitcode ("", "%05d$:", tlbl->key + 100);
6645 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6646 genIfxJump (ifx, "c", left, right, result);
6650 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6651 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6652 if ((AOP_TYPE (right) == AOP_LIT) &&
6653 (AOP_TYPE (result) == AOP_CRY) &&
6654 (AOP_TYPE (left) != AOP_CRY))
6660 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6662 continueIfTrue (ifx);
6667 // lit = 0, result = boolean(left)
6669 emitcode ("setb", "c");
6673 symbol *tlbl = newiTempLabel (NULL);
6674 emitcode ("jnz", "%05d$", tlbl->key + 100);
6676 emitcode ("", "%05d$:", tlbl->key + 100);
6680 genIfxJump (ifx, "a", left, right, result);
6688 /* if left is same as result */
6689 if (sameRegs (AOP (result), AOP (left)))
6691 for (; size--; offset++)
6693 if (AOP_TYPE (right) == AOP_LIT)
6695 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6698 /* dummy read of volatile operand */
6699 if (isOperandVolatile (left, FALSE))
6700 MOVA (aopGet (left, offset, FALSE, FALSE));
6704 else if (bytelit == 0x0FF)
6706 aopPut (result, "#0xFF", offset, isOperandVolatile (result, FALSE));
6708 else if (IS_AOP_PREG (left))
6710 MOVA (aopGet (left, offset, FALSE, TRUE));
6711 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6712 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6716 emitcode ("orl", "%s,%s",
6717 aopGet (left, offset, FALSE, TRUE),
6718 aopGet (right, offset, FALSE, FALSE));
6723 if (AOP_TYPE (left) == AOP_ACC)
6726 emitcode("mov", "a,b");
6727 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6731 MOVA (aopGet (right, offset, FALSE, FALSE));
6732 if (IS_AOP_PREG (left))
6734 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6735 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6739 emitcode ("orl", "%s,a",
6740 aopGet (left, offset, FALSE, TRUE));
6748 // left & result in different registers
6749 if (AOP_TYPE (result) == AOP_CRY)
6752 // if(size), result in bit
6753 // if(!size && ifx), conditional oper: if(left | right)
6754 symbol *tlbl = newiTempLabel (NULL);
6755 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6757 emitcode ("setb", "c");
6760 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6762 emitcode("mov", "a,b");
6763 emitcode ("orl", "a,%s",
6764 aopGet (right, offset, FALSE, FALSE));
6766 MOVA (aopGet (right, offset, FALSE, FALSE));
6767 emitcode ("orl", "a,%s",
6768 aopGet (left, offset, FALSE, FALSE));
6770 emitcode ("jnz", "%05d$", tlbl->key + 100);
6776 emitcode ("", "%05d$:", tlbl->key + 100);
6780 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6782 emitcode ("", "%05d$:", tlbl->key + 100);
6786 for (; (size--); offset++)
6789 // result = left | right
6790 if (AOP_TYPE (right) == AOP_LIT)
6792 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6796 aopGet (left, offset, FALSE, FALSE),
6798 isOperandVolatile (result, FALSE));
6801 else if (bytelit == 0x0FF)
6803 /* dummy read of volatile operand */
6804 if (isOperandVolatile (left, FALSE))
6805 MOVA (aopGet (left, offset, FALSE, FALSE));
6806 aopPut (result, "#0xFF", offset, isOperandVolatile (result, FALSE));
6810 // faster than result <- left, anl result,right
6811 // and better if result is SFR
6812 if (AOP_TYPE (left) == AOP_ACC)
6815 emitcode("mov", "a,b");
6816 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6820 MOVA (aopGet (right, offset, FALSE, FALSE));
6821 emitcode ("orl", "a,%s",
6822 aopGet (left, offset, FALSE, FALSE));
6824 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6830 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6831 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6832 freeAsmop (result, NULL, ic, TRUE);
6835 /*-----------------------------------------------------------------*/
6836 /* genXor - code for xclusive or */
6837 /*-----------------------------------------------------------------*/
6839 genXor (iCode * ic, iCode * ifx)
6841 operand *left, *right, *result;
6842 int size, offset = 0;
6843 unsigned long lit = 0L;
6846 D(emitcode ("; genXor",""));
6848 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6849 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6850 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6853 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6855 AOP_TYPE (left), AOP_TYPE (right));
6856 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6858 AOP_SIZE (left), AOP_SIZE (right));
6861 /* if left is a literal & right is not ||
6862 if left needs acc & right does not */
6863 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6864 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
6866 operand *tmp = right;
6871 /* if result = right then exchange them */
6872 if (sameRegs (AOP (result), AOP (right)))
6874 operand *tmp = right;
6879 /* if right is bit then exchange them */
6880 if (AOP_TYPE (right) == AOP_CRY &&
6881 AOP_TYPE (left) != AOP_CRY)
6883 operand *tmp = right;
6887 if (AOP_TYPE (right) == AOP_LIT)
6888 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6890 size = AOP_SIZE (result);
6894 if (AOP_TYPE (left) == AOP_CRY)
6896 if (AOP_TYPE (right) == AOP_LIT)
6898 // c = bit & literal;
6901 // lit>>1 != 0 => result = 1
6902 if (AOP_TYPE (result) == AOP_CRY)
6905 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6907 continueIfTrue (ifx);
6910 emitcode ("setb", "c");
6917 // lit == 0, result = left
6918 if (size && sameRegs (AOP (result), AOP (left)))
6920 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6924 // lit == 1, result = not(left)
6925 if (size && sameRegs (AOP (result), AOP (left)))
6927 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6932 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6933 emitcode ("cpl", "c");
6942 symbol *tlbl = newiTempLabel (NULL);
6943 if (AOP_TYPE (right) == AOP_CRY)
6946 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6950 int sizer = AOP_SIZE (right);
6952 // if val>>1 != 0, result = 1
6953 emitcode ("setb", "c");
6956 MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
6958 // test the msb of the lsb
6959 emitcode ("anl", "a,#0xfe");
6960 emitcode ("jnz", "%05d$", tlbl->key + 100);
6964 emitcode ("rrc", "a");
6966 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6967 emitcode ("cpl", "c");
6968 emitcode ("", "%05d$:", (tlbl->key + 100));
6975 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6976 genIfxJump (ifx, "c", left, right, result);
6980 /* if left is same as result */
6981 if (sameRegs (AOP (result), AOP (left)))
6983 for (; size--; offset++)
6985 if (AOP_TYPE (right) == AOP_LIT)
6987 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6990 /* dummy read of volatile operand */
6991 if (isOperandVolatile (left, FALSE))
6992 MOVA (aopGet (left, offset, FALSE, FALSE));
6996 else if (IS_AOP_PREG (left))
6998 MOVA (aopGet (left, offset, FALSE, TRUE));
6999 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7000 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7004 emitcode ("xrl", "%s,%s",
7005 aopGet (left, offset, FALSE, TRUE),
7006 aopGet (right, offset, FALSE, FALSE));
7011 if (AOP_TYPE (left) == AOP_ACC)
7014 emitcode("mov", "a,b");
7015 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7019 MOVA (aopGet (right, offset, FALSE, FALSE));
7020 if (IS_AOP_PREG (left))
7022 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7023 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7026 emitcode ("xrl", "%s,a",
7027 aopGet (left, offset, FALSE, TRUE));
7034 // left & result in different registers
7035 if (AOP_TYPE (result) == AOP_CRY)
7038 // if(size), result in bit
7039 // if(!size && ifx), conditional oper: if(left ^ right)
7040 symbol *tlbl = newiTempLabel (NULL);
7041 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7043 emitcode ("setb", "c");
7046 if ((AOP_TYPE (right) == AOP_LIT) &&
7047 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7049 MOVA (aopGet (left, offset, FALSE, FALSE));
7053 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7055 emitcode("mov", "a,b");
7056 emitcode ("xrl", "a,%s",
7057 aopGet (right, offset, FALSE, FALSE));
7059 MOVA (aopGet (right, offset, FALSE, FALSE));
7060 emitcode ("xrl", "a,%s",
7061 aopGet (left, offset, FALSE, FALSE));
7064 emitcode ("jnz", "%05d$", tlbl->key + 100);
7070 emitcode ("", "%05d$:", tlbl->key + 100);
7074 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7078 for (; (size--); offset++)
7081 // result = left & right
7082 if (AOP_TYPE (right) == AOP_LIT)
7084 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7088 aopGet (left, offset, FALSE, FALSE),
7090 isOperandVolatile (result, FALSE));
7094 // faster than result <- left, anl result,right
7095 // and better if result is SFR
7096 if (AOP_TYPE (left) == AOP_ACC)
7099 emitcode("mov", "a,b");
7100 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7104 MOVA (aopGet (right, offset, FALSE, FALSE));
7105 emitcode ("xrl", "a,%s",
7106 aopGet (left, offset, FALSE, TRUE));
7108 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7114 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7115 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7116 freeAsmop (result, NULL, ic, TRUE);
7119 /*-----------------------------------------------------------------*/
7120 /* genInline - write the inline code out */
7121 /*-----------------------------------------------------------------*/
7123 genInline (iCode * ic)
7125 char *buffer, *bp, *bp1;
7127 D(emitcode ("; genInline",""));
7129 _G.inLine += (!options.asmpeep);
7131 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
7132 strcpy (buffer, IC_INLINE (ic));
7134 /* emit each line as a code */
7145 /* Add \n for labels, not dirs such as c:\mydir */
7146 if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
7160 /* emitcode("",buffer); */
7161 _G.inLine -= (!options.asmpeep);
7164 /*-----------------------------------------------------------------*/
7165 /* genRRC - rotate right with carry */
7166 /*-----------------------------------------------------------------*/
7170 operand *left, *result;
7171 int size, offset = 0;
7174 D(emitcode ("; genRRC",""));
7176 /* rotate right with carry */
7177 left = IC_LEFT (ic);
7178 result = IC_RESULT (ic);
7179 aopOp (left, ic, FALSE);
7180 aopOp (result, ic, FALSE);
7182 /* move it to the result */
7183 size = AOP_SIZE (result);
7185 if (size == 1) { /* special case for 1 byte */
7186 l = aopGet (left, offset, FALSE, FALSE);
7188 emitcode ("rr", "a");
7191 /* no need to clear carry, bit7 will be written later */
7194 l = aopGet (left, offset, FALSE, FALSE);
7196 emitcode ("rrc", "a");
7197 if (AOP_SIZE (result) > 1)
7198 aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
7200 /* now we need to put the carry into the
7201 highest order byte of the result */
7202 if (AOP_SIZE (result) > 1)
7204 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7207 emitcode ("mov", "acc.7,c");
7209 aopPut (result, "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
7210 freeAsmop (left, NULL, ic, TRUE);
7211 freeAsmop (result, NULL, ic, TRUE);
7214 /*-----------------------------------------------------------------*/
7215 /* genRLC - generate code for rotate left with carry */
7216 /*-----------------------------------------------------------------*/
7220 operand *left, *result;
7221 int size, offset = 0;
7224 D(emitcode ("; genRLC",""));
7226 /* rotate right with carry */
7227 left = IC_LEFT (ic);
7228 result = IC_RESULT (ic);
7229 aopOp (left, ic, FALSE);
7230 aopOp (result, ic, FALSE);
7232 /* move it to the result */
7233 size = AOP_SIZE (result);
7237 l = aopGet (left, offset, FALSE, FALSE);
7239 if (size == 0) { /* special case for 1 byte */
7243 emitcode("rlc","a"); /* bit0 will be written later */
7244 if (AOP_SIZE (result) > 1)
7245 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
7248 l = aopGet (left, offset, FALSE, FALSE);
7250 emitcode ("rlc", "a");
7251 if (AOP_SIZE (result) > 1)
7252 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
7255 /* now we need to put the carry into the
7256 highest order byte of the result */
7257 if (AOP_SIZE (result) > 1)
7259 l = aopGet (result, 0, FALSE, FALSE);
7262 emitcode ("mov", "acc.0,c");
7264 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
7265 freeAsmop (left, NULL, ic, TRUE);
7266 freeAsmop (result, NULL, ic, TRUE);
7269 /*-----------------------------------------------------------------*/
7270 /* genGetHbit - generates code get highest order bit */
7271 /*-----------------------------------------------------------------*/
7273 genGetHbit (iCode * ic)
7275 operand *left, *result;
7277 D(emitcode ("; genGetHbit",""));
7279 left = IC_LEFT (ic);
7280 result = IC_RESULT (ic);
7281 aopOp (left, ic, FALSE);
7282 aopOp (result, ic, FALSE);
7284 /* get the highest order byte into a */
7285 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7286 if (AOP_TYPE (result) == AOP_CRY)
7288 emitcode ("rlc", "a");
7293 emitcode ("rl", "a");
7294 emitcode ("anl", "a,#0x01");
7299 freeAsmop (left, NULL, ic, TRUE);
7300 freeAsmop (result, NULL, ic, TRUE);
7303 /*-----------------------------------------------------------------*/
7304 /* genGetAbit - generates code get a single bit */
7305 /*-----------------------------------------------------------------*/
7307 genGetAbit (iCode * ic)
7309 operand *left, *right, *result;
7312 D(emitcode ("; genGetAbit",""));
7314 left = IC_LEFT (ic);
7315 right = IC_RIGHT (ic);
7316 result = IC_RESULT (ic);
7317 aopOp (left, ic, FALSE);
7318 aopOp (right, ic, FALSE);
7319 aopOp (result, ic, FALSE);
7321 shCount = (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7323 /* get the needed byte into a */
7324 MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7326 if (AOP_TYPE (result) == AOP_CRY)
7329 emitcode ("rlc", "a");
7330 else if ((shCount) == 0)
7331 emitcode ("rrc", "a");
7333 emitcode ("mov", "c,acc[%d]", shCount);
7341 emitcode ("rr", "a");
7344 emitcode ("rr", "a");
7347 emitcode ("anl", "a,#0x01");
7351 emitcode ("mov", "c,acc[%d]", shCount);
7352 emitcode ("clr", "a");
7353 emitcode ("rlc", "a");
7356 emitcode ("swap", "a");
7357 emitcode ("anl", "a,#0x01");
7360 emitcode ("rl", "a");
7363 emitcode ("rl", "a");
7364 emitcode ("anl", "a,#0x01");
7370 freeAsmop (left, NULL, ic, TRUE);
7371 freeAsmop (right, NULL, ic, TRUE);
7372 freeAsmop (result, NULL, ic, TRUE);
7375 /*-----------------------------------------------------------------*/
7376 /* genGetByte - generates code get a single byte */
7377 /*-----------------------------------------------------------------*/
7379 genGetByte (iCode * ic)
7381 operand *left, *right, *result;
7384 D(emitcode ("; genGetByte",""));
7386 left = IC_LEFT (ic);
7387 right = IC_RIGHT (ic);
7388 result = IC_RESULT (ic);
7389 aopOp (left, ic, FALSE);
7390 aopOp (right, ic, FALSE);
7391 aopOp (result, ic, FALSE);
7393 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7395 aopGet (left, offset, FALSE, FALSE),
7397 isOperandVolatile (result, FALSE));
7399 freeAsmop (left, NULL, ic, TRUE);
7400 freeAsmop (right, NULL, ic, TRUE);
7401 freeAsmop (result, NULL, ic, TRUE);
7404 /*-----------------------------------------------------------------*/
7405 /* genGetWord - generates code get two bytes */
7406 /*-----------------------------------------------------------------*/
7408 genGetWord (iCode * ic)
7410 operand *left, *right, *result;
7413 D(emitcode ("; genGetWord",""));
7415 left = IC_LEFT (ic);
7416 right = IC_RIGHT (ic);
7417 result = IC_RESULT (ic);
7418 aopOp (left, ic, FALSE);
7419 aopOp (right, ic, FALSE);
7420 aopOp (result, ic, FALSE);
7422 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7424 aopGet (left, offset, FALSE, FALSE),
7426 isOperandVolatile (result, FALSE));
7428 aopGet (left, offset+1, FALSE, FALSE),
7430 isOperandVolatile (result, FALSE));
7432 freeAsmop (left, NULL, ic, TRUE);
7433 freeAsmop (right, NULL, ic, TRUE);
7434 freeAsmop (result, NULL, ic, TRUE);
7437 /*-----------------------------------------------------------------*/
7438 /* genSwap - generates code to swap nibbles or bytes */
7439 /*-----------------------------------------------------------------*/
7441 genSwap (iCode * ic)
7443 operand *left, *result;
7445 D(emitcode ("; genSwap",""));
7447 left = IC_LEFT (ic);
7448 result = IC_RESULT (ic);
7449 aopOp (left, ic, FALSE);
7450 aopOp (result, ic, FALSE);
7452 switch (AOP_SIZE (left))
7454 case 1: /* swap nibbles in byte */
7455 MOVA (aopGet (left, 0, FALSE, FALSE));
7456 emitcode ("swap", "a");
7457 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
7459 case 2: /* swap bytes in word */
7460 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7462 MOVA (aopGet (left, 0, FALSE, FALSE));
7463 aopPut (result, aopGet (left, 1, FALSE, FALSE),
7464 0, isOperandVolatile (result, FALSE));
7465 aopPut (result, "a", 1, isOperandVolatile (result, FALSE));
7467 else if (operandsEqu (left, result))
7470 bool pushedB = FALSE, leftInB = FALSE;
7472 MOVA (aopGet (left, 0, FALSE, FALSE));
7473 if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
7476 emitcode ("mov", "b,a");
7480 aopPut (result, aopGet (left, 1, FALSE, FALSE),
7481 0, isOperandVolatile (result, FALSE));
7482 aopPut (result, reg, 1, isOperandVolatile (result, FALSE));
7489 aopPut (result, aopGet (left, 1, FALSE, FALSE),
7490 0, isOperandVolatile (result, FALSE));
7491 aopPut (result, aopGet (left, 0, FALSE, FALSE),
7492 1, isOperandVolatile (result, FALSE));
7496 wassertl(FALSE, "unsupported SWAP operand size");
7499 freeAsmop (left, NULL, ic, TRUE);
7500 freeAsmop (result, NULL, ic, TRUE);
7504 /*-----------------------------------------------------------------*/
7505 /* AccRol - rotate left accumulator by known count */
7506 /*-----------------------------------------------------------------*/
7508 AccRol (int shCount)
7510 shCount &= 0x0007; // shCount : 0..7
7517 emitcode ("rl", "a");
7520 emitcode ("rl", "a");
7521 emitcode ("rl", "a");
7524 emitcode ("swap", "a");
7525 emitcode ("rr", "a");
7528 emitcode ("swap", "a");
7531 emitcode ("swap", "a");
7532 emitcode ("rl", "a");
7535 emitcode ("rr", "a");
7536 emitcode ("rr", "a");
7539 emitcode ("rr", "a");
7544 /*-----------------------------------------------------------------*/
7545 /* AccLsh - left shift accumulator by known count */
7546 /*-----------------------------------------------------------------*/
7548 AccLsh (int shCount)
7553 emitcode ("add", "a,acc");
7554 else if (shCount == 2)
7556 emitcode ("add", "a,acc");
7557 emitcode ("add", "a,acc");
7561 /* rotate left accumulator */
7563 /* and kill the lower order bits */
7564 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
7569 /*-----------------------------------------------------------------*/
7570 /* AccRsh - right shift accumulator by known count */
7571 /*-----------------------------------------------------------------*/
7573 AccRsh (int shCount)
7580 emitcode ("rrc", "a");
7584 /* rotate right accumulator */
7585 AccRol (8 - shCount);
7586 /* and kill the higher order bits */
7587 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7592 /*-----------------------------------------------------------------*/
7593 /* AccSRsh - signed right shift accumulator by known count */
7594 /*-----------------------------------------------------------------*/
7596 AccSRsh (int shCount)
7603 emitcode ("mov", "c,acc.7");
7604 emitcode ("rrc", "a");
7606 else if (shCount == 2)
7608 emitcode ("mov", "c,acc.7");
7609 emitcode ("rrc", "a");
7610 emitcode ("mov", "c,acc.7");
7611 emitcode ("rrc", "a");
7615 tlbl = newiTempLabel (NULL);
7616 /* rotate right accumulator */
7617 AccRol (8 - shCount);
7618 /* and kill the higher order bits */
7619 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7620 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7621 emitcode ("orl", "a,#0x%02x",
7622 (unsigned char) ~SRMask[shCount]);
7623 emitcode ("", "%05d$:", tlbl->key + 100);
7628 /*-----------------------------------------------------------------*/
7629 /* shiftR1Left2Result - shift right one byte from left to result */
7630 /*-----------------------------------------------------------------*/
7632 shiftR1Left2Result (operand * left, int offl,
7633 operand * result, int offr,
7634 int shCount, int sign)
7636 MOVA (aopGet (left, offl, FALSE, FALSE));
7637 /* shift right accumulator */
7642 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7645 /*-----------------------------------------------------------------*/
7646 /* shiftL1Left2Result - shift left one byte from left to result */
7647 /*-----------------------------------------------------------------*/
7649 shiftL1Left2Result (operand * left, int offl,
7650 operand * result, int offr, int shCount)
7653 l = aopGet (left, offl, FALSE, FALSE);
7655 /* shift left accumulator */
7657 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7660 /*-----------------------------------------------------------------*/
7661 /* movLeft2Result - move byte from left to result */
7662 /*-----------------------------------------------------------------*/
7664 movLeft2Result (operand * left, int offl,
7665 operand * result, int offr, int sign)
7668 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7670 l = aopGet (left, offl, FALSE, FALSE);
7672 if (*l == '@' && (IS_AOP_PREG (result)))
7674 emitcode ("mov", "a,%s", l);
7675 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7680 aopPut (result, l, offr, isOperandVolatile (result, FALSE));
7683 /* MSB sign in acc.7 ! */
7684 if (getDataSize (left) == offl + 1)
7686 emitcode ("mov", "a,%s", l);
7687 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7694 /*-----------------------------------------------------------------*/
7695 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7696 /*-----------------------------------------------------------------*/
7700 emitcode ("rrc", "a");
7701 emitcode ("xch", "a,%s", x);
7702 emitcode ("rrc", "a");
7703 emitcode ("xch", "a,%s", x);
7706 /*-----------------------------------------------------------------*/
7707 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7708 /*-----------------------------------------------------------------*/
7712 emitcode ("xch", "a,%s", x);
7713 emitcode ("rlc", "a");
7714 emitcode ("xch", "a,%s", x);
7715 emitcode ("rlc", "a");
7718 /*-----------------------------------------------------------------*/
7719 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7720 /*-----------------------------------------------------------------*/
7724 emitcode ("xch", "a,%s", x);
7725 emitcode ("add", "a,acc");
7726 emitcode ("xch", "a,%s", x);
7727 emitcode ("rlc", "a");
7730 /*-----------------------------------------------------------------*/
7731 /* AccAXLsh - left shift a:x by known count (0..7) */
7732 /*-----------------------------------------------------------------*/
7734 AccAXLsh (char *x, int shCount)
7749 case 5: // AAAAABBB:CCCCCDDD
7751 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7753 emitcode ("anl", "a,#0x%02x",
7754 SLMask[shCount]); // BBB00000:CCCCCDDD
7756 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7758 AccRol (shCount); // DDDCCCCC:BBB00000
7760 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7762 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7764 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7766 emitcode ("anl", "a,#0x%02x",
7767 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7769 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7771 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7774 case 6: // AAAAAABB:CCCCCCDD
7775 emitcode ("anl", "a,#0x%02x",
7776 SRMask[shCount]); // 000000BB:CCCCCCDD
7777 emitcode ("mov", "c,acc.0"); // c = B
7778 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7780 AccAXRrl1 (x); // BCCCCCCD:D000000B
7781 AccAXRrl1 (x); // BBCCCCCC:DD000000
7783 emitcode("rrc","a");
7784 emitcode("xch","a,%s", x);
7785 emitcode("rrc","a");
7786 emitcode("mov","c,acc.0"); //<< get correct bit
7787 emitcode("xch","a,%s", x);
7789 emitcode("rrc","a");
7790 emitcode("xch","a,%s", x);
7791 emitcode("rrc","a");
7792 emitcode("xch","a,%s", x);
7795 case 7: // a:x <<= 7
7797 emitcode ("anl", "a,#0x%02x",
7798 SRMask[shCount]); // 0000000B:CCCCCCCD
7800 emitcode ("mov", "c,acc.0"); // c = B
7802 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7804 AccAXRrl1 (x); // BCCCCCCC:D0000000
7812 /*-----------------------------------------------------------------*/
7813 /* AccAXRsh - right shift a:x known count (0..7) */
7814 /*-----------------------------------------------------------------*/
7816 AccAXRsh (char *x, int shCount)
7824 AccAXRrl1 (x); // 0->a:x
7829 AccAXRrl1 (x); // 0->a:x
7832 AccAXRrl1 (x); // 0->a:x
7837 case 5: // AAAAABBB:CCCCCDDD = a:x
7839 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7841 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7843 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7845 emitcode ("anl", "a,#0x%02x",
7846 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7848 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7850 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7852 emitcode ("anl", "a,#0x%02x",
7853 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7855 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7857 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7859 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7862 case 6: // AABBBBBB:CCDDDDDD
7864 emitcode ("mov", "c,acc.7");
7865 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7867 emitcode ("mov", "c,acc.7");
7868 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7870 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7872 emitcode ("anl", "a,#0x%02x",
7873 SRMask[shCount]); // 000000AA:BBBBBBCC
7876 case 7: // ABBBBBBB:CDDDDDDD
7878 emitcode ("mov", "c,acc.7"); // c = A
7880 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7882 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7884 emitcode ("anl", "a,#0x%02x",
7885 SRMask[shCount]); // 0000000A:BBBBBBBC
7893 /*-----------------------------------------------------------------*/
7894 /* AccAXRshS - right shift signed a:x known count (0..7) */
7895 /*-----------------------------------------------------------------*/
7897 AccAXRshS (char *x, int shCount)
7905 emitcode ("mov", "c,acc.7");
7906 AccAXRrl1 (x); // s->a:x
7910 emitcode ("mov", "c,acc.7");
7911 AccAXRrl1 (x); // s->a:x
7913 emitcode ("mov", "c,acc.7");
7914 AccAXRrl1 (x); // s->a:x
7919 case 5: // AAAAABBB:CCCCCDDD = a:x
7921 tlbl = newiTempLabel (NULL);
7922 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7924 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7926 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7928 emitcode ("anl", "a,#0x%02x",
7929 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7931 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7933 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7935 emitcode ("anl", "a,#0x%02x",
7936 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7938 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7940 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7942 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7944 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7945 emitcode ("orl", "a,#0x%02x",
7946 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7948 emitcode ("", "%05d$:", tlbl->key + 100);
7949 break; // SSSSAAAA:BBBCCCCC
7951 case 6: // AABBBBBB:CCDDDDDD
7953 tlbl = newiTempLabel (NULL);
7954 emitcode ("mov", "c,acc.7");
7955 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7957 emitcode ("mov", "c,acc.7");
7958 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7960 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7962 emitcode ("anl", "a,#0x%02x",
7963 SRMask[shCount]); // 000000AA:BBBBBBCC
7965 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7966 emitcode ("orl", "a,#0x%02x",
7967 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7969 emitcode ("", "%05d$:", tlbl->key + 100);
7971 case 7: // ABBBBBBB:CDDDDDDD
7973 tlbl = newiTempLabel (NULL);
7974 emitcode ("mov", "c,acc.7"); // c = A
7976 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7978 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7980 emitcode ("anl", "a,#0x%02x",
7981 SRMask[shCount]); // 0000000A:BBBBBBBC
7983 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7984 emitcode ("orl", "a,#0x%02x",
7985 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7987 emitcode ("", "%05d$:", tlbl->key + 100);
7994 /*-----------------------------------------------------------------*/
7995 /* shiftL2Left2Result - shift left two bytes from left to result */
7996 /*-----------------------------------------------------------------*/
7998 shiftL2Left2Result (operand * left, int offl,
7999 operand * result, int offr, int shCount)
8001 if (sameRegs (AOP (result), AOP (left)) &&
8002 ((offl + MSB16) == offr))
8004 /* don't crash result[offr] */
8005 MOVA (aopGet (left, offl, FALSE, FALSE));
8006 emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8010 movLeft2Result (left, offl, result, offr, 0);
8011 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8013 /* ax << shCount (x = lsb(result)) */
8014 AccAXLsh (aopGet (result, offr, FALSE, FALSE), shCount);
8015 aopPut (result, "a", offr + MSB16, isOperandVolatile (result, FALSE));
8019 /*-----------------------------------------------------------------*/
8020 /* shiftR2Left2Result - shift right two bytes from left to result */
8021 /*-----------------------------------------------------------------*/
8023 shiftR2Left2Result (operand * left, int offl,
8024 operand * result, int offr,
8025 int shCount, int sign)
8027 if (sameRegs (AOP (result), AOP (left)) &&
8028 ((offl + MSB16) == offr))
8030 /* don't crash result[offr] */
8031 MOVA (aopGet (left, offl, FALSE, FALSE));
8032 emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8036 movLeft2Result (left, offl, result, offr, 0);
8037 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8039 /* a:x >> shCount (x = lsb(result)) */
8041 AccAXRshS (aopGet (result, offr, FALSE, FALSE), shCount);
8043 AccAXRsh (aopGet (result, offr, FALSE, FALSE), shCount);
8044 if (getDataSize (result) > 1)
8045 aopPut (result, "a", offr + MSB16, isOperandVolatile (result, FALSE));
8048 /*-----------------------------------------------------------------*/
8049 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8050 /*-----------------------------------------------------------------*/
8052 shiftLLeftOrResult (operand * left, int offl,
8053 operand * result, int offr, int shCount)
8055 MOVA (aopGet (left, offl, FALSE, FALSE));
8056 /* shift left accumulator */
8058 /* or with result */
8059 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8060 /* back to result */
8061 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
8064 /*-----------------------------------------------------------------*/
8065 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8066 /*-----------------------------------------------------------------*/
8068 shiftRLeftOrResult (operand * left, int offl,
8069 operand * result, int offr, int shCount)
8071 MOVA (aopGet (left, offl, FALSE, FALSE));
8072 /* shift right accumulator */
8074 /* or with result */
8075 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8076 /* back to result */
8077 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
8080 /*-----------------------------------------------------------------*/
8081 /* genlshOne - left shift a one byte quantity by known count */
8082 /*-----------------------------------------------------------------*/
8084 genlshOne (operand * result, operand * left, int shCount)
8086 D(emitcode ("; genlshOne",""));
8088 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8091 /*-----------------------------------------------------------------*/
8092 /* genlshTwo - left shift two bytes by known amount != 0 */
8093 /*-----------------------------------------------------------------*/
8095 genlshTwo (operand * result, operand * left, int shCount)
8099 D(emitcode ("; genlshTwo",""));
8101 size = getDataSize (result);
8103 /* if shCount >= 8 */
8111 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8113 movLeft2Result (left, LSB, result, MSB16, 0);
8115 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8118 /* 1 <= shCount <= 7 */
8122 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8124 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8128 /*-----------------------------------------------------------------*/
8129 /* shiftLLong - shift left one long from left to result */
8130 /* offl = LSB or MSB16 */
8131 /*-----------------------------------------------------------------*/
8133 shiftLLong (operand * left, operand * result, int offr)
8136 int size = AOP_SIZE (result);
8138 if (size >= LSB + offr)
8140 l = aopGet (left, LSB, FALSE, FALSE);
8142 emitcode ("add", "a,acc");
8143 if (sameRegs (AOP (left), AOP (result)) &&
8144 size >= MSB16 + offr && offr != LSB)
8145 emitcode ("xch", "a,%s",
8146 aopGet (left, LSB + offr, FALSE, FALSE));
8148 aopPut (result, "a", LSB + offr, isOperandVolatile (result, FALSE));
8151 if (size >= MSB16 + offr)
8153 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8155 l = aopGet (left, MSB16, FALSE, FALSE);
8158 emitcode ("rlc", "a");
8159 if (sameRegs (AOP (left), AOP (result)) &&
8160 size >= MSB24 + offr && offr != LSB)
8161 emitcode ("xch", "a,%s",
8162 aopGet (left, MSB16 + offr, FALSE, FALSE));
8164 aopPut (result, "a", MSB16 + offr, isOperandVolatile (result, FALSE));
8167 if (size >= MSB24 + offr)
8169 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8171 l = aopGet (left, MSB24, FALSE, FALSE);
8174 emitcode ("rlc", "a");
8175 if (sameRegs (AOP (left), AOP (result)) &&
8176 size >= MSB32 + offr && offr != LSB)
8177 emitcode ("xch", "a,%s",
8178 aopGet (left, MSB24 + offr, FALSE, FALSE));
8180 aopPut (result, "a", MSB24 + offr, isOperandVolatile (result, FALSE));
8183 if (size > MSB32 + offr)
8185 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8187 l = aopGet (left, MSB32, FALSE, FALSE);
8190 emitcode ("rlc", "a");
8191 aopPut (result, "a", MSB32 + offr, isOperandVolatile (result, FALSE));
8194 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8197 /*-----------------------------------------------------------------*/
8198 /* genlshFour - shift four byte by a known amount != 0 */
8199 /*-----------------------------------------------------------------*/
8201 genlshFour (operand * result, operand * left, int shCount)
8205 D(emitcode ("; genlshFour",""));
8207 size = AOP_SIZE (result);
8209 /* if shifting more that 3 bytes */
8214 /* lowest order of left goes to the highest
8215 order of the destination */
8216 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8218 movLeft2Result (left, LSB, result, MSB32, 0);
8219 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8220 aopPut (result, zero, MSB16, isOperandVolatile (result, FALSE));
8221 aopPut (result, zero, MSB24, isOperandVolatile (result, FALSE));
8225 /* more than two bytes */
8226 else if (shCount >= 16)
8228 /* lower order two bytes goes to higher order two bytes */
8230 /* if some more remaining */
8232 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8235 movLeft2Result (left, MSB16, result, MSB32, 0);
8236 movLeft2Result (left, LSB, result, MSB24, 0);
8238 aopPut (result, zero, MSB16, isOperandVolatile (result, FALSE));
8239 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8243 /* if more than 1 byte */
8244 else if (shCount >= 8)
8246 /* lower order three bytes goes to higher order three bytes */
8251 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8253 movLeft2Result (left, LSB, result, MSB16, 0);
8259 movLeft2Result (left, MSB24, result, MSB32, 0);
8260 movLeft2Result (left, MSB16, result, MSB24, 0);
8261 movLeft2Result (left, LSB, result, MSB16, 0);
8262 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8264 else if (shCount == 1)
8265 shiftLLong (left, result, MSB16);
8268 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8269 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8270 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8271 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8276 /* 1 <= shCount <= 7 */
8277 else if (shCount <= 2)
8279 shiftLLong (left, result, LSB);
8281 shiftLLong (result, result, LSB);
8283 /* 3 <= shCount <= 7, optimize */
8286 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8287 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8288 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8292 /*-----------------------------------------------------------------*/
8293 /* genLeftShiftLiteral - left shifting by known count */
8294 /*-----------------------------------------------------------------*/
8296 genLeftShiftLiteral (operand * left,
8301 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8304 D(emitcode ("; genLeftShiftLiteral",""));
8306 freeAsmop (right, NULL, ic, TRUE);
8308 aopOp (left, ic, FALSE);
8309 aopOp (result, ic, FALSE);
8311 size = getSize (operandType (result));
8314 emitcode ("; shift left ", "result %d, left %d", size,
8318 /* I suppose that the left size >= result size */
8323 movLeft2Result (left, size, result, size, 0);
8327 else if (shCount >= (size * 8))
8329 aopPut (result, zero, size, isOperandVolatile (result, FALSE));
8335 genlshOne (result, left, shCount);
8339 genlshTwo (result, left, shCount);
8343 genlshFour (result, left, shCount);
8346 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8347 "*** ack! mystery literal shift!\n");
8351 freeAsmop (left, NULL, ic, TRUE);
8352 freeAsmop (result, NULL, ic, TRUE);
8355 /*-----------------------------------------------------------------*/
8356 /* genLeftShift - generates code for left shifting */
8357 /*-----------------------------------------------------------------*/
8359 genLeftShift (iCode * ic)
8361 operand *left, *right, *result;
8364 symbol *tlbl, *tlbl1;
8367 D(emitcode ("; genLeftShift",""));
8369 right = IC_RIGHT (ic);
8370 left = IC_LEFT (ic);
8371 result = IC_RESULT (ic);
8373 aopOp (right, ic, FALSE);
8375 /* if the shift count is known then do it
8376 as efficiently as possible */
8377 if (AOP_TYPE (right) == AOP_LIT)
8379 genLeftShiftLiteral (left, right, result, ic);
8383 /* shift count is unknown then we have to form
8384 a loop get the loop count in B : Note: we take
8385 only the lower order byte since shifting
8386 more that 32 bits make no sense anyway, ( the
8387 largest size of an object can be only 32 bits ) */
8390 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
8391 emitcode ("inc", "b");
8392 freeAsmop (right, NULL, ic, TRUE);
8393 aopOp (left, ic, FALSE);
8394 aopOp (result, ic, FALSE);
8396 /* now move the left to the result if they are not the same */
8397 if (!sameRegs (AOP (left), AOP (result)) &&
8398 AOP_SIZE (result) > 1)
8401 size = AOP_SIZE (result);
8405 l = aopGet (left, offset, FALSE, TRUE);
8406 if (*l == '@' && (IS_AOP_PREG (result)))
8409 emitcode ("mov", "a,%s", l);
8410 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
8413 aopPut (result, l, offset, isOperandVolatile (result, FALSE));
8418 tlbl = newiTempLabel (NULL);
8419 size = AOP_SIZE (result);
8421 tlbl1 = newiTempLabel (NULL);
8423 /* if it is only one byte then */
8426 symbol *tlbl1 = newiTempLabel (NULL);
8428 l = aopGet (left, 0, FALSE, FALSE);
8430 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8431 emitcode ("", "%05d$:", tlbl->key + 100);
8432 emitcode ("add", "a,acc");
8433 emitcode ("", "%05d$:", tlbl1->key + 100);
8434 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8436 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
8440 reAdjustPreg (AOP (result));
8442 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8443 emitcode ("", "%05d$:", tlbl->key + 100);
8444 l = aopGet (result, offset, FALSE, FALSE);
8446 emitcode ("add", "a,acc");
8447 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8450 l = aopGet (result, offset, FALSE, FALSE);
8452 emitcode ("rlc", "a");
8453 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8455 reAdjustPreg (AOP (result));
8457 emitcode ("", "%05d$:", tlbl1->key + 100);
8458 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8461 freeAsmop (left, NULL, ic, TRUE);
8462 freeAsmop (result, NULL, ic, TRUE);
8465 /*-----------------------------------------------------------------*/
8466 /* genrshOne - right shift a one byte quantity by known count */
8467 /*-----------------------------------------------------------------*/
8469 genrshOne (operand * result, operand * left,
8470 int shCount, int sign)
8472 D(emitcode ("; genrshOne",""));
8474 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8477 /*-----------------------------------------------------------------*/
8478 /* genrshTwo - right shift two bytes by known amount != 0 */
8479 /*-----------------------------------------------------------------*/
8481 genrshTwo (operand * result, operand * left,
8482 int shCount, int sign)
8484 D(emitcode ("; genrshTwo",""));
8486 /* if shCount >= 8 */
8491 shiftR1Left2Result (left, MSB16, result, LSB,
8494 movLeft2Result (left, MSB16, result, LSB, sign);
8495 addSign (result, MSB16, sign);
8498 /* 1 <= shCount <= 7 */
8500 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8503 /*-----------------------------------------------------------------*/
8504 /* shiftRLong - shift right one long from left to result */
8505 /* offl = LSB or MSB16 */
8506 /*-----------------------------------------------------------------*/
8508 shiftRLong (operand * left, int offl,
8509 operand * result, int sign)
8511 int isSameRegs=sameRegs(AOP(left),AOP(result));
8513 if (isSameRegs && offl>1) {
8514 // we are in big trouble, but this shouldn't happen
8515 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8518 MOVA (aopGet (left, MSB32, FALSE, FALSE));
8523 emitcode ("rlc", "a");
8524 emitcode ("subb", "a,acc");
8526 emitcode ("xch", "a,%s", aopGet (left, MSB32, FALSE, FALSE));
8528 aopPut (result, "a", MSB32, isOperandVolatile (result, FALSE));
8529 MOVA (aopGet (left, MSB32, FALSE, FALSE));
8532 aopPut (result, zero, MSB32, isOperandVolatile (result, FALSE));
8537 emitcode ("clr", "c");
8539 emitcode ("mov", "c,acc.7");
8542 emitcode ("rrc", "a");
8544 if (isSameRegs && offl==MSB16) {
8545 emitcode ("xch", "a,%s",aopGet (left, MSB24, FALSE, FALSE));
8547 aopPut (result, "a", MSB32-offl, isOperandVolatile (result, FALSE));
8548 MOVA (aopGet (left, MSB24, FALSE, FALSE));
8551 emitcode ("rrc", "a");
8552 if (isSameRegs && offl==1) {
8553 emitcode ("xch", "a,%s",aopGet (left, MSB16, FALSE, FALSE));
8555 aopPut (result, "a", MSB24-offl, isOperandVolatile (result, FALSE));
8556 MOVA (aopGet (left, MSB16, FALSE, FALSE));
8558 emitcode ("rrc", "a");
8559 aopPut (result, "a", MSB16 - offl, isOperandVolatile (result, FALSE));
8563 MOVA (aopGet (left, LSB, FALSE, FALSE));
8564 emitcode ("rrc", "a");
8565 aopPut (result, "a", LSB, isOperandVolatile (result, FALSE));
8569 /*-----------------------------------------------------------------*/
8570 /* genrshFour - shift four byte by a known amount != 0 */
8571 /*-----------------------------------------------------------------*/
8573 genrshFour (operand * result, operand * left,
8574 int shCount, int sign)
8576 D(emitcode ("; genrshFour",""));
8578 /* if shifting more that 3 bytes */
8583 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8585 movLeft2Result (left, MSB32, result, LSB, sign);
8586 addSign (result, MSB16, sign);
8588 else if (shCount >= 16)
8592 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8595 movLeft2Result (left, MSB24, result, LSB, 0);
8596 movLeft2Result (left, MSB32, result, MSB16, sign);
8598 addSign (result, MSB24, sign);
8600 else if (shCount >= 8)
8604 shiftRLong (left, MSB16, result, sign);
8605 else if (shCount == 0)
8607 movLeft2Result (left, MSB16, result, LSB, 0);
8608 movLeft2Result (left, MSB24, result, MSB16, 0);
8609 movLeft2Result (left, MSB32, result, MSB24, sign);
8610 addSign (result, MSB32, sign);
8614 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8615 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8616 /* the last shift is signed */
8617 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8618 addSign (result, MSB32, sign);
8622 { /* 1 <= shCount <= 7 */
8625 shiftRLong (left, LSB, result, sign);
8627 shiftRLong (result, LSB, result, sign);
8631 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8632 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8633 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8638 /*-----------------------------------------------------------------*/
8639 /* genRightShiftLiteral - right shifting by known count */
8640 /*-----------------------------------------------------------------*/
8642 genRightShiftLiteral (operand * left,
8648 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8651 D(emitcode ("; genRightShiftLiteral",""));
8653 freeAsmop (right, NULL, ic, TRUE);
8655 aopOp (left, ic, FALSE);
8656 aopOp (result, ic, FALSE);
8659 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8663 size = getDataSize (left);
8664 /* test the LEFT size !!! */
8666 /* I suppose that the left size >= result size */
8669 size = getDataSize (result);
8671 movLeft2Result (left, size, result, size, 0);
8674 else if (shCount >= (size * 8))
8677 /* get sign in acc.7 */
8678 MOVA (aopGet (left, size - 1, FALSE, FALSE));
8680 addSign (result, LSB, sign);
8687 genrshOne (result, left, shCount, sign);
8691 genrshTwo (result, left, shCount, sign);
8695 genrshFour (result, left, shCount, sign);
8701 freeAsmop (left, NULL, ic, TRUE);
8702 freeAsmop (result, NULL, ic, TRUE);
8705 /*-----------------------------------------------------------------*/
8706 /* genSignedRightShift - right shift of signed number */
8707 /*-----------------------------------------------------------------*/
8709 genSignedRightShift (iCode * ic)
8711 operand *right, *left, *result;
8714 symbol *tlbl, *tlbl1;
8717 D(emitcode ("; genSignedRightShift",""));
8719 /* we do it the hard way put the shift count in b
8720 and loop thru preserving the sign */
8722 right = IC_RIGHT (ic);
8723 left = IC_LEFT (ic);
8724 result = IC_RESULT (ic);
8726 aopOp (right, ic, FALSE);
8729 if (AOP_TYPE (right) == AOP_LIT)
8731 genRightShiftLiteral (left, right, result, ic, 1);
8734 /* shift count is unknown then we have to form
8735 a loop get the loop count in B : Note: we take
8736 only the lower order byte since shifting
8737 more that 32 bits make no sense anyway, ( the
8738 largest size of an object can be only 32 bits ) */
8741 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
8742 emitcode ("inc", "b");
8743 freeAsmop (right, NULL, ic, TRUE);
8744 aopOp (left, ic, FALSE);
8745 aopOp (result, ic, FALSE);
8747 /* now move the left to the result if they are not the
8749 if (!sameRegs (AOP (left), AOP (result)) &&
8750 AOP_SIZE (result) > 1)
8753 size = AOP_SIZE (result);
8757 l = aopGet (left, offset, FALSE, TRUE);
8758 if (*l == '@' && IS_AOP_PREG (result))
8761 emitcode ("mov", "a,%s", l);
8762 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
8765 aopPut (result, l, offset, isOperandVolatile (result, FALSE));
8770 /* mov the highest order bit to OVR */
8771 tlbl = newiTempLabel (NULL);
8772 tlbl1 = newiTempLabel (NULL);
8774 size = AOP_SIZE (result);
8776 MOVA (aopGet (left, offset, FALSE, FALSE));
8777 emitcode ("rlc", "a");
8778 emitcode ("mov", "ov,c");
8779 /* if it is only one byte then */
8782 l = aopGet (left, 0, FALSE, FALSE);
8784 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8785 emitcode ("", "%05d$:", tlbl->key + 100);
8786 emitcode ("mov", "c,ov");
8787 emitcode ("rrc", "a");
8788 emitcode ("", "%05d$:", tlbl1->key + 100);
8789 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8791 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
8795 reAdjustPreg (AOP (result));
8796 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8797 emitcode ("", "%05d$:", tlbl->key + 100);
8798 emitcode ("mov", "c,ov");
8801 l = aopGet (result, offset, FALSE, FALSE);
8803 emitcode ("rrc", "a");
8804 aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
8806 reAdjustPreg (AOP (result));
8807 emitcode ("", "%05d$:", tlbl1->key + 100);
8808 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8812 freeAsmop (left, NULL, ic, TRUE);
8813 freeAsmop (result, NULL, ic, TRUE);
8816 /*-----------------------------------------------------------------*/
8817 /* genRightShift - generate code for right shifting */
8818 /*-----------------------------------------------------------------*/
8820 genRightShift (iCode * ic)
8822 operand *right, *left, *result;
8826 symbol *tlbl, *tlbl1;
8829 D(emitcode ("; genRightShift",""));
8831 /* if signed then we do it the hard way preserve the
8832 sign bit moving it inwards */
8833 letype = getSpec (operandType (IC_LEFT (ic)));
8835 if (!SPEC_USIGN (letype))
8837 genSignedRightShift (ic);
8841 /* signed & unsigned types are treated the same : i.e. the
8842 signed is NOT propagated inwards : quoting from the
8843 ANSI - standard : "for E1 >> E2, is equivalent to division
8844 by 2**E2 if unsigned or if it has a non-negative value,
8845 otherwise the result is implementation defined ", MY definition
8846 is that the sign does not get propagated */
8848 right = IC_RIGHT (ic);
8849 left = IC_LEFT (ic);
8850 result = IC_RESULT (ic);
8852 aopOp (right, ic, FALSE);
8854 /* if the shift count is known then do it
8855 as efficiently as possible */
8856 if (AOP_TYPE (right) == AOP_LIT)
8858 genRightShiftLiteral (left, right, result, ic, 0);
8862 /* shift count is unknown then we have to form
8863 a loop get the loop count in B : Note: we take
8864 only the lower order byte since shifting
8865 more that 32 bits make no sense anyway, ( the
8866 largest size of an object can be only 32 bits ) */
8869 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
8870 emitcode ("inc", "b");
8871 freeAsmop (right, NULL, ic, TRUE);
8872 aopOp (left, ic, FALSE);
8873 aopOp (result, ic, FALSE);
8875 /* now move the left to the result if they are not the
8877 if (!sameRegs (AOP (left), AOP (result)) &&
8878 AOP_SIZE (result) > 1)
8881 size = AOP_SIZE (result);
8885 l = aopGet (left, offset, FALSE, TRUE);
8886 if (*l == '@' && IS_AOP_PREG (result))
8889 emitcode ("mov", "a,%s", l);
8890 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
8893 aopPut (result, l, offset, isOperandVolatile (result, FALSE));
8898 tlbl = newiTempLabel (NULL);
8899 tlbl1 = newiTempLabel (NULL);
8900 size = AOP_SIZE (result);
8903 /* if it is only one byte then */
8906 l = aopGet (left, 0, FALSE, FALSE);
8908 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8909 emitcode ("", "%05d$:", tlbl->key + 100);
8911 emitcode ("rrc", "a");
8912 emitcode ("", "%05d$:", tlbl1->key + 100);
8913 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8915 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
8919 reAdjustPreg (AOP (result));
8920 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8921 emitcode ("", "%05d$:", tlbl->key + 100);
8925 l = aopGet (result, offset, FALSE, FALSE);
8927 emitcode ("rrc", "a");
8928 aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
8930 reAdjustPreg (AOP (result));
8932 emitcode ("", "%05d$:", tlbl1->key + 100);
8933 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8937 freeAsmop (left, NULL, ic, TRUE);
8938 freeAsmop (result, NULL, ic, TRUE);
8941 /*-----------------------------------------------------------------*/
8942 /* emitPtrByteGet - emits code to get a byte into A through a */
8943 /* pointer register (R0, R1, or DPTR). The */
8944 /* original value of A can be preserved in B. */
8945 /*-----------------------------------------------------------------*/
8947 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
8954 emitcode ("mov", "b,a");
8955 emitcode ("mov", "a,@%s", rname);
8960 emitcode ("mov", "b,a");
8961 emitcode ("movx", "a,@%s", rname);
8966 emitcode ("mov", "b,a");
8967 emitcode ("movx", "a,@dptr");
8972 emitcode ("mov", "b,a");
8973 emitcode ("clr", "a");
8974 emitcode ("movc", "a,@a+dptr");
8980 emitcode ("push", "b");
8981 emitcode ("push", "acc");
8983 emitcode ("lcall", "__gptrget");
8985 emitcode ("pop", "b");
8990 /*-----------------------------------------------------------------*/
8991 /* emitPtrByteSet - emits code to set a byte from src through a */
8992 /* pointer register (R0, R1, or DPTR). */
8993 /*-----------------------------------------------------------------*/
8995 emitPtrByteSet (char *rname, int p_type, char *src)
9004 emitcode ("mov", "@%s,a", rname);
9007 emitcode ("mov", "@%s,%s", rname, src);
9012 emitcode ("movx", "@%s,a", rname);
9017 emitcode ("movx", "@dptr,a");
9022 emitcode ("lcall", "__gptrput");
9027 /*-----------------------------------------------------------------*/
9028 /* genUnpackBits - generates code for unpacking bits */
9029 /*-----------------------------------------------------------------*/
9031 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9033 int offset = 0; /* result byte offset */
9034 int rsize; /* result size */
9035 int rlen = 0; /* remaining bitfield length */
9036 sym_link *etype; /* bitfield type information */
9037 int blen; /* bitfield length */
9038 int bstr; /* bitfield starting bit within byte */
9041 D(emitcode ("; genUnpackBits",""));
9043 etype = getSpec (operandType (result));
9044 rsize = getSize (operandType (result));
9045 blen = SPEC_BLEN (etype);
9046 bstr = SPEC_BSTR (etype);
9048 if (ifx && blen <= 8)
9050 emitPtrByteGet (rname, ptype, FALSE);
9053 SNPRINTF (buffer, sizeof(buffer),
9055 genIfxJump (ifx, buffer, NULL, NULL, NULL);
9060 emitcode ("anl", "a,#0x%02x",
9061 (((unsigned char) -1) >> (8 - blen)) << bstr);
9062 genIfxJump (ifx, "a", NULL, NULL, NULL);
9068 /* If the bitfield length is less than a byte */
9071 emitPtrByteGet (rname, ptype, FALSE);
9073 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9074 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9078 /* Bit field did not fit in a byte. Copy all
9079 but the partial byte at the end. */
9080 for (rlen=blen;rlen>=8;rlen-=8)
9082 emitPtrByteGet (rname, ptype, FALSE);
9083 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9085 emitcode ("inc", "%s", rname);
9088 /* Handle the partial byte at the end */
9091 emitPtrByteGet (rname, ptype, FALSE);
9092 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9093 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9101 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
9106 /*-----------------------------------------------------------------*/
9107 /* genDataPointerGet - generates code when ptr offset is known */
9108 /*-----------------------------------------------------------------*/
9110 genDataPointerGet (operand * left,
9116 int size, offset = 0;
9118 D(emitcode ("; genDataPointerGet",""));
9120 aopOp (result, ic, TRUE);
9122 /* get the string representation of the name */
9123 l = aopGet (left, 0, FALSE, TRUE);
9124 size = AOP_SIZE (result);
9128 sprintf (buffer, "(%s + %d)", l + 1, offset);
9130 sprintf (buffer, "%s", l + 1);
9131 aopPut (result, buffer, offset++, isOperandVolatile (result, FALSE));
9134 freeAsmop (left, NULL, ic, TRUE);
9135 freeAsmop (result, NULL, ic, TRUE);
9138 /*-----------------------------------------------------------------*/
9139 /* genNearPointerGet - emitcode for near pointer fetch */
9140 /*-----------------------------------------------------------------*/
9142 genNearPointerGet (operand * left,
9151 sym_link *rtype, *retype;
9152 sym_link *ltype = operandType (left);
9155 D(emitcode ("; genNearPointerGet",""));
9157 rtype = operandType (result);
9158 retype = getSpec (rtype);
9160 aopOp (left, ic, FALSE);
9162 /* if left is rematerialisable and
9163 result is not bitfield variable type and
9164 the left is pointer to data space i.e
9165 lower 128 bytes of space */
9166 if (AOP_TYPE (left) == AOP_IMMD &&
9167 !IS_BITFIELD (retype) &&
9168 DCL_TYPE (ltype) == POINTER)
9170 genDataPointerGet (left, result, ic);
9174 /* if the value is already in a pointer register
9175 then don't need anything more */
9176 if (!AOP_INPREG (AOP (left)))
9178 if (IS_AOP_PREG (left))
9180 // Aha, it is a pointer, just in disguise.
9181 rname = aopGet (left, 0, FALSE, FALSE);
9184 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9185 __FILE__, __LINE__);
9190 emitcode ("mov", "a%s,%s", rname + 1, rname);
9191 rname++; // skip the '@'.
9196 /* otherwise get a free pointer register */
9198 preg = getFreePtr (ic, &aop, FALSE);
9199 emitcode ("mov", "%s,%s",
9201 aopGet (left, 0, FALSE, TRUE));
9206 rname = aopGet (left, 0, FALSE, FALSE);
9208 //aopOp (result, ic, FALSE);
9209 aopOp (result, ic, result?TRUE:FALSE);
9211 /* if bitfield then unpack the bits */
9212 if (IS_BITFIELD (retype))
9213 genUnpackBits (result, rname, POINTER, ifx);
9216 /* we have can just get the values */
9217 int size = AOP_SIZE (result);
9222 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9225 emitcode ("mov", "a,@%s", rname);
9227 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9231 sprintf (buffer, "@%s", rname);
9232 aopPut (result, buffer, offset, isOperandVolatile (result, FALSE));
9236 emitcode ("inc", "%s", rname);
9240 /* now some housekeeping stuff */
9241 if (aop) /* we had to allocate for this iCode */
9243 if (pi) { /* post increment present */
9244 aopPut (left, rname, 0, isOperandVolatile (left, FALSE));
9246 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9250 /* we did not allocate which means left
9251 already in a pointer register, then
9252 if size > 0 && this could be used again
9253 we have to point it back to where it
9255 if ((AOP_SIZE (result) > 1 &&
9256 !OP_SYMBOL (left)->remat &&
9257 (OP_SYMBOL (left)->liveTo > ic->seq ||
9261 int size = AOP_SIZE (result) - 1;
9263 emitcode ("dec", "%s", rname);
9267 if (ifx && !ifx->generated)
9269 genIfxJump (ifx, "a", left, NULL, result);
9273 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9274 freeAsmop (left, NULL, ic, TRUE);
9275 if (pi) pi->generated = 1;
9278 /*-----------------------------------------------------------------*/
9279 /* genPagedPointerGet - emitcode for paged pointer fetch */
9280 /*-----------------------------------------------------------------*/
9282 genPagedPointerGet (operand * left,
9291 sym_link *rtype, *retype;
9293 D(emitcode ("; genPagedPointerGet",""));
9295 rtype = operandType (result);
9296 retype = getSpec (rtype);
9298 aopOp (left, ic, FALSE);
9300 /* if the value is already in a pointer register
9301 then don't need anything more */
9302 if (!AOP_INPREG (AOP (left)))
9304 /* otherwise get a free pointer register */
9306 preg = getFreePtr (ic, &aop, FALSE);
9307 emitcode ("mov", "%s,%s",
9309 aopGet (left, 0, FALSE, TRUE));
9313 rname = aopGet (left, 0, FALSE, FALSE);
9315 aopOp (result, ic, FALSE);
9317 /* if bitfield then unpack the bits */
9318 if (IS_BITFIELD (retype))
9319 genUnpackBits (result, rname, PPOINTER, ifx);
9322 /* we have can just get the values */
9323 int size = AOP_SIZE (result);
9329 emitcode ("movx", "a,@%s", rname);
9331 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9336 emitcode ("inc", "%s", rname);
9340 /* now some housekeeping stuff */
9341 if (aop) /* we had to allocate for this iCode */
9343 if (pi) aopPut (left, rname, 0, isOperandVolatile (left, FALSE));
9344 freeAsmop (NULL, aop, ic, TRUE);
9348 /* we did not allocate which means left
9349 already in a pointer register, then
9350 if size > 0 && this could be used again
9351 we have to point it back to where it
9353 if ((AOP_SIZE (result) > 1 &&
9354 !OP_SYMBOL (left)->remat &&
9355 (OP_SYMBOL (left)->liveTo > ic->seq ||
9359 int size = AOP_SIZE (result) - 1;
9361 emitcode ("dec", "%s", rname);
9365 if (ifx && !ifx->generated)
9367 genIfxJump (ifx, "a", left, NULL, result);
9371 freeAsmop (left, NULL, ic, TRUE);
9372 freeAsmop (result, NULL, ic, TRUE);
9373 if (pi) pi->generated = 1;
9377 /*--------------------------------------------------------------------*/
9378 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
9379 /*--------------------------------------------------------------------*/
9381 loadDptrFromOperand (operand *op, bool loadBToo)
9383 if (AOP_TYPE (op) != AOP_STR)
9385 /* if this is rematerializable */
9386 if (AOP_TYPE (op) == AOP_IMMD)
9388 emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
9391 if (AOP(op)->aopu.aop_immd.from_cast_remat)
9392 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
9395 wassertl(FALSE, "need pointerCode");
9396 emitcode ("", "; mov b,???");
9397 /* genPointerGet and genPointerSet originally did different
9398 ** things for this case. Both seem wrong.
9399 ** from genPointerGet:
9400 ** emitcode ("mov", "b,#%d", pointerCode (retype));
9401 ** from genPointerSet:
9402 ** emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
9407 else if (AOP_TYPE (op) == AOP_DPTR)
9411 MOVA (aopGet (op, 0, FALSE, FALSE));
9412 emitcode ("push", "acc");
9413 MOVA (aopGet (op, 1, FALSE, FALSE));
9414 emitcode ("push", "acc");
9415 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9416 emitcode ("pop", "dph");
9417 emitcode ("pop", "dpl");
9421 MOVA (aopGet (op, 0, FALSE, FALSE));
9422 emitcode ("push", "acc");
9423 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9424 emitcode ("pop", "dpl");
9428 { /* we need to get it byte by byte */
9429 emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
9430 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9432 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9437 /*-----------------------------------------------------------------*/
9438 /* genFarPointerGet - gget value from far space */
9439 /*-----------------------------------------------------------------*/
9441 genFarPointerGet (operand * left,
9442 operand * result, iCode * ic, iCode * pi, iCode * ifx)
9445 sym_link *retype = getSpec (operandType (result));
9447 D(emitcode ("; genFarPointerGet",""));
9449 aopOp (left, ic, FALSE);
9450 loadDptrFromOperand (left, FALSE);
9452 /* so dptr now contains the address */
9453 aopOp (result, ic, FALSE);
9455 /* if bit then unpack */
9456 if (IS_BITFIELD (retype))
9457 genUnpackBits (result, "dptr", FPOINTER, ifx);
9460 size = AOP_SIZE (result);
9465 emitcode ("movx", "a,@dptr");
9467 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9469 emitcode ("inc", "dptr");
9473 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9475 aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9476 aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9480 if (ifx && !ifx->generated)
9482 genIfxJump (ifx, "a", left, NULL, result);
9485 freeAsmop (left, NULL, ic, TRUE);
9486 freeAsmop (result, NULL, ic, TRUE);
9489 /*-----------------------------------------------------------------*/
9490 /* genCodePointerGet - gget value from code space */
9491 /*-----------------------------------------------------------------*/
9493 genCodePointerGet (operand * left,
9494 operand * result, iCode * ic, iCode *pi, iCode *ifx)
9497 sym_link *retype = getSpec (operandType (result));
9499 D(emitcode ("; genCodePointerGet",""));
9501 aopOp (left, ic, FALSE);
9502 loadDptrFromOperand (left, FALSE);
9504 /* so dptr now contains the address */
9505 aopOp (result, ic, FALSE);
9507 /* if bit then unpack */
9508 if (IS_BITFIELD (retype))
9509 genUnpackBits (result, "dptr", CPOINTER, ifx);
9512 size = AOP_SIZE (result);
9519 emitcode ("clr", "a");
9520 emitcode ("movc", "a,@a+dptr");
9522 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9523 emitcode ("inc", "dptr");
9527 emitcode ("mov", "a,#0x%02x", offset);
9528 emitcode ("movc", "a,@a+dptr");
9530 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9535 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9537 aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9538 aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9542 if (ifx && !ifx->generated)
9544 genIfxJump (ifx, "a", left, NULL, result);
9547 freeAsmop (left, NULL, ic, TRUE);
9548 freeAsmop (result, NULL, ic, TRUE);
9551 /*-----------------------------------------------------------------*/
9552 /* genGenPointerGet - gget value from generic pointer space */
9553 /*-----------------------------------------------------------------*/
9555 genGenPointerGet (operand * left,
9556 operand * result, iCode * ic, iCode *pi, iCode *ifx)
9559 sym_link *retype = getSpec (operandType (result));
9561 D(emitcode ("; genGenPointerGet",""));
9563 aopOp (left, ic, FALSE);
9564 loadDptrFromOperand (left, TRUE);
9566 /* so dptr know contains the address */
9567 aopOp (result, ic, FALSE);
9569 /* if bit then unpack */
9570 if (IS_BITFIELD (retype))
9571 genUnpackBits (result, "dptr", GPOINTER, ifx);
9574 size = AOP_SIZE (result);
9579 emitcode ("lcall", "__gptrget");
9581 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9583 emitcode ("inc", "dptr");
9587 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9589 aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9590 aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9594 if (ifx && !ifx->generated)
9596 genIfxJump (ifx, "a", left, NULL, result);
9600 freeAsmop (left, NULL, ic, TRUE);
9601 freeAsmop (result, NULL, ic, TRUE);
9604 /*-----------------------------------------------------------------*/
9605 /* genPointerGet - generate code for pointer get */
9606 /*-----------------------------------------------------------------*/
9608 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
9610 operand *left, *result;
9611 sym_link *type, *etype;
9614 D(emitcode ("; genPointerGet",""));
9616 left = IC_LEFT (ic);
9617 result = IC_RESULT (ic);
9619 if (getSize (operandType (result))>1)
9622 /* depending on the type of pointer we need to
9623 move it to the correct pointer register */
9624 type = operandType (left);
9625 etype = getSpec (type);
9626 /* if left is of type of pointer then it is simple */
9627 if (IS_PTR (type) && !IS_FUNC (type->next))
9628 p_type = DCL_TYPE (type);
9631 /* we have to go by the storage class */
9632 p_type = PTR_TYPE (SPEC_OCLS (etype));
9635 /* special case when cast remat */
9636 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9637 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9638 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9639 type = operandType (left);
9640 p_type = DCL_TYPE (type);
9642 /* now that we have the pointer type we assign
9643 the pointer values */
9649 genNearPointerGet (left, result, ic, pi, ifx);
9653 genPagedPointerGet (left, result, ic, pi, ifx);
9657 genFarPointerGet (left, result, ic, pi, ifx);
9661 genCodePointerGet (left, result, ic, pi, ifx);
9665 genGenPointerGet (left, result, ic, pi, ifx);
9673 /*-----------------------------------------------------------------*/
9674 /* genPackBits - generates code for packed bit storage */
9675 /*-----------------------------------------------------------------*/
9677 genPackBits (sym_link * etype,
9679 char *rname, int p_type)
9681 int offset = 0; /* source byte offset */
9682 int rlen = 0; /* remaining bitfield length */
9683 int blen; /* bitfield length */
9684 int bstr; /* bitfield starting bit within byte */
9685 int litval; /* source literal value (if AOP_LIT) */
9686 unsigned char mask; /* bitmask within current byte */
9688 D(emitcode ("; genPackBits",""));
9690 blen = SPEC_BLEN (etype);
9691 bstr = SPEC_BSTR (etype);
9693 /* If the bitfield length is less than a byte */
9696 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9697 (unsigned char) (0xFF >> (8 - bstr)));
9699 if (AOP_TYPE (right) == AOP_LIT)
9701 /* Case with a bitfield length <8 and literal source
9703 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9705 litval &= (~mask) & 0xff;
9706 emitPtrByteGet (rname, p_type, FALSE);
9707 if ((mask|litval)!=0xff)
9708 emitcode ("anl","a,#0x%02x", mask);
9710 emitcode ("orl","a,#0x%02x", litval);
9714 if ((blen==1) && (p_type!=GPOINTER))
9716 /* Case with a bitfield length == 1 and no generic pointer
9718 if (AOP_TYPE (right) == AOP_CRY)
9719 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9722 MOVA (aopGet (right, 0, FALSE, FALSE));
9723 emitcode ("rrc","a");
9725 emitPtrByteGet (rname, p_type, FALSE);
9726 emitcode ("mov","acc.%d,c",bstr);
9731 /* Case with a bitfield length < 8 and arbitrary source
9733 MOVA (aopGet (right, 0, FALSE, FALSE));
9734 /* shift and mask source value */
9736 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9739 /* transfer A to B and get next byte */
9740 emitPtrByteGet (rname, p_type, TRUE);
9742 emitcode ("anl", "a,#0x%02x", mask);
9743 emitcode ("orl", "a,b");
9744 if (p_type == GPOINTER)
9745 emitcode ("pop", "b");
9751 emitPtrByteSet (rname, p_type, "a");
9755 /* Bit length is greater than 7 bits. In this case, copy */
9756 /* all except the partial byte at the end */
9757 for (rlen=blen;rlen>=8;rlen-=8)
9759 emitPtrByteSet (rname, p_type,
9760 aopGet (right, offset++, FALSE, TRUE) );
9762 emitcode ("inc", "%s", rname);
9765 /* If there was a partial byte at the end */
9768 mask = (((unsigned char) -1 << rlen) & 0xff);
9770 if (AOP_TYPE (right) == AOP_LIT)
9772 /* Case with partial byte and literal source
9774 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9775 litval >>= (blen-rlen);
9776 litval &= (~mask) & 0xff;
9777 emitPtrByteGet (rname, p_type, FALSE);
9778 if ((mask|litval)!=0xff)
9779 emitcode ("anl","a,#0x%02x", mask);
9781 emitcode ("orl","a,#0x%02x", litval);
9786 /* Case with partial byte and arbitrary source
9788 MOVA (aopGet (right, offset++, FALSE, FALSE));
9789 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9792 /* transfer A to B and get next byte */
9793 emitPtrByteGet (rname, p_type, TRUE);
9795 emitcode ("anl", "a,#0x%02x", mask);
9796 emitcode ("orl", "a,b");
9797 if (p_type == GPOINTER)
9798 emitcode ("pop", "b");
9802 emitPtrByteSet (rname, p_type, "a");
9808 /*-----------------------------------------------------------------*/
9809 /* genDataPointerSet - remat pointer to data space */
9810 /*-----------------------------------------------------------------*/
9812 genDataPointerSet (operand * right,
9816 int size, offset = 0;
9817 char *l, buffer[256];
9819 D(emitcode ("; genDataPointerSet",""));
9821 aopOp (right, ic, FALSE);
9823 l = aopGet (result, 0, FALSE, TRUE);
9824 size = AOP_SIZE (right);
9828 sprintf (buffer, "(%s + %d)", l + 1, offset);
9830 sprintf (buffer, "%s", l + 1);
9831 emitcode ("mov", "%s,%s", buffer,
9832 aopGet (right, offset++, FALSE, FALSE));
9835 freeAsmop (right, NULL, ic, TRUE);
9836 freeAsmop (result, NULL, ic, TRUE);
9839 /*-----------------------------------------------------------------*/
9840 /* genNearPointerSet - emitcode for near pointer put */
9841 /*-----------------------------------------------------------------*/
9843 genNearPointerSet (operand * right,
9851 sym_link *retype, *letype;
9852 sym_link *ptype = operandType (result);
9854 D(emitcode ("; genNearPointerSet",""));
9856 retype = getSpec (operandType (right));
9857 letype = getSpec (ptype);
9858 aopOp (result, ic, FALSE);
9860 /* if the result is rematerializable &
9861 in data space & not a bit variable */
9862 if (AOP_TYPE (result) == AOP_IMMD &&
9863 DCL_TYPE (ptype) == POINTER &&
9864 !IS_BITVAR (retype) &&
9865 !IS_BITVAR (letype))
9867 genDataPointerSet (right, result, ic);
9871 /* if the value is already in a pointer register
9872 then don't need anything more */
9873 if (!AOP_INPREG (AOP (result)))
9876 //AOP_TYPE (result) == AOP_STK
9880 // Aha, it is a pointer, just in disguise.
9881 rname = aopGet (result, 0, FALSE, FALSE);
9884 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9885 __FILE__, __LINE__);
9890 emitcode ("mov", "a%s,%s", rname + 1, rname);
9891 rname++; // skip the '@'.
9896 /* otherwise get a free pointer register */
9898 preg = getFreePtr (ic, &aop, FALSE);
9899 emitcode ("mov", "%s,%s",
9901 aopGet (result, 0, FALSE, TRUE));
9907 rname = aopGet (result, 0, FALSE, FALSE);
9910 aopOp (right, ic, FALSE);
9912 /* if bitfield then unpack the bits */
9913 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9914 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
9917 /* we have can just get the values */
9918 int size = AOP_SIZE (right);
9923 l = aopGet (right, offset, FALSE, TRUE);
9927 emitcode ("mov", "@%s,a", rname);
9930 emitcode ("mov", "@%s,%s", rname, l);
9932 emitcode ("inc", "%s", rname);
9937 /* now some housekeeping stuff */
9938 if (aop) /* we had to allocate for this iCode */
9941 aopPut (result, rname, 0, isOperandVolatile (result, FALSE));
9942 freeAsmop (NULL, aop, ic, TRUE);
9946 /* we did not allocate which means left
9947 already in a pointer register, then
9948 if size > 0 && this could be used again
9949 we have to point it back to where it
9951 if ((AOP_SIZE (right) > 1 &&
9952 !OP_SYMBOL (result)->remat &&
9953 (OP_SYMBOL (result)->liveTo > ic->seq ||
9957 int size = AOP_SIZE (right) - 1;
9959 emitcode ("dec", "%s", rname);
9964 if (pi) pi->generated = 1;
9965 freeAsmop (result, NULL, ic, TRUE);
9966 freeAsmop (right, NULL, ic, TRUE);
9969 /*-----------------------------------------------------------------*/
9970 /* genPagedPointerSet - emitcode for Paged pointer put */
9971 /*-----------------------------------------------------------------*/
9973 genPagedPointerSet (operand * right,
9981 sym_link *retype, *letype;
9983 D(emitcode ("; genPagedPointerSet",""));
9985 retype = getSpec (operandType (right));
9986 letype = getSpec (operandType (result));
9988 aopOp (result, ic, FALSE);
9990 /* if the value is already in a pointer register
9991 then don't need anything more */
9992 if (!AOP_INPREG (AOP (result)))
9994 /* otherwise get a free pointer register */
9996 preg = getFreePtr (ic, &aop, FALSE);
9997 emitcode ("mov", "%s,%s",
9999 aopGet (result, 0, FALSE, TRUE));
10000 rname = preg->name;
10003 rname = aopGet (result, 0, FALSE, FALSE);
10005 aopOp (right, ic, FALSE);
10007 /* if bitfield then unpack the bits */
10008 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10009 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10012 /* we have can just get the values */
10013 int size = AOP_SIZE (right);
10018 l = aopGet (right, offset, FALSE, TRUE);
10021 emitcode ("movx", "@%s,a", rname);
10024 emitcode ("inc", "%s", rname);
10030 /* now some housekeeping stuff */
10031 if (aop) /* we had to allocate for this iCode */
10034 aopPut (result, rname, 0, isOperandVolatile (result, FALSE));
10035 freeAsmop (NULL, aop, ic, TRUE);
10039 /* we did not allocate which means left
10040 already in a pointer register, then
10041 if size > 0 && this could be used again
10042 we have to point it back to where it
10044 if (AOP_SIZE (right) > 1 &&
10045 !OP_SYMBOL (result)->remat &&
10046 (OP_SYMBOL (result)->liveTo > ic->seq ||
10049 int size = AOP_SIZE (right) - 1;
10051 emitcode ("dec", "%s", rname);
10056 if (pi) pi->generated = 1;
10057 freeAsmop (result, NULL, ic, TRUE);
10058 freeAsmop (right, NULL, ic, TRUE);
10063 /*-----------------------------------------------------------------*/
10064 /* genFarPointerSet - set value from far space */
10065 /*-----------------------------------------------------------------*/
10067 genFarPointerSet (operand * right,
10068 operand * result, iCode * ic, iCode * pi)
10071 sym_link *retype = getSpec (operandType (right));
10072 sym_link *letype = getSpec (operandType (result));
10074 D(emitcode ("; genFarPointerSet",""));
10076 aopOp (result, ic, FALSE);
10077 loadDptrFromOperand (result, FALSE);
10079 /* so dptr know contains the address */
10080 aopOp (right, ic, FALSE);
10082 /* if bit then unpack */
10083 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10084 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10087 size = AOP_SIZE (right);
10092 char *l = aopGet (right, offset++, FALSE, FALSE);
10094 emitcode ("movx", "@dptr,a");
10096 emitcode ("inc", "dptr");
10099 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10100 aopPut (result, "dpl", 0, isOperandVolatile (result, FALSE));
10101 aopPut (result, "dph", 1, isOperandVolatile (result, FALSE));
10104 freeAsmop (result, NULL, ic, TRUE);
10105 freeAsmop (right, NULL, ic, TRUE);
10108 /*-----------------------------------------------------------------*/
10109 /* genGenPointerSet - set value from generic pointer space */
10110 /*-----------------------------------------------------------------*/
10112 genGenPointerSet (operand * right,
10113 operand * result, iCode * ic, iCode * pi)
10116 sym_link *retype = getSpec (operandType (right));
10117 sym_link *letype = getSpec (operandType (result));
10119 D(emitcode ("; genGenPointerSet",""));
10121 aopOp (result, ic, FALSE);
10122 loadDptrFromOperand (result, TRUE);
10124 /* so dptr know contains the address */
10125 aopOp (right, ic, FALSE);
10127 /* if bit then unpack */
10128 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10129 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10132 size = AOP_SIZE (right);
10137 char *l = aopGet (right, offset++, FALSE, FALSE);
10139 emitcode ("lcall", "__gptrput");
10141 emitcode ("inc", "dptr");
10145 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10146 aopPut (result, "dpl", 0, isOperandVolatile (result, FALSE));
10147 aopPut (result, "dph", 1, isOperandVolatile (result, FALSE));
10150 freeAsmop (result, NULL, ic, TRUE);
10151 freeAsmop (right, NULL, ic, TRUE);
10154 /*-----------------------------------------------------------------*/
10155 /* genPointerSet - stores the value into a pointer location */
10156 /*-----------------------------------------------------------------*/
10158 genPointerSet (iCode * ic, iCode *pi)
10160 operand *right, *result;
10161 sym_link *type, *etype;
10164 D(emitcode ("; genPointerSet",""));
10166 right = IC_RIGHT (ic);
10167 result = IC_RESULT (ic);
10169 /* depending on the type of pointer we need to
10170 move it to the correct pointer register */
10171 type = operandType (result);
10172 etype = getSpec (type);
10173 /* if left is of type of pointer then it is simple */
10174 if (IS_PTR (type) && !IS_FUNC (type->next))
10176 p_type = DCL_TYPE (type);
10180 /* we have to go by the storage class */
10181 p_type = PTR_TYPE (SPEC_OCLS (etype));
10184 /* special case when cast remat */
10185 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10186 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10187 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10188 type = operandType (result);
10189 p_type = DCL_TYPE (type);
10191 /* now that we have the pointer type we assign
10192 the pointer values */
10198 genNearPointerSet (right, result, ic, pi);
10202 genPagedPointerSet (right, result, ic, pi);
10206 genFarPointerSet (right, result, ic, pi);
10210 genGenPointerSet (right, result, ic, pi);
10214 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10215 "genPointerSet: illegal pointer type");
10220 /*-----------------------------------------------------------------*/
10221 /* genIfx - generate code for Ifx statement */
10222 /*-----------------------------------------------------------------*/
10224 genIfx (iCode * ic, iCode * popIc)
10226 operand *cond = IC_COND (ic);
10230 D(emitcode ("; genIfx",""));
10232 aopOp (cond, ic, FALSE);
10234 /* get the value into acc */
10235 if (AOP_TYPE (cond) != AOP_CRY)
10240 if (AOP(cond)->aopu.aop_dir)
10241 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10243 /* the result is now in the accumulator or a directly addressable bit */
10244 freeAsmop (cond, NULL, ic, TRUE);
10246 /* if there was something to be popped then do it */
10250 /* if the condition is a bit variable */
10252 genIfxJump(ic, dup, NULL, NULL, NULL);
10253 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10254 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10255 else if (isbit && !IS_ITEMP (cond))
10256 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10258 genIfxJump (ic, "a", NULL, NULL, NULL);
10263 /*-----------------------------------------------------------------*/
10264 /* genAddrOf - generates code for address of */
10265 /*-----------------------------------------------------------------*/
10267 genAddrOf (iCode * ic)
10269 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10272 D(emitcode ("; genAddrOf",""));
10274 aopOp (IC_RESULT (ic), ic, FALSE);
10276 /* if the operand is on the stack then we
10277 need to get the stack offset of this
10281 /* if it has an offset then we need to compute
10285 emitcode ("mov", "a,%s", SYM_BP (sym));
10286 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
10287 ((char) (sym->stack - _G.nRegsSaved)) :
10288 ((char) sym->stack)) & 0xff);
10289 aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10293 /* we can just move _bp */
10294 aopPut (IC_RESULT (ic), SYM_BP (sym), 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10296 /* fill the result with zero */
10297 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10302 aopPut (IC_RESULT (ic), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10308 /* object not on stack then we need the name */
10309 size = AOP_SIZE (IC_RESULT (ic));
10314 char s[SDCC_NAME_MAX];
10316 sprintf (s, "#(%s >> %d)",
10320 sprintf (s, "#%s", sym->rname);
10321 aopPut (IC_RESULT (ic), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10325 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10329 /*-----------------------------------------------------------------*/
10330 /* genFarFarAssign - assignment when both are in far space */
10331 /*-----------------------------------------------------------------*/
10333 genFarFarAssign (operand * result, operand * right, iCode * ic)
10335 int size = AOP_SIZE (right);
10339 D(emitcode ("; genFarFarAssign",""));
10341 /* first push the right side on to the stack */
10344 l = aopGet (right, offset++, FALSE, FALSE);
10346 emitcode ("push", "acc");
10349 freeAsmop (right, NULL, ic, FALSE);
10350 /* now assign DPTR to result */
10351 aopOp (result, ic, FALSE);
10352 size = AOP_SIZE (result);
10355 emitcode ("pop", "acc");
10356 aopPut (result, "a", --offset, isOperandVolatile (result, FALSE));
10358 freeAsmop (result, NULL, ic, FALSE);
10362 /*-----------------------------------------------------------------*/
10363 /* genAssign - generate code for assignment */
10364 /*-----------------------------------------------------------------*/
10366 genAssign (iCode * ic)
10368 operand *result, *right;
10370 unsigned long lit = 0L;
10372 D(emitcode("; genAssign",""));
10374 result = IC_RESULT (ic);
10375 right = IC_RIGHT (ic);
10377 /* if they are the same */
10378 if (operandsEqu (result, right) &&
10379 !isOperandVolatile (result, FALSE) &&
10380 !isOperandVolatile (right, FALSE))
10383 aopOp (right, ic, FALSE);
10385 /* special case both in far space */
10386 if (AOP_TYPE (right) == AOP_DPTR &&
10387 IS_TRUE_SYMOP (result) &&
10388 isOperandInFarSpace (result))
10391 genFarFarAssign (result, right, ic);
10395 aopOp (result, ic, TRUE);
10397 /* if they are the same registers */
10398 if (sameRegs (AOP (right), AOP (result)) &&
10399 !isOperandVolatile (result, FALSE) &&
10400 !isOperandVolatile (right, FALSE))
10403 /* if the result is a bit */
10404 if (AOP_TYPE (result) == AOP_CRY)
10407 /* if the right size is a literal then
10408 we know what the value is */
10409 if (AOP_TYPE (right) == AOP_LIT)
10411 if (((int) operandLitValue (right)))
10412 aopPut (result, one, 0, isOperandVolatile (result, FALSE));
10414 aopPut (result, zero, 0, isOperandVolatile (result, FALSE));
10418 /* the right is also a bit variable */
10419 if (AOP_TYPE (right) == AOP_CRY)
10421 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10422 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
10426 /* we need to or */
10428 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
10432 /* bit variables done */
10434 size = AOP_SIZE (result);
10436 if (AOP_TYPE (right) == AOP_LIT)
10437 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10439 (AOP_TYPE (result) != AOP_REG) &&
10440 (AOP_TYPE (right) == AOP_LIT) &&
10441 !IS_FLOAT (operandType (right)) &&
10444 while ((size) && (lit))
10447 aopGet (right, offset, FALSE, FALSE),
10449 isOperandVolatile (result, FALSE));
10454 emitcode ("clr", "a");
10457 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
10466 aopGet (right, offset, FALSE, FALSE),
10468 isOperandVolatile (result, FALSE));
10474 freeAsmop (right, NULL, ic, TRUE);
10475 freeAsmop (result, NULL, ic, TRUE);
10478 /*-----------------------------------------------------------------*/
10479 /* genJumpTab - generates code for jump table */
10480 /*-----------------------------------------------------------------*/
10482 genJumpTab (iCode * ic)
10484 symbol *jtab,*jtablo,*jtabhi;
10486 unsigned int count;
10488 D(emitcode ("; genJumpTab",""));
10490 count = elementsInSet( IC_JTLABELS (ic) );
10494 /* this algorithm needs 9 cycles and 7 + 3*n bytes
10495 if the switch argument is in a register.
10496 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
10497 /* (MB) What if peephole converts ljmp to sjmp or ret ???
10498 How will multiply by three be updated ???*/
10499 aopOp (IC_JTCOND (ic), ic, FALSE);
10500 /* get the condition into accumulator */
10501 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10503 /* multiply by three */
10504 emitcode ("add", "a,acc");
10505 emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
10506 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10508 jtab = newiTempLabel (NULL);
10509 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
10510 emitcode ("jmp", "@a+dptr");
10511 emitcode ("", "%05d$:", jtab->key + 100);
10512 /* now generate the jump labels */
10513 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10514 jtab = setNextItem (IC_JTLABELS (ic)))
10515 emitcode ("ljmp", "%05d$", jtab->key + 100);
10519 /* this algorithm needs 14 cycles and 13 + 2*n bytes
10520 if the switch argument is in a register.
10521 For n>6 this algorithm may be more compact */
10522 jtablo = newiTempLabel (NULL);
10523 jtabhi = newiTempLabel (NULL);
10525 /* get the condition into accumulator.
10526 Using b as temporary storage, if register push/pop is needed */
10527 aopOp (IC_JTCOND (ic), ic, FALSE);
10528 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10529 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
10530 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
10532 // (MB) what if B is in use???
10533 wassertl(!BINUSE, "B was in use");
10534 emitcode ("mov", "b,%s", l);
10537 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10541 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
10542 emitcode ("movc", "a,@a+pc");
10543 emitcode ("push", "acc");
10546 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
10547 emitcode ("movc", "a,@a+pc");
10548 emitcode ("push", "acc");
10552 /* this scales up to n<=255, but needs two more bytes
10553 and changes dptr */
10554 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
10555 emitcode ("movc", "a,@a+dptr");
10556 emitcode ("push", "acc");
10559 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
10560 emitcode ("movc", "a,@a+dptr");
10561 emitcode ("push", "acc");
10564 emitcode ("ret", "");
10566 /* now generate jump table, LSB */
10567 emitcode ("", "%05d$:", jtablo->key + 100);
10568 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10569 jtab = setNextItem (IC_JTLABELS (ic)))
10570 emitcode (".db", "%05d$", jtab->key + 100);
10572 /* now generate jump table, MSB */
10573 emitcode ("", "%05d$:", jtabhi->key + 100);
10574 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10575 jtab = setNextItem (IC_JTLABELS (ic)))
10576 emitcode (".db", "%05d$>>8", jtab->key + 100);
10580 /*-----------------------------------------------------------------*/
10581 /* genCast - gen code for casting */
10582 /*-----------------------------------------------------------------*/
10584 genCast (iCode * ic)
10586 operand *result = IC_RESULT (ic);
10587 sym_link *ctype = operandType (IC_LEFT (ic));
10588 sym_link *rtype = operandType (IC_RIGHT (ic));
10589 operand *right = IC_RIGHT (ic);
10592 D(emitcode("; genCast",""));
10594 /* if they are equivalent then do nothing */
10595 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10598 aopOp (right, ic, FALSE);
10599 aopOp (result, ic, FALSE);
10601 /* if the result is a bit (and not a bitfield) */
10602 // if (AOP_TYPE (result) == AOP_CRY)
10603 if (IS_BITVAR (OP_SYMBOL (result)->type)
10604 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
10606 /* if the right size is a literal then
10607 we know what the value is */
10608 if (AOP_TYPE (right) == AOP_LIT)
10610 if (((int) operandLitValue (right)))
10611 aopPut (result, one, 0, isOperandVolatile (result, FALSE));
10613 aopPut (result, zero, 0, isOperandVolatile (result, FALSE));
10618 /* the right is also a bit variable */
10619 if (AOP_TYPE (right) == AOP_CRY)
10621 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10622 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
10626 /* we need to or */
10628 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
10633 /* if they are the same size : or less */
10634 if (AOP_SIZE (result) <= AOP_SIZE (right))
10637 /* if they are in the same place */
10638 if (sameRegs (AOP (right), AOP (result)))
10641 /* if they in different places then copy */
10642 size = AOP_SIZE (result);
10647 aopGet (right, offset, FALSE, FALSE),
10649 isOperandVolatile (result, FALSE));
10656 /* if the result is of type pointer */
10657 if (IS_PTR (ctype))
10661 sym_link *type = operandType (right);
10662 sym_link *etype = getSpec (type);
10664 /* pointer to generic pointer */
10665 if (IS_GENPTR (ctype))
10668 p_type = DCL_TYPE (type);
10671 if (SPEC_SCLS(etype)==S_REGISTER) {
10672 // let's assume it is a generic pointer
10675 /* we have to go by the storage class */
10676 p_type = PTR_TYPE (SPEC_OCLS (etype));
10680 /* the first two bytes are known */
10681 size = GPTRSIZE - 1;
10686 aopGet (right, offset, FALSE, FALSE),
10688 isOperandVolatile (result, FALSE));
10691 /* the last byte depending on type */
10693 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
10698 // pointerTypeToGPByte will have bitched.
10702 sprintf(gpValStr, "#0x%x", gpVal);
10703 aopPut (result, gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
10708 /* just copy the pointers */
10709 size = AOP_SIZE (result);
10714 aopGet (right, offset, FALSE, FALSE),
10716 isOperandVolatile (result, FALSE));
10722 /* so we now know that the size of destination is greater
10723 than the size of the source */
10724 /* we move to result for the size of source */
10725 size = AOP_SIZE (right);
10730 aopGet (right, offset, FALSE, FALSE),
10732 isOperandVolatile (result, FALSE));
10736 /* now depending on the sign of the source && destination */
10737 size = AOP_SIZE (result) - AOP_SIZE (right);
10738 /* if unsigned or not an integral type */
10739 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
10742 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
10746 /* we need to extend the sign :{ */
10747 char *l = aopGet (right, AOP_SIZE (right) - 1,
10750 emitcode ("rlc", "a");
10751 emitcode ("subb", "a,acc");
10753 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
10756 /* we are done hurray !!!! */
10759 freeAsmop (right, NULL, ic, TRUE);
10760 freeAsmop (result, NULL, ic, TRUE);
10764 /*-----------------------------------------------------------------*/
10765 /* genDjnz - generate decrement & jump if not zero instrucion */
10766 /*-----------------------------------------------------------------*/
10768 genDjnz (iCode * ic, iCode * ifx)
10770 symbol *lbl, *lbl1;
10774 D(emitcode ("; genDjnz",""));
10776 /* if the if condition has a false label
10777 then we cannot save */
10778 if (IC_FALSE (ifx))
10781 /* if the minus is not of the form
10783 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10784 !IS_OP_LITERAL (IC_RIGHT (ic)))
10787 if (operandLitValue (IC_RIGHT (ic)) != 1)
10790 /* if the size of this greater than one then no
10792 if (getSize (operandType (IC_RESULT (ic))) > 1)
10795 /* otherwise we can save BIG */
10796 lbl = newiTempLabel (NULL);
10797 lbl1 = newiTempLabel (NULL);
10799 aopOp (IC_RESULT (ic), ic, FALSE);
10801 if (AOP_NEEDSACC(IC_RESULT(ic)))
10803 /* If the result is accessed indirectly via
10804 * the accumulator, we must explicitly write
10805 * it back after the decrement.
10807 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
10809 if (strcmp(rByte, "a"))
10811 /* Something is hopelessly wrong */
10812 fprintf(stderr, "*** warning: internal error at %s:%d\n",
10813 __FILE__, __LINE__);
10814 /* We can just give up; the generated code will be inefficient,
10815 * but what the hey.
10817 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10820 emitcode ("dec", "%s", rByte);
10821 aopPut (IC_RESULT (ic), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10822 emitcode ("jnz", "%05d$", lbl->key + 100);
10824 else if (IS_AOP_PREG (IC_RESULT (ic)))
10826 emitcode ("dec", "%s",
10827 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
10828 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
10829 emitcode ("jnz", "%05d$", lbl->key + 100);
10833 emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
10836 emitcode ("sjmp", "%05d$", lbl1->key + 100);
10837 emitcode ("", "%05d$:", lbl->key + 100);
10838 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
10839 emitcode ("", "%05d$:", lbl1->key + 100);
10841 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10842 ifx->generated = 1;
10846 /*-----------------------------------------------------------------*/
10847 /* genReceive - generate code for a receive iCode */
10848 /*-----------------------------------------------------------------*/
10850 genReceive (iCode * ic)
10852 int size = getSize (operandType (IC_RESULT (ic)));
10855 D(emitcode ("; genReceive",""));
10857 if (ic->argreg == 1)
10858 { /* first parameter */
10859 if (isOperandInFarSpace (IC_RESULT (ic)) &&
10860 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10861 IS_TRUE_SYMOP (IC_RESULT (ic))))
10864 int receivingA = 0;
10867 for (offset = 0; offset<size; offset++)
10868 if (!strcmp (fReturn[offset], "a"))
10873 if (size==1 || getTempRegs(tempRegs, size-1, ic))
10875 for (offset = size-1; offset>0; offset--)
10876 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
10877 emitcode("mov","a,%s", fReturn[0]);
10879 aopOp (IC_RESULT (ic), ic, FALSE);
10881 aopPut (IC_RESULT (ic), "a", offset,
10882 isOperandVolatile (IC_RESULT (ic), FALSE));
10883 for (offset = 1; offset<size; offset++)
10884 aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset,
10885 isOperandVolatile (IC_RESULT (ic), FALSE));
10891 if (getTempRegs(tempRegs, size, ic))
10893 for (offset = 0; offset<size; offset++)
10894 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
10895 aopOp (IC_RESULT (ic), ic, FALSE);
10896 for (offset = 0; offset<size; offset++)
10897 aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset,
10898 isOperandVolatile (IC_RESULT (ic), FALSE));
10903 offset = fReturnSizeMCS51 - size;
10906 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
10907 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
10910 aopOp (IC_RESULT (ic), ic, FALSE);
10911 size = AOP_SIZE (IC_RESULT (ic));
10915 emitcode ("pop", "acc");
10916 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10922 aopOp (IC_RESULT (ic), ic, FALSE);
10924 assignResultValue (IC_RESULT (ic), NULL);
10927 else if (ic->argreg > 12)
10928 { /* bit parameters */
10929 if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
10931 aopOp (IC_RESULT (ic), ic, FALSE);
10932 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
10933 outBitC(IC_RESULT (ic));
10937 { /* other parameters */
10939 aopOp (IC_RESULT (ic), ic, FALSE);
10940 rb1off = ic->argreg;
10943 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10948 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10951 /*-----------------------------------------------------------------*/
10952 /* genDummyRead - generate code for dummy read of volatiles */
10953 /*-----------------------------------------------------------------*/
10955 genDummyRead (iCode * ic)
10960 D(emitcode("; genDummyRead",""));
10962 op = IC_RIGHT (ic);
10963 if (op && IS_SYMOP (op))
10965 aopOp (op, ic, FALSE);
10967 /* if the result is a bit */
10968 if (AOP_TYPE (op) == AOP_CRY)
10969 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
10972 /* bit variables done */
10974 size = AOP_SIZE (op);
10978 MOVA (aopGet (op, offset, FALSE, FALSE));
10983 freeAsmop (op, NULL, ic, TRUE);
10987 if (op && IS_SYMOP (op))
10989 aopOp (op, ic, FALSE);
10991 /* if the result is a bit */
10992 if (AOP_TYPE (op) == AOP_CRY)
10993 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
10996 /* bit variables done */
10998 size = AOP_SIZE (op);
11002 MOVA (aopGet (op, offset, FALSE, FALSE));
11007 freeAsmop (op, NULL, ic, TRUE);
11011 /*-----------------------------------------------------------------*/
11012 /* genCritical - generate code for start of a critical sequence */
11013 /*-----------------------------------------------------------------*/
11015 genCritical (iCode *ic)
11017 symbol *tlbl = newiTempLabel (NULL);
11019 D(emitcode("; genCritical",""));
11021 if (IC_RESULT (ic))
11023 aopOp (IC_RESULT (ic), ic, TRUE);
11024 aopPut (IC_RESULT (ic), one, 0, 0);
11025 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11026 aopPut (IC_RESULT (ic), zero, 0, 0);
11027 emitcode ("", "%05d$:", (tlbl->key + 100));
11028 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11032 emitcode ("setb", "c");
11033 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11034 emitcode ("clr", "c");
11035 emitcode ("", "%05d$:", (tlbl->key + 100));
11036 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11040 /*-----------------------------------------------------------------*/
11041 /* genEndCritical - generate code for end of a critical sequence */
11042 /*-----------------------------------------------------------------*/
11044 genEndCritical (iCode *ic)
11046 D(emitcode("; genEndCritical",""));
11050 aopOp (IC_RIGHT (ic), ic, FALSE);
11051 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11053 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11054 emitcode ("mov", "ea,c");
11058 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11059 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11060 emitcode ("rrc", "a");
11061 emitcode ("mov", "ea,c");
11063 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11067 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11068 emitcode ("mov", "ea,c");
11072 /*-----------------------------------------------------------------*/
11073 /* gen51Code - generate code for 8051 based controllers */
11074 /*-----------------------------------------------------------------*/
11076 gen51Code (iCode * lic)
11080 /* int cseq = 0; */
11082 _G.currentFunc = NULL;
11083 lineHead = lineCurr = NULL;
11085 /* print the allocation information */
11086 if (allocInfo && currFunc)
11087 printAllocInfo (currFunc, codeOutFile);
11088 /* if debug information required */
11089 if (options.debug && currFunc)
11091 debugFile->writeFunction (currFunc, lic);
11093 /* stack pointer name */
11094 if (options.useXstack)
11100 for (ic = lic; ic; ic = ic->next)
11102 _G.current_iCode = ic;
11104 if (ic->lineno && cln != ic->lineno)
11108 debugFile->writeCLine (ic);
11110 if (!options.noCcodeInAsm) {
11111 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
11112 printCLine(ic->filename, ic->lineno));
11117 if (ic->seqPoint && ic->seqPoint != cseq)
11119 emitcode ("", "; sequence point %d", ic->seqPoint);
11120 cseq = ic->seqPoint;
11123 if (options.iCodeInAsm) {
11124 char regsInUse[80];
11127 for (i=0; i<8; i++) {
11128 sprintf (®sInUse[i],
11129 "%c", ic->riu & (1<<i) ? i+'0' : '-');
11132 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
11134 /* if the result is marked as
11135 spilt and rematerializable or code for
11136 this has already been generated then
11138 if (resultRemat (ic) || ic->generated)
11141 /* depending on the operation */
11161 /* IPOP happens only when trying to restore a
11162 spilt live range, if there is an ifx statement
11163 following this pop then the if statement might
11164 be using some of the registers being popped which
11165 would destory the contents of the register so
11166 we need to check for this condition and handle it */
11168 ic->next->op == IFX &&
11169 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11170 genIfx (ic->next, ic);
11188 genEndFunction (ic);
11208 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11225 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11229 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11236 /* note these two are xlated by algebraic equivalence
11237 during parsing SDCC.y */
11238 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11239 "got '>=' or '<=' shouldn't have come here");
11243 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11255 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11259 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11263 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11299 genRightShift (ic);
11302 case GET_VALUE_AT_ADDRESS:
11304 hasInc (IC_LEFT (ic), ic,
11305 getSize (operandType (IC_RESULT (ic)))),
11306 ifxForOp (IC_RESULT (ic), ic) );
11310 if (POINTER_SET (ic))
11311 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
11337 addSet (&_G.sendSet, ic);
11340 case DUMMY_READ_VOLATILE:
11349 genEndCritical (ic);
11361 _G.current_iCode = NULL;
11363 /* now we are ready to call the
11364 peep hole optimizer */
11365 if (!options.nopeep)
11366 peepHole (&lineHead);
11368 /* now do the actual printing */
11369 printLine (lineHead, codeOutFile);