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 (*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 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1749 emitcode ("cpl", "c");
1750 outBitC (IC_RESULT (ic));
1754 toBoolean (IC_LEFT (ic));
1756 tlbl = newiTempLabel (NULL);
1757 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1758 emitcode ("", "%05d$:", tlbl->key + 100);
1759 outBitC (IC_RESULT (ic));
1762 /* release the aops */
1763 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1764 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1768 /*-----------------------------------------------------------------*/
1769 /* genCpl - generate code for complement */
1770 /*-----------------------------------------------------------------*/
1777 sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
1779 D(emitcode (";", "genCpl"));
1781 /* assign asmOps to operand & result */
1782 aopOp (IC_LEFT (ic), ic, FALSE);
1783 aopOp (IC_RESULT (ic), ic, TRUE);
1785 /* special case if in bit space */
1786 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1790 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
1791 (SPEC_USIGN (letype) && IS_CHAR (letype)))
1793 /* promotion rules are responsible for this strange result:
1794 bit -> int -> ~int -> bit
1795 uchar -> int -> ~int -> bit
1797 werror(W_COMPLEMENT);
1798 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
1802 tlbl=newiTempLabel(NULL);
1803 l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
1804 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
1805 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1806 IS_AOP_PREG (IC_LEFT (ic)))
1808 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
1813 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
1815 emitcode ("", "%05d$:", tlbl->key + 100);
1816 outBitC (IC_RESULT(ic));
1820 size = AOP_SIZE (IC_RESULT (ic));
1823 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
1825 emitcode ("cpl", "a");
1826 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1831 /* release the aops */
1832 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1833 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1836 /*-----------------------------------------------------------------*/
1837 /* genUminusFloat - unary minus for floating points */
1838 /*-----------------------------------------------------------------*/
1840 genUminusFloat (operand * op, operand * result)
1842 int size, offset = 0;
1845 D(emitcode ("; genUminusFloat",""));
1847 /* for this we just copy and then flip the bit */
1849 size = AOP_SIZE (op) - 1;
1854 aopGet (op, offset, FALSE, FALSE),
1856 isOperandVolatile (result, FALSE));
1860 l = aopGet (op, offset, FALSE, FALSE);
1864 emitcode ("cpl", "acc.7");
1865 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
1868 /*-----------------------------------------------------------------*/
1869 /* genUminus - unary minus code generation */
1870 /*-----------------------------------------------------------------*/
1872 genUminus (iCode * ic)
1875 sym_link *optype, *rtype;
1878 D(emitcode ("; genUminus",""));
1881 aopOp (IC_LEFT (ic), ic, FALSE);
1882 aopOp (IC_RESULT (ic), ic, TRUE);
1884 /* if both in bit space then special
1886 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1887 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1890 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1891 emitcode ("cpl", "c");
1892 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1896 optype = operandType (IC_LEFT (ic));
1897 rtype = operandType (IC_RESULT (ic));
1899 /* if float then do float stuff */
1900 if (IS_FLOAT (optype))
1902 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1906 /* otherwise subtract from zero */
1907 size = AOP_SIZE (IC_LEFT (ic));
1912 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
1913 if (!strcmp (l, "a"))
1917 emitcode ("cpl", "a");
1918 emitcode ("addc", "a,#0");
1924 emitcode ("clr", "a");
1925 emitcode ("subb", "a,%s", l);
1927 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1930 /* if any remaining bytes in the result */
1931 /* we just need to propagate the sign */
1932 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1934 emitcode ("rlc", "a");
1935 emitcode ("subb", "a,acc");
1937 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1941 /* release the aops */
1942 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1943 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1946 /*-----------------------------------------------------------------*/
1947 /* saveRegisters - will look for a call and save the registers */
1948 /*-----------------------------------------------------------------*/
1950 saveRegisters (iCode * lic)
1957 for (ic = lic; ic; ic = ic->next)
1958 if (ic->op == CALL || ic->op == PCALL)
1963 fprintf (stderr, "found parameter push with no function call\n");
1967 /* if the registers have been saved already or don't need to be then
1971 if (IS_SYMOP(IC_LEFT(ic)) &&
1972 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1973 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
1976 /* save the registers in use at this time but skip the
1977 ones for the result */
1978 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1979 mcs51_rUmaskForOp (IC_RESULT(ic)));
1982 if (options.useXstack)
1984 int count = bitVectnBitsOn (rsave);
1988 regs * reg = mcs51_regWithIdx (bitVectFirstBit (rsave));
1989 if (reg->type == REG_BIT)
1991 emitcode ("mov", "a,%s", reg->base);
1995 emitcode ("mov", "a,%s", reg->name);
1997 emitcode ("mov", "r0,%s", spname);
1998 emitcode ("inc", "%s", spname);// allocate before use
1999 emitcode ("movx", "@r0,a");
2000 if (bitVectBitValue (rsave, R0_IDX))
2001 emitcode ("mov", "r0,a");
2003 else if (count != 0)
2005 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2006 int nBits = bitVectnBitsOn (rsavebits);
2010 count = count - nBits + 1;
2011 /* remove all but the first bits as they are pushed all at once */
2012 rsave = bitVectCplAnd (rsave, rsavebits);
2013 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2016 if (bitVectBitValue (rsave, R0_IDX))
2018 emitcode ("push", "%s", mcs51_regWithIdx (R0_IDX)->dname);
2020 emitcode ("mov", "r0,%s", spname);
2022 emitcode ("add", "a,#%d", count);
2023 emitcode ("mov", "%s,a", spname);
2024 for (i = 0; i < mcs51_nRegs; i++)
2026 if (bitVectBitValue (rsave, i))
2028 regs * reg = mcs51_regWithIdx (i);
2031 emitcode ("pop", "acc");
2032 emitcode ("push", "acc");
2034 else if (reg->type == REG_BIT)
2036 emitcode ("mov", "a,%s", reg->base);
2040 emitcode ("mov", "a,%s", reg->name);
2042 emitcode ("movx", "@r0,a");
2045 emitcode ("inc", "r0");
2049 if (bitVectBitValue (rsave, R0_IDX))
2051 emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
2057 bool bits_pushed = FALSE;
2058 for (i = 0; i < mcs51_nRegs; i++)
2060 if (bitVectBitValue (rsave, i))
2062 bits_pushed = pushReg (i, bits_pushed);
2068 /*-----------------------------------------------------------------*/
2069 /* unsaveRegisters - pop the pushed registers */
2070 /*-----------------------------------------------------------------*/
2072 unsaveRegisters (iCode * ic)
2077 /* restore the registers in use at this time but skip the
2078 ones for the result */
2079 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2080 mcs51_rUmaskForOp (IC_RESULT(ic)));
2082 if (options.useXstack)
2084 int count = bitVectnBitsOn (rsave);
2088 regs * reg = mcs51_regWithIdx (bitVectFirstBit (rsave));
2089 emitcode ("mov", "r0,%s", spname);
2090 emitcode ("dec", "r0");
2091 emitcode ("movx", "a,@r0");
2092 if (reg->type == REG_BIT)
2094 emitcode ("mov", "%s,a", reg->base);
2098 emitcode ("mov", "%s,a", reg->name);
2100 emitcode ("dec", "%s", spname);
2102 else if (count != 0)
2104 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2105 int nBits = bitVectnBitsOn (rsavebits);
2109 count = count - nBits + 1;
2110 /* remove all but the first bits as they are popped all at once */
2111 rsave = bitVectCplAnd (rsave, rsavebits);
2112 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2115 emitcode ("mov", "r0,%s", spname);
2116 for (i = mcs51_nRegs; i >= 0; i--)
2118 if (bitVectBitValue (rsave, i))
2120 regs * reg = mcs51_regWithIdx (i);
2121 emitcode ("dec", "r0");
2122 emitcode ("movx", "a,@r0");
2125 emitcode ("push", "acc");
2127 else if (reg->type == REG_BIT)
2129 emitcode ("mov", "%s,a", reg->base);
2133 emitcode ("mov", "%s,a", reg->name);
2137 emitcode ("mov", "%s,r0", spname);
2138 if (bitVectBitValue (rsave, R0_IDX))
2140 emitcode ("pop", "ar0");
2146 bool bits_popped = FALSE;
2147 for (i = mcs51_nRegs; i >= 0; i--)
2149 if (bitVectBitValue (rsave, i))
2151 bits_popped = popReg (i, bits_popped);
2158 /*-----------------------------------------------------------------*/
2160 /*-----------------------------------------------------------------*/
2162 pushSide (operand * oper, int size)
2167 char *l = aopGet (oper, offset++, FALSE, TRUE);
2168 if (AOP_TYPE (oper) != AOP_REG &&
2169 AOP_TYPE (oper) != AOP_DIR &&
2173 emitcode ("push", "acc");
2177 emitcode ("push", "%s", l);
2182 /*-----------------------------------------------------------------*/
2183 /* assignResultValue - also indicates if acc is in use afterwards */
2184 /*-----------------------------------------------------------------*/
2186 assignResultValue (operand * oper, operand * func)
2189 int size = AOP_SIZE (oper);
2190 bool accuse = FALSE;
2192 if (func && IS_BIT (OP_SYM_ETYPE (func)))
2200 accuse |= aopPut (oper, fReturn[offset], offset, isOperandVolatile (oper, FALSE));
2207 /*-----------------------------------------------------------------*/
2208 /* genXpush - pushes onto the external stack */
2209 /*-----------------------------------------------------------------*/
2211 genXpush (iCode * ic)
2213 asmop *aop = newAsmop (0);
2215 int size, offset = 0;
2217 D(emitcode ("; genXpush",""));
2219 aopOp (IC_LEFT (ic), ic, FALSE);
2220 r = getFreePtr (ic, &aop, FALSE);
2222 size = AOP_SIZE (IC_LEFT (ic));
2226 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2227 emitcode ("mov", "%s,%s", r->name, spname);
2228 emitcode ("inc", "%s", spname); // allocate space first
2229 emitcode ("movx", "@%s,a", r->name);
2233 // allocate space first
2234 emitcode ("mov", "%s,%s", r->name, spname);
2236 emitcode ("add", "a,#%d", size);
2237 emitcode ("mov", "%s,a", spname);
2241 MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2242 emitcode ("movx", "@%s,a", r->name);
2243 emitcode ("inc", "%s", r->name);
2247 freeAsmop (NULL, aop, ic, TRUE);
2248 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2251 /*-----------------------------------------------------------------*/
2252 /* genIpush - generate code for pushing this gets a little complex */
2253 /*-----------------------------------------------------------------*/
2255 genIpush (iCode * ic)
2257 int size, offset = 0;
2261 D(emitcode ("; genIpush",""));
2263 /* if this is not a parm push : ie. it is spill push
2264 and spill push is always done on the local stack */
2268 /* and the item is spilt then do nothing */
2269 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2272 aopOp (IC_LEFT (ic), ic, FALSE);
2273 size = AOP_SIZE (IC_LEFT (ic));
2274 /* push it on the stack */
2277 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2283 emitcode ("push", "%s", l);
2288 /* this is a parameter push: in this case we call
2289 the routine to find the call and save those
2290 registers that need to be saved */
2293 /* if use external stack then call the external
2294 stack pushing routine */
2295 if (options.useXstack)
2301 /* then do the push */
2302 aopOp (IC_LEFT (ic), ic, FALSE);
2304 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2305 size = AOP_SIZE (IC_LEFT (ic));
2309 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2310 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2311 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2314 if (strcmp (l, prev) || *l == '@')
2316 emitcode ("push", "acc");
2320 emitcode ("push", "%s", l);
2325 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2328 /*-----------------------------------------------------------------*/
2329 /* genIpop - recover the registers: can happen only for spilling */
2330 /*-----------------------------------------------------------------*/
2332 genIpop (iCode * ic)
2336 D(emitcode ("; genIpop",""));
2338 /* if the temp was not pushed then */
2339 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2342 aopOp (IC_LEFT (ic), ic, FALSE);
2343 size = AOP_SIZE (IC_LEFT (ic));
2344 offset = (size - 1);
2346 emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2349 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2352 /*-----------------------------------------------------------------*/
2353 /* saveRBank - saves an entire register bank on the stack */
2354 /*-----------------------------------------------------------------*/
2356 saveRBank (int bank, iCode * ic, bool pushPsw)
2359 int count = mcs51_nRegs + (pushPsw ? 1 : 0);
2363 if (options.useXstack)
2367 /* Assume r0 is available for use. */
2368 r = mcs51_regWithIdx (R0_IDX);;
2373 r = getFreePtr (ic, &aop, FALSE);
2375 // allocate space first
2376 emitcode ("mov", "%s,%s", r->name, spname);
2378 emitcode ("add", "a,#%d", count);
2379 emitcode ("mov", "%s,a", spname);
2382 for (i = 0; i < mcs51_nRegs; i++)
2384 if (options.useXstack)
2386 emitcode ("mov", "a,(%s+%d)",
2387 regs8051[i].base, 8 * bank + regs8051[i].offset);
2388 emitcode ("movx", "@%s,a", r->name);
2390 emitcode ("inc", "%s", r->name);
2393 emitcode ("push", "(%s+%d)",
2394 regs8051[i].base, 8 * bank + regs8051[i].offset);
2399 if (options.useXstack)
2401 emitcode ("mov", "a,psw");
2402 emitcode ("movx", "@%s,a", r->name);
2407 emitcode ("push", "psw");
2410 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2415 freeAsmop (NULL, aop, ic, TRUE);
2424 /*-----------------------------------------------------------------*/
2425 /* unsaveRBank - restores the register bank from stack */
2426 /*-----------------------------------------------------------------*/
2428 unsaveRBank (int bank, iCode * ic, bool popPsw)
2434 if (options.useXstack)
2438 /* Assume r0 is available for use. */
2439 r = mcs51_regWithIdx (R0_IDX);;
2444 r = getFreePtr (ic, &aop, FALSE);
2446 emitcode ("mov", "%s,%s", r->name, spname);
2451 if (options.useXstack)
2453 emitcode ("dec", "%s", r->name);
2454 emitcode ("movx", "a,@%s", r->name);
2455 emitcode ("mov", "psw,a");
2459 emitcode ("pop", "psw");
2463 for (i = (mcs51_nRegs - 1); i >= 0; i--)
2465 if (options.useXstack)
2467 emitcode ("dec", "%s", r->name);
2468 emitcode ("movx", "a,@%s", r->name);
2469 emitcode ("mov", "(%s+%d),a",
2470 regs8051[i].base, 8 * bank + regs8051[i].offset);
2474 emitcode ("pop", "(%s+%d)",
2475 regs8051[i].base, 8 * bank + regs8051[i].offset);
2479 if (options.useXstack)
2481 emitcode ("mov", "%s,%s", spname, r->name);
2486 freeAsmop (NULL, aop, ic, TRUE);
2490 /*-----------------------------------------------------------------*/
2491 /* genSend - gen code for SEND */
2492 /*-----------------------------------------------------------------*/
2493 static void genSend(set *sendSet)
2498 /* first we do all bit parameters */
2499 for (sic = setFirstItem (sendSet); sic;
2500 sic = setNextItem (sendSet))
2502 aopOp (IC_LEFT (sic), sic, FALSE);
2504 if (sic->argreg > 12)
2506 int bit = sic->argreg-13;
2508 /* if left is a literal then
2509 we know what the value is */
2510 if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2512 if (((int) operandLitValue (IC_LEFT (sic))))
2513 emitcode ("setb", "b[%d]", bit);
2515 emitcode ("clr", "b[%d]", bit);
2517 else if (AOP_TYPE (IC_LEFT (sic)) == AOP_CRY)
2519 char *l = AOP (IC_LEFT (sic))->aopu.aop_dir;
2520 if (strcmp (l, "c"))
2521 emitcode ("mov", "c,%s", l);
2522 emitcode ("mov", "b[%d],c", bit);
2527 toBoolean (IC_LEFT (sic));
2528 /* set C, if a >= 1 */
2529 emitcode ("add", "a,#0xff");
2530 emitcode ("mov", "b[%d],c", bit);
2534 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2539 saveRegisters (setFirstItem (sendSet));
2540 emitcode ("mov", "bits,b");
2543 /* then we do all other parameters */
2544 for (sic = setFirstItem (sendSet); sic;
2545 sic = setNextItem (sendSet))
2547 int size, offset = 0;
2548 aopOp (IC_LEFT (sic), sic, FALSE);
2549 size = AOP_SIZE (IC_LEFT (sic));
2551 if (sic->argreg == 1)
2555 char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2556 if (strcmp (l, fReturn[offset]))
2557 emitcode ("mov", "%s,%s", fReturn[offset], l);
2561 else if (sic->argreg <= 12)
2565 emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2566 aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2570 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2574 /*-----------------------------------------------------------------*/
2575 /* genCall - generates a call statement */
2576 /*-----------------------------------------------------------------*/
2578 genCall (iCode * ic)
2581 // bool restoreBank = FALSE;
2582 bool swapBanks = FALSE;
2583 bool accuse = FALSE;
2584 bool accPushed = FALSE;
2585 bool resultInF0 = FALSE;
2587 D(emitcode("; genCall",""));
2589 dtype = operandType (IC_LEFT (ic));
2590 /* if send set is not empty then assign */
2593 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2594 genSend(reverseSet(_G.sendSet));
2596 genSend(_G.sendSet);
2602 /* if we are calling a not _naked function that is not using
2603 the same register bank then we need to save the
2604 destination registers on the stack */
2605 dtype = operandType (IC_LEFT (ic));
2606 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2607 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2608 !IFFUNC_ISISR (dtype))
2613 /* if caller saves & we have not saved then */
2619 emitcode ("mov", "psw,#0x%02x",
2620 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2624 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2626 if (IFFUNC_CALLEESAVES(dtype))
2628 werror (E_BANKED_WITH_CALLEESAVES);
2632 char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2633 OP_SYMBOL (IC_LEFT (ic))->rname :
2634 OP_SYMBOL (IC_LEFT (ic))->name);
2636 emitcode ("mov", "r0,#%s", l);
2637 emitcode ("mov", "r1,#(%s >> 8)", l);
2638 emitcode ("mov", "r2,#(%s >> 16)", l);
2639 emitcode ("lcall", "__sdcc_banked_call");
2644 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2645 OP_SYMBOL (IC_LEFT (ic))->rname :
2646 OP_SYMBOL (IC_LEFT (ic))->name));
2651 /* if result is in carry */
2652 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
2654 emitcode ("anl", "psw,#0xE7");
2655 if (FUNC_REGBANK(currFunc->type))
2656 emitcode ("orl", "psw,#0x%02x",
2657 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2661 emitcode ("mov", "psw,#0x%02x",
2662 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2666 /* if we need assign a result value */
2667 if ((IS_ITEMP (IC_RESULT (ic)) &&
2668 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2669 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2670 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2671 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2672 IS_TRUE_SYMOP (IC_RESULT (ic)))
2676 aopOp (IC_RESULT (ic), ic, FALSE);
2679 accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2681 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2684 /* adjust the stack for parameters if required */
2688 if (ic->parmBytes > 3)
2692 emitcode ("push", "acc");
2695 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2696 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
2698 emitcode ("mov", "F0,c");
2702 emitcode ("mov", "a,%s", spname);
2703 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2704 emitcode ("mov", "%s,a", spname);
2706 /* unsaveRegisters from xstack needs acc, but */
2707 /* unsaveRegisters from stack needs this popped */
2708 if (accPushed && !options.useXstack)
2710 emitcode ("pop", "acc");
2715 for (i = 0; i < ic->parmBytes; i++)
2716 emitcode ("dec", "%s", spname);
2719 /* if we had saved some registers then unsave them */
2720 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2722 if (accuse && !accPushed && options.useXstack)
2724 /* xstack needs acc, but doesn't touch normal stack */
2725 emitcode ("push", "acc");
2728 unsaveRegisters (ic);
2731 // /* if register bank was saved then pop them */
2733 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2735 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
2738 emitcode ("mov", "c,F0");
2740 aopOp (IC_RESULT (ic), ic, FALSE);
2741 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2742 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2746 emitcode ("pop", "acc");
2749 /*-----------------------------------------------------------------*/
2750 /* -10l - generates a call by pointer statement */
2751 /*-----------------------------------------------------------------*/
2753 genPcall (iCode * ic)
2757 symbol *rlbl = newiTempLabel (NULL);
2758 // bool restoreBank=FALSE;
2759 bool swapBanks = FALSE;
2761 D(emitcode("; genPCall",""));
2763 /* if caller saves & we have not saved then */
2767 /* if we are calling a not _naked function that is not using
2768 the same register bank then we need to save the
2769 destination registers on the stack */
2770 dtype = operandType (IC_LEFT (ic))->next;
2771 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2772 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2773 !IFFUNC_ISISR (dtype))
2775 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2776 // restoreBank=TRUE;
2778 // need caution message to user here
2781 etype = getSpec(dtype);
2782 if (IS_LITERAL(etype))
2784 /* if send set is not empty then assign */
2787 genSend(reverseSet(_G.sendSet));
2793 emitcode ("mov", "psw,#0x%02x",
2794 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2797 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2799 if (IFFUNC_CALLEESAVES(dtype))
2801 werror (E_BANKED_WITH_CALLEESAVES);
2805 char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
2807 emitcode ("mov", "r0,#%s", l);
2808 emitcode ("mov", "r1,#(%s >> 8)", l);
2809 emitcode ("mov", "r2,#(%s >> 16)", l);
2810 emitcode ("lcall", "__sdcc_banked_call");
2815 emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
2820 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2822 if (IFFUNC_CALLEESAVES(dtype))
2824 werror (E_BANKED_WITH_CALLEESAVES);
2828 aopOp (IC_LEFT (ic), ic, FALSE);
2832 emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
2833 emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
2834 emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
2838 int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
2839 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
2840 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
2841 emitcode ("mov", "0x%02x,%s", reg, aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
2844 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2846 /* if send set is not empty then assign */
2849 genSend(reverseSet(_G.sendSet));
2855 emitcode ("mov", "psw,#0x%02x",
2856 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2860 emitcode ("lcall", "__sdcc_banked_call");
2865 /* push the return address on to the stack */
2866 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2867 emitcode ("push", "acc");
2868 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2869 emitcode ("push", "acc");
2871 /* now push the calling address */
2872 aopOp (IC_LEFT (ic), ic, FALSE);
2874 pushSide (IC_LEFT (ic), FPTRSIZE);
2876 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2878 /* if send set is not empty the assign */
2881 genSend(reverseSet(_G.sendSet));
2887 emitcode ("mov", "psw,#0x%02x",
2888 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2892 emitcode ("ret", "");
2893 emitcode ("", "%05d$:", (rlbl->key + 100));
2898 emitcode ("mov", "psw,#0x%02x",
2899 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2902 /* if we need assign a result value */
2903 if ((IS_ITEMP (IC_RESULT (ic)) &&
2904 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2905 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2906 IS_TRUE_SYMOP (IC_RESULT (ic)))
2910 aopOp (IC_RESULT (ic), ic, FALSE);
2913 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2915 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2918 /* adjust the stack for parameters if
2923 if (ic->parmBytes > 3)
2925 emitcode ("mov", "a,%s", spname);
2926 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2927 emitcode ("mov", "%s,a", spname);
2930 for (i = 0; i < ic->parmBytes; i++)
2931 emitcode ("dec", "%s", spname);
2935 // /* if register bank was saved then unsave them */
2937 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2939 /* if we hade saved some registers then
2941 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2942 unsaveRegisters (ic);
2945 /*-----------------------------------------------------------------*/
2946 /* resultRemat - result is rematerializable */
2947 /*-----------------------------------------------------------------*/
2949 resultRemat (iCode * ic)
2951 if (SKIP_IC (ic) || ic->op == IFX)
2954 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2956 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2957 if (sym->remat && !POINTER_SET (ic))
2964 #if defined(__BORLANDC__) || defined(_MSC_VER)
2965 #define STRCASECMP stricmp
2967 #define STRCASECMP strcasecmp
2970 /*-----------------------------------------------------------------*/
2971 /* inExcludeList - return 1 if the string is in exclude Reg list */
2972 /*-----------------------------------------------------------------*/
2974 regsCmp(void *p1, void *p2)
2976 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2980 inExcludeList (char *s)
2982 const char *p = setFirstItem(options.excludeRegsSet);
2984 if (p == NULL || STRCASECMP(p, "none") == 0)
2988 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2991 /*-----------------------------------------------------------------*/
2992 /* genFunction - generated code for function entry */
2993 /*-----------------------------------------------------------------*/
2995 genFunction (iCode * ic)
2997 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2999 bool switchedPSW = FALSE;
3000 int calleesaves_saved_register = -1;
3001 int stackAdjust = sym->stack;
3002 int accIsFree = sym->recvSize < 4;
3003 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3004 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3007 /* create the function header */
3008 emitcode (";", "-----------------------------------------");
3009 emitcode (";", " function %s", sym->name);
3010 emitcode (";", "-----------------------------------------");
3012 emitcode ("", "%s:", sym->rname);
3013 ftype = operandType (IC_LEFT (ic));
3014 _G.currentFunc = sym;
3016 if (IFFUNC_ISNAKED(ftype))
3018 emitcode(";", "naked function: no prologue.");
3022 /* here we need to generate the equates for the
3023 register bank if required */
3024 if (FUNC_REGBANK (ftype) != rbank)
3028 rbank = FUNC_REGBANK (ftype);
3029 for (i = 0; i < mcs51_nRegs; i++)
3031 if (regs8051[i].type != REG_BIT)
3033 if (strcmp (regs8051[i].base, "0") == 0)
3034 emitcode ("", "%s = 0x%02x",
3036 8 * rbank + regs8051[i].offset);
3038 emitcode ("", "%s = %s + 0x%02x",
3041 8 * rbank + regs8051[i].offset);
3046 /* if this is an interrupt service routine then
3047 save acc, b, dpl, dph */
3048 if (IFFUNC_ISISR (sym->type))
3051 if (!inExcludeList ("acc"))
3052 emitcode ("push", "acc");
3053 if (!inExcludeList ("b"))
3054 emitcode ("push", "b");
3055 if (!inExcludeList ("dpl"))
3056 emitcode ("push", "dpl");
3057 if (!inExcludeList ("dph"))
3058 emitcode ("push", "dph");
3059 /* if this isr has no bank i.e. is going to
3060 run with bank 0 , then we need to save more
3062 if (!FUNC_REGBANK (sym->type))
3065 /* if this function does not call any other
3066 function then we can be economical and
3067 save only those registers that are used */
3068 if (!IFFUNC_HASFCALL(sym->type))
3072 /* if any registers used */
3075 bool bits_pushed = FALSE;
3076 /* save the registers used */
3077 for (i = 0; i < sym->regsUsed->size; i++)
3079 if (bitVectBitValue (sym->regsUsed, i))
3080 bits_pushed = pushReg (i, bits_pushed);
3087 /* this function has a function call. We cannot
3088 determines register usage so we will have to push the
3090 saveRBank (0, ic, FALSE);
3091 if (options.parms_in_bank1) {
3093 for (i=0; i < 8 ; i++ ) {
3094 emitcode ("push","%s",rb1regs[i]);
3101 /* This ISR uses a non-zero bank.
3103 * We assume that the bank is available for our
3106 * However, if this ISR calls a function which uses some
3107 * other bank, we must save that bank entirely.
3109 unsigned long banksToSave = 0;
3111 if (IFFUNC_HASFCALL(sym->type))
3114 #define MAX_REGISTER_BANKS 4
3119 for (i = ic; i; i = i->next)
3121 if (i->op == ENDFUNCTION)
3123 /* we got to the end OK. */
3131 dtype = operandType (IC_LEFT(i));
3133 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3135 /* Mark this bank for saving. */
3136 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3138 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3142 banksToSave |= (1 << FUNC_REGBANK(dtype));
3145 /* And note that we don't need to do it in
3153 /* This is a mess; we have no idea what
3154 * register bank the called function might
3157 * The only thing I can think of to do is
3158 * throw a warning and hope.
3160 werror(W_FUNCPTR_IN_USING_ISR);
3164 if (banksToSave && options.useXstack)
3166 /* Since we aren't passing it an ic,
3167 * saveRBank will assume r0 is available to abuse.
3169 * So switch to our (trashable) bank now, so
3170 * the caller's R0 isn't trashed.
3172 emitcode ("push", "psw");
3173 emitcode ("mov", "psw,#0x%02x",
3174 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3178 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3180 if (banksToSave & (1 << ix))
3182 saveRBank(ix, NULL, FALSE);
3186 // TODO: this needs a closer look
3187 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3190 /* Set the register bank to the desired value if nothing else */
3191 /* has done so yet. */
3194 emitcode ("push", "psw");
3195 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3200 /* This is a non-ISR function. The caller has already switched register */
3201 /* banks, if necessary, so just handle the callee-saves option. */
3203 /* if callee-save to be used for this function
3204 then save the registers being used in this function */
3205 if (IFFUNC_CALLEESAVES(sym->type))
3209 /* if any registers used */
3212 bool bits_pushed = FALSE;
3213 /* save the registers used */
3214 for (i = 0; i < sym->regsUsed->size; i++)
3216 if (bitVectBitValue (sym->regsUsed, i))
3218 /* remember one saved register for later usage */
3219 if (calleesaves_saved_register < 0)
3220 calleesaves_saved_register = i;
3221 bits_pushed = pushReg (i, bits_pushed);
3232 if (options.useXstack)
3234 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3236 emitcode ("mov", "r0,%s", spname);
3237 emitcode ("inc", "%s", spname);
3238 emitcode ("xch", "a,_bpx");
3239 emitcode ("movx", "@r0,a");
3240 emitcode ("inc", "r0");
3241 emitcode ("mov", "a,r0");
3242 emitcode ("xch", "a,_bpx");
3246 emitcode ("push", "_bp"); /* save the callers stack */
3247 emitcode ("mov", "_bp,sp");
3252 if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3254 /* set up the stack */
3255 emitcode ("push", "_bp"); /* save the callers stack */
3256 emitcode ("mov", "_bp,sp");
3261 /* For some cases it is worthwhile to perform a RECEIVE iCode */
3262 /* before setting up the stack frame completely. */
3263 if (ric && ric->argreg == 1 && IC_RESULT (ric))
3265 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3269 if (rsym && rsym->regType == REG_CND)
3271 if (rsym && (rsym->accuse || rsym->ruonly))
3273 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3274 rsym = rsym->usl.spillLoc;
3277 /* If the RECEIVE operand immediately spills to the first entry on the */
3278 /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3279 /* rather than the usual @r0/r1 machinations. */
3280 if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3284 _G.current_iCode = ric;
3285 D(emitcode ("; genReceive",""));
3286 for (ofs=0; ofs < sym->recvSize; ofs++)
3288 if (!strcmp (fReturn[ofs], "a"))
3289 emitcode ("push", "acc");
3291 emitcode ("push", fReturn[ofs]);
3293 stackAdjust -= sym->recvSize;
3296 assert (stackAdjust>=0);
3299 _G.current_iCode = ic;
3303 /* If the RECEIVE operand is 4 registers, we can do the moves now */
3304 /* to free up the accumulator. */
3305 else if (rsym && rsym->nRegs && sym->recvSize == 4)
3309 _G.current_iCode = ric;
3310 D(emitcode ("; genReceive",""));
3311 for (ofs=0; ofs < sym->recvSize; ofs++)
3313 emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3315 _G.current_iCode = ic;
3321 /* adjust the stack for the function */
3324 int i = stackAdjust;
3326 werror (W_STACK_OVERFLOW, sym->name);
3328 if (i > 3 && accIsFree)
3330 emitcode ("mov", "a,sp");
3331 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3332 emitcode ("mov", "sp,a");
3336 /* The accumulator is not free, so we will need another register */
3337 /* to clobber. No need to worry about a possible conflict with */
3338 /* the above early RECEIVE optimizations since they would have */
3339 /* freed the accumulator if they were generated. */
3341 if (IFFUNC_CALLEESAVES(sym->type))
3343 /* if it's a callee-saves function we need a saved register */
3344 if (calleesaves_saved_register >= 0)
3346 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
3347 emitcode ("mov", "a,sp");
3348 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3349 emitcode ("mov", "sp,a");
3350 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
3353 /* do it the hard way */
3355 emitcode ("inc", "sp");
3359 /* not callee-saves, we can clobber r0 */
3360 emitcode ("mov", "r0,a");
3361 emitcode ("mov", "a,sp");
3362 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3363 emitcode ("mov", "sp,a");
3364 emitcode ("mov", "a,r0");
3369 emitcode ("inc", "sp");
3374 char i = ((char) sym->xstack & 0xff);
3376 if (i > 3 && accIsFree)
3378 emitcode ("mov", "a,_spx");
3379 emitcode ("add", "a,#0x%02x", i);
3380 emitcode ("mov", "_spx,a");
3384 emitcode ("push", "acc");
3385 emitcode ("mov", "a,_spx");
3386 emitcode ("add", "a,#0x%02x", i);
3387 emitcode ("mov", "_spx,a");
3388 emitcode ("pop", "acc");
3393 emitcode ("inc", "_spx");
3397 /* if critical function then turn interrupts off */
3398 if (IFFUNC_ISCRITICAL (ftype))
3400 symbol *tlbl = newiTempLabel (NULL);
3401 emitcode ("setb", "c");
3402 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3403 emitcode ("clr", "c");
3404 emitcode ("", "%05d$:", (tlbl->key + 100));
3405 emitcode ("push", "psw"); /* save old ea via c in psw */
3409 /*-----------------------------------------------------------------*/
3410 /* genEndFunction - generates epilogue for functions */
3411 /*-----------------------------------------------------------------*/
3413 genEndFunction (iCode * ic)
3415 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3416 lineNode *lnp = lineCurr;
3418 bitVect *regsUsedPrologue;
3419 bitVect *regsUnneeded;
3422 _G.currentFunc = NULL;
3423 if (IFFUNC_ISNAKED(sym->type))
3425 emitcode(";", "naked function: no epilogue.");
3426 if (options.debug && currFunc)
3427 debugFile->writeEndFunction (currFunc, ic, 0);
3431 if (IFFUNC_ISCRITICAL (sym->type))
3433 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3435 emitcode ("rlc", "a"); /* save c in a */
3436 emitcode ("pop", "psw"); /* restore ea via c in psw */
3437 emitcode ("mov", "ea,c");
3438 emitcode ("rrc", "a"); /* restore c from a */
3442 emitcode ("pop", "psw"); /* restore ea via c in psw */
3443 emitcode ("mov", "ea,c");
3447 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3449 if (options.useXstack)
3453 emitcode ("mov", "sp,_bp");
3454 emitcode ("pop", "_bp");
3456 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3458 emitcode ("xch", "a,_bpx");
3459 emitcode ("mov", "r0,a");
3460 emitcode ("dec", "r0");
3461 emitcode ("movx", "a,@r0");
3462 emitcode ("xch", "a,_bpx");
3463 emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3466 else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3468 emitcode ("mov", "sp,_bp");
3469 emitcode ("pop", "_bp");
3473 /* restore the register bank */
3474 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3476 if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
3477 || !options.useXstack)
3479 /* Special case of ISR using non-zero bank with useXstack
3482 emitcode ("pop", "psw");
3486 if (IFFUNC_ISISR (sym->type))
3489 /* now we need to restore the registers */
3490 /* if this isr has no bank i.e. is going to
3491 run with bank 0 , then we need to save more
3493 if (!FUNC_REGBANK (sym->type))
3495 /* if this function does not call any other
3496 function then we can be economical and
3497 save only those registers that are used */
3498 if (!IFFUNC_HASFCALL(sym->type))
3502 /* if any registers used */
3505 bool bits_popped = FALSE;
3506 /* save the registers used */
3507 for (i = sym->regsUsed->size; i >= 0; i--)
3509 if (bitVectBitValue (sym->regsUsed, i))
3510 bits_popped = popReg (i, bits_popped);
3516 if (options.parms_in_bank1) {
3518 for (i = 7 ; i >= 0 ; i-- ) {
3519 emitcode ("pop","%s",rb1regs[i]);
3522 /* this function has a function call cannot
3523 determines register usage so we will have to pop the
3525 unsaveRBank (0, ic, FALSE);
3530 /* This ISR uses a non-zero bank.
3532 * Restore any register banks saved by genFunction
3535 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3538 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3540 if (savedBanks & (1 << ix))
3542 unsaveRBank(ix, NULL, FALSE);
3546 if (options.useXstack)
3548 /* Restore bank AFTER calling unsaveRBank,
3549 * since it can trash r0.
3551 emitcode ("pop", "psw");
3555 if (!inExcludeList ("dph"))
3556 emitcode ("pop", "dph");
3557 if (!inExcludeList ("dpl"))
3558 emitcode ("pop", "dpl");
3559 if (!inExcludeList ("b"))
3560 emitcode ("pop", "b");
3561 if (!inExcludeList ("acc"))
3562 emitcode ("pop", "acc");
3564 /* if debug then send end of function */
3565 if (options.debug && currFunc)
3567 debugFile->writeEndFunction (currFunc, ic, 1);
3570 emitcode ("reti", "");
3574 if (IFFUNC_CALLEESAVES(sym->type))
3578 /* if any registers used */
3581 /* save the registers used */
3582 for (i = sym->regsUsed->size; i >= 0; i--)
3584 if (bitVectBitValue (sym->regsUsed, i) ||
3585 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3586 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
3589 else if (mcs51_ptrRegReq)
3591 emitcode ("pop", "%s", mcs51_regWithIdx (R1_IDX)->dname);
3592 emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
3597 /* if debug then send end of function */
3598 if (options.debug && currFunc)
3600 debugFile->writeEndFunction (currFunc, ic, 1);
3603 if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3605 emitcode ("ljmp", "__sdcc_banked_ret");
3609 emitcode ("ret", "");
3613 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3616 /* If this was an interrupt handler using bank 0 that called another */
3617 /* function, then all registers must be saved; nothing to optimized. */
3618 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3619 && !FUNC_REGBANK(sym->type))
3622 /* There are no push/pops to optimize if not callee-saves or ISR */
3623 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3626 /* If there were stack parameters, we cannot optimize without also */
3627 /* fixing all of the stack offsets; this is too dificult to consider. */
3628 if (FUNC_HASSTACKPARM(sym->type))
3631 /* Compute the registers actually used */
3632 regsUsed = newBitVect (mcs51_nRegs);
3633 regsUsedPrologue = newBitVect (mcs51_nRegs);
3636 if (lnp->ic && lnp->ic->op == FUNCTION)
3637 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3639 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3641 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3642 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3649 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3650 && !bitVectBitValue (regsUsed, CND_IDX))
3652 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3653 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3654 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3655 bitVectUnSetBit (regsUsed, CND_IDX);
3658 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3660 /* If this was an interrupt handler that called another function */
3661 /* function, then assume A, B, DPH, & DPL may be modified by it. */
3662 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3664 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3665 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3666 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3667 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3668 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3671 /* Remove the unneeded push/pops */
3672 regsUnneeded = newBitVect (mcs51_nRegs);
3675 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3677 if (!strncmp(lnp->line, "push", 4))
3679 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3680 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3682 connectLine (lnp->prev, lnp->next);
3683 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3686 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3688 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3689 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3691 connectLine (lnp->prev, lnp->next);
3692 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3699 for (idx = 0; idx < regsUnneeded->size; idx++)
3700 if (bitVectBitValue (regsUnneeded, idx))
3701 emitcode ("", ";\teliminated unneeded push/pop %s", mcs51_regWithIdx (idx)->dname);
3703 freeBitVect (regsUnneeded);
3704 freeBitVect (regsUsed);
3705 freeBitVect (regsUsedPrologue);
3708 /*-----------------------------------------------------------------*/
3709 /* genRet - generate code for return statement */
3710 /*-----------------------------------------------------------------*/
3714 int size, offset = 0, pushed = 0;
3716 D(emitcode ("; genRet",""));
3718 /* if we have no return value then
3719 just generate the "ret" */
3723 /* we have something to return then
3724 move the return value into place */
3725 aopOp (IC_LEFT (ic), ic, FALSE);
3726 size = AOP_SIZE (IC_LEFT (ic));
3729 if (IS_BIT(_G.currentFunc->etype))
3731 movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
3738 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3741 l = aopGet (IC_LEFT (ic), offset++,
3743 emitcode ("push", "%s", l);
3748 l = aopGet (IC_LEFT (ic), offset,
3750 if (strcmp (fReturn[offset], l))
3751 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3758 if (strcmp (fReturn[pushed], "a"))
3759 emitcode ("pop", fReturn[pushed]);
3761 emitcode ("pop", "acc");
3763 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3766 /* generate a jump to the return label
3767 if the next is not the return statement */
3768 if (!(ic->next && ic->next->op == LABEL &&
3769 IC_LABEL (ic->next) == returnLabel))
3771 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3775 /*-----------------------------------------------------------------*/
3776 /* genLabel - generates a label */
3777 /*-----------------------------------------------------------------*/
3779 genLabel (iCode * ic)
3781 /* special case never generate */
3782 if (IC_LABEL (ic) == entryLabel)
3785 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3788 /*-----------------------------------------------------------------*/
3789 /* genGoto - generates a ljmp */
3790 /*-----------------------------------------------------------------*/
3792 genGoto (iCode * ic)
3794 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3797 /*-----------------------------------------------------------------*/
3798 /* findLabelBackwards: walks back through the iCode chain looking */
3799 /* for the given label. Returns number of iCode instructions */
3800 /* between that label and given ic. */
3801 /* Returns zero if label not found. */
3802 /*-----------------------------------------------------------------*/
3804 findLabelBackwards (iCode * ic, int key)
3813 /* If we have any pushes or pops, we cannot predict the distance.
3814 I don't like this at all, this should be dealt with in the
3816 if (ic->op == IPUSH || ic->op == IPOP) {
3820 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3829 /*-----------------------------------------------------------------*/
3830 /* genPlusIncr :- does addition with increment if possible */
3831 /*-----------------------------------------------------------------*/
3833 genPlusIncr (iCode * ic)
3835 unsigned int icount;
3836 unsigned int size = getDataSize (IC_RESULT (ic));
3838 /* will try to generate an increment */
3839 /* if the right side is not a literal
3841 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3844 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3846 D(emitcode ("; genPlusIncr",""));
3848 /* if increment >=16 bits in register or direct space */
3849 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
3850 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3851 !isOperandVolatile (IC_RESULT (ic), FALSE) &&
3859 /* If the next instruction is a goto and the goto target
3860 * is < 10 instructions previous to this, we can generate
3861 * jumps straight to that target.
3863 if (ic->next && ic->next->op == GOTO
3864 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3865 && labelRange <= 10)
3867 emitcode (";", "tail increment optimized");
3868 tlbl = IC_LABEL (ic->next);
3873 tlbl = newiTempLabel (NULL);
3876 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
3877 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3878 IS_AOP_PREG (IC_RESULT (ic)))
3879 emitcode ("cjne", "%s,#0x00,%05d$",
3880 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
3884 emitcode ("clr", "a");
3885 emitcode ("cjne", "a,%s,%05d$",
3886 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
3890 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
3893 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3894 IS_AOP_PREG (IC_RESULT (ic)))
3895 emitcode ("cjne", "%s,#0x00,%05d$",
3896 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
3899 emitcode ("cjne", "a,%s,%05d$",
3900 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
3903 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
3907 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3908 IS_AOP_PREG (IC_RESULT (ic)))
3909 emitcode ("cjne", "%s,#0x00,%05d$",
3910 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
3914 emitcode ("cjne", "a,%s,%05d$",
3915 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
3918 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
3923 emitcode ("", "%05d$:", tlbl->key + 100);
3928 /* if result is dptr */
3929 if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
3930 (AOP_SIZE (IC_RESULT (ic)) == 2) &&
3931 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
3932 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
3934 if (aopGetUsesAcc (IC_LEFT (ic), 0))
3940 if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
3943 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0, FALSE);
3944 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1, FALSE);
3946 emitcode ("inc", "dptr");
3951 /* if the literal value of the right hand side
3952 is greater than 4 then it is not worth it */
3956 /* if the sizes are greater than 1 then we cannot */
3957 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3958 AOP_SIZE (IC_LEFT (ic)) > 1)
3961 /* we can if the aops of the left & result match or
3962 if they are in registers and the registers are the
3964 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3969 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
3970 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3971 aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3977 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
3986 /*-----------------------------------------------------------------*/
3987 /* outBitAcc - output a bit in acc */
3988 /*-----------------------------------------------------------------*/
3990 outBitAcc (operand * result)
3992 symbol *tlbl = newiTempLabel (NULL);
3993 /* if the result is a bit */
3994 if (AOP_TYPE (result) == AOP_CRY)
3996 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4000 emitcode ("jz", "%05d$", tlbl->key + 100);
4001 emitcode ("mov", "a,%s", one);
4002 emitcode ("", "%05d$:", tlbl->key + 100);
4007 /*-----------------------------------------------------------------*/
4008 /* genPlusBits - generates code for addition of two bits */
4009 /*-----------------------------------------------------------------*/
4011 genPlusBits (iCode * ic)
4013 D(emitcode ("; genPlusBits",""));
4015 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4017 symbol *lbl = newiTempLabel (NULL);
4018 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4019 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4020 emitcode ("cpl", "c");
4021 emitcode ("", "%05d$:", (lbl->key + 100));
4022 outBitC (IC_RESULT (ic));
4026 emitcode ("clr", "a");
4027 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4028 emitcode ("rlc", "a");
4029 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4030 emitcode ("addc", "a,#0x00");
4031 outAcc (IC_RESULT (ic));
4036 /* This is the original version of this code.
4038 * This is being kept around for reference,
4039 * because I am not entirely sure I got it right...
4042 adjustArithmeticResult (iCode * ic)
4044 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4045 AOP_SIZE (IC_LEFT (ic)) == 3 &&
4046 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4047 aopPut (IC_RESULT (ic),
4048 aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4050 isOperandVolatile (IC_RESULT (ic), FALSE));
4052 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4053 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4054 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4055 aopPut (IC_RESULT (ic),
4056 aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4058 isOperandVolatile (IC_RESULT (ic), FALSE));
4060 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4061 AOP_SIZE (IC_LEFT (ic)) < 3 &&
4062 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4063 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4064 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4067 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4068 aopPut (IC_RESULT (ic), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
4072 /* This is the pure and virtuous version of this code.
4073 * I'm pretty certain it's right, but not enough to toss the old
4077 adjustArithmeticResult (iCode * ic)
4079 if (opIsGptr (IC_RESULT (ic)) &&
4080 opIsGptr (IC_LEFT (ic)) &&
4081 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4083 aopPut (IC_RESULT (ic),
4084 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4086 isOperandVolatile (IC_RESULT (ic), FALSE));
4089 if (opIsGptr (IC_RESULT (ic)) &&
4090 opIsGptr (IC_RIGHT (ic)) &&
4091 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4093 aopPut (IC_RESULT (ic),
4094 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4096 isOperandVolatile (IC_RESULT (ic), FALSE));
4099 if (opIsGptr (IC_RESULT (ic)) &&
4100 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4101 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4102 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4103 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4106 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4107 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
4112 /*-----------------------------------------------------------------*/
4113 /* genPlus - generates code for addition */
4114 /*-----------------------------------------------------------------*/
4116 genPlus (iCode * ic)
4118 int size, offset = 0;
4121 operand *leftOp, *rightOp;
4124 /* special cases :- */
4126 D(emitcode ("; genPlus",""));
4128 aopOp (IC_LEFT (ic), ic, FALSE);
4129 aopOp (IC_RIGHT (ic), ic, FALSE);
4130 aopOp (IC_RESULT (ic), ic, TRUE);
4132 /* if literal, literal on the right or
4133 if left requires ACC or right is already
4135 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4136 (AOP_NEEDSACC (IC_LEFT (ic))) ||
4137 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4139 operand *t = IC_RIGHT (ic);
4140 IC_RIGHT (ic) = IC_LEFT (ic);
4144 /* if both left & right are in bit
4146 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4147 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4153 /* if left in bit space & right literal */
4154 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4155 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4157 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4158 /* if result in bit space */
4159 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4161 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4162 emitcode ("cpl", "c");
4163 outBitC (IC_RESULT (ic));
4167 size = getDataSize (IC_RESULT (ic));
4170 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4171 emitcode ("addc", "a,#00");
4172 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4178 /* if I can do an increment instead
4179 of add then GOOD for ME */
4180 if (genPlusIncr (ic) == TRUE)
4183 size = getDataSize (IC_RESULT (ic));
4184 leftOp = IC_LEFT(ic);
4185 rightOp = IC_RIGHT(ic);
4188 /* if this is an add for an array access
4189 at a 256 byte boundary */
4191 && AOP_TYPE (op) == AOP_IMMD
4193 && IS_SPEC (OP_SYM_ETYPE (op))
4194 && SPEC_ABSA (OP_SYM_ETYPE (op))
4195 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4198 D(emitcode ("; genPlus aligned array",""));
4199 aopPut (IC_RESULT (ic),
4200 aopGet (rightOp, 0, FALSE, FALSE),
4202 isOperandVolatile (IC_RESULT (ic), FALSE));
4204 if( 1 == getDataSize (IC_RIGHT (ic)) )
4206 aopPut (IC_RESULT (ic),
4207 aopGet (leftOp, 1, FALSE, FALSE),
4209 isOperandVolatile (IC_RESULT (ic), FALSE));
4213 MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4214 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4215 aopPut (IC_RESULT (ic), "a", 1, isOperandVolatile (IC_RESULT (ic), FALSE));
4220 /* if the lower bytes of a literal are zero skip the addition */
4221 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4223 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4224 (skip_bytes+1 < size))
4229 D(emitcode ("; genPlus shortcut",""));
4234 if( offset >= skip_bytes )
4236 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4239 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4241 emitcode("xch", "a,b");
4242 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4243 emitcode (add, "a,b");
4246 else if (aopGetUsesAcc (leftOp, offset))
4248 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4249 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4253 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4254 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4256 aopPut (IC_RESULT (ic), "a", offset, isOperandVolatile (IC_RESULT (ic), FALSE));
4257 add = "addc"; /* further adds must propagate carry */
4261 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4262 isOperandVolatile (IC_RESULT (ic), FALSE))
4265 aopPut (IC_RESULT (ic),
4266 aopGet (leftOp, offset, FALSE, FALSE),
4268 isOperandVolatile (IC_RESULT (ic), FALSE));
4274 adjustArithmeticResult (ic);
4277 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4278 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4279 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4282 /*-----------------------------------------------------------------*/
4283 /* genMinusDec :- does subtraction with deccrement if possible */
4284 /*-----------------------------------------------------------------*/
4286 genMinusDec (iCode * ic)
4288 unsigned int icount;
4289 unsigned int size = getDataSize (IC_RESULT (ic));
4291 /* will try to generate an increment */
4292 /* if the right side is not a literal
4294 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4297 /* if the literal value of the right hand side
4298 is greater than 4 then it is not worth it */
4299 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4302 D(emitcode ("; genMinusDec",""));
4304 /* if decrement >=16 bits in register or direct space */
4305 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
4306 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4314 /* If the next instruction is a goto and the goto target
4315 * is <= 10 instructions previous to this, we can generate
4316 * jumps straight to that target.
4318 if (ic->next && ic->next->op == GOTO
4319 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4320 && labelRange <= 10)
4322 emitcode (";", "tail decrement optimized");
4323 tlbl = IC_LABEL (ic->next);
4328 tlbl = newiTempLabel (NULL);
4332 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4333 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4334 IS_AOP_PREG (IC_RESULT (ic)))
4335 emitcode ("cjne", "%s,#0xff,%05d$"
4336 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4340 emitcode ("mov", "a,#0xff");
4341 emitcode ("cjne", "a,%s,%05d$"
4342 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4345 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4348 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4349 IS_AOP_PREG (IC_RESULT (ic)))
4350 emitcode ("cjne", "%s,#0xff,%05d$"
4351 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4355 emitcode ("cjne", "a,%s,%05d$"
4356 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4359 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4363 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4364 IS_AOP_PREG (IC_RESULT (ic)))
4365 emitcode ("cjne", "%s,#0xff,%05d$"
4366 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4370 emitcode ("cjne", "a,%s,%05d$"
4371 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4374 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4378 emitcode ("", "%05d$:", tlbl->key + 100);
4383 /* if the sizes are greater than 1 then we cannot */
4384 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4385 AOP_SIZE (IC_LEFT (ic)) > 1)
4388 /* we can if the aops of the left & result match or
4389 if they are in registers and the registers are the
4391 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4395 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4403 /*-----------------------------------------------------------------*/
4404 /* addSign - complete with sign */
4405 /*-----------------------------------------------------------------*/
4407 addSign (operand * result, int offset, int sign)
4409 int size = (getDataSize (result) - offset);
4414 emitcode ("rlc", "a");
4415 emitcode ("subb", "a,acc");
4417 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
4421 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
4425 /*-----------------------------------------------------------------*/
4426 /* genMinusBits - generates code for subtraction of two bits */
4427 /*-----------------------------------------------------------------*/
4429 genMinusBits (iCode * ic)
4431 symbol *lbl = newiTempLabel (NULL);
4433 D(emitcode ("; genMinusBits",""));
4435 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4437 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4438 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4439 emitcode ("cpl", "c");
4440 emitcode ("", "%05d$:", (lbl->key + 100));
4441 outBitC (IC_RESULT (ic));
4445 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4446 emitcode ("subb", "a,acc");
4447 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4448 emitcode ("inc", "a");
4449 emitcode ("", "%05d$:", (lbl->key + 100));
4450 aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4451 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4455 /*-----------------------------------------------------------------*/
4456 /* genMinus - generates code for subtraction */
4457 /*-----------------------------------------------------------------*/
4459 genMinus (iCode * ic)
4461 int size, offset = 0;
4463 D(emitcode ("; genMinus",""));
4465 aopOp (IC_LEFT (ic), ic, FALSE);
4466 aopOp (IC_RIGHT (ic), ic, FALSE);
4467 aopOp (IC_RESULT (ic), ic, TRUE);
4469 /* special cases :- */
4470 /* if both left & right are in bit space */
4471 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4472 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4478 /* if I can do an decrement instead
4479 of subtract then GOOD for ME */
4480 if (genMinusDec (ic) == TRUE)
4483 size = getDataSize (IC_RESULT (ic));
4485 /* if literal, add a,#-lit, else normal subb */
4486 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4488 unsigned long lit = 0L;
4489 bool useCarry = FALSE;
4491 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4496 if (useCarry || ((lit >> (offset * 8)) & 0x0FFL)) {
4497 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4498 if (!offset && !size && lit== (unsigned long) -1) {
4499 emitcode ("dec", "a");
4500 } else if (!useCarry) {
4501 /* first add without previous c */
4502 emitcode ("add", "a,#0x%02x",
4503 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4506 emitcode ("addc", "a,#0x%02x",
4507 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4509 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4511 /* no need to add zeroes */
4518 operand *leftOp, *rightOp;
4520 leftOp = IC_LEFT(ic);
4521 rightOp = IC_RIGHT(ic);
4525 if (aopGetUsesAcc(rightOp, offset)) {
4526 if (aopGetUsesAcc(leftOp, offset)) {
4529 MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4531 emitcode ("mov", "b,a");
4534 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4535 emitcode ("subb", "a,b");
4538 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4539 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4541 emitcode( "setb", "c");
4543 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4544 emitcode("cpl", "a");
4547 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4550 emitcode ("subb", "a,%s",
4551 aopGet(rightOp, offset, FALSE, TRUE));
4554 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4559 adjustArithmeticResult (ic);
4562 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4563 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4564 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4568 /*-----------------------------------------------------------------*/
4569 /* genMultbits :- multiplication of bits */
4570 /*-----------------------------------------------------------------*/
4572 genMultbits (operand * left,
4576 D(emitcode ("; genMultbits",""));
4578 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4579 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4583 /*-----------------------------------------------------------------*/
4584 /* genMultOneByte : 8*8=8/16 bit multiplication */
4585 /*-----------------------------------------------------------------*/
4587 genMultOneByte (operand * left,
4592 int size = AOP_SIZE (result);
4593 bool runtimeSign, compiletimeSign;
4594 bool lUnsigned, rUnsigned, pushedB;
4596 D(emitcode ("; genMultOneByte",""));
4598 if (size < 1 || size > 2)
4600 /* this should never happen */
4601 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4602 AOP_SIZE(result), __FILE__, lineno);
4606 /* (if two literals: the value is computed before) */
4607 /* if one literal, literal on the right */
4608 if (AOP_TYPE (left) == AOP_LIT)
4613 /* emitcode (";", "swapped left and right"); */
4615 /* if no literal, unsigned on the right: shorter code */
4616 if ( AOP_TYPE (right) != AOP_LIT
4617 && SPEC_USIGN (getSpec (operandType (left))))
4624 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4625 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4629 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4630 no need to take care about the signedness! */
4631 || (lUnsigned && rUnsigned))
4633 /* just an unsigned 8 * 8 = 8 multiply
4635 /* emitcode (";","unsigned"); */
4636 /* TODO: check for accumulator clash between left & right aops? */
4638 if (AOP_TYPE (right) == AOP_LIT)
4640 /* moving to accumulator first helps peepholes */
4641 MOVA (aopGet (left, 0, FALSE, FALSE));
4642 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4646 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4647 MOVA (aopGet (left, 0, FALSE, FALSE));
4650 emitcode ("mul", "ab");
4651 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4653 aopPut (result, "b", 1, isOperandVolatile (result, FALSE));
4659 /* we have to do a signed multiply */
4660 /* emitcode (";", "signed"); */
4662 /* now sign adjust for both left & right */
4664 /* let's see what's needed: */
4665 /* apply negative sign during runtime */
4666 runtimeSign = FALSE;
4667 /* negative sign from literals */
4668 compiletimeSign = FALSE;
4672 if (AOP_TYPE(left) == AOP_LIT)
4674 /* signed literal */
4675 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4677 compiletimeSign = TRUE;
4680 /* signed but not literal */
4686 if (AOP_TYPE(right) == AOP_LIT)
4688 /* signed literal */
4689 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4691 compiletimeSign ^= TRUE;
4694 /* signed but not literal */
4698 /* initialize F0, which stores the runtime sign */
4701 if (compiletimeSign)
4702 emitcode ("setb", "F0"); /* set sign flag */
4704 emitcode ("clr", "F0"); /* reset sign flag */
4707 /* save the signs of the operands */
4708 if (AOP_TYPE(right) == AOP_LIT)
4710 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4712 if (!rUnsigned && val < 0)
4713 emitcode ("mov", "b,#0x%02x", -val);
4715 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4717 else /* ! literal */
4719 if (rUnsigned) /* emitcode (";", "signed"); */
4721 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4724 MOVA (aopGet (right, 0, FALSE, FALSE));
4725 lbl = newiTempLabel (NULL);
4726 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4727 emitcode ("cpl", "F0"); /* complement sign flag */
4728 emitcode ("cpl", "a"); /* 2's complement */
4729 emitcode ("inc", "a");
4730 emitcode ("", "%05d$:", (lbl->key + 100));
4731 emitcode ("mov", "b,a");
4735 if (AOP_TYPE(left) == AOP_LIT)
4737 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4739 if (!lUnsigned && val < 0)
4740 emitcode ("mov", "a,#0x%02x", -val);
4742 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4744 else /* ! literal */
4746 MOVA (aopGet (left, 0, FALSE, FALSE));
4750 lbl = newiTempLabel (NULL);
4751 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4752 emitcode ("cpl", "F0"); /* complement sign flag */
4753 emitcode ("cpl", "a"); /* 2's complement */
4754 emitcode ("inc", "a");
4755 emitcode ("", "%05d$:", (lbl->key + 100));
4759 /* now the multiplication */
4760 emitcode ("mul", "ab");
4761 if (runtimeSign || compiletimeSign)
4763 lbl = newiTempLabel (NULL);
4765 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4766 emitcode ("cpl", "a"); /* lsb 2's complement */
4768 emitcode ("inc", "a"); /* inc doesn't set carry flag */
4771 emitcode ("add", "a,#1"); /* this sets carry flag */
4772 emitcode ("xch", "a,b");
4773 emitcode ("cpl", "a"); /* msb 2's complement */
4774 emitcode ("addc", "a,#0");
4775 emitcode ("xch", "a,b");
4777 emitcode ("", "%05d$:", (lbl->key + 100));
4779 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4781 aopPut (result, "b", 1, isOperandVolatile (result, FALSE));
4786 /*-----------------------------------------------------------------*/
4787 /* genMult - generates code for multiplication */
4788 /*-----------------------------------------------------------------*/
4790 genMult (iCode * ic)
4792 operand *left = IC_LEFT (ic);
4793 operand *right = IC_RIGHT (ic);
4794 operand *result = IC_RESULT (ic);
4796 D(emitcode ("; genMult",""));
4798 /* assign the amsops */
4799 aopOp (left, ic, FALSE);
4800 aopOp (right, ic, FALSE);
4801 aopOp (result, ic, TRUE);
4803 /* special cases first */
4805 if (AOP_TYPE (left) == AOP_CRY &&
4806 AOP_TYPE (right) == AOP_CRY)
4808 genMultbits (left, right, result);
4812 /* if both are of size == 1 */
4813 #if 0 // one of them can be a sloc shared with the result
4814 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
4816 if (getSize(operandType(left)) == 1 &&
4817 getSize(operandType(right)) == 1)
4820 genMultOneByte (left, right, result);
4824 /* should have been converted to function call */
4825 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
4826 getSize(OP_SYMBOL(right)->type));
4830 freeAsmop (result, NULL, ic, TRUE);
4831 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4832 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4835 /*-----------------------------------------------------------------*/
4836 /* genDivbits :- division of bits */
4837 /*-----------------------------------------------------------------*/
4839 genDivbits (operand * left,
4846 D(emitcode ("; genDivbits",""));
4850 /* the result must be bit */
4851 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4852 l = aopGet (left, 0, FALSE, FALSE);
4856 emitcode ("div", "ab");
4857 emitcode ("rrc", "a");
4861 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
4864 /*-----------------------------------------------------------------*/
4865 /* genDivOneByte : 8 bit division */
4866 /*-----------------------------------------------------------------*/
4868 genDivOneByte (operand * left,
4872 bool lUnsigned, rUnsigned, pushedB;
4873 bool runtimeSign, compiletimeSign;
4877 D(emitcode ("; genDivOneByte",""));
4879 /* Why is it necessary that genDivOneByte() can return an int result?
4882 volatile unsigned char uc;
4883 volatile signed char sc1, sc2;
4896 In all cases a one byte result would overflow, the following cast to int
4897 would return the wrong result.
4899 Two possible solution:
4900 a) cast operands to int, if ((unsigned) / (signed)) or
4901 ((signed) / (signed))
4902 b) return an 16 bit signed int; this is what we're doing here!
4905 size = AOP_SIZE (result) - 1;
4907 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4908 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4912 /* signed or unsigned */
4913 if (lUnsigned && rUnsigned)
4915 /* unsigned is easy */
4916 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4917 MOVA (aopGet (left, 0, FALSE, FALSE));
4918 emitcode ("div", "ab");
4919 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4921 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
4927 /* signed is a little bit more difficult */
4929 /* now sign adjust for both left & right */
4931 /* let's see what's needed: */
4932 /* apply negative sign during runtime */
4933 runtimeSign = FALSE;
4934 /* negative sign from literals */
4935 compiletimeSign = FALSE;
4939 if (AOP_TYPE(left) == AOP_LIT)
4941 /* signed literal */
4942 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4944 compiletimeSign = TRUE;
4947 /* signed but not literal */
4953 if (AOP_TYPE(right) == AOP_LIT)
4955 /* signed literal */
4956 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4958 compiletimeSign ^= TRUE;
4961 /* signed but not literal */
4965 /* initialize F0, which stores the runtime sign */
4968 if (compiletimeSign)
4969 emitcode ("setb", "F0"); /* set sign flag */
4971 emitcode ("clr", "F0"); /* reset sign flag */
4974 /* save the signs of the operands */
4975 if (AOP_TYPE(right) == AOP_LIT)
4977 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4979 if (!rUnsigned && val < 0)
4980 emitcode ("mov", "b,#0x%02x", -val);
4982 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4984 else /* ! literal */
4987 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4990 MOVA (aopGet (right, 0, FALSE, FALSE));
4991 lbl = newiTempLabel (NULL);
4992 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4993 emitcode ("cpl", "F0"); /* complement sign flag */
4994 emitcode ("cpl", "a"); /* 2's complement */
4995 emitcode ("inc", "a");
4996 emitcode ("", "%05d$:", (lbl->key + 100));
4997 emitcode ("mov", "b,a");
5001 if (AOP_TYPE(left) == AOP_LIT)
5003 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5005 if (!lUnsigned && val < 0)
5006 emitcode ("mov", "a,#0x%02x", -val);
5008 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5010 else /* ! literal */
5012 MOVA (aopGet (left, 0, FALSE, FALSE));
5016 lbl = newiTempLabel (NULL);
5017 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5018 emitcode ("cpl", "F0"); /* complement sign flag */
5019 emitcode ("cpl", "a"); /* 2's complement */
5020 emitcode ("inc", "a");
5021 emitcode ("", "%05d$:", (lbl->key + 100));
5025 /* now the division */
5026 emitcode ("div", "ab");
5028 if (runtimeSign || compiletimeSign)
5030 lbl = newiTempLabel (NULL);
5032 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5033 emitcode ("cpl", "a"); /* lsb 2's complement */
5034 emitcode ("inc", "a");
5035 emitcode ("", "%05d$:", (lbl->key + 100));
5037 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5040 /* msb is 0x00 or 0xff depending on the sign */
5043 emitcode ("mov", "c,F0");
5044 emitcode ("subb", "a,acc");
5046 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
5048 else /* compiletimeSign */
5050 aopPut (result, "#0xff", offset++, isOperandVolatile (result, FALSE));
5055 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5057 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5063 /*-----------------------------------------------------------------*/
5064 /* genDiv - generates code for division */
5065 /*-----------------------------------------------------------------*/
5069 operand *left = IC_LEFT (ic);
5070 operand *right = IC_RIGHT (ic);
5071 operand *result = IC_RESULT (ic);
5073 D(emitcode ("; genDiv",""));
5075 /* assign the amsops */
5076 aopOp (left, ic, FALSE);
5077 aopOp (right, ic, FALSE);
5078 aopOp (result, ic, TRUE);
5080 /* special cases first */
5082 if (AOP_TYPE (left) == AOP_CRY &&
5083 AOP_TYPE (right) == AOP_CRY)
5085 genDivbits (left, right, result);
5089 /* if both are of size == 1 */
5090 if (AOP_SIZE (left) == 1 &&
5091 AOP_SIZE (right) == 1)
5093 genDivOneByte (left, right, result);
5097 /* should have been converted to function call */
5100 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5101 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5102 freeAsmop (result, NULL, ic, TRUE);
5105 /*-----------------------------------------------------------------*/
5106 /* genModbits :- modulus of bits */
5107 /*-----------------------------------------------------------------*/
5109 genModbits (operand * left,
5116 D(emitcode ("; genModbits",""));
5120 /* the result must be bit */
5121 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5122 l = aopGet (left, 0, FALSE, FALSE);
5126 emitcode ("div", "ab");
5127 emitcode ("mov", "a,b");
5128 emitcode ("rrc", "a");
5132 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
5135 /*-----------------------------------------------------------------*/
5136 /* genModOneByte : 8 bit modulus */
5137 /*-----------------------------------------------------------------*/
5139 genModOneByte (operand * left,
5143 bool lUnsigned, rUnsigned, pushedB;
5144 bool runtimeSign, compiletimeSign;
5148 D(emitcode ("; genModOneByte",""));
5150 size = AOP_SIZE (result) - 1;
5152 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5153 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5155 /* if right is a literal, check it for 2^n */
5156 if (AOP_TYPE(right) == AOP_LIT)
5158 unsigned char val = abs((int) operandLitValue(right));
5159 symbol *lbl2 = NULL;
5163 case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5172 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5173 "modulus of unsigned char by 2^n literal shouldn't be processed here");
5174 /* because iCode should have been changed to genAnd */
5175 /* see file "SDCCopt.c", function "convertToFcall()" */
5177 MOVA (aopGet (left, 0, FALSE, FALSE));
5178 emitcode ("mov", "c,acc.7");
5179 emitcode ("anl", "a,#0x%02x", val - 1);
5180 lbl = newiTempLabel (NULL);
5181 emitcode ("jz", "%05d$", (lbl->key + 100));
5182 emitcode ("jnc", "%05d$", (lbl->key + 100));
5183 emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5189 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5191 aopPut (result, "#0xff", offs2++, isOperandVolatile (result, FALSE));
5192 lbl2 = newiTempLabel (NULL);
5193 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5195 emitcode ("", "%05d$:", (lbl->key + 100));
5196 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5198 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5201 emitcode ("", "%05d$:", (lbl2->key + 100));
5212 /* signed or unsigned */
5213 if (lUnsigned && rUnsigned)
5215 /* unsigned is easy */
5216 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5217 MOVA (aopGet (left, 0, FALSE, FALSE));
5218 emitcode ("div", "ab");
5219 aopPut (result, "b", 0, isOperandVolatile (result, FALSE));
5221 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5227 /* signed is a little bit more difficult */
5229 /* now sign adjust for both left & right */
5231 /* modulus: sign of the right operand has no influence on the result! */
5232 if (AOP_TYPE(right) == AOP_LIT)
5234 signed char val = (char) operandLitValue(right);
5236 if (!rUnsigned && val < 0)
5237 emitcode ("mov", "b,#0x%02x", -val);
5239 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5241 else /* not literal */
5244 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5247 MOVA (aopGet (right, 0, FALSE, FALSE));
5248 lbl = newiTempLabel (NULL);
5249 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5250 emitcode ("cpl", "a"); /* 2's complement */
5251 emitcode ("inc", "a");
5252 emitcode ("", "%05d$:", (lbl->key + 100));
5253 emitcode ("mov", "b,a");
5257 /* let's see what's needed: */
5258 /* apply negative sign during runtime */
5259 runtimeSign = FALSE;
5260 /* negative sign from literals */
5261 compiletimeSign = FALSE;
5263 /* sign adjust left side */
5264 if (AOP_TYPE(left) == AOP_LIT)
5266 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5268 if (!lUnsigned && val < 0)
5270 compiletimeSign = TRUE; /* set sign flag */
5271 emitcode ("mov", "a,#0x%02x", -val);
5274 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5276 else /* ! literal */
5278 MOVA (aopGet (left, 0, FALSE, FALSE));
5283 emitcode ("clr", "F0"); /* clear sign flag */
5285 lbl = newiTempLabel (NULL);
5286 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5287 emitcode ("setb", "F0"); /* set sign flag */
5288 emitcode ("cpl", "a"); /* 2's complement */
5289 emitcode ("inc", "a");
5290 emitcode ("", "%05d$:", (lbl->key + 100));
5294 /* now the modulus */
5295 emitcode ("div", "ab");
5297 if (runtimeSign || compiletimeSign)
5299 emitcode ("mov", "a,b");
5300 lbl = newiTempLabel (NULL);
5302 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5303 emitcode ("cpl", "a"); /* 2's complement */
5304 emitcode ("inc", "a");
5305 emitcode ("", "%05d$:", (lbl->key + 100));
5307 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5310 /* msb is 0x00 or 0xff depending on the sign */
5313 emitcode ("mov", "c,F0");
5314 emitcode ("subb", "a,acc");
5316 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
5318 else /* compiletimeSign */
5320 aopPut (result, "#0xff", offset++, isOperandVolatile (result, FALSE));
5325 aopPut (result, "b", 0, isOperandVolatile (result, FALSE));
5327 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5333 /*-----------------------------------------------------------------*/
5334 /* genMod - generates code for division */
5335 /*-----------------------------------------------------------------*/
5339 operand *left = IC_LEFT (ic);
5340 operand *right = IC_RIGHT (ic);
5341 operand *result = IC_RESULT (ic);
5343 D(emitcode ("; genMod",""));
5345 /* assign the asmops */
5346 aopOp (left, ic, FALSE);
5347 aopOp (right, ic, FALSE);
5348 aopOp (result, ic, TRUE);
5350 /* special cases first */
5352 if (AOP_TYPE (left) == AOP_CRY &&
5353 AOP_TYPE (right) == AOP_CRY)
5355 genModbits (left, right, result);
5359 /* if both are of size == 1 */
5360 if (AOP_SIZE (left) == 1 &&
5361 AOP_SIZE (right) == 1)
5363 genModOneByte (left, right, result);
5367 /* should have been converted to function call */
5371 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5372 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5373 freeAsmop (result, NULL, ic, TRUE);
5376 /*-----------------------------------------------------------------*/
5377 /* genIfxJump :- will create a jump depending on the ifx */
5378 /*-----------------------------------------------------------------*/
5380 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5383 symbol *tlbl = newiTempLabel (NULL);
5386 D(emitcode ("; genIfxJump",""));
5388 /* if true label then we jump if condition
5392 jlbl = IC_TRUE (ic);
5393 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5394 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5398 /* false label is present */
5399 jlbl = IC_FALSE (ic);
5400 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5401 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5403 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5404 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5406 emitcode (inst, "%05d$", tlbl->key + 100);
5407 freeForBranchAsmop (result);
5408 freeForBranchAsmop (right);
5409 freeForBranchAsmop (left);
5410 emitcode ("ljmp", "%05d$", jlbl->key + 100);
5411 emitcode ("", "%05d$:", tlbl->key + 100);
5413 /* mark the icode as generated */
5417 /*-----------------------------------------------------------------*/
5418 /* genCmp :- greater or less than comparison */
5419 /*-----------------------------------------------------------------*/
5421 genCmp (operand * left, operand * right,
5422 operand * result, iCode * ifx, int sign, iCode *ic)
5424 int size, offset = 0;
5425 unsigned long lit = 0L;
5428 D(emitcode ("; genCmp",""));
5430 /* if left & right are bit variables */
5431 if (AOP_TYPE (left) == AOP_CRY &&
5432 AOP_TYPE (right) == AOP_CRY)
5434 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5435 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5439 /* subtract right from left if at the
5440 end the carry flag is set then we know that
5441 left is greater than right */
5442 size = max (AOP_SIZE (left), AOP_SIZE (right));
5444 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5445 if ((size == 1) && !sign &&
5446 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5448 symbol *lbl = newiTempLabel (NULL);
5449 emitcode ("cjne", "%s,%s,%05d$",
5450 aopGet (left, offset, FALSE, FALSE),
5451 aopGet (right, offset, FALSE, FALSE),
5453 emitcode ("", "%05d$:", lbl->key + 100);
5457 if (AOP_TYPE (right) == AOP_LIT)
5459 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5460 /* optimize if(x < 0) or if(x >= 0) */
5469 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5470 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5472 genIfxJump (ifx, "acc.7", left, right, result);
5473 freeAsmop (right, NULL, ic, TRUE);
5474 freeAsmop (left, NULL, ic, TRUE);
5479 emitcode ("rlc", "a");
5487 bool pushedB = FALSE;
5488 rightInB = aopGetUsesAcc(right, offset);
5492 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5494 MOVA (aopGet (left, offset, FALSE, FALSE));
5495 if (sign && size == 0)
5497 emitcode ("xrl", "a,#0x80");
5498 if (AOP_TYPE (right) == AOP_LIT)
5500 unsigned long lit = (unsigned long)
5501 floatFromVal (AOP (right)->aopu.aop_lit);
5502 emitcode ("subb", "a,#0x%02x",
5503 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5511 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5513 emitcode ("xrl", "b,#0x80");
5514 emitcode ("subb", "a,b");
5520 emitcode ("subb", "a,b");
5522 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5532 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5533 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5534 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5540 /* if the result is used in the next
5541 ifx conditional branch then generate
5542 code a little differently */
5544 genIfxJump (ifx, "c", NULL, NULL, result);
5547 /* leave the result in acc */
5551 /*-----------------------------------------------------------------*/
5552 /* genCmpGt :- greater than comparison */
5553 /*-----------------------------------------------------------------*/
5555 genCmpGt (iCode * ic, iCode * ifx)
5557 operand *left, *right, *result;
5558 sym_link *letype, *retype;
5561 D(emitcode ("; genCmpGt",""));
5563 left = IC_LEFT (ic);
5564 right = IC_RIGHT (ic);
5565 result = IC_RESULT (ic);
5567 letype = getSpec (operandType (left));
5568 retype = getSpec (operandType (right));
5569 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5570 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5571 /* assign the amsops */
5572 aopOp (left, ic, FALSE);
5573 aopOp (right, ic, FALSE);
5574 aopOp (result, ic, TRUE);
5576 genCmp (right, left, result, ifx, sign, ic);
5578 freeAsmop (result, NULL, ic, TRUE);
5581 /*-----------------------------------------------------------------*/
5582 /* genCmpLt - less than comparisons */
5583 /*-----------------------------------------------------------------*/
5585 genCmpLt (iCode * ic, iCode * ifx)
5587 operand *left, *right, *result;
5588 sym_link *letype, *retype;
5591 D(emitcode ("; genCmpLt",""));
5593 left = IC_LEFT (ic);
5594 right = IC_RIGHT (ic);
5595 result = IC_RESULT (ic);
5597 letype = getSpec (operandType (left));
5598 retype = getSpec (operandType (right));
5599 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5600 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5601 /* assign the amsops */
5602 aopOp (left, ic, FALSE);
5603 aopOp (right, ic, FALSE);
5604 aopOp (result, ic, TRUE);
5606 genCmp (left, right, result, ifx, sign,ic);
5608 freeAsmop (result, NULL, ic, TRUE);
5611 /*-----------------------------------------------------------------*/
5612 /* gencjneshort - compare and jump if not equal */
5613 /*-----------------------------------------------------------------*/
5615 gencjneshort (operand * left, operand * right, symbol * lbl)
5617 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5619 unsigned long lit = 0L;
5621 /* if the left side is a literal or
5622 if the right is in a pointer register and left
5624 if ((AOP_TYPE (left) == AOP_LIT) ||
5625 (AOP_TYPE (left) == AOP_IMMD) ||
5626 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5633 if (AOP_TYPE (right) == AOP_LIT)
5634 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5636 /* if the right side is a literal then anything goes */
5637 if (AOP_TYPE (right) == AOP_LIT &&
5638 AOP_TYPE (left) != AOP_DIR &&
5639 AOP_TYPE (left) != AOP_IMMD)
5643 emitcode ("cjne", "%s,%s,%05d$",
5644 aopGet (left, offset, FALSE, FALSE),
5645 aopGet (right, offset, FALSE, FALSE),
5651 /* if the right side is in a register or in direct space or
5652 if the left is a pointer register & right is not */
5653 else if (AOP_TYPE (right) == AOP_REG ||
5654 AOP_TYPE (right) == AOP_DIR ||
5655 AOP_TYPE (right) == AOP_LIT ||
5656 AOP_TYPE (right) == AOP_IMMD ||
5657 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5658 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5662 MOVA (aopGet (left, offset, FALSE, FALSE));
5663 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5664 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5665 emitcode ("jnz", "%05d$", lbl->key + 100);
5667 emitcode ("cjne", "a,%s,%05d$",
5668 aopGet (right, offset, FALSE, TRUE),
5675 /* right is a pointer reg need both a & b */
5679 //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
5680 wassertl(!BINUSE, "B was in use");
5681 l = aopGet (left, offset, FALSE, FALSE);
5682 if (strcmp (l, "b"))
5683 emitcode ("mov", "b,%s", l);
5684 MOVA (aopGet (right, offset, FALSE, FALSE));
5685 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5691 /*-----------------------------------------------------------------*/
5692 /* gencjne - compare and jump if not equal */
5693 /*-----------------------------------------------------------------*/
5695 gencjne (operand * left, operand * right, symbol * lbl)
5697 symbol *tlbl = newiTempLabel (NULL);
5699 gencjneshort (left, right, lbl);
5701 emitcode ("mov", "a,%s", one);
5702 emitcode ("sjmp", "%05d$", tlbl->key + 100);
5703 emitcode ("", "%05d$:", lbl->key + 100);
5704 emitcode ("clr", "a");
5705 emitcode ("", "%05d$:", tlbl->key + 100);
5708 /*-----------------------------------------------------------------*/
5709 /* genCmpEq - generates code for equal to */
5710 /*-----------------------------------------------------------------*/
5712 genCmpEq (iCode * ic, iCode * ifx)
5714 operand *left, *right, *result;
5716 D(emitcode ("; genCmpEq",""));
5718 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5719 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5720 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5722 /* if literal, literal on the right or
5723 if the right is in a pointer register and left
5725 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5726 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5728 operand *t = IC_RIGHT (ic);
5729 IC_RIGHT (ic) = IC_LEFT (ic);
5733 if (ifx && !AOP_SIZE (result))
5736 /* if they are both bit variables */
5737 if (AOP_TYPE (left) == AOP_CRY &&
5738 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5740 if (AOP_TYPE (right) == AOP_LIT)
5742 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5745 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5746 emitcode ("cpl", "c");
5750 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5754 emitcode ("clr", "c");
5756 /* AOP_TYPE(right) == AOP_CRY */
5760 symbol *lbl = newiTempLabel (NULL);
5761 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5762 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5763 emitcode ("cpl", "c");
5764 emitcode ("", "%05d$:", (lbl->key + 100));
5766 /* if true label then we jump if condition
5768 tlbl = newiTempLabel (NULL);
5771 emitcode ("jnc", "%05d$", tlbl->key + 100);
5772 freeForBranchAsmop (result);
5773 freeForBranchAsmop (right);
5774 freeForBranchAsmop (left);
5775 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5779 emitcode ("jc", "%05d$", tlbl->key + 100);
5780 freeForBranchAsmop (result);
5781 freeForBranchAsmop (right);
5782 freeForBranchAsmop (left);
5783 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5785 emitcode ("", "%05d$:", tlbl->key + 100);
5789 tlbl = newiTempLabel (NULL);
5790 gencjneshort (left, right, tlbl);
5793 freeForBranchAsmop (result);
5794 freeForBranchAsmop (right);
5795 freeForBranchAsmop (left);
5796 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5797 emitcode ("", "%05d$:", tlbl->key + 100);
5801 symbol *lbl = newiTempLabel (NULL);
5802 emitcode ("sjmp", "%05d$", lbl->key + 100);
5803 emitcode ("", "%05d$:", tlbl->key + 100);
5804 freeForBranchAsmop (result);
5805 freeForBranchAsmop (right);
5806 freeForBranchAsmop (left);
5807 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5808 emitcode ("", "%05d$:", lbl->key + 100);
5811 /* mark the icode as generated */
5816 /* if they are both bit variables */
5817 if (AOP_TYPE (left) == AOP_CRY &&
5818 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5820 if (AOP_TYPE (right) == AOP_LIT)
5822 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5825 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5826 emitcode ("cpl", "c");
5830 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5834 emitcode ("clr", "c");
5836 /* AOP_TYPE(right) == AOP_CRY */
5840 symbol *lbl = newiTempLabel (NULL);
5841 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5842 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5843 emitcode ("cpl", "c");
5844 emitcode ("", "%05d$:", (lbl->key + 100));
5847 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5854 genIfxJump (ifx, "c", left, right, result);
5857 /* if the result is used in an arithmetic operation
5858 then put the result in place */
5863 gencjne (left, right, newiTempLabel (NULL));
5864 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5866 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5871 genIfxJump (ifx, "a", left, right, result);
5874 /* if the result is used in an arithmetic operation
5875 then put the result in place */
5876 if (AOP_TYPE (result) != AOP_CRY)
5878 /* leave the result in acc */
5882 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5883 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5884 freeAsmop (result, NULL, ic, TRUE);
5887 /*-----------------------------------------------------------------*/
5888 /* ifxForOp - returns the icode containing the ifx for operand */
5889 /*-----------------------------------------------------------------*/
5891 ifxForOp (operand * op, iCode * ic)
5893 /* if true symbol then needs to be assigned */
5894 if (IS_TRUE_SYMOP (op))
5897 /* if this has register type condition and
5898 the next instruction is ifx with the same operand
5899 and live to of the operand is upto the ifx only then */
5901 ic->next->op == IFX &&
5902 IC_COND (ic->next)->key == op->key &&
5903 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5909 /*-----------------------------------------------------------------*/
5910 /* hasInc - operand is incremented before any other use */
5911 /*-----------------------------------------------------------------*/
5913 hasInc (operand *op, iCode *ic,int osize)
5915 sym_link *type = operandType(op);
5916 sym_link *retype = getSpec (type);
5917 iCode *lic = ic->next;
5920 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5921 if (!IS_SYMOP(op)) return NULL;
5923 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5924 if (IS_AGGREGATE(type->next)) return NULL;
5925 if (osize != (isize = getSize(type->next))) return NULL;
5928 /* if operand of the form op = op + <sizeof *op> */
5929 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5930 isOperandEqual(IC_RESULT(lic),op) &&
5931 isOperandLiteral(IC_RIGHT(lic)) &&
5932 operandLitValue(IC_RIGHT(lic)) == isize) {
5935 /* if the operand used or deffed */
5936 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
5939 /* if GOTO or IFX */
5940 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5946 /*-----------------------------------------------------------------*/
5947 /* genAndOp - for && operation */
5948 /*-----------------------------------------------------------------*/
5950 genAndOp (iCode * ic)
5952 operand *left, *right, *result;
5955 D(emitcode ("; genAndOp",""));
5957 /* note here that && operations that are in an
5958 if statement are taken away by backPatchLabels
5959 only those used in arthmetic operations remain */
5960 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5961 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5962 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
5964 /* if both are bit variables */
5965 if (AOP_TYPE (left) == AOP_CRY &&
5966 AOP_TYPE (right) == AOP_CRY)
5968 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5969 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5974 tlbl = newiTempLabel (NULL);
5976 emitcode ("jz", "%05d$", tlbl->key + 100);
5978 emitcode ("", "%05d$:", tlbl->key + 100);
5982 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5983 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5984 freeAsmop (result, NULL, ic, TRUE);
5988 /*-----------------------------------------------------------------*/
5989 /* genOrOp - for || operation */
5990 /*-----------------------------------------------------------------*/
5992 genOrOp (iCode * ic)
5994 operand *left, *right, *result;
5997 D(emitcode ("; genOrOp",""));
5999 /* note here that || operations that are in an
6000 if statement are taken away by backPatchLabels
6001 only those used in arthmetic operations remain */
6002 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6003 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6004 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6006 /* if both are bit variables */
6007 if (AOP_TYPE (left) == AOP_CRY &&
6008 AOP_TYPE (right) == AOP_CRY)
6010 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6011 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6016 tlbl = newiTempLabel (NULL);
6018 emitcode ("jnz", "%05d$", tlbl->key + 100);
6020 emitcode ("", "%05d$:", tlbl->key + 100);
6024 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6025 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6026 freeAsmop (result, NULL, ic, TRUE);
6029 /*-----------------------------------------------------------------*/
6030 /* isLiteralBit - test if lit == 2^n */
6031 /*-----------------------------------------------------------------*/
6033 isLiteralBit (unsigned long lit)
6035 unsigned long pw[32] =
6036 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6037 0x100L, 0x200L, 0x400L, 0x800L,
6038 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6039 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6040 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6041 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6042 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6045 for (idx = 0; idx < 32; idx++)
6051 /*-----------------------------------------------------------------*/
6052 /* continueIfTrue - */
6053 /*-----------------------------------------------------------------*/
6055 continueIfTrue (iCode * ic)
6058 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6062 /*-----------------------------------------------------------------*/
6064 /*-----------------------------------------------------------------*/
6066 jumpIfTrue (iCode * ic)
6069 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6073 /*-----------------------------------------------------------------*/
6074 /* jmpTrueOrFalse - */
6075 /*-----------------------------------------------------------------*/
6077 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6079 // ugly but optimized by peephole
6082 symbol *nlbl = newiTempLabel (NULL);
6083 emitcode ("sjmp", "%05d$", nlbl->key + 100);
6084 emitcode ("", "%05d$:", tlbl->key + 100);
6085 freeForBranchAsmop (result);
6086 freeForBranchAsmop (right);
6087 freeForBranchAsmop (left);
6088 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6089 emitcode ("", "%05d$:", nlbl->key + 100);
6093 freeForBranchAsmop (result);
6094 freeForBranchAsmop (right);
6095 freeForBranchAsmop (left);
6096 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6097 emitcode ("", "%05d$:", tlbl->key + 100);
6102 /*-----------------------------------------------------------------*/
6103 /* genAnd - code for and */
6104 /*-----------------------------------------------------------------*/
6106 genAnd (iCode * ic, iCode * ifx)
6108 operand *left, *right, *result;
6109 int size, offset = 0;
6110 unsigned long lit = 0L;
6114 D(emitcode ("; genAnd",""));
6116 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6117 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6118 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6121 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6123 AOP_TYPE (left), AOP_TYPE (right));
6124 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6126 AOP_SIZE (left), AOP_SIZE (right));
6129 /* if left is a literal & right is not then exchange them */
6130 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6131 AOP_NEEDSACC (left))
6133 operand *tmp = right;
6138 /* if result = right then exchange left and right */
6139 if (sameRegs (AOP (result), AOP (right)))
6141 operand *tmp = right;
6146 /* if right is bit then exchange them */
6147 if (AOP_TYPE (right) == AOP_CRY &&
6148 AOP_TYPE (left) != AOP_CRY)
6150 operand *tmp = right;
6154 if (AOP_TYPE (right) == AOP_LIT)
6155 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6157 size = AOP_SIZE (result);
6160 // result = bit & yy;
6161 if (AOP_TYPE (left) == AOP_CRY)
6163 // c = bit & literal;
6164 if (AOP_TYPE (right) == AOP_LIT)
6168 if (size && sameRegs (AOP (result), AOP (left)))
6171 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6176 if (size && (AOP_TYPE (result) == AOP_CRY))
6178 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6181 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6186 emitcode ("clr", "c");
6191 if (AOP_TYPE (right) == AOP_CRY)
6194 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6195 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6200 MOVA (aopGet (right, 0, FALSE, FALSE));
6202 emitcode ("rrc", "a");
6203 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6211 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6212 genIfxJump (ifx, "c", left, right, result);
6216 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6217 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6218 if ((AOP_TYPE (right) == AOP_LIT) &&
6219 (AOP_TYPE (result) == AOP_CRY) &&
6220 (AOP_TYPE (left) != AOP_CRY))
6222 int posbit = isLiteralBit (lit);
6227 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6231 switch (posbit & 0x07)
6233 case 0: emitcode ("rrc", "a");
6235 case 7: emitcode ("rlc", "a");
6237 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6246 SNPRINTF (buffer, sizeof(buffer),
6247 "acc.%d", posbit & 0x07);
6248 genIfxJump (ifx, buffer, left, right, result);
6251 {// what is this case? just found it in ds390/gen.c
6252 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6259 symbol *tlbl = newiTempLabel (NULL);
6260 int sizel = AOP_SIZE (left);
6262 emitcode ("setb", "c");
6265 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6267 MOVA (aopGet (left, offset, FALSE, FALSE));
6269 if ((posbit = isLiteralBit (bytelit)) != 0)
6270 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6273 if (bytelit != 0x0FFL)
6274 emitcode ("anl", "a,%s",
6275 aopGet (right, offset, FALSE, TRUE));
6276 emitcode ("jnz", "%05d$", tlbl->key + 100);
6281 // bit = left & literal
6284 emitcode ("clr", "c");
6285 emitcode ("", "%05d$:", tlbl->key + 100);
6287 // if(left & literal)
6291 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6293 emitcode ("", "%05d$:", tlbl->key + 100);
6301 /* if left is same as result */
6302 if (sameRegs (AOP (result), AOP (left)))
6304 for (; size--; offset++)
6306 if (AOP_TYPE (right) == AOP_LIT)
6308 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6309 if (bytelit == 0x0FF)
6311 /* dummy read of volatile operand */
6312 if (isOperandVolatile (left, FALSE))
6313 MOVA (aopGet (left, offset, FALSE, FALSE));
6317 else if (bytelit == 0)
6319 aopPut (result, zero, offset, isOperandVolatile (result, FALSE));
6321 else if (IS_AOP_PREG (result))
6323 MOVA (aopGet (left, offset, FALSE, TRUE));
6324 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6325 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6328 emitcode ("anl", "%s,%s",
6329 aopGet (left, offset, FALSE, TRUE),
6330 aopGet (right, offset, FALSE, FALSE));
6334 if (AOP_TYPE (left) == AOP_ACC && offset == 0)
6336 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6340 MOVA (aopGet (right, offset, FALSE, FALSE));
6341 if (IS_AOP_PREG (result))
6343 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6344 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6347 emitcode ("anl", "%s,a",
6348 aopGet (left, offset, FALSE, TRUE));
6355 // left & result in different registers
6356 if (AOP_TYPE (result) == AOP_CRY)
6359 // if(size), result in bit
6360 // if(!size && ifx), conditional oper: if(left & right)
6361 symbol *tlbl = newiTempLabel (NULL);
6362 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6364 emitcode ("setb", "c");
6367 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6368 && AOP_TYPE(left)==AOP_ACC)
6371 emitcode("mov", "a,b");
6372 emitcode ("anl", "a,%s",
6373 aopGet (right, offset, FALSE, FALSE));
6375 if (AOP_TYPE(left)==AOP_ACC)
6379 bool pushedB = pushB ();
6380 emitcode("mov", "b,a");
6381 MOVA (aopGet (right, offset, FALSE, FALSE));
6382 emitcode("anl", "a,b");
6387 MOVA (aopGet (right, offset, FALSE, FALSE));
6388 emitcode("anl", "a,b");
6391 MOVA (aopGet (right, offset, FALSE, FALSE));
6392 emitcode ("anl", "a,%s",
6393 aopGet (left, offset, FALSE, FALSE));
6396 emitcode ("jnz", "%05d$", tlbl->key + 100);
6402 emitcode ("", "%05d$:", tlbl->key + 100);
6406 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6408 emitcode ("", "%05d$:", tlbl->key + 100);
6412 for (; (size--); offset++)
6415 // result = left & right
6416 if (AOP_TYPE (right) == AOP_LIT)
6418 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6419 if (bytelit == 0x0FF)
6422 aopGet (left, offset, FALSE, FALSE),
6424 isOperandVolatile (result, FALSE));
6427 else if (bytelit == 0)
6429 /* dummy read of volatile operand */
6430 if (isOperandVolatile (left, FALSE))
6431 MOVA (aopGet (left, offset, FALSE, FALSE));
6432 aopPut (result, zero, offset, isOperandVolatile (result, FALSE));
6435 else if (AOP_TYPE (left) == AOP_ACC)
6439 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6440 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6445 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6446 aopPut (result, "b", offset, isOperandVolatile (result, FALSE));
6451 // faster than result <- left, anl result,right
6452 // and better if result is SFR
6453 if (AOP_TYPE (left) == AOP_ACC)
6456 emitcode("mov", "a,b");
6457 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6461 MOVA (aopGet (right, offset, FALSE, FALSE));
6462 emitcode ("anl", "a,%s",
6463 aopGet (left, offset, FALSE, FALSE));
6465 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6471 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6472 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6473 freeAsmop (result, NULL, ic, TRUE);
6476 /*-----------------------------------------------------------------*/
6477 /* genOr - code for or */
6478 /*-----------------------------------------------------------------*/
6480 genOr (iCode * ic, iCode * ifx)
6482 operand *left, *right, *result;
6483 int size, offset = 0;
6484 unsigned long lit = 0L;
6487 D(emitcode ("; genOr",""));
6489 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6490 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6491 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6494 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6496 AOP_TYPE (left), AOP_TYPE (right));
6497 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6499 AOP_SIZE (left), AOP_SIZE (right));
6502 /* if left is a literal & right is not then exchange them */
6503 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6504 AOP_NEEDSACC (left))
6506 operand *tmp = right;
6511 /* if result = right then exchange them */
6512 if (sameRegs (AOP (result), AOP (right)))
6514 operand *tmp = right;
6519 /* if right is bit then exchange them */
6520 if (AOP_TYPE (right) == AOP_CRY &&
6521 AOP_TYPE (left) != AOP_CRY)
6523 operand *tmp = right;
6527 if (AOP_TYPE (right) == AOP_LIT)
6528 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6530 size = AOP_SIZE (result);
6534 if (AOP_TYPE (left) == AOP_CRY)
6536 if (AOP_TYPE (right) == AOP_LIT)
6538 // c = bit | literal;
6541 // lit != 0 => result = 1
6542 if (AOP_TYPE (result) == AOP_CRY)
6545 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6547 continueIfTrue (ifx);
6550 emitcode ("setb", "c");
6554 // lit == 0 => result = left
6555 if (size && sameRegs (AOP (result), AOP (left)))
6557 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6562 if (AOP_TYPE (right) == AOP_CRY)
6565 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6566 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6571 symbol *tlbl = newiTempLabel (NULL);
6572 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6573 emitcode ("setb", "c");
6574 emitcode ("jb", "%s,%05d$",
6575 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6577 emitcode ("jnz", "%05d$", tlbl->key + 100);
6578 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6580 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6586 emitcode ("", "%05d$:", tlbl->key + 100);
6595 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6596 genIfxJump (ifx, "c", left, right, result);
6600 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6601 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6602 if ((AOP_TYPE (right) == AOP_LIT) &&
6603 (AOP_TYPE (result) == AOP_CRY) &&
6604 (AOP_TYPE (left) != AOP_CRY))
6610 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6612 continueIfTrue (ifx);
6617 // lit = 0, result = boolean(left)
6619 emitcode ("setb", "c");
6623 symbol *tlbl = newiTempLabel (NULL);
6624 emitcode ("jnz", "%05d$", tlbl->key + 100);
6626 emitcode ("", "%05d$:", tlbl->key + 100);
6630 genIfxJump (ifx, "a", left, right, result);
6638 /* if left is same as result */
6639 if (sameRegs (AOP (result), AOP (left)))
6641 for (; size--; offset++)
6643 if (AOP_TYPE (right) == AOP_LIT)
6645 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6648 /* dummy read of volatile operand */
6649 if (isOperandVolatile (left, FALSE))
6650 MOVA (aopGet (left, offset, FALSE, FALSE));
6654 else if (bytelit == 0x0FF)
6656 aopPut (result, "#0xFF", offset, isOperandVolatile (result, FALSE));
6658 else if (IS_AOP_PREG (left))
6660 MOVA (aopGet (left, offset, FALSE, TRUE));
6661 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6662 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6666 emitcode ("orl", "%s,%s",
6667 aopGet (left, offset, FALSE, TRUE),
6668 aopGet (right, offset, FALSE, FALSE));
6673 if (AOP_TYPE (left) == AOP_ACC)
6676 emitcode("mov", "a,b");
6677 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6681 MOVA (aopGet (right, offset, FALSE, FALSE));
6682 if (IS_AOP_PREG (left))
6684 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6685 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6689 emitcode ("orl", "%s,a",
6690 aopGet (left, offset, FALSE, TRUE));
6698 // left & result in different registers
6699 if (AOP_TYPE (result) == AOP_CRY)
6702 // if(size), result in bit
6703 // if(!size && ifx), conditional oper: if(left | right)
6704 symbol *tlbl = newiTempLabel (NULL);
6705 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6707 emitcode ("setb", "c");
6710 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6712 emitcode("mov", "a,b");
6713 emitcode ("orl", "a,%s",
6714 aopGet (right, offset, FALSE, FALSE));
6716 MOVA (aopGet (right, offset, FALSE, FALSE));
6717 emitcode ("orl", "a,%s",
6718 aopGet (left, offset, FALSE, FALSE));
6720 emitcode ("jnz", "%05d$", tlbl->key + 100);
6726 emitcode ("", "%05d$:", tlbl->key + 100);
6730 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6732 emitcode ("", "%05d$:", tlbl->key + 100);
6736 for (; (size--); offset++)
6739 // result = left | right
6740 if (AOP_TYPE (right) == AOP_LIT)
6742 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6746 aopGet (left, offset, FALSE, FALSE),
6748 isOperandVolatile (result, FALSE));
6751 else if (bytelit == 0x0FF)
6753 /* dummy read of volatile operand */
6754 if (isOperandVolatile (left, FALSE))
6755 MOVA (aopGet (left, offset, FALSE, FALSE));
6756 aopPut (result, "#0xFF", offset, isOperandVolatile (result, FALSE));
6760 // faster than result <- left, anl result,right
6761 // and better if result is SFR
6762 if (AOP_TYPE (left) == AOP_ACC)
6765 emitcode("mov", "a,b");
6766 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6770 MOVA (aopGet (right, offset, FALSE, FALSE));
6771 emitcode ("orl", "a,%s",
6772 aopGet (left, offset, FALSE, FALSE));
6774 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6780 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6781 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6782 freeAsmop (result, NULL, ic, TRUE);
6785 /*-----------------------------------------------------------------*/
6786 /* genXor - code for xclusive or */
6787 /*-----------------------------------------------------------------*/
6789 genXor (iCode * ic, iCode * ifx)
6791 operand *left, *right, *result;
6792 int size, offset = 0;
6793 unsigned long lit = 0L;
6796 D(emitcode ("; genXor",""));
6798 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6799 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6800 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6803 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6805 AOP_TYPE (left), AOP_TYPE (right));
6806 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6808 AOP_SIZE (left), AOP_SIZE (right));
6811 /* if left is a literal & right is not ||
6812 if left needs acc & right does not */
6813 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6814 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
6816 operand *tmp = right;
6821 /* if result = right then exchange them */
6822 if (sameRegs (AOP (result), AOP (right)))
6824 operand *tmp = right;
6829 /* if right is bit then exchange them */
6830 if (AOP_TYPE (right) == AOP_CRY &&
6831 AOP_TYPE (left) != AOP_CRY)
6833 operand *tmp = right;
6837 if (AOP_TYPE (right) == AOP_LIT)
6838 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6840 size = AOP_SIZE (result);
6844 if (AOP_TYPE (left) == AOP_CRY)
6846 if (AOP_TYPE (right) == AOP_LIT)
6848 // c = bit & literal;
6851 // lit>>1 != 0 => result = 1
6852 if (AOP_TYPE (result) == AOP_CRY)
6855 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6857 continueIfTrue (ifx);
6860 emitcode ("setb", "c");
6867 // lit == 0, result = left
6868 if (size && sameRegs (AOP (result), AOP (left)))
6870 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6874 // lit == 1, result = not(left)
6875 if (size && sameRegs (AOP (result), AOP (left)))
6877 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6882 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6883 emitcode ("cpl", "c");
6892 symbol *tlbl = newiTempLabel (NULL);
6893 if (AOP_TYPE (right) == AOP_CRY)
6896 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6900 int sizer = AOP_SIZE (right);
6902 // if val>>1 != 0, result = 1
6903 emitcode ("setb", "c");
6906 MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
6908 // test the msb of the lsb
6909 emitcode ("anl", "a,#0xfe");
6910 emitcode ("jnz", "%05d$", tlbl->key + 100);
6914 emitcode ("rrc", "a");
6916 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6917 emitcode ("cpl", "c");
6918 emitcode ("", "%05d$:", (tlbl->key + 100));
6925 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6926 genIfxJump (ifx, "c", left, right, result);
6930 /* if left is same as result */
6931 if (sameRegs (AOP (result), AOP (left)))
6933 for (; size--; offset++)
6935 if (AOP_TYPE (right) == AOP_LIT)
6937 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6940 /* dummy read of volatile operand */
6941 if (isOperandVolatile (left, FALSE))
6942 MOVA (aopGet (left, offset, FALSE, FALSE));
6946 else if (IS_AOP_PREG (left))
6948 MOVA (aopGet (left, offset, FALSE, TRUE));
6949 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6950 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6954 emitcode ("xrl", "%s,%s",
6955 aopGet (left, offset, FALSE, TRUE),
6956 aopGet (right, offset, FALSE, FALSE));
6961 if (AOP_TYPE (left) == AOP_ACC)
6964 emitcode("mov", "a,b");
6965 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6969 MOVA (aopGet (right, offset, FALSE, FALSE));
6970 if (IS_AOP_PREG (left))
6972 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6973 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6976 emitcode ("xrl", "%s,a",
6977 aopGet (left, offset, FALSE, TRUE));
6984 // left & result in different registers
6985 if (AOP_TYPE (result) == AOP_CRY)
6988 // if(size), result in bit
6989 // if(!size && ifx), conditional oper: if(left ^ right)
6990 symbol *tlbl = newiTempLabel (NULL);
6991 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6993 emitcode ("setb", "c");
6996 if ((AOP_TYPE (right) == AOP_LIT) &&
6997 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6999 MOVA (aopGet (left, offset, FALSE, FALSE));
7003 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7005 emitcode("mov", "a,b");
7006 emitcode ("xrl", "a,%s",
7007 aopGet (right, offset, FALSE, FALSE));
7009 MOVA (aopGet (right, offset, FALSE, FALSE));
7010 emitcode ("xrl", "a,%s",
7011 aopGet (left, offset, FALSE, FALSE));
7014 emitcode ("jnz", "%05d$", tlbl->key + 100);
7020 emitcode ("", "%05d$:", tlbl->key + 100);
7024 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7028 for (; (size--); offset++)
7031 // result = left & right
7032 if (AOP_TYPE (right) == AOP_LIT)
7034 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7038 aopGet (left, offset, FALSE, FALSE),
7040 isOperandVolatile (result, FALSE));
7044 // faster than result <- left, anl result,right
7045 // and better if result is SFR
7046 if (AOP_TYPE (left) == AOP_ACC)
7049 emitcode("mov", "a,b");
7050 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7054 MOVA (aopGet (right, offset, FALSE, FALSE));
7055 emitcode ("xrl", "a,%s",
7056 aopGet (left, offset, FALSE, TRUE));
7058 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7064 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7065 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7066 freeAsmop (result, NULL, ic, TRUE);
7069 /*-----------------------------------------------------------------*/
7070 /* genInline - write the inline code out */
7071 /*-----------------------------------------------------------------*/
7073 genInline (iCode * ic)
7075 char *buffer, *bp, *bp1;
7077 D(emitcode ("; genInline",""));
7079 _G.inLine += (!options.asmpeep);
7081 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
7082 strcpy (buffer, IC_INLINE (ic));
7084 /* emit each line as a code */
7095 /* Add \n for labels, not dirs such as c:\mydir */
7096 if ( (*bp == ':') && (isspace(bp[1])) )
7110 /* emitcode("",buffer); */
7111 _G.inLine -= (!options.asmpeep);
7114 /*-----------------------------------------------------------------*/
7115 /* genRRC - rotate right with carry */
7116 /*-----------------------------------------------------------------*/
7120 operand *left, *result;
7121 int size, offset = 0;
7124 D(emitcode ("; genRRC",""));
7126 /* rotate right with carry */
7127 left = IC_LEFT (ic);
7128 result = IC_RESULT (ic);
7129 aopOp (left, ic, FALSE);
7130 aopOp (result, ic, FALSE);
7132 /* move it to the result */
7133 size = AOP_SIZE (result);
7135 if (size == 1) { /* special case for 1 byte */
7136 l = aopGet (left, offset, FALSE, FALSE);
7138 emitcode ("rr", "a");
7141 /* no need to clear carry, bit7 will be written later */
7144 l = aopGet (left, offset, FALSE, FALSE);
7146 emitcode ("rrc", "a");
7147 if (AOP_SIZE (result) > 1)
7148 aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
7150 /* now we need to put the carry into the
7151 highest order byte of the result */
7152 if (AOP_SIZE (result) > 1)
7154 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7157 emitcode ("mov", "acc.7,c");
7159 aopPut (result, "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
7160 freeAsmop (left, NULL, ic, TRUE);
7161 freeAsmop (result, NULL, ic, TRUE);
7164 /*-----------------------------------------------------------------*/
7165 /* genRLC - generate code for rotate left with carry */
7166 /*-----------------------------------------------------------------*/
7170 operand *left, *result;
7171 int size, offset = 0;
7174 D(emitcode ("; genRLC",""));
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);
7187 l = aopGet (left, offset, FALSE, FALSE);
7189 if (size == 0) { /* special case for 1 byte */
7193 emitcode("rlc","a"); /* bit0 will be written later */
7194 if (AOP_SIZE (result) > 1)
7195 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
7198 l = aopGet (left, offset, FALSE, FALSE);
7200 emitcode ("rlc", "a");
7201 if (AOP_SIZE (result) > 1)
7202 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
7205 /* now we need to put the carry into the
7206 highest order byte of the result */
7207 if (AOP_SIZE (result) > 1)
7209 l = aopGet (result, 0, FALSE, FALSE);
7212 emitcode ("mov", "acc.0,c");
7214 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
7215 freeAsmop (left, NULL, ic, TRUE);
7216 freeAsmop (result, NULL, ic, TRUE);
7219 /*-----------------------------------------------------------------*/
7220 /* genGetHbit - generates code get highest order bit */
7221 /*-----------------------------------------------------------------*/
7223 genGetHbit (iCode * ic)
7225 operand *left, *result;
7227 D(emitcode ("; genGetHbit",""));
7229 left = IC_LEFT (ic);
7230 result = IC_RESULT (ic);
7231 aopOp (left, ic, FALSE);
7232 aopOp (result, ic, FALSE);
7234 /* get the highest order byte into a */
7235 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7236 if (AOP_TYPE (result) == AOP_CRY)
7238 emitcode ("rlc", "a");
7243 emitcode ("rl", "a");
7244 emitcode ("anl", "a,#0x01");
7249 freeAsmop (left, NULL, ic, TRUE);
7250 freeAsmop (result, NULL, ic, TRUE);
7253 /*-----------------------------------------------------------------*/
7254 /* genSwap - generates code to swap nibbles or bytes */
7255 /*-----------------------------------------------------------------*/
7257 genSwap (iCode * ic)
7259 operand *left, *result;
7261 D(emitcode ("; genSwap",""));
7263 left = IC_LEFT (ic);
7264 result = IC_RESULT (ic);
7265 aopOp (left, ic, FALSE);
7266 aopOp (result, ic, FALSE);
7268 switch (AOP_SIZE (left))
7270 case 1: /* swap nibbles in byte */
7271 MOVA (aopGet (left, 0, FALSE, FALSE));
7272 emitcode ("swap", "a");
7273 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
7275 case 2: /* swap bytes in word */
7276 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7278 MOVA (aopGet (left, 0, FALSE, FALSE));
7279 aopPut (result, aopGet (left, 1, FALSE, FALSE),
7280 0, isOperandVolatile (result, FALSE));
7281 aopPut (result, "a", 1, isOperandVolatile (result, FALSE));
7283 else if (operandsEqu (left, result))
7286 bool pushedB = FALSE, leftInB = FALSE;
7288 MOVA (aopGet (left, 0, FALSE, FALSE));
7289 if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
7292 emitcode ("mov", "b,a");
7296 aopPut (result, aopGet (left, 1, FALSE, FALSE),
7297 0, isOperandVolatile (result, FALSE));
7298 aopPut (result, reg, 1, isOperandVolatile (result, FALSE));
7305 aopPut (result, aopGet (left, 1, FALSE, FALSE),
7306 0, isOperandVolatile (result, FALSE));
7307 aopPut (result, aopGet (left, 0, FALSE, FALSE),
7308 1, isOperandVolatile (result, FALSE));
7312 wassertl(FALSE, "unsupported SWAP operand size");
7315 freeAsmop (left, NULL, ic, TRUE);
7316 freeAsmop (result, NULL, ic, TRUE);
7320 /*-----------------------------------------------------------------*/
7321 /* AccRol - rotate left accumulator by known count */
7322 /*-----------------------------------------------------------------*/
7324 AccRol (int shCount)
7326 shCount &= 0x0007; // shCount : 0..7
7333 emitcode ("rl", "a");
7336 emitcode ("rl", "a");
7337 emitcode ("rl", "a");
7340 emitcode ("swap", "a");
7341 emitcode ("rr", "a");
7344 emitcode ("swap", "a");
7347 emitcode ("swap", "a");
7348 emitcode ("rl", "a");
7351 emitcode ("rr", "a");
7352 emitcode ("rr", "a");
7355 emitcode ("rr", "a");
7360 /*-----------------------------------------------------------------*/
7361 /* AccLsh - left shift accumulator by known count */
7362 /*-----------------------------------------------------------------*/
7364 AccLsh (int shCount)
7369 emitcode ("add", "a,acc");
7370 else if (shCount == 2)
7372 emitcode ("add", "a,acc");
7373 emitcode ("add", "a,acc");
7377 /* rotate left accumulator */
7379 /* and kill the lower order bits */
7380 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
7385 /*-----------------------------------------------------------------*/
7386 /* AccRsh - right shift accumulator by known count */
7387 /*-----------------------------------------------------------------*/
7389 AccRsh (int shCount)
7396 emitcode ("rrc", "a");
7400 /* rotate right accumulator */
7401 AccRol (8 - shCount);
7402 /* and kill the higher order bits */
7403 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7408 /*-----------------------------------------------------------------*/
7409 /* AccSRsh - signed right shift accumulator by known count */
7410 /*-----------------------------------------------------------------*/
7412 AccSRsh (int shCount)
7419 emitcode ("mov", "c,acc.7");
7420 emitcode ("rrc", "a");
7422 else if (shCount == 2)
7424 emitcode ("mov", "c,acc.7");
7425 emitcode ("rrc", "a");
7426 emitcode ("mov", "c,acc.7");
7427 emitcode ("rrc", "a");
7431 tlbl = newiTempLabel (NULL);
7432 /* rotate right accumulator */
7433 AccRol (8 - shCount);
7434 /* and kill the higher order bits */
7435 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7436 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7437 emitcode ("orl", "a,#0x%02x",
7438 (unsigned char) ~SRMask[shCount]);
7439 emitcode ("", "%05d$:", tlbl->key + 100);
7444 /*-----------------------------------------------------------------*/
7445 /* shiftR1Left2Result - shift right one byte from left to result */
7446 /*-----------------------------------------------------------------*/
7448 shiftR1Left2Result (operand * left, int offl,
7449 operand * result, int offr,
7450 int shCount, int sign)
7452 MOVA (aopGet (left, offl, FALSE, FALSE));
7453 /* shift right accumulator */
7458 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7461 /*-----------------------------------------------------------------*/
7462 /* shiftL1Left2Result - shift left one byte from left to result */
7463 /*-----------------------------------------------------------------*/
7465 shiftL1Left2Result (operand * left, int offl,
7466 operand * result, int offr, int shCount)
7469 l = aopGet (left, offl, FALSE, FALSE);
7471 /* shift left accumulator */
7473 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7476 /*-----------------------------------------------------------------*/
7477 /* movLeft2Result - move byte from left to result */
7478 /*-----------------------------------------------------------------*/
7480 movLeft2Result (operand * left, int offl,
7481 operand * result, int offr, int sign)
7484 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7486 l = aopGet (left, offl, FALSE, FALSE);
7488 if (*l == '@' && (IS_AOP_PREG (result)))
7490 emitcode ("mov", "a,%s", l);
7491 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7496 aopPut (result, l, offr, isOperandVolatile (result, FALSE));
7499 /* MSB sign in acc.7 ! */
7500 if (getDataSize (left) == offl + 1)
7502 emitcode ("mov", "a,%s", l);
7503 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7510 /*-----------------------------------------------------------------*/
7511 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7512 /*-----------------------------------------------------------------*/
7516 emitcode ("rrc", "a");
7517 emitcode ("xch", "a,%s", x);
7518 emitcode ("rrc", "a");
7519 emitcode ("xch", "a,%s", x);
7522 /*-----------------------------------------------------------------*/
7523 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7524 /*-----------------------------------------------------------------*/
7528 emitcode ("xch", "a,%s", x);
7529 emitcode ("rlc", "a");
7530 emitcode ("xch", "a,%s", x);
7531 emitcode ("rlc", "a");
7534 /*-----------------------------------------------------------------*/
7535 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7536 /*-----------------------------------------------------------------*/
7540 emitcode ("xch", "a,%s", x);
7541 emitcode ("add", "a,acc");
7542 emitcode ("xch", "a,%s", x);
7543 emitcode ("rlc", "a");
7546 /*-----------------------------------------------------------------*/
7547 /* AccAXLsh - left shift a:x by known count (0..7) */
7548 /*-----------------------------------------------------------------*/
7550 AccAXLsh (char *x, int shCount)
7565 case 5: // AAAAABBB:CCCCCDDD
7567 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7569 emitcode ("anl", "a,#0x%02x",
7570 SLMask[shCount]); // BBB00000:CCCCCDDD
7572 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7574 AccRol (shCount); // DDDCCCCC:BBB00000
7576 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7578 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7580 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7582 emitcode ("anl", "a,#0x%02x",
7583 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7585 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7587 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7590 case 6: // AAAAAABB:CCCCCCDD
7591 emitcode ("anl", "a,#0x%02x",
7592 SRMask[shCount]); // 000000BB:CCCCCCDD
7593 emitcode ("mov", "c,acc.0"); // c = B
7594 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7596 AccAXRrl1 (x); // BCCCCCCD:D000000B
7597 AccAXRrl1 (x); // BBCCCCCC:DD000000
7599 emitcode("rrc","a");
7600 emitcode("xch","a,%s", x);
7601 emitcode("rrc","a");
7602 emitcode("mov","c,acc.0"); //<< get correct bit
7603 emitcode("xch","a,%s", x);
7605 emitcode("rrc","a");
7606 emitcode("xch","a,%s", x);
7607 emitcode("rrc","a");
7608 emitcode("xch","a,%s", x);
7611 case 7: // a:x <<= 7
7613 emitcode ("anl", "a,#0x%02x",
7614 SRMask[shCount]); // 0000000B:CCCCCCCD
7616 emitcode ("mov", "c,acc.0"); // c = B
7618 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7620 AccAXRrl1 (x); // BCCCCCCC:D0000000
7628 /*-----------------------------------------------------------------*/
7629 /* AccAXRsh - right shift a:x known count (0..7) */
7630 /*-----------------------------------------------------------------*/
7632 AccAXRsh (char *x, int shCount)
7640 AccAXRrl1 (x); // 0->a:x
7645 AccAXRrl1 (x); // 0->a:x
7648 AccAXRrl1 (x); // 0->a:x
7653 case 5: // AAAAABBB:CCCCCDDD = a:x
7655 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7657 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7659 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7661 emitcode ("anl", "a,#0x%02x",
7662 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7664 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7666 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7668 emitcode ("anl", "a,#0x%02x",
7669 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7671 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7673 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7675 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7678 case 6: // AABBBBBB:CCDDDDDD
7680 emitcode ("mov", "c,acc.7");
7681 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7683 emitcode ("mov", "c,acc.7");
7684 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7686 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7688 emitcode ("anl", "a,#0x%02x",
7689 SRMask[shCount]); // 000000AA:BBBBBBCC
7692 case 7: // ABBBBBBB:CDDDDDDD
7694 emitcode ("mov", "c,acc.7"); // c = A
7696 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7698 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7700 emitcode ("anl", "a,#0x%02x",
7701 SRMask[shCount]); // 0000000A:BBBBBBBC
7709 /*-----------------------------------------------------------------*/
7710 /* AccAXRshS - right shift signed a:x known count (0..7) */
7711 /*-----------------------------------------------------------------*/
7713 AccAXRshS (char *x, int shCount)
7721 emitcode ("mov", "c,acc.7");
7722 AccAXRrl1 (x); // s->a:x
7726 emitcode ("mov", "c,acc.7");
7727 AccAXRrl1 (x); // s->a:x
7729 emitcode ("mov", "c,acc.7");
7730 AccAXRrl1 (x); // s->a:x
7735 case 5: // AAAAABBB:CCCCCDDD = a:x
7737 tlbl = newiTempLabel (NULL);
7738 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7740 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7742 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7744 emitcode ("anl", "a,#0x%02x",
7745 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7747 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7749 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7751 emitcode ("anl", "a,#0x%02x",
7752 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7754 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7756 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7758 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7760 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7761 emitcode ("orl", "a,#0x%02x",
7762 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7764 emitcode ("", "%05d$:", tlbl->key + 100);
7765 break; // SSSSAAAA:BBBCCCCC
7767 case 6: // AABBBBBB:CCDDDDDD
7769 tlbl = newiTempLabel (NULL);
7770 emitcode ("mov", "c,acc.7");
7771 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7773 emitcode ("mov", "c,acc.7");
7774 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7776 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7778 emitcode ("anl", "a,#0x%02x",
7779 SRMask[shCount]); // 000000AA:BBBBBBCC
7781 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7782 emitcode ("orl", "a,#0x%02x",
7783 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7785 emitcode ("", "%05d$:", tlbl->key + 100);
7787 case 7: // ABBBBBBB:CDDDDDDD
7789 tlbl = newiTempLabel (NULL);
7790 emitcode ("mov", "c,acc.7"); // c = A
7792 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7794 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7796 emitcode ("anl", "a,#0x%02x",
7797 SRMask[shCount]); // 0000000A:BBBBBBBC
7799 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7800 emitcode ("orl", "a,#0x%02x",
7801 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7803 emitcode ("", "%05d$:", tlbl->key + 100);
7810 /*-----------------------------------------------------------------*/
7811 /* shiftL2Left2Result - shift left two bytes from left to result */
7812 /*-----------------------------------------------------------------*/
7814 shiftL2Left2Result (operand * left, int offl,
7815 operand * result, int offr, int shCount)
7817 if (sameRegs (AOP (result), AOP (left)) &&
7818 ((offl + MSB16) == offr))
7820 /* don't crash result[offr] */
7821 MOVA (aopGet (left, offl, FALSE, FALSE));
7822 emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
7826 movLeft2Result (left, offl, result, offr, 0);
7827 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
7829 /* ax << shCount (x = lsb(result)) */
7830 AccAXLsh (aopGet (result, offr, FALSE, FALSE), shCount);
7831 aopPut (result, "a", offr + MSB16, isOperandVolatile (result, FALSE));
7835 /*-----------------------------------------------------------------*/
7836 /* shiftR2Left2Result - shift right two bytes from left to result */
7837 /*-----------------------------------------------------------------*/
7839 shiftR2Left2Result (operand * left, int offl,
7840 operand * result, int offr,
7841 int shCount, int sign)
7843 if (sameRegs (AOP (result), AOP (left)) &&
7844 ((offl + MSB16) == offr))
7846 /* don't crash result[offr] */
7847 MOVA (aopGet (left, offl, FALSE, FALSE));
7848 emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
7852 movLeft2Result (left, offl, result, offr, 0);
7853 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
7855 /* a:x >> shCount (x = lsb(result)) */
7857 AccAXRshS (aopGet (result, offr, FALSE, FALSE), shCount);
7859 AccAXRsh (aopGet (result, offr, FALSE, FALSE), shCount);
7860 if (getDataSize (result) > 1)
7861 aopPut (result, "a", offr + MSB16, isOperandVolatile (result, FALSE));
7864 /*-----------------------------------------------------------------*/
7865 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7866 /*-----------------------------------------------------------------*/
7868 shiftLLeftOrResult (operand * left, int offl,
7869 operand * result, int offr, int shCount)
7871 MOVA (aopGet (left, offl, FALSE, FALSE));
7872 /* shift left accumulator */
7874 /* or with result */
7875 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
7876 /* back to result */
7877 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7880 /*-----------------------------------------------------------------*/
7881 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7882 /*-----------------------------------------------------------------*/
7884 shiftRLeftOrResult (operand * left, int offl,
7885 operand * result, int offr, int shCount)
7887 MOVA (aopGet (left, offl, FALSE, FALSE));
7888 /* shift right accumulator */
7890 /* or with result */
7891 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
7892 /* back to result */
7893 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7896 /*-----------------------------------------------------------------*/
7897 /* genlshOne - left shift a one byte quantity by known count */
7898 /*-----------------------------------------------------------------*/
7900 genlshOne (operand * result, operand * left, int shCount)
7902 D(emitcode ("; genlshOne",""));
7904 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7907 /*-----------------------------------------------------------------*/
7908 /* genlshTwo - left shift two bytes by known amount != 0 */
7909 /*-----------------------------------------------------------------*/
7911 genlshTwo (operand * result, operand * left, int shCount)
7915 D(emitcode ("; genlshTwo",""));
7917 size = getDataSize (result);
7919 /* if shCount >= 8 */
7927 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7929 movLeft2Result (left, LSB, result, MSB16, 0);
7931 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
7934 /* 1 <= shCount <= 7 */
7938 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7940 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7944 /*-----------------------------------------------------------------*/
7945 /* shiftLLong - shift left one long from left to result */
7946 /* offl = LSB or MSB16 */
7947 /*-----------------------------------------------------------------*/
7949 shiftLLong (operand * left, operand * result, int offr)
7952 int size = AOP_SIZE (result);
7954 if (size >= LSB + offr)
7956 l = aopGet (left, LSB, FALSE, FALSE);
7958 emitcode ("add", "a,acc");
7959 if (sameRegs (AOP (left), AOP (result)) &&
7960 size >= MSB16 + offr && offr != LSB)
7961 emitcode ("xch", "a,%s",
7962 aopGet (left, LSB + offr, FALSE, FALSE));
7964 aopPut (result, "a", LSB + offr, isOperandVolatile (result, FALSE));
7967 if (size >= MSB16 + offr)
7969 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7971 l = aopGet (left, MSB16, FALSE, FALSE);
7974 emitcode ("rlc", "a");
7975 if (sameRegs (AOP (left), AOP (result)) &&
7976 size >= MSB24 + offr && offr != LSB)
7977 emitcode ("xch", "a,%s",
7978 aopGet (left, MSB16 + offr, FALSE, FALSE));
7980 aopPut (result, "a", MSB16 + offr, isOperandVolatile (result, FALSE));
7983 if (size >= MSB24 + offr)
7985 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7987 l = aopGet (left, MSB24, FALSE, FALSE);
7990 emitcode ("rlc", "a");
7991 if (sameRegs (AOP (left), AOP (result)) &&
7992 size >= MSB32 + offr && offr != LSB)
7993 emitcode ("xch", "a,%s",
7994 aopGet (left, MSB24 + offr, FALSE, FALSE));
7996 aopPut (result, "a", MSB24 + offr, isOperandVolatile (result, FALSE));
7999 if (size > MSB32 + offr)
8001 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8003 l = aopGet (left, MSB32, FALSE, FALSE);
8006 emitcode ("rlc", "a");
8007 aopPut (result, "a", MSB32 + offr, isOperandVolatile (result, FALSE));
8010 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8013 /*-----------------------------------------------------------------*/
8014 /* genlshFour - shift four byte by a known amount != 0 */
8015 /*-----------------------------------------------------------------*/
8017 genlshFour (operand * result, operand * left, int shCount)
8021 D(emitcode ("; genlshFour",""));
8023 size = AOP_SIZE (result);
8025 /* if shifting more that 3 bytes */
8030 /* lowest order of left goes to the highest
8031 order of the destination */
8032 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8034 movLeft2Result (left, LSB, result, MSB32, 0);
8035 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8036 aopPut (result, zero, MSB16, isOperandVolatile (result, FALSE));
8037 aopPut (result, zero, MSB24, isOperandVolatile (result, FALSE));
8041 /* more than two bytes */
8042 else if (shCount >= 16)
8044 /* lower order two bytes goes to higher order two bytes */
8046 /* if some more remaining */
8048 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8051 movLeft2Result (left, MSB16, result, MSB32, 0);
8052 movLeft2Result (left, LSB, result, MSB24, 0);
8054 aopPut (result, zero, MSB16, isOperandVolatile (result, FALSE));
8055 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8059 /* if more than 1 byte */
8060 else if (shCount >= 8)
8062 /* lower order three bytes goes to higher order three bytes */
8067 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8069 movLeft2Result (left, LSB, result, MSB16, 0);
8075 movLeft2Result (left, MSB24, result, MSB32, 0);
8076 movLeft2Result (left, MSB16, result, MSB24, 0);
8077 movLeft2Result (left, LSB, result, MSB16, 0);
8078 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8080 else if (shCount == 1)
8081 shiftLLong (left, result, MSB16);
8084 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8085 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8086 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8087 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8092 /* 1 <= shCount <= 7 */
8093 else if (shCount <= 2)
8095 shiftLLong (left, result, LSB);
8097 shiftLLong (result, result, LSB);
8099 /* 3 <= shCount <= 7, optimize */
8102 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8103 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8104 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8108 /*-----------------------------------------------------------------*/
8109 /* genLeftShiftLiteral - left shifting by known count */
8110 /*-----------------------------------------------------------------*/
8112 genLeftShiftLiteral (operand * left,
8117 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8120 D(emitcode ("; genLeftShiftLiteral",""));
8122 freeAsmop (right, NULL, ic, TRUE);
8124 aopOp (left, ic, FALSE);
8125 aopOp (result, ic, FALSE);
8127 size = getSize (operandType (result));
8130 emitcode ("; shift left ", "result %d, left %d", size,
8134 /* I suppose that the left size >= result size */
8139 movLeft2Result (left, size, result, size, 0);
8143 else if (shCount >= (size * 8))
8145 aopPut (result, zero, size, isOperandVolatile (result, FALSE));
8151 genlshOne (result, left, shCount);
8155 genlshTwo (result, left, shCount);
8159 genlshFour (result, left, shCount);
8162 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8163 "*** ack! mystery literal shift!\n");
8167 freeAsmop (left, NULL, ic, TRUE);
8168 freeAsmop (result, NULL, ic, TRUE);
8171 /*-----------------------------------------------------------------*/
8172 /* genLeftShift - generates code for left shifting */
8173 /*-----------------------------------------------------------------*/
8175 genLeftShift (iCode * ic)
8177 operand *left, *right, *result;
8180 symbol *tlbl, *tlbl1;
8183 D(emitcode ("; genLeftShift",""));
8185 right = IC_RIGHT (ic);
8186 left = IC_LEFT (ic);
8187 result = IC_RESULT (ic);
8189 aopOp (right, ic, FALSE);
8191 /* if the shift count is known then do it
8192 as efficiently as possible */
8193 if (AOP_TYPE (right) == AOP_LIT)
8195 genLeftShiftLiteral (left, right, result, ic);
8199 /* shift count is unknown then we have to form
8200 a loop get the loop count in B : Note: we take
8201 only the lower order byte since shifting
8202 more that 32 bits make no sense anyway, ( the
8203 largest size of an object can be only 32 bits ) */
8206 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
8207 emitcode ("inc", "b");
8208 freeAsmop (right, NULL, ic, TRUE);
8209 aopOp (left, ic, FALSE);
8210 aopOp (result, ic, FALSE);
8212 /* now move the left to the result if they are not the same */
8213 if (!sameRegs (AOP (left), AOP (result)) &&
8214 AOP_SIZE (result) > 1)
8217 size = AOP_SIZE (result);
8221 l = aopGet (left, offset, FALSE, TRUE);
8222 if (*l == '@' && (IS_AOP_PREG (result)))
8225 emitcode ("mov", "a,%s", l);
8226 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
8229 aopPut (result, l, offset, isOperandVolatile (result, FALSE));
8234 tlbl = newiTempLabel (NULL);
8235 size = AOP_SIZE (result);
8237 tlbl1 = newiTempLabel (NULL);
8239 /* if it is only one byte then */
8242 symbol *tlbl1 = newiTempLabel (NULL);
8244 l = aopGet (left, 0, FALSE, FALSE);
8246 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8247 emitcode ("", "%05d$:", tlbl->key + 100);
8248 emitcode ("add", "a,acc");
8249 emitcode ("", "%05d$:", tlbl1->key + 100);
8250 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8252 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
8256 reAdjustPreg (AOP (result));
8258 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8259 emitcode ("", "%05d$:", tlbl->key + 100);
8260 l = aopGet (result, offset, FALSE, FALSE);
8262 emitcode ("add", "a,acc");
8263 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8266 l = aopGet (result, offset, FALSE, FALSE);
8268 emitcode ("rlc", "a");
8269 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8271 reAdjustPreg (AOP (result));
8273 emitcode ("", "%05d$:", tlbl1->key + 100);
8274 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8277 freeAsmop (left, NULL, ic, TRUE);
8278 freeAsmop (result, NULL, ic, TRUE);
8281 /*-----------------------------------------------------------------*/
8282 /* genrshOne - right shift a one byte quantity by known count */
8283 /*-----------------------------------------------------------------*/
8285 genrshOne (operand * result, operand * left,
8286 int shCount, int sign)
8288 D(emitcode ("; genrshOne",""));
8290 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8293 /*-----------------------------------------------------------------*/
8294 /* genrshTwo - right shift two bytes by known amount != 0 */
8295 /*-----------------------------------------------------------------*/
8297 genrshTwo (operand * result, operand * left,
8298 int shCount, int sign)
8300 D(emitcode ("; genrshTwo",""));
8302 /* if shCount >= 8 */
8307 shiftR1Left2Result (left, MSB16, result, LSB,
8310 movLeft2Result (left, MSB16, result, LSB, sign);
8311 addSign (result, MSB16, sign);
8314 /* 1 <= shCount <= 7 */
8316 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8319 /*-----------------------------------------------------------------*/
8320 /* shiftRLong - shift right one long from left to result */
8321 /* offl = LSB or MSB16 */
8322 /*-----------------------------------------------------------------*/
8324 shiftRLong (operand * left, int offl,
8325 operand * result, int sign)
8327 int isSameRegs=sameRegs(AOP(left),AOP(result));
8329 if (isSameRegs && offl>1) {
8330 // we are in big trouble, but this shouldn't happen
8331 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8334 MOVA (aopGet (left, MSB32, FALSE, FALSE));
8339 emitcode ("rlc", "a");
8340 emitcode ("subb", "a,acc");
8342 emitcode ("xch", "a,%s", aopGet (left, MSB32, FALSE, FALSE));
8344 aopPut (result, "a", MSB32, isOperandVolatile (result, FALSE));
8345 MOVA (aopGet (left, MSB32, FALSE, FALSE));
8348 aopPut (result, zero, MSB32, isOperandVolatile (result, FALSE));
8353 emitcode ("clr", "c");
8355 emitcode ("mov", "c,acc.7");
8358 emitcode ("rrc", "a");
8360 if (isSameRegs && offl==MSB16) {
8361 emitcode ("xch", "a,%s",aopGet (left, MSB24, FALSE, FALSE));
8363 aopPut (result, "a", MSB32-offl, isOperandVolatile (result, FALSE));
8364 MOVA (aopGet (left, MSB24, FALSE, FALSE));
8367 emitcode ("rrc", "a");
8368 if (isSameRegs && offl==1) {
8369 emitcode ("xch", "a,%s",aopGet (left, MSB16, FALSE, FALSE));
8371 aopPut (result, "a", MSB24-offl, isOperandVolatile (result, FALSE));
8372 MOVA (aopGet (left, MSB16, FALSE, FALSE));
8374 emitcode ("rrc", "a");
8375 aopPut (result, "a", MSB16 - offl, isOperandVolatile (result, FALSE));
8379 MOVA (aopGet (left, LSB, FALSE, FALSE));
8380 emitcode ("rrc", "a");
8381 aopPut (result, "a", LSB, isOperandVolatile (result, FALSE));
8385 /*-----------------------------------------------------------------*/
8386 /* genrshFour - shift four byte by a known amount != 0 */
8387 /*-----------------------------------------------------------------*/
8389 genrshFour (operand * result, operand * left,
8390 int shCount, int sign)
8392 D(emitcode ("; genrshFour",""));
8394 /* if shifting more that 3 bytes */
8399 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8401 movLeft2Result (left, MSB32, result, LSB, sign);
8402 addSign (result, MSB16, sign);
8404 else if (shCount >= 16)
8408 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8411 movLeft2Result (left, MSB24, result, LSB, 0);
8412 movLeft2Result (left, MSB32, result, MSB16, sign);
8414 addSign (result, MSB24, sign);
8416 else if (shCount >= 8)
8420 shiftRLong (left, MSB16, result, sign);
8421 else if (shCount == 0)
8423 movLeft2Result (left, MSB16, result, LSB, 0);
8424 movLeft2Result (left, MSB24, result, MSB16, 0);
8425 movLeft2Result (left, MSB32, result, MSB24, sign);
8426 addSign (result, MSB32, sign);
8430 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8431 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8432 /* the last shift is signed */
8433 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8434 addSign (result, MSB32, sign);
8438 { /* 1 <= shCount <= 7 */
8441 shiftRLong (left, LSB, result, sign);
8443 shiftRLong (result, LSB, result, sign);
8447 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8448 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8449 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8454 /*-----------------------------------------------------------------*/
8455 /* genRightShiftLiteral - right shifting by known count */
8456 /*-----------------------------------------------------------------*/
8458 genRightShiftLiteral (operand * left,
8464 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8467 D(emitcode ("; genRightShiftLiteral",""));
8469 freeAsmop (right, NULL, ic, TRUE);
8471 aopOp (left, ic, FALSE);
8472 aopOp (result, ic, FALSE);
8475 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8479 size = getDataSize (left);
8480 /* test the LEFT size !!! */
8482 /* I suppose that the left size >= result size */
8485 size = getDataSize (result);
8487 movLeft2Result (left, size, result, size, 0);
8490 else if (shCount >= (size * 8))
8493 /* get sign in acc.7 */
8494 MOVA (aopGet (left, size - 1, FALSE, FALSE));
8496 addSign (result, LSB, sign);
8503 genrshOne (result, left, shCount, sign);
8507 genrshTwo (result, left, shCount, sign);
8511 genrshFour (result, left, shCount, sign);
8517 freeAsmop (left, NULL, ic, TRUE);
8518 freeAsmop (result, NULL, ic, TRUE);
8521 /*-----------------------------------------------------------------*/
8522 /* genSignedRightShift - right shift of signed number */
8523 /*-----------------------------------------------------------------*/
8525 genSignedRightShift (iCode * ic)
8527 operand *right, *left, *result;
8530 symbol *tlbl, *tlbl1;
8533 D(emitcode ("; genSignedRightShift",""));
8535 /* we do it the hard way put the shift count in b
8536 and loop thru preserving the sign */
8538 right = IC_RIGHT (ic);
8539 left = IC_LEFT (ic);
8540 result = IC_RESULT (ic);
8542 aopOp (right, ic, FALSE);
8545 if (AOP_TYPE (right) == AOP_LIT)
8547 genRightShiftLiteral (left, right, result, ic, 1);
8550 /* shift count is unknown then we have to form
8551 a loop get the loop count in B : Note: we take
8552 only the lower order byte since shifting
8553 more that 32 bits make no sense anyway, ( the
8554 largest size of an object can be only 32 bits ) */
8557 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
8558 emitcode ("inc", "b");
8559 freeAsmop (right, NULL, ic, TRUE);
8560 aopOp (left, ic, FALSE);
8561 aopOp (result, ic, FALSE);
8563 /* now move the left to the result if they are not the
8565 if (!sameRegs (AOP (left), AOP (result)) &&
8566 AOP_SIZE (result) > 1)
8569 size = AOP_SIZE (result);
8573 l = aopGet (left, offset, FALSE, TRUE);
8574 if (*l == '@' && IS_AOP_PREG (result))
8577 emitcode ("mov", "a,%s", l);
8578 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
8581 aopPut (result, l, offset, isOperandVolatile (result, FALSE));
8586 /* mov the highest order bit to OVR */
8587 tlbl = newiTempLabel (NULL);
8588 tlbl1 = newiTempLabel (NULL);
8590 size = AOP_SIZE (result);
8592 MOVA (aopGet (left, offset, FALSE, FALSE));
8593 emitcode ("rlc", "a");
8594 emitcode ("mov", "ov,c");
8595 /* if it is only one byte then */
8598 l = aopGet (left, 0, FALSE, FALSE);
8600 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8601 emitcode ("", "%05d$:", tlbl->key + 100);
8602 emitcode ("mov", "c,ov");
8603 emitcode ("rrc", "a");
8604 emitcode ("", "%05d$:", tlbl1->key + 100);
8605 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8607 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
8611 reAdjustPreg (AOP (result));
8612 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8613 emitcode ("", "%05d$:", tlbl->key + 100);
8614 emitcode ("mov", "c,ov");
8617 l = aopGet (result, offset, FALSE, FALSE);
8619 emitcode ("rrc", "a");
8620 aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
8622 reAdjustPreg (AOP (result));
8623 emitcode ("", "%05d$:", tlbl1->key + 100);
8624 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8628 freeAsmop (left, NULL, ic, TRUE);
8629 freeAsmop (result, NULL, ic, TRUE);
8632 /*-----------------------------------------------------------------*/
8633 /* genRightShift - generate code for right shifting */
8634 /*-----------------------------------------------------------------*/
8636 genRightShift (iCode * ic)
8638 operand *right, *left, *result;
8642 symbol *tlbl, *tlbl1;
8645 D(emitcode ("; genRightShift",""));
8647 /* if signed then we do it the hard way preserve the
8648 sign bit moving it inwards */
8649 letype = getSpec (operandType (IC_LEFT (ic)));
8651 if (!SPEC_USIGN (letype))
8653 genSignedRightShift (ic);
8657 /* signed & unsigned types are treated the same : i.e. the
8658 signed is NOT propagated inwards : quoting from the
8659 ANSI - standard : "for E1 >> E2, is equivalent to division
8660 by 2**E2 if unsigned or if it has a non-negative value,
8661 otherwise the result is implementation defined ", MY definition
8662 is that the sign does not get propagated */
8664 right = IC_RIGHT (ic);
8665 left = IC_LEFT (ic);
8666 result = IC_RESULT (ic);
8668 aopOp (right, ic, FALSE);
8670 /* if the shift count is known then do it
8671 as efficiently as possible */
8672 if (AOP_TYPE (right) == AOP_LIT)
8674 genRightShiftLiteral (left, right, result, ic, 0);
8678 /* shift count is unknown then we have to form
8679 a loop get the loop count in B : Note: we take
8680 only the lower order byte since shifting
8681 more that 32 bits make no sense anyway, ( the
8682 largest size of an object can be only 32 bits ) */
8685 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
8686 emitcode ("inc", "b");
8687 freeAsmop (right, NULL, ic, TRUE);
8688 aopOp (left, ic, FALSE);
8689 aopOp (result, ic, FALSE);
8691 /* now move the left to the result if they are not the
8693 if (!sameRegs (AOP (left), AOP (result)) &&
8694 AOP_SIZE (result) > 1)
8697 size = AOP_SIZE (result);
8701 l = aopGet (left, offset, FALSE, TRUE);
8702 if (*l == '@' && IS_AOP_PREG (result))
8705 emitcode ("mov", "a,%s", l);
8706 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
8709 aopPut (result, l, offset, isOperandVolatile (result, FALSE));
8714 tlbl = newiTempLabel (NULL);
8715 tlbl1 = newiTempLabel (NULL);
8716 size = AOP_SIZE (result);
8719 /* if it is only one byte then */
8722 l = aopGet (left, 0, FALSE, FALSE);
8724 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8725 emitcode ("", "%05d$:", tlbl->key + 100);
8727 emitcode ("rrc", "a");
8728 emitcode ("", "%05d$:", tlbl1->key + 100);
8729 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8731 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
8735 reAdjustPreg (AOP (result));
8736 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8737 emitcode ("", "%05d$:", tlbl->key + 100);
8741 l = aopGet (result, offset, FALSE, FALSE);
8743 emitcode ("rrc", "a");
8744 aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
8746 reAdjustPreg (AOP (result));
8748 emitcode ("", "%05d$:", tlbl1->key + 100);
8749 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8753 freeAsmop (left, NULL, ic, TRUE);
8754 freeAsmop (result, NULL, ic, TRUE);
8757 /*-----------------------------------------------------------------*/
8758 /* emitPtrByteGet - emits code to get a byte into A through a */
8759 /* pointer register (R0, R1, or DPTR). The */
8760 /* original value of A can be preserved in B. */
8761 /*-----------------------------------------------------------------*/
8763 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
8770 emitcode ("mov", "b,a");
8771 emitcode ("mov", "a,@%s", rname);
8776 emitcode ("mov", "b,a");
8777 emitcode ("movx", "a,@%s", rname);
8782 emitcode ("mov", "b,a");
8783 emitcode ("movx", "a,@dptr");
8788 emitcode ("mov", "b,a");
8789 emitcode ("clr", "a");
8790 emitcode ("movc", "a,@a+dptr");
8796 emitcode ("push", "b");
8797 emitcode ("push", "acc");
8799 emitcode ("lcall", "__gptrget");
8801 emitcode ("pop", "b");
8806 /*-----------------------------------------------------------------*/
8807 /* emitPtrByteSet - emits code to set a byte from src through a */
8808 /* pointer register (R0, R1, or DPTR). */
8809 /*-----------------------------------------------------------------*/
8811 emitPtrByteSet (char *rname, int p_type, char *src)
8820 emitcode ("mov", "@%s,a", rname);
8823 emitcode ("mov", "@%s,%s", rname, src);
8828 emitcode ("movx", "@%s,a", rname);
8833 emitcode ("movx", "@dptr,a");
8838 emitcode ("lcall", "__gptrput");
8843 /*-----------------------------------------------------------------*/
8844 /* genUnpackBits - generates code for unpacking bits */
8845 /*-----------------------------------------------------------------*/
8847 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
8849 int offset = 0; /* result byte offset */
8850 int rsize; /* result size */
8851 int rlen = 0; /* remaining bitfield length */
8852 sym_link *etype; /* bitfield type information */
8853 int blen; /* bitfield length */
8854 int bstr; /* bitfield starting bit within byte */
8857 D(emitcode ("; genUnpackBits",""));
8859 etype = getSpec (operandType (result));
8860 rsize = getSize (operandType (result));
8861 blen = SPEC_BLEN (etype);
8862 bstr = SPEC_BSTR (etype);
8864 if (ifx && blen <= 8)
8866 emitPtrByteGet (rname, ptype, FALSE);
8869 SNPRINTF (buffer, sizeof(buffer),
8871 genIfxJump (ifx, buffer, NULL, NULL, NULL);
8876 emitcode ("anl", "a,#0x%02x",
8877 (((unsigned char) -1) >> (8 - blen)) << bstr);
8878 genIfxJump (ifx, "a", NULL, NULL, NULL);
8884 /* If the bitfield length is less than a byte */
8887 emitPtrByteGet (rname, ptype, FALSE);
8889 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
8890 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8894 /* Bit field did not fit in a byte. Copy all
8895 but the partial byte at the end. */
8896 for (rlen=blen;rlen>=8;rlen-=8)
8898 emitPtrByteGet (rname, ptype, FALSE);
8899 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8901 emitcode ("inc", "%s", rname);
8904 /* Handle the partial byte at the end */
8907 emitPtrByteGet (rname, ptype, FALSE);
8908 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
8909 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8917 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
8922 /*-----------------------------------------------------------------*/
8923 /* genDataPointerGet - generates code when ptr offset is known */
8924 /*-----------------------------------------------------------------*/
8926 genDataPointerGet (operand * left,
8932 int size, offset = 0;
8934 D(emitcode ("; genDataPointerGet",""));
8936 aopOp (result, ic, TRUE);
8938 /* get the string representation of the name */
8939 l = aopGet (left, 0, FALSE, TRUE);
8940 size = AOP_SIZE (result);
8944 sprintf (buffer, "(%s + %d)", l + 1, offset);
8946 sprintf (buffer, "%s", l + 1);
8947 aopPut (result, buffer, offset++, isOperandVolatile (result, FALSE));
8950 freeAsmop (left, NULL, ic, TRUE);
8951 freeAsmop (result, NULL, ic, TRUE);
8954 /*-----------------------------------------------------------------*/
8955 /* genNearPointerGet - emitcode for near pointer fetch */
8956 /*-----------------------------------------------------------------*/
8958 genNearPointerGet (operand * left,
8967 sym_link *rtype, *retype;
8968 sym_link *ltype = operandType (left);
8971 D(emitcode ("; genNearPointerGet",""));
8973 rtype = operandType (result);
8974 retype = getSpec (rtype);
8976 aopOp (left, ic, FALSE);
8978 /* if left is rematerialisable and
8979 result is not bitfield variable type and
8980 the left is pointer to data space i.e
8981 lower 128 bytes of space */
8982 if (AOP_TYPE (left) == AOP_IMMD &&
8983 !IS_BITFIELD (retype) &&
8984 DCL_TYPE (ltype) == POINTER)
8986 genDataPointerGet (left, result, ic);
8990 /* if the value is already in a pointer register
8991 then don't need anything more */
8992 if (!AOP_INPREG (AOP (left)))
8994 if (IS_AOP_PREG (left))
8996 // Aha, it is a pointer, just in disguise.
8997 rname = aopGet (left, 0, FALSE, FALSE);
9000 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9001 __FILE__, __LINE__);
9006 emitcode ("mov", "a%s,%s", rname + 1, rname);
9007 rname++; // skip the '@'.
9012 /* otherwise get a free pointer register */
9014 preg = getFreePtr (ic, &aop, FALSE);
9015 emitcode ("mov", "%s,%s",
9017 aopGet (left, 0, FALSE, TRUE));
9022 rname = aopGet (left, 0, FALSE, FALSE);
9024 //aopOp (result, ic, FALSE);
9025 aopOp (result, ic, result?TRUE:FALSE);
9027 /* if bitfield then unpack the bits */
9028 if (IS_BITFIELD (retype))
9029 genUnpackBits (result, rname, POINTER, ifx);
9032 /* we have can just get the values */
9033 int size = AOP_SIZE (result);
9038 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9041 emitcode ("mov", "a,@%s", rname);
9043 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9047 sprintf (buffer, "@%s", rname);
9048 aopPut (result, buffer, offset, isOperandVolatile (result, FALSE));
9052 emitcode ("inc", "%s", rname);
9056 /* now some housekeeping stuff */
9057 if (aop) /* we had to allocate for this iCode */
9059 if (pi) { /* post increment present */
9060 aopPut (left, rname, 0, isOperandVolatile (left, FALSE));
9062 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9066 /* we did not allocate which means left
9067 already in a pointer register, then
9068 if size > 0 && this could be used again
9069 we have to point it back to where it
9071 if ((AOP_SIZE (result) > 1 &&
9072 !OP_SYMBOL (left)->remat &&
9073 (OP_SYMBOL (left)->liveTo > ic->seq ||
9077 int size = AOP_SIZE (result) - 1;
9079 emitcode ("dec", "%s", rname);
9083 if (ifx && !ifx->generated)
9085 genIfxJump (ifx, "a", left, NULL, result);
9089 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9090 freeAsmop (left, NULL, ic, TRUE);
9091 if (pi) pi->generated = 1;
9094 /*-----------------------------------------------------------------*/
9095 /* genPagedPointerGet - emitcode for paged pointer fetch */
9096 /*-----------------------------------------------------------------*/
9098 genPagedPointerGet (operand * left,
9107 sym_link *rtype, *retype;
9109 D(emitcode ("; genPagedPointerGet",""));
9111 rtype = operandType (result);
9112 retype = getSpec (rtype);
9114 aopOp (left, ic, FALSE);
9116 /* if the value is already in a pointer register
9117 then don't need anything more */
9118 if (!AOP_INPREG (AOP (left)))
9120 /* otherwise get a free pointer register */
9122 preg = getFreePtr (ic, &aop, FALSE);
9123 emitcode ("mov", "%s,%s",
9125 aopGet (left, 0, FALSE, TRUE));
9129 rname = aopGet (left, 0, FALSE, FALSE);
9131 aopOp (result, ic, FALSE);
9133 /* if bitfield then unpack the bits */
9134 if (IS_BITFIELD (retype))
9135 genUnpackBits (result, rname, PPOINTER, ifx);
9138 /* we have can just get the values */
9139 int size = AOP_SIZE (result);
9145 emitcode ("movx", "a,@%s", rname);
9147 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9152 emitcode ("inc", "%s", rname);
9156 /* now some housekeeping stuff */
9157 if (aop) /* we had to allocate for this iCode */
9159 if (pi) aopPut (left, rname, 0, isOperandVolatile (left, FALSE));
9160 freeAsmop (NULL, aop, ic, TRUE);
9164 /* we did not allocate which means left
9165 already in a pointer register, then
9166 if size > 0 && this could be used again
9167 we have to point it back to where it
9169 if ((AOP_SIZE (result) > 1 &&
9170 !OP_SYMBOL (left)->remat &&
9171 (OP_SYMBOL (left)->liveTo > ic->seq ||
9175 int size = AOP_SIZE (result) - 1;
9177 emitcode ("dec", "%s", rname);
9181 if (ifx && !ifx->generated)
9183 genIfxJump (ifx, "a", left, NULL, result);
9187 freeAsmop (left, NULL, ic, TRUE);
9188 freeAsmop (result, NULL, ic, TRUE);
9189 if (pi) pi->generated = 1;
9193 /*--------------------------------------------------------------------*/
9194 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
9195 /*--------------------------------------------------------------------*/
9197 loadDptrFromOperand (operand *op, bool loadBToo)
9199 if (AOP_TYPE (op) != AOP_STR)
9201 /* if this is rematerializable */
9202 if (AOP_TYPE (op) == AOP_IMMD)
9204 emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
9207 if (AOP(op)->aopu.aop_immd.from_cast_remat)
9208 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
9211 wassertl(FALSE, "need pointerCode");
9212 emitcode ("", "; mov b,???");
9213 /* genPointerGet and genPointerSet originally did different
9214 ** things for this case. Both seem wrong.
9215 ** from genPointerGet:
9216 ** emitcode ("mov", "b,#%d", pointerCode (retype));
9217 ** from genPointerSet:
9218 ** emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
9223 else if (AOP_TYPE (op) == AOP_DPTR)
9227 MOVA (aopGet (op, 0, FALSE, FALSE));
9228 emitcode ("push", "acc");
9229 MOVA (aopGet (op, 1, FALSE, FALSE));
9230 emitcode ("push", "acc");
9231 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9232 emitcode ("pop", "dph");
9233 emitcode ("pop", "dpl");
9237 MOVA (aopGet (op, 0, FALSE, FALSE));
9238 emitcode ("push", "acc");
9239 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9240 emitcode ("pop", "dpl");
9244 { /* we need to get it byte by byte */
9245 emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
9246 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9248 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9253 /*-----------------------------------------------------------------*/
9254 /* genFarPointerGet - gget value from far space */
9255 /*-----------------------------------------------------------------*/
9257 genFarPointerGet (operand * left,
9258 operand * result, iCode * ic, iCode * pi, iCode * ifx)
9261 sym_link *retype = getSpec (operandType (result));
9263 D(emitcode ("; genFarPointerGet",""));
9265 aopOp (left, ic, FALSE);
9266 loadDptrFromOperand (left, FALSE);
9268 /* so dptr now contains the address */
9269 aopOp (result, ic, FALSE);
9271 /* if bit then unpack */
9272 if (IS_BITFIELD (retype))
9273 genUnpackBits (result, "dptr", FPOINTER, ifx);
9276 size = AOP_SIZE (result);
9281 emitcode ("movx", "a,@dptr");
9283 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9285 emitcode ("inc", "dptr");
9289 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9291 aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9292 aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9296 if (ifx && !ifx->generated)
9298 genIfxJump (ifx, "a", left, NULL, result);
9301 freeAsmop (left, NULL, ic, TRUE);
9302 freeAsmop (result, NULL, ic, TRUE);
9305 /*-----------------------------------------------------------------*/
9306 /* genCodePointerGet - gget value from code space */
9307 /*-----------------------------------------------------------------*/
9309 genCodePointerGet (operand * left,
9310 operand * result, iCode * ic, iCode *pi, iCode *ifx)
9313 sym_link *retype = getSpec (operandType (result));
9315 D(emitcode ("; genCodePointerGet",""));
9317 aopOp (left, ic, FALSE);
9318 loadDptrFromOperand (left, FALSE);
9320 /* so dptr now contains the address */
9321 aopOp (result, ic, FALSE);
9323 /* if bit then unpack */
9324 if (IS_BITFIELD (retype))
9325 genUnpackBits (result, "dptr", CPOINTER, ifx);
9328 size = AOP_SIZE (result);
9335 emitcode ("clr", "a");
9336 emitcode ("movc", "a,@a+dptr");
9338 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9339 emitcode ("inc", "dptr");
9343 emitcode ("mov", "a,#0x%02x", offset);
9344 emitcode ("movc", "a,@a+dptr");
9346 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9351 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9353 aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9354 aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9358 if (ifx && !ifx->generated)
9360 genIfxJump (ifx, "a", left, NULL, result);
9363 freeAsmop (left, NULL, ic, TRUE);
9364 freeAsmop (result, NULL, ic, TRUE);
9367 /*-----------------------------------------------------------------*/
9368 /* genGenPointerGet - gget value from generic pointer space */
9369 /*-----------------------------------------------------------------*/
9371 genGenPointerGet (operand * left,
9372 operand * result, iCode * ic, iCode *pi, iCode *ifx)
9375 sym_link *retype = getSpec (operandType (result));
9377 D(emitcode ("; genGenPointerGet",""));
9379 aopOp (left, ic, FALSE);
9380 loadDptrFromOperand (left, TRUE);
9382 /* so dptr know contains the address */
9383 aopOp (result, ic, FALSE);
9385 /* if bit then unpack */
9386 if (IS_BITFIELD (retype))
9387 genUnpackBits (result, "dptr", GPOINTER, ifx);
9390 size = AOP_SIZE (result);
9395 emitcode ("lcall", "__gptrget");
9397 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9399 emitcode ("inc", "dptr");
9403 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9405 aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9406 aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9410 if (ifx && !ifx->generated)
9412 genIfxJump (ifx, "a", left, NULL, result);
9416 freeAsmop (left, NULL, ic, TRUE);
9417 freeAsmop (result, NULL, ic, TRUE);
9420 /*-----------------------------------------------------------------*/
9421 /* genPointerGet - generate code for pointer get */
9422 /*-----------------------------------------------------------------*/
9424 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
9426 operand *left, *result;
9427 sym_link *type, *etype;
9430 D(emitcode ("; genPointerGet",""));
9432 left = IC_LEFT (ic);
9433 result = IC_RESULT (ic);
9435 if (getSize (operandType (result))>1)
9438 /* depending on the type of pointer we need to
9439 move it to the correct pointer register */
9440 type = operandType (left);
9441 etype = getSpec (type);
9442 /* if left is of type of pointer then it is simple */
9443 if (IS_PTR (type) && !IS_FUNC (type->next))
9444 p_type = DCL_TYPE (type);
9447 /* we have to go by the storage class */
9448 p_type = PTR_TYPE (SPEC_OCLS (etype));
9451 /* special case when cast remat */
9452 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9453 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9454 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9455 type = operandType (left);
9456 p_type = DCL_TYPE (type);
9458 /* now that we have the pointer type we assign
9459 the pointer values */
9465 genNearPointerGet (left, result, ic, pi, ifx);
9469 genPagedPointerGet (left, result, ic, pi, ifx);
9473 genFarPointerGet (left, result, ic, pi, ifx);
9477 genCodePointerGet (left, result, ic, pi, ifx);
9481 genGenPointerGet (left, result, ic, pi, ifx);
9489 /*-----------------------------------------------------------------*/
9490 /* genPackBits - generates code for packed bit storage */
9491 /*-----------------------------------------------------------------*/
9493 genPackBits (sym_link * etype,
9495 char *rname, int p_type)
9497 int offset = 0; /* source byte offset */
9498 int rlen = 0; /* remaining bitfield length */
9499 int blen; /* bitfield length */
9500 int bstr; /* bitfield starting bit within byte */
9501 int litval; /* source literal value (if AOP_LIT) */
9502 unsigned char mask; /* bitmask within current byte */
9504 D(emitcode ("; genPackBits",""));
9506 blen = SPEC_BLEN (etype);
9507 bstr = SPEC_BSTR (etype);
9509 /* If the bitfield length is less than a byte */
9512 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9513 (unsigned char) (0xFF >> (8 - bstr)));
9515 if (AOP_TYPE (right) == AOP_LIT)
9517 /* Case with a bitfield length <8 and literal source
9519 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9521 litval &= (~mask) & 0xff;
9522 emitPtrByteGet (rname, p_type, FALSE);
9523 if ((mask|litval)!=0xff)
9524 emitcode ("anl","a,#0x%02x", mask);
9526 emitcode ("orl","a,#0x%02x", litval);
9530 if ((blen==1) && (p_type!=GPOINTER))
9532 /* Case with a bitfield length == 1 and no generic pointer
9534 if (AOP_TYPE (right) == AOP_CRY)
9535 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9538 MOVA (aopGet (right, 0, FALSE, FALSE));
9539 emitcode ("rrc","a");
9541 emitPtrByteGet (rname, p_type, FALSE);
9542 emitcode ("mov","acc.%d,c",bstr);
9547 /* Case with a bitfield length < 8 and arbitrary source
9549 MOVA (aopGet (right, 0, FALSE, FALSE));
9550 /* shift and mask source value */
9552 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9555 /* transfer A to B and get next byte */
9556 emitPtrByteGet (rname, p_type, TRUE);
9558 emitcode ("anl", "a,#0x%02x", mask);
9559 emitcode ("orl", "a,b");
9560 if (p_type == GPOINTER)
9561 emitcode ("pop", "b");
9567 emitPtrByteSet (rname, p_type, "a");
9571 /* Bit length is greater than 7 bits. In this case, copy */
9572 /* all except the partial byte at the end */
9573 for (rlen=blen;rlen>=8;rlen-=8)
9575 emitPtrByteSet (rname, p_type,
9576 aopGet (right, offset++, FALSE, TRUE) );
9578 emitcode ("inc", "%s", rname);
9581 /* If there was a partial byte at the end */
9584 mask = (((unsigned char) -1 << rlen) & 0xff);
9586 if (AOP_TYPE (right) == AOP_LIT)
9588 /* Case with partial byte and literal source
9590 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9591 litval >>= (blen-rlen);
9592 litval &= (~mask) & 0xff;
9593 emitPtrByteGet (rname, p_type, FALSE);
9594 if ((mask|litval)!=0xff)
9595 emitcode ("anl","a,#0x%02x", mask);
9597 emitcode ("orl","a,#0x%02x", litval);
9602 /* Case with partial byte and arbitrary source
9604 MOVA (aopGet (right, offset++, FALSE, FALSE));
9605 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9608 /* transfer A to B and get next byte */
9609 emitPtrByteGet (rname, p_type, TRUE);
9611 emitcode ("anl", "a,#0x%02x", mask);
9612 emitcode ("orl", "a,b");
9613 if (p_type == GPOINTER)
9614 emitcode ("pop", "b");
9618 emitPtrByteSet (rname, p_type, "a");
9624 /*-----------------------------------------------------------------*/
9625 /* genDataPointerSet - remat pointer to data space */
9626 /*-----------------------------------------------------------------*/
9628 genDataPointerSet (operand * right,
9632 int size, offset = 0;
9633 char *l, buffer[256];
9635 D(emitcode ("; genDataPointerSet",""));
9637 aopOp (right, ic, FALSE);
9639 l = aopGet (result, 0, FALSE, TRUE);
9640 size = AOP_SIZE (right);
9644 sprintf (buffer, "(%s + %d)", l + 1, offset);
9646 sprintf (buffer, "%s", l + 1);
9647 emitcode ("mov", "%s,%s", buffer,
9648 aopGet (right, offset++, FALSE, FALSE));
9651 freeAsmop (right, NULL, ic, TRUE);
9652 freeAsmop (result, NULL, ic, TRUE);
9655 /*-----------------------------------------------------------------*/
9656 /* genNearPointerSet - emitcode for near pointer put */
9657 /*-----------------------------------------------------------------*/
9659 genNearPointerSet (operand * right,
9667 sym_link *retype, *letype;
9668 sym_link *ptype = operandType (result);
9670 D(emitcode ("; genNearPointerSet",""));
9672 retype = getSpec (operandType (right));
9673 letype = getSpec (ptype);
9674 aopOp (result, ic, FALSE);
9676 /* if the result is rematerializable &
9677 in data space & not a bit variable */
9678 if (AOP_TYPE (result) == AOP_IMMD &&
9679 DCL_TYPE (ptype) == POINTER &&
9680 !IS_BITVAR (retype) &&
9681 !IS_BITVAR (letype))
9683 genDataPointerSet (right, result, ic);
9687 /* if the value is already in a pointer register
9688 then don't need anything more */
9689 if (!AOP_INPREG (AOP (result)))
9692 //AOP_TYPE (result) == AOP_STK
9696 // Aha, it is a pointer, just in disguise.
9697 rname = aopGet (result, 0, FALSE, FALSE);
9700 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9701 __FILE__, __LINE__);
9706 emitcode ("mov", "a%s,%s", rname + 1, rname);
9707 rname++; // skip the '@'.
9712 /* otherwise get a free pointer register */
9714 preg = getFreePtr (ic, &aop, FALSE);
9715 emitcode ("mov", "%s,%s",
9717 aopGet (result, 0, FALSE, TRUE));
9723 rname = aopGet (result, 0, FALSE, FALSE);
9726 aopOp (right, ic, FALSE);
9728 /* if bitfield then unpack the bits */
9729 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9730 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
9733 /* we have can just get the values */
9734 int size = AOP_SIZE (right);
9739 l = aopGet (right, offset, FALSE, TRUE);
9743 emitcode ("mov", "@%s,a", rname);
9746 emitcode ("mov", "@%s,%s", rname, l);
9748 emitcode ("inc", "%s", rname);
9753 /* now some housekeeping stuff */
9754 if (aop) /* we had to allocate for this iCode */
9757 aopPut (result, rname, 0, isOperandVolatile (result, FALSE));
9758 freeAsmop (NULL, aop, ic, TRUE);
9762 /* we did not allocate which means left
9763 already in a pointer register, then
9764 if size > 0 && this could be used again
9765 we have to point it back to where it
9767 if ((AOP_SIZE (right) > 1 &&
9768 !OP_SYMBOL (result)->remat &&
9769 (OP_SYMBOL (result)->liveTo > ic->seq ||
9773 int size = AOP_SIZE (right) - 1;
9775 emitcode ("dec", "%s", rname);
9780 if (pi) pi->generated = 1;
9781 freeAsmop (result, NULL, ic, TRUE);
9782 freeAsmop (right, NULL, ic, TRUE);
9785 /*-----------------------------------------------------------------*/
9786 /* genPagedPointerSet - emitcode for Paged pointer put */
9787 /*-----------------------------------------------------------------*/
9789 genPagedPointerSet (operand * right,
9797 sym_link *retype, *letype;
9799 D(emitcode ("; genPagedPointerSet",""));
9801 retype = getSpec (operandType (right));
9802 letype = getSpec (operandType (result));
9804 aopOp (result, ic, FALSE);
9806 /* if the value is already in a pointer register
9807 then don't need anything more */
9808 if (!AOP_INPREG (AOP (result)))
9810 /* otherwise get a free pointer register */
9812 preg = getFreePtr (ic, &aop, FALSE);
9813 emitcode ("mov", "%s,%s",
9815 aopGet (result, 0, FALSE, TRUE));
9819 rname = aopGet (result, 0, FALSE, FALSE);
9821 aopOp (right, ic, FALSE);
9823 /* if bitfield then unpack the bits */
9824 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9825 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
9828 /* we have can just get the values */
9829 int size = AOP_SIZE (right);
9834 l = aopGet (right, offset, FALSE, TRUE);
9837 emitcode ("movx", "@%s,a", rname);
9840 emitcode ("inc", "%s", rname);
9846 /* now some housekeeping stuff */
9847 if (aop) /* we had to allocate for this iCode */
9850 aopPut (result, rname, 0, isOperandVolatile (result, FALSE));
9851 freeAsmop (NULL, aop, ic, TRUE);
9855 /* we did not allocate which means left
9856 already in a pointer register, then
9857 if size > 0 && this could be used again
9858 we have to point it back to where it
9860 if (AOP_SIZE (right) > 1 &&
9861 !OP_SYMBOL (result)->remat &&
9862 (OP_SYMBOL (result)->liveTo > ic->seq ||
9865 int size = AOP_SIZE (right) - 1;
9867 emitcode ("dec", "%s", rname);
9872 if (pi) pi->generated = 1;
9873 freeAsmop (result, NULL, ic, TRUE);
9874 freeAsmop (right, NULL, ic, TRUE);
9879 /*-----------------------------------------------------------------*/
9880 /* genFarPointerSet - set value from far space */
9881 /*-----------------------------------------------------------------*/
9883 genFarPointerSet (operand * right,
9884 operand * result, iCode * ic, iCode * pi)
9887 sym_link *retype = getSpec (operandType (right));
9888 sym_link *letype = getSpec (operandType (result));
9890 D(emitcode ("; genFarPointerSet",""));
9892 aopOp (result, ic, FALSE);
9893 loadDptrFromOperand (result, FALSE);
9895 /* so dptr know contains the address */
9896 aopOp (right, ic, FALSE);
9898 /* if bit then unpack */
9899 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9900 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
9903 size = AOP_SIZE (right);
9908 char *l = aopGet (right, offset++, FALSE, FALSE);
9910 emitcode ("movx", "@dptr,a");
9912 emitcode ("inc", "dptr");
9915 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9916 aopPut (result, "dpl", 0, isOperandVolatile (result, FALSE));
9917 aopPut (result, "dph", 1, isOperandVolatile (result, FALSE));
9920 freeAsmop (result, NULL, ic, TRUE);
9921 freeAsmop (right, NULL, ic, TRUE);
9924 /*-----------------------------------------------------------------*/
9925 /* genGenPointerSet - set value from generic pointer space */
9926 /*-----------------------------------------------------------------*/
9928 genGenPointerSet (operand * right,
9929 operand * result, iCode * ic, iCode * pi)
9932 sym_link *retype = getSpec (operandType (right));
9933 sym_link *letype = getSpec (operandType (result));
9935 D(emitcode ("; genGenPointerSet",""));
9937 aopOp (result, ic, FALSE);
9938 loadDptrFromOperand (result, TRUE);
9940 /* so dptr know contains the address */
9941 aopOp (right, ic, FALSE);
9943 /* if bit then unpack */
9944 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9945 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
9948 size = AOP_SIZE (right);
9953 char *l = aopGet (right, offset++, FALSE, FALSE);
9955 emitcode ("lcall", "__gptrput");
9957 emitcode ("inc", "dptr");
9961 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9962 aopPut (result, "dpl", 0, isOperandVolatile (result, FALSE));
9963 aopPut (result, "dph", 1, isOperandVolatile (result, FALSE));
9966 freeAsmop (result, NULL, ic, TRUE);
9967 freeAsmop (right, NULL, ic, TRUE);
9970 /*-----------------------------------------------------------------*/
9971 /* genPointerSet - stores the value into a pointer location */
9972 /*-----------------------------------------------------------------*/
9974 genPointerSet (iCode * ic, iCode *pi)
9976 operand *right, *result;
9977 sym_link *type, *etype;
9980 D(emitcode ("; genPointerSet",""));
9982 right = IC_RIGHT (ic);
9983 result = IC_RESULT (ic);
9985 /* depending on the type of pointer we need to
9986 move it to the correct pointer register */
9987 type = operandType (result);
9988 etype = getSpec (type);
9989 /* if left is of type of pointer then it is simple */
9990 if (IS_PTR (type) && !IS_FUNC (type->next))
9992 p_type = DCL_TYPE (type);
9996 /* we have to go by the storage class */
9997 p_type = PTR_TYPE (SPEC_OCLS (etype));
10000 /* special case when cast remat */
10001 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10002 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10003 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10004 type = operandType (result);
10005 p_type = DCL_TYPE (type);
10007 /* now that we have the pointer type we assign
10008 the pointer values */
10014 genNearPointerSet (right, result, ic, pi);
10018 genPagedPointerSet (right, result, ic, pi);
10022 genFarPointerSet (right, result, ic, pi);
10026 genGenPointerSet (right, result, ic, pi);
10030 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10031 "genPointerSet: illegal pointer type");
10036 /*-----------------------------------------------------------------*/
10037 /* genIfx - generate code for Ifx statement */
10038 /*-----------------------------------------------------------------*/
10040 genIfx (iCode * ic, iCode * popIc)
10042 operand *cond = IC_COND (ic);
10046 D(emitcode ("; genIfx",""));
10048 aopOp (cond, ic, FALSE);
10050 /* get the value into acc */
10051 if (AOP_TYPE (cond) != AOP_CRY)
10056 if (AOP(cond)->aopu.aop_dir)
10057 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10059 /* the result is now in the accumulator or a directly addressable bit */
10060 freeAsmop (cond, NULL, ic, TRUE);
10062 /* if there was something to be popped then do it */
10066 /* if the condition is a bit variable */
10068 genIfxJump(ic, dup, NULL, NULL, NULL);
10069 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10070 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10071 else if (isbit && !IS_ITEMP (cond))
10072 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10074 genIfxJump (ic, "a", NULL, NULL, NULL);
10079 /*-----------------------------------------------------------------*/
10080 /* genAddrOf - generates code for address of */
10081 /*-----------------------------------------------------------------*/
10083 genAddrOf (iCode * ic)
10085 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10088 D(emitcode ("; genAddrOf",""));
10090 aopOp (IC_RESULT (ic), ic, FALSE);
10092 /* if the operand is on the stack then we
10093 need to get the stack offset of this
10097 /* if it has an offset then we need to compute
10101 emitcode ("mov", "a,%s", SYM_BP (sym));
10102 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
10103 ((char) (sym->stack - _G.nRegsSaved)) :
10104 ((char) sym->stack)) & 0xff);
10105 aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10109 /* we can just move _bp */
10110 aopPut (IC_RESULT (ic), SYM_BP (sym), 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10112 /* fill the result with zero */
10113 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10118 aopPut (IC_RESULT (ic), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10124 /* object not on stack then we need the name */
10125 size = AOP_SIZE (IC_RESULT (ic));
10130 char s[SDCC_NAME_MAX];
10132 sprintf (s, "#(%s >> %d)",
10136 sprintf (s, "#%s", sym->rname);
10137 aopPut (IC_RESULT (ic), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10141 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10145 /*-----------------------------------------------------------------*/
10146 /* genFarFarAssign - assignment when both are in far space */
10147 /*-----------------------------------------------------------------*/
10149 genFarFarAssign (operand * result, operand * right, iCode * ic)
10151 int size = AOP_SIZE (right);
10155 D(emitcode ("; genFarFarAssign",""));
10157 /* first push the right side on to the stack */
10160 l = aopGet (right, offset++, FALSE, FALSE);
10162 emitcode ("push", "acc");
10165 freeAsmop (right, NULL, ic, FALSE);
10166 /* now assign DPTR to result */
10167 aopOp (result, ic, FALSE);
10168 size = AOP_SIZE (result);
10171 emitcode ("pop", "acc");
10172 aopPut (result, "a", --offset, isOperandVolatile (result, FALSE));
10174 freeAsmop (result, NULL, ic, FALSE);
10178 /*-----------------------------------------------------------------*/
10179 /* genAssign - generate code for assignment */
10180 /*-----------------------------------------------------------------*/
10182 genAssign (iCode * ic)
10184 operand *result, *right;
10186 unsigned long lit = 0L;
10188 D(emitcode("; genAssign",""));
10190 result = IC_RESULT (ic);
10191 right = IC_RIGHT (ic);
10193 /* if they are the same */
10194 if (operandsEqu (result, right) &&
10195 !isOperandVolatile (result, FALSE) &&
10196 !isOperandVolatile (right, FALSE))
10199 aopOp (right, ic, FALSE);
10201 /* special case both in far space */
10202 if (AOP_TYPE (right) == AOP_DPTR &&
10203 IS_TRUE_SYMOP (result) &&
10204 isOperandInFarSpace (result))
10207 genFarFarAssign (result, right, ic);
10211 aopOp (result, ic, TRUE);
10213 /* if they are the same registers */
10214 if (sameRegs (AOP (right), AOP (result)) &&
10215 !isOperandVolatile (result, FALSE) &&
10216 !isOperandVolatile (right, FALSE))
10219 /* if the result is a bit */
10220 if (AOP_TYPE (result) == AOP_CRY)
10223 /* if the right size is a literal then
10224 we know what the value is */
10225 if (AOP_TYPE (right) == AOP_LIT)
10227 if (((int) operandLitValue (right)))
10228 aopPut (result, one, 0, isOperandVolatile (result, FALSE));
10230 aopPut (result, zero, 0, isOperandVolatile (result, FALSE));
10234 /* the right is also a bit variable */
10235 if (AOP_TYPE (right) == AOP_CRY)
10237 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10238 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
10242 /* we need to or */
10244 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
10248 /* bit variables done */
10250 size = AOP_SIZE (result);
10252 if (AOP_TYPE (right) == AOP_LIT)
10253 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10255 (AOP_TYPE (result) != AOP_REG) &&
10256 (AOP_TYPE (right) == AOP_LIT) &&
10257 !IS_FLOAT (operandType (right)) &&
10260 while ((size) && (lit))
10263 aopGet (right, offset, FALSE, FALSE),
10265 isOperandVolatile (result, FALSE));
10270 emitcode ("clr", "a");
10273 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
10282 aopGet (right, offset, FALSE, FALSE),
10284 isOperandVolatile (result, FALSE));
10290 freeAsmop (right, NULL, ic, TRUE);
10291 freeAsmop (result, NULL, ic, TRUE);
10294 /*-----------------------------------------------------------------*/
10295 /* genJumpTab - generates code for jump table */
10296 /*-----------------------------------------------------------------*/
10298 genJumpTab (iCode * ic)
10300 symbol *jtab,*jtablo,*jtabhi;
10302 unsigned int count;
10304 D(emitcode ("; genJumpTab",""));
10306 count = elementsInSet( IC_JTLABELS (ic) );
10310 /* this algorithm needs 9 cycles and 7 + 3*n bytes
10311 if the switch argument is in a register.
10312 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
10313 /* (MB) What if peephole converts ljmp to sjmp or ret ???
10314 How will multiply by three be updated ???*/
10315 aopOp (IC_JTCOND (ic), ic, FALSE);
10316 /* get the condition into accumulator */
10317 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10319 /* multiply by three */
10320 emitcode ("add", "a,acc");
10321 emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
10322 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10324 jtab = newiTempLabel (NULL);
10325 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
10326 emitcode ("jmp", "@a+dptr");
10327 emitcode ("", "%05d$:", jtab->key + 100);
10328 /* now generate the jump labels */
10329 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10330 jtab = setNextItem (IC_JTLABELS (ic)))
10331 emitcode ("ljmp", "%05d$", jtab->key + 100);
10335 /* this algorithm needs 14 cycles and 13 + 2*n bytes
10336 if the switch argument is in a register.
10337 For n>6 this algorithm may be more compact */
10338 jtablo = newiTempLabel (NULL);
10339 jtabhi = newiTempLabel (NULL);
10341 /* get the condition into accumulator.
10342 Using b as temporary storage, if register push/pop is needed */
10343 aopOp (IC_JTCOND (ic), ic, FALSE);
10344 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10345 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
10346 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
10348 // (MB) what if B is in use???
10349 wassertl(!BINUSE, "B was in use");
10350 emitcode ("mov", "b,%s", l);
10353 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10357 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
10358 emitcode ("movc", "a,@a+pc");
10359 emitcode ("push", "acc");
10362 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
10363 emitcode ("movc", "a,@a+pc");
10364 emitcode ("push", "acc");
10368 /* this scales up to n<=255, but needs two more bytes
10369 and changes dptr */
10370 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
10371 emitcode ("movc", "a,@a+dptr");
10372 emitcode ("push", "acc");
10375 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
10376 emitcode ("movc", "a,@a+dptr");
10377 emitcode ("push", "acc");
10380 emitcode ("ret", "");
10382 /* now generate jump table, LSB */
10383 emitcode ("", "%05d$:", jtablo->key + 100);
10384 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10385 jtab = setNextItem (IC_JTLABELS (ic)))
10386 emitcode (".db", "%05d$", jtab->key + 100);
10388 /* now generate jump table, MSB */
10389 emitcode ("", "%05d$:", jtabhi->key + 100);
10390 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10391 jtab = setNextItem (IC_JTLABELS (ic)))
10392 emitcode (".db", "%05d$>>8", jtab->key + 100);
10396 /*-----------------------------------------------------------------*/
10397 /* genCast - gen code for casting */
10398 /*-----------------------------------------------------------------*/
10400 genCast (iCode * ic)
10402 operand *result = IC_RESULT (ic);
10403 sym_link *ctype = operandType (IC_LEFT (ic));
10404 sym_link *rtype = operandType (IC_RIGHT (ic));
10405 operand *right = IC_RIGHT (ic);
10408 D(emitcode("; genCast",""));
10410 /* if they are equivalent then do nothing */
10411 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10414 aopOp (right, ic, FALSE);
10415 aopOp (result, ic, FALSE);
10417 /* if the result is a bit (and not a bitfield) */
10418 // if (AOP_TYPE (result) == AOP_CRY)
10419 if (IS_BITVAR (OP_SYMBOL (result)->type)
10420 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
10422 /* if the right size is a literal then
10423 we know what the value is */
10424 if (AOP_TYPE (right) == AOP_LIT)
10426 if (((int) operandLitValue (right)))
10427 aopPut (result, one, 0, isOperandVolatile (result, FALSE));
10429 aopPut (result, zero, 0, isOperandVolatile (result, FALSE));
10434 /* the right is also a bit variable */
10435 if (AOP_TYPE (right) == AOP_CRY)
10437 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10438 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
10442 /* we need to or */
10444 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
10449 /* if they are the same size : or less */
10450 if (AOP_SIZE (result) <= AOP_SIZE (right))
10453 /* if they are in the same place */
10454 if (sameRegs (AOP (right), AOP (result)))
10457 /* if they in different places then copy */
10458 size = AOP_SIZE (result);
10463 aopGet (right, offset, FALSE, FALSE),
10465 isOperandVolatile (result, FALSE));
10472 /* if the result is of type pointer */
10473 if (IS_PTR (ctype))
10477 sym_link *type = operandType (right);
10478 sym_link *etype = getSpec (type);
10480 /* pointer to generic pointer */
10481 if (IS_GENPTR (ctype))
10484 p_type = DCL_TYPE (type);
10487 if (SPEC_SCLS(etype)==S_REGISTER) {
10488 // let's assume it is a generic pointer
10491 /* we have to go by the storage class */
10492 p_type = PTR_TYPE (SPEC_OCLS (etype));
10496 /* the first two bytes are known */
10497 size = GPTRSIZE - 1;
10502 aopGet (right, offset, FALSE, FALSE),
10504 isOperandVolatile (result, FALSE));
10507 /* the last byte depending on type */
10509 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
10514 // pointerTypeToGPByte will have bitched.
10518 sprintf(gpValStr, "#0x%x", gpVal);
10519 aopPut (result, gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
10524 /* just copy the pointers */
10525 size = AOP_SIZE (result);
10530 aopGet (right, offset, FALSE, FALSE),
10532 isOperandVolatile (result, FALSE));
10538 /* so we now know that the size of destination is greater
10539 than the size of the source */
10540 /* we move to result for the size of source */
10541 size = AOP_SIZE (right);
10546 aopGet (right, offset, FALSE, FALSE),
10548 isOperandVolatile (result, FALSE));
10552 /* now depending on the sign of the source && destination */
10553 size = AOP_SIZE (result) - AOP_SIZE (right);
10554 /* if unsigned or not an integral type */
10555 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
10558 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
10562 /* we need to extend the sign :{ */
10563 char *l = aopGet (right, AOP_SIZE (right) - 1,
10566 emitcode ("rlc", "a");
10567 emitcode ("subb", "a,acc");
10569 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
10572 /* we are done hurray !!!! */
10575 freeAsmop (right, NULL, ic, TRUE);
10576 freeAsmop (result, NULL, ic, TRUE);
10580 /*-----------------------------------------------------------------*/
10581 /* genDjnz - generate decrement & jump if not zero instrucion */
10582 /*-----------------------------------------------------------------*/
10584 genDjnz (iCode * ic, iCode * ifx)
10586 symbol *lbl, *lbl1;
10590 D(emitcode ("; genDjnz",""));
10592 /* if the if condition has a false label
10593 then we cannot save */
10594 if (IC_FALSE (ifx))
10597 /* if the minus is not of the form
10599 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10600 !IS_OP_LITERAL (IC_RIGHT (ic)))
10603 if (operandLitValue (IC_RIGHT (ic)) != 1)
10606 /* if the size of this greater than one then no
10608 if (getSize (operandType (IC_RESULT (ic))) > 1)
10611 /* otherwise we can save BIG */
10612 lbl = newiTempLabel (NULL);
10613 lbl1 = newiTempLabel (NULL);
10615 aopOp (IC_RESULT (ic), ic, FALSE);
10617 if (AOP_NEEDSACC(IC_RESULT(ic)))
10619 /* If the result is accessed indirectly via
10620 * the accumulator, we must explicitly write
10621 * it back after the decrement.
10623 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
10625 if (strcmp(rByte, "a"))
10627 /* Something is hopelessly wrong */
10628 fprintf(stderr, "*** warning: internal error at %s:%d\n",
10629 __FILE__, __LINE__);
10630 /* We can just give up; the generated code will be inefficient,
10631 * but what the hey.
10633 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10636 emitcode ("dec", "%s", rByte);
10637 aopPut (IC_RESULT (ic), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10638 emitcode ("jnz", "%05d$", lbl->key + 100);
10640 else if (IS_AOP_PREG (IC_RESULT (ic)))
10642 emitcode ("dec", "%s",
10643 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
10644 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
10645 emitcode ("jnz", "%05d$", lbl->key + 100);
10649 emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
10652 emitcode ("sjmp", "%05d$", lbl1->key + 100);
10653 emitcode ("", "%05d$:", lbl->key + 100);
10654 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
10655 emitcode ("", "%05d$:", lbl1->key + 100);
10657 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10658 ifx->generated = 1;
10662 /*-----------------------------------------------------------------*/
10663 /* genReceive - generate code for a receive iCode */
10664 /*-----------------------------------------------------------------*/
10666 genReceive (iCode * ic)
10668 int size = getSize (operandType (IC_RESULT (ic)));
10671 D(emitcode ("; genReceive",""));
10673 if (ic->argreg == 1) { /* first parameter */
10674 if (isOperandInFarSpace (IC_RESULT (ic)) &&
10675 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10676 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
10679 int receivingA = 0;
10682 for (offset = 0; offset<size; offset++)
10683 if (!strcmp (fReturn[offset], "a"))
10688 if (size==1 || getTempRegs(tempRegs, size-1, ic))
10690 for (offset = size-1; offset>0; offset--)
10691 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
10692 emitcode("mov","a,%s", fReturn[0]);
10694 aopOp (IC_RESULT (ic), ic, FALSE);
10696 aopPut (IC_RESULT (ic), "a", offset,
10697 isOperandVolatile (IC_RESULT (ic), FALSE));
10698 for (offset = 1; offset<size; offset++)
10699 aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset,
10700 isOperandVolatile (IC_RESULT (ic), FALSE));
10706 if (getTempRegs(tempRegs, size, ic))
10708 for (offset = 0; offset<size; offset++)
10709 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
10710 aopOp (IC_RESULT (ic), ic, FALSE);
10711 for (offset = 0; offset<size; offset++)
10712 aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset,
10713 isOperandVolatile (IC_RESULT (ic), FALSE));
10718 offset = fReturnSizeMCS51 - size;
10720 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
10721 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
10724 aopOp (IC_RESULT (ic), ic, FALSE);
10725 size = AOP_SIZE (IC_RESULT (ic));
10728 emitcode ("pop", "acc");
10729 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10734 aopOp (IC_RESULT (ic), ic, FALSE);
10736 assignResultValue (IC_RESULT (ic), NULL);
10738 } else { /* second receive onwards */
10740 aopOp (IC_RESULT (ic), ic, FALSE);
10741 rb1off = ic->argreg;
10743 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10748 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10751 /*-----------------------------------------------------------------*/
10752 /* genDummyRead - generate code for dummy read of volatiles */
10753 /*-----------------------------------------------------------------*/
10755 genDummyRead (iCode * ic)
10760 D(emitcode("; genDummyRead",""));
10762 op = IC_RIGHT (ic);
10763 if (op && IS_SYMOP (op))
10765 aopOp (op, ic, FALSE);
10767 /* if the result is a bit */
10768 if (AOP_TYPE (op) == AOP_CRY)
10769 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
10772 /* bit variables done */
10774 size = AOP_SIZE (op);
10778 MOVA (aopGet (op, offset, FALSE, FALSE));
10783 freeAsmop (op, NULL, ic, TRUE);
10787 if (op && IS_SYMOP (op))
10789 aopOp (op, ic, FALSE);
10791 /* if the result is a bit */
10792 if (AOP_TYPE (op) == AOP_CRY)
10793 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
10796 /* bit variables done */
10798 size = AOP_SIZE (op);
10802 MOVA (aopGet (op, offset, FALSE, FALSE));
10807 freeAsmop (op, NULL, ic, TRUE);
10811 /*-----------------------------------------------------------------*/
10812 /* genCritical - generate code for start of a critical sequence */
10813 /*-----------------------------------------------------------------*/
10815 genCritical (iCode *ic)
10817 symbol *tlbl = newiTempLabel (NULL);
10819 D(emitcode("; genCritical",""));
10821 if (IC_RESULT (ic))
10823 aopOp (IC_RESULT (ic), ic, TRUE);
10824 aopPut (IC_RESULT (ic), one, 0, 0);
10825 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
10826 aopPut (IC_RESULT (ic), zero, 0, 0);
10827 emitcode ("", "%05d$:", (tlbl->key + 100));
10828 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10832 emitcode ("setb", "c");
10833 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
10834 emitcode ("clr", "c");
10835 emitcode ("", "%05d$:", (tlbl->key + 100));
10836 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
10840 /*-----------------------------------------------------------------*/
10841 /* genEndCritical - generate code for end of a critical sequence */
10842 /*-----------------------------------------------------------------*/
10844 genEndCritical (iCode *ic)
10846 D(emitcode("; genEndCritical",""));
10850 aopOp (IC_RIGHT (ic), ic, FALSE);
10851 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
10853 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
10854 emitcode ("mov", "ea,c");
10858 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
10859 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
10860 emitcode ("rrc", "a");
10861 emitcode ("mov", "ea,c");
10863 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
10867 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
10868 emitcode ("mov", "ea,c");
10872 /*-----------------------------------------------------------------*/
10873 /* gen51Code - generate code for 8051 based controllers */
10874 /*-----------------------------------------------------------------*/
10876 gen51Code (iCode * lic)
10880 /* int cseq = 0; */
10882 _G.currentFunc = NULL;
10883 lineHead = lineCurr = NULL;
10885 /* print the allocation information */
10886 if (allocInfo && currFunc)
10887 printAllocInfo (currFunc, codeOutFile);
10888 /* if debug information required */
10889 if (options.debug && currFunc)
10891 debugFile->writeFunction (currFunc, lic);
10893 /* stack pointer name */
10894 if (options.useXstack)
10900 for (ic = lic; ic; ic = ic->next)
10902 _G.current_iCode = ic;
10904 if (ic->lineno && cln != ic->lineno)
10908 debugFile->writeCLine (ic);
10910 if (!options.noCcodeInAsm) {
10911 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
10912 printCLine(ic->filename, ic->lineno));
10917 if (ic->seqPoint && ic->seqPoint != cseq)
10919 emitcode ("", "; sequence point %d", ic->seqPoint);
10920 cseq = ic->seqPoint;
10923 if (options.iCodeInAsm) {
10924 char regsInUse[80];
10927 for (i=0; i<8; i++) {
10928 sprintf (®sInUse[i],
10929 "%c", ic->riu & (1<<i) ? i+'0' : '-');
10932 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
10934 /* if the result is marked as
10935 spilt and rematerializable or code for
10936 this has already been generated then
10938 if (resultRemat (ic) || ic->generated)
10941 /* depending on the operation */
10961 /* IPOP happens only when trying to restore a
10962 spilt live range, if there is an ifx statement
10963 following this pop then the if statement might
10964 be using some of the registers being popped which
10965 would destory the contents of the register so
10966 we need to check for this condition and handle it */
10968 ic->next->op == IFX &&
10969 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
10970 genIfx (ic->next, ic);
10988 genEndFunction (ic);
11008 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11025 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11029 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11036 /* note these two are xlated by algebraic equivalence
11037 during parsing SDCC.y */
11038 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11039 "got '>=' or '<=' shouldn't have come here");
11043 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11055 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11059 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11063 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11087 genRightShift (ic);
11090 case GET_VALUE_AT_ADDRESS:
11092 hasInc (IC_LEFT (ic), ic,
11093 getSize (operandType (IC_RESULT (ic)))),
11094 ifxForOp (IC_RESULT (ic), ic) );
11098 if (POINTER_SET (ic))
11099 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
11125 addSet (&_G.sendSet, ic);
11128 case DUMMY_READ_VOLATILE:
11137 genEndCritical (ic);
11149 _G.current_iCode = NULL;
11151 /* now we are ready to call the
11152 peep hole optimizer */
11153 if (!options.nopeep)
11154 peepHole (&lineHead);
11156 /* now do the actual printing */
11157 printLine (lineHead, codeOutFile);