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 || \
78 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
79 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
80 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 FILE *codeOutFile;
119 static void saveRBank (int, iCode *, bool);
121 #define RESULTONSTACK(x) \
122 (IC_RESULT(x) && IC_RESULT(x)->aop && \
123 IC_RESULT(x)->aop->type == AOP_STK )
125 #define MOVA(x) mova(x) /* use function to avoid multiple eval */
126 #define CLRC emitcode("clr","c")
127 #define SETC emitcode("setb","c")
129 static lineNode *lineHead = NULL;
130 static lineNode *lineCurr = NULL;
132 static unsigned char SLMask[] =
133 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
134 0xE0, 0xC0, 0x80, 0x00};
135 static unsigned char SRMask[] =
136 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
137 0x07, 0x03, 0x01, 0x00};
144 /*-----------------------------------------------------------------*/
145 /* emitcode - writes the code into a file : for now it is simple */
146 /*-----------------------------------------------------------------*/
148 emitcode (char *inst, const char *fmt,...)
151 char lb[INITIAL_INLINEASM];
160 SNPRINTF (lb, sizeof(lb), "%s\t", inst);
164 SNPRINTF (lb, sizeof(lb), "%s", inst);
167 tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb), fmt, ap);
171 tvsprintf (lb, sizeof(lb), fmt, ap);
174 while (isspace ((unsigned char)*lbp))
181 lineCurr = (lineCurr ?
182 connectLine (lineCurr, newLineNode (lb)) :
183 (lineHead = newLineNode (lb)));
186 lineCurr->isInline = _G.inLine;
187 lineCurr->isDebug = _G.debugLine;
188 lineCurr->ic = _G.current_iCode;
189 lineCurr->isComment = (*lbp==';');
193 /*-----------------------------------------------------------------*/
194 /* mcs51_emitDebuggerSymbol - associate the current code location */
195 /* with a debugger symbol */
196 /*-----------------------------------------------------------------*/
198 mcs51_emitDebuggerSymbol (char * debugSym)
201 emitcode ("", "%s ==.", debugSym);
205 /*-----------------------------------------------------------------*/
206 /* mova - moves specified value into accumulator */
207 /*-----------------------------------------------------------------*/
211 /* do some early peephole optimization */
212 if (!strncmp(x, "a", 2) || !strncmp(x, "acc", 4))
215 emitcode("mov", "a,%s", x);
218 /*-----------------------------------------------------------------*/
219 /* movc - moves specified value into the carry */
220 /*-----------------------------------------------------------------*/
228 else if (strcmp (s, "c"))
229 {/* it's not in carry already */
231 /* set C, if a >= 1 */
232 emitcode ("add", "a,#0xff");
236 /*-----------------------------------------------------------------*/
237 /* pushB - saves register B if necessary */
238 /*-----------------------------------------------------------------*/
242 bool pushedB = FALSE;
246 emitcode ("push", "b");
247 // printf("B was in use !\n");
257 /*-----------------------------------------------------------------*/
258 /* popB - restores value of register B if necessary */
259 /*-----------------------------------------------------------------*/
265 emitcode ("pop", "b");
273 /*-----------------------------------------------------------------*/
274 /* pushReg - saves register */
275 /*-----------------------------------------------------------------*/
277 pushReg (int index, bool bits_pushed)
279 regs * reg = mcs51_regWithIdx (index);
280 if (reg->type == REG_BIT)
283 emitcode ("push", "%s", reg->base);
287 emitcode ("push", "%s", reg->dname);
291 /*-----------------------------------------------------------------*/
292 /* popReg - restores register */
293 /*-----------------------------------------------------------------*/
295 popReg (int index, bool bits_popped)
297 regs * reg = mcs51_regWithIdx (index);
298 if (reg->type == REG_BIT)
301 emitcode ("pop", "%s", reg->base);
305 emitcode ("pop", "%s", reg->dname);
309 /*-----------------------------------------------------------------*/
310 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
311 /*-----------------------------------------------------------------*/
313 getFreePtr (iCode * ic, asmop ** aopp, bool result)
318 /* the logic: if r0 & r1 used in the instruction
319 then we are in trouble otherwise */
321 /* first check if r0 & r1 are used by this
322 instruction, in which case we are in trouble */
323 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
324 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
329 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
330 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
332 /* if no usage of r0 then return it */
335 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
336 (*aopp)->type = AOP_R0;
338 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
341 /* if no usage of r1 then return it */
344 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
345 (*aopp)->type = AOP_R1;
347 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
350 /* now we know they both have usage */
351 /* if r0 not used in this instruction */
354 /* push it if not already pushed */
357 emitcode ("mov", "b,%s",
358 mcs51_regWithIdx (R0_IDX)->dname);
361 else if (!_G.r0Pushed)
363 emitcode ("push", "%s",
364 mcs51_regWithIdx (R0_IDX)->dname);
368 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
369 (*aopp)->type = AOP_R0;
371 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
374 /* if r1 not used then */
378 /* push it if not already pushed */
381 emitcode ("mov", "b,%s",
382 mcs51_regWithIdx (R1_IDX)->dname);
385 else if (!_G.r1Pushed)
387 emitcode ("push", "%s",
388 mcs51_regWithIdx (R1_IDX)->dname);
392 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
393 (*aopp)->type = AOP_R1;
394 return mcs51_regWithIdx (R1_IDX);
397 /* I said end of world, but not quite end of world yet */
399 /* we can push it on the stack */
400 (*aopp)->type = AOP_STK;
403 /* in the case that result AND left AND right needs a pointer reg
404 we can safely use the result's */
405 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX)) {
406 (*aopp)->type = AOP_R0;
407 return mcs51_regWithIdx (R0_IDX);
409 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX)) {
410 (*aopp)->type = AOP_R1;
411 return mcs51_regWithIdx (R1_IDX);
415 /* now this is REALLY the end of the world */
416 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
417 "getFreePtr should never reach here");
422 /*-----------------------------------------------------------------*/
423 /* getTempRegs - initialize an array of pointers to GPR registers */
424 /* that are not in use. Returns 1 if the requested */
425 /* number of registers were available, 0 otherwise. */
426 /*-----------------------------------------------------------------*/
428 getTempRegs(regs **tempRegs, int size, iCode *ic)
435 ic = _G.current_iCode;
441 freeRegs = newBitVect(8);
442 bitVectSetBit (freeRegs, R2_IDX);
443 bitVectSetBit (freeRegs, R3_IDX);
444 bitVectSetBit (freeRegs, R4_IDX);
445 bitVectSetBit (freeRegs, R5_IDX);
446 bitVectSetBit (freeRegs, R6_IDX);
447 bitVectSetBit (freeRegs, R7_IDX);
449 if (IFFUNC_CALLEESAVES(_G.currentFunc->type))
451 bitVect * newfreeRegs;
452 newfreeRegs = bitVectIntersect (freeRegs, _G.currentFunc->regsUsed);
453 freeBitVect(freeRegs);
454 freeRegs = newfreeRegs;
456 freeRegs = bitVectCplAnd (freeRegs, ic->rMask);
459 for (i=0; i<freeRegs->size; i++)
461 if (bitVectBitValue(freeRegs,i))
462 tempRegs[offset++] = mcs51_regWithIdx(i);
465 freeBitVect(freeRegs);
470 freeBitVect(freeRegs);
475 /*-----------------------------------------------------------------*/
476 /* newAsmop - creates a new asmOp */
477 /*-----------------------------------------------------------------*/
479 newAsmop (short type)
483 aop = Safe_calloc (1, sizeof (asmop));
489 /*-----------------------------------------------------------------*/
490 /* pointerCode - returns the code for a pointer type */
491 /*-----------------------------------------------------------------*/
493 pointerCode (sym_link * etype)
496 return PTR_TYPE (SPEC_OCLS (etype));
500 /*-----------------------------------------------------------------*/
501 /* leftRightUseAcc - returns size of accumulator use by operands */
502 /*-----------------------------------------------------------------*/
504 leftRightUseAcc(iCode *ic)
513 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
514 "null iCode pointer");
521 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
524 size = getSize (OP_SYMBOL (op)->type);
529 else if (ic->op == JUMPTABLE)
532 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
535 size = getSize (OP_SYMBOL (op)->type);
543 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
546 size = getSize (OP_SYMBOL (op)->type);
551 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
554 size = getSize (OP_SYMBOL (op)->type);
566 /*-----------------------------------------------------------------*/
567 /* aopForSym - for a true symbol */
568 /*-----------------------------------------------------------------*/
570 aopForSym (iCode * ic, symbol * sym, bool result)
574 bool accuse = leftRightUseAcc (ic) || _G.accInUse;
576 wassertl (ic != NULL, "Got a null iCode");
577 wassertl (sym != NULL, "Got a null symbol");
579 space = SPEC_OCLS (sym->etype);
581 /* if already has one */
584 sym->aop->allocated++;
588 /* assign depending on the storage class */
589 /* if it is on the stack or indirectly addressable */
590 /* space we need to assign either r0 or r1 to it */
591 if (sym->onStack || sym->iaccess)
593 sym->aop = aop = newAsmop (0);
594 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
595 aop->size = getSize (sym->type);
597 /* now assign the address of the variable to
598 the pointer register */
599 if (aop->type != AOP_STK)
603 char offset = ((sym->stack < 0) ?
604 ((char) (sym->stack - _G.nRegsSaved)) :
605 ((char) sym->stack)) & 0xff;
607 if ((abs(offset) <= 3) ||
608 (accuse && (abs(offset) <= 7)))
610 emitcode ("mov", "%s,%s",
611 aop->aopu.aop_ptr->name, SYM_BP (sym));
614 emitcode ("dec", aop->aopu.aop_ptr->name);
619 emitcode ("inc", aop->aopu.aop_ptr->name);
626 emitcode ("push", "acc");
627 emitcode ("mov", "a,%s", SYM_BP (sym));
628 emitcode ("add", "a,#0x%02x", offset);
629 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
631 emitcode ("pop", "acc");
636 emitcode ("mov", "%s,#%s",
637 aop->aopu.aop_ptr->name,
640 aop->paged = space->paged;
643 aop->aopu.aop_stk = sym->stack;
647 /* if in bit space */
648 if (IN_BITSPACE (space))
650 sym->aop = aop = newAsmop (AOP_CRY);
651 aop->aopu.aop_dir = sym->rname;
652 aop->size = getSize (sym->type);
655 /* if it is in direct space */
656 if (IN_DIRSPACE (space))
658 //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
659 //printTypeChainRaw(sym->type, NULL);
660 //printf("space = %s\n", space ? space->sname : "NULL");
661 sym->aop = aop = newAsmop (AOP_DIR);
662 aop->aopu.aop_dir = sym->rname;
663 aop->size = getSize (sym->type);
667 /* special case for a function */
668 if (IS_FUNC (sym->type))
670 sym->aop = aop = newAsmop (AOP_IMMD);
671 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
672 aop->size = getSize (sym->type);
676 /* only remaining is far space */
677 /* in which case DPTR gets the address */
678 sym->aop = aop = newAsmop (AOP_DPTR);
679 emitcode ("mov", "dptr,#%s", sym->rname);
680 aop->size = getSize (sym->type);
682 /* if it is in code space */
683 if (IN_CODESPACE (space))
689 /*-----------------------------------------------------------------*/
690 /* aopForRemat - rematerialzes an object */
691 /*-----------------------------------------------------------------*/
693 aopForRemat (symbol * sym)
695 iCode *ic = sym->rematiCode;
696 asmop *aop = newAsmop (AOP_IMMD);
703 val += (int) operandLitValue (IC_RIGHT (ic));
704 else if (ic->op == '-')
705 val -= (int) operandLitValue (IC_RIGHT (ic));
706 else if (IS_CAST_ICODE(ic)) {
707 sym_link *from_type = operandType(IC_RIGHT(ic));
708 aop->aopu.aop_immd.from_cast_remat = 1;
709 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
710 ptr_type = pointerTypeToGPByte (DCL_TYPE(from_type), NULL, NULL);
714 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
719 SNPRINTF (buffer, sizeof(buffer),
721 OP_SYMBOL (IC_LEFT (ic))->rname,
722 val >= 0 ? '+' : '-',
727 strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
730 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
731 /* set immd2 field if required */
732 if (aop->aopu.aop_immd.from_cast_remat)
734 sprintf(buffer,"#0x%02x",ptr_type);
735 aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
741 /*-----------------------------------------------------------------*/
742 /* regsInCommon - two operands have some registers in common */
743 /*-----------------------------------------------------------------*/
745 regsInCommon (operand * op1, operand * op2)
750 /* if they have registers in common */
751 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
754 sym1 = OP_SYMBOL (op1);
755 sym2 = OP_SYMBOL (op2);
757 if (sym1->nRegs == 0 || sym2->nRegs == 0)
760 for (i = 0; i < sym1->nRegs; i++)
766 for (j = 0; j < sym2->nRegs; j++)
771 if (sym2->regs[j] == sym1->regs[i])
779 /*-----------------------------------------------------------------*/
780 /* operandsEqu - equivalent */
781 /*-----------------------------------------------------------------*/
783 operandsEqu (operand * op1, operand * op2)
787 /* if they're not symbols */
788 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
791 sym1 = OP_SYMBOL (op1);
792 sym2 = OP_SYMBOL (op2);
794 /* if both are itemps & one is spilt
795 and the other is not then false */
796 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
797 sym1->isspilt != sym2->isspilt)
800 /* if they are the same */
804 /* if they have the same rname */
805 if (sym1->rname[0] && sym2->rname[0] &&
806 strcmp (sym1->rname, sym2->rname) == 0 &&
807 !(IS_PARM (op2) && IS_ITEMP (op1)))
810 /* if left is a tmp & right is not */
811 if (IS_ITEMP (op1) &&
814 (sym1->usl.spillLoc == sym2))
817 if (IS_ITEMP (op2) &&
821 (sym2->usl.spillLoc == sym1))
827 /*-----------------------------------------------------------------*/
828 /* sameReg - two asmops have the same register at given offsets */
829 /*-----------------------------------------------------------------*/
831 sameReg (asmop * aop1, int off1, asmop * aop2, int off2)
833 if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
836 if (aop1->type != aop2->type)
839 if (aop1->aopu.aop_reg[off1] != aop2->aopu.aop_reg[off2])
845 /*-----------------------------------------------------------------*/
846 /* sameRegs - two asmops have the same registers */
847 /*-----------------------------------------------------------------*/
849 sameRegs (asmop * aop1, asmop * aop2)
856 if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
859 if (aop1->type != aop2->type)
862 if (aop1->size != aop2->size)
865 for (i = 0; i < aop1->size; i++)
866 if (aop1->aopu.aop_reg[i] != aop2->aopu.aop_reg[i])
872 /*-----------------------------------------------------------------*/
873 /* aopOp - allocates an asmop for an operand : */
874 /*-----------------------------------------------------------------*/
876 aopOp (operand * op, iCode * ic, bool result)
885 /* if this a literal */
886 if (IS_OP_LITERAL (op))
888 op->aop = aop = newAsmop (AOP_LIT);
889 aop->aopu.aop_lit = op->operand.valOperand;
890 aop->size = getSize (operandType (op));
894 /* if already has a asmop then continue */
897 op->aop->allocated++;
901 /* if the underlying symbol has a aop */
902 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
904 op->aop = OP_SYMBOL (op)->aop;
905 op->aop->allocated++;
909 /* if this is a true symbol */
910 if (IS_TRUE_SYMOP (op))
912 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
916 /* this is a temporary : this has
922 e) can be a return use only */
924 sym = OP_SYMBOL (op);
926 /* if the type is a conditional */
927 if (sym->regType == REG_CND)
929 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
934 /* if it is spilt then two situations
936 b) has a spill location */
937 if (sym->isspilt || sym->nRegs == 0)
940 /* rematerialize it NOW */
943 sym->aop = op->aop = aop =
945 aop->size = getSize (sym->type);
952 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
953 aop->size = getSize (sym->type);
954 for (i = 0; i < 2; i++)
955 aop->aopu.aop_str[i] = accUse[i];
963 aop = op->aop = sym->aop = newAsmop (AOP_STR);
964 aop->size = getSize (sym->type);
965 for (i = 0; i < fReturnSizeMCS51; i++)
966 aop->aopu.aop_str[i] = fReturn[i];
970 if (sym->usl.spillLoc)
972 asmop *oldAsmOp = NULL;
974 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
976 /* force a new aop if sizes differ */
977 oldAsmOp = sym->usl.spillLoc->aop;
978 sym->usl.spillLoc->aop = NULL;
980 sym->aop = op->aop = aop =
981 aopForSym (ic, sym->usl.spillLoc, result);
982 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
984 /* Don't reuse the new aop, go with the last one */
985 sym->usl.spillLoc->aop = oldAsmOp;
987 aop->size = getSize (sym->type);
991 /* else must be a dummy iTemp */
992 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
993 aop->size = getSize (sym->type);
997 /* if the type is a bit register */
998 if (sym->regType == REG_BIT)
1000 sym->aop = op->aop = aop = newAsmop (AOP_CRY);
1001 aop->size = sym->nRegs;//1???
1002 aop->aopu.aop_reg[0] = sym->regs[0];
1003 aop->aopu.aop_dir = sym->regs[0]->name;
1007 /* must be in a register */
1008 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1009 aop->size = sym->nRegs;
1010 for (i = 0; i < sym->nRegs; i++)
1011 aop->aopu.aop_reg[i] = sym->regs[i];
1014 /*-----------------------------------------------------------------*/
1015 /* freeAsmop - free up the asmop given to an operand */
1016 /*----------------------------------------------------------------*/
1018 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1035 /* depending on the asmop type only three cases need work
1036 AOP_R0, AOP_R1 & AOP_STK */
1042 emitcode ("mov", "r0,b");
1045 else if (_G.r0Pushed)
1049 emitcode ("pop", "ar0");
1053 bitVectUnSetBit (ic->rUsed, R0_IDX);
1059 emitcode ("mov", "r1,b");
1066 emitcode ("pop", "ar1");
1070 bitVectUnSetBit (ic->rUsed, R1_IDX);
1076 int stk = aop->aopu.aop_stk + aop->size - 1;
1077 bitVectUnSetBit (ic->rUsed, R0_IDX);
1078 bitVectUnSetBit (ic->rUsed, R1_IDX);
1080 getFreePtr (ic, &aop, FALSE);
1084 emitcode ("mov", "a,_bp");
1085 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1086 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1090 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1095 emitcode ("pop", "acc");
1096 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1099 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1102 freeAsmop (op, NULL, ic, TRUE);
1105 emitcode ("pop", "ar1");
1111 emitcode ("pop", "ar0");
1119 /* all other cases just dealloc */
1125 OP_SYMBOL (op)->aop = NULL;
1126 /* if the symbol has a spill */
1128 SPIL_LOC (op)->aop = NULL;
1133 /*------------------------------------------------------------------*/
1134 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
1135 /* pop r0 or r1 off stack if pushed */
1136 /*------------------------------------------------------------------*/
1138 freeForBranchAsmop (operand * op)
1150 if (!aop->allocated)
1158 emitcode ("mov", "r0,b");
1160 else if (_G.r0Pushed)
1162 emitcode ("pop", "ar0");
1169 emitcode ("mov", "r1,b");
1171 else if (_G.r1Pushed)
1173 emitcode ("pop", "ar1");
1180 int stk = aop->aopu.aop_stk + aop->size - 1;
1182 emitcode ("mov", "b,r0");
1185 emitcode ("mov", "a,_bp");
1186 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1187 emitcode ("mov", "r0,a");
1191 emitcode ("mov", "r0,_bp");
1196 emitcode ("pop", "acc");
1197 emitcode ("mov", "@r0,a");
1200 emitcode ("dec", "r0");
1202 emitcode ("mov", "r0,b");
1208 /*-----------------------------------------------------------------*/
1209 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
1210 /* clobber the accumulator */
1211 /*-----------------------------------------------------------------*/
1213 aopGetUsesAcc (operand * oper, int offset)
1215 asmop * aop = AOP (oper);
1217 if (offset > (aop->size - 1))
1235 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1246 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1252 /* Error case --- will have been caught already */
1258 /*-------------------------------------------------------------------*/
1259 /* aopGet - for fetching value of the aop */
1260 /*-------------------------------------------------------------------*/
1262 aopGet (operand * oper, int offset, bool bit16, bool dname)
1264 asmop * aop = AOP (oper);
1266 /* offset is greater than
1268 if (offset > (aop->size - 1) &&
1269 aop->type != AOP_LIT)
1272 /* depending on type */
1280 /* if we need to increment it */
1281 while (offset > aop->coff)
1283 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1287 while (offset < aop->coff)
1289 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1296 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1297 return (dname ? "acc" : "a");
1299 SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1300 return Safe_strdup(buffer);
1304 if (aop->code && aop->coff==0 && offset>=1) {
1305 emitcode ("mov", "a,#0x%02x", offset);
1306 emitcode ("movc", "a,@a+dptr");
1307 return (dname ? "acc" : "a");
1310 while (offset > aop->coff)
1312 emitcode ("inc", "dptr");
1316 while (offset < aop->coff)
1318 emitcode ("lcall", "__decdptr");
1325 emitcode ("clr", "a");
1326 emitcode ("movc", "a,@a+dptr");
1330 emitcode ("movx", "a,@dptr");
1332 return (dname ? "acc" : "a");
1335 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1337 SNPRINTF(buffer, sizeof(buffer),
1338 "%s",aop->aopu.aop_immd.aop_immd2);
1342 SNPRINTF(buffer, sizeof(buffer),
1343 "#%s", aop->aopu.aop_immd.aop_immd1);
1347 SNPRINTF (buffer, sizeof(buffer),
1349 aop->aopu.aop_immd.aop_immd1,
1354 SNPRINTF (buffer, sizeof(buffer),
1355 "#%s", aop->aopu.aop_immd.aop_immd1);
1357 return Safe_strdup(buffer);
1360 if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
1362 SNPRINTF (buffer, sizeof(buffer),
1364 aop->aopu.aop_dir, offset * 8);
1368 SNPRINTF (buffer, sizeof(buffer),
1375 SNPRINTF (buffer, sizeof(buffer),
1376 "%s", aop->aopu.aop_dir);
1379 return Safe_strdup(buffer);
1383 return aop->aopu.aop_reg[offset]->dname;
1385 return aop->aopu.aop_reg[offset]->name;
1388 emitcode ("clr", "a");
1389 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1390 emitcode ("rlc", "a");
1391 return (dname ? "acc" : "a");
1394 if (!offset && dname)
1396 return aop->aopu.aop_str[offset];
1399 return aopLiteral (aop->aopu.aop_lit, offset);
1403 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1407 return aop->aopu.aop_str[offset];
1411 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1412 "aopget got unsupported aop->type");
1416 /*-----------------------------------------------------------------*/
1417 /* aopPutUsesAcc - indicates ahead of time whether aopPut() will */
1418 /* clobber the accumulator */
1419 /*-----------------------------------------------------------------*/
1421 aopPutUsesAcc (operand * oper, const char *s, int offset)
1423 asmop * aop = AOP (oper);
1425 if (offset > (aop->size - 1))
1435 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1441 return ((aop->paged) || (*s == '@'));
1445 return (!aop->aopu.aop_dir || strcmp(s, aop->aopu.aop_dir));
1453 /* Error case --- will have been caught already */
1459 /*-----------------------------------------------------------------*/
1460 /* aopPut - puts a string for a aop and indicates if acc is in use */
1461 /*-----------------------------------------------------------------*/
1463 aopPut (operand * result, const char *s, int offset)
1465 bool bvolatile = isOperandVolatile (result, FALSE);
1466 bool accuse = FALSE;
1467 asmop * aop = AOP (result);
1469 if (aop->size && offset > (aop->size - 1))
1471 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1472 "aopPut got offset > aop->size");
1476 /* will assign value to value */
1477 /* depending on where it is ofcourse */
1481 MOVA (s); /* read s in case it was volatile */
1486 if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1488 SNPRINTF (buffer, sizeof(buffer),
1490 aop->aopu.aop_dir, offset * 8);
1494 SNPRINTF (buffer, sizeof(buffer),
1496 aop->aopu.aop_dir, offset);
1500 SNPRINTF (buffer, sizeof(buffer),
1501 "%s", aop->aopu.aop_dir);
1504 if (strcmp (buffer, s) || bvolatile)
1506 emitcode ("mov", "%s,%s", buffer, s);
1508 if (!strcmp (buffer, "acc"))
1515 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1516 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1519 strcmp (s, "r0") == 0 ||
1520 strcmp (s, "r1") == 0 ||
1521 strcmp (s, "r2") == 0 ||
1522 strcmp (s, "r3") == 0 ||
1523 strcmp (s, "r4") == 0 ||
1524 strcmp (s, "r5") == 0 ||
1525 strcmp (s, "r6") == 0 ||
1526 strcmp (s, "r7") == 0)
1528 emitcode ("mov", "%s,%s",
1529 aop->aopu.aop_reg[offset]->dname, s);
1533 emitcode ("mov", "%s,%s",
1534 aop->aopu.aop_reg[offset]->name, s);
1542 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1543 "aopPut writing to code space");
1547 while (offset > aop->coff)
1550 emitcode ("inc", "dptr");
1553 while (offset < aop->coff)
1556 emitcode ("lcall", "__decdptr");
1561 /* if not in accumulator */
1564 emitcode ("movx", "@dptr,a");
1569 while (offset > aop->coff)
1572 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1574 while (offset < aop->coff)
1577 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1584 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1589 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1591 else if (strcmp (s, "r0") == 0 ||
1592 strcmp (s, "r1") == 0 ||
1593 strcmp (s, "r2") == 0 ||
1594 strcmp (s, "r3") == 0 ||
1595 strcmp (s, "r4") == 0 ||
1596 strcmp (s, "r5") == 0 ||
1597 strcmp (s, "r6") == 0 ||
1598 strcmp (s, "r7") == 0)
1601 SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1602 emitcode ("mov", "@%s,%s",
1603 aop->aopu.aop_ptr->name, buffer);
1607 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1612 if (strcmp (s, "a") == 0)
1613 emitcode ("push", "acc");
1617 emitcode ("push", "acc");
1619 emitcode ("push", s);
1625 /* if not bit variable */
1626 if (!aop->aopu.aop_dir)
1628 /* inefficient: move carry into A and use jz/jnz */
1629 emitcode ("clr", "a");
1630 emitcode ("rlc", "a");
1636 emitcode ("clr", "%s", aop->aopu.aop_dir);
1638 emitcode ("setb", "%s", aop->aopu.aop_dir);
1639 else if (!strcmp (s, "c"))
1640 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1641 else if (strcmp (s, aop->aopu.aop_dir))
1644 /* set C, if a >= 1 */
1645 emitcode ("add", "a,#0xff");
1646 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1653 if (strcmp (aop->aopu.aop_str[offset], s) || bvolatile)
1654 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1660 if (!offset && (strcmp (s, "acc") == 0) && !bvolatile)
1663 if (strcmp (aop->aopu.aop_str[offset], s) && !bvolatile)
1664 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1668 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1669 "aopPut got unsupported aop->type");
1678 /*-----------------------------------------------------------------*/
1679 /* pointToEnd :- points to the last byte of the operand */
1680 /*-----------------------------------------------------------------*/
1682 pointToEnd (asmop * aop)
1688 aop->coff = count = (aop->size - 1);
1694 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1698 emitcode ("inc", "dptr");
1705 /*-----------------------------------------------------------------*/
1706 /* reAdjustPreg - points a register back to where it should */
1707 /*-----------------------------------------------------------------*/
1709 reAdjustPreg (asmop * aop)
1711 if ((aop->coff==0) || (aop->size <= 1))
1719 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1724 emitcode ("lcall", "__decdptr");
1731 /*-----------------------------------------------------------------*/
1732 /* opIsGptr: returns non-zero if the passed operand is */
1733 /* a generic pointer type. */
1734 /*-----------------------------------------------------------------*/
1736 opIsGptr (operand * op)
1738 sym_link *type = operandType (op);
1740 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1747 /*-----------------------------------------------------------------*/
1748 /* getDataSize - get the operand data size */
1749 /*-----------------------------------------------------------------*/
1751 getDataSize (operand * op)
1754 size = AOP_SIZE (op);
1755 if (size == GPTRSIZE)
1757 sym_link *type = operandType (op);
1758 if (IS_GENPTR (type))
1760 /* generic pointer; arithmetic operations
1761 * should ignore the high byte (pointer type).
1769 /*-----------------------------------------------------------------*/
1770 /* outAcc - output Acc */
1771 /*-----------------------------------------------------------------*/
1773 outAcc (operand * result)
1776 size = getDataSize (result);
1779 aopPut (result, "a", 0);
1782 /* unsigned or positive */
1785 aopPut (result, zero, offset++);
1790 /*-----------------------------------------------------------------*/
1791 /* outBitC - output a bit C */
1792 /*-----------------------------------------------------------------*/
1794 outBitC (operand * result)
1796 /* if the result is bit */
1797 if (AOP_TYPE (result) == AOP_CRY)
1799 aopPut (result, "c", 0);
1803 emitcode ("clr", "a");
1804 emitcode ("rlc", "a");
1809 /*-----------------------------------------------------------------*/
1810 /* toBoolean - emit code for orl a,operator(sizeop) */
1811 /*-----------------------------------------------------------------*/
1813 toBoolean (operand * oper)
1815 int size = AOP_SIZE (oper) - 1;
1817 bool AccUsed = FALSE;
1820 while (!AccUsed && size--)
1822 AccUsed |= aopGetUsesAcc(oper, offset++);
1825 size = AOP_SIZE (oper) - 1;
1827 MOVA (aopGet (oper, 0, FALSE, FALSE));
1828 if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1831 emitcode("mov", "b,a");
1834 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1835 emitcode ("orl", "b,a");
1837 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1838 emitcode ("orl", "a,b");
1845 emitcode ("orl", "a,%s", aopGet (oper, offset++, FALSE, FALSE));
1851 /*-----------------------------------------------------------------*/
1852 /* genNot - generate code for ! operation */
1853 /*-----------------------------------------------------------------*/
1859 D (emitcode (";", "genNot"));
1861 /* assign asmOps to operand & result */
1862 aopOp (IC_LEFT (ic), ic, FALSE);
1863 aopOp (IC_RESULT (ic), ic, TRUE);
1865 /* if in bit space then a special case */
1866 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1868 /* if left==result then cpl bit */
1869 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1871 emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1875 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1876 emitcode ("cpl", "c");
1877 outBitC (IC_RESULT (ic));
1882 toBoolean (IC_LEFT (ic));
1884 /* set C, if a == 0 */
1885 tlbl = newiTempLabel (NULL);
1886 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1887 emitcode ("", "%05d$:", tlbl->key + 100);
1888 outBitC (IC_RESULT (ic));
1891 /* release the aops */
1892 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1893 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1897 /*-----------------------------------------------------------------*/
1898 /* genCpl - generate code for complement */
1899 /*-----------------------------------------------------------------*/
1906 sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
1908 D(emitcode (";", "genCpl"));
1910 /* assign asmOps to operand & result */
1911 aopOp (IC_LEFT (ic), ic, FALSE);
1912 aopOp (IC_RESULT (ic), ic, TRUE);
1914 /* special case if in bit space */
1915 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1919 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
1920 (SPEC_USIGN (letype) && IS_CHAR (letype)))
1922 /* promotion rules are responsible for this strange result:
1923 bit -> int -> ~int -> bit
1924 uchar -> int -> ~int -> bit
1926 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
1930 tlbl=newiTempLabel(NULL);
1931 l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
1932 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
1933 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1934 IS_AOP_PREG (IC_LEFT (ic)))
1936 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
1941 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
1943 emitcode ("", "%05d$:", tlbl->key + 100);
1944 outBitC (IC_RESULT(ic));
1948 size = AOP_SIZE (IC_RESULT (ic));
1951 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
1953 emitcode ("cpl", "a");
1954 aopPut (IC_RESULT (ic), "a", offset++);
1959 /* release the aops */
1960 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1961 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1964 /*-----------------------------------------------------------------*/
1965 /* genUminusFloat - unary minus for floating points */
1966 /*-----------------------------------------------------------------*/
1968 genUminusFloat (operand * op, operand * result)
1970 int size, offset = 0;
1973 D (emitcode (";", "genUminusFloat"));
1975 /* for this we just copy and then flip the bit */
1977 size = AOP_SIZE (op) - 1;
1982 aopGet (op, offset, FALSE, FALSE),
1987 l = aopGet (op, offset, FALSE, FALSE);
1990 emitcode ("cpl", "acc.7");
1991 aopPut (result, "a", offset);
1994 /*-----------------------------------------------------------------*/
1995 /* genUminus - unary minus code generation */
1996 /*-----------------------------------------------------------------*/
1998 genUminus (iCode * ic)
2003 D (emitcode (";", "genUminus"));
2006 aopOp (IC_LEFT (ic), ic, FALSE);
2007 aopOp (IC_RESULT (ic), ic, TRUE);
2009 /* if both in bit space then special
2011 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2012 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2015 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2016 emitcode ("cpl", "c");
2017 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2021 optype = operandType (IC_LEFT (ic));
2023 /* if float then do float stuff */
2024 if (IS_FLOAT (optype))
2026 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2030 /* otherwise subtract from zero */
2031 size = AOP_SIZE (IC_LEFT (ic));
2035 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2036 if (!strcmp (l, "a"))
2040 emitcode ("cpl", "a");
2041 emitcode ("addc", "a,#0");
2047 emitcode ("clr", "a");
2048 emitcode ("subb", "a,%s", l);
2050 aopPut (IC_RESULT (ic), "a", offset++);
2053 /* if any remaining bytes in the result */
2054 /* we just need to propagate the sign */
2055 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2057 emitcode ("rlc", "a");
2058 emitcode ("subb", "a,acc");
2060 aopPut (IC_RESULT (ic), "a", offset++);
2064 /* release the aops */
2065 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2066 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2069 /*-----------------------------------------------------------------*/
2070 /* saveRegisters - will look for a call and save the registers */
2071 /*-----------------------------------------------------------------*/
2073 saveRegisters (iCode * lic)
2080 for (ic = lic; ic; ic = ic->next)
2081 if (ic->op == CALL || ic->op == PCALL)
2086 fprintf (stderr, "found parameter push with no function call\n");
2090 /* if the registers have been saved already or don't need to be then
2094 if (IS_SYMOP(IC_LEFT(ic)) &&
2095 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
2096 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
2099 /* save the registers in use at this time but skip the
2100 ones for the result */
2101 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2102 mcs51_rUmaskForOp (IC_RESULT(ic)));
2105 if (options.useXstack)
2107 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2108 int nBits = bitVectnBitsOn (rsavebits);
2109 int count = bitVectnBitsOn (rsave);
2113 count = count - nBits + 1;
2114 /* remove all but the first bits as they are pushed all at once */
2115 rsave = bitVectCplAnd (rsave, rsavebits);
2116 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2121 regs * reg = mcs51_regWithIdx (bitVectFirstBit (rsave));
2122 if (reg->type == REG_BIT)
2124 emitcode ("mov", "a,%s", reg->base);
2128 emitcode ("mov", "a,%s", reg->name);
2130 emitcode ("mov", "r0,%s", spname);
2131 emitcode ("inc", "%s", spname);// allocate before use
2132 emitcode ("movx", "@r0,a");
2133 if (bitVectBitValue (rsave, R0_IDX))
2134 emitcode ("mov", "r0,a");
2136 else if (count != 0)
2138 if (bitVectBitValue (rsave, R0_IDX))
2140 emitcode ("push", "%s", mcs51_regWithIdx (R0_IDX)->dname);
2142 emitcode ("mov", "r0,%s", spname);
2144 emitcode ("add", "a,#%d", count);
2145 emitcode ("mov", "%s,a", spname);
2146 for (i = 0; i < mcs51_nRegs; i++)
2148 if (bitVectBitValue (rsave, i))
2150 regs * reg = mcs51_regWithIdx (i);
2153 emitcode ("pop", "acc");
2154 emitcode ("push", "acc");
2156 else if (reg->type == REG_BIT)
2158 emitcode ("mov", "a,%s", reg->base);
2162 emitcode ("mov", "a,%s", reg->name);
2164 emitcode ("movx", "@r0,a");
2167 emitcode ("inc", "r0");
2171 if (bitVectBitValue (rsave, R0_IDX))
2173 emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
2179 bool bits_pushed = FALSE;
2180 for (i = 0; i < mcs51_nRegs; i++)
2182 if (bitVectBitValue (rsave, i))
2184 bits_pushed = pushReg (i, bits_pushed);
2190 /*-----------------------------------------------------------------*/
2191 /* unsaveRegisters - pop the pushed registers */
2192 /*-----------------------------------------------------------------*/
2194 unsaveRegisters (iCode * ic)
2199 /* restore the registers in use at this time but skip the
2200 ones for the result */
2201 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2202 mcs51_rUmaskForOp (IC_RESULT(ic)));
2204 if (options.useXstack)
2206 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2207 int nBits = bitVectnBitsOn (rsavebits);
2208 int count = bitVectnBitsOn (rsave);
2212 count = count - nBits + 1;
2213 /* remove all but the first bits as they are popped all at once */
2214 rsave = bitVectCplAnd (rsave, rsavebits);
2215 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2220 regs * reg = mcs51_regWithIdx (bitVectFirstBit (rsave));
2221 emitcode ("mov", "r0,%s", spname);
2222 emitcode ("dec", "r0");
2223 emitcode ("movx", "a,@r0");
2224 if (reg->type == REG_BIT)
2226 emitcode ("mov", "%s,a", reg->base);
2230 emitcode ("mov", "%s,a", reg->name);
2232 emitcode ("dec", "%s", spname);
2234 else if (count != 0)
2236 emitcode ("mov", "r0,%s", spname);
2237 for (i = mcs51_nRegs; i >= 0; i--)
2239 if (bitVectBitValue (rsave, i))
2241 regs * reg = mcs51_regWithIdx (i);
2242 emitcode ("dec", "r0");
2243 emitcode ("movx", "a,@r0");
2246 emitcode ("push", "acc");
2248 else if (reg->type == REG_BIT)
2250 emitcode ("mov", "%s,a", reg->base);
2254 emitcode ("mov", "%s,a", reg->name);
2258 emitcode ("mov", "%s,r0", spname);
2259 if (bitVectBitValue (rsave, R0_IDX))
2261 emitcode ("pop", "ar0");
2267 bool bits_popped = FALSE;
2268 for (i = mcs51_nRegs; i >= 0; i--)
2270 if (bitVectBitValue (rsave, i))
2272 bits_popped = popReg (i, bits_popped);
2279 /*-----------------------------------------------------------------*/
2281 /*-----------------------------------------------------------------*/
2283 pushSide (operand * oper, int size)
2288 char *l = aopGet (oper, offset++, FALSE, TRUE);
2289 if (AOP_TYPE (oper) != AOP_REG &&
2290 AOP_TYPE (oper) != AOP_DIR &&
2294 emitcode ("push", "acc");
2298 emitcode ("push", "%s", l);
2303 /*-----------------------------------------------------------------*/
2304 /* assignResultValue - also indicates if acc is in use afterwards */
2305 /*-----------------------------------------------------------------*/
2307 assignResultValue (operand * oper, operand * func)
2310 int size = AOP_SIZE (oper);
2311 bool accuse = FALSE;
2312 bool pushedA = FALSE;
2314 if (func && IS_BIT (OP_SYM_ETYPE (func)))
2320 if ((size > 3) && aopPutUsesAcc (oper, fReturn[offset], offset))
2322 emitcode ("push", "acc");
2327 if ((offset == 3) && pushedA)
2328 emitcode ("pop", "acc");
2329 accuse |= aopPut (oper, fReturn[offset], offset);
2336 /*-----------------------------------------------------------------*/
2337 /* genXpush - pushes onto the external stack */
2338 /*-----------------------------------------------------------------*/
2340 genXpush (iCode * ic)
2342 asmop *aop = newAsmop (0);
2344 int size, offset = 0;
2346 D (emitcode (";", "genXpush"));
2348 aopOp (IC_LEFT (ic), ic, FALSE);
2349 r = getFreePtr (ic, &aop, FALSE);
2351 size = AOP_SIZE (IC_LEFT (ic));
2355 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2356 emitcode ("mov", "%s,%s", r->name, spname);
2357 emitcode ("inc", "%s", spname); // allocate space first
2358 emitcode ("movx", "@%s,a", r->name);
2362 // allocate space first
2363 emitcode ("mov", "%s,%s", r->name, spname);
2365 emitcode ("add", "a,#%d", size);
2366 emitcode ("mov", "%s,a", spname);
2370 MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2371 emitcode ("movx", "@%s,a", r->name);
2372 emitcode ("inc", "%s", r->name);
2376 freeAsmop (NULL, aop, ic, TRUE);
2377 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2380 /*-----------------------------------------------------------------*/
2381 /* genIpush - generate code for pushing this gets a little complex */
2382 /*-----------------------------------------------------------------*/
2384 genIpush (iCode * ic)
2386 int size, offset = 0;
2390 D (emitcode (";", "genIpush"));
2392 /* if this is not a parm push : ie. it is spill push
2393 and spill push is always done on the local stack */
2397 /* and the item is spilt then do nothing */
2398 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2401 aopOp (IC_LEFT (ic), ic, FALSE);
2402 size = AOP_SIZE (IC_LEFT (ic));
2403 /* push it on the stack */
2406 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2412 emitcode ("push", "%s", l);
2417 /* this is a parameter push: in this case we call
2418 the routine to find the call and save those
2419 registers that need to be saved */
2422 /* if use external stack then call the external
2423 stack pushing routine */
2424 if (options.useXstack)
2430 /* then do the push */
2431 aopOp (IC_LEFT (ic), ic, FALSE);
2433 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2434 size = AOP_SIZE (IC_LEFT (ic));
2438 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2439 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2440 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR)
2442 if (strcmp (l, prev) || *l == '@')
2444 emitcode ("push", "acc");
2448 emitcode ("push", "%s", l);
2453 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2456 /*-----------------------------------------------------------------*/
2457 /* genIpop - recover the registers: can happen only for spilling */
2458 /*-----------------------------------------------------------------*/
2460 genIpop (iCode * ic)
2464 D (emitcode (";", "genIpop"));
2466 /* if the temp was not pushed then */
2467 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2470 aopOp (IC_LEFT (ic), ic, FALSE);
2471 size = AOP_SIZE (IC_LEFT (ic));
2472 offset = (size - 1);
2475 emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2479 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2482 /*-----------------------------------------------------------------*/
2483 /* saveRBank - saves an entire register bank on the stack */
2484 /*-----------------------------------------------------------------*/
2486 saveRBank (int bank, iCode * ic, bool pushPsw)
2489 int count = 8 + ((mcs51_nRegs > 8) ? 1 : 0) + (pushPsw ? 1 : 0);
2493 if (options.useXstack)
2497 /* Assume r0 is available for use. */
2498 r = mcs51_regWithIdx (R0_IDX);;
2503 r = getFreePtr (ic, &aop, FALSE);
2505 // allocate space first
2506 emitcode ("mov", "%s,%s", r->name, spname);
2508 emitcode ("add", "a,#%d", count);
2509 emitcode ("mov", "%s,a", spname);
2512 for (i = 0; i < 8; i++)
2514 if (options.useXstack)
2516 emitcode ("mov", "a,(%s+%d)",
2517 regs8051[i].base, 8 * bank + regs8051[i].offset);
2518 emitcode ("movx", "@%s,a", r->name);
2520 emitcode ("inc", "%s", r->name);
2523 emitcode ("push", "(%s+%d)",
2524 regs8051[i].base, 8 * bank + regs8051[i].offset);
2527 if (mcs51_nRegs > 8)
2529 if (options.useXstack)
2531 emitcode ("mov", "a,bits");
2532 emitcode ("movx", "@%s,a", r->name);
2534 emitcode ("inc", "%s", r->name);
2538 emitcode ("push", "bits");
2545 if (options.useXstack)
2547 emitcode ("mov", "a,psw");
2548 emitcode ("movx", "@%s,a", r->name);
2552 emitcode ("push", "psw");
2555 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2560 freeAsmop (NULL, aop, ic, TRUE);
2569 /*-----------------------------------------------------------------*/
2570 /* unsaveRBank - restores the register bank from stack */
2571 /*-----------------------------------------------------------------*/
2573 unsaveRBank (int bank, iCode * ic, bool popPsw)
2579 if (options.useXstack)
2583 /* Assume r0 is available for use. */
2584 r = mcs51_regWithIdx (R0_IDX);;
2589 r = getFreePtr (ic, &aop, FALSE);
2591 emitcode ("mov", "%s,%s", r->name, spname);
2596 if (options.useXstack)
2598 emitcode ("dec", "%s", r->name);
2599 emitcode ("movx", "a,@%s", r->name);
2600 emitcode ("mov", "psw,a");
2604 emitcode ("pop", "psw");
2608 if (mcs51_nRegs > 8)
2610 if (options.useXstack)
2612 emitcode ("dec", "%s", r->name);
2613 emitcode ("movx", "a,@%s", r->name);
2614 emitcode ("mov", "bits,a");
2618 emitcode ("pop", "bits");
2622 for (i = 7; i >= 0; i--)
2624 if (options.useXstack)
2626 emitcode ("dec", "%s", r->name);
2627 emitcode ("movx", "a,@%s", r->name);
2628 emitcode ("mov", "(%s+%d),a",
2629 regs8051[i].base, 8 * bank + regs8051[i].offset);
2633 emitcode ("pop", "(%s+%d)",
2634 regs8051[i].base, 8 * bank + regs8051[i].offset);
2638 if (options.useXstack)
2640 emitcode ("mov", "%s,%s", spname, r->name);
2645 freeAsmop (NULL, aop, ic, TRUE);
2649 /*-----------------------------------------------------------------*/
2650 /* genSend - gen code for SEND */
2651 /*-----------------------------------------------------------------*/
2652 static void genSend(set *sendSet)
2657 /* first we do all bit parameters */
2658 for (sic = setFirstItem (sendSet); sic;
2659 sic = setNextItem (sendSet))
2661 if (sic->argreg > 12)
2663 int bit = sic->argreg-13;
2665 aopOp (IC_LEFT (sic), sic, FALSE);
2667 /* if left is a literal then
2668 we know what the value is */
2669 if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2671 if (((int) operandLitValue (IC_LEFT (sic))))
2672 emitcode ("setb", "b[%d]", bit);
2674 emitcode ("clr", "b[%d]", bit);
2676 else if (AOP_TYPE (IC_LEFT (sic)) == AOP_CRY)
2678 char *l = AOP (IC_LEFT (sic))->aopu.aop_dir;
2679 if (strcmp (l, "c"))
2680 emitcode ("mov", "c,%s", l);
2681 emitcode ("mov", "b[%d],c", bit);
2686 toBoolean (IC_LEFT (sic));
2687 /* set C, if a >= 1 */
2688 emitcode ("add", "a,#0xff");
2689 emitcode ("mov", "b[%d],c", bit);
2694 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2700 saveRegisters (setFirstItem (sendSet));
2701 emitcode ("mov", "bits,b");
2704 /* then we do all other parameters */
2705 for (sic = setFirstItem (sendSet); sic;
2706 sic = setNextItem (sendSet))
2708 if (sic->argreg <= 12)
2710 int size, offset = 0;
2711 aopOp (IC_LEFT (sic), sic, FALSE);
2712 size = AOP_SIZE (IC_LEFT (sic));
2714 if (sic->argreg == 1)
2718 char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2719 if (strcmp (l, fReturn[offset]))
2720 emitcode ("mov", "%s,%s", fReturn[offset], l);
2728 emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2729 aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2733 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2738 /*-----------------------------------------------------------------*/
2739 /* selectRegBank - emit code to select the register bank */
2740 /*-----------------------------------------------------------------*/
2742 selectRegBank (short bank, bool keepFlags)
2744 /* if f.e. result is in carry */
2747 emitcode ("anl", "psw,#0xE7");
2749 emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2753 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2757 /*-----------------------------------------------------------------*/
2758 /* genCall - generates a call statement */
2759 /*-----------------------------------------------------------------*/
2761 genCall (iCode * ic)
2765 // bool restoreBank = FALSE;
2766 bool swapBanks = FALSE;
2767 bool accuse = FALSE;
2768 bool accPushed = FALSE;
2769 bool resultInF0 = FALSE;
2770 bool assignResultGenerated = FALSE;
2772 D (emitcode (";", "genCall"));
2774 dtype = operandType (IC_LEFT (ic));
2775 etype = getSpec(dtype);
2776 /* if send set is not empty then assign */
2779 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2780 genSend(reverseSet(_G.sendSet));
2782 genSend(_G.sendSet);
2787 /* if we are calling a not _naked function that is not using
2788 the same register bank then we need to save the
2789 destination registers on the stack */
2790 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2791 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2792 !IFFUNC_ISISR (dtype))
2797 /* if caller saves & we have not saved then */
2803 emitcode ("mov", "psw,#0x%02x",
2804 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2808 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2810 if (IFFUNC_CALLEESAVES(dtype))
2812 werror (E_BANKED_WITH_CALLEESAVES);
2816 char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2817 OP_SYMBOL (IC_LEFT (ic))->rname :
2818 OP_SYMBOL (IC_LEFT (ic))->name);
2820 emitcode ("mov", "r0,#%s", l);
2821 emitcode ("mov", "r1,#(%s >> 8)", l);
2822 emitcode ("mov", "r2,#(%s >> 16)", l);
2823 emitcode ("lcall", "__sdcc_banked_call");
2828 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2829 OP_SYMBOL (IC_LEFT (ic))->rname :
2830 OP_SYMBOL (IC_LEFT (ic))->name));
2835 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2838 /* if we need assign a result value */
2839 if ((IS_ITEMP (IC_RESULT (ic)) &&
2840 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2841 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2842 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2843 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2844 IS_TRUE_SYMOP (IC_RESULT (ic)))
2848 aopOp (IC_RESULT (ic), ic, FALSE);
2851 accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2852 assignResultGenerated = TRUE;
2854 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2857 /* adjust the stack for parameters if required */
2861 if (ic->parmBytes > 3)
2865 emitcode ("push", "acc");
2868 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2869 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2870 !assignResultGenerated)
2872 emitcode ("mov", "F0,c");
2876 emitcode ("mov", "a,%s", spname);
2877 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2878 emitcode ("mov", "%s,a", spname);
2880 /* unsaveRegisters from xstack needs acc, but */
2881 /* unsaveRegisters from stack needs this popped */
2882 if (accPushed && !options.useXstack)
2884 emitcode ("pop", "acc");
2889 for (i = 0; i < ic->parmBytes; i++)
2890 emitcode ("dec", "%s", spname);
2893 /* if we had saved some registers then unsave them */
2894 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2896 if (accuse && !accPushed && options.useXstack)
2898 /* xstack needs acc, but doesn't touch normal stack */
2899 emitcode ("push", "acc");
2902 unsaveRegisters (ic);
2905 // /* if register bank was saved then pop them */
2907 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2909 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
2912 emitcode ("mov", "c,F0");
2914 aopOp (IC_RESULT (ic), ic, FALSE);
2915 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2916 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2920 emitcode ("pop", "acc");
2923 /*-----------------------------------------------------------------*/
2924 /* genPcall - generates a call by pointer statement */
2925 /*-----------------------------------------------------------------*/
2927 genPcall (iCode * ic)
2931 symbol *rlbl = newiTempLabel (NULL);
2932 // bool restoreBank=FALSE;
2933 bool swapBanks = FALSE;
2934 bool resultInF0 = FALSE;
2936 D (emitcode (";", "genPcall"));
2938 dtype = operandType (IC_LEFT (ic))->next;
2939 etype = getSpec(dtype);
2940 /* if caller saves & we have not saved then */
2944 /* if we are calling a not _naked function that is not using
2945 the same register bank then we need to save the
2946 destination registers on the stack */
2947 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2948 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2949 !IFFUNC_ISISR (dtype))
2951 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2952 // restoreBank=TRUE;
2954 // need caution message to user here
2957 if (IS_LITERAL(etype))
2959 /* if send set is not empty then assign */
2962 genSend(reverseSet(_G.sendSet));
2968 emitcode ("mov", "psw,#0x%02x",
2969 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2972 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2974 if (IFFUNC_CALLEESAVES(dtype))
2976 werror (E_BANKED_WITH_CALLEESAVES);
2980 char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
2982 emitcode ("mov", "r0,#%s", l);
2983 emitcode ("mov", "r1,#(%s >> 8)", l);
2984 emitcode ("mov", "r2,#(%s >> 16)", l);
2985 emitcode ("lcall", "__sdcc_banked_call");
2990 emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
2995 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2997 if (IFFUNC_CALLEESAVES(dtype))
2999 werror (E_BANKED_WITH_CALLEESAVES);
3003 aopOp (IC_LEFT (ic), ic, FALSE);
3007 emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3008 emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3009 emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3013 int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
3014 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3015 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3016 emitcode ("mov", "0x%02x,%s", reg, aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3019 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3021 /* if send set is not empty then assign */
3024 genSend(reverseSet(_G.sendSet));
3030 emitcode ("mov", "psw,#0x%02x",
3031 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3035 emitcode ("lcall", "__sdcc_banked_call");
3040 /* push the return address on to the stack */
3041 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
3042 emitcode ("push", "acc");
3043 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
3044 emitcode ("push", "acc");
3046 /* now push the calling address */
3047 aopOp (IC_LEFT (ic), ic, FALSE);
3049 pushSide (IC_LEFT (ic), FPTRSIZE);
3051 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3053 /* if send set is not empty the assign */
3056 genSend(reverseSet(_G.sendSet));
3062 emitcode ("mov", "psw,#0x%02x",
3063 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3067 emitcode ("ret", "");
3068 emitcode ("", "%05d$:", (rlbl->key + 100));
3073 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
3076 /* if we need assign a result value */
3077 if ((IS_ITEMP (IC_RESULT (ic)) &&
3078 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3079 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3080 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3081 IS_TRUE_SYMOP (IC_RESULT (ic)))
3085 aopOp (IC_RESULT (ic), ic, FALSE);
3088 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3090 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3093 /* adjust the stack for parameters if required */
3097 if (ic->parmBytes > 3)
3099 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3100 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3102 emitcode ("mov", "F0,c");
3106 emitcode ("mov", "a,%s", spname);
3107 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3108 emitcode ("mov", "%s,a", spname);
3111 for (i = 0; i < ic->parmBytes; i++)
3112 emitcode ("dec", "%s", spname);
3116 // /* if register bank was saved then unsave them */
3118 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3120 /* if we had saved some registers then unsave them */
3121 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3122 unsaveRegisters (ic);
3124 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3127 emitcode ("mov", "c,F0");
3129 aopOp (IC_RESULT (ic), ic, FALSE);
3130 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3131 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3135 /*-----------------------------------------------------------------*/
3136 /* resultRemat - result is rematerializable */
3137 /*-----------------------------------------------------------------*/
3139 resultRemat (iCode * ic)
3141 if (SKIP_IC (ic) || ic->op == IFX)
3144 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3146 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3147 if (sym->remat && !POINTER_SET (ic))
3154 #if defined(__BORLANDC__) || defined(_MSC_VER)
3155 #define STRCASECMP stricmp
3157 #define STRCASECMP strcasecmp
3160 /*-----------------------------------------------------------------*/
3161 /* inExcludeList - return 1 if the string is in exclude Reg list */
3162 /*-----------------------------------------------------------------*/
3164 regsCmp(void *p1, void *p2)
3166 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3170 inExcludeList (char *s)
3172 const char *p = setFirstItem(options.excludeRegsSet);
3174 if (p == NULL || STRCASECMP(p, "none") == 0)
3178 return isinSetWith(options.excludeRegsSet, s, regsCmp);
3181 /*-----------------------------------------------------------------*/
3182 /* genFunction - generated code for function entry */
3183 /*-----------------------------------------------------------------*/
3185 genFunction (iCode * ic)
3187 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3189 bool switchedPSW = FALSE;
3190 int calleesaves_saved_register = -1;
3191 int stackAdjust = sym->stack;
3192 int accIsFree = sym->recvSize < 4;
3193 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3194 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3197 /* create the function header */
3198 emitcode (";", "-----------------------------------------");
3199 emitcode (";", " function %s", sym->name);
3200 emitcode (";", "-----------------------------------------");
3202 emitcode ("", "%s:", sym->rname);
3203 ftype = operandType (IC_LEFT (ic));
3204 _G.currentFunc = sym;
3206 if (IFFUNC_ISNAKED(ftype))
3208 emitcode(";", "naked function: no prologue.");
3212 /* here we need to generate the equates for the
3213 register bank if required */
3214 if (FUNC_REGBANK (ftype) != rbank)
3218 rbank = FUNC_REGBANK (ftype);
3219 for (i = 0; i < mcs51_nRegs; i++)
3221 if (regs8051[i].type != REG_BIT)
3223 if (strcmp (regs8051[i].base, "0") == 0)
3224 emitcode ("", "%s = 0x%02x",
3226 8 * rbank + regs8051[i].offset);
3228 emitcode ("", "%s = %s + 0x%02x",
3231 8 * rbank + regs8051[i].offset);
3236 /* if this is an interrupt service routine then
3237 save acc, b, dpl, dph */
3238 if (IFFUNC_ISISR (sym->type))
3240 if (!inExcludeList ("acc"))
3241 emitcode ("push", "acc");
3242 if (!inExcludeList ("b"))
3243 emitcode ("push", "b");
3244 if (!inExcludeList ("dpl"))
3245 emitcode ("push", "dpl");
3246 if (!inExcludeList ("dph"))
3247 emitcode ("push", "dph");
3248 /* if this isr has no bank i.e. is going to
3249 run with bank 0 , then we need to save more
3251 if (!FUNC_REGBANK (sym->type))
3255 /* if this function does not call any other
3256 function then we can be economical and
3257 save only those registers that are used */
3258 if (!IFFUNC_HASFCALL(sym->type))
3260 /* if any registers used */
3263 bool bits_pushed = FALSE;
3264 /* save the registers used */
3265 for (i = 0; i < sym->regsUsed->size; i++)
3267 if (bitVectBitValue (sym->regsUsed, i))
3268 bits_pushed = pushReg (i, bits_pushed);
3274 /* this function has a function call. We cannot
3275 determine register usage so we will have to push the
3277 saveRBank (0, ic, FALSE);
3278 if (options.parms_in_bank1) {
3279 for (i=0; i < 8 ; i++ ) {
3280 emitcode ("push","%s",rb1regs[i]);
3287 /* This ISR uses a non-zero bank.
3289 * We assume that the bank is available for our
3292 * However, if this ISR calls a function which uses some
3293 * other bank, we must save that bank entirely.
3295 unsigned long banksToSave = 0;
3297 if (IFFUNC_HASFCALL(sym->type))
3300 #define MAX_REGISTER_BANKS 4
3305 for (i = ic; i; i = i->next)
3307 if (i->op == ENDFUNCTION)
3309 /* we got to the end OK. */
3317 dtype = operandType (IC_LEFT(i));
3319 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3321 /* Mark this bank for saving. */
3322 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3324 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3328 banksToSave |= (1 << FUNC_REGBANK(dtype));
3331 /* And note that we don't need to do it in
3339 /* This is a mess; we have no idea what
3340 * register bank the called function might
3343 * The only thing I can think of to do is
3344 * throw a warning and hope.
3346 werror(W_FUNCPTR_IN_USING_ISR);
3350 if (banksToSave && options.useXstack)
3352 /* Since we aren't passing it an ic,
3353 * saveRBank will assume r0 is available to abuse.
3355 * So switch to our (trashable) bank now, so
3356 * the caller's R0 isn't trashed.
3358 emitcode ("push", "psw");
3359 emitcode ("mov", "psw,#0x%02x",
3360 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3364 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3366 if (banksToSave & (1 << ix))
3368 saveRBank(ix, NULL, FALSE);
3372 // TODO: this needs a closer look
3373 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3376 /* Set the register bank to the desired value if nothing else */
3377 /* has done so yet. */
3380 emitcode ("push", "psw");
3381 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3386 /* This is a non-ISR function. The caller has already switched register */
3387 /* banks, if necessary, so just handle the callee-saves option. */
3389 /* if callee-save to be used for this function
3390 then save the registers being used in this function */
3391 if (IFFUNC_CALLEESAVES(sym->type))
3395 /* if any registers used */
3398 bool bits_pushed = FALSE;
3399 /* save the registers used */
3400 for (i = 0; i < sym->regsUsed->size; i++)
3402 if (bitVectBitValue (sym->regsUsed, i))
3404 /* remember one saved register for later usage */
3405 if (calleesaves_saved_register < 0)
3406 calleesaves_saved_register = i;
3407 bits_pushed = pushReg (i, bits_pushed);
3418 if (options.useXstack)
3420 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3422 emitcode ("mov", "r0,%s", spname);
3423 emitcode ("inc", "%s", spname);
3424 emitcode ("xch", "a,_bpx");
3425 emitcode ("movx", "@r0,a");
3426 emitcode ("inc", "r0");
3427 emitcode ("mov", "a,r0");
3428 emitcode ("xch", "a,_bpx");
3432 emitcode ("push", "_bp"); /* save the callers stack */
3433 emitcode ("mov", "_bp,sp");
3438 if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3440 /* set up the stack */
3441 emitcode ("push", "_bp"); /* save the callers stack */
3442 emitcode ("mov", "_bp,sp");
3447 /* For some cases it is worthwhile to perform a RECEIVE iCode */
3448 /* before setting up the stack frame completely. */
3449 if (ric && ric->argreg == 1 && IC_RESULT (ric))
3451 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3455 if (rsym && rsym->regType == REG_CND)
3457 if (rsym && (rsym->accuse || rsym->ruonly))
3459 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3460 rsym = rsym->usl.spillLoc;
3463 /* If the RECEIVE operand immediately spills to the first entry on the */
3464 /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3465 /* rather than the usual @r0/r1 machinations. */
3466 if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3470 _G.current_iCode = ric;
3471 D(emitcode ("; genReceive",""));
3472 for (ofs=0; ofs < sym->recvSize; ofs++)
3474 if (!strcmp (fReturn[ofs], "a"))
3475 emitcode ("push", "acc");
3477 emitcode ("push", fReturn[ofs]);
3479 stackAdjust -= sym->recvSize;
3482 assert (stackAdjust>=0);
3485 _G.current_iCode = ic;
3489 /* If the RECEIVE operand is 4 registers, we can do the moves now */
3490 /* to free up the accumulator. */
3491 else if (rsym && rsym->nRegs && sym->recvSize == 4)
3495 _G.current_iCode = ric;
3496 D(emitcode ("; genReceive",""));
3497 for (ofs=0; ofs < sym->recvSize; ofs++)
3499 emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3501 _G.current_iCode = ic;
3507 /* adjust the stack for the function */
3510 int i = stackAdjust;
3512 werror (W_STACK_OVERFLOW, sym->name);
3514 if (i > 3 && accIsFree)
3516 emitcode ("mov", "a,sp");
3517 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3518 emitcode ("mov", "sp,a");
3522 /* The accumulator is not free, so we will need another register */
3523 /* to clobber. No need to worry about a possible conflict with */
3524 /* the above early RECEIVE optimizations since they would have */
3525 /* freed the accumulator if they were generated. */
3527 if (IFFUNC_CALLEESAVES(sym->type))
3529 /* if it's a callee-saves function we need a saved register */
3530 if (calleesaves_saved_register >= 0)
3532 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
3533 emitcode ("mov", "a,sp");
3534 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3535 emitcode ("mov", "sp,a");
3536 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
3539 /* do it the hard way */
3541 emitcode ("inc", "sp");
3545 /* not callee-saves, we can clobber r0 */
3546 emitcode ("mov", "r0,a");
3547 emitcode ("mov", "a,sp");
3548 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3549 emitcode ("mov", "sp,a");
3550 emitcode ("mov", "a,r0");
3555 emitcode ("inc", "sp");
3560 char i = ((char) sym->xstack & 0xff);
3562 if (i > 3 && accIsFree)
3564 emitcode ("mov", "a,_spx");
3565 emitcode ("add", "a,#0x%02x", i);
3566 emitcode ("mov", "_spx,a");
3570 emitcode ("push", "acc");
3571 emitcode ("mov", "a,_spx");
3572 emitcode ("add", "a,#0x%02x", i);
3573 emitcode ("mov", "_spx,a");
3574 emitcode ("pop", "acc");
3579 emitcode ("inc", "_spx");
3583 /* if critical function then turn interrupts off */
3584 if (IFFUNC_ISCRITICAL (ftype))
3586 symbol *tlbl = newiTempLabel (NULL);
3587 emitcode ("setb", "c");
3588 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3589 emitcode ("clr", "c");
3590 emitcode ("", "%05d$:", (tlbl->key + 100));
3591 emitcode ("push", "psw"); /* save old ea via c in psw */
3595 /*-----------------------------------------------------------------*/
3596 /* genEndFunction - generates epilogue for functions */
3597 /*-----------------------------------------------------------------*/
3599 genEndFunction (iCode * ic)
3601 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3602 lineNode *lnp = lineCurr;
3604 bitVect *regsUsedPrologue;
3605 bitVect *regsUnneeded;
3608 _G.currentFunc = NULL;
3609 if (IFFUNC_ISNAKED(sym->type))
3611 emitcode(";", "naked function: no epilogue.");
3612 if (options.debug && currFunc)
3613 debugFile->writeEndFunction (currFunc, ic, 0);
3617 if (IFFUNC_ISCRITICAL (sym->type))
3619 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3621 emitcode ("rlc", "a"); /* save c in a */
3622 emitcode ("pop", "psw"); /* restore ea via c in psw */
3623 emitcode ("mov", "ea,c");
3624 emitcode ("rrc", "a"); /* restore c from a */
3628 emitcode ("pop", "psw"); /* restore ea via c in psw */
3629 emitcode ("mov", "ea,c");
3633 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3635 if (options.useXstack)
3639 emitcode ("mov", "sp,_bp");
3640 emitcode ("pop", "_bp");
3642 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3644 emitcode ("xch", "a,_bpx");
3645 emitcode ("mov", "r0,a");
3646 emitcode ("dec", "r0");
3647 emitcode ("movx", "a,@r0");
3648 emitcode ("xch", "a,_bpx");
3649 emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3652 else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3654 emitcode ("mov", "sp,_bp");
3655 emitcode ("pop", "_bp");
3659 /* restore the register bank */
3660 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3662 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3663 || !options.useXstack)
3665 /* Special case of ISR using non-zero bank with useXstack
3668 emitcode ("pop", "psw");
3672 if (IFFUNC_ISISR (sym->type))
3675 /* now we need to restore the registers */
3676 /* if this isr has no bank i.e. is going to
3677 run with bank 0 , then we need to save more
3679 if (!FUNC_REGBANK (sym->type))
3682 /* if this function does not call any other
3683 function then we can be economical and
3684 save only those registers that are used */
3685 if (!IFFUNC_HASFCALL(sym->type))
3687 /* if any registers used */
3690 bool bits_popped = FALSE;
3691 /* save the registers used */
3692 for (i = sym->regsUsed->size; i >= 0; i--)
3694 if (bitVectBitValue (sym->regsUsed, i))
3695 bits_popped = popReg (i, bits_popped);
3701 if (options.parms_in_bank1) {
3702 for (i = 7 ; i >= 0 ; i-- ) {
3703 emitcode ("pop","%s",rb1regs[i]);
3706 /* this function has a function call cannot
3707 determines register usage so we will have to pop the
3709 unsaveRBank (0, ic, FALSE);
3714 /* This ISR uses a non-zero bank.
3716 * Restore any register banks saved by genFunction
3719 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3722 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3724 if (savedBanks & (1 << ix))
3726 unsaveRBank(ix, NULL, FALSE);
3730 if (options.useXstack)
3732 /* Restore bank AFTER calling unsaveRBank,
3733 * since it can trash r0.
3735 emitcode ("pop", "psw");
3739 if (!inExcludeList ("dph"))
3740 emitcode ("pop", "dph");
3741 if (!inExcludeList ("dpl"))
3742 emitcode ("pop", "dpl");
3743 if (!inExcludeList ("b"))
3744 emitcode ("pop", "b");
3745 if (!inExcludeList ("acc"))
3746 emitcode ("pop", "acc");
3748 /* if debug then send end of function */
3749 if (options.debug && currFunc)
3751 debugFile->writeEndFunction (currFunc, ic, 1);
3754 emitcode ("reti", "");
3758 if (IFFUNC_CALLEESAVES(sym->type))
3762 /* if any registers used */
3765 /* save the registers used */
3766 for (i = sym->regsUsed->size; i >= 0; i--)
3768 if (bitVectBitValue (sym->regsUsed, i) ||
3769 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3770 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
3773 else if (mcs51_ptrRegReq)
3775 emitcode ("pop", "%s", mcs51_regWithIdx (R1_IDX)->dname);
3776 emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
3781 /* if debug then send end of function */
3782 if (options.debug && currFunc)
3784 debugFile->writeEndFunction (currFunc, ic, 1);
3787 if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3789 emitcode ("ljmp", "__sdcc_banked_ret");
3793 emitcode ("ret", "");
3797 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3800 /* If this was an interrupt handler using bank 0 that called another */
3801 /* function, then all registers must be saved; nothing to optimized. */
3802 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3803 && !FUNC_REGBANK(sym->type))
3806 /* There are no push/pops to optimize if not callee-saves or ISR */
3807 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3810 /* If there were stack parameters, we cannot optimize without also */
3811 /* fixing all of the stack offsets; this is too dificult to consider. */
3812 if (FUNC_HASSTACKPARM(sym->type))
3815 /* Compute the registers actually used */
3816 regsUsed = newBitVect (mcs51_nRegs);
3817 regsUsedPrologue = newBitVect (mcs51_nRegs);
3820 if (lnp->ic && lnp->ic->op == FUNCTION)
3821 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3823 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3825 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3826 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3833 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3834 && !bitVectBitValue (regsUsed, CND_IDX))
3836 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3837 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3838 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3839 bitVectUnSetBit (regsUsed, CND_IDX);
3842 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3844 /* If this was an interrupt handler that called another function */
3845 /* function, then assume A, B, DPH, & DPL may be modified by it. */
3846 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3848 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3849 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3850 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3851 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3852 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3855 /* Remove the unneeded push/pops */
3856 regsUnneeded = newBitVect (mcs51_nRegs);
3859 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3861 if (!strncmp(lnp->line, "push", 4))
3863 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3864 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3866 connectLine (lnp->prev, lnp->next);
3867 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3870 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3872 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3873 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3875 connectLine (lnp->prev, lnp->next);
3876 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3883 for (idx = 0; idx < regsUnneeded->size; idx++)
3884 if (bitVectBitValue (regsUnneeded, idx))
3885 emitcode ("", ";\teliminated unneeded push/pop %s", mcs51_regWithIdx (idx)->dname);
3887 freeBitVect (regsUnneeded);
3888 freeBitVect (regsUsed);
3889 freeBitVect (regsUsedPrologue);
3892 /*-----------------------------------------------------------------*/
3893 /* genRet - generate code for return statement */
3894 /*-----------------------------------------------------------------*/
3898 int size, offset = 0, pushed = 0;
3900 D (emitcode (";", "genRet"));
3902 /* if we have no return value then
3903 just generate the "ret" */
3907 /* we have something to return then
3908 move the return value into place */
3909 aopOp (IC_LEFT (ic), ic, FALSE);
3910 size = AOP_SIZE (IC_LEFT (ic));
3912 if (IS_BIT(_G.currentFunc->etype))
3914 movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
3921 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3924 l = aopGet (IC_LEFT (ic), offset++,
3926 emitcode ("push", "%s", l);
3931 l = aopGet (IC_LEFT (ic), offset,
3933 if (strcmp (fReturn[offset], l))
3934 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3941 if (strcmp (fReturn[pushed], "a"))
3942 emitcode ("pop", fReturn[pushed]);
3944 emitcode ("pop", "acc");
3946 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3949 /* generate a jump to the return label
3950 if the next is not the return statement */
3951 if (!(ic->next && ic->next->op == LABEL &&
3952 IC_LABEL (ic->next) == returnLabel))
3954 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3958 /*-----------------------------------------------------------------*/
3959 /* genLabel - generates a label */
3960 /*-----------------------------------------------------------------*/
3962 genLabel (iCode * ic)
3964 /* special case never generate */
3965 if (IC_LABEL (ic) == entryLabel)
3968 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3971 /*-----------------------------------------------------------------*/
3972 /* genGoto - generates a ljmp */
3973 /*-----------------------------------------------------------------*/
3975 genGoto (iCode * ic)
3977 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3980 /*-----------------------------------------------------------------*/
3981 /* findLabelBackwards: walks back through the iCode chain looking */
3982 /* for the given label. Returns number of iCode instructions */
3983 /* between that label and given ic. */
3984 /* Returns zero if label not found. */
3985 /*-----------------------------------------------------------------*/
3987 findLabelBackwards (iCode * ic, int key)
3996 /* If we have any pushes or pops, we cannot predict the distance.
3997 I don't like this at all, this should be dealt with in the
3999 if (ic->op == IPUSH || ic->op == IPOP) {
4003 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4012 /*-----------------------------------------------------------------*/
4013 /* genPlusIncr :- does addition with increment if possible */
4014 /*-----------------------------------------------------------------*/
4016 genPlusIncr (iCode * ic)
4018 unsigned int icount;
4019 unsigned int size = getDataSize (IC_RESULT (ic));
4021 /* will try to generate an increment */
4022 /* if the right side is not a literal
4024 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4027 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4029 D(emitcode ("; genPlusIncr",""));
4031 /* if increment >=16 bits in register or direct space */
4032 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
4033 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4034 !isOperandVolatile (IC_RESULT (ic), FALSE) &&
4042 /* If the next instruction is a goto and the goto target
4043 * is < 10 instructions previous to this, we can generate
4044 * jumps straight to that target.
4046 if (ic->next && ic->next->op == GOTO
4047 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4048 && labelRange <= 10)
4050 emitcode (";", "tail increment optimized");
4051 tlbl = IC_LABEL (ic->next);
4056 tlbl = newiTempLabel (NULL);
4059 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4060 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4061 IS_AOP_PREG (IC_RESULT (ic)))
4062 emitcode ("cjne", "%s,#0x00,%05d$",
4063 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4067 emitcode ("clr", "a");
4068 emitcode ("cjne", "a,%s,%05d$",
4069 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4073 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4076 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4077 IS_AOP_PREG (IC_RESULT (ic)))
4078 emitcode ("cjne", "%s,#0x00,%05d$",
4079 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4082 emitcode ("cjne", "a,%s,%05d$",
4083 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4086 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4090 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4091 IS_AOP_PREG (IC_RESULT (ic)))
4092 emitcode ("cjne", "%s,#0x00,%05d$",
4093 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4097 emitcode ("cjne", "a,%s,%05d$",
4098 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4101 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4106 emitcode ("", "%05d$:", tlbl->key + 100);
4111 /* if result is dptr */
4112 if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
4113 (AOP_SIZE (IC_RESULT (ic)) == 2) &&
4114 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
4115 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
4117 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4123 if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
4126 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0);
4127 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1);
4129 emitcode ("inc", "dptr");
4134 /* if the literal value of the right hand side
4135 is greater than 4 then it is not worth it */
4139 /* if the sizes are greater than 1 then we cannot */
4140 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4141 AOP_SIZE (IC_LEFT (ic)) > 1)
4144 /* we can if the aops of the left & result match or
4145 if they are in registers and the registers are the
4147 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4152 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4153 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4154 aopPut (IC_RESULT (ic), "a", 0);
4160 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4169 /*-----------------------------------------------------------------*/
4170 /* outBitAcc - output a bit in acc */
4171 /*-----------------------------------------------------------------*/
4173 outBitAcc (operand * result)
4175 symbol *tlbl = newiTempLabel (NULL);
4176 /* if the result is a bit */
4177 if (AOP_TYPE (result) == AOP_CRY)
4179 aopPut (result, "a", 0);
4183 emitcode ("jz", "%05d$", tlbl->key + 100);
4184 emitcode ("mov", "a,%s", one);
4185 emitcode ("", "%05d$:", tlbl->key + 100);
4190 /*-----------------------------------------------------------------*/
4191 /* genPlusBits - generates code for addition of two bits */
4192 /*-----------------------------------------------------------------*/
4194 genPlusBits (iCode * ic)
4196 D(emitcode ("; genPlusBits",""));
4198 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4200 symbol *lbl = newiTempLabel (NULL);
4201 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4202 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4203 emitcode ("cpl", "c");
4204 emitcode ("", "%05d$:", (lbl->key + 100));
4205 outBitC (IC_RESULT (ic));
4209 emitcode ("clr", "a");
4210 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4211 emitcode ("rlc", "a");
4212 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4213 emitcode ("addc", "a,#0x00");
4214 outAcc (IC_RESULT (ic));
4219 /* This is the original version of this code.
4221 * This is being kept around for reference,
4222 * because I am not entirely sure I got it right...
4225 adjustArithmeticResult (iCode * ic)
4227 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4228 AOP_SIZE (IC_LEFT (ic)) == 3 &&
4229 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4230 aopPut (IC_RESULT (ic),
4231 aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4234 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4235 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4236 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4237 aopPut (IC_RESULT (ic),
4238 aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4241 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4242 AOP_SIZE (IC_LEFT (ic)) < 3 &&
4243 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4244 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4245 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4248 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4249 aopPut (IC_RESULT (ic), buffer, 2);
4253 /* This is the pure and virtuous version of this code.
4254 * I'm pretty certain it's right, but not enough to toss the old
4258 adjustArithmeticResult (iCode * ic)
4260 if (opIsGptr (IC_RESULT (ic)) &&
4261 opIsGptr (IC_LEFT (ic)) &&
4262 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4264 aopPut (IC_RESULT (ic),
4265 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4269 if (opIsGptr (IC_RESULT (ic)) &&
4270 opIsGptr (IC_RIGHT (ic)) &&
4271 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4273 aopPut (IC_RESULT (ic),
4274 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4278 if (opIsGptr (IC_RESULT (ic)) &&
4279 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4280 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4281 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4282 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4285 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4286 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4291 /*-----------------------------------------------------------------*/
4292 /* genPlus - generates code for addition */
4293 /*-----------------------------------------------------------------*/
4295 genPlus (iCode * ic)
4297 int size, offset = 0;
4300 bool swappedLR = FALSE;
4301 operand *leftOp, *rightOp;
4304 /* special cases :- */
4306 D(emitcode ("; genPlus",""));
4308 aopOp (IC_LEFT (ic), ic, FALSE);
4309 aopOp (IC_RIGHT (ic), ic, FALSE);
4310 aopOp (IC_RESULT (ic), ic, TRUE);
4312 /* if literal, literal on the right or
4313 if left requires ACC or right is already
4315 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4316 (AOP_NEEDSACC (IC_LEFT (ic))) ||
4317 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4319 operand *t = IC_RIGHT (ic);
4320 IC_RIGHT (ic) = IC_LEFT (ic);
4325 /* if both left & right are in bit
4327 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4328 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4334 /* if left in bit space & right literal */
4335 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4336 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4338 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4339 /* if result in bit space */
4340 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4342 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4343 emitcode ("cpl", "c");
4344 outBitC (IC_RESULT (ic));
4348 size = getDataSize (IC_RESULT (ic));
4351 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4352 emitcode ("addc", "a,#00");
4353 aopPut (IC_RESULT (ic), "a", offset++);
4359 /* if I can do an increment instead
4360 of add then GOOD for ME */
4361 if (genPlusIncr (ic) == TRUE)
4364 size = getDataSize (IC_RESULT (ic));
4365 leftOp = IC_LEFT(ic);
4366 rightOp = IC_RIGHT(ic);
4369 /* if this is an add for an array access
4370 at a 256 byte boundary */
4372 && AOP_TYPE (op) == AOP_IMMD
4374 && IS_SPEC (OP_SYM_ETYPE (op))
4375 && SPEC_ABSA (OP_SYM_ETYPE (op))
4376 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4379 D(emitcode ("; genPlus aligned array",""));
4380 aopPut (IC_RESULT (ic),
4381 aopGet (rightOp, 0, FALSE, FALSE),
4384 if( 1 == getDataSize (IC_RIGHT (ic)) )
4386 aopPut (IC_RESULT (ic),
4387 aopGet (leftOp, 1, FALSE, FALSE),
4392 MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4393 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4394 aopPut (IC_RESULT (ic), "a", 1);
4399 /* if the lower bytes of a literal are zero skip the addition */
4400 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4402 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4403 (skip_bytes+1 < size))
4408 D(emitcode ("; genPlus shortcut",""));
4413 if( offset >= skip_bytes )
4415 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4418 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4420 emitcode("xch", "a,b");
4421 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4422 emitcode (add, "a,b");
4425 else if (aopGetUsesAcc (leftOp, offset))
4427 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4428 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4432 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4433 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4435 aopPut (IC_RESULT (ic), "a", offset);
4436 add = "addc"; /* further adds must propagate carry */
4440 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4441 isOperandVolatile (IC_RESULT (ic), FALSE))
4444 aopPut (IC_RESULT (ic),
4445 aopGet (leftOp, offset, FALSE, FALSE),
4452 adjustArithmeticResult (ic);
4455 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4458 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4459 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4463 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4464 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4468 /*-----------------------------------------------------------------*/
4469 /* genMinusDec :- does subtraction with decrement if possible */
4470 /*-----------------------------------------------------------------*/
4472 genMinusDec (iCode * ic)
4474 unsigned int icount;
4475 unsigned int size = getDataSize (IC_RESULT (ic));
4477 /* will try to generate an increment */
4478 /* if the right side is not a literal
4480 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4483 /* if the literal value of the right hand side
4484 is greater than 4 then it is not worth it */
4485 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4488 D(emitcode ("; genMinusDec",""));
4490 /* if decrement >=16 bits in register or direct space */
4491 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
4492 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4500 /* If the next instruction is a goto and the goto target
4501 * is <= 10 instructions previous to this, we can generate
4502 * jumps straight to that target.
4504 if (ic->next && ic->next->op == GOTO
4505 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4506 && labelRange <= 10)
4508 emitcode (";", "tail decrement optimized");
4509 tlbl = IC_LABEL (ic->next);
4514 tlbl = newiTempLabel (NULL);
4518 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4519 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4520 IS_AOP_PREG (IC_RESULT (ic)))
4521 emitcode ("cjne", "%s,#0xff,%05d$"
4522 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4526 emitcode ("mov", "a,#0xff");
4527 emitcode ("cjne", "a,%s,%05d$"
4528 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4531 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4534 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4535 IS_AOP_PREG (IC_RESULT (ic)))
4536 emitcode ("cjne", "%s,#0xff,%05d$"
4537 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4541 emitcode ("cjne", "a,%s,%05d$"
4542 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4545 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4549 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4550 IS_AOP_PREG (IC_RESULT (ic)))
4551 emitcode ("cjne", "%s,#0xff,%05d$"
4552 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4556 emitcode ("cjne", "a,%s,%05d$"
4557 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4560 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4564 emitcode ("", "%05d$:", tlbl->key + 100);
4569 /* if the sizes are greater than 1 then we cannot */
4570 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4571 AOP_SIZE (IC_LEFT (ic)) > 1)
4574 /* we can if the aops of the left & result match or
4575 if they are in registers and the registers are the
4577 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4581 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4583 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4588 l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
4592 emitcode ("dec", "%s", l);
4594 if (AOP_NEEDSACC (IC_RESULT (ic)))
4595 aopPut (IC_RESULT (ic), "a", 0);
4603 /*-----------------------------------------------------------------*/
4604 /* addSign - complete with sign */
4605 /*-----------------------------------------------------------------*/
4607 addSign (operand * result, int offset, int sign)
4609 int size = (getDataSize (result) - offset);
4614 emitcode ("rlc", "a");
4615 emitcode ("subb", "a,acc");
4617 aopPut (result, "a", offset++);
4621 aopPut (result, zero, offset++);
4625 /*-----------------------------------------------------------------*/
4626 /* genMinusBits - generates code for subtraction of two bits */
4627 /*-----------------------------------------------------------------*/
4629 genMinusBits (iCode * ic)
4631 symbol *lbl = newiTempLabel (NULL);
4633 D(emitcode ("; genMinusBits",""));
4635 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4637 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4638 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4639 emitcode ("cpl", "c");
4640 emitcode ("", "%05d$:", (lbl->key + 100));
4641 outBitC (IC_RESULT (ic));
4645 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4646 emitcode ("subb", "a,acc");
4647 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4648 emitcode ("inc", "a");
4649 emitcode ("", "%05d$:", (lbl->key + 100));
4650 aopPut (IC_RESULT (ic), "a", 0);
4651 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4655 /*-----------------------------------------------------------------*/
4656 /* genMinus - generates code for subtraction */
4657 /*-----------------------------------------------------------------*/
4659 genMinus (iCode * ic)
4661 int size, offset = 0;
4663 D(emitcode ("; genMinus",""));
4665 aopOp (IC_LEFT (ic), ic, FALSE);
4666 aopOp (IC_RIGHT (ic), ic, FALSE);
4667 aopOp (IC_RESULT (ic), ic, TRUE);
4669 /* special cases :- */
4670 /* if both left & right are in bit space */
4671 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4672 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4678 /* if I can do an decrement instead
4679 of subtract then GOOD for ME */
4680 if (genMinusDec (ic) == TRUE)
4683 size = getDataSize (IC_RESULT (ic));
4685 /* if literal, add a,#-lit, else normal subb */
4686 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4688 unsigned long lit = 0L;
4689 bool useCarry = FALSE;
4691 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4696 if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4698 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4699 if (!offset && !size && lit== (unsigned long) -1)
4701 emitcode ("dec", "a");
4705 /* first add without previous c */
4706 emitcode ("add", "a,#0x%02x",
4707 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4712 emitcode ("addc", "a,#0x%02x",
4713 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4715 aopPut (IC_RESULT (ic), "a", offset++);
4719 /* no need to add zeroes */
4720 if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4722 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4731 operand *leftOp, *rightOp;
4733 leftOp = IC_LEFT(ic);
4734 rightOp = IC_RIGHT(ic);
4738 if (aopGetUsesAcc(rightOp, offset)) {
4739 if (aopGetUsesAcc(leftOp, offset)) {
4742 MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4744 emitcode ("mov", "b,a");
4747 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4748 emitcode ("subb", "a,b");
4751 /* reverse subtraction with 2's complement */
4753 emitcode( "setb", "c");
4755 emitcode( "cpl", "c");
4756 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4757 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4758 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4759 emitcode("cpl", "a");
4760 if (size) /* skip if last byte */
4761 emitcode( "cpl", "c");
4764 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4767 emitcode ("subb", "a,%s",
4768 aopGet(rightOp, offset, FALSE, TRUE));
4771 aopPut (IC_RESULT (ic), "a", offset++);
4775 adjustArithmeticResult (ic);
4778 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4779 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4780 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4784 /*-----------------------------------------------------------------*/
4785 /* genMultbits :- multiplication of bits */
4786 /*-----------------------------------------------------------------*/
4788 genMultbits (operand * left,
4792 D(emitcode ("; genMultbits",""));
4794 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4795 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4799 /*-----------------------------------------------------------------*/
4800 /* genMultOneByte : 8*8=8/16 bit multiplication */
4801 /*-----------------------------------------------------------------*/
4803 genMultOneByte (operand * left,
4808 int size = AOP_SIZE (result);
4809 bool runtimeSign, compiletimeSign;
4810 bool lUnsigned, rUnsigned, pushedB;
4812 D(emitcode ("; genMultOneByte",""));
4814 if (size < 1 || size > 2)
4816 /* this should never happen */
4817 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4818 AOP_SIZE(result), __FILE__, lineno);
4822 /* (if two literals: the value is computed before) */
4823 /* if one literal, literal on the right */
4824 if (AOP_TYPE (left) == AOP_LIT)
4829 /* emitcode (";", "swapped left and right"); */
4831 /* if no literal, unsigned on the right: shorter code */
4832 if ( AOP_TYPE (right) != AOP_LIT
4833 && SPEC_USIGN (getSpec (operandType (left))))
4840 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4841 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4845 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4846 no need to take care about the signedness! */
4847 || (lUnsigned && rUnsigned))
4849 /* just an unsigned 8 * 8 = 8 multiply
4851 /* emitcode (";","unsigned"); */
4852 /* TODO: check for accumulator clash between left & right aops? */
4854 if (AOP_TYPE (right) == AOP_LIT)
4856 /* moving to accumulator first helps peepholes */
4857 MOVA (aopGet (left, 0, FALSE, FALSE));
4858 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4862 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4863 MOVA (aopGet (left, 0, FALSE, FALSE));
4866 emitcode ("mul", "ab");
4867 aopPut (result, "a", 0);
4869 aopPut (result, "b", 1);
4875 /* we have to do a signed multiply */
4876 /* emitcode (";", "signed"); */
4878 /* now sign adjust for both left & right */
4880 /* let's see what's needed: */
4881 /* apply negative sign during runtime */
4882 runtimeSign = FALSE;
4883 /* negative sign from literals */
4884 compiletimeSign = FALSE;
4888 if (AOP_TYPE(left) == AOP_LIT)
4890 /* signed literal */
4891 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4893 compiletimeSign = TRUE;
4896 /* signed but not literal */
4902 if (AOP_TYPE(right) == AOP_LIT)
4904 /* signed literal */
4905 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4907 compiletimeSign ^= TRUE;
4910 /* signed but not literal */
4914 /* initialize F0, which stores the runtime sign */
4917 if (compiletimeSign)
4918 emitcode ("setb", "F0"); /* set sign flag */
4920 emitcode ("clr", "F0"); /* reset sign flag */
4923 /* save the signs of the operands */
4924 if (AOP_TYPE(right) == AOP_LIT)
4926 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4928 if (!rUnsigned && val < 0)
4929 emitcode ("mov", "b,#0x%02x", -val);
4931 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4933 else /* ! literal */
4935 if (rUnsigned) /* emitcode (";", "signed"); */
4936 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4939 MOVA (aopGet (right, 0, FALSE, FALSE));
4940 lbl = newiTempLabel (NULL);
4941 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4942 emitcode ("cpl", "F0"); /* complement sign flag */
4943 emitcode ("cpl", "a"); /* 2's complement */
4944 emitcode ("inc", "a");
4945 emitcode ("", "%05d$:", (lbl->key + 100));
4946 emitcode ("mov", "b,a");
4950 if (AOP_TYPE(left) == AOP_LIT)
4952 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4954 if (!lUnsigned && val < 0)
4955 emitcode ("mov", "a,#0x%02x", -val);
4957 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4959 else /* ! literal */
4961 MOVA (aopGet (left, 0, FALSE, FALSE));
4965 lbl = newiTempLabel (NULL);
4966 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4967 emitcode ("cpl", "F0"); /* complement sign flag */
4968 emitcode ("cpl", "a"); /* 2's complement */
4969 emitcode ("inc", "a");
4970 emitcode ("", "%05d$:", (lbl->key + 100));
4974 /* now the multiplication */
4975 emitcode ("mul", "ab");
4976 if (runtimeSign || compiletimeSign)
4978 lbl = newiTempLabel (NULL);
4980 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4981 emitcode ("cpl", "a"); /* lsb 2's complement */
4983 emitcode ("inc", "a"); /* inc doesn't set carry flag */
4986 emitcode ("add", "a,#1"); /* this sets carry flag */
4987 emitcode ("xch", "a,b");
4988 emitcode ("cpl", "a"); /* msb 2's complement */
4989 emitcode ("addc", "a,#0");
4990 emitcode ("xch", "a,b");
4992 emitcode ("", "%05d$:", (lbl->key + 100));
4994 aopPut (result, "a", 0);
4996 aopPut (result, "b", 1);
5001 /*-----------------------------------------------------------------*/
5002 /* genMult - generates code for multiplication */
5003 /*-----------------------------------------------------------------*/
5005 genMult (iCode * ic)
5007 operand *left = IC_LEFT (ic);
5008 operand *right = IC_RIGHT (ic);
5009 operand *result = IC_RESULT (ic);
5011 D(emitcode ("; genMult",""));
5013 /* assign the asmops */
5014 aopOp (left, ic, FALSE);
5015 aopOp (right, ic, FALSE);
5016 aopOp (result, ic, TRUE);
5018 /* special cases first */
5020 if (AOP_TYPE (left) == AOP_CRY &&
5021 AOP_TYPE (right) == AOP_CRY)
5023 genMultbits (left, right, result);
5027 /* if both are of size == 1 */
5028 #if 0 // one of them can be a sloc shared with the result
5029 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
5031 if (getSize(operandType(left)) == 1 &&
5032 getSize(operandType(right)) == 1)
5035 genMultOneByte (left, right, result);
5039 /* should have been converted to function call */
5040 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
5041 getSize(OP_SYMBOL(right)->type));
5045 freeAsmop (result, NULL, ic, TRUE);
5046 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5047 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5050 /*-----------------------------------------------------------------*/
5051 /* genDivbits :- division of bits */
5052 /*-----------------------------------------------------------------*/
5054 genDivbits (operand * left,
5061 D(emitcode ("; genDivbits",""));
5065 /* the result must be bit */
5066 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5067 l = aopGet (left, 0, FALSE, FALSE);
5071 emitcode ("div", "ab");
5072 emitcode ("rrc", "a");
5076 aopPut (result, "c", 0);
5079 /*-----------------------------------------------------------------*/
5080 /* genDivOneByte : 8 bit division */
5081 /*-----------------------------------------------------------------*/
5083 genDivOneByte (operand * left,
5087 bool lUnsigned, rUnsigned, pushedB;
5088 bool runtimeSign, compiletimeSign;
5089 bool accuse = FALSE;
5090 bool pushedA = FALSE;
5094 D(emitcode ("; genDivOneByte",""));
5096 /* Why is it necessary that genDivOneByte() can return an int result?
5099 volatile unsigned char uc;
5100 volatile signed char sc1, sc2;
5113 In all cases a one byte result would overflow, the following cast to int
5114 would return the wrong result.
5116 Two possible solution:
5117 a) cast operands to int, if ((unsigned) / (signed)) or
5118 ((signed) / (signed))
5119 b) return an 16 bit signed int; this is what we're doing here!
5122 size = AOP_SIZE (result) - 1;
5124 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5125 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5129 /* signed or unsigned */
5130 if (lUnsigned && rUnsigned)
5132 /* unsigned is easy */
5133 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5134 MOVA (aopGet (left, 0, FALSE, FALSE));
5135 emitcode ("div", "ab");
5136 aopPut (result, "a", 0);
5138 aopPut (result, zero, offset++);
5144 /* signed is a little bit more difficult */
5146 /* now sign adjust for both left & right */
5148 /* let's see what's needed: */
5149 /* apply negative sign during runtime */
5150 runtimeSign = FALSE;
5151 /* negative sign from literals */
5152 compiletimeSign = FALSE;
5156 if (AOP_TYPE(left) == AOP_LIT)
5158 /* signed literal */
5159 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5161 compiletimeSign = TRUE;
5164 /* signed but not literal */
5170 if (AOP_TYPE(right) == AOP_LIT)
5172 /* signed literal */
5173 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5175 compiletimeSign ^= TRUE;
5178 /* signed but not literal */
5182 /* initialize F0, which stores the runtime sign */
5185 if (compiletimeSign)
5186 emitcode ("setb", "F0"); /* set sign flag */
5188 emitcode ("clr", "F0"); /* reset sign flag */
5191 /* save the signs of the operands */
5192 if (AOP_TYPE(right) == AOP_LIT)
5194 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5196 if (!rUnsigned && val < 0)
5197 emitcode ("mov", "b,#0x%02x", -val);
5199 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5201 else /* ! literal */
5204 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5207 MOVA (aopGet (right, 0, FALSE, FALSE));
5208 lbl = newiTempLabel (NULL);
5209 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5210 emitcode ("cpl", "F0"); /* complement sign flag */
5211 emitcode ("cpl", "a"); /* 2's complement */
5212 emitcode ("inc", "a");
5213 emitcode ("", "%05d$:", (lbl->key + 100));
5214 emitcode ("mov", "b,a");
5218 if (AOP_TYPE(left) == AOP_LIT)
5220 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5222 if (!lUnsigned && val < 0)
5223 emitcode ("mov", "a,#0x%02x", -val);
5225 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5227 else /* ! literal */
5229 MOVA (aopGet (left, 0, FALSE, FALSE));
5233 lbl = newiTempLabel (NULL);
5234 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5235 emitcode ("cpl", "F0"); /* complement sign flag */
5236 emitcode ("cpl", "a"); /* 2's complement */
5237 emitcode ("inc", "a");
5238 emitcode ("", "%05d$:", (lbl->key + 100));
5242 /* now the division */
5243 emitcode ("div", "ab");
5245 if (runtimeSign || compiletimeSign)
5247 lbl = newiTempLabel (NULL);
5249 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5250 emitcode ("cpl", "a"); /* lsb 2's complement */
5251 emitcode ("inc", "a");
5252 emitcode ("", "%05d$:", (lbl->key + 100));
5254 accuse = aopPut (result, "a", 0);
5257 /* msb is 0x00 or 0xff depending on the sign */
5262 emitcode ("push", "acc");
5265 emitcode ("mov", "c,F0");
5266 emitcode ("subb", "a,acc");
5268 aopPut (result, "a", offset++);
5270 else /* compiletimeSign */
5272 if (aopPutUsesAcc (result, "#0xFF", offset))
5274 emitcode ("push", "acc");
5278 aopPut (result, "#0xff", offset++);
5284 aopPut (result, "a", 0);
5286 aopPut (result, zero, offset++);
5290 emitcode ("pop", "acc");
5294 /*-----------------------------------------------------------------*/
5295 /* genDiv - generates code for division */
5296 /*-----------------------------------------------------------------*/
5300 operand *left = IC_LEFT (ic);
5301 operand *right = IC_RIGHT (ic);
5302 operand *result = IC_RESULT (ic);
5304 D(emitcode ("; genDiv",""));
5306 /* assign the amsops */
5307 aopOp (left, ic, FALSE);
5308 aopOp (right, ic, FALSE);
5309 aopOp (result, ic, TRUE);
5311 /* special cases first */
5313 if (AOP_TYPE (left) == AOP_CRY &&
5314 AOP_TYPE (right) == AOP_CRY)
5316 genDivbits (left, right, result);
5320 /* if both are of size == 1 */
5321 if (AOP_SIZE (left) == 1 &&
5322 AOP_SIZE (right) == 1)
5324 genDivOneByte (left, right, result);
5328 /* should have been converted to function call */
5331 freeAsmop (result, NULL, ic, TRUE);
5332 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5333 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5336 /*-----------------------------------------------------------------*/
5337 /* genModbits :- modulus of bits */
5338 /*-----------------------------------------------------------------*/
5340 genModbits (operand * left,
5347 D(emitcode ("; genModbits",""));
5351 /* the result must be bit */
5352 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5353 l = aopGet (left, 0, FALSE, FALSE);
5357 emitcode ("div", "ab");
5358 emitcode ("mov", "a,b");
5359 emitcode ("rrc", "a");
5363 aopPut (result, "c", 0);
5366 /*-----------------------------------------------------------------*/
5367 /* genModOneByte : 8 bit modulus */
5368 /*-----------------------------------------------------------------*/
5370 genModOneByte (operand * left,
5374 bool lUnsigned, rUnsigned, pushedB;
5375 bool runtimeSign, compiletimeSign;
5379 D(emitcode ("; genModOneByte",""));
5381 size = AOP_SIZE (result) - 1;
5383 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5384 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5386 /* if right is a literal, check it for 2^n */
5387 if (AOP_TYPE(right) == AOP_LIT)
5389 unsigned char val = abs((int) operandLitValue(right));
5390 symbol *lbl2 = NULL;
5394 case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5403 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5404 "modulus of unsigned char by 2^n literal shouldn't be processed here");
5405 /* because iCode should have been changed to genAnd */
5406 /* see file "SDCCopt.c", function "convertToFcall()" */
5408 MOVA (aopGet (left, 0, FALSE, FALSE));
5409 emitcode ("mov", "c,acc.7");
5410 emitcode ("anl", "a,#0x%02x", val - 1);
5411 lbl = newiTempLabel (NULL);
5412 emitcode ("jz", "%05d$", (lbl->key + 100));
5413 emitcode ("jnc", "%05d$", (lbl->key + 100));
5414 emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5420 aopPut (result, "a", 0);
5422 aopPut (result, "#0xff", offs2++);
5423 lbl2 = newiTempLabel (NULL);
5424 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5426 emitcode ("", "%05d$:", (lbl->key + 100));
5427 aopPut (result, "a", 0);
5429 aopPut (result, zero, offset++);
5432 emitcode ("", "%05d$:", (lbl2->key + 100));
5443 /* signed or unsigned */
5444 if (lUnsigned && rUnsigned)
5446 /* unsigned is easy */
5447 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5448 MOVA (aopGet (left, 0, FALSE, FALSE));
5449 emitcode ("div", "ab");
5450 aopPut (result, "b", 0);
5452 aopPut (result, zero, offset++);
5458 /* signed is a little bit more difficult */
5460 /* now sign adjust for both left & right */
5462 /* modulus: sign of the right operand has no influence on the result! */
5463 if (AOP_TYPE(right) == AOP_LIT)
5465 signed char val = (char) operandLitValue(right);
5467 if (!rUnsigned && val < 0)
5468 emitcode ("mov", "b,#0x%02x", -val);
5470 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5472 else /* not literal */
5475 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5478 MOVA (aopGet (right, 0, FALSE, FALSE));
5479 lbl = newiTempLabel (NULL);
5480 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5481 emitcode ("cpl", "a"); /* 2's complement */
5482 emitcode ("inc", "a");
5483 emitcode ("", "%05d$:", (lbl->key + 100));
5484 emitcode ("mov", "b,a");
5488 /* let's see what's needed: */
5489 /* apply negative sign during runtime */
5490 runtimeSign = FALSE;
5491 /* negative sign from literals */
5492 compiletimeSign = FALSE;
5494 /* sign adjust left side */
5495 if (AOP_TYPE(left) == AOP_LIT)
5497 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5499 if (!lUnsigned && val < 0)
5501 compiletimeSign = TRUE; /* set sign flag */
5502 emitcode ("mov", "a,#0x%02x", -val);
5505 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5507 else /* ! literal */
5509 MOVA (aopGet (left, 0, FALSE, FALSE));
5514 emitcode ("clr", "F0"); /* clear sign flag */
5516 lbl = newiTempLabel (NULL);
5517 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5518 emitcode ("setb", "F0"); /* set sign flag */
5519 emitcode ("cpl", "a"); /* 2's complement */
5520 emitcode ("inc", "a");
5521 emitcode ("", "%05d$:", (lbl->key + 100));
5525 /* now the modulus */
5526 emitcode ("div", "ab");
5528 if (runtimeSign || compiletimeSign)
5530 emitcode ("mov", "a,b");
5531 lbl = newiTempLabel (NULL);
5533 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5534 emitcode ("cpl", "a"); /* 2's complement */
5535 emitcode ("inc", "a");
5536 emitcode ("", "%05d$:", (lbl->key + 100));
5538 aopPut (result, "a", 0);
5541 /* msb is 0x00 or 0xff depending on the sign */
5544 emitcode ("mov", "c,F0");
5545 emitcode ("subb", "a,acc");
5547 aopPut (result, "a", offset++);
5549 else /* compiletimeSign */
5551 aopPut (result, "#0xff", offset++);
5556 aopPut (result, "b", 0);
5558 aopPut (result, zero, offset++);
5564 /*-----------------------------------------------------------------*/
5565 /* genMod - generates code for division */
5566 /*-----------------------------------------------------------------*/
5570 operand *left = IC_LEFT (ic);
5571 operand *right = IC_RIGHT (ic);
5572 operand *result = IC_RESULT (ic);
5574 D(emitcode ("; genMod",""));
5576 /* assign the asmops */
5577 aopOp (left, ic, FALSE);
5578 aopOp (right, ic, FALSE);
5579 aopOp (result, ic, TRUE);
5581 /* special cases first */
5583 if (AOP_TYPE (left) == AOP_CRY &&
5584 AOP_TYPE (right) == AOP_CRY)
5586 genModbits (left, right, result);
5590 /* if both are of size == 1 */
5591 if (AOP_SIZE (left) == 1 &&
5592 AOP_SIZE (right) == 1)
5594 genModOneByte (left, right, result);
5598 /* should have been converted to function call */
5602 freeAsmop (result, NULL, ic, TRUE);
5603 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5604 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5607 /*-----------------------------------------------------------------*/
5608 /* genIfxJump :- will create a jump depending on the ifx */
5609 /*-----------------------------------------------------------------*/
5611 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5614 symbol *tlbl = newiTempLabel (NULL);
5617 D(emitcode ("; genIfxJump",""));
5619 /* if true label then we jump if condition
5623 jlbl = IC_TRUE (ic);
5624 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5625 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5629 /* false label is present */
5630 jlbl = IC_FALSE (ic);
5631 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5632 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5634 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5635 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5637 emitcode (inst, "%05d$", tlbl->key + 100);
5638 freeForBranchAsmop (result);
5639 freeForBranchAsmop (right);
5640 freeForBranchAsmop (left);
5641 emitcode ("ljmp", "%05d$", jlbl->key + 100);
5642 emitcode ("", "%05d$:", tlbl->key + 100);
5644 /* mark the icode as generated */
5648 /*-----------------------------------------------------------------*/
5649 /* genCmp :- greater or less than comparison */
5650 /*-----------------------------------------------------------------*/
5652 genCmp (operand * left, operand * right,
5653 operand * result, iCode * ifx, int sign, iCode *ic)
5655 int size, offset = 0;
5656 unsigned long lit = 0L;
5659 D(emitcode ("; genCmp",""));
5661 /* if left & right are bit variables */
5662 if (AOP_TYPE (left) == AOP_CRY &&
5663 AOP_TYPE (right) == AOP_CRY)
5665 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5666 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5670 /* subtract right from left if at the
5671 end the carry flag is set then we know that
5672 left is greater than right */
5673 size = max (AOP_SIZE (left), AOP_SIZE (right));
5675 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5676 if ((size == 1) && !sign &&
5677 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5679 symbol *lbl = newiTempLabel (NULL);
5680 emitcode ("cjne", "%s,%s,%05d$",
5681 aopGet (left, offset, FALSE, FALSE),
5682 aopGet (right, offset, FALSE, FALSE),
5684 emitcode ("", "%05d$:", lbl->key + 100);
5688 if (AOP_TYPE (right) == AOP_LIT)
5690 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5691 /* optimize if(x < 0) or if(x >= 0) */
5700 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5701 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5703 genIfxJump (ifx, "acc.7", left, right, result);
5704 freeAsmop (right, NULL, ic, TRUE);
5705 freeAsmop (left, NULL, ic, TRUE);
5710 emitcode ("rlc", "a");
5718 bool pushedB = FALSE;
5719 rightInB = aopGetUsesAcc(right, offset);
5723 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5725 MOVA (aopGet (left, offset, FALSE, FALSE));
5726 if (sign && size == 0)
5728 emitcode ("xrl", "a,#0x80");
5729 if (AOP_TYPE (right) == AOP_LIT)
5731 unsigned long lit = (unsigned long)
5732 floatFromVal (AOP (right)->aopu.aop_lit);
5733 emitcode ("subb", "a,#0x%02x",
5734 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5742 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5744 emitcode ("xrl", "b,#0x80");
5745 emitcode ("subb", "a,b");
5751 emitcode ("subb", "a,b");
5753 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5763 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5764 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5765 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5771 /* if the result is used in the next
5772 ifx conditional branch then generate
5773 code a little differently */
5775 genIfxJump (ifx, "c", NULL, NULL, result);
5778 /* leave the result in acc */
5782 /*-----------------------------------------------------------------*/
5783 /* genCmpGt :- greater than comparison */
5784 /*-----------------------------------------------------------------*/
5786 genCmpGt (iCode * ic, iCode * ifx)
5788 operand *left, *right, *result;
5789 sym_link *letype, *retype;
5792 D(emitcode ("; genCmpGt",""));
5794 left = IC_LEFT (ic);
5795 right = IC_RIGHT (ic);
5796 result = IC_RESULT (ic);
5798 letype = getSpec (operandType (left));
5799 retype = getSpec (operandType (right));
5800 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5801 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5802 /* assign the amsops */
5803 aopOp (result, ic, TRUE);
5804 aopOp (left, ic, FALSE);
5805 aopOp (right, ic, FALSE);
5807 genCmp (right, left, result, ifx, sign, ic);
5809 freeAsmop (result, NULL, ic, TRUE);
5812 /*-----------------------------------------------------------------*/
5813 /* genCmpLt - less than comparisons */
5814 /*-----------------------------------------------------------------*/
5816 genCmpLt (iCode * ic, iCode * ifx)
5818 operand *left, *right, *result;
5819 sym_link *letype, *retype;
5822 D(emitcode ("; genCmpLt",""));
5824 left = IC_LEFT (ic);
5825 right = IC_RIGHT (ic);
5826 result = IC_RESULT (ic);
5828 letype = getSpec (operandType (left));
5829 retype = getSpec (operandType (right));
5830 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5831 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5832 /* assign the amsops */
5833 aopOp (result, ic, TRUE);
5834 aopOp (left, ic, FALSE);
5835 aopOp (right, ic, FALSE);
5837 genCmp (left, right, result, ifx, sign, ic);
5839 freeAsmop (result, NULL, ic, TRUE);
5842 /*-----------------------------------------------------------------*/
5843 /* gencjneshort - compare and jump if not equal */
5844 /*-----------------------------------------------------------------*/
5846 gencjneshort (operand * left, operand * right, symbol * lbl)
5848 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5850 unsigned long lit = 0L;
5852 /* if the left side is a literal or
5853 if the right is in a pointer register and left
5855 if ((AOP_TYPE (left) == AOP_LIT) ||
5856 (AOP_TYPE (left) == AOP_IMMD) ||
5857 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5864 if (AOP_TYPE (right) == AOP_LIT)
5865 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5867 /* if the right side is a literal then anything goes */
5868 if (AOP_TYPE (right) == AOP_LIT &&
5869 AOP_TYPE (left) != AOP_DIR &&
5870 AOP_TYPE (left) != AOP_IMMD)
5874 emitcode ("cjne", "%s,%s,%05d$",
5875 aopGet (left, offset, FALSE, FALSE),
5876 aopGet (right, offset, FALSE, FALSE),
5882 /* if the right side is in a register or in direct space or
5883 if the left is a pointer register & right is not */
5884 else if (AOP_TYPE (right) == AOP_REG ||
5885 AOP_TYPE (right) == AOP_DIR ||
5886 AOP_TYPE (right) == AOP_LIT ||
5887 AOP_TYPE (right) == AOP_IMMD ||
5888 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5889 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5893 MOVA (aopGet (left, offset, FALSE, FALSE));
5894 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5895 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5896 emitcode ("jnz", "%05d$", lbl->key + 100);
5898 emitcode ("cjne", "a,%s,%05d$",
5899 aopGet (right, offset, FALSE, TRUE),
5906 /* right is a pointer reg need both a & b */
5910 //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
5911 wassertl(!BINUSE, "B was in use");
5912 l = aopGet (left, offset, FALSE, FALSE);
5913 if (strcmp (l, "b"))
5914 emitcode ("mov", "b,%s", l);
5915 MOVA (aopGet (right, offset, FALSE, FALSE));
5916 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5922 /*-----------------------------------------------------------------*/
5923 /* gencjne - compare and jump if not equal */
5924 /*-----------------------------------------------------------------*/
5926 gencjne (operand * left, operand * right, symbol * lbl)
5928 symbol *tlbl = newiTempLabel (NULL);
5930 gencjneshort (left, right, lbl);
5932 emitcode ("mov", "a,%s", one);
5933 emitcode ("sjmp", "%05d$", tlbl->key + 100);
5934 emitcode ("", "%05d$:", lbl->key + 100);
5935 emitcode ("clr", "a");
5936 emitcode ("", "%05d$:", tlbl->key + 100);
5939 /*-----------------------------------------------------------------*/
5940 /* genCmpEq - generates code for equal to */
5941 /*-----------------------------------------------------------------*/
5943 genCmpEq (iCode * ic, iCode * ifx)
5945 bool swappedLR = FALSE;
5946 operand *left, *right, *result;
5948 D(emitcode ("; genCmpEq",""));
5950 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5951 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5952 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5954 /* if literal, literal on the right or
5955 if the right is in a pointer register and left
5957 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5958 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5960 operand *t = IC_RIGHT (ic);
5961 IC_RIGHT (ic) = IC_LEFT (ic);
5966 if (ifx && !AOP_SIZE (result))
5969 /* if they are both bit variables */
5970 if (AOP_TYPE (left) == AOP_CRY &&
5971 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5973 if (AOP_TYPE (right) == AOP_LIT)
5975 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5978 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5979 emitcode ("cpl", "c");
5983 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5987 emitcode ("clr", "c");
5989 /* AOP_TYPE(right) == AOP_CRY */
5993 symbol *lbl = newiTempLabel (NULL);
5994 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5995 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5996 emitcode ("cpl", "c");
5997 emitcode ("", "%05d$:", (lbl->key + 100));
5999 /* if true label then we jump if condition
6001 tlbl = newiTempLabel (NULL);
6004 emitcode ("jnc", "%05d$", tlbl->key + 100);
6005 freeForBranchAsmop (result);
6006 freeForBranchAsmop (right);
6007 freeForBranchAsmop (left);
6008 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6012 emitcode ("jc", "%05d$", tlbl->key + 100);
6013 freeForBranchAsmop (result);
6014 freeForBranchAsmop (right);
6015 freeForBranchAsmop (left);
6016 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6018 emitcode ("", "%05d$:", tlbl->key + 100);
6022 tlbl = newiTempLabel (NULL);
6023 gencjneshort (left, right, tlbl);
6026 freeForBranchAsmop (result);
6027 freeForBranchAsmop (right);
6028 freeForBranchAsmop (left);
6029 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6030 emitcode ("", "%05d$:", tlbl->key + 100);
6034 symbol *lbl = newiTempLabel (NULL);
6035 emitcode ("sjmp", "%05d$", lbl->key + 100);
6036 emitcode ("", "%05d$:", tlbl->key + 100);
6037 freeForBranchAsmop (result);
6038 freeForBranchAsmop (right);
6039 freeForBranchAsmop (left);
6040 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6041 emitcode ("", "%05d$:", lbl->key + 100);
6044 /* mark the icode as generated */
6049 /* if they are both bit variables */
6050 if (AOP_TYPE (left) == AOP_CRY &&
6051 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6053 if (AOP_TYPE (right) == AOP_LIT)
6055 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6058 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6059 emitcode ("cpl", "c");
6063 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6067 emitcode ("clr", "c");
6069 /* AOP_TYPE(right) == AOP_CRY */
6073 symbol *lbl = newiTempLabel (NULL);
6074 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6075 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6076 emitcode ("cpl", "c");
6077 emitcode ("", "%05d$:", (lbl->key + 100));
6080 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6087 genIfxJump (ifx, "c", left, right, result);
6090 /* if the result is used in an arithmetic operation
6091 then put the result in place */
6096 gencjne (left, right, newiTempLabel (NULL));
6097 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6099 aopPut (result, "a", 0);
6104 genIfxJump (ifx, "a", left, right, result);
6107 /* if the result is used in an arithmetic operation
6108 then put the result in place */
6109 if (AOP_TYPE (result) != AOP_CRY)
6111 /* leave the result in acc */
6115 freeAsmop (result, NULL, ic, TRUE);
6118 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6119 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6123 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6124 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6128 /*-----------------------------------------------------------------*/
6129 /* ifxForOp - returns the icode containing the ifx for operand */
6130 /*-----------------------------------------------------------------*/
6132 ifxForOp (operand * op, iCode * ic)
6134 /* if true symbol then needs to be assigned */
6135 if (IS_TRUE_SYMOP (op))
6138 /* if this has register type condition and
6139 the next instruction is ifx with the same operand
6140 and live to of the operand is upto the ifx only then */
6142 ic->next->op == IFX &&
6143 IC_COND (ic->next)->key == op->key &&
6144 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6150 /*-----------------------------------------------------------------*/
6151 /* hasInc - operand is incremented before any other use */
6152 /*-----------------------------------------------------------------*/
6154 hasInc (operand *op, iCode *ic,int osize)
6156 sym_link *type = operandType(op);
6157 sym_link *retype = getSpec (type);
6158 iCode *lic = ic->next;
6161 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6162 if (!IS_SYMOP(op)) return NULL;
6164 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6165 if (IS_AGGREGATE(type->next)) return NULL;
6166 if (osize != (isize = getSize(type->next))) return NULL;
6169 /* if operand of the form op = op + <sizeof *op> */
6170 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6171 isOperandEqual(IC_RESULT(lic),op) &&
6172 isOperandLiteral(IC_RIGHT(lic)) &&
6173 operandLitValue(IC_RIGHT(lic)) == isize) {
6176 /* if the operand used or deffed */
6177 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6180 /* if GOTO or IFX */
6181 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6187 /*-----------------------------------------------------------------*/
6188 /* genAndOp - for && operation */
6189 /*-----------------------------------------------------------------*/
6191 genAndOp (iCode * ic)
6193 operand *left, *right, *result;
6196 D(emitcode ("; genAndOp",""));
6198 /* note here that && operations that are in an
6199 if statement are taken away by backPatchLabels
6200 only those used in arthmetic operations remain */
6201 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6202 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6203 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6205 /* if both are bit variables */
6206 if (AOP_TYPE (left) == AOP_CRY &&
6207 AOP_TYPE (right) == AOP_CRY)
6209 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6210 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6215 tlbl = newiTempLabel (NULL);
6217 emitcode ("jz", "%05d$", tlbl->key + 100);
6219 emitcode ("", "%05d$:", tlbl->key + 100);
6223 freeAsmop (result, NULL, ic, TRUE);
6224 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6225 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6229 /*-----------------------------------------------------------------*/
6230 /* genOrOp - for || operation */
6231 /*-----------------------------------------------------------------*/
6233 genOrOp (iCode * ic)
6235 operand *left, *right, *result;
6238 D(emitcode ("; genOrOp",""));
6240 /* note here that || operations that are in an
6241 if statement are taken away by backPatchLabels
6242 only those used in arthmetic operations remain */
6243 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6244 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6245 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6247 /* if both are bit variables */
6248 if (AOP_TYPE (left) == AOP_CRY &&
6249 AOP_TYPE (right) == AOP_CRY)
6251 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6252 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6257 tlbl = newiTempLabel (NULL);
6259 emitcode ("jnz", "%05d$", tlbl->key + 100);
6261 emitcode ("", "%05d$:", tlbl->key + 100);
6265 freeAsmop (result, NULL, ic, TRUE);
6266 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6267 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6270 /*-----------------------------------------------------------------*/
6271 /* isLiteralBit - test if lit == 2^n */
6272 /*-----------------------------------------------------------------*/
6274 isLiteralBit (unsigned long lit)
6276 unsigned long pw[32] =
6277 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6278 0x100L, 0x200L, 0x400L, 0x800L,
6279 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6280 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6281 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6282 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6283 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6286 for (idx = 0; idx < 32; idx++)
6292 /*-----------------------------------------------------------------*/
6293 /* continueIfTrue - */
6294 /*-----------------------------------------------------------------*/
6296 continueIfTrue (iCode * ic)
6299 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6303 /*-----------------------------------------------------------------*/
6305 /*-----------------------------------------------------------------*/
6307 jumpIfTrue (iCode * ic)
6310 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6314 /*-----------------------------------------------------------------*/
6315 /* jmpTrueOrFalse - */
6316 /*-----------------------------------------------------------------*/
6318 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6320 // ugly but optimized by peephole
6323 symbol *nlbl = newiTempLabel (NULL);
6324 emitcode ("sjmp", "%05d$", nlbl->key + 100);
6325 emitcode ("", "%05d$:", tlbl->key + 100);
6326 freeForBranchAsmop (result);
6327 freeForBranchAsmop (right);
6328 freeForBranchAsmop (left);
6329 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6330 emitcode ("", "%05d$:", nlbl->key + 100);
6334 freeForBranchAsmop (result);
6335 freeForBranchAsmop (right);
6336 freeForBranchAsmop (left);
6337 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6338 emitcode ("", "%05d$:", tlbl->key + 100);
6343 /*-----------------------------------------------------------------*/
6344 /* genAnd - code for and */
6345 /*-----------------------------------------------------------------*/
6347 genAnd (iCode * ic, iCode * ifx)
6349 operand *left, *right, *result;
6350 int size, offset = 0;
6351 unsigned long lit = 0L;
6355 D(emitcode ("; genAnd",""));
6357 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6358 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6359 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6362 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6364 AOP_TYPE (left), AOP_TYPE (right));
6365 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6367 AOP_SIZE (left), AOP_SIZE (right));
6370 /* if left is a literal & right is not then exchange them */
6371 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6372 AOP_NEEDSACC (left))
6374 operand *tmp = right;
6379 /* if result = right then exchange left and right */
6380 if (sameRegs (AOP (result), AOP (right)))
6382 operand *tmp = right;
6387 /* if right is bit then exchange them */
6388 if (AOP_TYPE (right) == AOP_CRY &&
6389 AOP_TYPE (left) != AOP_CRY)
6391 operand *tmp = right;
6395 if (AOP_TYPE (right) == AOP_LIT)
6396 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6398 size = AOP_SIZE (result);
6401 // result = bit & yy;
6402 if (AOP_TYPE (left) == AOP_CRY)
6404 // c = bit & literal;
6405 if (AOP_TYPE (right) == AOP_LIT)
6409 if (size && sameRegs (AOP (result), AOP (left)))
6412 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6417 if (size && (AOP_TYPE (result) == AOP_CRY))
6419 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6422 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6427 emitcode ("clr", "c");
6432 if (AOP_TYPE (right) == AOP_CRY)
6435 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6436 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6441 MOVA (aopGet (right, 0, FALSE, FALSE));
6443 emitcode ("rrc", "a");
6444 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6452 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6453 genIfxJump (ifx, "c", left, right, result);
6457 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6458 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6459 if ((AOP_TYPE (right) == AOP_LIT) &&
6460 (AOP_TYPE (result) == AOP_CRY) &&
6461 (AOP_TYPE (left) != AOP_CRY))
6463 int posbit = isLiteralBit (lit);
6468 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6472 switch (posbit & 0x07)
6474 case 0: emitcode ("rrc", "a");
6476 case 7: emitcode ("rlc", "a");
6478 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6487 SNPRINTF (buffer, sizeof(buffer),
6488 "acc.%d", posbit & 0x07);
6489 genIfxJump (ifx, buffer, left, right, result);
6492 {// what is this case? just found it in ds390/gen.c
6493 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6500 symbol *tlbl = newiTempLabel (NULL);
6501 int sizel = AOP_SIZE (left);
6503 emitcode ("setb", "c");
6506 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6508 MOVA (aopGet (left, offset, FALSE, FALSE));
6510 if ((posbit = isLiteralBit (bytelit)) != 0)
6511 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6514 if (bytelit != 0x0FFL)
6515 emitcode ("anl", "a,%s",
6516 aopGet (right, offset, FALSE, TRUE));
6517 emitcode ("jnz", "%05d$", tlbl->key + 100);
6522 // bit = left & literal
6525 emitcode ("clr", "c");
6526 emitcode ("", "%05d$:", tlbl->key + 100);
6528 // if(left & literal)
6532 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6534 emitcode ("", "%05d$:", tlbl->key + 100);
6542 /* if left is same as result */
6543 if (sameRegs (AOP (result), AOP (left)))
6545 for (; size--; offset++)
6547 if (AOP_TYPE (right) == AOP_LIT)
6549 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6550 if (bytelit == 0x0FF)
6552 /* dummy read of volatile operand */
6553 if (isOperandVolatile (left, FALSE))
6554 MOVA (aopGet (left, offset, FALSE, FALSE));
6558 else if (bytelit == 0)
6560 aopPut (result, zero, offset);
6562 else if (IS_AOP_PREG (result))
6564 MOVA (aopGet (left, offset, FALSE, TRUE));
6565 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6566 aopPut (result, "a", offset);
6569 emitcode ("anl", "%s,%s",
6570 aopGet (left, offset, FALSE, TRUE),
6571 aopGet (right, offset, FALSE, FALSE));
6575 if (AOP_TYPE (left) == AOP_ACC)
6578 emitcode("mov", "a,b");
6579 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6581 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6583 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6584 MOVA (aopGet (right, offset, FALSE, FALSE));
6585 emitcode ("anl", "a,b");
6586 aopPut (result, "a", offset);
6588 else if (aopGetUsesAcc (left, offset))
6590 MOVA (aopGet (left, offset, FALSE, FALSE));
6591 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6592 aopPut (result, "a", offset);
6596 MOVA (aopGet (right, offset, FALSE, FALSE));
6597 if (IS_AOP_PREG (result))
6599 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6600 aopPut (result, "a", offset);
6603 emitcode ("anl", "%s,a",
6604 aopGet (left, offset, FALSE, TRUE));
6611 // left & result in different registers
6612 if (AOP_TYPE (result) == AOP_CRY)
6615 // if(size), result in bit
6616 // if(!size && ifx), conditional oper: if(left & right)
6617 symbol *tlbl = newiTempLabel (NULL);
6618 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6620 emitcode ("setb", "c");
6623 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6624 && AOP_TYPE(left)==AOP_ACC)
6627 emitcode("mov", "a,b");
6628 emitcode ("anl", "a,%s",
6629 aopGet (right, offset, FALSE, FALSE));
6631 if (AOP_TYPE(left)==AOP_ACC)
6635 bool pushedB = pushB ();
6636 emitcode("mov", "b,a");
6637 MOVA (aopGet (right, offset, FALSE, FALSE));
6638 emitcode("anl", "a,b");
6643 MOVA (aopGet (right, offset, FALSE, FALSE));
6644 emitcode("anl", "a,b");
6647 MOVA (aopGet (right, offset, FALSE, FALSE));
6648 emitcode ("anl", "a,%s",
6649 aopGet (left, offset, FALSE, FALSE));
6652 emitcode ("jnz", "%05d$", tlbl->key + 100);
6658 emitcode ("", "%05d$:", tlbl->key + 100);
6662 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6664 emitcode ("", "%05d$:", tlbl->key + 100);
6668 for (; (size--); offset++)
6671 // result = left & right
6672 if (AOP_TYPE (right) == AOP_LIT)
6674 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6675 if (bytelit == 0x0FF)
6678 aopGet (left, offset, FALSE, FALSE),
6682 else if (bytelit == 0)
6684 /* dummy read of volatile operand */
6685 if (isOperandVolatile (left, FALSE))
6686 MOVA (aopGet (left, offset, FALSE, FALSE));
6687 aopPut (result, zero, offset);
6690 else if (AOP_TYPE (left) == AOP_ACC)
6694 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6695 aopPut (result, "a", offset);
6700 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6701 aopPut (result, "b", offset);
6706 // faster than result <- left, anl result,right
6707 // and better if result is SFR
6708 if (AOP_TYPE (left) == AOP_ACC)
6711 emitcode("mov", "a,b");
6712 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6714 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6716 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6717 MOVA (aopGet (right, offset, FALSE, FALSE));
6718 emitcode ("anl", "a,b");
6720 else if (aopGetUsesAcc (left, offset))
6722 MOVA (aopGet (left, offset, FALSE, FALSE));
6723 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6727 MOVA (aopGet (right, offset, FALSE, FALSE));
6728 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6730 aopPut (result, "a", offset);
6736 freeAsmop (result, NULL, ic, TRUE);
6737 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6738 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6741 /*-----------------------------------------------------------------*/
6742 /* genOr - code for or */
6743 /*-----------------------------------------------------------------*/
6745 genOr (iCode * ic, iCode * ifx)
6747 operand *left, *right, *result;
6748 int size, offset = 0;
6749 unsigned long lit = 0L;
6752 D(emitcode ("; genOr",""));
6754 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6755 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6756 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6759 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6761 AOP_TYPE (left), AOP_TYPE (right));
6762 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6764 AOP_SIZE (left), AOP_SIZE (right));
6767 /* if left is a literal & right is not then exchange them */
6768 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6769 AOP_NEEDSACC (left))
6771 operand *tmp = right;
6776 /* if result = right then exchange them */
6777 if (sameRegs (AOP (result), AOP (right)))
6779 operand *tmp = right;
6784 /* if right is bit then exchange them */
6785 if (AOP_TYPE (right) == AOP_CRY &&
6786 AOP_TYPE (left) != AOP_CRY)
6788 operand *tmp = right;
6792 if (AOP_TYPE (right) == AOP_LIT)
6793 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6795 size = AOP_SIZE (result);
6799 if (AOP_TYPE (left) == AOP_CRY)
6801 if (AOP_TYPE (right) == AOP_LIT)
6803 // c = bit | literal;
6806 // lit != 0 => result = 1
6807 if (AOP_TYPE (result) == AOP_CRY)
6810 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6812 continueIfTrue (ifx);
6815 emitcode ("setb", "c");
6819 // lit == 0 => result = left
6820 if (size && sameRegs (AOP (result), AOP (left)))
6822 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6827 if (AOP_TYPE (right) == AOP_CRY)
6830 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6831 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6836 symbol *tlbl = newiTempLabel (NULL);
6837 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6838 emitcode ("setb", "c");
6839 emitcode ("jb", "%s,%05d$",
6840 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6842 emitcode ("jnz", "%05d$", tlbl->key + 100);
6843 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6845 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6851 emitcode ("", "%05d$:", tlbl->key + 100);
6860 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6861 genIfxJump (ifx, "c", left, right, result);
6865 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6866 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6867 if ((AOP_TYPE (right) == AOP_LIT) &&
6868 (AOP_TYPE (result) == AOP_CRY) &&
6869 (AOP_TYPE (left) != AOP_CRY))
6875 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6877 continueIfTrue (ifx);
6882 // lit = 0, result = boolean(left)
6884 emitcode ("setb", "c");
6888 symbol *tlbl = newiTempLabel (NULL);
6889 emitcode ("jnz", "%05d$", tlbl->key + 100);
6891 emitcode ("", "%05d$:", tlbl->key + 100);
6895 genIfxJump (ifx, "a", left, right, result);
6903 /* if left is same as result */
6904 if (sameRegs (AOP (result), AOP (left)))
6906 for (; size--; offset++)
6908 if (AOP_TYPE (right) == AOP_LIT)
6910 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6913 /* dummy read of volatile operand */
6914 if (isOperandVolatile (left, FALSE))
6915 MOVA (aopGet (left, offset, FALSE, FALSE));
6919 else if (bytelit == 0x0FF)
6921 aopPut (result, "#0xFF", offset);
6923 else if (IS_AOP_PREG (left))
6925 MOVA (aopGet (left, offset, FALSE, TRUE));
6926 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6927 aopPut (result, "a", offset);
6931 emitcode ("orl", "%s,%s",
6932 aopGet (left, offset, FALSE, TRUE),
6933 aopGet (right, offset, FALSE, FALSE));
6938 if (AOP_TYPE (left) == AOP_ACC)
6941 emitcode("mov", "a,b");
6942 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6944 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6946 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6947 MOVA (aopGet (right, offset, FALSE, FALSE));
6948 emitcode ("orl", "a,b");
6949 aopPut (result, "a", offset);
6951 else if (aopGetUsesAcc (left, offset))
6953 MOVA (aopGet (left, offset, FALSE, FALSE));
6954 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6955 aopPut (result, "a", offset);
6959 MOVA (aopGet (right, offset, FALSE, FALSE));
6960 if (IS_AOP_PREG (left))
6962 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6963 aopPut (result, "a", offset);
6967 emitcode ("orl", "%s,a",
6968 aopGet (left, offset, FALSE, TRUE));
6976 // left & result in different registers
6977 if (AOP_TYPE (result) == AOP_CRY)
6980 // if(size), result in bit
6981 // if(!size && ifx), conditional oper: if(left | right)
6982 symbol *tlbl = newiTempLabel (NULL);
6983 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6985 emitcode ("setb", "c");
6988 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6990 emitcode("mov", "a,b");
6991 emitcode ("orl", "a,%s",
6992 aopGet (right, offset, FALSE, FALSE));
6994 MOVA (aopGet (right, offset, FALSE, FALSE));
6995 emitcode ("orl", "a,%s",
6996 aopGet (left, offset, FALSE, FALSE));
6998 emitcode ("jnz", "%05d$", tlbl->key + 100);
7004 emitcode ("", "%05d$:", tlbl->key + 100);
7008 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7010 emitcode ("", "%05d$:", tlbl->key + 100);
7014 for (; (size--); offset++)
7017 // result = left | right
7018 if (AOP_TYPE (right) == AOP_LIT)
7020 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7024 aopGet (left, offset, FALSE, FALSE),
7028 else if (bytelit == 0x0FF)
7030 /* dummy read of volatile operand */
7031 if (isOperandVolatile (left, FALSE))
7032 MOVA (aopGet (left, offset, FALSE, FALSE));
7033 aopPut (result, "#0xFF", offset);
7037 // faster than result <- left, anl result,right
7038 // and better if result is SFR
7039 if (AOP_TYPE (left) == AOP_ACC)
7042 emitcode("mov", "a,b");
7043 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7045 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7047 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7048 MOVA (aopGet (right, offset, FALSE, FALSE));
7049 emitcode ("orl", "a,b");
7051 else if (aopGetUsesAcc (left, offset))
7053 MOVA (aopGet (left, offset, FALSE, FALSE));
7054 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7058 MOVA (aopGet (right, offset, FALSE, FALSE));
7059 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7061 aopPut (result, "a", offset);
7067 freeAsmop (result, NULL, ic, TRUE);
7068 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7069 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7072 /*-----------------------------------------------------------------*/
7073 /* genXor - code for xclusive or */
7074 /*-----------------------------------------------------------------*/
7076 genXor (iCode * ic, iCode * ifx)
7078 operand *left, *right, *result;
7079 int size, offset = 0;
7080 unsigned long lit = 0L;
7083 D(emitcode ("; genXor",""));
7085 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7086 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7087 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7090 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7092 AOP_TYPE (left), AOP_TYPE (right));
7093 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7095 AOP_SIZE (left), AOP_SIZE (right));
7098 /* if left is a literal & right is not ||
7099 if left needs acc & right does not */
7100 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7101 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7103 operand *tmp = right;
7108 /* if result = right then exchange them */
7109 if (sameRegs (AOP (result), AOP (right)))
7111 operand *tmp = right;
7116 /* if right is bit then exchange them */
7117 if (AOP_TYPE (right) == AOP_CRY &&
7118 AOP_TYPE (left) != AOP_CRY)
7120 operand *tmp = right;
7124 if (AOP_TYPE (right) == AOP_LIT)
7125 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7127 size = AOP_SIZE (result);
7131 if (AOP_TYPE (left) == AOP_CRY)
7133 if (AOP_TYPE (right) == AOP_LIT)
7135 // c = bit & literal;
7138 // lit>>1 != 0 => result = 1
7139 if (AOP_TYPE (result) == AOP_CRY)
7142 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7144 continueIfTrue (ifx);
7147 emitcode ("setb", "c");
7154 // lit == 0, result = left
7155 if (size && sameRegs (AOP (result), AOP (left)))
7157 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7161 // lit == 1, result = not(left)
7162 if (size && sameRegs (AOP (result), AOP (left)))
7164 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7169 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7170 emitcode ("cpl", "c");
7179 symbol *tlbl = newiTempLabel (NULL);
7180 if (AOP_TYPE (right) == AOP_CRY)
7183 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7187 int sizer = AOP_SIZE (right);
7189 // if val>>1 != 0, result = 1
7190 emitcode ("setb", "c");
7193 MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
7195 // test the msb of the lsb
7196 emitcode ("anl", "a,#0xfe");
7197 emitcode ("jnz", "%05d$", tlbl->key + 100);
7201 emitcode ("rrc", "a");
7203 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7204 emitcode ("cpl", "c");
7205 emitcode ("", "%05d$:", (tlbl->key + 100));
7212 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7213 genIfxJump (ifx, "c", left, right, result);
7217 /* if left is same as result */
7218 if (sameRegs (AOP (result), AOP (left)))
7220 for (; size--; offset++)
7222 if (AOP_TYPE (right) == AOP_LIT)
7224 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7227 /* dummy read of volatile operand */
7228 if (isOperandVolatile (left, FALSE))
7229 MOVA (aopGet (left, offset, FALSE, FALSE));
7233 else if (IS_AOP_PREG (left))
7235 MOVA (aopGet (left, offset, FALSE, TRUE));
7236 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7237 aopPut (result, "a", offset);
7241 emitcode ("xrl", "%s,%s",
7242 aopGet (left, offset, FALSE, TRUE),
7243 aopGet (right, offset, FALSE, FALSE));
7248 if (AOP_TYPE (left) == AOP_ACC)
7251 emitcode("mov", "a,b");
7252 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7254 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7256 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7257 MOVA (aopGet (right, offset, FALSE, FALSE));
7258 emitcode ("xrl", "a,b");
7259 aopPut (result, "a", offset);
7261 else if (aopGetUsesAcc (left, offset))
7263 MOVA (aopGet (left, offset, FALSE, FALSE));
7264 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7265 aopPut (result, "a", offset);
7269 MOVA (aopGet (right, offset, FALSE, FALSE));
7270 if (IS_AOP_PREG (left))
7272 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7273 aopPut (result, "a", offset);
7276 emitcode ("xrl", "%s,a",
7277 aopGet (left, offset, FALSE, TRUE));
7284 // left & result in different registers
7285 if (AOP_TYPE (result) == AOP_CRY)
7288 // if(size), result in bit
7289 // if(!size && ifx), conditional oper: if(left ^ right)
7290 symbol *tlbl = newiTempLabel (NULL);
7291 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7293 emitcode ("setb", "c");
7296 if ((AOP_TYPE (right) == AOP_LIT) &&
7297 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7299 MOVA (aopGet (left, offset, FALSE, FALSE));
7303 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7305 emitcode("mov", "a,b");
7306 emitcode ("xrl", "a,%s",
7307 aopGet (right, offset, FALSE, FALSE));
7309 MOVA (aopGet (right, offset, FALSE, FALSE));
7310 emitcode ("xrl", "a,%s",
7311 aopGet (left, offset, FALSE, FALSE));
7314 emitcode ("jnz", "%05d$", tlbl->key + 100);
7320 emitcode ("", "%05d$:", tlbl->key + 100);
7324 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7328 for (; (size--); offset++)
7331 // result = left & right
7332 if (AOP_TYPE (right) == AOP_LIT)
7334 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7338 aopGet (left, offset, FALSE, FALSE),
7343 // faster than result <- left, anl result,right
7344 // and better if result is SFR
7345 if (AOP_TYPE (left) == AOP_ACC)
7348 emitcode("mov", "a,b");
7349 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7351 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7353 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7354 MOVA (aopGet (right, offset, FALSE, FALSE));
7355 emitcode ("xrl", "a,b");
7357 else if (aopGetUsesAcc (left, offset))
7359 MOVA (aopGet (left, offset, FALSE, FALSE));
7360 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7364 MOVA (aopGet (right, offset, FALSE, FALSE));
7365 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7367 aopPut (result, "a", offset);
7373 freeAsmop (result, NULL, ic, TRUE);
7374 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7375 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7378 /*-----------------------------------------------------------------*/
7379 /* genInline - write the inline code out */
7380 /*-----------------------------------------------------------------*/
7382 genInline (iCode * ic)
7384 char *buffer, *bp, *bp1;
7386 D (emitcode (";", "genInline"));
7388 _G.inLine += (!options.asmpeep);
7390 buffer = bp = bp1 = Safe_strdup(IC_INLINE(ic));
7392 /* emit each line as a code */
7403 /* Add \n for labels, not dirs such as c:\mydir */
7404 if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
7418 /* emitcode("",buffer); */
7419 _G.inLine -= (!options.asmpeep);
7422 /*-----------------------------------------------------------------*/
7423 /* genRRC - rotate right with carry */
7424 /*-----------------------------------------------------------------*/
7428 operand *left, *result;
7429 int size, offset = 0;
7432 D(emitcode ("; genRRC",""));
7434 /* rotate right with carry */
7435 left = IC_LEFT (ic);
7436 result = IC_RESULT (ic);
7437 aopOp (left, ic, FALSE);
7438 aopOp (result, ic, FALSE);
7440 /* move it to the result */
7441 size = AOP_SIZE (result);
7443 if (size == 1) { /* special case for 1 byte */
7444 l = aopGet (left, offset, FALSE, FALSE);
7446 emitcode ("rr", "a");
7449 /* no need to clear carry, bit7 will be written later */
7452 l = aopGet (left, offset, FALSE, FALSE);
7454 emitcode ("rrc", "a");
7455 if (AOP_SIZE (result) > 1)
7456 aopPut (result, "a", offset--);
7458 /* now we need to put the carry into the
7459 highest order byte of the result */
7460 if (AOP_SIZE (result) > 1)
7462 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7465 emitcode ("mov", "acc.7,c");
7467 aopPut (result, "a", AOP_SIZE (result) - 1);
7468 freeAsmop (result, NULL, ic, TRUE);
7469 freeAsmop (left, NULL, ic, TRUE);
7472 /*-----------------------------------------------------------------*/
7473 /* genRLC - generate code for rotate left with carry */
7474 /*-----------------------------------------------------------------*/
7478 operand *left, *result;
7479 int size, offset = 0;
7482 D(emitcode ("; genRLC",""));
7484 /* rotate right with carry */
7485 left = IC_LEFT (ic);
7486 result = IC_RESULT (ic);
7487 aopOp (left, ic, FALSE);
7488 aopOp (result, ic, FALSE);
7490 /* move it to the result */
7491 size = AOP_SIZE (result);
7495 l = aopGet (left, offset, FALSE, FALSE);
7497 if (size == 0) { /* special case for 1 byte */
7501 emitcode("rlc","a"); /* bit0 will be written later */
7502 if (AOP_SIZE (result) > 1)
7503 aopPut (result, "a", offset++);
7506 l = aopGet (left, offset, FALSE, FALSE);
7508 emitcode ("rlc", "a");
7509 if (AOP_SIZE (result) > 1)
7510 aopPut (result, "a", offset++);
7513 /* now we need to put the carry into the
7514 highest order byte of the result */
7515 if (AOP_SIZE (result) > 1)
7517 l = aopGet (result, 0, FALSE, FALSE);
7520 emitcode ("mov", "acc.0,c");
7522 aopPut (result, "a", 0);
7523 freeAsmop (result, NULL, ic, TRUE);
7524 freeAsmop (left, NULL, ic, TRUE);
7527 /*-----------------------------------------------------------------*/
7528 /* genGetHbit - generates code get highest order bit */
7529 /*-----------------------------------------------------------------*/
7531 genGetHbit (iCode * ic)
7533 operand *left, *result;
7535 D(emitcode ("; genGetHbit",""));
7537 left = IC_LEFT (ic);
7538 result = IC_RESULT (ic);
7539 aopOp (left, ic, FALSE);
7540 aopOp (result, ic, FALSE);
7542 /* get the highest order byte into a */
7543 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7544 if (AOP_TYPE (result) == AOP_CRY)
7546 emitcode ("rlc", "a");
7551 emitcode ("rl", "a");
7552 emitcode ("anl", "a,#0x01");
7556 freeAsmop (result, NULL, ic, TRUE);
7557 freeAsmop (left, NULL, ic, TRUE);
7560 /*-----------------------------------------------------------------*/
7561 /* genGetAbit - generates code get a single bit */
7562 /*-----------------------------------------------------------------*/
7564 genGetAbit (iCode * ic)
7566 operand *left, *right, *result;
7569 D(emitcode ("; genGetAbit",""));
7571 left = IC_LEFT (ic);
7572 right = IC_RIGHT (ic);
7573 result = IC_RESULT (ic);
7574 aopOp (left, ic, FALSE);
7575 aopOp (right, ic, FALSE);
7576 aopOp (result, ic, FALSE);
7578 shCount = (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7580 /* get the needed byte into a */
7581 MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7583 if (AOP_TYPE (result) == AOP_CRY)
7586 emitcode ("rlc", "a");
7587 else if ((shCount) == 0)
7588 emitcode ("rrc", "a");
7590 emitcode ("mov", "c,acc[%d]", shCount);
7598 emitcode ("rr", "a");
7601 emitcode ("rr", "a");
7604 emitcode ("anl", "a,#0x01");
7608 emitcode ("mov", "c,acc[%d]", shCount);
7609 emitcode ("clr", "a");
7610 emitcode ("rlc", "a");
7613 emitcode ("swap", "a");
7614 emitcode ("anl", "a,#0x01");
7617 emitcode ("rl", "a");
7620 emitcode ("rl", "a");
7621 emitcode ("anl", "a,#0x01");
7627 freeAsmop (result, NULL, ic, TRUE);
7628 freeAsmop (right, NULL, ic, TRUE);
7629 freeAsmop (left, NULL, ic, TRUE);
7632 /*-----------------------------------------------------------------*/
7633 /* genGetByte - generates code get a single byte */
7634 /*-----------------------------------------------------------------*/
7636 genGetByte (iCode * ic)
7638 operand *left, *right, *result;
7641 D(emitcode ("; genGetByte",""));
7643 left = IC_LEFT (ic);
7644 right = IC_RIGHT (ic);
7645 result = IC_RESULT (ic);
7646 aopOp (left, ic, FALSE);
7647 aopOp (right, ic, FALSE);
7648 aopOp (result, ic, FALSE);
7650 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7652 aopGet (left, offset, FALSE, FALSE),
7655 freeAsmop (result, NULL, ic, TRUE);
7656 freeAsmop (right, NULL, ic, TRUE);
7657 freeAsmop (left, NULL, ic, TRUE);
7660 /*-----------------------------------------------------------------*/
7661 /* genGetWord - generates code get two bytes */
7662 /*-----------------------------------------------------------------*/
7664 genGetWord (iCode * ic)
7666 operand *left, *right, *result;
7669 D(emitcode ("; genGetWord",""));
7671 left = IC_LEFT (ic);
7672 right = IC_RIGHT (ic);
7673 result = IC_RESULT (ic);
7674 aopOp (left, ic, FALSE);
7675 aopOp (right, ic, FALSE);
7676 aopOp (result, ic, FALSE);
7678 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7680 aopGet (left, offset, FALSE, FALSE),
7683 aopGet (left, offset+1, FALSE, FALSE),
7686 freeAsmop (result, NULL, ic, TRUE);
7687 freeAsmop (right, NULL, ic, TRUE);
7688 freeAsmop (left, NULL, ic, TRUE);
7691 /*-----------------------------------------------------------------*/
7692 /* genSwap - generates code to swap nibbles or bytes */
7693 /*-----------------------------------------------------------------*/
7695 genSwap (iCode * ic)
7697 operand *left, *result;
7699 D(emitcode ("; genSwap",""));
7701 left = IC_LEFT (ic);
7702 result = IC_RESULT (ic);
7703 aopOp (left, ic, FALSE);
7704 aopOp (result, ic, FALSE);
7706 switch (AOP_SIZE (left))
7708 case 1: /* swap nibbles in byte */
7709 MOVA (aopGet (left, 0, FALSE, FALSE));
7710 emitcode ("swap", "a");
7711 aopPut (result, "a", 0);
7713 case 2: /* swap bytes in word */
7714 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7716 MOVA (aopGet (left, 0, FALSE, FALSE));
7717 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7718 aopPut (result, "a", 1);
7720 else if (operandsEqu (left, result))
7723 bool pushedB = FALSE, leftInB = FALSE;
7725 MOVA (aopGet (left, 0, FALSE, FALSE));
7726 if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
7729 emitcode ("mov", "b,a");
7733 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7734 aopPut (result, reg, 1);
7741 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7742 aopPut (result, aopGet (left, 0, FALSE, FALSE), 1);
7746 wassertl(FALSE, "unsupported SWAP operand size");
7749 freeAsmop (result, NULL, ic, TRUE);
7750 freeAsmop (left, NULL, ic, TRUE);
7753 /*-----------------------------------------------------------------*/
7754 /* AccRol - rotate left accumulator by known count */
7755 /*-----------------------------------------------------------------*/
7757 AccRol (int shCount)
7759 shCount &= 0x0007; // shCount : 0..7
7766 emitcode ("rl", "a");
7769 emitcode ("rl", "a");
7770 emitcode ("rl", "a");
7773 emitcode ("swap", "a");
7774 emitcode ("rr", "a");
7777 emitcode ("swap", "a");
7780 emitcode ("swap", "a");
7781 emitcode ("rl", "a");
7784 emitcode ("rr", "a");
7785 emitcode ("rr", "a");
7788 emitcode ("rr", "a");
7793 /*-----------------------------------------------------------------*/
7794 /* AccLsh - left shift accumulator by known count */
7795 /*-----------------------------------------------------------------*/
7797 AccLsh (int shCount)
7802 emitcode ("add", "a,acc");
7803 else if (shCount == 2)
7805 emitcode ("add", "a,acc");
7806 emitcode ("add", "a,acc");
7810 /* rotate left accumulator */
7812 /* and kill the lower order bits */
7813 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
7818 /*-----------------------------------------------------------------*/
7819 /* AccRsh - right shift accumulator by known count */
7820 /*-----------------------------------------------------------------*/
7822 AccRsh (int shCount)
7829 emitcode ("rrc", "a");
7833 /* rotate right accumulator */
7834 AccRol (8 - shCount);
7835 /* and kill the higher order bits */
7836 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7841 /*-----------------------------------------------------------------*/
7842 /* AccSRsh - signed right shift accumulator by known count */
7843 /*-----------------------------------------------------------------*/
7845 AccSRsh (int shCount)
7852 emitcode ("mov", "c,acc.7");
7853 emitcode ("rrc", "a");
7855 else if (shCount == 2)
7857 emitcode ("mov", "c,acc.7");
7858 emitcode ("rrc", "a");
7859 emitcode ("mov", "c,acc.7");
7860 emitcode ("rrc", "a");
7864 tlbl = newiTempLabel (NULL);
7865 /* rotate right accumulator */
7866 AccRol (8 - shCount);
7867 /* and kill the higher order bits */
7868 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7869 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7870 emitcode ("orl", "a,#0x%02x",
7871 (unsigned char) ~SRMask[shCount]);
7872 emitcode ("", "%05d$:", tlbl->key + 100);
7877 /*-----------------------------------------------------------------*/
7878 /* shiftR1Left2Result - shift right one byte from left to result */
7879 /*-----------------------------------------------------------------*/
7881 shiftR1Left2Result (operand * left, int offl,
7882 operand * result, int offr,
7883 int shCount, int sign)
7885 MOVA (aopGet (left, offl, FALSE, FALSE));
7886 /* shift right accumulator */
7891 aopPut (result, "a", offr);
7894 /*-----------------------------------------------------------------*/
7895 /* shiftL1Left2Result - shift left one byte from left to result */
7896 /*-----------------------------------------------------------------*/
7898 shiftL1Left2Result (operand * left, int offl,
7899 operand * result, int offr, int shCount)
7902 l = aopGet (left, offl, FALSE, FALSE);
7904 /* shift left accumulator */
7906 aopPut (result, "a", offr);
7909 /*-----------------------------------------------------------------*/
7910 /* movLeft2Result - move byte from left to result */
7911 /*-----------------------------------------------------------------*/
7913 movLeft2Result (operand * left, int offl,
7914 operand * result, int offr, int sign)
7917 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7919 l = aopGet (left, offl, FALSE, FALSE);
7921 if (*l == '@' && (IS_AOP_PREG (result)))
7923 emitcode ("mov", "a,%s", l);
7924 aopPut (result, "a", offr);
7929 aopPut (result, l, offr);
7932 /* MSB sign in acc.7 ! */
7933 if (getDataSize (left) == offl + 1)
7936 aopPut (result, "a", offr);
7943 /*-----------------------------------------------------------------*/
7944 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7945 /*-----------------------------------------------------------------*/
7949 emitcode ("rrc", "a");
7950 emitcode ("xch", "a,%s", x);
7951 emitcode ("rrc", "a");
7952 emitcode ("xch", "a,%s", x);
7955 /*-----------------------------------------------------------------*/
7956 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7957 /*-----------------------------------------------------------------*/
7961 emitcode ("xch", "a,%s", x);
7962 emitcode ("rlc", "a");
7963 emitcode ("xch", "a,%s", x);
7964 emitcode ("rlc", "a");
7967 /*-----------------------------------------------------------------*/
7968 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7969 /*-----------------------------------------------------------------*/
7973 emitcode ("xch", "a,%s", x);
7974 emitcode ("add", "a,acc");
7975 emitcode ("xch", "a,%s", x);
7976 emitcode ("rlc", "a");
7979 /*-----------------------------------------------------------------*/
7980 /* AccAXLsh - left shift a:x by known count (0..7) */
7981 /*-----------------------------------------------------------------*/
7983 AccAXLsh (char *x, int shCount)
7998 case 5: // AAAAABBB:CCCCCDDD
8000 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8002 emitcode ("anl", "a,#0x%02x",
8003 SLMask[shCount]); // BBB00000:CCCCCDDD
8005 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8007 AccRol (shCount); // DDDCCCCC:BBB00000
8009 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8011 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8013 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8015 emitcode ("anl", "a,#0x%02x",
8016 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8018 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8020 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8023 case 6: // AAAAAABB:CCCCCCDD
8024 emitcode ("anl", "a,#0x%02x",
8025 SRMask[shCount]); // 000000BB:CCCCCCDD
8026 emitcode ("mov", "c,acc.0"); // c = B
8027 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8029 AccAXRrl1 (x); // BCCCCCCD:D000000B
8030 AccAXRrl1 (x); // BBCCCCCC:DD000000
8032 emitcode("rrc","a");
8033 emitcode("xch","a,%s", x);
8034 emitcode("rrc","a");
8035 emitcode("mov","c,acc.0"); //<< get correct bit
8036 emitcode("xch","a,%s", x);
8038 emitcode("rrc","a");
8039 emitcode("xch","a,%s", x);
8040 emitcode("rrc","a");
8041 emitcode("xch","a,%s", x);
8044 case 7: // a:x <<= 7
8046 emitcode ("anl", "a,#0x%02x",
8047 SRMask[shCount]); // 0000000B:CCCCCCCD
8049 emitcode ("mov", "c,acc.0"); // c = B
8051 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
8053 AccAXRrl1 (x); // BCCCCCCC:D0000000
8061 /*-----------------------------------------------------------------*/
8062 /* AccAXRsh - right shift a:x known count (0..7) */
8063 /*-----------------------------------------------------------------*/
8065 AccAXRsh (char *x, int shCount)
8073 AccAXRrl1 (x); // 0->a:x
8078 AccAXRrl1 (x); // 0->a:x
8081 AccAXRrl1 (x); // 0->a:x
8086 case 5: // AAAAABBB:CCCCCDDD = a:x
8088 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8090 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8092 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8094 emitcode ("anl", "a,#0x%02x",
8095 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8097 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8099 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8101 emitcode ("anl", "a,#0x%02x",
8102 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8104 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8106 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8108 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8111 case 6: // AABBBBBB:CCDDDDDD
8113 emitcode ("mov", "c,acc.7");
8114 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8116 emitcode ("mov", "c,acc.7");
8117 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8119 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8121 emitcode ("anl", "a,#0x%02x",
8122 SRMask[shCount]); // 000000AA:BBBBBBCC
8125 case 7: // ABBBBBBB:CDDDDDDD
8127 emitcode ("mov", "c,acc.7"); // c = A
8129 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8131 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8133 emitcode ("anl", "a,#0x%02x",
8134 SRMask[shCount]); // 0000000A:BBBBBBBC
8142 /*-----------------------------------------------------------------*/
8143 /* AccAXRshS - right shift signed a:x known count (0..7) */
8144 /*-----------------------------------------------------------------*/
8146 AccAXRshS (char *x, int shCount)
8154 emitcode ("mov", "c,acc.7");
8155 AccAXRrl1 (x); // s->a:x
8159 emitcode ("mov", "c,acc.7");
8160 AccAXRrl1 (x); // s->a:x
8162 emitcode ("mov", "c,acc.7");
8163 AccAXRrl1 (x); // s->a:x
8168 case 5: // AAAAABBB:CCCCCDDD = a:x
8170 tlbl = newiTempLabel (NULL);
8171 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8173 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8175 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8177 emitcode ("anl", "a,#0x%02x",
8178 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8180 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8182 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8184 emitcode ("anl", "a,#0x%02x",
8185 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8187 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8189 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8191 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8193 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8194 emitcode ("orl", "a,#0x%02x",
8195 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8197 emitcode ("", "%05d$:", tlbl->key + 100);
8198 break; // SSSSAAAA:BBBCCCCC
8200 case 6: // AABBBBBB:CCDDDDDD
8202 tlbl = newiTempLabel (NULL);
8203 emitcode ("mov", "c,acc.7");
8204 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8206 emitcode ("mov", "c,acc.7");
8207 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8209 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8211 emitcode ("anl", "a,#0x%02x",
8212 SRMask[shCount]); // 000000AA:BBBBBBCC
8214 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8215 emitcode ("orl", "a,#0x%02x",
8216 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8218 emitcode ("", "%05d$:", tlbl->key + 100);
8220 case 7: // ABBBBBBB:CDDDDDDD
8222 tlbl = newiTempLabel (NULL);
8223 emitcode ("mov", "c,acc.7"); // c = A
8225 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8227 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8229 emitcode ("anl", "a,#0x%02x",
8230 SRMask[shCount]); // 0000000A:BBBBBBBC
8232 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8233 emitcode ("orl", "a,#0x%02x",
8234 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8236 emitcode ("", "%05d$:", tlbl->key + 100);
8243 /*-----------------------------------------------------------------*/
8244 /* shiftL2Left2Result - shift left two bytes from left to result */
8245 /*-----------------------------------------------------------------*/
8247 shiftL2Left2Result (operand * left, int offl,
8248 operand * result, int offr, int shCount)
8251 bool pushedB = FALSE;
8254 if (sameRegs (AOP (result), AOP (left)) &&
8255 ((offl + MSB16) == offr))
8257 /* don't crash result[offr] */
8258 MOVA (aopGet (left, offl, FALSE, FALSE));
8259 emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8260 x = aopGet (result, offr, FALSE, FALSE);
8262 else if (aopGetUsesAcc (result, offr))
8264 movLeft2Result (left, offl, result, offr, 0);
8267 emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8268 MOVA (aopGet (result, offr, FALSE, FALSE));
8269 emitcode ("xch", "a,b");
8274 movLeft2Result (left, offl, result, offr, 0);
8275 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8276 x = aopGet (result, offr, FALSE, FALSE);
8278 /* ax << shCount (x = lsb(result)) */
8279 AccAXLsh (x, shCount);
8282 emitcode ("xch", "a,b");
8283 aopPut (result, "a", offr);
8284 aopPut (result, "b", offr + MSB16);
8289 aopPut (result, "a", offr + MSB16);
8294 /*-----------------------------------------------------------------*/
8295 /* shiftR2Left2Result - shift right two bytes from left to result */
8296 /*-----------------------------------------------------------------*/
8298 shiftR2Left2Result (operand * left, int offl,
8299 operand * result, int offr,
8300 int shCount, int sign)
8303 bool pushedB = FALSE;
8306 if (sameRegs (AOP (result), AOP (left)) &&
8307 ((offl + MSB16) == offr))
8309 /* don't crash result[offr] */
8310 MOVA (aopGet (left, offl, FALSE, FALSE));
8311 emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8312 x = aopGet (result, offr, FALSE, FALSE);
8314 else if (aopGetUsesAcc (result, offr))
8316 movLeft2Result (left, offl, result, offr, 0);
8319 emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8320 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8325 movLeft2Result (left, offl, result, offr, 0);
8326 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8327 x = aopGet (result, offr, FALSE, FALSE);
8329 /* a:x >> shCount (x = lsb(result)) */
8331 AccAXRshS (x, shCount);
8333 AccAXRsh (x, shCount);
8336 emitcode ("xch", "a,b");
8337 aopPut (result, "a", offr);
8338 emitcode ("xch", "a,b");
8341 if (getDataSize (result) > 1)
8342 aopPut (result, "a", offr + MSB16);
8345 /*-----------------------------------------------------------------*/
8346 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8347 /*-----------------------------------------------------------------*/
8349 shiftLLeftOrResult (operand * left, int offl,
8350 operand * result, int offr, int shCount)
8352 MOVA (aopGet (left, offl, FALSE, FALSE));
8353 /* shift left accumulator */
8355 /* or with result */
8356 if (aopGetUsesAcc (result, offr))
8358 emitcode ("xch", "a,b");
8359 MOVA (aopGet (result, offr, FALSE, FALSE));
8360 emitcode ("orl", "a,b");
8364 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8366 /* back to result */
8367 aopPut (result, "a", offr);
8370 /*-----------------------------------------------------------------*/
8371 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8372 /*-----------------------------------------------------------------*/
8374 shiftRLeftOrResult (operand * left, int offl,
8375 operand * result, int offr, int shCount)
8377 MOVA (aopGet (left, offl, FALSE, FALSE));
8378 /* shift right accumulator */
8380 /* or with result */
8381 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8382 /* back to result */
8383 aopPut (result, "a", offr);
8386 /*-----------------------------------------------------------------*/
8387 /* genlshOne - left shift a one byte quantity by known count */
8388 /*-----------------------------------------------------------------*/
8390 genlshOne (operand * result, operand * left, int shCount)
8392 D(emitcode ("; genlshOne",""));
8394 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8397 /*-----------------------------------------------------------------*/
8398 /* genlshTwo - left shift two bytes by known amount != 0 */
8399 /*-----------------------------------------------------------------*/
8401 genlshTwo (operand * result, operand * left, int shCount)
8405 D(emitcode ("; genlshTwo",""));
8407 size = getDataSize (result);
8409 /* if shCount >= 8 */
8417 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8419 movLeft2Result (left, LSB, result, MSB16, 0);
8421 aopPut (result, zero, LSB);
8424 /* 1 <= shCount <= 7 */
8428 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8430 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8434 /*-----------------------------------------------------------------*/
8435 /* shiftLLong - shift left one long from left to result */
8436 /* offl = LSB or MSB16 */
8437 /*-----------------------------------------------------------------*/
8439 shiftLLong (operand * left, operand * result, int offr)
8442 int size = AOP_SIZE (result);
8444 if (size >= LSB + offr)
8446 l = aopGet (left, LSB, FALSE, FALSE);
8448 emitcode ("add", "a,acc");
8449 if (sameRegs (AOP (left), AOP (result)) &&
8450 size >= MSB16 + offr && offr != LSB)
8451 emitcode ("xch", "a,%s",
8452 aopGet (left, LSB + offr, FALSE, FALSE));
8454 aopPut (result, "a", LSB + offr);
8457 if (size >= MSB16 + offr)
8459 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8461 l = aopGet (left, MSB16, FALSE, FALSE);
8464 emitcode ("rlc", "a");
8465 if (sameRegs (AOP (left), AOP (result)) &&
8466 size >= MSB24 + offr && offr != LSB)
8467 emitcode ("xch", "a,%s",
8468 aopGet (left, MSB16 + offr, FALSE, FALSE));
8470 aopPut (result, "a", MSB16 + offr);
8473 if (size >= MSB24 + offr)
8475 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8477 l = aopGet (left, MSB24, FALSE, FALSE);
8480 emitcode ("rlc", "a");
8481 if (sameRegs (AOP (left), AOP (result)) &&
8482 size >= MSB32 + offr && offr != LSB)
8483 emitcode ("xch", "a,%s",
8484 aopGet (left, MSB24 + offr, FALSE, FALSE));
8486 aopPut (result, "a", MSB24 + offr);
8489 if (size > MSB32 + offr)
8491 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8493 l = aopGet (left, MSB32, FALSE, FALSE);
8496 emitcode ("rlc", "a");
8497 aopPut (result, "a", MSB32 + offr);
8500 aopPut (result, zero, LSB);
8503 /*-----------------------------------------------------------------*/
8504 /* genlshFour - shift four byte by a known amount != 0 */
8505 /*-----------------------------------------------------------------*/
8507 genlshFour (operand * result, operand * left, int shCount)
8511 D(emitcode ("; genlshFour",""));
8513 size = AOP_SIZE (result);
8515 /* if shifting more that 3 bytes */
8520 /* lowest order of left goes to the highest
8521 order of the destination */
8522 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8524 movLeft2Result (left, LSB, result, MSB32, 0);
8525 aopPut (result, zero, LSB);
8526 aopPut (result, zero, MSB16);
8527 aopPut (result, zero, MSB24);
8531 /* more than two bytes */
8532 else if (shCount >= 16)
8534 /* lower order two bytes goes to higher order two bytes */
8536 /* if some more remaining */
8538 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8541 movLeft2Result (left, MSB16, result, MSB32, 0);
8542 movLeft2Result (left, LSB, result, MSB24, 0);
8544 aopPut (result, zero, MSB16);
8545 aopPut (result, zero, LSB);
8549 /* if more than 1 byte */
8550 else if (shCount >= 8)
8552 /* lower order three bytes goes to higher order three bytes */
8557 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8559 movLeft2Result (left, LSB, result, MSB16, 0);
8565 movLeft2Result (left, MSB24, result, MSB32, 0);
8566 movLeft2Result (left, MSB16, result, MSB24, 0);
8567 movLeft2Result (left, LSB, result, MSB16, 0);
8568 aopPut (result, zero, LSB);
8570 else if (shCount == 1)
8571 shiftLLong (left, result, MSB16);
8574 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8575 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8576 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8577 aopPut (result, zero, LSB);
8582 /* 1 <= shCount <= 7 */
8583 else if (shCount <= 2)
8585 shiftLLong (left, result, LSB);
8587 shiftLLong (result, result, LSB);
8589 /* 3 <= shCount <= 7, optimize */
8592 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8593 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8594 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8598 /*-----------------------------------------------------------------*/
8599 /* genLeftShiftLiteral - left shifting by known count */
8600 /*-----------------------------------------------------------------*/
8602 genLeftShiftLiteral (operand * left,
8607 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8610 D(emitcode ("; genLeftShiftLiteral",""));
8612 freeAsmop (right, NULL, ic, TRUE);
8614 aopOp (left, ic, FALSE);
8615 aopOp (result, ic, FALSE);
8617 size = getSize (operandType (result));
8620 emitcode ("; shift left ", "result %d, left %d", size,
8624 /* I suppose that the left size >= result size */
8629 movLeft2Result (left, size, result, size, 0);
8633 else if (shCount >= (size * 8))
8635 aopPut (result, zero, size);
8641 genlshOne (result, left, shCount);
8645 genlshTwo (result, left, shCount);
8649 genlshFour (result, left, shCount);
8652 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8653 "*** ack! mystery literal shift!\n");
8657 freeAsmop (result, NULL, ic, TRUE);
8658 freeAsmop (left, NULL, ic, TRUE);
8661 /*-----------------------------------------------------------------*/
8662 /* genLeftShift - generates code for left shifting */
8663 /*-----------------------------------------------------------------*/
8665 genLeftShift (iCode * ic)
8667 operand *left, *right, *result;
8670 symbol *tlbl, *tlbl1;
8673 D(emitcode ("; genLeftShift",""));
8675 right = IC_RIGHT (ic);
8676 left = IC_LEFT (ic);
8677 result = IC_RESULT (ic);
8679 aopOp (right, ic, FALSE);
8681 /* if the shift count is known then do it
8682 as efficiently as possible */
8683 if (AOP_TYPE (right) == AOP_LIT)
8685 genLeftShiftLiteral (left, right, result, ic);
8689 /* shift count is unknown then we have to form
8690 a loop get the loop count in B : Note: we take
8691 only the lower order byte since shifting
8692 more that 32 bits make no sense anyway, ( the
8693 largest size of an object can be only 32 bits ) */
8696 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
8697 emitcode ("inc", "b");
8698 freeAsmop (right, NULL, ic, TRUE);
8699 aopOp (left, ic, FALSE);
8700 aopOp (result, ic, FALSE);
8702 /* now move the left to the result if they are not the same */
8703 if (!sameRegs (AOP (left), AOP (result)) &&
8704 AOP_SIZE (result) > 1)
8707 size = AOP_SIZE (result);
8711 l = aopGet (left, offset, FALSE, TRUE);
8712 if (*l == '@' && (IS_AOP_PREG (result)))
8715 emitcode ("mov", "a,%s", l);
8716 aopPut (result, "a", offset);
8719 aopPut (result, l, offset);
8724 tlbl = newiTempLabel (NULL);
8725 size = AOP_SIZE (result);
8727 tlbl1 = newiTempLabel (NULL);
8729 /* if it is only one byte then */
8732 symbol *tlbl1 = newiTempLabel (NULL);
8734 l = aopGet (left, 0, FALSE, FALSE);
8736 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8737 emitcode ("", "%05d$:", tlbl->key + 100);
8738 emitcode ("add", "a,acc");
8739 emitcode ("", "%05d$:", tlbl1->key + 100);
8740 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8742 aopPut (result, "a", 0);
8746 reAdjustPreg (AOP (result));
8748 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8749 emitcode ("", "%05d$:", tlbl->key + 100);
8750 l = aopGet (result, offset, FALSE, FALSE);
8752 emitcode ("add", "a,acc");
8753 aopPut (result, "a", offset++);
8756 l = aopGet (result, offset, FALSE, FALSE);
8758 emitcode ("rlc", "a");
8759 aopPut (result, "a", offset++);
8761 reAdjustPreg (AOP (result));
8763 emitcode ("", "%05d$:", tlbl1->key + 100);
8764 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8767 freeAsmop (result, NULL, ic, TRUE);
8768 freeAsmop (left, NULL, ic, TRUE);
8771 /*-----------------------------------------------------------------*/
8772 /* genrshOne - right shift a one byte quantity by known count */
8773 /*-----------------------------------------------------------------*/
8775 genrshOne (operand * result, operand * left,
8776 int shCount, int sign)
8778 D(emitcode ("; genrshOne",""));
8780 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8783 /*-----------------------------------------------------------------*/
8784 /* genrshTwo - right shift two bytes by known amount != 0 */
8785 /*-----------------------------------------------------------------*/
8787 genrshTwo (operand * result, operand * left,
8788 int shCount, int sign)
8790 D(emitcode ("; genrshTwo",""));
8792 /* if shCount >= 8 */
8797 shiftR1Left2Result (left, MSB16, result, LSB,
8800 movLeft2Result (left, MSB16, result, LSB, sign);
8801 addSign (result, MSB16, sign);
8804 /* 1 <= shCount <= 7 */
8806 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8809 /*-----------------------------------------------------------------*/
8810 /* shiftRLong - shift right one long from left to result */
8811 /* offl = LSB or MSB16 */
8812 /*-----------------------------------------------------------------*/
8814 shiftRLong (operand * left, int offl,
8815 operand * result, int sign)
8817 bool useSameRegs = regsInCommon (left, result);
8819 if (useSameRegs && offl>1)
8821 // we are in big trouble, but this shouldn't happen
8822 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8825 MOVA (aopGet (left, MSB32, FALSE, FALSE));
8832 emitcode ("rlc", "a");
8833 emitcode ("subb", "a,acc");
8834 if (useSameRegs && sameReg (AOP (left), MSB32, AOP (result), MSB32))
8836 emitcode ("xch", "a,%s", aopGet (left, MSB32, FALSE, FALSE));
8840 aopPut (result, "a", MSB32);
8841 MOVA (aopGet (left, MSB32, FALSE, FALSE));
8846 aopPut (result, zero, MSB32);
8852 emitcode ("clr", "c");
8856 emitcode ("mov", "c,acc.7");
8859 emitcode ("rrc", "a");
8861 if (useSameRegs && offl==MSB16 &&
8862 sameReg (AOP (left), MSB24, AOP (result), MSB32-offl))
8864 emitcode ("xch", "a,%s",aopGet (left, MSB24, FALSE, FALSE));
8868 aopPut (result, "a", MSB32-offl);
8869 MOVA (aopGet (left, MSB24, FALSE, FALSE));
8872 emitcode ("rrc", "a");
8873 if (useSameRegs && offl==1 &&
8874 sameReg (AOP (left), MSB16, AOP (result), MSB24-offl))
8876 emitcode ("xch", "a,%s",aopGet (left, MSB16, FALSE, FALSE));
8880 aopPut (result, "a", MSB24-offl);
8881 MOVA (aopGet (left, MSB16, FALSE, FALSE));
8883 emitcode ("rrc", "a");
8886 aopPut (result, "a", MSB16 - offl);
8891 sameReg (AOP (left), LSB, AOP (result), MSB16-offl))
8893 emitcode ("xch", "a,%s",aopGet (left, LSB, FALSE, FALSE));
8897 aopPut (result, "a", MSB16 - offl);
8898 MOVA (aopGet (left, LSB, FALSE, FALSE));
8900 emitcode ("rrc", "a");
8901 aopPut (result, "a", LSB);
8905 /*-----------------------------------------------------------------*/
8906 /* genrshFour - shift four byte by a known amount != 0 */
8907 /*-----------------------------------------------------------------*/
8909 genrshFour (operand * result, operand * left,
8910 int shCount, int sign)
8912 D(emitcode ("; genrshFour",""));
8914 /* if shifting more that 3 bytes */
8919 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8921 movLeft2Result (left, MSB32, result, LSB, sign);
8922 addSign (result, MSB16, sign);
8924 else if (shCount >= 16)
8928 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8931 movLeft2Result (left, MSB24, result, LSB, 0);
8932 movLeft2Result (left, MSB32, result, MSB16, sign);
8934 addSign (result, MSB24, sign);
8936 else if (shCount >= 8)
8940 shiftRLong (left, MSB16, result, sign);
8941 else if (shCount == 0)
8943 movLeft2Result (left, MSB16, result, LSB, 0);
8944 movLeft2Result (left, MSB24, result, MSB16, 0);
8945 movLeft2Result (left, MSB32, result, MSB24, sign);
8946 addSign (result, MSB32, sign);
8950 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8951 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8952 /* the last shift is signed */
8953 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8954 addSign (result, MSB32, sign);
8958 { /* 1 <= shCount <= 7 */
8961 shiftRLong (left, LSB, result, sign);
8963 shiftRLong (result, LSB, result, sign);
8967 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8968 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8969 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8974 /*-----------------------------------------------------------------*/
8975 /* genRightShiftLiteral - right shifting by known count */
8976 /*-----------------------------------------------------------------*/
8978 genRightShiftLiteral (operand * left,
8984 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8987 D(emitcode ("; genRightShiftLiteral",""));
8989 freeAsmop (right, NULL, ic, TRUE);
8991 aopOp (left, ic, FALSE);
8992 aopOp (result, ic, FALSE);
8995 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8999 size = getDataSize (left);
9000 /* test the LEFT size !!! */
9002 /* I suppose that the left size >= result size */
9005 size = getDataSize (result);
9007 movLeft2Result (left, size, result, size, 0);
9010 else if (shCount >= (size * 8))
9013 /* get sign in acc.7 */
9014 MOVA (aopGet (left, size - 1, FALSE, FALSE));
9016 addSign (result, LSB, sign);
9023 genrshOne (result, left, shCount, sign);
9027 genrshTwo (result, left, shCount, sign);
9031 genrshFour (result, left, shCount, sign);
9037 freeAsmop (result, NULL, ic, TRUE);
9038 freeAsmop (left, NULL, ic, TRUE);
9041 /*-----------------------------------------------------------------*/
9042 /* genSignedRightShift - right shift of signed number */
9043 /*-----------------------------------------------------------------*/
9045 genSignedRightShift (iCode * ic)
9047 operand *right, *left, *result;
9050 symbol *tlbl, *tlbl1;
9053 D(emitcode ("; genSignedRightShift",""));
9055 /* we do it the hard way put the shift count in b
9056 and loop thru preserving the sign */
9058 right = IC_RIGHT (ic);
9059 left = IC_LEFT (ic);
9060 result = IC_RESULT (ic);
9062 aopOp (right, ic, FALSE);
9065 if (AOP_TYPE (right) == AOP_LIT)
9067 genRightShiftLiteral (left, right, result, ic, 1);
9070 /* shift count is unknown then we have to form
9071 a loop get the loop count in B : Note: we take
9072 only the lower order byte since shifting
9073 more that 32 bits make no sense anyway, ( the
9074 largest size of an object can be only 32 bits ) */
9077 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
9078 emitcode ("inc", "b");
9079 freeAsmop (right, NULL, ic, TRUE);
9080 aopOp (left, ic, FALSE);
9081 aopOp (result, ic, FALSE);
9083 /* now move the left to the result if they are not the
9085 if (!sameRegs (AOP (left), AOP (result)) &&
9086 AOP_SIZE (result) > 1)
9089 size = AOP_SIZE (result);
9093 l = aopGet (left, offset, FALSE, TRUE);
9094 if (*l == '@' && IS_AOP_PREG (result))
9097 emitcode ("mov", "a,%s", l);
9098 aopPut (result, "a", offset);
9101 aopPut (result, l, offset);
9106 /* mov the highest order bit to OVR */
9107 tlbl = newiTempLabel (NULL);
9108 tlbl1 = newiTempLabel (NULL);
9110 size = AOP_SIZE (result);
9112 MOVA (aopGet (left, offset, FALSE, FALSE));
9113 emitcode ("rlc", "a");
9114 emitcode ("mov", "ov,c");
9115 /* if it is only one byte then */
9118 l = aopGet (left, 0, FALSE, FALSE);
9120 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9121 emitcode ("", "%05d$:", tlbl->key + 100);
9122 emitcode ("mov", "c,ov");
9123 emitcode ("rrc", "a");
9124 emitcode ("", "%05d$:", tlbl1->key + 100);
9125 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9127 aopPut (result, "a", 0);
9131 reAdjustPreg (AOP (result));
9132 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9133 emitcode ("", "%05d$:", tlbl->key + 100);
9134 emitcode ("mov", "c,ov");
9137 l = aopGet (result, offset, FALSE, FALSE);
9139 emitcode ("rrc", "a");
9140 aopPut (result, "a", offset--);
9142 reAdjustPreg (AOP (result));
9143 emitcode ("", "%05d$:", tlbl1->key + 100);
9144 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9148 freeAsmop (result, NULL, ic, TRUE);
9149 freeAsmop (left, NULL, ic, TRUE);
9152 /*-----------------------------------------------------------------*/
9153 /* genRightShift - generate code for right shifting */
9154 /*-----------------------------------------------------------------*/
9156 genRightShift (iCode * ic)
9158 operand *right, *left, *result;
9162 symbol *tlbl, *tlbl1;
9165 D(emitcode ("; genRightShift",""));
9167 /* if signed then we do it the hard way preserve the
9168 sign bit moving it inwards */
9169 letype = getSpec (operandType (IC_LEFT (ic)));
9171 if (!SPEC_USIGN (letype))
9173 genSignedRightShift (ic);
9177 /* signed & unsigned types are treated the same : i.e. the
9178 signed is NOT propagated inwards : quoting from the
9179 ANSI - standard : "for E1 >> E2, is equivalent to division
9180 by 2**E2 if unsigned or if it has a non-negative value,
9181 otherwise the result is implementation defined ", MY definition
9182 is that the sign does not get propagated */
9184 right = IC_RIGHT (ic);
9185 left = IC_LEFT (ic);
9186 result = IC_RESULT (ic);
9188 aopOp (right, ic, FALSE);
9190 /* if the shift count is known then do it
9191 as efficiently as possible */
9192 if (AOP_TYPE (right) == AOP_LIT)
9194 genRightShiftLiteral (left, right, result, ic, 0);
9198 /* shift count is unknown then we have to form
9199 a loop get the loop count in B : Note: we take
9200 only the lower order byte since shifting
9201 more that 32 bits make no sense anyway, ( the
9202 largest size of an object can be only 32 bits ) */
9205 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
9206 emitcode ("inc", "b");
9207 freeAsmop (right, NULL, ic, TRUE);
9208 aopOp (left, ic, FALSE);
9209 aopOp (result, ic, FALSE);
9211 /* now move the left to the result if they are not the
9213 if (!sameRegs (AOP (left), AOP (result)) &&
9214 AOP_SIZE (result) > 1)
9217 size = AOP_SIZE (result);
9221 l = aopGet (left, offset, FALSE, TRUE);
9222 if (*l == '@' && IS_AOP_PREG (result))
9225 emitcode ("mov", "a,%s", l);
9226 aopPut (result, "a", offset);
9229 aopPut (result, l, offset);
9234 tlbl = newiTempLabel (NULL);
9235 tlbl1 = newiTempLabel (NULL);
9236 size = AOP_SIZE (result);
9239 /* if it is only one byte then */
9242 l = aopGet (left, 0, FALSE, FALSE);
9244 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9245 emitcode ("", "%05d$:", tlbl->key + 100);
9247 emitcode ("rrc", "a");
9248 emitcode ("", "%05d$:", tlbl1->key + 100);
9249 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9251 aopPut (result, "a", 0);
9255 reAdjustPreg (AOP (result));
9256 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9257 emitcode ("", "%05d$:", tlbl->key + 100);
9261 l = aopGet (result, offset, FALSE, FALSE);
9263 emitcode ("rrc", "a");
9264 aopPut (result, "a", offset--);
9266 reAdjustPreg (AOP (result));
9268 emitcode ("", "%05d$:", tlbl1->key + 100);
9269 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9273 freeAsmop (result, NULL, ic, TRUE);
9274 freeAsmop (left, NULL, ic, TRUE);
9277 /*-----------------------------------------------------------------*/
9278 /* emitPtrByteGet - emits code to get a byte into A through a */
9279 /* pointer register (R0, R1, or DPTR). The */
9280 /* original value of A can be preserved in B. */
9281 /*-----------------------------------------------------------------*/
9283 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9290 emitcode ("mov", "b,a");
9291 emitcode ("mov", "a,@%s", rname);
9296 emitcode ("mov", "b,a");
9297 emitcode ("movx", "a,@%s", rname);
9302 emitcode ("mov", "b,a");
9303 emitcode ("movx", "a,@dptr");
9308 emitcode ("mov", "b,a");
9309 emitcode ("clr", "a");
9310 emitcode ("movc", "a,@a+dptr");
9316 emitcode ("push", "b");
9317 emitcode ("push", "acc");
9319 emitcode ("lcall", "__gptrget");
9321 emitcode ("pop", "b");
9326 /*-----------------------------------------------------------------*/
9327 /* emitPtrByteSet - emits code to set a byte from src through a */
9328 /* pointer register (R0, R1, or DPTR). */
9329 /*-----------------------------------------------------------------*/
9331 emitPtrByteSet (char *rname, int p_type, char *src)
9340 emitcode ("mov", "@%s,a", rname);
9343 emitcode ("mov", "@%s,%s", rname, src);
9348 emitcode ("movx", "@%s,a", rname);
9353 emitcode ("movx", "@dptr,a");
9358 emitcode ("lcall", "__gptrput");
9363 /*-----------------------------------------------------------------*/
9364 /* genUnpackBits - generates code for unpacking bits */
9365 /*-----------------------------------------------------------------*/
9367 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9369 int offset = 0; /* result byte offset */
9370 int rsize; /* result size */
9371 int rlen = 0; /* remaining bitfield length */
9372 sym_link *etype; /* bitfield type information */
9373 int blen; /* bitfield length */
9374 int bstr; /* bitfield starting bit within byte */
9377 D(emitcode ("; genUnpackBits",""));
9379 etype = getSpec (operandType (result));
9380 rsize = getSize (operandType (result));
9381 blen = SPEC_BLEN (etype);
9382 bstr = SPEC_BSTR (etype);
9384 if (ifx && blen <= 8)
9386 emitPtrByteGet (rname, ptype, FALSE);
9389 SNPRINTF (buffer, sizeof(buffer),
9391 genIfxJump (ifx, buffer, NULL, NULL, NULL);
9396 emitcode ("anl", "a,#0x%02x",
9397 (((unsigned char) -1) >> (8 - blen)) << bstr);
9398 genIfxJump (ifx, "a", NULL, NULL, NULL);
9404 /* If the bitfield length is less than a byte */
9407 emitPtrByteGet (rname, ptype, FALSE);
9409 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9410 if (!SPEC_USIGN (etype))
9412 /* signed bitfield */
9413 symbol *tlbl = newiTempLabel (NULL);
9415 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9416 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9417 emitcode ("", "%05d$:", tlbl->key + 100);
9419 aopPut (result, "a", offset++);
9423 /* Bit field did not fit in a byte. Copy all
9424 but the partial byte at the end. */
9425 for (rlen=blen;rlen>=8;rlen-=8)
9427 emitPtrByteGet (rname, ptype, FALSE);
9428 aopPut (result, "a", offset++);
9430 emitcode ("inc", "%s", rname);
9433 /* Handle the partial byte at the end */
9436 emitPtrByteGet (rname, ptype, FALSE);
9437 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9438 if (!SPEC_USIGN (etype))
9440 /* signed bitfield */
9441 symbol *tlbl = newiTempLabel (NULL);
9443 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9444 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9445 emitcode ("", "%05d$:", tlbl->key + 100);
9447 aopPut (result, "a", offset++);
9455 if (SPEC_USIGN (etype))
9459 /* signed bitfield: sign extension with 0x00 or 0xff */
9460 emitcode ("rlc", "a");
9461 emitcode ("subb", "a,acc");
9467 aopPut (result, source, offset++);
9472 /*-----------------------------------------------------------------*/
9473 /* genDataPointerGet - generates code when ptr offset is known */
9474 /*-----------------------------------------------------------------*/
9476 genDataPointerGet (operand * left,
9482 int size, offset = 0;
9484 D(emitcode ("; genDataPointerGet",""));
9486 aopOp (result, ic, TRUE);
9488 /* get the string representation of the name */
9489 l = aopGet (left, 0, FALSE, TRUE);
9490 size = AOP_SIZE (result);
9494 sprintf (buffer, "(%s + %d)", l + 1, offset);
9496 sprintf (buffer, "%s", l + 1);
9497 aopPut (result, buffer, offset++);
9500 freeAsmop (result, NULL, ic, TRUE);
9501 freeAsmop (left, NULL, ic, TRUE);
9504 /*-----------------------------------------------------------------*/
9505 /* genNearPointerGet - emitcode for near pointer fetch */
9506 /*-----------------------------------------------------------------*/
9508 genNearPointerGet (operand * left,
9517 sym_link *rtype, *retype;
9518 sym_link *ltype = operandType (left);
9521 D(emitcode ("; genNearPointerGet",""));
9523 rtype = operandType (result);
9524 retype = getSpec (rtype);
9526 aopOp (left, ic, FALSE);
9528 /* if left is rematerialisable and
9529 result is not bitfield variable type and
9530 the left is pointer to data space i.e
9531 lower 128 bytes of space */
9532 if (AOP_TYPE (left) == AOP_IMMD &&
9533 !IS_BITFIELD (retype) &&
9534 DCL_TYPE (ltype) == POINTER)
9536 genDataPointerGet (left, result, ic);
9540 /* if the value is already in a pointer register
9541 then don't need anything more */
9542 if (!AOP_INPREG (AOP (left)))
9544 if (IS_AOP_PREG (left))
9546 // Aha, it is a pointer, just in disguise.
9547 rname = aopGet (left, 0, FALSE, FALSE);
9550 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9551 __FILE__, __LINE__);
9556 emitcode ("mov", "a%s,%s", rname + 1, rname);
9557 rname++; // skip the '@'.
9562 /* otherwise get a free pointer register */
9564 preg = getFreePtr (ic, &aop, FALSE);
9565 emitcode ("mov", "%s,%s",
9567 aopGet (left, 0, FALSE, TRUE));
9572 rname = aopGet (left, 0, FALSE, FALSE);
9574 //aopOp (result, ic, FALSE);
9575 aopOp (result, ic, result?TRUE:FALSE);
9577 /* if bitfield then unpack the bits */
9578 if (IS_BITFIELD (retype))
9579 genUnpackBits (result, rname, POINTER, ifx);
9582 /* we have can just get the values */
9583 int size = AOP_SIZE (result);
9588 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9591 emitcode ("mov", "a,@%s", rname);
9593 aopPut (result, "a", offset);
9597 sprintf (buffer, "@%s", rname);
9598 aopPut (result, buffer, offset);
9602 emitcode ("inc", "%s", rname);
9606 /* now some housekeeping stuff */
9607 if (aop) /* we had to allocate for this iCode */
9609 if (pi) { /* post increment present */
9610 aopPut (left, rname, 0);
9612 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9616 /* we did not allocate which means left
9617 already in a pointer register, then
9618 if size > 0 && this could be used again
9619 we have to point it back to where it
9621 if ((AOP_SIZE (result) > 1 &&
9622 !OP_SYMBOL (left)->remat &&
9623 (OP_SYMBOL (left)->liveTo > ic->seq ||
9627 int size = AOP_SIZE (result) - 1;
9629 emitcode ("dec", "%s", rname);
9633 if (ifx && !ifx->generated)
9635 genIfxJump (ifx, "a", left, NULL, result);
9639 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9640 freeAsmop (left, NULL, ic, TRUE);
9641 if (pi) pi->generated = 1;
9644 /*-----------------------------------------------------------------*/
9645 /* genPagedPointerGet - emitcode for paged pointer fetch */
9646 /*-----------------------------------------------------------------*/
9648 genPagedPointerGet (operand * left,
9657 sym_link *rtype, *retype;
9659 D(emitcode ("; genPagedPointerGet",""));
9661 rtype = operandType (result);
9662 retype = getSpec (rtype);
9664 aopOp (left, ic, FALSE);
9666 /* if the value is already in a pointer register
9667 then don't need anything more */
9668 if (!AOP_INPREG (AOP (left)))
9670 /* otherwise get a free pointer register */
9672 preg = getFreePtr (ic, &aop, FALSE);
9673 emitcode ("mov", "%s,%s",
9675 aopGet (left, 0, FALSE, TRUE));
9679 rname = aopGet (left, 0, FALSE, FALSE);
9681 aopOp (result, ic, FALSE);
9683 /* if bitfield then unpack the bits */
9684 if (IS_BITFIELD (retype))
9685 genUnpackBits (result, rname, PPOINTER, ifx);
9688 /* we have can just get the values */
9689 int size = AOP_SIZE (result);
9695 emitcode ("movx", "a,@%s", rname);
9697 aopPut (result, "a", offset);
9702 emitcode ("inc", "%s", rname);
9706 /* now some housekeeping stuff */
9707 if (aop) /* we had to allocate for this iCode */
9710 aopPut (left, rname, 0);
9711 freeAsmop (NULL, aop, ic, TRUE);
9715 /* we did not allocate which means left
9716 already in a pointer register, then
9717 if size > 0 && this could be used again
9718 we have to point it back to where it
9720 if ((AOP_SIZE (result) > 1 &&
9721 !OP_SYMBOL (left)->remat &&
9722 (OP_SYMBOL (left)->liveTo > ic->seq ||
9726 int size = AOP_SIZE (result) - 1;
9728 emitcode ("dec", "%s", rname);
9732 if (ifx && !ifx->generated)
9734 genIfxJump (ifx, "a", left, NULL, result);
9738 freeAsmop (result, NULL, ic, TRUE);
9739 freeAsmop (left, NULL, ic, TRUE);
9740 if (pi) pi->generated = 1;
9743 /*--------------------------------------------------------------------*/
9744 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
9745 /*--------------------------------------------------------------------*/
9747 loadDptrFromOperand (operand *op, bool loadBToo)
9749 if (AOP_TYPE (op) != AOP_STR)
9751 /* if this is rematerializable */
9752 if (AOP_TYPE (op) == AOP_IMMD)
9754 emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
9757 if (AOP(op)->aopu.aop_immd.from_cast_remat)
9758 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
9761 wassertl(FALSE, "need pointerCode");
9762 emitcode ("", "; mov b,???");
9763 /* genPointerGet and genPointerSet originally did different
9764 ** things for this case. Both seem wrong.
9765 ** from genPointerGet:
9766 ** emitcode ("mov", "b,#%d", pointerCode (retype));
9767 ** from genPointerSet:
9768 ** emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
9773 else if (AOP_TYPE (op) == AOP_DPTR)
9777 MOVA (aopGet (op, 0, FALSE, FALSE));
9778 emitcode ("push", "acc");
9779 MOVA (aopGet (op, 1, FALSE, FALSE));
9780 emitcode ("push", "acc");
9781 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9782 emitcode ("pop", "dph");
9783 emitcode ("pop", "dpl");
9787 MOVA (aopGet (op, 0, FALSE, FALSE));
9788 emitcode ("push", "acc");
9789 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9790 emitcode ("pop", "dpl");
9794 { /* we need to get it byte by byte */
9795 emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
9796 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9798 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9803 /*-----------------------------------------------------------------*/
9804 /* genFarPointerGet - gget value from far space */
9805 /*-----------------------------------------------------------------*/
9807 genFarPointerGet (operand * left,
9808 operand * result, iCode * ic, iCode * pi, iCode * ifx)
9811 sym_link *retype = getSpec (operandType (result));
9813 D(emitcode ("; genFarPointerGet",""));
9815 aopOp (left, ic, FALSE);
9816 loadDptrFromOperand (left, FALSE);
9818 /* so dptr now contains the address */
9819 aopOp (result, ic, FALSE);
9821 /* if bit then unpack */
9822 if (IS_BITFIELD (retype))
9823 genUnpackBits (result, "dptr", FPOINTER, ifx);
9826 size = AOP_SIZE (result);
9831 emitcode ("movx", "a,@dptr");
9833 aopPut (result, "a", offset++);
9835 emitcode ("inc", "dptr");
9839 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9841 aopPut (left, "dpl", 0);
9842 aopPut (left, "dph", 1);
9846 if (ifx && !ifx->generated)
9848 genIfxJump (ifx, "a", left, NULL, result);
9851 freeAsmop (result, NULL, ic, TRUE);
9852 freeAsmop (left, NULL, ic, TRUE);
9855 /*-----------------------------------------------------------------*/
9856 /* genCodePointerGet - get value from code space */
9857 /*-----------------------------------------------------------------*/
9859 genCodePointerGet (operand * left,
9860 operand * result, iCode * ic, iCode *pi, iCode *ifx)
9863 sym_link *retype = getSpec (operandType (result));
9865 D(emitcode ("; genCodePointerGet",""));
9867 aopOp (left, ic, FALSE);
9868 loadDptrFromOperand (left, FALSE);
9870 /* so dptr now contains the address */
9871 aopOp (result, ic, FALSE);
9873 /* if bit then unpack */
9874 if (IS_BITFIELD (retype))
9875 genUnpackBits (result, "dptr", CPOINTER, ifx);
9878 size = AOP_SIZE (result);
9883 emitcode ("clr", "a");
9884 emitcode ("movc", "a,@a+dptr");
9886 aopPut (result, "a", offset++);
9888 emitcode ("inc", "dptr");
9892 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9894 aopPut (left, "dpl", 0);
9895 aopPut (left, "dph", 1);
9899 if (ifx && !ifx->generated)
9901 genIfxJump (ifx, "a", left, NULL, result);
9904 freeAsmop (result, NULL, ic, TRUE);
9905 freeAsmop (left, NULL, ic, TRUE);
9908 /*-----------------------------------------------------------------*/
9909 /* genGenPointerGet - get value from generic pointer space */
9910 /*-----------------------------------------------------------------*/
9912 genGenPointerGet (operand * left,
9913 operand * result, iCode * ic, iCode *pi, iCode *ifx)
9916 sym_link *retype = getSpec (operandType (result));
9918 D(emitcode ("; genGenPointerGet",""));
9920 aopOp (left, ic, FALSE);
9921 loadDptrFromOperand (left, TRUE);
9923 /* so dptr know contains the address */
9924 aopOp (result, ic, FALSE);
9926 /* if bit then unpack */
9927 if (IS_BITFIELD (retype))
9928 genUnpackBits (result, "dptr", GPOINTER, ifx);
9931 size = AOP_SIZE (result);
9936 emitcode ("lcall", "__gptrget");
9938 aopPut (result, "a", offset++);
9940 emitcode ("inc", "dptr");
9944 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9946 aopPut (left, "dpl", 0);
9947 aopPut (left, "dph", 1);
9951 if (ifx && !ifx->generated)
9953 genIfxJump (ifx, "a", left, NULL, result);
9956 freeAsmop (result, NULL, ic, TRUE);
9957 freeAsmop (left, NULL, ic, TRUE);
9960 /*-----------------------------------------------------------------*/
9961 /* genPointerGet - generate code for pointer get */
9962 /*-----------------------------------------------------------------*/
9964 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
9966 operand *left, *result;
9967 sym_link *type, *etype;
9970 D(emitcode ("; genPointerGet",""));
9972 left = IC_LEFT (ic);
9973 result = IC_RESULT (ic);
9975 if (getSize (operandType (result))>1)
9978 /* depending on the type of pointer we need to
9979 move it to the correct pointer register */
9980 type = operandType (left);
9981 etype = getSpec (type);
9982 /* if left is of type of pointer then it is simple */
9983 if (IS_PTR (type) && !IS_FUNC (type->next))
9984 p_type = DCL_TYPE (type);
9987 /* we have to go by the storage class */
9988 p_type = PTR_TYPE (SPEC_OCLS (etype));
9991 /* special case when cast remat */
9992 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9993 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9994 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9995 type = operandType (left);
9996 p_type = DCL_TYPE (type);
9998 /* now that we have the pointer type we assign
9999 the pointer values */
10005 genNearPointerGet (left, result, ic, pi, ifx);
10009 genPagedPointerGet (left, result, ic, pi, ifx);
10013 genFarPointerGet (left, result, ic, pi, ifx);
10017 genCodePointerGet (left, result, ic, pi, ifx);
10021 genGenPointerGet (left, result, ic, pi, ifx);
10029 /*-----------------------------------------------------------------*/
10030 /* genPackBits - generates code for packed bit storage */
10031 /*-----------------------------------------------------------------*/
10033 genPackBits (sym_link * etype,
10035 char *rname, int p_type)
10037 int offset = 0; /* source byte offset */
10038 int rlen = 0; /* remaining bitfield length */
10039 int blen; /* bitfield length */
10040 int bstr; /* bitfield starting bit within byte */
10041 int litval; /* source literal value (if AOP_LIT) */
10042 unsigned char mask; /* bitmask within current byte */
10044 D(emitcode ("; genPackBits",""));
10046 blen = SPEC_BLEN (etype);
10047 bstr = SPEC_BSTR (etype);
10049 /* If the bitfield length is less than a byte */
10052 mask = ((unsigned char) (0xFF << (blen + bstr)) |
10053 (unsigned char) (0xFF >> (8 - bstr)));
10055 if (AOP_TYPE (right) == AOP_LIT)
10057 /* Case with a bitfield length <8 and literal source
10059 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10061 litval &= (~mask) & 0xff;
10062 emitPtrByteGet (rname, p_type, FALSE);
10063 if ((mask|litval)!=0xff)
10064 emitcode ("anl","a,#0x%02x", mask);
10066 emitcode ("orl","a,#0x%02x", litval);
10070 if ((blen==1) && (p_type!=GPOINTER))
10072 /* Case with a bitfield length == 1 and no generic pointer
10074 if (AOP_TYPE (right) == AOP_CRY)
10075 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10078 MOVA (aopGet (right, 0, FALSE, FALSE));
10079 emitcode ("rrc","a");
10081 emitPtrByteGet (rname, p_type, FALSE);
10082 emitcode ("mov","acc.%d,c",bstr);
10087 /* Case with a bitfield length < 8 and arbitrary source
10089 MOVA (aopGet (right, 0, FALSE, FALSE));
10090 /* shift and mask source value */
10092 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10094 pushedB = pushB ();
10095 /* transfer A to B and get next byte */
10096 emitPtrByteGet (rname, p_type, TRUE);
10098 emitcode ("anl", "a,#0x%02x", mask);
10099 emitcode ("orl", "a,b");
10100 if (p_type == GPOINTER)
10101 emitcode ("pop", "b");
10107 emitPtrByteSet (rname, p_type, "a");
10111 /* Bit length is greater than 7 bits. In this case, copy */
10112 /* all except the partial byte at the end */
10113 for (rlen=blen;rlen>=8;rlen-=8)
10115 emitPtrByteSet (rname, p_type,
10116 aopGet (right, offset++, FALSE, TRUE) );
10118 emitcode ("inc", "%s", rname);
10121 /* If there was a partial byte at the end */
10124 mask = (((unsigned char) -1 << rlen) & 0xff);
10126 if (AOP_TYPE (right) == AOP_LIT)
10128 /* Case with partial byte and literal source
10130 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10131 litval >>= (blen-rlen);
10132 litval &= (~mask) & 0xff;
10133 emitPtrByteGet (rname, p_type, FALSE);
10134 if ((mask|litval)!=0xff)
10135 emitcode ("anl","a,#0x%02x", mask);
10137 emitcode ("orl","a,#0x%02x", litval);
10142 /* Case with partial byte and arbitrary source
10144 MOVA (aopGet (right, offset++, FALSE, FALSE));
10145 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10147 pushedB = pushB ();
10148 /* transfer A to B and get next byte */
10149 emitPtrByteGet (rname, p_type, TRUE);
10151 emitcode ("anl", "a,#0x%02x", mask);
10152 emitcode ("orl", "a,b");
10153 if (p_type == GPOINTER)
10154 emitcode ("pop", "b");
10158 emitPtrByteSet (rname, p_type, "a");
10164 /*-----------------------------------------------------------------*/
10165 /* genDataPointerSet - remat pointer to data space */
10166 /*-----------------------------------------------------------------*/
10168 genDataPointerSet (operand * right,
10172 int size, offset = 0;
10173 char *l, buffer[256];
10175 D(emitcode ("; genDataPointerSet",""));
10177 aopOp (right, ic, FALSE);
10179 l = aopGet (result, 0, FALSE, TRUE);
10180 size = AOP_SIZE (right);
10184 sprintf (buffer, "(%s + %d)", l + 1, offset);
10186 sprintf (buffer, "%s", l + 1);
10187 emitcode ("mov", "%s,%s", buffer,
10188 aopGet (right, offset++, FALSE, FALSE));
10191 freeAsmop (result, NULL, ic, TRUE);
10192 freeAsmop (right, NULL, ic, TRUE);
10195 /*-----------------------------------------------------------------*/
10196 /* genNearPointerSet - emitcode for near pointer put */
10197 /*-----------------------------------------------------------------*/
10199 genNearPointerSet (operand * right,
10207 sym_link *retype, *letype;
10208 sym_link *ptype = operandType (result);
10210 D(emitcode ("; genNearPointerSet",""));
10212 retype = getSpec (operandType (right));
10213 letype = getSpec (ptype);
10214 aopOp (result, ic, FALSE);
10216 /* if the result is rematerializable &
10217 in data space & not a bit variable */
10218 if (AOP_TYPE (result) == AOP_IMMD &&
10219 DCL_TYPE (ptype) == POINTER &&
10220 !IS_BITVAR (retype) &&
10221 !IS_BITVAR (letype))
10223 genDataPointerSet (right, result, ic);
10227 /* if the value is already in a pointer register
10228 then don't need anything more */
10229 if (!AOP_INPREG (AOP (result)))
10232 //AOP_TYPE (result) == AOP_STK
10233 IS_AOP_PREG(result)
10236 // Aha, it is a pointer, just in disguise.
10237 rname = aopGet (result, 0, FALSE, FALSE);
10240 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10241 __FILE__, __LINE__);
10246 emitcode ("mov", "a%s,%s", rname + 1, rname);
10247 rname++; // skip the '@'.
10252 /* otherwise get a free pointer register */
10253 aop = newAsmop (0);
10254 preg = getFreePtr (ic, &aop, FALSE);
10255 emitcode ("mov", "%s,%s",
10257 aopGet (result, 0, FALSE, TRUE));
10258 rname = preg->name;
10263 rname = aopGet (result, 0, FALSE, FALSE);
10266 aopOp (right, ic, FALSE);
10268 /* if bitfield then unpack the bits */
10269 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10270 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10273 /* we have can just get the values */
10274 int size = AOP_SIZE (right);
10279 l = aopGet (right, offset, FALSE, TRUE);
10283 emitcode ("mov", "@%s,a", rname);
10286 emitcode ("mov", "@%s,%s", rname, l);
10288 emitcode ("inc", "%s", rname);
10293 /* now some housekeeping stuff */
10294 if (aop) /* we had to allocate for this iCode */
10297 aopPut (result, rname, 0);
10298 freeAsmop (NULL, aop, ic, TRUE);
10302 /* we did not allocate which means left
10303 already in a pointer register, then
10304 if size > 0 && this could be used again
10305 we have to point it back to where it
10307 if ((AOP_SIZE (right) > 1 &&
10308 !OP_SYMBOL (result)->remat &&
10309 (OP_SYMBOL (result)->liveTo > ic->seq ||
10313 int size = AOP_SIZE (right) - 1;
10315 emitcode ("dec", "%s", rname);
10320 if (pi) pi->generated = 1;
10321 freeAsmop (result, NULL, ic, TRUE);
10322 freeAsmop (right, NULL, ic, TRUE);
10325 /*-----------------------------------------------------------------*/
10326 /* genPagedPointerSet - emitcode for Paged pointer put */
10327 /*-----------------------------------------------------------------*/
10329 genPagedPointerSet (operand * right,
10337 sym_link *retype, *letype;
10339 D(emitcode ("; genPagedPointerSet",""));
10341 retype = getSpec (operandType (right));
10342 letype = getSpec (operandType (result));
10344 aopOp (result, ic, FALSE);
10346 /* if the value is already in a pointer register
10347 then don't need anything more */
10348 if (!AOP_INPREG (AOP (result)))
10350 /* otherwise get a free pointer register */
10351 aop = newAsmop (0);
10352 preg = getFreePtr (ic, &aop, FALSE);
10353 emitcode ("mov", "%s,%s",
10355 aopGet (result, 0, FALSE, TRUE));
10356 rname = preg->name;
10359 rname = aopGet (result, 0, FALSE, FALSE);
10361 aopOp (right, ic, FALSE);
10363 /* if bitfield then unpack the bits */
10364 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10365 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10368 /* we have can just get the values */
10369 int size = AOP_SIZE (right);
10374 l = aopGet (right, offset, FALSE, TRUE);
10377 emitcode ("movx", "@%s,a", rname);
10380 emitcode ("inc", "%s", rname);
10386 /* now some housekeeping stuff */
10387 if (aop) /* we had to allocate for this iCode */
10390 aopPut (result, rname, 0);
10391 freeAsmop (NULL, aop, ic, TRUE);
10395 /* we did not allocate which means left
10396 already in a pointer register, then
10397 if size > 0 && this could be used again
10398 we have to point it back to where it
10400 if (AOP_SIZE (right) > 1 &&
10401 !OP_SYMBOL (result)->remat &&
10402 (OP_SYMBOL (result)->liveTo > ic->seq ||
10405 int size = AOP_SIZE (right) - 1;
10407 emitcode ("dec", "%s", rname);
10412 if (pi) pi->generated = 1;
10413 freeAsmop (result, NULL, ic, TRUE);
10414 freeAsmop (right, NULL, ic, TRUE);
10417 /*-----------------------------------------------------------------*/
10418 /* genFarPointerSet - set value from far space */
10419 /*-----------------------------------------------------------------*/
10421 genFarPointerSet (operand * right,
10422 operand * result, iCode * ic, iCode * pi)
10425 sym_link *retype = getSpec (operandType (right));
10426 sym_link *letype = getSpec (operandType (result));
10428 D(emitcode ("; genFarPointerSet",""));
10430 aopOp (result, ic, FALSE);
10431 loadDptrFromOperand (result, FALSE);
10433 /* so dptr know contains the address */
10434 aopOp (right, ic, FALSE);
10436 /* if bit then unpack */
10437 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10438 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10441 size = AOP_SIZE (right);
10446 char *l = aopGet (right, offset++, FALSE, FALSE);
10448 emitcode ("movx", "@dptr,a");
10450 emitcode ("inc", "dptr");
10453 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10454 aopPut (result, "dpl", 0);
10455 aopPut (result, "dph", 1);
10458 freeAsmop (result, NULL, ic, TRUE);
10459 freeAsmop (right, NULL, ic, TRUE);
10462 /*-----------------------------------------------------------------*/
10463 /* genGenPointerSet - set value from generic pointer space */
10464 /*-----------------------------------------------------------------*/
10466 genGenPointerSet (operand * right,
10467 operand * result, iCode * ic, iCode * pi)
10470 sym_link *retype = getSpec (operandType (right));
10471 sym_link *letype = getSpec (operandType (result));
10473 D(emitcode ("; genGenPointerSet",""));
10475 aopOp (result, ic, FALSE);
10476 loadDptrFromOperand (result, TRUE);
10478 /* so dptr know contains the address */
10479 aopOp (right, ic, FALSE);
10481 /* if bit then unpack */
10482 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10483 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10486 size = AOP_SIZE (right);
10491 char *l = aopGet (right, offset++, FALSE, FALSE);
10493 emitcode ("lcall", "__gptrput");
10495 emitcode ("inc", "dptr");
10499 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10500 aopPut (result, "dpl", 0);
10501 aopPut (result, "dph", 1);
10504 freeAsmop (result, NULL, ic, TRUE);
10505 freeAsmop (right, NULL, ic, TRUE);
10508 /*-----------------------------------------------------------------*/
10509 /* genPointerSet - stores the value into a pointer location */
10510 /*-----------------------------------------------------------------*/
10512 genPointerSet (iCode * ic, iCode *pi)
10514 operand *right, *result;
10515 sym_link *type, *etype;
10518 D(emitcode ("; genPointerSet",""));
10520 right = IC_RIGHT (ic);
10521 result = IC_RESULT (ic);
10523 /* depending on the type of pointer we need to
10524 move it to the correct pointer register */
10525 type = operandType (result);
10526 etype = getSpec (type);
10527 /* if left is of type of pointer then it is simple */
10528 if (IS_PTR (type) && !IS_FUNC (type->next))
10530 p_type = DCL_TYPE (type);
10534 /* we have to go by the storage class */
10535 p_type = PTR_TYPE (SPEC_OCLS (etype));
10538 /* special case when cast remat */
10539 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10540 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10541 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10542 type = operandType (result);
10543 p_type = DCL_TYPE (type);
10545 /* now that we have the pointer type we assign
10546 the pointer values */
10552 genNearPointerSet (right, result, ic, pi);
10556 genPagedPointerSet (right, result, ic, pi);
10560 genFarPointerSet (right, result, ic, pi);
10564 genGenPointerSet (right, result, ic, pi);
10568 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10569 "genPointerSet: illegal pointer type");
10574 /*-----------------------------------------------------------------*/
10575 /* genIfx - generate code for Ifx statement */
10576 /*-----------------------------------------------------------------*/
10578 genIfx (iCode * ic, iCode * popIc)
10580 operand *cond = IC_COND (ic);
10584 D(emitcode ("; genIfx",""));
10586 aopOp (cond, ic, FALSE);
10588 /* get the value into acc */
10589 if (AOP_TYPE (cond) != AOP_CRY)
10594 if (AOP(cond)->aopu.aop_dir)
10595 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10597 /* the result is now in the accumulator or a directly addressable bit */
10598 freeAsmop (cond, NULL, ic, TRUE);
10600 /* if there was something to be popped then do it */
10604 /* if the condition is a bit variable */
10606 genIfxJump(ic, dup, NULL, NULL, NULL);
10607 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10608 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10609 else if (isbit && !IS_ITEMP (cond))
10610 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10612 genIfxJump (ic, "a", NULL, NULL, NULL);
10617 /*-----------------------------------------------------------------*/
10618 /* genAddrOf - generates code for address of */
10619 /*-----------------------------------------------------------------*/
10621 genAddrOf (iCode * ic)
10623 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10626 D(emitcode ("; genAddrOf",""));
10628 aopOp (IC_RESULT (ic), ic, FALSE);
10630 /* if the operand is on the stack then we
10631 need to get the stack offset of this
10635 /* if it has an offset then we need to compute
10639 emitcode ("mov", "a,%s", SYM_BP (sym));
10640 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
10641 ((char) (sym->stack - _G.nRegsSaved)) :
10642 ((char) sym->stack)) & 0xff);
10643 aopPut (IC_RESULT (ic), "a", 0);
10647 /* we can just move _bp */
10648 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
10650 /* fill the result with zero */
10651 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10656 aopPut (IC_RESULT (ic), zero, offset++);
10662 /* object not on stack then we need the name */
10663 size = AOP_SIZE (IC_RESULT (ic));
10668 char s[SDCC_NAME_MAX];
10670 sprintf (s, "#(%s >> %d)",
10674 sprintf (s, "#%s", sym->rname);
10675 aopPut (IC_RESULT (ic), s, offset++);
10679 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10683 /*-----------------------------------------------------------------*/
10684 /* genFarFarAssign - assignment when both are in far space */
10685 /*-----------------------------------------------------------------*/
10687 genFarFarAssign (operand * result, operand * right, iCode * ic)
10689 int size = AOP_SIZE (right);
10693 D(emitcode ("; genFarFarAssign",""));
10695 /* first push the right side on to the stack */
10698 l = aopGet (right, offset++, FALSE, FALSE);
10700 emitcode ("push", "acc");
10703 freeAsmop (right, NULL, ic, FALSE);
10704 /* now assign DPTR to result */
10705 aopOp (result, ic, FALSE);
10706 size = AOP_SIZE (result);
10709 emitcode ("pop", "acc");
10710 aopPut (result, "a", --offset);
10712 freeAsmop (result, NULL, ic, FALSE);
10715 /*-----------------------------------------------------------------*/
10716 /* genAssign - generate code for assignment */
10717 /*-----------------------------------------------------------------*/
10719 genAssign (iCode * ic)
10721 operand *result, *right;
10723 unsigned long lit = 0L;
10725 D(emitcode("; genAssign",""));
10727 result = IC_RESULT (ic);
10728 right = IC_RIGHT (ic);
10730 /* if they are the same */
10731 if (operandsEqu (result, right) &&
10732 !isOperandVolatile (result, FALSE) &&
10733 !isOperandVolatile (right, FALSE))
10736 aopOp (right, ic, FALSE);
10738 /* special case both in far space */
10739 if (AOP_TYPE (right) == AOP_DPTR &&
10740 IS_TRUE_SYMOP (result) &&
10741 isOperandInFarSpace (result))
10744 genFarFarAssign (result, right, ic);
10748 aopOp (result, ic, TRUE);
10750 /* if they are the same registers */
10751 if (sameRegs (AOP (right), AOP (result)) &&
10752 !isOperandVolatile (result, FALSE) &&
10753 !isOperandVolatile (right, FALSE))
10756 /* if the result is a bit */
10757 if (AOP_TYPE (result) == AOP_CRY)
10760 /* if the right size is a literal then
10761 we know what the value is */
10762 if (AOP_TYPE (right) == AOP_LIT)
10764 if (((int) operandLitValue (right)))
10765 aopPut (result, one, 0);
10767 aopPut (result, zero, 0);
10771 /* the right is also a bit variable */
10772 if (AOP_TYPE (right) == AOP_CRY)
10774 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10775 aopPut (result, "c", 0);
10779 /* we need to or */
10781 aopPut (result, "a", 0);
10785 /* bit variables done */
10787 size = AOP_SIZE (result);
10789 if (AOP_TYPE (right) == AOP_LIT)
10790 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10792 (AOP_TYPE (result) != AOP_REG) &&
10793 (AOP_TYPE (right) == AOP_LIT) &&
10794 !IS_FLOAT (operandType (right)) &&
10797 while ((size) && (lit))
10800 aopGet (right, offset, FALSE, FALSE),
10806 emitcode ("clr", "a");
10809 aopPut (result, "a", offset);
10818 aopGet (right, offset, FALSE, FALSE),
10825 freeAsmop (result, NULL, ic, TRUE);
10826 freeAsmop (right, NULL, ic, TRUE);
10829 /*-----------------------------------------------------------------*/
10830 /* genJumpTab - generates code for jump table */
10831 /*-----------------------------------------------------------------*/
10833 genJumpTab (iCode * ic)
10835 symbol *jtab,*jtablo,*jtabhi;
10837 unsigned int count;
10839 D(emitcode ("; genJumpTab",""));
10841 count = elementsInSet( IC_JTLABELS (ic) );
10845 /* this algorithm needs 9 cycles and 7 + 3*n bytes
10846 if the switch argument is in a register.
10847 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
10848 /* Peephole may not convert ljmp to sjmp or ret
10849 labelIsReturnOnly & labelInRange must check
10850 currPl->ic->op != JUMPTABLE */
10851 aopOp (IC_JTCOND (ic), ic, FALSE);
10852 /* get the condition into accumulator */
10853 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10855 /* multiply by three */
10856 if (aopGetUsesAcc (IC_JTCOND (ic), 0))
10858 emitcode ("mov", "b,#3");
10859 emitcode ("mul", "ab");
10863 emitcode ("add", "a,acc");
10864 emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
10866 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10868 jtab = newiTempLabel (NULL);
10869 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
10870 emitcode ("jmp", "@a+dptr");
10871 emitcode ("", "%05d$:", jtab->key + 100);
10872 /* now generate the jump labels */
10873 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10874 jtab = setNextItem (IC_JTLABELS (ic)))
10875 emitcode ("ljmp", "%05d$", jtab->key + 100);
10879 /* this algorithm needs 14 cycles and 13 + 2*n bytes
10880 if the switch argument is in a register.
10881 For n>6 this algorithm may be more compact */
10882 jtablo = newiTempLabel (NULL);
10883 jtabhi = newiTempLabel (NULL);
10885 /* get the condition into accumulator.
10886 Using b as temporary storage, if register push/pop is needed */
10887 aopOp (IC_JTCOND (ic), ic, FALSE);
10888 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10889 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
10890 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
10892 // (MB) what if B is in use???
10893 wassertl(!BINUSE, "B was in use");
10894 emitcode ("mov", "b,%s", l);
10897 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10901 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
10902 emitcode ("movc", "a,@a+pc");
10903 emitcode ("push", "acc");
10906 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
10907 emitcode ("movc", "a,@a+pc");
10908 emitcode ("push", "acc");
10912 /* this scales up to n<=255, but needs two more bytes
10913 and changes dptr */
10914 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
10915 emitcode ("movc", "a,@a+dptr");
10916 emitcode ("push", "acc");
10919 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
10920 emitcode ("movc", "a,@a+dptr");
10921 emitcode ("push", "acc");
10924 emitcode ("ret", "");
10926 /* now generate jump table, LSB */
10927 emitcode ("", "%05d$:", jtablo->key + 100);
10928 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10929 jtab = setNextItem (IC_JTLABELS (ic)))
10930 emitcode (".db", "%05d$", jtab->key + 100);
10932 /* now generate jump table, MSB */
10933 emitcode ("", "%05d$:", jtabhi->key + 100);
10934 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10935 jtab = setNextItem (IC_JTLABELS (ic)))
10936 emitcode (".db", "%05d$>>8", jtab->key + 100);
10940 /*-----------------------------------------------------------------*/
10941 /* genCast - gen code for casting */
10942 /*-----------------------------------------------------------------*/
10944 genCast (iCode * ic)
10946 operand *result = IC_RESULT (ic);
10947 sym_link *ctype = operandType (IC_LEFT (ic));
10948 sym_link *rtype = operandType (IC_RIGHT (ic));
10949 operand *right = IC_RIGHT (ic);
10952 D(emitcode("; genCast",""));
10954 /* if they are equivalent then do nothing */
10955 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10958 aopOp (right, ic, FALSE);
10959 aopOp (result, ic, FALSE);
10961 /* if the result is a bit (and not a bitfield) */
10962 // if (AOP_TYPE (result) == AOP_CRY)
10963 if (IS_BIT (OP_SYMBOL (result)->type))
10964 /* not for bitfields */
10966 /* if the right size is a literal then
10967 we know what the value is */
10968 if (AOP_TYPE (right) == AOP_LIT)
10970 if (((int) operandLitValue (right)))
10971 aopPut (result, one, 0);
10973 aopPut (result, zero, 0);
10978 /* the right is also a bit variable */
10979 if (AOP_TYPE (right) == AOP_CRY)
10981 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10982 aopPut (result, "c", 0);
10986 /* we need to or */
10988 aopPut (result, "a", 0);
10992 /* if they are the same size : or less */
10993 if (AOP_SIZE (result) <= AOP_SIZE (right))
10996 /* if they are in the same place */
10997 if (sameRegs (AOP (right), AOP (result)))
11000 /* if they in different places then copy */
11001 size = AOP_SIZE (result);
11006 aopGet (right, offset, FALSE, FALSE),
11013 /* if the result is of type pointer */
11014 if (IS_PTR (ctype))
11018 sym_link *type = operandType (right);
11019 sym_link *etype = getSpec (type);
11021 /* pointer to generic pointer */
11022 if (IS_GENPTR (ctype))
11025 p_type = DCL_TYPE (type);
11028 if (SPEC_SCLS(etype)==S_REGISTER) {
11029 // let's assume it is a generic pointer
11032 /* we have to go by the storage class */
11033 p_type = PTR_TYPE (SPEC_OCLS (etype));
11037 /* the first two bytes are known */
11038 size = GPTRSIZE - 1;
11043 aopGet (right, offset, FALSE, FALSE),
11047 /* the last byte depending on type */
11049 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11054 // pointerTypeToGPByte will have bitched.
11058 sprintf(gpValStr, "#0x%x", gpVal);
11059 aopPut (result, gpValStr, GPTRSIZE - 1);
11064 /* just copy the pointers */
11065 size = AOP_SIZE (result);
11070 aopGet (right, offset, FALSE, FALSE),
11077 /* so we now know that the size of destination is greater
11078 than the size of the source */
11079 /* we move to result for the size of source */
11080 size = AOP_SIZE (right);
11085 aopGet (right, offset, FALSE, FALSE),
11090 /* now depending on the sign of the source && destination */
11091 size = AOP_SIZE (result) - AOP_SIZE (right);
11092 /* if unsigned or not an integral type */
11093 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11096 aopPut (result, zero, offset++);
11100 /* we need to extend the sign :{ */
11101 char *l = aopGet (right, AOP_SIZE (right) - 1,
11104 emitcode ("rlc", "a");
11105 emitcode ("subb", "a,acc");
11107 aopPut (result, "a", offset++);
11110 /* we are done hurray !!!! */
11113 freeAsmop (result, NULL, ic, TRUE);
11114 freeAsmop (right, NULL, ic, TRUE);
11117 /*-----------------------------------------------------------------*/
11118 /* genDjnz - generate decrement & jump if not zero instrucion */
11119 /*-----------------------------------------------------------------*/
11121 genDjnz (iCode * ic, iCode * ifx)
11123 symbol *lbl, *lbl1;
11127 D(emitcode ("; genDjnz",""));
11129 /* if the if condition has a false label
11130 then we cannot save */
11131 if (IC_FALSE (ifx))
11134 /* if the minus is not of the form
11136 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11137 !IS_OP_LITERAL (IC_RIGHT (ic)))
11140 if (operandLitValue (IC_RIGHT (ic)) != 1)
11143 /* if the size of this greater than one then no
11145 if (getSize (operandType (IC_RESULT (ic))) > 1)
11148 /* otherwise we can save BIG */
11149 lbl = newiTempLabel (NULL);
11150 lbl1 = newiTempLabel (NULL);
11152 aopOp (IC_RESULT (ic), ic, FALSE);
11154 if (AOP_NEEDSACC(IC_RESULT(ic)))
11156 /* If the result is accessed indirectly via
11157 * the accumulator, we must explicitly write
11158 * it back after the decrement.
11160 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11162 if (strcmp(rByte, "a"))
11164 /* Something is hopelessly wrong */
11165 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11166 __FILE__, __LINE__);
11167 /* We can just give up; the generated code will be inefficient,
11168 * but what the hey.
11170 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11173 emitcode ("dec", "%s", rByte);
11174 aopPut (IC_RESULT (ic), rByte, 0);
11175 emitcode ("jnz", "%05d$", lbl->key + 100);
11177 else if (IS_AOP_PREG (IC_RESULT (ic)))
11179 emitcode ("dec", "%s",
11180 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11181 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11182 emitcode ("jnz", "%05d$", lbl->key + 100);
11186 emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11189 emitcode ("sjmp", "%05d$", lbl1->key + 100);
11190 emitcode ("", "%05d$:", lbl->key + 100);
11191 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11192 emitcode ("", "%05d$:", lbl1->key + 100);
11194 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11195 ifx->generated = 1;
11199 /*-----------------------------------------------------------------*/
11200 /* genReceive - generate code for a receive iCode */
11201 /*-----------------------------------------------------------------*/
11203 genReceive (iCode * ic)
11205 int size = getSize (operandType (IC_RESULT (ic)));
11208 D(emitcode ("; genReceive",""));
11210 if (ic->argreg == 1)
11211 { /* first parameter */
11212 if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11213 isOperandInPagedSpace (IC_RESULT (ic))) &&
11214 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11215 IS_TRUE_SYMOP (IC_RESULT (ic))))
11218 int receivingA = 0;
11221 for (offset = 0; offset<size; offset++)
11222 if (!strcmp (fReturn[offset], "a"))
11227 if (size==1 || getTempRegs(tempRegs, size-1, ic))
11229 for (offset = size-1; offset>0; offset--)
11230 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11231 emitcode("mov","a,%s", fReturn[0]);
11233 aopOp (IC_RESULT (ic), ic, FALSE);
11235 aopPut (IC_RESULT (ic), "a", offset);
11236 for (offset = 1; offset<size; offset++)
11237 aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset);
11243 if (getTempRegs(tempRegs, size, ic))
11245 for (offset = 0; offset<size; offset++)
11246 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11247 aopOp (IC_RESULT (ic), ic, FALSE);
11248 for (offset = 0; offset<size; offset++)
11249 aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset);
11254 offset = fReturnSizeMCS51 - size;
11257 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11258 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11261 aopOp (IC_RESULT (ic), ic, FALSE);
11262 size = AOP_SIZE (IC_RESULT (ic));
11266 emitcode ("pop", "acc");
11267 aopPut (IC_RESULT (ic), "a", offset++);
11273 aopOp (IC_RESULT (ic), ic, FALSE);
11275 assignResultValue (IC_RESULT (ic), NULL);
11278 else if (ic->argreg > 12)
11279 { /* bit parameters */
11280 if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
11282 aopOp (IC_RESULT (ic), ic, FALSE);
11283 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11284 outBitC(IC_RESULT (ic));
11288 { /* other parameters */
11290 aopOp (IC_RESULT (ic), ic, FALSE);
11291 rb1off = ic->argreg;
11294 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
11299 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11302 /*-----------------------------------------------------------------*/
11303 /* genDummyRead - generate code for dummy read of volatiles */
11304 /*-----------------------------------------------------------------*/
11306 genDummyRead (iCode * ic)
11311 D(emitcode("; genDummyRead",""));
11313 op = IC_RIGHT (ic);
11314 if (op && IS_SYMOP (op))
11316 aopOp (op, ic, FALSE);
11318 /* if the result is a bit */
11319 if (AOP_TYPE (op) == AOP_CRY)
11320 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11323 /* bit variables done */
11325 size = AOP_SIZE (op);
11329 MOVA (aopGet (op, offset, FALSE, FALSE));
11334 freeAsmop (op, NULL, ic, TRUE);
11338 if (op && IS_SYMOP (op))
11340 aopOp (op, ic, FALSE);
11342 /* if the result is a bit */
11343 if (AOP_TYPE (op) == AOP_CRY)
11344 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11347 /* bit variables done */
11349 size = AOP_SIZE (op);
11353 MOVA (aopGet (op, offset, FALSE, FALSE));
11358 freeAsmop (op, NULL, ic, TRUE);
11362 /*-----------------------------------------------------------------*/
11363 /* genCritical - generate code for start of a critical sequence */
11364 /*-----------------------------------------------------------------*/
11366 genCritical (iCode *ic)
11368 symbol *tlbl = newiTempLabel (NULL);
11370 D(emitcode("; genCritical",""));
11372 if (IC_RESULT (ic))
11374 aopOp (IC_RESULT (ic), ic, TRUE);
11375 aopPut (IC_RESULT (ic), one, 0);
11376 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11377 aopPut (IC_RESULT (ic), zero, 0);
11378 emitcode ("", "%05d$:", (tlbl->key + 100));
11379 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11383 emitcode ("setb", "c");
11384 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11385 emitcode ("clr", "c");
11386 emitcode ("", "%05d$:", (tlbl->key + 100));
11387 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11391 /*-----------------------------------------------------------------*/
11392 /* genEndCritical - generate code for end of a critical sequence */
11393 /*-----------------------------------------------------------------*/
11395 genEndCritical (iCode *ic)
11397 D(emitcode("; genEndCritical",""));
11401 aopOp (IC_RIGHT (ic), ic, FALSE);
11402 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11404 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11405 emitcode ("mov", "ea,c");
11409 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11410 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11411 emitcode ("rrc", "a");
11412 emitcode ("mov", "ea,c");
11414 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11418 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11419 emitcode ("mov", "ea,c");
11423 /*-----------------------------------------------------------------*/
11424 /* gen51Code - generate code for 8051 based controllers */
11425 /*-----------------------------------------------------------------*/
11427 gen51Code (iCode * lic)
11431 /* int cseq = 0; */
11433 _G.currentFunc = NULL;
11434 lineHead = lineCurr = NULL;
11436 /* print the allocation information */
11437 if (allocInfo && currFunc)
11438 printAllocInfo (currFunc, codeOutFile);
11439 /* if debug information required */
11440 if (options.debug && currFunc)
11442 debugFile->writeFunction (currFunc, lic);
11444 /* stack pointer name */
11445 if (options.useXstack)
11451 for (ic = lic; ic; ic = ic->next)
11453 _G.current_iCode = ic;
11455 if (ic->lineno && cln != ic->lineno)
11459 debugFile->writeCLine (ic);
11461 if (!options.noCcodeInAsm) {
11462 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
11463 printCLine(ic->filename, ic->lineno));
11468 if (ic->seqPoint && ic->seqPoint != cseq)
11470 emitcode ("", "; sequence point %d", ic->seqPoint);
11471 cseq = ic->seqPoint;
11474 if (options.iCodeInAsm) {
11475 char regsInUse[80];
11479 for (i=0; i<8; i++) {
11480 sprintf (®sInUse[i],
11481 "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11484 strcpy (regsInUse, "--------");
11485 for (i=0; i < 8; i++) {
11486 if (bitVectBitValue (ic->rMask, i))
11488 int offset = regs8051[i].offset;
11489 regsInUse[offset] = offset + '0'; /* show rMask */
11493 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
11495 /* if the result is marked as
11496 spilt and rematerializable or code for
11497 this has already been generated then
11499 if (resultRemat (ic) || ic->generated)
11502 /* depending on the operation */
11522 /* IPOP happens only when trying to restore a
11523 spilt live range, if there is an ifx statement
11524 following this pop then the if statement might
11525 be using some of the registers being popped which
11526 would destory the contents of the register so
11527 we need to check for this condition and handle it */
11529 ic->next->op == IFX &&
11530 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11531 genIfx (ic->next, ic);
11549 genEndFunction (ic);
11569 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11586 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11590 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11597 /* note these two are xlated by algebraic equivalence
11598 during parsing SDCC.y */
11599 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11600 "got '>=' or '<=' shouldn't have come here");
11604 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11616 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11620 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11624 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11660 genRightShift (ic);
11663 case GET_VALUE_AT_ADDRESS:
11665 hasInc (IC_LEFT (ic), ic,
11666 getSize (operandType (IC_RESULT (ic)))),
11667 ifxForOp (IC_RESULT (ic), ic) );
11671 if (POINTER_SET (ic))
11672 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
11698 addSet (&_G.sendSet, ic);
11701 case DUMMY_READ_VOLATILE:
11710 genEndCritical (ic);
11722 _G.current_iCode = NULL;
11724 /* now we are ready to call the
11725 peep hole optimizer */
11726 if (!options.nopeep)
11727 peepHole (&lineHead);
11729 /* now do the actual printing */
11730 printLine (lineHead, codeOutFile);