1 /*-------------------------------------------------------------------------
2 gen.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 -------------------------------------------------------------------------*/
31 #define D(x) do if (options.verboseAsm) {x;} while(0)
37 #include "SDCCglobl.h"
41 #include "SDCCpeeph.h"
45 #include "dbuf_string.h"
47 char *aopLiteral (value * val, int offset);
48 char *aopLiteralLong (value * val, int offset, int size);
51 /* this is the down and dirty file with all kinds of
52 kludgy & hacky stuff. This is what it is all about
53 CODE GENERATION for a specific MCU . some of the
54 routines may be reusable, will have to see */
56 static char *zero = "#0x00";
57 static char *one = "#0x01";
61 {"dpl", "dph", "b", "a"};
62 unsigned fReturnSizeMCS51 = 4; /* shared with ralloc.c */
63 char **fReturn = fReturn8051;
64 static char *accUse[] =
67 static unsigned short rbank = -1;
69 #define REG_WITH_INDEX mcs51_regWithIdx
71 #define AOP(op) op->aop
72 #define AOP_TYPE(op) AOP(op)->type
73 #define AOP_SIZE(op) AOP(op)->size
74 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
75 AOP_TYPE(x) == AOP_R0))
77 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
78 AOP_TYPE(x) == AOP_DPTR || \
81 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
82 (x->aopu.aop_reg[0] == REG_WITH_INDEX(R0_IDX) || \
83 x->aopu.aop_reg[0] == REG_WITH_INDEX(R1_IDX) )))
85 #define SYM_BP(sym) (SPEC_OCLS (sym->etype)->paged ? "_bpx" : "_bp")
87 #define R0INB _G.bu.bs.r0InB
88 #define R1INB _G.bu.bs.r1InB
89 #define OPINB _G.bu.bs.OpInB
90 #define BINUSE _G.bu.BInUse
100 short r0InB : 2;//2 so we can see it overflow
101 short r1InB : 2;//2 so we can see it overflow
102 short OpInB : 2;//2 so we can see it overflow
111 iCode *current_iCode;
116 static char *rb1regs[] = {
117 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7",
118 "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7"
121 extern struct dbuf_s *codeOutBuf;
123 #define RESULTONSTACK(x) \
124 (IC_RESULT(x) && IC_RESULT(x)->aop && \
125 IC_RESULT(x)->aop->type == AOP_STK )
127 #define MOVA(x) mova(x) /* use function to avoid multiple eval */
128 #define MOVB(x) movb(x)
130 #define CLRC emitcode("clr","c")
131 #define SETC emitcode("setb","c")
133 static lineNode *lineHead = NULL;
134 static lineNode *lineCurr = NULL;
136 static unsigned char SLMask[] =
137 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
138 0xE0, 0xC0, 0x80, 0x00};
139 static unsigned char SRMask[] =
140 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
141 0x07, 0x03, 0x01, 0x00};
148 /*-----------------------------------------------------------------*/
149 /* emitcode - writes the code into a file : for now it is simple */
150 /*-----------------------------------------------------------------*/
152 emitcode (const char *inst, const char *fmt,...)
156 const char *lbp, *lb;
158 dbuf_init (&dbuf, INITIAL_INLINEASM);
164 dbuf_append_str (&dbuf, inst);
168 dbuf_append_char (&dbuf, '\t');
169 dbuf_tvprintf (&dbuf, fmt, ap);
174 dbuf_tvprintf (&dbuf, fmt, ap);
177 lbp = lb = dbuf_c_str(&dbuf);
179 while (isspace ((unsigned char)*lbp))
188 lineCurr = (lineCurr ?
189 connectLine (lineCurr, newLineNode (lb)) :
190 (lineHead = newLineNode (lb)));
192 lineCurr->isInline = _G.inLine;
193 lineCurr->isDebug = _G.debugLine;
194 lineCurr->ic = _G.current_iCode;
195 lineCurr->isComment = (*lbp==';');
204 emitLabel (symbol *tlbl)
206 emitcode ("", "%05d$:", tlbl->key + 100);
207 lineCurr->isLabel = 1;
210 /*-----------------------------------------------------------------*/
211 /* mcs51_emitDebuggerSymbol - associate the current code location */
212 /* with a debugger symbol */
213 /*-----------------------------------------------------------------*/
215 mcs51_emitDebuggerSymbol (char * debugSym)
218 emitcode ("", "%s ==.", debugSym);
222 /*-----------------------------------------------------------------*/
223 /* mova - moves specified value into accumulator */
224 /*-----------------------------------------------------------------*/
228 /* do some early peephole optimization */
229 if (!strncmp(x, "a", 2) || !strncmp(x, "acc", 4))
232 /* if it is a literal mov try to get it cheaper */
237 emitcode("mov", "a,%s", x);
240 /*-----------------------------------------------------------------*/
241 /* movb - moves specified value into register b */
242 /*-----------------------------------------------------------------*/
246 /* do some early peephole optimization */
247 if (!strncmp(x, "b", 2))
250 /* if it is a literal mov try to get it cheaper */
253 emitcode("mov","b,%s", rtrackGetLit(x));
257 emitcode("mov","b,%s", x);
260 /*-----------------------------------------------------------------*/
261 /* pushB - saves register B if necessary */
262 /*-----------------------------------------------------------------*/
266 bool pushedB = FALSE;
270 emitcode ("push", "b");
271 // printf("B was in use !\n");
281 /*-----------------------------------------------------------------*/
282 /* popB - restores value of register B if necessary */
283 /*-----------------------------------------------------------------*/
289 emitcode ("pop", "b");
297 /*-----------------------------------------------------------------*/
298 /* pushReg - saves register */
299 /*-----------------------------------------------------------------*/
301 pushReg (int index, bool bits_pushed)
303 regs * reg = REG_WITH_INDEX (index);
304 if (reg->type == REG_BIT)
307 emitcode ("push", "%s", reg->base);
311 emitcode ("push", "%s", reg->dname);
315 /*-----------------------------------------------------------------*/
316 /* popReg - restores register */
317 /*-----------------------------------------------------------------*/
319 popReg (int index, bool bits_popped)
321 regs * reg = REG_WITH_INDEX (index);
322 if (reg->type == REG_BIT)
325 emitcode ("pop", "%s", reg->base);
329 emitcode ("pop", "%s", reg->dname);
333 /*-----------------------------------------------------------------*/
334 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
335 /*-----------------------------------------------------------------*/
337 getFreePtr (iCode * ic, asmop ** aopp, bool result)
342 /* the logic: if r0 & r1 used in the instruction
343 then we are in trouble otherwise */
345 /* first check if r0 & r1 are used by this
346 instruction, in which case we are in trouble */
347 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
348 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
353 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
354 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
356 /* if no usage of r0 then return it */
359 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
360 (*aopp)->type = AOP_R0;
362 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
365 /* if no usage of r1 then return it */
368 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
369 (*aopp)->type = AOP_R1;
371 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R1_IDX);
374 /* now we know they both have usage */
375 /* if r0 not used in this instruction */
378 /* push it if not already pushed */
381 MOVB (REG_WITH_INDEX (R0_IDX)->dname);
384 else if (!_G.r0Pushed)
386 emitcode ("push", "%s",
387 REG_WITH_INDEX (R0_IDX)->dname);
391 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
392 (*aopp)->type = AOP_R0;
394 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
397 /* if r1 not used then */
401 /* push it if not already pushed */
404 MOVB (REG_WITH_INDEX (R1_IDX)->dname);
407 else if (!_G.r1Pushed)
409 emitcode ("push", "%s",
410 REG_WITH_INDEX (R1_IDX)->dname);
414 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
415 (*aopp)->type = AOP_R1;
416 return REG_WITH_INDEX (R1_IDX);
420 /* I said end of world, but not quite end of world yet */
421 /* if this is a result then we can push it on the stack */
424 (*aopp)->type = AOP_STK;
427 /* in the case that result AND left AND right needs a pointer reg
428 we can safely use the result's */
429 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX))
431 (*aopp)->type = AOP_R0;
432 return REG_WITH_INDEX (R0_IDX);
434 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX))
436 (*aopp)->type = AOP_R1;
437 return REG_WITH_INDEX (R1_IDX);
440 /* now this is REALLY the end of the world */
441 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
442 "getFreePtr should never reach here");
447 /*-----------------------------------------------------------------*/
448 /* getTempRegs - initialize an array of pointers to GPR registers */
449 /* that are not in use. Returns 1 if the requested */
450 /* number of registers were available, 0 otherwise. */
451 /*-----------------------------------------------------------------*/
453 getTempRegs(regs **tempRegs, int size, iCode *ic)
460 ic = _G.current_iCode;
466 freeRegs = newBitVect(8);
467 bitVectSetBit (freeRegs, R2_IDX);
468 bitVectSetBit (freeRegs, R3_IDX);
469 bitVectSetBit (freeRegs, R4_IDX);
470 bitVectSetBit (freeRegs, R5_IDX);
471 bitVectSetBit (freeRegs, R6_IDX);
472 bitVectSetBit (freeRegs, R7_IDX);
474 if (IFFUNC_CALLEESAVES(_G.currentFunc->type))
476 bitVect * newfreeRegs;
477 newfreeRegs = bitVectIntersect (freeRegs, _G.currentFunc->regsUsed);
478 freeBitVect(freeRegs);
479 freeRegs = newfreeRegs;
481 freeRegs = bitVectCplAnd (freeRegs, ic->rMask);
484 for (i=0; i<freeRegs->size; i++)
486 if (bitVectBitValue(freeRegs,i))
487 tempRegs[offset++] = REG_WITH_INDEX(i);
490 freeBitVect(freeRegs);
495 freeBitVect(freeRegs);
500 /*-----------------------------------------------------------------*/
501 /* newAsmop - creates a new asmOp */
502 /*-----------------------------------------------------------------*/
504 newAsmop (short type)
508 aop = Safe_calloc (1, sizeof (asmop));
514 /*-----------------------------------------------------------------*/
515 /* pointerCode - returns the code for a pointer type */
516 /*-----------------------------------------------------------------*/
518 pointerCode (sym_link * etype)
521 return PTR_TYPE (SPEC_OCLS (etype));
525 /*-----------------------------------------------------------------*/
526 /* leftRightUseAcc - returns size of accumulator use by operands */
527 /*-----------------------------------------------------------------*/
529 leftRightUseAcc(iCode *ic)
538 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
539 "null iCode pointer");
546 if (IS_OP_ACCUSE (op))
549 size = getSize (OP_SYMBOL (op)->type);
554 else if (ic->op == JUMPTABLE)
557 if (IS_OP_ACCUSE (op))
560 size = getSize (OP_SYMBOL (op)->type);
568 if (IS_OP_ACCUSE (op))
571 size = getSize (OP_SYMBOL (op)->type);
576 if (IS_OP_ACCUSE (op))
579 size = getSize (OP_SYMBOL (op)->type);
591 /*-----------------------------------------------------------------*/
592 /* aopForSym - for a true symbol */
593 /*-----------------------------------------------------------------*/
595 aopForSym (iCode * ic, symbol * sym, bool result)
599 bool accuse = leftRightUseAcc (ic) || _G.accInUse;
601 wassertl (ic != NULL, "Got a null iCode");
602 wassertl (sym != NULL, "Got a null symbol");
604 space = SPEC_OCLS (sym->etype);
606 /* if already has one */
609 sym->aop->allocated++;
613 /* assign depending on the storage class */
614 /* if it is on the stack or indirectly addressable */
615 /* space we need to assign either r0 or r1 to it */
616 if (sym->onStack || sym->iaccess)
618 sym->aop = aop = newAsmop (0);
619 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
620 aop->size = getSize (sym->type);
622 /* now assign the address of the variable to
623 the pointer register */
624 if (aop->type != AOP_STK)
628 signed char offset = ((sym->stack < 0) ?
629 ((signed char) (sym->stack - _G.nRegsSaved)) :
630 ((signed char) sym->stack)) & 0xff;
632 if ((abs(offset) <= 3) ||
633 (accuse && (abs(offset) <= 7)))
635 emitcode ("mov", "%s,%s",
636 aop->aopu.aop_ptr->name, SYM_BP (sym));
639 emitcode ("dec", aop->aopu.aop_ptr->name);
644 emitcode ("inc", aop->aopu.aop_ptr->name);
651 emitcode ("push", "acc");
652 emitcode ("mov", "a,%s", SYM_BP (sym));
653 emitcode ("add", "a,#0x%02x", offset & 0xff);
654 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
656 emitcode ("pop", "acc");
661 emitcode ("mov", "%s,#%s",
662 aop->aopu.aop_ptr->name,
665 aop->paged = space->paged;
668 aop->aopu.aop_stk = sym->stack;
672 /* if in bit space */
673 if (IN_BITSPACE (space))
675 sym->aop = aop = newAsmop (AOP_CRY);
676 aop->aopu.aop_dir = sym->rname;
677 aop->size = getSize (sym->type);
680 /* if it is in direct space */
681 if (IN_DIRSPACE (space))
683 //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
684 //printTypeChainRaw(sym->type, NULL);
685 //printf("space = %s\n", space ? space->sname : "NULL");
686 sym->aop = aop = newAsmop (AOP_DIR);
687 aop->aopu.aop_dir = sym->rname;
688 aop->size = getSize (sym->type);
692 /* special case for a function */
693 if (IS_FUNC (sym->type))
695 sym->aop = aop = newAsmop (AOP_IMMD);
696 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
697 aop->size = getSize (sym->type);
701 /* only remaining is far space */
702 /* in which case DPTR gets the address */
703 sym->aop = aop = newAsmop (AOP_DPTR);
704 emitcode ("mov", "dptr,#%s", sym->rname);
705 aop->size = getSize (sym->type);
707 /* if it is in code space */
708 if (IN_CODESPACE (space))
714 /*-----------------------------------------------------------------*/
715 /* aopForRemat - rematerializes an object */
716 /*-----------------------------------------------------------------*/
718 aopForRemat (symbol * sym)
720 iCode *ic = sym->rematiCode;
721 asmop *aop = newAsmop (AOP_IMMD);
728 val += (int) operandLitValue (IC_RIGHT (ic));
729 else if (ic->op == '-')
730 val -= (int) operandLitValue (IC_RIGHT (ic));
731 else if (IS_CAST_ICODE(ic))
733 sym_link *from_type = operandType(IC_RIGHT(ic));
734 aop->aopu.aop_immd.from_cast_remat = 1;
735 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
736 ptr_type = pointerTypeToGPByte (DCL_TYPE(from_type), NULL, NULL);
741 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
746 SNPRINTF (buffer, sizeof(buffer),
748 OP_SYMBOL (IC_LEFT (ic))->rname,
749 val >= 0 ? '+' : '-',
754 strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
757 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
758 /* set immd2 field if required */
759 if (aop->aopu.aop_immd.from_cast_remat)
761 SNPRINTF (buffer, sizeof(buffer), "#0x%02x", ptr_type);
762 aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
768 /*-----------------------------------------------------------------*/
769 /* regsInCommon - two operands have some registers in common */
770 /*-----------------------------------------------------------------*/
772 regsInCommon (operand * op1, operand * op2)
777 /* if they have registers in common */
778 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
781 sym1 = OP_SYMBOL (op1);
782 sym2 = OP_SYMBOL (op2);
784 if (sym1->nRegs == 0 || sym2->nRegs == 0)
787 for (i = 0; i < sym1->nRegs; i++)
793 for (j = 0; j < sym2->nRegs; j++)
798 if (sym2->regs[j] == sym1->regs[i])
806 /*-----------------------------------------------------------------*/
807 /* operandsEqu - equivalent */
808 /*-----------------------------------------------------------------*/
810 operandsEqu (operand * op1, operand * op2)
814 /* if they're not symbols */
815 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
818 sym1 = OP_SYMBOL (op1);
819 sym2 = OP_SYMBOL (op2);
821 /* if both are itemps & one is spilt
822 and the other is not then false */
823 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
824 sym1->isspilt != sym2->isspilt)
827 /* if they are the same */
831 /* if they have the same rname */
832 if (sym1->rname[0] && sym2->rname[0] &&
833 strcmp (sym1->rname, sym2->rname) == 0 &&
834 !(IS_PARM (op2) && IS_ITEMP (op1)))
837 /* if left is a tmp & right is not */
838 if (IS_ITEMP (op1) &&
841 (sym1->usl.spillLoc == sym2))
844 if (IS_ITEMP (op2) &&
848 (sym2->usl.spillLoc == sym1))
854 /*-----------------------------------------------------------------*/
855 /* sameByte - two asmops have the same address at given offsets */
856 /*-----------------------------------------------------------------*/
858 sameByte (asmop * aop1, int off1, asmop * aop2, int off2)
860 if (aop1 == aop2 && off1 == off2)
863 if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
866 if (aop1->type != aop2->type)
869 if (aop1->aopu.aop_reg[off1] != aop2->aopu.aop_reg[off2])
875 /*-----------------------------------------------------------------*/
876 /* sameRegs - two asmops have the same registers */
877 /*-----------------------------------------------------------------*/
879 sameRegs (asmop * aop1, asmop * aop2)
886 if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
889 if (aop1->type != aop2->type)
892 if (aop1->size != aop2->size)
895 for (i = 0; i < aop1->size; i++)
896 if (aop1->aopu.aop_reg[i] != aop2->aopu.aop_reg[i])
902 /*-----------------------------------------------------------------*/
903 /* aopOp - allocates an asmop for an operand : */
904 /*-----------------------------------------------------------------*/
906 aopOp (operand * op, iCode * ic, bool result)
915 /* if this a literal */
916 if (IS_OP_LITERAL (op))
918 op->aop = aop = newAsmop (AOP_LIT);
919 aop->aopu.aop_lit = op->operand.valOperand;
920 aop->size = getSize (operandType (op));
924 /* if already has a asmop then continue */
927 op->aop->allocated++;
931 /* if the underlying symbol has a aop */
932 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
934 op->aop = OP_SYMBOL (op)->aop;
935 op->aop->allocated++;
939 /* if this is a true symbol */
940 if (IS_TRUE_SYMOP (op))
942 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
946 /* this is a temporary : this has
952 e) can be a return use only */
954 sym = OP_SYMBOL (op);
956 /* if the type is a conditional */
957 if (sym->regType == REG_CND)
959 sym->aop = op->aop = aop = newAsmop (AOP_CRY);
960 aop->size = sym->ruonly ? 1 : 0;
964 /* if it is spilt then two situations
966 b) has a spill location */
967 if (sym->isspilt || sym->nRegs == 0)
970 /* rematerialize it NOW */
973 sym->aop = op->aop = aop = aopForRemat (sym);
974 aop->size = operandSize (op);
981 sym->aop = op->aop = aop = newAsmop (AOP_ACC);
982 aop->size = getSize (sym->type);
983 for (i = 0; i < 2; i++)
984 aop->aopu.aop_str[i] = accUse[i];
992 sym->aop = op->aop = aop = newAsmop (AOP_STR);
993 aop->size = getSize (sym->type);
994 for (i = 0; i < fReturnSizeMCS51; i++)
995 aop->aopu.aop_str[i] = fReturn[i];
999 if (sym->usl.spillLoc)
1001 asmop *oldAsmOp = NULL;
1003 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1005 /* force a new aop if sizes differ */
1006 oldAsmOp = sym->usl.spillLoc->aop;
1007 sym->usl.spillLoc->aop = NULL;
1009 sym->aop = op->aop = aop =
1010 aopForSym (ic, sym->usl.spillLoc, result);
1011 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1013 /* Don't reuse the new aop, go with the last one */
1014 sym->usl.spillLoc->aop = oldAsmOp;
1016 aop->size = getSize (sym->type);
1020 /* else must be a dummy iTemp */
1021 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1022 aop->size = getSize (sym->type);
1026 /* if the type is a bit register */
1027 if (sym->regType == REG_BIT)
1029 sym->aop = op->aop = aop = newAsmop (AOP_CRY);
1030 aop->size = sym->nRegs;//1???
1031 aop->aopu.aop_reg[0] = sym->regs[0];
1032 aop->aopu.aop_dir = sym->regs[0]->name;
1036 /* must be in a register */
1037 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1038 aop->size = sym->nRegs;
1039 for (i = 0; i < sym->nRegs; i++)
1040 aop->aopu.aop_reg[i] = sym->regs[i];
1043 /*-----------------------------------------------------------------*/
1044 /* freeAsmop - free up the asmop given to an operand */
1045 /*----------------------------------------------------------------*/
1047 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1064 /* depending on the asmop type only three cases need work
1065 AOP_R0, AOP_R1 & AOP_STK */
1071 emitcode ("mov", "r0,b");
1074 else if (_G.r0Pushed)
1078 emitcode ("pop", "ar0");
1082 bitVectUnSetBit (ic->rUsed, R0_IDX);
1088 emitcode ("mov", "r1,b");
1091 else if (_G.r1Pushed)
1095 emitcode ("pop", "ar1");
1099 bitVectUnSetBit (ic->rUsed, R1_IDX);
1105 int stk = aop->aopu.aop_stk + aop->size - 1;
1106 bitVectUnSetBit (ic->rUsed, R0_IDX);
1107 bitVectUnSetBit (ic->rUsed, R1_IDX);
1109 getFreePtr (ic, &aop, FALSE);
1113 emitcode ("mov", "a,_bp");
1114 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1115 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1119 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1124 emitcode ("pop", "acc");
1125 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1128 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1131 freeAsmop (op, NULL, ic, TRUE);
1134 emitcode ("pop", "ar1");
1139 emitcode ("pop", "ar0");
1147 /* all other cases just dealloc */
1153 OP_SYMBOL (op)->aop = NULL;
1154 /* if the symbol has a spill */
1156 SPIL_LOC (op)->aop = NULL;
1161 /*------------------------------------------------------------------*/
1162 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
1163 /* pop r0 or r1 off stack if pushed */
1164 /*------------------------------------------------------------------*/
1166 freeForBranchAsmop (operand * op)
1178 if (!aop->allocated)
1186 emitcode ("mov", "r0,b");
1188 else if (_G.r0Pushed)
1190 emitcode ("pop", "ar0");
1197 emitcode ("mov", "r1,b");
1199 else if (_G.r1Pushed)
1201 emitcode ("pop", "ar1");
1208 int stk = aop->aopu.aop_stk + aop->size - 1;
1210 emitcode ("mov", "b,r0");
1213 emitcode ("mov", "a,_bp");
1214 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1215 emitcode ("mov", "r0,a");
1219 emitcode ("mov", "r0,_bp");
1224 emitcode ("pop", "acc");
1225 emitcode ("mov", "@r0,a");
1228 emitcode ("dec", "r0");
1230 emitcode ("mov", "r0,b");
1236 /*-----------------------------------------------------------------*/
1237 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
1238 /* clobber the accumulator */
1239 /*-----------------------------------------------------------------*/
1241 aopGetUsesAcc (operand * oper, int offset)
1243 asmop * aop = AOP (oper);
1245 if (offset > (aop->size - 1))
1263 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1274 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1280 /* Error case --- will have been caught already */
1286 /*-------------------------------------------------------------------*/
1287 /* aopGet - for fetching value of the aop */
1288 /*-------------------------------------------------------------------*/
1290 aopGet (operand * oper, int offset, bool bit16, bool dname)
1292 asmop * aop = AOP (oper);
1294 /* offset is greater than
1296 if (offset > (aop->size - 1) &&
1297 aop->type != AOP_LIT)
1300 /* depending on type */
1308 /* if we need to increment it */
1309 while (offset > aop->coff)
1311 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1315 while (offset < aop->coff)
1317 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1324 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1325 return (dname ? "acc" : "a");
1327 SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1328 return Safe_strdup(buffer);
1331 if (aop->code && aop->coff==0 && offset>=1) {
1332 emitcode ("mov", "a,#0x%02x", offset);
1333 emitcode ("movc", "a,@a+dptr");
1334 return (dname ? "acc" : "a");
1337 while (offset > aop->coff)
1339 emitcode ("inc", "dptr");
1343 while (offset < aop->coff)
1345 emitcode ("lcall", "__decdptr");
1352 emitcode ("clr", "a");
1353 emitcode ("movc", "a,@a+dptr");
1357 emitcode ("movx", "a,@dptr");
1359 return (dname ? "acc" : "a");
1362 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1364 SNPRINTF(buffer, sizeof(buffer),
1365 "%s",aop->aopu.aop_immd.aop_immd2);
1369 SNPRINTF(buffer, sizeof(buffer),
1370 "#%s", aop->aopu.aop_immd.aop_immd1);
1374 SNPRINTF (buffer, sizeof(buffer),
1376 aop->aopu.aop_immd.aop_immd1,
1381 SNPRINTF (buffer, sizeof(buffer),
1383 aop->aopu.aop_immd.aop_immd1);
1385 return Safe_strdup(buffer);
1388 if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
1390 SNPRINTF (buffer, sizeof(buffer),
1392 aop->aopu.aop_dir, offset * 8);
1396 SNPRINTF (buffer, sizeof(buffer),
1403 SNPRINTF (buffer, sizeof(buffer),
1408 return Safe_strdup(buffer);
1412 return aop->aopu.aop_reg[offset]->dname;
1414 return aop->aopu.aop_reg[offset]->name;
1417 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1418 emitcode ("clr", "a");
1419 emitcode ("rlc", "a");
1420 return (dname ? "acc" : "a");
1423 if (!offset && dname)
1425 return aop->aopu.aop_str[offset];
1428 return aopLiteral (aop->aopu.aop_lit, offset);
1432 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1436 return aop->aopu.aop_str[offset];
1440 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1441 "aopget got unsupported aop->type");
1445 /*-----------------------------------------------------------------*/
1446 /* aopPutUsesAcc - indicates ahead of time whether aopPut() will */
1447 /* clobber the accumulator */
1448 /*-----------------------------------------------------------------*/
1450 aopPutUsesAcc (operand * oper, const char *s, int offset)
1452 asmop * aop = AOP (oper);
1454 if (offset > (aop->size - 1))
1464 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1470 return ((aop->paged) || (*s == '@'));
1474 return (!aop->aopu.aop_dir || strcmp(s, aop->aopu.aop_dir));
1482 /* Error case --- will have been caught already */
1488 /*-----------------------------------------------------------------*/
1489 /* aopPut - puts a string for a aop and indicates if acc is in use */
1490 /*-----------------------------------------------------------------*/
1492 aopPut (operand * result, const char *s, int offset)
1494 bool bvolatile = isOperandVolatile (result, FALSE);
1495 bool accuse = FALSE;
1496 asmop * aop = AOP (result);
1497 const char *d = NULL;
1499 if (aop->size && offset > (aop->size - 1))
1501 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1502 "aopPut got offset > aop->size");
1506 /* will assign value to value */
1507 /* depending on where it is ofcourse */
1511 MOVA (s); /* read s in case it was volatile */
1516 if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1518 SNPRINTF (buffer, sizeof(buffer),
1520 aop->aopu.aop_dir, offset * 8);
1524 SNPRINTF (buffer, sizeof(buffer),
1526 aop->aopu.aop_dir, offset);
1530 SNPRINTF (buffer, sizeof(buffer),
1535 if (strcmp (buffer, s) || bvolatile)
1537 emitcode ("mov", "%s,%s", buffer, s);
1539 if (!strcmp (buffer, "acc"))
1546 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1547 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1550 strcmp (s, "r0") == 0 ||
1551 strcmp (s, "r1") == 0 ||
1552 strcmp (s, "r2") == 0 ||
1553 strcmp (s, "r3") == 0 ||
1554 strcmp (s, "r4") == 0 ||
1555 strcmp (s, "r5") == 0 ||
1556 strcmp (s, "r6") == 0 ||
1557 strcmp (s, "r7") == 0)
1559 emitcode ("mov", "%s,%s",
1560 aop->aopu.aop_reg[offset]->dname, s);
1564 emitcode ("mov", "%s,%s",
1565 aop->aopu.aop_reg[offset]->name, s);
1573 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1574 "aopPut writing to code space");
1578 while (offset > aop->coff)
1581 emitcode ("inc", "dptr");
1584 while (offset < aop->coff)
1587 emitcode ("lcall", "__decdptr");
1592 /* if not in accumulator */
1595 emitcode ("movx", "@dptr,a");
1600 while (offset > aop->coff)
1603 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1605 while (offset < aop->coff)
1608 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1615 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1620 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1622 else if (strcmp (s, "r0") == 0 ||
1623 strcmp (s, "r1") == 0 ||
1624 strcmp (s, "r2") == 0 ||
1625 strcmp (s, "r3") == 0 ||
1626 strcmp (s, "r4") == 0 ||
1627 strcmp (s, "r5") == 0 ||
1628 strcmp (s, "r6") == 0 ||
1629 strcmp (s, "r7") == 0)
1632 SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1633 emitcode ("mov", "@%s,%s",
1634 aop->aopu.aop_ptr->name, buffer);
1638 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1643 if (strcmp (s, "a") == 0)
1645 emitcode ("push", "acc");
1650 emitcode ("push", "acc");
1652 else if (strcmp (s, "r0") == 0 ||
1653 strcmp (s, "r1") == 0 ||
1654 strcmp (s, "r2") == 0 ||
1655 strcmp (s, "r3") == 0 ||
1656 strcmp (s, "r4") == 0 ||
1657 strcmp (s, "r5") == 0 ||
1658 strcmp (s, "r6") == 0 ||
1659 strcmp (s, "r7") == 0)
1662 SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1663 emitcode ("push", buffer);
1667 emitcode ("push", s);
1673 // destination is carry for return-use-only
1674 d = (IS_OP_RUONLY (result)) ? "c" : aop->aopu.aop_dir;
1675 // source is no literal and not in carry
1676 if ((s != zero) && (s != one) && strcmp (s, "c"))
1679 /* set C, if a >= 1 */
1680 emitcode ("add", "a,#0xff");
1683 // now source is zero, one or carry
1685 /* if result no bit variable */
1688 if (!strcmp (s, "c"))
1690 /* inefficient: move carry into A and use jz/jnz */
1691 emitcode ("clr", "a");
1692 emitcode ("rlc", "a");
1702 emitcode ("clr", "%s", d);
1704 emitcode ("setb", "%s", d);
1705 else if (strcmp (s, d))
1706 emitcode ("mov", "%s,c", d);
1711 if (strcmp (aop->aopu.aop_str[offset], s) || bvolatile)
1712 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1718 if (!offset && (strcmp (s, "acc") == 0) && !bvolatile)
1721 if (strcmp (aop->aopu.aop_str[offset], s) && !bvolatile)
1722 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1726 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1727 "aopPut got unsupported aop->type");
1736 /*-----------------------------------------------------------------*/
1737 /* pointToEnd :- points to the last byte of the operand */
1738 /*-----------------------------------------------------------------*/
1740 pointToEnd (asmop * aop)
1746 aop->coff = count = (aop->size - 1);
1752 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1756 emitcode ("inc", "dptr");
1763 /*-----------------------------------------------------------------*/
1764 /* reAdjustPreg - points a register back to where it should */
1765 /*-----------------------------------------------------------------*/
1767 reAdjustPreg (asmop * aop)
1769 if ((aop->coff==0) || (aop->size <= 1))
1777 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1782 emitcode ("lcall", "__decdptr");
1789 /*-----------------------------------------------------------------*/
1790 /* opIsGptr: returns non-zero if the passed operand is */
1791 /* a generic pointer type. */
1792 /*-----------------------------------------------------------------*/
1794 opIsGptr (operand * op)
1796 sym_link *type = operandType (op);
1798 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1805 /*-----------------------------------------------------------------*/
1806 /* getDataSize - get the operand data size */
1807 /*-----------------------------------------------------------------*/
1809 getDataSize (operand * op)
1812 size = AOP_SIZE (op);
1813 if (size == GPTRSIZE)
1815 sym_link *type = operandType (op);
1816 if (IS_GENPTR (type))
1818 /* generic pointer; arithmetic operations
1819 * should ignore the high byte (pointer type).
1827 /*-----------------------------------------------------------------*/
1828 /* outAcc - output Acc */
1829 /*-----------------------------------------------------------------*/
1831 outAcc (operand * result)
1834 size = getDataSize (result);
1837 aopPut (result, "a", 0);
1840 /* unsigned or positive */
1843 aopPut (result, zero, offset++);
1848 /*-----------------------------------------------------------------*/
1849 /* outBitC - output a bit C */
1850 /*-----------------------------------------------------------------*/
1852 outBitC (operand * result)
1854 /* if the result is bit */
1855 if (AOP_TYPE (result) == AOP_CRY)
1857 if (!IS_OP_RUONLY (result))
1858 aopPut (result, "c", 0);
1862 if (getDataSize (result))
1864 emitcode ("clr", "a");
1865 emitcode ("rlc", "a");
1871 /*-----------------------------------------------------------------*/
1872 /* toBoolean - emit code for orl a,operator(sizeop) */
1873 /*-----------------------------------------------------------------*/
1875 toBoolean (operand * oper)
1877 int size = AOP_SIZE (oper) - 1;
1879 bool AccUsed = FALSE;
1882 while (!AccUsed && size--)
1884 AccUsed |= aopGetUsesAcc(oper, offset++);
1887 size = AOP_SIZE (oper) - 1;
1889 MOVA (aopGet (oper, 0, FALSE, FALSE));
1890 if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1893 emitcode("mov", "b,a");
1896 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1897 emitcode ("orl", "b,a");
1899 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1900 emitcode ("orl", "a,b");
1907 emitcode ("orl", "a,%s",
1908 aopGet (oper, offset++, FALSE, FALSE));
1913 /*-----------------------------------------------------------------*/
1914 /* toCarry - make boolean and move into carry */
1915 /*-----------------------------------------------------------------*/
1917 toCarry (operand * oper)
1919 /* if the operand is a literal then
1920 we know what the value is */
1921 if (AOP_TYPE (oper) == AOP_LIT)
1923 if ((int) operandLitValue (oper))
1928 else if (AOP_TYPE (oper) == AOP_CRY)
1930 emitcode ("mov", "c,%s", oper->aop->aopu.aop_dir);
1934 /* or the operand into a */
1936 /* set C, if a >= 1 */
1937 emitcode ("add", "a,#0xff");
1941 /*-----------------------------------------------------------------*/
1942 /* assignBit - assign operand to bit operand */
1943 /*-----------------------------------------------------------------*/
1945 assignBit (operand * result, operand * right)
1947 /* if the right side is a literal then
1948 we know what the value is */
1949 if (AOP_TYPE (right) == AOP_LIT)
1951 if ((int) operandLitValue (right))
1952 aopPut (result, one, 0);
1954 aopPut (result, zero, 0);
1959 aopPut (result, "c", 0);
1964 /*-------------------------------------------------------------------*/
1965 /* xch_a_aopGet - for exchanging acc with value of the aop */
1966 /*-------------------------------------------------------------------*/
1968 xch_a_aopGet (operand * oper, int offset, bool bit16, bool dname)
1972 if (aopGetUsesAcc (oper, offset))
1974 emitcode("mov", "b,a");
1975 MOVA (aopGet (oper, offset, bit16, dname));
1976 emitcode("xch", "a,b");
1977 aopPut (oper, "a", offset);
1978 emitcode("xch", "a,b");
1983 l = aopGet (oper, offset, bit16, dname);
1984 emitcode("xch", "a,%s", l);
1990 /*-----------------------------------------------------------------*/
1991 /* genNot - generate code for ! operation */
1992 /*-----------------------------------------------------------------*/
1998 D (emitcode (";", "genNot"));
2000 /* assign asmOps to operand & result */
2001 aopOp (IC_LEFT (ic), ic, FALSE);
2002 aopOp (IC_RESULT (ic), ic, TRUE);
2004 /* if in bit space then a special case */
2005 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2007 /* if left==result then cpl bit */
2008 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2010 emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2014 toCarry (IC_LEFT (ic));
2015 emitcode ("cpl", "c");
2016 outBitC (IC_RESULT (ic));
2021 toBoolean (IC_LEFT (ic));
2023 /* set C, if a == 0 */
2024 tlbl = newiTempLabel (NULL);
2025 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
2027 outBitC (IC_RESULT (ic));
2030 /* release the aops */
2031 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2032 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2036 /*-----------------------------------------------------------------*/
2037 /* genCpl - generate code for complement */
2038 /*-----------------------------------------------------------------*/
2045 sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
2047 D(emitcode (";", "genCpl"));
2049 /* assign asmOps to operand & result */
2050 aopOp (IC_LEFT (ic), ic, FALSE);
2051 aopOp (IC_RESULT (ic), ic, TRUE);
2053 /* special case if in bit space */
2054 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2058 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
2059 (SPEC_USIGN (letype) && IS_CHAR (letype)))
2061 /* promotion rules are responsible for this strange result:
2062 bit -> int -> ~int -> bit
2063 uchar -> int -> ~int -> bit
2065 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
2069 tlbl=newiTempLabel(NULL);
2070 l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
2071 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
2072 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
2073 IS_AOP_PREG (IC_LEFT (ic)))
2075 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
2080 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
2083 outBitC (IC_RESULT(ic));
2087 size = AOP_SIZE (IC_RESULT (ic));
2090 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2092 emitcode ("cpl", "a");
2093 aopPut (IC_RESULT (ic), "a", offset++);
2098 /* release the aops */
2099 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2100 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2103 /*-----------------------------------------------------------------*/
2104 /* genUminusFloat - unary minus for floating points */
2105 /*-----------------------------------------------------------------*/
2107 genUminusFloat (operand * op, operand * result)
2109 int size, offset = 0;
2112 D (emitcode (";", "genUminusFloat"));
2114 /* for this we just copy and then flip the bit */
2116 size = AOP_SIZE (op) - 1;
2121 aopGet (op, offset, FALSE, FALSE),
2126 l = aopGet (op, offset, FALSE, FALSE);
2129 emitcode ("cpl", "acc.7");
2130 aopPut (result, "a", offset);
2133 /*-----------------------------------------------------------------*/
2134 /* genUminus - unary minus code generation */
2135 /*-----------------------------------------------------------------*/
2137 genUminus (iCode * ic)
2142 D (emitcode (";", "genUminus"));
2145 aopOp (IC_LEFT (ic), ic, FALSE);
2146 aopOp (IC_RESULT (ic), ic, TRUE);
2148 /* if both in bit space then special
2150 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2151 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2154 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2155 emitcode ("cpl", "c");
2156 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2160 optype = operandType (IC_LEFT (ic));
2162 /* if float then do float stuff */
2163 if (IS_FLOAT (optype))
2165 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2169 /* otherwise subtract from zero */
2170 size = AOP_SIZE (IC_LEFT (ic));
2174 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2175 if (!strcmp (l, "a"))
2179 emitcode ("cpl", "a");
2180 emitcode ("addc", "a,#0");
2186 emitcode ("clr", "a");
2187 emitcode ("subb", "a,%s", l);
2189 aopPut (IC_RESULT (ic), "a", offset++);
2192 /* if any remaining bytes in the result */
2193 /* we just need to propagate the sign */
2194 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2196 emitcode ("rlc", "a");
2197 emitcode ("subb", "a,acc");
2199 aopPut (IC_RESULT (ic), "a", offset++);
2203 /* release the aops */
2204 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2205 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2208 /*-----------------------------------------------------------------*/
2209 /* saveRegisters - will look for a call and save the registers */
2210 /*-----------------------------------------------------------------*/
2212 saveRegisters (iCode * lic)
2219 for (ic = lic; ic; ic = ic->next)
2220 if (ic->op == CALL || ic->op == PCALL)
2225 fprintf (stderr, "found parameter push with no function call\n");
2229 /* if the registers have been saved already or don't need to be then
2233 if (IS_SYMOP(IC_LEFT(ic)) &&
2234 (IFFUNC_CALLEESAVES (OP_SYMBOL (IC_LEFT (ic))->type) ||
2235 IFFUNC_ISNAKED (OP_SYM_TYPE (IC_LEFT (ic)))))
2238 /* save the registers in use at this time but skip the
2239 ones for the result */
2240 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2241 mcs51_rUmaskForOp (IC_RESULT(ic)));
2244 if (options.useXstack)
2246 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2247 int nBits = bitVectnBitsOn (rsavebits);
2248 int count = bitVectnBitsOn (rsave);
2252 count = count - nBits + 1;
2253 /* remove all but the first bits as they are pushed all at once */
2254 rsave = bitVectCplAnd (rsave, rsavebits);
2255 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2257 freeBitVect (rsavebits);
2261 regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2262 if (reg->type == REG_BIT)
2264 emitcode ("mov", "a,%s", reg->base);
2268 emitcode ("mov", "a,%s", reg->name);
2270 emitcode ("mov", "r0,%s", spname);
2271 emitcode ("inc", "%s", spname);// allocate before use
2272 emitcode ("movx", "@r0,a");
2273 if (bitVectBitValue (rsave, R0_IDX))
2274 emitcode ("mov", "r0,a");
2276 else if (count != 0)
2278 if (bitVectBitValue (rsave, R0_IDX))
2280 emitcode ("push", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2282 emitcode ("mov", "r0,%s", spname);
2284 emitcode ("add", "a,#%d", count);
2285 emitcode ("mov", "%s,a", spname);
2286 for (i = 0; i < mcs51_nRegs; i++)
2288 if (bitVectBitValue (rsave, i))
2290 regs * reg = REG_WITH_INDEX (i);
2293 emitcode ("pop", "acc");
2294 emitcode ("push", "acc");
2296 else if (reg->type == REG_BIT)
2298 emitcode ("mov", "a,%s", reg->base);
2302 emitcode ("mov", "a,%s", reg->name);
2304 emitcode ("movx", "@r0,a");
2307 emitcode ("inc", "r0");
2311 if (bitVectBitValue (rsave, R0_IDX))
2313 emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2319 bool bits_pushed = FALSE;
2320 for (i = 0; i < mcs51_nRegs; i++)
2322 if (bitVectBitValue (rsave, i))
2324 bits_pushed = pushReg (i, bits_pushed);
2328 freeBitVect (rsave);
2331 /*-----------------------------------------------------------------*/
2332 /* unsaveRegisters - pop the pushed registers */
2333 /*-----------------------------------------------------------------*/
2335 unsaveRegisters (iCode * ic)
2340 /* restore the registers in use at this time but skip the
2341 ones for the result */
2342 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2343 mcs51_rUmaskForOp (IC_RESULT(ic)));
2345 if (options.useXstack)
2347 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2348 int nBits = bitVectnBitsOn (rsavebits);
2349 int count = bitVectnBitsOn (rsave);
2353 count = count - nBits + 1;
2354 /* remove all but the first bits as they are popped all at once */
2355 rsave = bitVectCplAnd (rsave, rsavebits);
2356 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2358 freeBitVect (rsavebits);
2362 regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2363 emitcode ("mov", "r0,%s", spname);
2364 emitcode ("dec", "r0");
2365 emitcode ("movx", "a,@r0");
2366 if (reg->type == REG_BIT)
2368 emitcode ("mov", "%s,a", reg->base);
2372 emitcode ("mov", "%s,a", reg->name);
2374 emitcode ("dec", "%s", spname);
2376 else if (count != 0)
2378 emitcode ("mov", "r0,%s", spname);
2379 for (i = mcs51_nRegs; i >= 0; i--)
2381 if (bitVectBitValue (rsave, i))
2383 regs * reg = REG_WITH_INDEX (i);
2384 emitcode ("dec", "r0");
2385 emitcode ("movx", "a,@r0");
2388 emitcode ("push", "acc");
2390 else if (reg->type == REG_BIT)
2392 emitcode ("mov", "%s,a", reg->base);
2396 emitcode ("mov", "%s,a", reg->name);
2400 emitcode ("mov", "%s,r0", spname);
2401 if (bitVectBitValue (rsave, R0_IDX))
2403 emitcode ("pop", "ar0");
2409 bool bits_popped = FALSE;
2410 for (i = mcs51_nRegs; i >= 0; i--)
2412 if (bitVectBitValue (rsave, i))
2414 bits_popped = popReg (i, bits_popped);
2418 freeBitVect (rsave);
2422 /*-----------------------------------------------------------------*/
2424 /*-----------------------------------------------------------------*/
2426 pushSide (operand * oper, int size)
2431 char *l = aopGet (oper, offset++, FALSE, TRUE);
2432 if (AOP_TYPE (oper) != AOP_REG &&
2433 AOP_TYPE (oper) != AOP_DIR &&
2437 emitcode ("push", "acc");
2441 emitcode ("push", "%s", l);
2446 /*-----------------------------------------------------------------*/
2447 /* assignResultValue - also indicates if acc is in use afterwards */
2448 /*-----------------------------------------------------------------*/
2450 assignResultValue (operand * oper, operand * func)
2453 int size = AOP_SIZE (oper);
2454 bool accuse = FALSE;
2455 bool pushedA = FALSE;
2457 if (func && IS_BIT (OP_SYM_ETYPE (func)))
2463 if ((size > 3) && aopPutUsesAcc (oper, fReturn[offset], offset))
2465 emitcode ("push", "acc");
2470 if ((offset == 3) && pushedA)
2471 emitcode ("pop", "acc");
2472 accuse |= aopPut (oper, fReturn[offset], offset);
2479 /*-----------------------------------------------------------------*/
2480 /* genXpush - pushes onto the external stack */
2481 /*-----------------------------------------------------------------*/
2483 genXpush (iCode * ic)
2485 asmop *aop = newAsmop (0);
2487 int size, offset = 0;
2489 D (emitcode (";", "genXpush"));
2491 aopOp (IC_LEFT (ic), ic, FALSE);
2492 r = getFreePtr (ic, &aop, FALSE);
2494 size = AOP_SIZE (IC_LEFT (ic));
2498 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2499 emitcode ("mov", "%s,%s", r->name, spname);
2500 emitcode ("inc", "%s", spname); // allocate space first
2501 emitcode ("movx", "@%s,a", r->name);
2505 // allocate space first
2506 emitcode ("mov", "%s,%s", r->name, spname);
2508 emitcode ("add", "a,#%d", size);
2509 emitcode ("mov", "%s,a", spname);
2513 MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2514 emitcode ("movx", "@%s,a", r->name);
2515 emitcode ("inc", "%s", r->name);
2519 freeAsmop (NULL, aop, ic, TRUE);
2520 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2523 /*-----------------------------------------------------------------*/
2524 /* genIpush - generate code for pushing this gets a little complex */
2525 /*-----------------------------------------------------------------*/
2527 genIpush (iCode * ic)
2529 int size, offset = 0;
2533 D (emitcode (";", "genIpush"));
2535 /* if this is not a parm push : ie. it is spill push
2536 and spill push is always done on the local stack */
2540 /* and the item is spilt then do nothing */
2541 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2544 aopOp (IC_LEFT (ic), ic, FALSE);
2545 size = AOP_SIZE (IC_LEFT (ic));
2546 /* push it on the stack */
2549 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2555 emitcode ("push", "%s", l);
2560 /* this is a parameter push: in this case we call
2561 the routine to find the call and save those
2562 registers that need to be saved */
2565 /* if use external stack then call the external
2566 stack pushing routine */
2567 if (options.useXstack)
2573 /* then do the push */
2574 aopOp (IC_LEFT (ic), ic, FALSE);
2576 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2577 size = AOP_SIZE (IC_LEFT (ic));
2581 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2582 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2583 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR)
2585 if (strcmp (l, prev) || *l == '@')
2587 emitcode ("push", "acc");
2591 emitcode ("push", "%s", l);
2596 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2599 /*-----------------------------------------------------------------*/
2600 /* genIpop - recover the registers: can happen only for spilling */
2601 /*-----------------------------------------------------------------*/
2603 genIpop (iCode * ic)
2607 D (emitcode (";", "genIpop"));
2609 /* if the temp was not pushed then */
2610 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2613 aopOp (IC_LEFT (ic), ic, FALSE);
2614 size = AOP_SIZE (IC_LEFT (ic));
2615 offset = (size - 1);
2618 emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2622 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2625 /*-----------------------------------------------------------------*/
2626 /* saveRBank - saves an entire register bank on the stack */
2627 /*-----------------------------------------------------------------*/
2629 saveRBank (int bank, iCode * ic, bool pushPsw)
2632 int count = 8 + (pushPsw ? 1 : 0);
2636 if (options.useXstack)
2640 /* Assume r0 is available for use. */
2641 r = REG_WITH_INDEX (R0_IDX);
2646 r = getFreePtr (ic, &aop, FALSE);
2648 // allocate space first
2649 emitcode ("mov", "%s,%s", r->name, spname);
2651 emitcode ("add", "a,#%d", count);
2652 emitcode ("mov", "%s,a", spname);
2655 for (i = 0; i < 8; i++)
2657 if (options.useXstack)
2659 emitcode ("mov", "a,(%s+%d)",
2660 regs8051[i].base, 8 * bank + regs8051[i].offset);
2661 emitcode ("movx", "@%s,a", r->name);
2663 emitcode ("inc", "%s", r->name);
2666 emitcode ("push", "(%s+%d)",
2667 regs8051[i].base, 8 * bank + regs8051[i].offset);
2672 if (options.useXstack)
2674 emitcode ("mov", "a,psw");
2675 emitcode ("movx", "@%s,a", r->name);
2679 emitcode ("push", "psw");
2682 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2687 freeAsmop (NULL, aop, ic, TRUE);
2696 /*-----------------------------------------------------------------*/
2697 /* unsaveRBank - restores the register bank from stack */
2698 /*-----------------------------------------------------------------*/
2700 unsaveRBank (int bank, iCode * ic, bool popPsw)
2706 if (options.useXstack)
2710 /* Assume r0 is available for use. */
2711 r = REG_WITH_INDEX (R0_IDX);;
2716 r = getFreePtr (ic, &aop, FALSE);
2718 emitcode ("mov", "%s,%s", r->name, spname);
2723 if (options.useXstack)
2725 emitcode ("dec", "%s", r->name);
2726 emitcode ("movx", "a,@%s", r->name);
2727 emitcode ("mov", "psw,a");
2731 emitcode ("pop", "psw");
2735 for (i = 7; i >= 0; i--)
2737 if (options.useXstack)
2739 emitcode ("dec", "%s", r->name);
2740 emitcode ("movx", "a,@%s", r->name);
2741 emitcode ("mov", "(%s+%d),a",
2742 regs8051[i].base, 8 * bank + regs8051[i].offset);
2746 emitcode ("pop", "(%s+%d)",
2747 regs8051[i].base, 8 * bank + regs8051[i].offset);
2751 if (options.useXstack)
2753 emitcode ("mov", "%s,%s", spname, r->name);
2758 freeAsmop (NULL, aop, ic, TRUE);
2762 /*-----------------------------------------------------------------*/
2763 /* genSend - gen code for SEND */
2764 /*-----------------------------------------------------------------*/
2765 static void genSend(set *sendSet)
2770 /* first we do all bit parameters */
2771 for (sic = setFirstItem (sendSet); sic;
2772 sic = setNextItem (sendSet))
2774 if (sic->argreg > 12)
2776 int bit = sic->argreg-13;
2778 aopOp (IC_LEFT (sic), sic, FALSE);
2780 /* if left is a literal then
2781 we know what the value is */
2782 if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2784 if (((int) operandLitValue (IC_LEFT (sic))))
2785 emitcode ("setb", "b[%d]", bit);
2787 emitcode ("clr", "b[%d]", bit);
2792 toCarry (IC_LEFT (sic));
2793 emitcode ("mov", "b[%d],c", bit);
2798 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2804 saveRegisters (setFirstItem (sendSet));
2805 emitcode ("mov", "bits,b");
2808 /* then we do all other parameters */
2809 for (sic = setFirstItem (sendSet); sic;
2810 sic = setNextItem (sendSet))
2812 if (sic->argreg <= 12)
2814 int size, offset = 0;
2815 aopOp (IC_LEFT (sic), sic, FALSE);
2816 size = AOP_SIZE (IC_LEFT (sic));
2818 if (sic->argreg == 1)
2822 char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2823 if (strcmp (l, fReturn[offset]))
2825 emitcode ("mov", "%s,%s", fReturn[offset], l);
2834 emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2835 aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2839 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2844 /*-----------------------------------------------------------------*/
2845 /* selectRegBank - emit code to select the register bank */
2846 /*-----------------------------------------------------------------*/
2848 selectRegBank (short bank, bool keepFlags)
2850 /* if f.e. result is in carry */
2853 emitcode ("anl", "psw,#0xE7");
2855 emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2859 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2863 /*-----------------------------------------------------------------*/
2864 /* genCall - generates a call statement */
2865 /*-----------------------------------------------------------------*/
2867 genCall (iCode * ic)
2871 // bool restoreBank = FALSE;
2872 bool swapBanks = FALSE;
2873 bool accuse = FALSE;
2874 bool accPushed = FALSE;
2875 bool resultInF0 = FALSE;
2876 bool assignResultGenerated = FALSE;
2878 D (emitcode (";", "genCall"));
2880 dtype = operandType (IC_LEFT (ic));
2881 etype = getSpec(dtype);
2882 /* if send set is not empty then assign */
2885 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2886 genSend(reverseSet(_G.sendSet));
2888 genSend(_G.sendSet);
2893 /* if we are calling a not _naked function that is not using
2894 the same register bank then we need to save the
2895 destination registers on the stack */
2896 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2897 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2898 !IFFUNC_ISISR (dtype))
2903 /* if caller saves & we have not saved then */
2909 emitcode ("mov", "psw,#0x%02x",
2910 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2914 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2916 if (IFFUNC_CALLEESAVES(dtype))
2918 werror (E_BANKED_WITH_CALLEESAVES);
2922 char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2923 OP_SYMBOL (IC_LEFT (ic))->rname :
2924 OP_SYMBOL (IC_LEFT (ic))->name);
2926 emitcode ("mov", "r0,#%s", l);
2927 emitcode ("mov", "r1,#(%s >> 8)", l);
2928 emitcode ("mov", "r2,#(%s >> 16)", l);
2929 emitcode ("lcall", "__sdcc_banked_call");
2934 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2935 OP_SYMBOL (IC_LEFT (ic))->rname :
2936 OP_SYMBOL (IC_LEFT (ic))->name));
2941 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2944 /* if we need assign a result value */
2945 if ((IS_ITEMP (IC_RESULT (ic)) &&
2946 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2947 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2948 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2949 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2950 IS_TRUE_SYMOP (IC_RESULT (ic)))
2954 aopOp (IC_RESULT (ic), ic, FALSE);
2957 accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2958 assignResultGenerated = TRUE;
2960 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2963 /* adjust the stack for parameters if required */
2967 if (ic->parmBytes > 3)
2971 emitcode ("push", "acc");
2974 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2975 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2976 !assignResultGenerated)
2978 emitcode ("mov", "F0,c");
2982 emitcode ("mov", "a,%s", spname);
2983 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2984 emitcode ("mov", "%s,a", spname);
2986 /* unsaveRegisters from xstack needs acc, but */
2987 /* unsaveRegisters from stack needs this popped */
2988 if (accPushed && !options.useXstack)
2990 emitcode ("pop", "acc");
2995 for (i = 0; i < ic->parmBytes; i++)
2996 emitcode ("dec", "%s", spname);
2999 /* if we had saved some registers then unsave them */
3000 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3002 if (accuse && !accPushed && options.useXstack)
3004 /* xstack needs acc, but doesn't touch normal stack */
3005 emitcode ("push", "acc");
3008 unsaveRegisters (ic);
3011 // /* if register bank was saved then pop them */
3013 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
3015 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
3018 emitcode ("mov", "c,F0");
3020 aopOp (IC_RESULT (ic), ic, FALSE);
3021 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3022 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3026 emitcode ("pop", "acc");
3029 /*-----------------------------------------------------------------*/
3030 /* genPcall - generates a call by pointer statement */
3031 /*-----------------------------------------------------------------*/
3033 genPcall (iCode * ic)
3037 symbol *rlbl = newiTempLabel (NULL);
3038 // bool restoreBank=FALSE;
3039 bool swapBanks = FALSE;
3040 bool resultInF0 = FALSE;
3042 D (emitcode (";", "genPcall"));
3044 dtype = operandType (IC_LEFT (ic))->next;
3045 etype = getSpec(dtype);
3046 /* if caller saves & we have not saved then */
3050 /* if we are calling a not _naked function that is not using
3051 the same register bank then we need to save the
3052 destination registers on the stack */
3053 if (currFunc && dtype && !IFFUNC_ISNAKED (dtype) &&
3054 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
3055 !IFFUNC_ISISR (dtype))
3057 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3058 // restoreBank=TRUE;
3060 // need caution message to user here
3063 if (IS_LITERAL (etype))
3065 /* if send set is not empty then assign */
3068 genSend(reverseSet(_G.sendSet));
3074 emitcode ("mov", "psw,#0x%02x",
3075 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3078 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT (getSpec(dtype)))
3080 if (IFFUNC_CALLEESAVES (dtype))
3082 werror (E_BANKED_WITH_CALLEESAVES);
3086 char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
3088 emitcode ("mov", "r0,#%s", l);
3089 emitcode ("mov", "r1,#(%s >> 8)", l);
3090 emitcode ("mov", "r2,#(%s >> 16)", l);
3091 emitcode ("lcall", "__sdcc_banked_call");
3096 emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
3101 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT (getSpec(dtype)))
3103 if (IFFUNC_CALLEESAVES (dtype))
3105 werror (E_BANKED_WITH_CALLEESAVES);
3109 aopOp (IC_LEFT (ic), ic, FALSE);
3113 /* what if aopGet needs r0 or r1 ??? */
3114 emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3115 emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3116 emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3120 int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
3121 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3122 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3123 emitcode ("mov", "0x%02x,%s", reg, aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3126 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3128 /* if send set is not empty then assign */
3131 genSend(reverseSet(_G.sendSet));
3137 emitcode ("mov", "psw,#0x%02x",
3138 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3142 emitcode ("lcall", "__sdcc_banked_call");
3145 else if (_G.sendSet)
3147 /* push the return address on to the stack */
3148 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
3149 emitcode ("push", "acc");
3150 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
3151 emitcode ("push", "acc");
3153 /* now push the calling address */
3154 aopOp (IC_LEFT (ic), ic, FALSE);
3156 pushSide (IC_LEFT (ic), FPTRSIZE);
3158 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3160 /* if send set is not empty the assign */
3163 genSend(reverseSet(_G.sendSet));
3169 emitcode ("mov", "psw,#0x%02x",
3170 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3174 emitcode ("ret", "");
3177 else /* the send set is empty */
3180 /* now get the calling address into dptr */
3181 aopOp (IC_LEFT (ic), ic, FALSE);
3183 l = aopGet (IC_LEFT (ic), 0, FALSE, FALSE);
3184 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3186 emitcode ("mov", "r0,%s", l);
3187 l = aopGet (IC_LEFT (ic), 1, FALSE, FALSE);
3188 emitcode ("mov", "dph,%s", l);
3189 emitcode ("mov", "dpl,r0");
3193 emitcode ("mov", "dpl,%s", l);
3194 l = aopGet (IC_LEFT (ic), 1, FALSE, FALSE);
3195 emitcode ("mov", "dph,%s", l);
3198 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3202 emitcode ("mov", "psw,#0x%02x",
3203 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3207 emitcode ("lcall", "__sdcc_call_dptr");
3212 selectRegBank (FUNC_REGBANK (currFunc->type), IS_BIT (etype));
3215 /* if we need assign a result value */
3216 if ((IS_ITEMP (IC_RESULT (ic)) &&
3217 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3218 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3219 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3220 IS_TRUE_SYMOP (IC_RESULT (ic)))
3224 aopOp (IC_RESULT (ic), ic, FALSE);
3227 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3229 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3232 /* adjust the stack for parameters if required */
3236 if (ic->parmBytes > 3)
3238 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3239 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3241 emitcode ("mov", "F0,c");
3245 emitcode ("mov", "a,%s", spname);
3246 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3247 emitcode ("mov", "%s,a", spname);
3250 for (i = 0; i < ic->parmBytes; i++)
3251 emitcode ("dec", "%s", spname);
3254 // /* if register bank was saved then unsave them */
3256 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3258 /* if we had saved some registers then unsave them */
3259 if (ic->regsSaved && !IFFUNC_CALLEESAVES (dtype))
3260 unsaveRegisters (ic);
3262 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3265 emitcode ("mov", "c,F0");
3267 aopOp (IC_RESULT (ic), ic, FALSE);
3268 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3269 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3273 /*-----------------------------------------------------------------*/
3274 /* resultRemat - result is rematerializable */
3275 /*-----------------------------------------------------------------*/
3277 resultRemat (iCode * ic)
3279 if (SKIP_IC (ic) || ic->op == IFX)
3282 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3284 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3285 if (sym->remat && !POINTER_SET (ic))
3292 /*-----------------------------------------------------------------*/
3293 /* inExcludeList - return 1 if the string is in exclude Reg list */
3294 /*-----------------------------------------------------------------*/
3296 regsCmp(void *p1, void *p2)
3298 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3302 inExcludeList (char *s)
3304 const char *p = setFirstItem(options.excludeRegsSet);
3306 if (p == NULL || STRCASECMP(p, "none") == 0)
3310 return isinSetWith(options.excludeRegsSet, s, regsCmp);
3313 /*-----------------------------------------------------------------*/
3314 /* genFunction - generated code for function entry */
3315 /*-----------------------------------------------------------------*/
3317 genFunction (iCode * ic)
3319 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3321 bool switchedPSW = FALSE;
3322 int calleesaves_saved_register = -1;
3323 int stackAdjust = sym->stack;
3324 int accIsFree = sym->recvSize < 4;
3325 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3326 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3329 /* create the function header */
3330 emitcode (";", "-----------------------------------------");
3331 emitcode (";", " function %s", sym->name);
3332 emitcode (";", "-----------------------------------------");
3334 emitcode ("", "%s:", sym->rname);
3335 lineCurr->isLabel = 1;
3336 ftype = operandType (IC_LEFT (ic));
3337 _G.currentFunc = sym;
3339 if (IFFUNC_ISNAKED(ftype))
3341 emitcode(";", "naked function: no prologue.");
3345 /* here we need to generate the equates for the
3346 register bank if required */
3347 if (FUNC_REGBANK (ftype) != rbank)
3351 rbank = FUNC_REGBANK (ftype);
3352 for (i = 0; i < mcs51_nRegs; i++)
3354 if (regs8051[i].type != REG_BIT)
3356 if (strcmp (regs8051[i].base, "0") == 0)
3357 emitcode ("", "%s = 0x%02x",
3359 8 * rbank + regs8051[i].offset);
3361 emitcode ("", "%s = %s + 0x%02x",
3364 8 * rbank + regs8051[i].offset);
3369 /* if this is an interrupt service routine then
3370 save acc, b, dpl, dph */
3371 if (IFFUNC_ISISR (sym->type))
3375 rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), sym->regsUsed);
3376 if (IFFUNC_HASFCALL(sym->type) || !bitVectIsZero (rsavebits))
3378 emitcode ("push", "bits");
3381 freeBitVect (rsavebits);
3383 if (!inExcludeList ("acc"))
3384 emitcode ("push", "acc");
3385 if (!inExcludeList ("b"))
3386 emitcode ("push", "b");
3387 if (!inExcludeList ("dpl"))
3388 emitcode ("push", "dpl");
3389 if (!inExcludeList ("dph"))
3390 emitcode ("push", "dph");
3391 /* if this isr has no bank i.e. is going to
3392 run with bank 0 , then we need to save more
3394 if (!FUNC_REGBANK (sym->type))
3398 /* if this function does not call any other
3399 function then we can be economical and
3400 save only those registers that are used */
3401 if (!IFFUNC_HASFCALL(sym->type))
3403 /* if any registers used */
3406 /* save the registers used */
3407 for (i = 0; i < sym->regsUsed->size; i++)
3409 if (bitVectBitValue (sym->regsUsed, i))
3416 /* this function has a function call. We cannot
3417 determine register usage so we will have to push the
3419 saveRBank (0, ic, FALSE);
3420 if (options.parms_in_bank1) {
3421 for (i=0; i < 8 ; i++ ) {
3422 emitcode ("push","%s",rb1regs[i]);
3429 /* This ISR uses a non-zero bank.
3431 * We assume that the bank is available for our
3434 * However, if this ISR calls a function which uses some
3435 * other bank, we must save that bank entirely.
3437 unsigned long banksToSave = 0;
3439 if (IFFUNC_HASFCALL(sym->type))
3442 #define MAX_REGISTER_BANKS 4
3447 for (i = ic; i; i = i->next)
3449 if (i->op == ENDFUNCTION)
3451 /* we got to the end OK. */
3459 dtype = operandType (IC_LEFT(i));
3461 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3463 /* Mark this bank for saving. */
3464 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3466 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3470 banksToSave |= (1 << FUNC_REGBANK(dtype));
3473 /* And note that we don't need to do it in
3481 /* This is a mess; we have no idea what
3482 * register bank the called function might
3485 * The only thing I can think of to do is
3486 * throw a warning and hope.
3488 werror(W_FUNCPTR_IN_USING_ISR);
3492 if (banksToSave && options.useXstack)
3494 /* Since we aren't passing it an ic,
3495 * saveRBank will assume r0 is available to abuse.
3497 * So switch to our (trashable) bank now, so
3498 * the caller's R0 isn't trashed.
3500 emitcode ("push", "psw");
3501 emitcode ("mov", "psw,#0x%02x",
3502 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3506 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3508 if (banksToSave & (1 << ix))
3510 saveRBank(ix, NULL, FALSE);
3514 // TODO: this needs a closer look
3515 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3518 /* Set the register bank to the desired value if nothing else */
3519 /* has done so yet. */
3522 emitcode ("push", "psw");
3523 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3528 /* This is a non-ISR function. The caller has already switched register */
3529 /* banks, if necessary, so just handle the callee-saves option. */
3531 /* if callee-save to be used for this function
3532 then save the registers being used in this function */
3533 if (IFFUNC_CALLEESAVES(sym->type))
3537 /* if any registers used */
3540 bool bits_pushed = FALSE;
3541 /* save the registers used */
3542 for (i = 0; i < sym->regsUsed->size; i++)
3544 if (bitVectBitValue (sym->regsUsed, i))
3546 /* remember one saved register for later usage */
3547 if (calleesaves_saved_register < 0)
3548 calleesaves_saved_register = i;
3549 bits_pushed = pushReg (i, bits_pushed);
3559 if (options.useXstack)
3561 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3563 emitcode ("mov", "r0,%s", spname);
3564 emitcode ("inc", "%s", spname);
3565 emitcode ("xch", "a,_bpx");
3566 emitcode ("movx", "@r0,a");
3567 emitcode ("inc", "r0");
3568 emitcode ("mov", "a,r0");
3569 emitcode ("xch", "a,_bpx");
3573 emitcode ("push", "_bp"); /* save the callers stack */
3574 emitcode ("mov", "_bp,sp");
3579 if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3581 /* set up the stack */
3582 emitcode ("push", "_bp"); /* save the callers stack */
3583 emitcode ("mov", "_bp,sp");
3588 /* For some cases it is worthwhile to perform a RECEIVE iCode */
3589 /* before setting up the stack frame completely. */
3590 if (ric && ric->argreg == 1 && IC_RESULT (ric))
3592 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3596 if (rsym && rsym->regType == REG_CND)
3598 if (rsym && (rsym->accuse || rsym->ruonly))
3600 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3601 rsym = rsym->usl.spillLoc;
3604 /* If the RECEIVE operand immediately spills to the first entry on the */
3605 /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3606 /* rather than the usual @r0/r1 machinations. */
3607 if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3611 _G.current_iCode = ric;
3612 D(emitcode (";", "genReceive"));
3613 for (ofs=0; ofs < sym->recvSize; ofs++)
3615 if (!strcmp (fReturn[ofs], "a"))
3616 emitcode ("push", "acc");
3618 emitcode ("push", fReturn[ofs]);
3620 stackAdjust -= sym->recvSize;
3623 assert (stackAdjust>=0);
3626 _G.current_iCode = ic;
3630 /* If the RECEIVE operand is 4 registers, we can do the moves now */
3631 /* to free up the accumulator. */
3632 else if (rsym && rsym->nRegs && sym->recvSize == 4)
3636 _G.current_iCode = ric;
3637 D(emitcode (";", "genReceive"));
3638 for (ofs=0; ofs < sym->recvSize; ofs++)
3640 emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3642 _G.current_iCode = ic;
3648 /* adjust the stack for the function */
3651 int i = stackAdjust;
3653 werror (W_STACK_OVERFLOW, sym->name);
3655 if (i > 3 && accIsFree)
3657 emitcode ("mov", "a,sp");
3658 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3659 emitcode ("mov", "sp,a");
3663 /* The accumulator is not free, so we will need another register */
3664 /* to clobber. No need to worry about a possible conflict with */
3665 /* the above early RECEIVE optimizations since they would have */
3666 /* freed the accumulator if they were generated. */
3668 if (IFFUNC_CALLEESAVES(sym->type))
3670 /* if it's a callee-saves function we need a saved register */
3671 if (calleesaves_saved_register >= 0)
3673 emitcode ("mov", "%s,a", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3674 emitcode ("mov", "a,sp");
3675 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3676 emitcode ("mov", "sp,a");
3677 emitcode ("mov", "a,%s", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3680 /* do it the hard way */
3682 emitcode ("inc", "sp");
3686 /* not callee-saves, we can clobber r0 */
3687 emitcode ("mov", "r0,a");
3688 emitcode ("mov", "a,sp");
3689 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3690 emitcode ("mov", "sp,a");
3691 emitcode ("mov", "a,r0");
3696 emitcode ("inc", "sp");
3701 char i = ((char) sym->xstack & 0xff);
3703 if (i > 3 && accIsFree)
3705 emitcode ("mov", "a,_spx");
3706 emitcode ("add", "a,#0x%02x", i & 0xff);
3707 emitcode ("mov", "_spx,a");
3711 emitcode ("push", "acc");
3712 emitcode ("mov", "a,_spx");
3713 emitcode ("add", "a,#0x%02x", i & 0xff);
3714 emitcode ("mov", "_spx,a");
3715 emitcode ("pop", "acc");
3720 emitcode ("inc", "_spx");
3724 /* if critical function then turn interrupts off */
3725 if (IFFUNC_ISCRITICAL (ftype))
3727 symbol *tlbl = newiTempLabel (NULL);
3728 emitcode ("setb", "c");
3729 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3730 emitcode ("clr", "c");
3732 emitcode ("push", "psw"); /* save old ea via c in psw */
3736 /*-----------------------------------------------------------------*/
3737 /* genEndFunction - generates epilogue for functions */
3738 /*-----------------------------------------------------------------*/
3740 genEndFunction (iCode * ic)
3742 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3743 lineNode *lnp = lineCurr;
3745 bitVect *regsUsedPrologue;
3746 bitVect *regsUnneeded;
3749 _G.currentFunc = NULL;
3750 if (IFFUNC_ISNAKED(sym->type))
3752 emitcode(";", "naked function: no epilogue.");
3753 if (options.debug && currFunc)
3754 debugFile->writeEndFunction (currFunc, ic, 0);
3758 if (IFFUNC_ISCRITICAL (sym->type))
3760 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3762 emitcode ("rlc", "a"); /* save c in a */
3763 emitcode ("pop", "psw"); /* restore ea via c in psw */
3764 emitcode ("mov", "ea,c");
3765 emitcode ("rrc", "a"); /* restore c from a */
3769 emitcode ("pop", "psw"); /* restore ea via c in psw */
3770 emitcode ("mov", "ea,c");
3774 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3776 if (options.useXstack)
3780 emitcode ("mov", "sp,_bp");
3781 emitcode ("pop", "_bp");
3783 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3785 emitcode ("xch", "a,_bpx");
3786 emitcode ("mov", "r0,a");
3787 emitcode ("dec", "r0");
3788 emitcode ("movx", "a,@r0");
3789 emitcode ("xch", "a,_bpx");
3790 emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3793 else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3796 emitcode ("mov", "sp,_bp");
3797 emitcode ("pop", "_bp");
3801 /* restore the register bank */
3802 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3804 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3805 || !options.useXstack)
3807 /* Special case of ISR using non-zero bank with useXstack
3810 emitcode ("pop", "psw");
3814 if (IFFUNC_ISISR (sym->type))
3818 /* now we need to restore the registers */
3819 /* if this isr has no bank i.e. is going to
3820 run with bank 0 , then we need to save more
3822 if (!FUNC_REGBANK (sym->type))
3825 /* if this function does not call any other
3826 function then we can be economical and
3827 save only those registers that are used */
3828 if (!IFFUNC_HASFCALL(sym->type))
3830 /* if any registers used */
3833 /* save the registers used */
3834 for (i = sym->regsUsed->size; i >= 0; i--)
3836 if (bitVectBitValue (sym->regsUsed, i))
3843 if (options.parms_in_bank1) {
3844 for (i = 7 ; i >= 0 ; i-- ) {
3845 emitcode ("pop","%s",rb1regs[i]);
3848 /* this function has a function call. We cannot
3849 determine register usage so we will have to pop the
3851 unsaveRBank (0, ic, FALSE);
3856 /* This ISR uses a non-zero bank.
3858 * Restore any register banks saved by genFunction
3861 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3864 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3866 if (savedBanks & (1 << ix))
3868 unsaveRBank(ix, NULL, FALSE);
3872 if (options.useXstack)
3874 /* Restore bank AFTER calling unsaveRBank,
3875 * since it can trash r0.
3877 emitcode ("pop", "psw");
3881 if (!inExcludeList ("dph"))
3882 emitcode ("pop", "dph");
3883 if (!inExcludeList ("dpl"))
3884 emitcode ("pop", "dpl");
3885 if (!inExcludeList ("b"))
3886 emitcode ("pop", "b");
3887 if (!inExcludeList ("acc"))
3888 emitcode ("pop", "acc");
3890 rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), sym->regsUsed);
3891 if (IFFUNC_HASFCALL(sym->type) || !bitVectIsZero (rsavebits))
3892 emitcode ("pop", "bits");
3893 freeBitVect (rsavebits);
3895 /* if debug then send end of function */
3896 if (options.debug && currFunc)
3898 debugFile->writeEndFunction (currFunc, ic, 1);
3901 emitcode ("reti", "");
3905 if (IFFUNC_CALLEESAVES(sym->type))
3909 /* if any registers used */
3912 /* save the registers used */
3913 for (i = sym->regsUsed->size; i >= 0; i--)
3915 if (bitVectBitValue (sym->regsUsed, i) ||
3916 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3917 emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
3920 else if (mcs51_ptrRegReq)
3922 emitcode ("pop", "%s", REG_WITH_INDEX (R1_IDX)->dname);
3923 emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
3928 /* if debug then send end of function */
3929 if (options.debug && currFunc)
3931 debugFile->writeEndFunction (currFunc, ic, 1);
3934 if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3936 emitcode ("ljmp", "__sdcc_banked_ret");
3940 emitcode ("ret", "");
3944 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3947 /* If this was an interrupt handler using bank 0 that called another */
3948 /* function, then all registers must be saved; nothing to optimized. */
3949 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3950 && !FUNC_REGBANK(sym->type))
3953 /* There are no push/pops to optimize if not callee-saves or ISR */
3954 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3957 /* If there were stack parameters, we cannot optimize without also */
3958 /* fixing all of the stack offsets; this is too dificult to consider. */
3959 if (FUNC_HASSTACKPARM(sym->type))
3962 /* Compute the registers actually used */
3963 regsUsed = newBitVect (mcs51_nRegs);
3964 regsUsedPrologue = newBitVect (mcs51_nRegs);
3967 if (lnp->ic && lnp->ic->op == FUNCTION)
3968 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3970 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3972 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3973 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3980 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3981 && !bitVectBitValue (regsUsed, CND_IDX))
3983 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3984 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3985 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3986 bitVectUnSetBit (regsUsed, CND_IDX);
3989 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3991 /* If this was an interrupt handler that called another function */
3992 /* function, then assume A, B, DPH, & DPL may be modified by it. */
3993 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3995 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3996 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3997 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3998 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3999 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
4002 /* Remove the unneeded push/pops */
4003 regsUnneeded = newBitVect (mcs51_nRegs);
4006 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
4008 if (!strncmp(lnp->line, "push", 4))
4010 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
4011 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4013 connectLine (lnp->prev, lnp->next);
4014 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4017 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
4019 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
4020 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4022 connectLine (lnp->prev, lnp->next);
4023 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4030 for (idx = 0; idx < regsUnneeded->size; idx++)
4031 if (bitVectBitValue (regsUnneeded, idx))
4032 emitcode (";", "eliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
4034 freeBitVect (regsUnneeded);
4035 freeBitVect (regsUsed);
4036 freeBitVect (regsUsedPrologue);
4039 /*-----------------------------------------------------------------*/
4040 /* genRet - generate code for return statement */
4041 /*-----------------------------------------------------------------*/
4045 int size, offset = 0, pushed = 0;
4047 D (emitcode (";", "genRet"));
4049 /* if we have no return value then
4050 just generate the "ret" */
4054 /* we have something to return then
4055 move the return value into place */
4056 aopOp (IC_LEFT (ic), ic, FALSE);
4057 size = AOP_SIZE (IC_LEFT (ic));
4059 if (IS_BIT(_G.currentFunc->etype))
4061 if (!IS_OP_RUONLY (IC_LEFT (ic)))
4062 toCarry (IC_LEFT (ic));
4069 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
4072 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
4073 emitcode ("push", "%s", l);
4078 l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
4079 if (strcmp (fReturn[offset], l))
4080 emitcode ("mov", "%s,%s", fReturn[offset++], l);
4087 if (strcmp (fReturn[pushed], "a"))
4088 emitcode ("pop", fReturn[pushed]);
4090 emitcode ("pop", "acc");
4093 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
4096 /* generate a jump to the return label
4097 if the next is not the return statement */
4098 if (!(ic->next && ic->next->op == LABEL &&
4099 IC_LABEL (ic->next) == returnLabel))
4101 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
4105 /*-----------------------------------------------------------------*/
4106 /* genLabel - generates a label */
4107 /*-----------------------------------------------------------------*/
4109 genLabel (iCode * ic)
4111 /* special case never generate */
4112 if (IC_LABEL (ic) == entryLabel)
4115 emitLabel (IC_LABEL (ic));
4118 /*-----------------------------------------------------------------*/
4119 /* genGoto - generates a ljmp */
4120 /*-----------------------------------------------------------------*/
4122 genGoto (iCode * ic)
4124 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
4127 /*-----------------------------------------------------------------*/
4128 /* findLabelBackwards: walks back through the iCode chain looking */
4129 /* for the given label. Returns number of iCode instructions */
4130 /* between that label and given ic. */
4131 /* Returns zero if label not found. */
4132 /*-----------------------------------------------------------------*/
4134 findLabelBackwards (iCode * ic, int key)
4143 /* If we have any pushes or pops, we cannot predict the distance.
4144 I don't like this at all, this should be dealt with in the
4146 if (ic->op == IPUSH || ic->op == IPOP) {
4150 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4159 /*-----------------------------------------------------------------*/
4160 /* genPlusIncr :- does addition with increment if possible */
4161 /*-----------------------------------------------------------------*/
4163 genPlusIncr (iCode * ic)
4165 unsigned int icount;
4166 unsigned int size = getDataSize (IC_RESULT (ic));
4168 /* will try to generate an increment */
4169 /* if the right side is not a literal
4171 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4174 icount = (unsigned int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4176 D(emitcode (";","genPlusIncr"));
4178 /* if increment >=16 bits in register or direct space */
4179 if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG ||
4180 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4181 (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4182 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4183 !isOperandVolatile (IC_RESULT (ic), FALSE) &&
4191 /* If the next instruction is a goto and the goto target
4192 * is < 10 instructions previous to this, we can generate
4193 * jumps straight to that target.
4195 if (ic->next && ic->next->op == GOTO
4196 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4197 && labelRange <= 10)
4199 D (emitcode (";", "tail increment optimized (range %d)", labelRange));
4200 tlbl = IC_LABEL (ic->next);
4205 tlbl = newiTempLabel (NULL);
4208 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4209 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4210 IS_AOP_PREG (IC_RESULT (ic)))
4211 emitcode ("cjne", "%s,#0x00,%05d$",
4212 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4216 emitcode ("clr", "a");
4217 emitcode ("cjne", "a,%s,%05d$",
4218 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4222 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4225 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4226 IS_AOP_PREG (IC_RESULT (ic)))
4227 emitcode ("cjne", "%s,#0x00,%05d$",
4228 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4231 emitcode ("cjne", "a,%s,%05d$",
4232 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4235 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4239 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4240 IS_AOP_PREG (IC_RESULT (ic)))
4241 emitcode ("cjne", "%s,#0x00,%05d$",
4242 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4246 emitcode ("cjne", "a,%s,%05d$",
4247 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4250 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4260 /* if result is dptr */
4261 if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
4262 (AOP_SIZE (IC_RESULT (ic)) == 2) &&
4263 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
4264 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
4266 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4272 if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
4275 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0);
4276 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1);
4278 emitcode ("inc", "dptr");
4283 /* if the literal value of the right hand side
4284 is greater than 4 then it is not worth it */
4288 /* if the sizes are greater than 1 then we cannot */
4289 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4290 AOP_SIZE (IC_LEFT (ic)) > 1)
4293 /* we can if the aops of the left & result match or
4294 if they are in registers and the registers are the
4296 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4300 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4301 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4302 aopPut (IC_RESULT (ic), "a", 0);
4308 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4317 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4318 emitcode ("inc", "a");
4319 aopPut (IC_RESULT (ic), "a", 0);
4326 /*-----------------------------------------------------------------*/
4327 /* outBitAcc - output a bit in acc */
4328 /*-----------------------------------------------------------------*/
4330 outBitAcc (operand * result)
4332 symbol *tlbl = newiTempLabel (NULL);
4333 /* if the result is a bit */
4334 if (AOP_TYPE (result) == AOP_CRY)
4336 aopPut (result, "a", 0);
4340 emitcode ("jz", "%05d$", tlbl->key + 100);
4341 emitcode ("mov", "a,%s", one);
4347 /*-----------------------------------------------------------------*/
4348 /* genPlusBits - generates code for addition of two bits */
4349 /*-----------------------------------------------------------------*/
4351 genPlusBits (iCode * ic)
4353 D (emitcode (";", "genPlusBits"));
4355 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4356 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4358 symbol *lbl = newiTempLabel (NULL);
4359 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4360 emitcode ("cpl", "c");
4362 outBitC (IC_RESULT (ic));
4366 emitcode ("clr", "a");
4367 emitcode ("rlc", "a");
4368 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4369 emitcode ("addc", "a,%s", zero);
4370 outAcc (IC_RESULT (ic));
4375 /* This is the original version of this code.
4377 * This is being kept around for reference,
4378 * because I am not entirely sure I got it right...
4381 adjustArithmeticResult (iCode * ic)
4383 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4384 AOP_SIZE (IC_LEFT (ic)) == 3 &&
4385 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4386 aopPut (IC_RESULT (ic),
4387 aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4390 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4391 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4392 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4393 aopPut (IC_RESULT (ic),
4394 aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4397 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4398 AOP_SIZE (IC_LEFT (ic)) < 3 &&
4399 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4400 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4401 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4404 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4405 aopPut (IC_RESULT (ic), buffer, 2);
4409 /* This is the pure and virtuous version of this code.
4410 * I'm pretty certain it's right, but not enough to toss the old
4414 adjustArithmeticResult (iCode * ic)
4416 if (opIsGptr (IC_RESULT (ic)) &&
4417 opIsGptr (IC_LEFT (ic)) &&
4418 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4420 aopPut (IC_RESULT (ic),
4421 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4425 if (opIsGptr (IC_RESULT (ic)) &&
4426 opIsGptr (IC_RIGHT (ic)) &&
4427 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4429 aopPut (IC_RESULT (ic),
4430 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4434 if (opIsGptr (IC_RESULT (ic)) &&
4435 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4436 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4437 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4438 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4441 SNPRINTF (buffer, sizeof(buffer),
4442 "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4443 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4448 /*-----------------------------------------------------------------*/
4449 /* genPlus - generates code for addition */
4450 /*-----------------------------------------------------------------*/
4452 genPlus (iCode * ic)
4454 int size, offset = 0;
4457 bool swappedLR = FALSE;
4458 operand *leftOp, *rightOp;
4461 D (emitcode (";", "genPlus"));
4463 /* special cases :- */
4465 aopOp (IC_LEFT (ic), ic, FALSE);
4466 aopOp (IC_RIGHT (ic), ic, FALSE);
4467 aopOp (IC_RESULT (ic), ic, TRUE);
4469 /* if literal, literal on the right or
4470 if left requires ACC or right is already
4472 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4473 (AOP_NEEDSACC (IC_LEFT (ic))) ||
4474 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4476 operand *t = IC_RIGHT (ic);
4477 IC_RIGHT (ic) = IC_LEFT (ic);
4482 /* if both left & right are in bit
4484 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4485 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4491 /* if left in bit space & right literal */
4492 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4493 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4495 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4496 /* if result in bit space */
4497 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4499 if (ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4500 emitcode ("cpl", "c");
4501 outBitC (IC_RESULT (ic));
4505 size = getDataSize (IC_RESULT (ic));
4508 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4509 emitcode ("addc", "a,%s", zero);
4510 aopPut (IC_RESULT (ic), "a", offset++);
4516 /* if I can do an increment instead
4517 of add then GOOD for ME */
4518 if (genPlusIncr (ic) == TRUE)
4521 size = getDataSize (IC_RESULT (ic));
4522 leftOp = IC_LEFT(ic);
4523 rightOp = IC_RIGHT(ic);
4526 /* if this is an add for an array access
4527 at a 256 byte boundary */
4529 && AOP_TYPE (op) == AOP_IMMD
4531 && IS_SPEC (OP_SYM_ETYPE (op))
4532 && SPEC_ABSA (OP_SYM_ETYPE (op))
4533 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4536 D(emitcode (";", "genPlus aligned array"));
4537 aopPut (IC_RESULT (ic),
4538 aopGet (rightOp, 0, FALSE, FALSE),
4541 if( 1 == getDataSize (IC_RIGHT (ic)) )
4543 aopPut (IC_RESULT (ic),
4544 aopGet (leftOp, 1, FALSE, FALSE),
4549 MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4550 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4551 aopPut (IC_RESULT (ic), "a", 1);
4556 /* if the lower bytes of a literal are zero skip the addition */
4557 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4559 while ((0 == ((unsigned int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4560 (skip_bytes+1 < size))
4565 D(emitcode (";", "genPlus shortcut"));
4570 if( offset >= skip_bytes )
4572 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4575 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4577 emitcode("xch", "a,b");
4578 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4579 emitcode (add, "a,b");
4582 else if (aopGetUsesAcc (leftOp, offset))
4584 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4585 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4589 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4590 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4592 aopPut (IC_RESULT (ic), "a", offset);
4593 add = "addc"; /* further adds must propagate carry */
4597 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4598 isOperandVolatile (IC_RESULT (ic), FALSE))
4601 aopPut (IC_RESULT (ic),
4602 aopGet (leftOp, offset, FALSE, FALSE),
4609 adjustArithmeticResult (ic);
4612 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4615 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4616 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4620 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4621 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4625 /*-----------------------------------------------------------------*/
4626 /* genMinusDec :- does subtraction with decrement if possible */
4627 /*-----------------------------------------------------------------*/
4629 genMinusDec (iCode * ic)
4631 unsigned int icount;
4632 unsigned int size = getDataSize (IC_RESULT (ic));
4634 /* will try to generate an increment */
4635 /* if the right side is not a literal
4637 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4640 /* if the literal value of the right hand side
4641 is greater than 4 then it is not worth it */
4642 if ((icount = (unsigned int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4645 D (emitcode (";", "genMinusDec"));
4647 /* if decrement >=16 bits in register or direct space */
4648 if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG ||
4649 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4650 (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4651 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4659 /* If the next instruction is a goto and the goto target
4660 * is <= 10 instructions previous to this, we can generate
4661 * jumps straight to that target.
4663 if (ic->next && ic->next->op == GOTO
4664 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4665 && labelRange <= 10)
4667 D (emitcode (";", "tail decrement optimized (range %d)", labelRange));
4668 tlbl = IC_LABEL (ic->next);
4673 tlbl = newiTempLabel (NULL);
4677 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4678 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4679 IS_AOP_PREG (IC_RESULT (ic)))
4680 emitcode ("cjne", "%s,#0xff,%05d$"
4681 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4685 emitcode ("mov", "a,#0xff");
4686 emitcode ("cjne", "a,%s,%05d$"
4687 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4690 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4693 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4694 IS_AOP_PREG (IC_RESULT (ic)))
4695 emitcode ("cjne", "%s,#0xff,%05d$"
4696 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4700 emitcode ("cjne", "a,%s,%05d$"
4701 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4704 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4708 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4709 IS_AOP_PREG (IC_RESULT (ic)))
4710 emitcode ("cjne", "%s,#0xff,%05d$"
4711 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4715 emitcode ("cjne", "a,%s,%05d$"
4716 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4719 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4728 /* if the sizes are greater than 1 then we cannot */
4729 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4730 AOP_SIZE (IC_LEFT (ic)) > 1)
4733 /* we can if the aops of the left & result match or
4734 if they are in registers and the registers are the
4736 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4740 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4742 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4747 l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
4752 emitcode ("dec", "%s", l);
4755 if (AOP_NEEDSACC (IC_RESULT (ic)))
4756 aopPut (IC_RESULT (ic), "a", 0);
4763 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4764 emitcode ("dec", "a");
4765 aopPut (IC_RESULT (ic), "a", 0);
4772 /*-----------------------------------------------------------------*/
4773 /* addSign - complete with sign */
4774 /*-----------------------------------------------------------------*/
4776 addSign (operand * result, int offset, int sign)
4778 int size = (getDataSize (result) - offset);
4783 emitcode ("rlc", "a");
4784 emitcode ("subb", "a,acc");
4787 aopPut (result, "a", offset++);
4794 aopPut (result, zero, offset++);
4800 /*-----------------------------------------------------------------*/
4801 /* genMinusBits - generates code for subtraction of two bits */
4802 /*-----------------------------------------------------------------*/
4804 genMinusBits (iCode * ic)
4806 symbol *lbl = newiTempLabel (NULL);
4808 D (emitcode (";", "genMinusBits"));
4810 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4812 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4813 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4814 emitcode ("cpl", "c");
4816 outBitC (IC_RESULT (ic));
4820 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4821 emitcode ("subb", "a,acc");
4822 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4823 emitcode ("inc", "a");
4825 aopPut (IC_RESULT (ic), "a", 0);
4826 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4830 /*-----------------------------------------------------------------*/
4831 /* genMinus - generates code for subtraction */
4832 /*-----------------------------------------------------------------*/
4834 genMinus (iCode * ic)
4836 int size, offset = 0;
4838 D (emitcode (";", "genMinus"));
4840 aopOp (IC_LEFT (ic), ic, FALSE);
4841 aopOp (IC_RIGHT (ic), ic, FALSE);
4842 aopOp (IC_RESULT (ic), ic, TRUE);
4844 /* special cases :- */
4845 /* if both left & right are in bit space */
4846 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4847 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4853 /* if I can do an decrement instead
4854 of subtract then GOOD for ME */
4855 if (genMinusDec (ic) == TRUE)
4858 size = getDataSize (IC_RESULT (ic));
4860 /* if literal, add a,#-lit, else normal subb */
4861 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4863 unsigned long lit = 0L;
4864 bool useCarry = FALSE;
4866 lit = ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4871 if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4873 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4874 if (!offset && !size && lit== (unsigned long) -1)
4876 emitcode ("dec", "a");
4880 /* first add without previous c */
4881 emitcode ("add", "a,#0x%02x",
4882 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4887 emitcode ("addc", "a,#0x%02x",
4888 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4890 aopPut (IC_RESULT (ic), "a", offset++);
4894 /* no need to add zeroes */
4895 if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4897 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4906 operand *leftOp, *rightOp;
4908 leftOp = IC_LEFT(ic);
4909 rightOp = IC_RIGHT(ic);
4913 if (aopGetUsesAcc(rightOp, offset)) {
4914 if (aopGetUsesAcc(leftOp, offset)) {
4917 MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4919 emitcode ("mov", "b,a");
4922 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4923 emitcode ("subb", "a,b");
4926 /* reverse subtraction with 2's complement */
4928 emitcode( "setb", "c");
4930 emitcode( "cpl", "c");
4931 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4932 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4933 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4934 emitcode("cpl", "a");
4935 if (size) /* skip if last byte */
4936 emitcode( "cpl", "c");
4939 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4942 emitcode ("subb", "a,%s",
4943 aopGet(rightOp, offset, FALSE, TRUE));
4946 aopPut (IC_RESULT (ic), "a", offset++);
4950 adjustArithmeticResult (ic);
4953 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4954 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4955 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4959 /*-----------------------------------------------------------------*/
4960 /* genMultbits :- multiplication of bits */
4961 /*-----------------------------------------------------------------*/
4963 genMultbits (operand * left,
4967 D (emitcode (";", "genMultbits"));
4969 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4970 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4974 /*-----------------------------------------------------------------*/
4975 /* genMultOneByte : 8*8=8/16 bit multiplication */
4976 /*-----------------------------------------------------------------*/
4978 genMultOneByte (operand * left,
4983 int size = AOP_SIZE (result);
4984 bool runtimeSign, compiletimeSign;
4985 bool lUnsigned, rUnsigned, pushedB;
4987 D (emitcode (";", "genMultOneByte"));
4989 if (size < 1 || size > 2)
4991 /* this should never happen */
4992 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4993 AOP_SIZE(result), __FILE__, lineno);
4997 /* (if two literals: the value is computed before) */
4998 /* if one literal, literal on the right */
4999 if (AOP_TYPE (left) == AOP_LIT)
5004 /* emitcode (";", "swapped left and right"); */
5006 /* if no literal, unsigned on the right: shorter code */
5007 if ( AOP_TYPE (right) != AOP_LIT
5008 && SPEC_USIGN (getSpec (operandType (left))))
5015 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5016 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5020 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
5021 no need to take care about the signedness! */
5022 || (lUnsigned && rUnsigned))
5024 /* just an unsigned 8 * 8 = 8 multiply
5026 /* emitcode (";","unsigned"); */
5027 /* TODO: check for accumulator clash between left & right aops? */
5029 if (AOP_TYPE (right) == AOP_LIT)
5031 /* moving to accumulator first helps peepholes */
5032 MOVA (aopGet (left, 0, FALSE, FALSE));
5033 MOVB (aopGet (right, 0, FALSE, FALSE));
5037 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5038 MOVA (aopGet (left, 0, FALSE, FALSE));
5041 emitcode ("mul", "ab");
5042 aopPut (result, "a", 0);
5044 aopPut (result, "b", 1);
5050 /* we have to do a signed multiply */
5051 /* emitcode (";", "signed"); */
5053 /* now sign adjust for both left & right */
5055 /* let's see what's needed: */
5056 /* apply negative sign during runtime */
5057 runtimeSign = FALSE;
5058 /* negative sign from literals */
5059 compiletimeSign = FALSE;
5063 if (AOP_TYPE(left) == AOP_LIT)
5065 /* signed literal */
5066 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5068 compiletimeSign = TRUE;
5071 /* signed but not literal */
5077 if (AOP_TYPE(right) == AOP_LIT)
5079 /* signed literal */
5080 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
5082 compiletimeSign ^= TRUE;
5085 /* signed but not literal */
5089 /* initialize F0, which stores the runtime sign */
5092 if (compiletimeSign)
5093 emitcode ("setb", "F0"); /* set sign flag */
5095 emitcode ("clr", "F0"); /* reset sign flag */
5098 /* save the signs of the operands */
5099 if (AOP_TYPE(right) == AOP_LIT)
5101 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
5103 if (!rUnsigned && val < 0)
5104 emitcode ("mov", "b,#0x%02x", -val);
5106 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5108 else /* ! literal */
5110 if (rUnsigned) /* emitcode (";", "signed"); */
5111 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5114 MOVA (aopGet (right, 0, FALSE, FALSE));
5115 lbl = newiTempLabel (NULL);
5116 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5117 emitcode ("cpl", "F0"); /* complement sign flag */
5118 emitcode ("cpl", "a"); /* 2's complement */
5119 emitcode ("inc", "a");
5121 emitcode ("mov", "b,a");
5125 if (AOP_TYPE(left) == AOP_LIT)
5127 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5129 if (!lUnsigned && val < 0)
5130 emitcode ("mov", "a,#0x%02x", -val);
5132 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5134 else /* ! literal */
5136 MOVA (aopGet (left, 0, FALSE, FALSE));
5140 lbl = newiTempLabel (NULL);
5141 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5142 emitcode ("cpl", "F0"); /* complement sign flag */
5143 emitcode ("cpl", "a"); /* 2's complement */
5144 emitcode ("inc", "a");
5149 /* now the multiplication */
5150 emitcode ("mul", "ab");
5151 if (runtimeSign || compiletimeSign)
5153 lbl = newiTempLabel (NULL);
5155 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5156 emitcode ("cpl", "a"); /* lsb 2's complement */
5158 emitcode ("inc", "a"); /* inc doesn't set carry flag */
5161 emitcode ("add", "a,#1"); /* this sets carry flag */
5162 emitcode ("xch", "a,b");
5163 emitcode ("cpl", "a"); /* msb 2's complement */
5164 emitcode ("addc", "a,#0");
5165 emitcode ("xch", "a,b");
5169 aopPut (result, "a", 0);
5171 aopPut (result, "b", 1);
5176 /*-----------------------------------------------------------------*/
5177 /* genMult - generates code for multiplication */
5178 /*-----------------------------------------------------------------*/
5180 genMult (iCode * ic)
5182 operand *left = IC_LEFT (ic);
5183 operand *right = IC_RIGHT (ic);
5184 operand *result = IC_RESULT (ic);
5186 D (emitcode (";", "genMult"));
5188 /* assign the asmops */
5189 aopOp (left, ic, FALSE);
5190 aopOp (right, ic, FALSE);
5191 aopOp (result, ic, TRUE);
5193 /* special cases first */
5195 if (AOP_TYPE (left) == AOP_CRY &&
5196 AOP_TYPE (right) == AOP_CRY)
5198 genMultbits (left, right, result);
5202 /* if both are of size == 1 */
5203 #if 0 // one of them can be a sloc shared with the result
5204 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
5206 if (getSize(operandType(left)) == 1 &&
5207 getSize(operandType(right)) == 1)
5210 genMultOneByte (left, right, result);
5214 /* should have been converted to function call */
5215 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
5216 getSize(OP_SYMBOL(right)->type));
5220 freeAsmop (result, NULL, ic, TRUE);
5221 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5222 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5225 /*-----------------------------------------------------------------*/
5226 /* genDivbits :- division of bits */
5227 /*-----------------------------------------------------------------*/
5229 genDivbits (operand * left,
5236 D(emitcode (";", "genDivbits"));
5240 /* the result must be bit */
5241 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5242 l = aopGet (left, 0, FALSE, FALSE);
5246 emitcode ("div", "ab");
5247 emitcode ("rrc", "a");
5251 aopPut (result, "c", 0);
5254 /*-----------------------------------------------------------------*/
5255 /* genDivOneByte : 8 bit division */
5256 /*-----------------------------------------------------------------*/
5258 genDivOneByte (operand * left,
5262 bool lUnsigned, rUnsigned, pushedB;
5263 bool runtimeSign, compiletimeSign;
5264 bool accuse = FALSE;
5265 bool pushedA = FALSE;
5269 D(emitcode (";", "genDivOneByte"));
5271 /* Why is it necessary that genDivOneByte() can return an int result?
5274 volatile unsigned char uc;
5275 volatile signed char sc1, sc2;
5288 In all cases a one byte result would overflow, the following cast to int
5289 would return the wrong result.
5291 Two possible solution:
5292 a) cast operands to int, if ((unsigned) / (signed)) or
5293 ((signed) / (signed))
5294 b) return an 16 bit signed int; this is what we're doing here!
5297 size = AOP_SIZE (result) - 1;
5299 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5300 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5304 /* signed or unsigned */
5305 if (lUnsigned && rUnsigned)
5307 /* unsigned is easy */
5308 MOVB (aopGet (right, 0, FALSE, FALSE));
5309 MOVA (aopGet (left, 0, FALSE, FALSE));
5310 emitcode ("div", "ab");
5311 aopPut (result, "a", 0);
5313 aopPut (result, zero, offset++);
5319 /* signed is a little bit more difficult */
5321 /* now sign adjust for both left & right */
5323 /* let's see what's needed: */
5324 /* apply negative sign during runtime */
5325 runtimeSign = FALSE;
5326 /* negative sign from literals */
5327 compiletimeSign = FALSE;
5331 if (AOP_TYPE(left) == AOP_LIT)
5333 /* signed literal */
5334 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5336 compiletimeSign = TRUE;
5339 /* signed but not literal */
5345 if (AOP_TYPE(right) == AOP_LIT)
5347 /* signed literal */
5348 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
5350 compiletimeSign ^= TRUE;
5353 /* signed but not literal */
5357 /* initialize F0, which stores the runtime sign */
5360 if (compiletimeSign)
5361 emitcode ("setb", "F0"); /* set sign flag */
5363 emitcode ("clr", "F0"); /* reset sign flag */
5366 /* save the signs of the operands */
5367 if (AOP_TYPE(right) == AOP_LIT)
5369 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
5371 if (!rUnsigned && val < 0)
5372 emitcode ("mov", "b,#0x%02x", -val);
5374 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5376 else /* ! literal */
5379 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5382 MOVA (aopGet (right, 0, FALSE, FALSE));
5383 lbl = newiTempLabel (NULL);
5384 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5385 emitcode ("cpl", "F0"); /* complement sign flag */
5386 emitcode ("cpl", "a"); /* 2's complement */
5387 emitcode ("inc", "a");
5389 emitcode ("mov", "b,a");
5393 if (AOP_TYPE(left) == AOP_LIT)
5395 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5397 if (!lUnsigned && val < 0)
5398 emitcode ("mov", "a,#0x%02x", -val);
5400 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5402 else /* ! literal */
5404 MOVA (aopGet (left, 0, FALSE, FALSE));
5408 lbl = newiTempLabel (NULL);
5409 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5410 emitcode ("cpl", "F0"); /* complement sign flag */
5411 emitcode ("cpl", "a"); /* 2's complement */
5412 emitcode ("inc", "a");
5417 /* now the division */
5418 emitcode ("div", "ab");
5420 if (runtimeSign || compiletimeSign)
5422 lbl = newiTempLabel (NULL);
5424 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5425 emitcode ("cpl", "a"); /* lsb 2's complement */
5426 emitcode ("inc", "a");
5429 accuse = aopPut (result, "a", 0);
5432 /* msb is 0x00 or 0xff depending on the sign */
5437 emitcode ("push", "acc");
5440 emitcode ("mov", "c,F0");
5441 emitcode ("subb", "a,acc");
5443 aopPut (result, "a", offset++);
5445 else /* compiletimeSign */
5447 if (aopPutUsesAcc (result, "#0xFF", offset))
5449 emitcode ("push", "acc");
5453 aopPut (result, "#0xff", offset++);
5459 aopPut (result, "a", 0);
5461 aopPut (result, zero, offset++);
5465 emitcode ("pop", "acc");
5469 /*-----------------------------------------------------------------*/
5470 /* genDiv - generates code for division */
5471 /*-----------------------------------------------------------------*/
5475 operand *left = IC_LEFT (ic);
5476 operand *right = IC_RIGHT (ic);
5477 operand *result = IC_RESULT (ic);
5479 D (emitcode (";", "genDiv"));
5481 /* assign the asmops */
5482 aopOp (left, ic, FALSE);
5483 aopOp (right, ic, FALSE);
5484 aopOp (result, ic, TRUE);
5486 /* special cases first */
5488 if (AOP_TYPE (left) == AOP_CRY &&
5489 AOP_TYPE (right) == AOP_CRY)
5491 genDivbits (left, right, result);
5495 /* if both are of size == 1 */
5496 if (AOP_SIZE (left) == 1 &&
5497 AOP_SIZE (right) == 1)
5499 genDivOneByte (left, right, result);
5503 /* should have been converted to function call */
5506 freeAsmop (result, NULL, ic, TRUE);
5507 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5508 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5511 /*-----------------------------------------------------------------*/
5512 /* genModbits :- modulus of bits */
5513 /*-----------------------------------------------------------------*/
5515 genModbits (operand * left,
5522 D (emitcode (";", "genModbits"));
5526 /* the result must be bit */
5527 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5528 l = aopGet (left, 0, FALSE, FALSE);
5532 emitcode ("div", "ab");
5533 emitcode ("mov", "a,b");
5534 emitcode ("rrc", "a");
5538 aopPut (result, "c", 0);
5541 /*-----------------------------------------------------------------*/
5542 /* genModOneByte : 8 bit modulus */
5543 /*-----------------------------------------------------------------*/
5545 genModOneByte (operand * left,
5549 bool lUnsigned, rUnsigned, pushedB;
5550 bool runtimeSign, compiletimeSign;
5554 D (emitcode (";", "genModOneByte"));
5556 size = AOP_SIZE (result) - 1;
5558 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5559 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5561 /* if right is a literal, check it for 2^n */
5562 if (AOP_TYPE(right) == AOP_LIT)
5564 unsigned char val = abs((int) operandLitValue(right));
5565 symbol *lbl2 = NULL;
5569 case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5578 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5579 "modulus of unsigned char by 2^n literal shouldn't be processed here");
5580 /* because iCode should have been changed to genAnd */
5581 /* see file "SDCCopt.c", function "convertToFcall()" */
5583 MOVA (aopGet (left, 0, FALSE, FALSE));
5584 emitcode ("mov", "c,acc.7");
5585 emitcode ("anl", "a,#0x%02x", val - 1);
5586 lbl = newiTempLabel (NULL);
5587 emitcode ("jz", "%05d$", (lbl->key + 100));
5588 emitcode ("jnc", "%05d$", (lbl->key + 100));
5589 emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5595 aopPut (result, "a", 0);
5597 aopPut (result, "#0xff", offs2++);
5598 lbl2 = newiTempLabel (NULL);
5599 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5602 aopPut (result, "a", 0);
5604 aopPut (result, zero, offset++);
5618 /* signed or unsigned */
5619 if (lUnsigned && rUnsigned)
5621 /* unsigned is easy */
5622 MOVB (aopGet (right, 0, FALSE, FALSE));
5623 MOVA (aopGet (left, 0, FALSE, FALSE));
5624 emitcode ("div", "ab");
5625 aopPut (result, "b", 0);
5627 aopPut (result, zero, offset++);
5633 /* signed is a little bit more difficult */
5635 /* now sign adjust for both left & right */
5637 /* modulus: sign of the right operand has no influence on the result! */
5638 if (AOP_TYPE(right) == AOP_LIT)
5640 signed char val = (char) operandLitValue(right);
5642 if (!rUnsigned && val < 0)
5643 emitcode ("mov", "b,#0x%02x", -val);
5645 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5647 else /* not literal */
5650 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5653 MOVA (aopGet (right, 0, FALSE, FALSE));
5654 lbl = newiTempLabel (NULL);
5655 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5656 emitcode ("cpl", "a"); /* 2's complement */
5657 emitcode ("inc", "a");
5659 emitcode ("mov", "b,a");
5663 /* let's see what's needed: */
5664 /* apply negative sign during runtime */
5665 runtimeSign = FALSE;
5666 /* negative sign from literals */
5667 compiletimeSign = FALSE;
5669 /* sign adjust left side */
5670 if (AOP_TYPE(left) == AOP_LIT)
5672 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5674 if (!lUnsigned && val < 0)
5676 compiletimeSign = TRUE; /* set sign flag */
5677 emitcode ("mov", "a,#0x%02x", -val);
5680 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5682 else /* ! literal */
5684 MOVA (aopGet (left, 0, FALSE, FALSE));
5689 emitcode ("clr", "F0"); /* clear sign flag */
5691 lbl = newiTempLabel (NULL);
5692 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5693 emitcode ("setb", "F0"); /* set sign flag */
5694 emitcode ("cpl", "a"); /* 2's complement */
5695 emitcode ("inc", "a");
5700 /* now the modulus */
5701 emitcode ("div", "ab");
5703 if (runtimeSign || compiletimeSign)
5705 emitcode ("mov", "a,b");
5706 lbl = newiTempLabel (NULL);
5708 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5709 emitcode ("cpl", "a"); /* 2's complement */
5710 emitcode ("inc", "a");
5713 aopPut (result, "a", 0);
5716 /* msb is 0x00 or 0xff depending on the sign */
5719 emitcode ("mov", "c,F0");
5720 emitcode ("subb", "a,acc");
5722 aopPut (result, "a", offset++);
5724 else /* compiletimeSign */
5726 aopPut (result, "#0xff", offset++);
5731 aopPut (result, "b", 0);
5733 aopPut (result, zero, offset++);
5739 /*-----------------------------------------------------------------*/
5740 /* genMod - generates code for division */
5741 /*-----------------------------------------------------------------*/
5745 operand *left = IC_LEFT (ic);
5746 operand *right = IC_RIGHT (ic);
5747 operand *result = IC_RESULT (ic);
5749 D (emitcode (";", "genMod"));
5751 /* assign the asmops */
5752 aopOp (left, ic, FALSE);
5753 aopOp (right, ic, FALSE);
5754 aopOp (result, ic, TRUE);
5756 /* special cases first */
5758 if (AOP_TYPE (left) == AOP_CRY &&
5759 AOP_TYPE (right) == AOP_CRY)
5761 genModbits (left, right, result);
5765 /* if both are of size == 1 */
5766 if (AOP_SIZE (left) == 1 &&
5767 AOP_SIZE (right) == 1)
5769 genModOneByte (left, right, result);
5773 /* should have been converted to function call */
5777 freeAsmop (result, NULL, ic, TRUE);
5778 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5779 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5782 /*-----------------------------------------------------------------*/
5783 /* genIfxJump :- will create a jump depending on the ifx */
5784 /*-----------------------------------------------------------------*/
5786 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5789 symbol *tlbl = newiTempLabel (NULL);
5792 D (emitcode (";", "genIfxJump"));
5794 /* if true label then we jump if condition
5798 jlbl = IC_TRUE (ic);
5799 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5800 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5804 /* false label is present */
5805 jlbl = IC_FALSE (ic);
5806 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5807 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5809 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5810 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5812 emitcode (inst, "%05d$", tlbl->key + 100);
5813 freeForBranchAsmop (result);
5814 freeForBranchAsmop (right);
5815 freeForBranchAsmop (left);
5816 emitcode ("ljmp", "%05d$", jlbl->key + 100);
5819 /* mark the icode as generated */
5823 /*-----------------------------------------------------------------*/
5824 /* genCmp :- greater or less than comparison */
5825 /*-----------------------------------------------------------------*/
5827 genCmp (operand * left, operand * right,
5828 operand * result, iCode * ifx, int sign, iCode *ic)
5830 int size, offset = 0;
5831 unsigned long lit = 0L;
5834 D (emitcode (";", "genCmp"));
5836 /* if left & right are bit variables */
5837 if (AOP_TYPE (left) == AOP_CRY &&
5838 AOP_TYPE (right) == AOP_CRY)
5840 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5841 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5845 /* subtract right from left if at the
5846 end the carry flag is set then we know that
5847 left is greater than right */
5848 size = max (AOP_SIZE (left), AOP_SIZE (right));
5850 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5851 if ((size == 1) && !sign &&
5852 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5854 symbol *lbl = newiTempLabel (NULL);
5855 emitcode ("cjne", "%s,%s,%05d$",
5856 aopGet (left, offset, FALSE, FALSE),
5857 aopGet (right, offset, FALSE, FALSE),
5863 if (AOP_TYPE (right) == AOP_LIT)
5865 lit = ulFromVal (AOP (right)->aopu.aop_lit);
5866 /* optimize if(x < 0) or if(x >= 0) */
5875 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5876 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5878 genIfxJump (ifx, "acc.7", left, right, result);
5879 freeAsmop (right, NULL, ic, TRUE);
5880 freeAsmop (left, NULL, ic, TRUE);
5886 emitcode ("rlc", "a");
5893 int bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5894 while (size && (bytelit == 0))
5897 bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5903 MOVA (aopGet (left, offset, FALSE, FALSE));
5904 if (sign && size == 0)
5906 emitcode ("xrl", "a,#0x80");
5907 emitcode ("subb", "a,#0x%02x",
5908 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5912 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5922 bool pushedB = FALSE;
5923 rightInB = aopGetUsesAcc(right, offset);
5927 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5929 MOVA (aopGet (left, offset, FALSE, FALSE));
5930 if (sign && size == 0)
5932 emitcode ("xrl", "a,#0x80");
5937 MOVB (aopGet (right, offset, FALSE, FALSE));
5939 emitcode ("xrl", "b,#0x80");
5940 emitcode ("subb", "a,b");
5945 emitcode ("subb", "a,b");
5947 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5957 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5958 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5959 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5965 /* if the result is used in the next
5966 ifx conditional branch then generate
5967 code a little differently */
5970 genIfxJump (ifx, "c", NULL, NULL, result);
5976 /* leave the result in acc */
5980 /*-----------------------------------------------------------------*/
5981 /* genCmpGt :- greater than comparison */
5982 /*-----------------------------------------------------------------*/
5984 genCmpGt (iCode * ic, iCode * ifx)
5986 operand *left, *right, *result;
5987 sym_link *letype, *retype;
5990 D (emitcode (";", "genCmpGt"));
5992 left = IC_LEFT (ic);
5993 right = IC_RIGHT (ic);
5994 result = IC_RESULT (ic);
5996 letype = getSpec (operandType (left));
5997 retype = getSpec (operandType (right));
5998 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5999 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
6000 /* assign the asmops */
6001 aopOp (result, ic, TRUE);
6002 aopOp (left, ic, FALSE);
6003 aopOp (right, ic, FALSE);
6005 genCmp (right, left, result, ifx, sign, ic);
6007 freeAsmop (result, NULL, ic, TRUE);
6010 /*-----------------------------------------------------------------*/
6011 /* genCmpLt - less than comparisons */
6012 /*-----------------------------------------------------------------*/
6014 genCmpLt (iCode * ic, iCode * ifx)
6016 operand *left, *right, *result;
6017 sym_link *letype, *retype;
6020 D (emitcode (";", "genCmpLt"));
6022 left = IC_LEFT (ic);
6023 right = IC_RIGHT (ic);
6024 result = IC_RESULT (ic);
6026 letype = getSpec (operandType (left));
6027 retype = getSpec (operandType (right));
6028 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
6029 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
6030 /* assign the asmops */
6031 aopOp (result, ic, TRUE);
6032 aopOp (left, ic, FALSE);
6033 aopOp (right, ic, FALSE);
6035 genCmp (left, right, result, ifx, sign, ic);
6037 freeAsmop (result, NULL, ic, TRUE);
6040 /*-----------------------------------------------------------------*/
6041 /* gencjneshort - compare and jump if not equal */
6042 /*-----------------------------------------------------------------*/
6044 gencjneshort (operand * left, operand * right, symbol * lbl)
6046 int size = max (AOP_SIZE (left), AOP_SIZE (right));
6048 unsigned long lit = 0L;
6050 D (emitcode (";", "gencjneshort"));
6052 /* if the left side is a literal or
6053 if the right is in a pointer register and left
6055 if ((AOP_TYPE (left) == AOP_LIT) ||
6056 (AOP_TYPE (left) == AOP_IMMD) ||
6057 (AOP_TYPE (left) == AOP_DIR) ||
6058 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6065 if (AOP_TYPE (right) == AOP_LIT)
6066 lit = ulFromVal (AOP (right)->aopu.aop_lit);
6068 /* if the right side is a literal then anything goes */
6069 if (AOP_TYPE (right) == AOP_LIT &&
6070 AOP_TYPE (left) != AOP_DIR &&
6071 AOP_TYPE (left) != AOP_IMMD)
6075 emitcode ("cjne", "%s,%s,%05d$",
6076 aopGet (left, offset, FALSE, FALSE),
6077 aopGet (right, offset, FALSE, FALSE),
6083 /* if the right side is in a register or in direct space or
6084 if the left is a pointer register & right is not */
6085 else if (AOP_TYPE (right) == AOP_REG ||
6086 AOP_TYPE (right) == AOP_DIR ||
6087 AOP_TYPE (right) == AOP_LIT ||
6088 AOP_TYPE (right) == AOP_IMMD ||
6089 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6090 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6094 MOVA (aopGet (left, offset, FALSE, FALSE));
6095 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6096 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6097 emitcode ("jnz", "%05d$", lbl->key + 100);
6099 emitcode ("cjne", "a,%s,%05d$",
6100 aopGet (right, offset, FALSE, TRUE),
6107 /* right is a pointer reg need both a & b */
6110 //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
6111 wassertl(!BINUSE, "B was in use");
6112 MOVB (aopGet (left, offset, FALSE, FALSE));
6113 MOVA (aopGet (right, offset, FALSE, FALSE));
6114 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
6120 /*-----------------------------------------------------------------*/
6121 /* gencjne - compare and jump if not equal */
6122 /*-----------------------------------------------------------------*/
6124 gencjne (operand * left, operand * right, symbol * lbl, bool useCarry)
6126 symbol *tlbl = newiTempLabel (NULL);
6128 D (emitcode (";", "gencjne"));
6130 gencjneshort (left, right, lbl);
6136 emitcode ("sjmp", "%05d$", tlbl->key + 100);
6145 /*-----------------------------------------------------------------*/
6146 /* genCmpEq - generates code for equal to */
6147 /*-----------------------------------------------------------------*/
6149 genCmpEq (iCode * ic, iCode * ifx)
6151 bool swappedLR = FALSE;
6152 operand *left, *right, *result;
6154 D (emitcode (";", "genCmpEq"));
6156 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6157 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6158 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6160 /* if literal, literal on the right or
6161 if the right is in a pointer register and left
6163 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6164 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6166 operand *t = IC_RIGHT (ic);
6167 IC_RIGHT (ic) = IC_LEFT (ic);
6172 if (ifx && !AOP_SIZE (result))
6175 /* if they are both bit variables */
6176 if (AOP_TYPE (left) == AOP_CRY &&
6177 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6179 if (AOP_TYPE (right) == AOP_LIT)
6181 unsigned long lit = ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6184 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6185 emitcode ("cpl", "c");
6189 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6193 emitcode ("clr", "c");
6195 /* AOP_TYPE(right) == AOP_CRY */
6199 symbol *lbl = newiTempLabel (NULL);
6200 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6201 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6202 emitcode ("cpl", "c");
6205 /* if true label then we jump if condition
6207 tlbl = newiTempLabel (NULL);
6210 emitcode ("jnc", "%05d$", tlbl->key + 100);
6211 freeForBranchAsmop (result);
6212 freeForBranchAsmop (right);
6213 freeForBranchAsmop (left);
6214 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6218 emitcode ("jc", "%05d$", tlbl->key + 100);
6219 freeForBranchAsmop (result);
6220 freeForBranchAsmop (right);
6221 freeForBranchAsmop (left);
6222 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6228 tlbl = newiTempLabel (NULL);
6229 gencjneshort (left, right, tlbl);
6232 freeForBranchAsmop (result);
6233 freeForBranchAsmop (right);
6234 freeForBranchAsmop (left);
6235 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6240 symbol *lbl = newiTempLabel (NULL);
6241 emitcode ("sjmp", "%05d$", lbl->key + 100);
6243 freeForBranchAsmop (result);
6244 freeForBranchAsmop (right);
6245 freeForBranchAsmop (left);
6246 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6250 /* mark the icode as generated */
6255 /* if they are both bit variables */
6256 if (AOP_TYPE (left) == AOP_CRY &&
6257 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6259 if (AOP_TYPE (right) == AOP_LIT)
6261 unsigned long lit = ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6264 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6265 emitcode ("cpl", "c");
6269 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6273 emitcode ("clr", "c");
6275 /* AOP_TYPE(right) == AOP_CRY */
6279 symbol *lbl = newiTempLabel (NULL);
6280 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6281 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6282 emitcode ("cpl", "c");
6286 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6293 genIfxJump (ifx, "c", left, right, result);
6296 /* if the result is used in an arithmetic operation
6297 then put the result in place */
6302 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6304 gencjne (left, right, newiTempLabel (NULL), TRUE);
6305 aopPut (result, "c", 0);
6308 gencjne (left, right, newiTempLabel (NULL), FALSE);
6311 genIfxJump (ifx, "a", left, right, result);
6314 /* if the result is used in an arithmetic operation
6315 then put the result in place */
6316 if (AOP_TYPE (result) != AOP_CRY)
6318 /* leave the result in acc */
6322 freeAsmop (result, NULL, ic, TRUE);
6325 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6326 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6330 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6331 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6335 /*-----------------------------------------------------------------*/
6336 /* ifxForOp - returns the icode containing the ifx for operand */
6337 /*-----------------------------------------------------------------*/
6339 ifxForOp (operand * op, iCode * ic)
6341 /* if true symbol then needs to be assigned */
6342 if (IS_TRUE_SYMOP (op))
6345 /* if this has register type condition and
6346 the next instruction is ifx with the same operand
6347 and live to of the operand is upto the ifx only then */
6349 ic->next->op == IFX &&
6350 IC_COND (ic->next)->key == op->key &&
6351 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6357 /*-----------------------------------------------------------------*/
6358 /* hasInc - operand is incremented before any other use */
6359 /*-----------------------------------------------------------------*/
6361 hasInc (operand *op, iCode *ic, int osize)
6363 sym_link *type = operandType(op);
6364 sym_link *retype = getSpec (type);
6365 iCode *lic = ic->next;
6368 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6369 if (!IS_SYMOP(op)) return NULL;
6371 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6372 if (IS_AGGREGATE(type->next)) return NULL;
6373 if (osize != (isize = getSize(type->next))) return NULL;
6376 /* if operand of the form op = op + <sizeof *op> */
6377 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6378 isOperandEqual(IC_RESULT(lic),op) &&
6379 isOperandLiteral(IC_RIGHT(lic)) &&
6380 operandLitValue(IC_RIGHT(lic)) == isize) {
6383 /* if the operand used or deffed */
6384 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6387 /* if GOTO or IFX */
6388 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6394 /*-----------------------------------------------------------------*/
6395 /* genAndOp - for && operation */
6396 /*-----------------------------------------------------------------*/
6398 genAndOp (iCode * ic)
6400 operand *left, *right, *result;
6403 D (emitcode (";", "genAndOp"));
6405 /* note here that && operations that are in an
6406 if statement are taken away by backPatchLabels
6407 only those used in arthmetic operations remain */
6408 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6409 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6410 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6412 /* if both are bit variables */
6413 if (AOP_TYPE (left) == AOP_CRY &&
6414 AOP_TYPE (right) == AOP_CRY)
6416 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6417 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6422 tlbl = newiTempLabel (NULL);
6424 emitcode ("jz", "%05d$", tlbl->key + 100);
6430 freeAsmop (result, NULL, ic, TRUE);
6431 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6432 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6436 /*-----------------------------------------------------------------*/
6437 /* genOrOp - for || operation */
6438 /*-----------------------------------------------------------------*/
6440 genOrOp (iCode * ic)
6442 operand *left, *right, *result;
6445 D (emitcode (";", "genOrOp"));
6447 /* note here that || operations that are in an
6448 if statement are taken away by backPatchLabels
6449 only those used in arthmetic operations remain */
6450 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6451 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6452 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6454 /* if both are bit variables */
6455 if (AOP_TYPE (left) == AOP_CRY &&
6456 AOP_TYPE (right) == AOP_CRY)
6458 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6459 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6464 tlbl = newiTempLabel (NULL);
6466 emitcode ("jnz", "%05d$", tlbl->key + 100);
6472 freeAsmop (result, NULL, ic, TRUE);
6473 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6474 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6477 /*-----------------------------------------------------------------*/
6478 /* isLiteralBit - test if lit == 2^n */
6479 /*-----------------------------------------------------------------*/
6481 isLiteralBit (unsigned long lit)
6483 unsigned long pw[32] =
6484 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6485 0x100L, 0x200L, 0x400L, 0x800L,
6486 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6487 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6488 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6489 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6490 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6493 for (idx = 0; idx < 32; idx++)
6499 /*-----------------------------------------------------------------*/
6500 /* continueIfTrue - */
6501 /*-----------------------------------------------------------------*/
6503 continueIfTrue (iCode * ic)
6506 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6510 /*-----------------------------------------------------------------*/
6512 /*-----------------------------------------------------------------*/
6514 jumpIfTrue (iCode * ic)
6517 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6521 /*-----------------------------------------------------------------*/
6522 /* jmpTrueOrFalse - */
6523 /*-----------------------------------------------------------------*/
6525 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6527 // ugly but optimized by peephole
6530 symbol *nlbl = newiTempLabel (NULL);
6531 emitcode ("sjmp", "%05d$", nlbl->key + 100);
6533 freeForBranchAsmop (result);
6534 freeForBranchAsmop (right);
6535 freeForBranchAsmop (left);
6536 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6541 freeForBranchAsmop (result);
6542 freeForBranchAsmop (right);
6543 freeForBranchAsmop (left);
6544 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6550 /*-----------------------------------------------------------------*/
6551 /* genAnd - code for and */
6552 /*-----------------------------------------------------------------*/
6554 genAnd (iCode * ic, iCode * ifx)
6556 operand *left, *right, *result;
6557 int size, offset = 0;
6558 unsigned long lit = 0L;
6562 D (emitcode (";", "genAnd"));
6564 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6565 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6566 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6569 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
6571 AOP_TYPE (left), AOP_TYPE (right));
6572 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
6574 AOP_SIZE (left), AOP_SIZE (right));
6577 /* if left is a literal & right is not then exchange them */
6578 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6579 AOP_NEEDSACC (left))
6581 operand *tmp = right;
6586 /* if result = right then exchange left and right */
6587 if (sameRegs (AOP (result), AOP (right)))
6589 operand *tmp = right;
6594 /* if right is bit then exchange them */
6595 if (AOP_TYPE (right) == AOP_CRY &&
6596 AOP_TYPE (left) != AOP_CRY)
6598 operand *tmp = right;
6602 if (AOP_TYPE (right) == AOP_LIT)
6603 lit = ulFromVal (AOP (right)->aopu.aop_lit);
6605 size = AOP_SIZE (result);
6608 // result = bit & yy;
6609 if (AOP_TYPE (left) == AOP_CRY)
6611 // c = bit & literal;
6612 if (AOP_TYPE (right) == AOP_LIT)
6616 if (size && sameRegs (AOP (result), AOP (left)))
6619 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6624 if (size && (AOP_TYPE (result) == AOP_CRY))
6626 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6629 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6634 emitcode ("clr", "c");
6639 if (AOP_TYPE (right) == AOP_CRY)
6642 if (IS_OP_ACCUSE (left))
6644 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6648 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6649 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6655 MOVA (aopGet (right, 0, FALSE, FALSE));
6657 emitcode ("rrc", "a");
6658 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6666 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6667 genIfxJump (ifx, "c", left, right, result);
6671 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6672 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6673 if ((AOP_TYPE (right) == AOP_LIT) &&
6674 (AOP_TYPE (result) == AOP_CRY) &&
6675 (AOP_TYPE (left) != AOP_CRY))
6677 int posbit = isLiteralBit (lit);
6682 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6686 switch (posbit & 0x07)
6688 case 0: emitcode ("rrc", "a");
6690 case 7: emitcode ("rlc", "a");
6692 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6701 SNPRINTF (buffer, sizeof(buffer),
6702 "acc.%d", posbit & 0x07);
6703 genIfxJump (ifx, buffer, left, right, result);
6706 {// what is this case? just found it in ds390/gen.c
6707 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6714 symbol *tlbl = newiTempLabel (NULL);
6715 int sizel = AOP_SIZE (left);
6717 emitcode ("setb", "c");
6720 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6722 MOVA (aopGet (left, offset, FALSE, FALSE));
6724 if ((posbit = isLiteralBit (bytelit)) != 0)
6725 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6728 if (bytelit != 0x0FFL)
6729 emitcode ("anl", "a,%s",
6730 aopGet (right, offset, FALSE, TRUE));
6731 emitcode ("jnz", "%05d$", tlbl->key + 100);
6736 // bit = left & literal
6739 emitcode ("clr", "c");
6742 // if(left & literal)
6746 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6756 /* if left is same as result */
6757 if (sameRegs (AOP (result), AOP (left)))
6759 for (; size--; offset++)
6761 if (AOP_TYPE (right) == AOP_LIT)
6763 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6764 if (bytelit == 0x0FF)
6766 /* dummy read of volatile operand */
6767 if (isOperandVolatile (left, FALSE))
6768 MOVA (aopGet (left, offset, FALSE, FALSE));
6772 else if (bytelit == 0)
6774 aopPut (result, zero, offset);
6776 else if (IS_AOP_PREG (result))
6778 MOVA (aopGet (left, offset, FALSE, TRUE));
6779 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6780 aopPut (result, "a", offset);
6783 emitcode ("anl", "%s,%s",
6784 aopGet (left, offset, FALSE, TRUE),
6785 aopGet (right, offset, FALSE, FALSE));
6789 if (AOP_TYPE (left) == AOP_ACC)
6792 emitcode("mov", "a,b");
6793 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6795 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6797 MOVB (aopGet (left, offset, FALSE, FALSE));
6798 MOVA (aopGet (right, offset, FALSE, FALSE));
6799 emitcode ("anl", "a,b");
6800 aopPut (result, "a", offset);
6802 else if (aopGetUsesAcc (left, offset))
6804 MOVA (aopGet (left, offset, FALSE, FALSE));
6805 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6806 aopPut (result, "a", offset);
6810 MOVA (aopGet (right, offset, FALSE, FALSE));
6811 if (IS_AOP_PREG (result))
6813 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6814 aopPut (result, "a", offset);
6817 emitcode ("anl", "%s,a", aopGet (left, offset, FALSE, TRUE));
6824 // left & result in different registers
6825 if (AOP_TYPE (result) == AOP_CRY)
6828 // if(size), result in bit
6829 // if(!size && ifx), conditional oper: if(left & right)
6830 symbol *tlbl = newiTempLabel (NULL);
6831 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6833 emitcode ("setb", "c");
6836 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6837 && AOP_TYPE(left)==AOP_ACC)
6840 emitcode("mov", "a,b");
6841 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6843 else if (AOP_TYPE(left)==AOP_ACC)
6847 bool pushedB = pushB ();
6848 emitcode("mov", "b,a");
6849 MOVA (aopGet (right, offset, FALSE, FALSE));
6850 emitcode("anl", "a,b");
6855 MOVA (aopGet (right, offset, FALSE, FALSE));
6856 emitcode("anl", "a,b");
6859 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6861 MOVB (aopGet (left, offset, FALSE, FALSE));
6862 MOVA (aopGet (right, offset, FALSE, FALSE));
6863 emitcode ("anl", "a,b");
6865 else if (aopGetUsesAcc (left, offset))
6867 MOVA (aopGet (left, offset, FALSE, FALSE));
6868 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6872 MOVA (aopGet (right, offset, FALSE, FALSE));
6873 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6876 emitcode ("jnz", "%05d$", tlbl->key + 100);
6886 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6892 for (; (size--); offset++)
6895 // result = left & right
6896 if (AOP_TYPE (right) == AOP_LIT)
6898 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6899 if (bytelit == 0x0FF)
6902 aopGet (left, offset, FALSE, FALSE),
6906 else if (bytelit == 0)
6908 /* dummy read of volatile operand */
6909 if (isOperandVolatile (left, FALSE))
6910 MOVA (aopGet (left, offset, FALSE, FALSE));
6911 aopPut (result, zero, offset);
6914 else if (AOP_TYPE (left) == AOP_ACC)
6918 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6919 aopPut (result, "a", offset);
6924 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6925 aopPut (result, "b", offset);
6930 // faster than result <- left, anl result,right
6931 // and better if result is SFR
6932 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6933 && AOP_TYPE(left)==AOP_ACC)
6936 emitcode("mov", "a,b");
6937 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6939 else if (AOP_TYPE(left)==AOP_ACC)
6943 bool pushedB = pushB ();
6944 emitcode("mov", "b,a");
6945 MOVA (aopGet (right, offset, FALSE, FALSE));
6946 emitcode("anl", "a,b");
6951 MOVA (aopGet (right, offset, FALSE, FALSE));
6952 emitcode("anl", "a,b");
6955 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6957 MOVB (aopGet (left, offset, FALSE, FALSE));
6958 MOVA (aopGet (right, offset, FALSE, FALSE));
6959 emitcode ("anl", "a,b");
6961 else if (aopGetUsesAcc (left, offset))
6963 MOVA (aopGet (left, offset, FALSE, FALSE));
6964 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6968 MOVA (aopGet (right, offset, FALSE, FALSE));
6969 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6971 aopPut (result, "a", offset);
6977 freeAsmop (result, NULL, ic, TRUE);
6978 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6979 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6982 /*-----------------------------------------------------------------*/
6983 /* genOr - code for or */
6984 /*-----------------------------------------------------------------*/
6986 genOr (iCode * ic, iCode * ifx)
6988 operand *left, *right, *result;
6989 int size, offset = 0;
6990 unsigned long lit = 0L;
6993 D (emitcode (";", "genOr"));
6995 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6996 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6997 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7000 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
7002 AOP_TYPE (left), AOP_TYPE (right));
7003 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
7005 AOP_SIZE (left), AOP_SIZE (right));
7008 /* if left is a literal & right is not then exchange them */
7009 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7010 AOP_NEEDSACC (left))
7012 operand *tmp = right;
7017 /* if result = right then exchange them */
7018 if (sameRegs (AOP (result), AOP (right)))
7020 operand *tmp = right;
7025 /* if right is bit then exchange them */
7026 if (AOP_TYPE (right) == AOP_CRY &&
7027 AOP_TYPE (left) != AOP_CRY)
7029 operand *tmp = right;
7033 if (AOP_TYPE (right) == AOP_LIT)
7034 lit = ulFromVal (AOP (right)->aopu.aop_lit);
7036 size = AOP_SIZE (result);
7040 if (AOP_TYPE (left) == AOP_CRY)
7042 if (AOP_TYPE (right) == AOP_LIT)
7044 // c = bit | literal;
7047 // lit != 0 => result = 1
7048 if (AOP_TYPE (result) == AOP_CRY)
7051 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7053 continueIfTrue (ifx);
7056 emitcode ("setb", "c");
7060 // lit == 0 => result = left
7061 if (size && sameRegs (AOP (result), AOP (left)))
7063 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7068 if (AOP_TYPE (right) == AOP_CRY)
7071 if (IS_OP_ACCUSE (left))
7073 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
7077 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7078 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7084 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7086 symbol *tlbl = newiTempLabel (NULL);
7087 emitcode ("jb", "%s,%05d$",
7088 AOP (left)->aopu.aop_dir, tlbl->key + 100);
7090 emitcode ("jnz", "%05d$", tlbl->key + 100);
7091 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7097 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7106 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7107 genIfxJump (ifx, "c", left, right, result);
7111 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7112 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7113 if ((AOP_TYPE (right) == AOP_LIT) &&
7114 (AOP_TYPE (result) == AOP_CRY) &&
7115 (AOP_TYPE (left) != AOP_CRY))
7121 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7123 continueIfTrue (ifx);
7128 // lit = 0, result = boolean(left)
7130 emitcode ("setb", "c");
7134 symbol *tlbl = newiTempLabel (NULL);
7135 emitcode ("jnz", "%05d$", tlbl->key + 100);
7141 genIfxJump (ifx, "a", left, right, result);
7149 /* if left is same as result */
7150 if (sameRegs (AOP (result), AOP (left)))
7152 for (; size--; offset++)
7154 if (AOP_TYPE (right) == AOP_LIT)
7156 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7159 /* dummy read of volatile operand */
7160 if (isOperandVolatile (left, FALSE))
7161 MOVA (aopGet (left, offset, FALSE, FALSE));
7165 else if (bytelit == 0x0FF)
7167 aopPut (result, "#0xFF", offset);
7169 else if (IS_AOP_PREG (left))
7171 MOVA (aopGet (left, offset, FALSE, TRUE));
7172 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7173 aopPut (result, "a", offset);
7177 emitcode ("orl", "%s,%s",
7178 aopGet (left, offset, FALSE, TRUE),
7179 aopGet (right, offset, FALSE, FALSE));
7184 if (AOP_TYPE (left) == AOP_ACC)
7187 emitcode("mov", "a,b");
7188 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7190 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7192 MOVB (aopGet (left, offset, FALSE, FALSE));
7193 MOVA (aopGet (right, offset, FALSE, FALSE));
7194 emitcode ("orl", "a,b");
7195 aopPut (result, "a", offset);
7197 else if (aopGetUsesAcc (left, offset))
7199 MOVA (aopGet (left, offset, FALSE, FALSE));
7200 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7201 aopPut (result, "a", offset);
7205 MOVA (aopGet (right, offset, FALSE, FALSE));
7206 if (IS_AOP_PREG (left))
7208 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7209 aopPut (result, "a", offset);
7213 emitcode ("orl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7221 // left & result in different registers
7222 if (AOP_TYPE (result) == AOP_CRY)
7225 // if(size), result in bit
7226 // if(!size && ifx), conditional oper: if(left | right)
7227 symbol *tlbl = newiTempLabel (NULL);
7228 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7230 emitcode ("setb", "c");
7233 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7234 && AOP_TYPE(left)==AOP_ACC)
7237 emitcode("mov", "a,b");
7238 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7240 else if (AOP_TYPE(left)==AOP_ACC)
7244 bool pushedB = pushB ();
7245 emitcode("mov", "b,a");
7246 MOVA (aopGet (right, offset, FALSE, FALSE));
7247 emitcode("orl", "a,b");
7252 MOVA (aopGet (right, offset, FALSE, FALSE));
7253 emitcode("orl", "a,b");
7256 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7258 MOVB (aopGet (left, offset, FALSE, FALSE));
7259 MOVA (aopGet (right, offset, FALSE, FALSE));
7260 emitcode ("orl", "a,b");
7262 else if (aopGetUsesAcc (left, offset))
7264 MOVA (aopGet (left, offset, FALSE, FALSE));
7265 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7269 MOVA (aopGet (right, offset, FALSE, FALSE));
7270 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7273 emitcode ("jnz", "%05d$", tlbl->key + 100);
7283 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7289 for (; (size--); offset++)
7292 // result = left | right
7293 if (AOP_TYPE (right) == AOP_LIT)
7295 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7299 aopGet (left, offset, FALSE, FALSE),
7303 else if (bytelit == 0x0FF)
7305 /* dummy read of volatile operand */
7306 if (isOperandVolatile (left, FALSE))
7307 MOVA (aopGet (left, offset, FALSE, FALSE));
7308 aopPut (result, "#0xFF", offset);
7312 // faster than result <- left, orl result,right
7313 // and better if result is SFR
7314 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7315 && AOP_TYPE(left)==AOP_ACC)
7318 emitcode("mov", "a,b");
7319 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7321 else if (AOP_TYPE(left)==AOP_ACC)
7325 bool pushedB = pushB ();
7326 emitcode("mov", "b,a");
7327 MOVA (aopGet (right, offset, FALSE, FALSE));
7328 emitcode("orl", "a,b");
7333 MOVA (aopGet (right, offset, FALSE, FALSE));
7334 emitcode("orl", "a,b");
7337 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7339 MOVB (aopGet (left, offset, FALSE, FALSE));
7340 MOVA (aopGet (right, offset, FALSE, FALSE));
7341 emitcode ("orl", "a,b");
7343 else if (aopGetUsesAcc (left, offset))
7345 MOVA (aopGet (left, offset, FALSE, FALSE));
7346 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7350 MOVA (aopGet (right, offset, FALSE, FALSE));
7351 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7353 aopPut (result, "a", offset);
7359 freeAsmop (result, NULL, ic, TRUE);
7360 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7361 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7364 /*-----------------------------------------------------------------*/
7365 /* genXor - code for xclusive or */
7366 /*-----------------------------------------------------------------*/
7368 genXor (iCode * ic, iCode * ifx)
7370 operand *left, *right, *result;
7371 int size, offset = 0;
7372 unsigned long lit = 0L;
7375 D (emitcode (";", "genXor"));
7377 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7378 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7379 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7382 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
7384 AOP_TYPE (left), AOP_TYPE (right));
7385 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
7387 AOP_SIZE (left), AOP_SIZE (right));
7390 /* if left is a literal & right is not ||
7391 if left needs acc & right does not */
7392 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7393 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7395 operand *tmp = right;
7400 /* if result = right then exchange them */
7401 if (sameRegs (AOP (result), AOP (right)))
7403 operand *tmp = right;
7408 /* if right is bit then exchange them */
7409 if (AOP_TYPE (right) == AOP_CRY &&
7410 AOP_TYPE (left) != AOP_CRY)
7412 operand *tmp = right;
7417 if (AOP_TYPE (right) == AOP_LIT)
7418 lit = ulFromVal (AOP (right)->aopu.aop_lit);
7420 size = AOP_SIZE (result);
7424 if (AOP_TYPE (left) == AOP_CRY)
7426 if (AOP_TYPE (right) == AOP_LIT)
7428 // c = bit & literal;
7431 // lit>>1 != 0 => result = 1
7432 if (AOP_TYPE (result) == AOP_CRY)
7435 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7437 continueIfTrue (ifx);
7440 emitcode ("setb", "c");
7447 // lit == 0, result = left
7448 if (size && sameRegs (AOP (result), AOP (left)))
7450 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7454 // lit == 1, result = not(left)
7455 if (size && sameRegs (AOP (result), AOP (left)))
7457 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7462 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7463 emitcode ("cpl", "c");
7471 symbol *tlbl = newiTempLabel (NULL);
7472 if (AOP_TYPE (right) == AOP_CRY)
7475 if (IS_OP_ACCUSE (left))
7476 {// left already is in the carry
7477 operand *tmp = right;
7491 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7492 emitcode ("cpl", "c");
7500 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7501 genIfxJump (ifx, "c", left, right, result);
7505 /* if left is same as result */
7506 if (sameRegs (AOP (result), AOP (left)))
7508 for (; size--; offset++)
7510 if (AOP_TYPE (right) == AOP_LIT)
7512 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7515 /* dummy read of volatile operand */
7516 if (isOperandVolatile (left, FALSE))
7517 MOVA (aopGet (left, offset, FALSE, FALSE));
7521 else if (IS_AOP_PREG (left))
7523 MOVA (aopGet (left, offset, FALSE, TRUE));
7524 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7525 aopPut (result, "a", offset);
7529 emitcode ("xrl", "%s,%s",
7530 aopGet (left, offset, FALSE, TRUE),
7531 aopGet (right, offset, FALSE, FALSE));
7536 if (AOP_TYPE (left) == AOP_ACC)
7539 emitcode("mov", "a,b");
7540 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7542 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7544 MOVB (aopGet (left, offset, FALSE, FALSE));
7545 MOVA (aopGet (right, offset, FALSE, FALSE));
7546 emitcode ("xrl", "a,b");
7547 aopPut (result, "a", offset);
7549 else if (aopGetUsesAcc (left, offset))
7551 MOVA (aopGet (left, offset, FALSE, FALSE));
7552 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7553 aopPut (result, "a", offset);
7557 MOVA (aopGet (right, offset, FALSE, FALSE));
7558 if (IS_AOP_PREG (left))
7560 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7561 aopPut (result, "a", offset);
7564 emitcode ("xrl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7571 // left & result in different registers
7572 if (AOP_TYPE (result) == AOP_CRY)
7575 // if(size), result in bit
7576 // if(!size && ifx), conditional oper: if(left ^ right)
7577 symbol *tlbl = newiTempLabel (NULL);
7578 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7581 emitcode ("setb", "c");
7584 if ((AOP_TYPE (right) == AOP_LIT) &&
7585 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7587 MOVA (aopGet (left, offset, FALSE, FALSE));
7589 else if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7590 && AOP_TYPE(left)==AOP_ACC)
7593 emitcode("mov", "a,b");
7594 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7596 else if (AOP_TYPE(left)==AOP_ACC)
7600 bool pushedB = pushB ();
7601 emitcode("mov", "b,a");
7602 MOVA (aopGet (right, offset, FALSE, FALSE));
7603 emitcode("xrl", "a,b");
7608 MOVA (aopGet (right, offset, FALSE, FALSE));
7609 emitcode("xrl", "a,b");
7612 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7614 MOVB (aopGet (left, offset, FALSE, FALSE));
7615 MOVA (aopGet (right, offset, FALSE, FALSE));
7616 emitcode ("xrl", "a,b");
7618 else if (aopGetUsesAcc (left, offset))
7620 MOVA (aopGet (left, offset, FALSE, FALSE));
7621 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7625 MOVA (aopGet (right, offset, FALSE, FALSE));
7626 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7629 emitcode ("jnz", "%05d$", tlbl->key + 100);
7639 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7643 for (; (size--); offset++)
7646 // result = left ^ right
7647 if (AOP_TYPE (right) == AOP_LIT)
7649 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7653 aopGet (left, offset, FALSE, FALSE),
7658 // faster than result <- left, xrl result,right
7659 // and better if result is SFR
7660 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7661 && AOP_TYPE(left)==AOP_ACC)
7664 emitcode("mov", "a,b");
7665 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7667 else if (AOP_TYPE(left)==AOP_ACC)
7671 bool pushedB = pushB ();
7672 emitcode("mov", "b,a");
7673 MOVA (aopGet (right, offset, FALSE, FALSE));
7674 emitcode("xrl", "a,b");
7679 MOVA (aopGet (right, offset, FALSE, FALSE));
7680 emitcode("xrl", "a,b");
7683 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7685 MOVB (aopGet (left, offset, FALSE, FALSE));
7686 MOVA (aopGet (right, offset, FALSE, FALSE));
7687 emitcode ("xrl", "a,b");
7689 else if (aopGetUsesAcc (left, offset))
7691 MOVA (aopGet (left, offset, FALSE, FALSE));
7692 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7696 MOVA (aopGet (right, offset, FALSE, FALSE));
7697 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7699 aopPut (result, "a", offset);
7705 freeAsmop (result, NULL, ic, TRUE);
7706 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7707 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7710 /*-----------------------------------------------------------------*/
7711 /* genInline - write the inline code out */
7712 /*-----------------------------------------------------------------*/
7714 genInline (iCode * ic)
7716 char *buffer, *bp, *bp1;
7717 bool inComment = FALSE;
7719 D (emitcode (";", "genInline"));
7721 _G.inLine += (!options.asmpeep);
7723 buffer = bp = bp1 = Safe_strdup (IC_INLINE (ic));
7725 /* emit each line as a code */
7743 /* Add \n for labels, not dirs such as c:\mydir */
7744 if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
7762 _G.inLine -= (!options.asmpeep);
7765 /*-----------------------------------------------------------------*/
7766 /* genRRC - rotate right with carry */
7767 /*-----------------------------------------------------------------*/
7771 operand *left, *result;
7775 D (emitcode (";", "genRRC"));
7777 /* rotate right with carry */
7778 left = IC_LEFT (ic);
7779 result = IC_RESULT (ic);
7780 aopOp (left, ic, FALSE);
7781 aopOp (result, ic, FALSE);
7783 /* move it to the result */
7784 size = AOP_SIZE (result);
7786 if (size == 1) { /* special case for 1 byte */
7787 l = aopGet (left, offset, FALSE, FALSE);
7789 emitcode ("rr", "a");
7792 /* no need to clear carry, bit7 will be written later */
7795 l = aopGet (left, offset, FALSE, FALSE);
7797 emitcode ("rrc", "a");
7798 if (AOP_SIZE (result) > 1)
7799 aopPut (result, "a", offset--);
7801 /* now we need to put the carry into the
7802 highest order byte of the result */
7803 if (AOP_SIZE (result) > 1)
7805 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7808 emitcode ("mov", "acc.7,c");
7810 aopPut (result, "a", AOP_SIZE (result) - 1);
7811 freeAsmop (result, NULL, ic, TRUE);
7812 freeAsmop (left, NULL, ic, TRUE);
7815 /*-----------------------------------------------------------------*/
7816 /* genRLC - generate code for rotate left with carry */
7817 /*-----------------------------------------------------------------*/
7821 operand *left, *result;
7825 D (emitcode (";", "genRLC"));
7827 /* rotate right with carry */
7828 left = IC_LEFT (ic);
7829 result = IC_RESULT (ic);
7830 aopOp (left, ic, FALSE);
7831 aopOp (result, ic, FALSE);
7833 /* move it to the result */
7834 size = AOP_SIZE (result);
7838 l = aopGet (left, offset, FALSE, FALSE);
7840 if (size == 0) { /* special case for 1 byte */
7844 emitcode("rlc","a"); /* bit0 will be written later */
7845 if (AOP_SIZE (result) > 1)
7847 aopPut (result, "a", offset++);
7852 l = aopGet (left, offset, FALSE, FALSE);
7854 emitcode ("rlc", "a");
7855 if (AOP_SIZE (result) > 1)
7856 aopPut (result, "a", offset++);
7859 /* now we need to put the carry into the
7860 highest order byte of the result */
7861 if (AOP_SIZE (result) > 1)
7863 l = aopGet (result, 0, FALSE, FALSE);
7866 emitcode ("mov", "acc.0,c");
7868 aopPut (result, "a", 0);
7869 freeAsmop (result, NULL, ic, TRUE);
7870 freeAsmop (left, NULL, ic, TRUE);
7873 /*-----------------------------------------------------------------*/
7874 /* genGetHbit - generates code get highest order bit */
7875 /*-----------------------------------------------------------------*/
7877 genGetHbit (iCode * ic)
7879 operand *left, *result;
7881 D (emitcode (";", "genGetHbit"));
7883 left = IC_LEFT (ic);
7884 result = IC_RESULT (ic);
7885 aopOp (left, ic, FALSE);
7886 aopOp (result, ic, FALSE);
7888 /* get the highest order byte into a */
7889 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7890 if (AOP_TYPE (result) == AOP_CRY)
7892 emitcode ("rlc", "a");
7897 emitcode ("rl", "a");
7898 emitcode ("anl", "a,#0x01");
7902 freeAsmop (result, NULL, ic, TRUE);
7903 freeAsmop (left, NULL, ic, TRUE);
7906 /*-----------------------------------------------------------------*/
7907 /* genGetAbit - generates code get a single bit */
7908 /*-----------------------------------------------------------------*/
7910 genGetAbit (iCode * ic)
7912 operand *left, *right, *result;
7915 D (emitcode (";", "genGetAbit"));
7917 left = IC_LEFT (ic);
7918 right = IC_RIGHT (ic);
7919 result = IC_RESULT (ic);
7920 aopOp (left, ic, FALSE);
7921 aopOp (right, ic, FALSE);
7922 aopOp (result, ic, FALSE);
7924 shCount = (int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7926 /* get the needed byte into a */
7927 MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7929 if (AOP_TYPE (result) == AOP_CRY)
7932 emitcode ("rlc", "a");
7933 else if ((shCount) == 0)
7934 emitcode ("rrc", "a");
7936 emitcode ("mov", "c,acc[%d]", shCount);
7944 emitcode ("rr", "a");
7947 emitcode ("rr", "a");
7950 emitcode ("anl", "a,#0x01");
7954 emitcode ("mov", "c,acc[%d]", shCount);
7955 emitcode ("clr", "a");
7956 emitcode ("rlc", "a");
7959 emitcode ("swap", "a");
7960 emitcode ("anl", "a,#0x01");
7963 emitcode ("rl", "a");
7966 emitcode ("rl", "a");
7967 emitcode ("anl", "a,#0x01");
7973 freeAsmop (result, NULL, ic, TRUE);
7974 freeAsmop (right, NULL, ic, TRUE);
7975 freeAsmop (left, NULL, ic, TRUE);
7978 /*-----------------------------------------------------------------*/
7979 /* genGetByte - generates code get a single byte */
7980 /*-----------------------------------------------------------------*/
7982 genGetByte (iCode * ic)
7984 operand *left, *right, *result;
7987 D (emitcode (";", "genGetByte"));
7989 left = IC_LEFT (ic);
7990 right = IC_RIGHT (ic);
7991 result = IC_RESULT (ic);
7992 aopOp (left, ic, FALSE);
7993 aopOp (right, ic, FALSE);
7994 aopOp (result, ic, FALSE);
7996 offset = (int) ulFromVal (AOP (right)->aopu.aop_lit) / 8;
7998 aopGet (left, offset, FALSE, FALSE),
8001 freeAsmop (result, NULL, ic, TRUE);
8002 freeAsmop (right, NULL, ic, TRUE);
8003 freeAsmop (left, NULL, ic, TRUE);
8006 /*-----------------------------------------------------------------*/
8007 /* genGetWord - generates code get two bytes */
8008 /*-----------------------------------------------------------------*/
8010 genGetWord (iCode * ic)
8012 operand *left, *right, *result;
8015 D (emitcode (";", "genGetWord"));
8017 left = IC_LEFT (ic);
8018 right = IC_RIGHT (ic);
8019 result = IC_RESULT (ic);
8020 aopOp (left, ic, FALSE);
8021 aopOp (right, ic, FALSE);
8022 aopOp (result, ic, FALSE);
8024 offset = (int) ulFromVal (AOP (right)->aopu.aop_lit) / 8;
8026 aopGet (left, offset, FALSE, FALSE),
8029 aopGet (left, offset+1, FALSE, FALSE),
8032 freeAsmop (result, NULL, ic, TRUE);
8033 freeAsmop (right, NULL, ic, TRUE);
8034 freeAsmop (left, NULL, ic, TRUE);
8037 /*-----------------------------------------------------------------*/
8038 /* genSwap - generates code to swap nibbles or bytes */
8039 /*-----------------------------------------------------------------*/
8041 genSwap (iCode * ic)
8043 operand *left, *result;
8045 D(emitcode (";", "genSwap"));
8047 left = IC_LEFT (ic);
8048 result = IC_RESULT (ic);
8049 aopOp (left, ic, FALSE);
8050 aopOp (result, ic, FALSE);
8052 switch (AOP_SIZE (left))
8054 case 1: /* swap nibbles in byte */
8055 MOVA (aopGet (left, 0, FALSE, FALSE));
8056 emitcode ("swap", "a");
8057 aopPut (result, "a", 0);
8059 case 2: /* swap bytes in word */
8060 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
8062 MOVA (aopGet (left, 0, FALSE, FALSE));
8063 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8064 aopPut (result, "a", 1);
8066 else if (operandsEqu (left, result))
8069 bool pushedB = FALSE, leftInB = FALSE;
8071 MOVA (aopGet (left, 0, FALSE, FALSE));
8072 if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
8075 emitcode ("mov", "b,a");
8079 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8080 aopPut (result, reg, 1);
8087 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8088 aopPut (result, aopGet (left, 0, FALSE, FALSE), 1);
8092 wassertl(FALSE, "unsupported SWAP operand size");
8095 freeAsmop (result, NULL, ic, TRUE);
8096 freeAsmop (left, NULL, ic, TRUE);
8099 /*-----------------------------------------------------------------*/
8100 /* AccRol - rotate left accumulator by known count */
8101 /*-----------------------------------------------------------------*/
8103 AccRol (int shCount)
8105 shCount &= 0x0007; // shCount : 0..7
8112 emitcode ("rl", "a");
8115 emitcode ("rl", "a");
8116 emitcode ("rl", "a");
8119 emitcode ("swap", "a");
8120 emitcode ("rr", "a");
8123 emitcode ("swap", "a");
8126 emitcode ("swap", "a");
8127 emitcode ("rl", "a");
8130 emitcode ("rr", "a");
8131 emitcode ("rr", "a");
8134 emitcode ("rr", "a");
8139 /*-----------------------------------------------------------------*/
8140 /* AccLsh - left shift accumulator by known count */
8141 /*-----------------------------------------------------------------*/
8143 AccLsh (int shCount)
8148 emitcode ("add", "a,acc");
8149 else if (shCount == 2)
8151 emitcode ("add", "a,acc");
8152 emitcode ("add", "a,acc");
8156 /* rotate left accumulator */
8158 /* and kill the lower order bits */
8159 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
8164 /*-----------------------------------------------------------------*/
8165 /* AccRsh - right shift accumulator by known count */
8166 /*-----------------------------------------------------------------*/
8168 AccRsh (int shCount)
8175 emitcode ("rrc", "a");
8179 /* rotate right accumulator */
8180 AccRol (8 - shCount);
8181 /* and kill the higher order bits */
8182 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8187 /*-----------------------------------------------------------------*/
8188 /* AccSRsh - signed right shift accumulator by known count */
8189 /*-----------------------------------------------------------------*/
8191 AccSRsh (int shCount)
8198 emitcode ("mov", "c,acc.7");
8199 emitcode ("rrc", "a");
8201 else if (shCount == 2)
8203 emitcode ("mov", "c,acc.7");
8204 emitcode ("rrc", "a");
8205 emitcode ("mov", "c,acc.7");
8206 emitcode ("rrc", "a");
8210 tlbl = newiTempLabel (NULL);
8211 /* rotate right accumulator */
8212 AccRol (8 - shCount);
8213 /* and kill the higher order bits */
8214 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8215 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8216 emitcode ("orl", "a,#0x%02x",
8217 (unsigned char) ~SRMask[shCount]);
8223 /*-----------------------------------------------------------------*/
8224 /* shiftR1Left2Result - shift right one byte from left to result */
8225 /*-----------------------------------------------------------------*/
8227 shiftR1Left2Result (operand * left, int offl,
8228 operand * result, int offr,
8229 int shCount, int sign)
8231 MOVA (aopGet (left, offl, FALSE, FALSE));
8232 /* shift right accumulator */
8237 aopPut (result, "a", offr);
8240 /*-----------------------------------------------------------------*/
8241 /* shiftL1Left2Result - shift left one byte from left to result */
8242 /*-----------------------------------------------------------------*/
8244 shiftL1Left2Result (operand * left, int offl,
8245 operand * result, int offr, int shCount)
8248 l = aopGet (left, offl, FALSE, FALSE);
8250 /* shift left accumulator */
8252 aopPut (result, "a", offr);
8255 /*-----------------------------------------------------------------*/
8256 /* movLeft2Result - move byte from left to result */
8257 /*-----------------------------------------------------------------*/
8259 movLeft2Result (operand * left, int offl,
8260 operand * result, int offr, int sign)
8263 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8265 l = aopGet (left, offl, FALSE, FALSE);
8267 if (*l == '@' && (IS_AOP_PREG (result)))
8269 emitcode ("mov", "a,%s", l);
8270 aopPut (result, "a", offr);
8276 aopPut (result, l, offr);
8280 /* MSB sign in acc.7 ! */
8281 if (getDataSize (left) == offl + 1)
8284 aopPut (result, "a", offr);
8291 /*-----------------------------------------------------------------*/
8292 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
8293 /*-----------------------------------------------------------------*/
8297 emitcode ("rrc", "a");
8298 emitcode ("xch", "a,%s", x);
8299 emitcode ("rrc", "a");
8300 emitcode ("xch", "a,%s", x);
8303 /*-----------------------------------------------------------------*/
8304 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
8305 /*-----------------------------------------------------------------*/
8309 emitcode ("xch", "a,%s", x);
8310 emitcode ("rlc", "a");
8311 emitcode ("xch", "a,%s", x);
8312 emitcode ("rlc", "a");
8315 /*-----------------------------------------------------------------*/
8316 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8317 /*-----------------------------------------------------------------*/
8321 emitcode ("xch", "a,%s", x);
8322 emitcode ("add", "a,acc");
8323 emitcode ("xch", "a,%s", x);
8324 emitcode ("rlc", "a");
8327 /*-----------------------------------------------------------------*/
8328 /* AccAXLsh - left shift a:x by known count (0..7) */
8329 /*-----------------------------------------------------------------*/
8331 AccAXLsh (char *x, int shCount)
8346 case 5: // AAAAABBB:CCCCCDDD
8348 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8350 emitcode ("anl", "a,#0x%02x",
8351 SLMask[shCount]); // BBB00000:CCCCCDDD
8353 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8355 AccRol (shCount); // DDDCCCCC:BBB00000
8357 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8359 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8361 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8363 emitcode ("anl", "a,#0x%02x",
8364 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8366 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8368 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8371 case 6: // AAAAAABB:CCCCCCDD
8372 emitcode ("anl", "a,#0x%02x",
8373 SRMask[shCount]); // 000000BB:CCCCCCDD
8374 emitcode ("mov", "c,acc.0"); // c = B
8375 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8377 AccAXRrl1 (x); // BCCCCCCD:D000000B
8378 AccAXRrl1 (x); // BBCCCCCC:DD000000
8380 emitcode("rrc","a");
8381 emitcode("xch","a,%s", x);
8382 emitcode("rrc","a");
8383 emitcode("mov","c,acc.0"); //<< get correct bit
8384 emitcode("xch","a,%s", x);
8386 emitcode("rrc","a");
8387 emitcode("xch","a,%s", x);
8388 emitcode("rrc","a");
8389 emitcode("xch","a,%s", x);
8392 case 7: // a:x <<= 7
8394 emitcode ("anl", "a,#0x%02x",
8395 SRMask[shCount]); // 0000000B:CCCCCCCD
8397 emitcode ("mov", "c,acc.0"); // c = B
8399 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
8401 AccAXRrl1 (x); // BCCCCCCC:D0000000
8409 /*-----------------------------------------------------------------*/
8410 /* AccAXRsh - right shift a:x known count (0..7) */
8411 /*-----------------------------------------------------------------*/
8413 AccAXRsh (char *x, int shCount)
8421 AccAXRrl1 (x); // 0->a:x
8426 AccAXRrl1 (x); // 0->a:x
8429 AccAXRrl1 (x); // 0->a:x
8434 case 5: // AAAAABBB:CCCCCDDD = a:x
8436 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8438 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8440 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8442 emitcode ("anl", "a,#0x%02x",
8443 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8445 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8447 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8449 emitcode ("anl", "a,#0x%02x",
8450 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8452 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8454 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8456 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8459 case 6: // AABBBBBB:CCDDDDDD
8461 emitcode ("mov", "c,acc.7");
8462 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8464 emitcode ("mov", "c,acc.7");
8465 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8467 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8469 emitcode ("anl", "a,#0x%02x",
8470 SRMask[shCount]); // 000000AA:BBBBBBCC
8473 case 7: // ABBBBBBB:CDDDDDDD
8475 emitcode ("mov", "c,acc.7"); // c = A
8477 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8479 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8481 emitcode ("anl", "a,#0x%02x",
8482 SRMask[shCount]); // 0000000A:BBBBBBBC
8490 /*-----------------------------------------------------------------*/
8491 /* AccAXRshS - right shift signed a:x known count (0..7) */
8492 /*-----------------------------------------------------------------*/
8494 AccAXRshS (char *x, int shCount)
8502 emitcode ("mov", "c,acc.7");
8503 AccAXRrl1 (x); // s->a:x
8507 emitcode ("mov", "c,acc.7");
8508 AccAXRrl1 (x); // s->a:x
8510 emitcode ("mov", "c,acc.7");
8511 AccAXRrl1 (x); // s->a:x
8516 case 5: // AAAAABBB:CCCCCDDD = a:x
8518 tlbl = newiTempLabel (NULL);
8519 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8521 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8523 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8525 emitcode ("anl", "a,#0x%02x",
8526 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8528 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8530 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8532 emitcode ("anl", "a,#0x%02x",
8533 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8535 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8537 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8539 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8541 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8542 emitcode ("orl", "a,#0x%02x",
8543 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8546 break; // SSSSAAAA:BBBCCCCC
8548 case 6: // AABBBBBB:CCDDDDDD
8550 tlbl = newiTempLabel (NULL);
8551 emitcode ("mov", "c,acc.7");
8552 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8554 emitcode ("mov", "c,acc.7");
8555 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8557 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8559 emitcode ("anl", "a,#0x%02x",
8560 SRMask[shCount]); // 000000AA:BBBBBBCC
8562 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8563 emitcode ("orl", "a,#0x%02x",
8564 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8568 case 7: // ABBBBBBB:CDDDDDDD
8570 tlbl = newiTempLabel (NULL);
8571 emitcode ("mov", "c,acc.7"); // c = A
8573 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8575 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8577 emitcode ("anl", "a,#0x%02x",
8578 SRMask[shCount]); // 0000000A:BBBBBBBC
8580 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8581 emitcode ("orl", "a,#0x%02x",
8582 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8591 /*-----------------------------------------------------------------*/
8592 /* shiftL2Left2Result - shift left two bytes from left to result */
8593 /*-----------------------------------------------------------------*/
8595 shiftL2Left2Result (operand * left, int offl,
8596 operand * result, int offr, int shCount)
8599 bool pushedB = FALSE;
8602 if (sameRegs (AOP (result), AOP (left)) &&
8603 ((offl + MSB16) == offr))
8605 /* don't crash result[offr] */
8606 MOVA (aopGet (left, offl, FALSE, FALSE));
8607 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8608 usedB = !strncmp(x, "b", 1);
8610 else if (aopGetUsesAcc (result, offr))
8612 movLeft2Result (left, offl, result, offr, 0);
8615 emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8616 MOVA (aopGet (result, offr, FALSE, FALSE));
8617 emitcode ("xch", "a,b");
8622 movLeft2Result (left, offl, result, offr, 0);
8623 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8624 x = aopGet (result, offr, FALSE, FALSE);
8626 /* ax << shCount (x = lsb(result)) */
8627 AccAXLsh (x, shCount);
8630 emitcode ("xch", "a,b");
8631 aopPut (result, "a", offr);
8632 aopPut (result, "b", offr + MSB16);
8637 aopPut (result, "a", offr + MSB16);
8642 /*-----------------------------------------------------------------*/
8643 /* shiftR2Left2Result - shift right two bytes from left to result */
8644 /*-----------------------------------------------------------------*/
8646 shiftR2Left2Result (operand * left, int offl,
8647 operand * result, int offr,
8648 int shCount, int sign)
8651 bool pushedB = FALSE;
8654 if (sameRegs (AOP (result), AOP (left)) &&
8655 ((offl + MSB16) == offr))
8657 /* don't crash result[offr] */
8658 MOVA (aopGet (left, offl, FALSE, FALSE));
8659 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8660 usedB = !strncmp(x, "b", 1);
8662 else if (aopGetUsesAcc (result, offr))
8664 movLeft2Result (left, offl, result, offr, 0);
8667 emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8668 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8673 movLeft2Result (left, offl, result, offr, 0);
8674 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8675 x = aopGet (result, offr, FALSE, FALSE);
8677 /* a:x >> shCount (x = lsb(result)) */
8679 AccAXRshS (x, shCount);
8681 AccAXRsh (x, shCount);
8684 emitcode ("xch", "a,b");
8685 aopPut (result, "a", offr);
8686 emitcode ("xch", "a,b");
8689 if (getDataSize (result) > 1)
8690 aopPut (result, "a", offr + MSB16);
8693 /*-----------------------------------------------------------------*/
8694 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8695 /*-----------------------------------------------------------------*/
8697 shiftLLeftOrResult (operand * left, int offl,
8698 operand * result, int offr, int shCount)
8700 MOVA (aopGet (left, offl, FALSE, FALSE));
8701 /* shift left accumulator */
8703 /* or with result */
8704 if (aopGetUsesAcc (result, offr))
8706 emitcode ("xch", "a,b");
8707 MOVA (aopGet (result, offr, FALSE, FALSE));
8708 emitcode ("orl", "a,b");
8712 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8714 /* back to result */
8715 aopPut (result, "a", offr);
8718 /*-----------------------------------------------------------------*/
8719 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8720 /*-----------------------------------------------------------------*/
8722 shiftRLeftOrResult (operand * left, int offl,
8723 operand * result, int offr, int shCount)
8725 MOVA (aopGet (left, offl, FALSE, FALSE));
8726 /* shift right accumulator */
8728 /* or with result */
8729 if (aopGetUsesAcc(result, offr))
8731 emitcode ("xch", "a,b");
8732 MOVA (aopGet (result, offr, FALSE, FALSE));
8733 emitcode ("orl", "a,b");
8737 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8739 /* back to result */
8740 aopPut (result, "a", offr);
8743 /*-----------------------------------------------------------------*/
8744 /* genlshOne - left shift a one byte quantity by known count */
8745 /*-----------------------------------------------------------------*/
8747 genlshOne (operand * result, operand * left, int shCount)
8749 D (emitcode (";", "genlshOne"));
8751 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8754 /*-----------------------------------------------------------------*/
8755 /* genlshTwo - left shift two bytes by known amount != 0 */
8756 /*-----------------------------------------------------------------*/
8758 genlshTwo (operand * result, operand * left, int shCount)
8762 D (emitcode (";", "genlshTwo"));
8764 size = getDataSize (result);
8766 /* if shCount >= 8 */
8774 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8776 movLeft2Result (left, LSB, result, MSB16, 0);
8778 aopPut (result, zero, LSB);
8781 /* 1 <= shCount <= 7 */
8785 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8787 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8791 /*-----------------------------------------------------------------*/
8792 /* shiftLLong - shift left one long from left to result */
8793 /* offl = LSB or MSB16 */
8794 /*-----------------------------------------------------------------*/
8796 shiftLLong (operand * left, operand * result, int offr)
8799 int size = AOP_SIZE (result);
8801 if (size >= LSB + offr)
8803 l = aopGet (left, LSB, FALSE, FALSE);
8805 emitcode ("add", "a,acc");
8806 if (sameRegs (AOP (left), AOP (result)) &&
8807 size >= MSB16 + offr && offr != LSB)
8808 xch_a_aopGet (left, LSB + offr, FALSE, FALSE);
8810 aopPut (result, "a", LSB + offr);
8813 if (size >= MSB16 + offr)
8815 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8817 l = aopGet (left, MSB16, FALSE, FALSE);
8820 emitcode ("rlc", "a");
8821 if (sameRegs (AOP (left), AOP (result)) &&
8822 size >= MSB24 + offr && offr != LSB)
8823 xch_a_aopGet (left, MSB16 + offr, FALSE, FALSE);
8825 aopPut (result, "a", MSB16 + offr);
8828 if (size >= MSB24 + offr)
8830 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8832 l = aopGet (left, MSB24, FALSE, FALSE);
8835 emitcode ("rlc", "a");
8836 if (sameRegs (AOP (left), AOP (result)) &&
8837 size >= MSB32 + offr && offr != LSB)
8838 xch_a_aopGet (left, MSB24 + offr, FALSE, FALSE);
8840 aopPut (result, "a", MSB24 + offr);
8843 if (size > MSB32 + offr)
8845 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8847 l = aopGet (left, MSB32, FALSE, FALSE);
8850 emitcode ("rlc", "a");
8851 aopPut (result, "a", MSB32 + offr);
8854 aopPut (result, zero, LSB);
8857 /*-----------------------------------------------------------------*/
8858 /* genlshFour - shift four byte by a known amount != 0 */
8859 /*-----------------------------------------------------------------*/
8861 genlshFour (operand * result, operand * left, int shCount)
8865 D (emitcode (";", "genlshFour"));
8867 size = AOP_SIZE (result);
8869 /* if shifting more that 3 bytes */
8874 /* lowest order of left goes to the highest
8875 order of the destination */
8876 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8878 movLeft2Result (left, LSB, result, MSB32, 0);
8879 aopPut (result, zero, LSB);
8880 aopPut (result, zero, MSB16);
8881 aopPut (result, zero, MSB24);
8885 /* more than two bytes */
8886 else if (shCount >= 16)
8888 /* lower order two bytes goes to higher order two bytes */
8890 /* if some more remaining */
8892 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8895 movLeft2Result (left, MSB16, result, MSB32, 0);
8896 movLeft2Result (left, LSB, result, MSB24, 0);
8898 aopPut (result, zero, MSB16);
8899 aopPut (result, zero, LSB);
8903 /* if more than 1 byte */
8904 else if (shCount >= 8)
8906 /* lower order three bytes goes to higher order three bytes */
8911 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8913 movLeft2Result (left, LSB, result, MSB16, 0);
8919 movLeft2Result (left, MSB24, result, MSB32, 0);
8920 movLeft2Result (left, MSB16, result, MSB24, 0);
8921 movLeft2Result (left, LSB, result, MSB16, 0);
8922 aopPut (result, zero, LSB);
8924 else if (shCount == 1)
8925 shiftLLong (left, result, MSB16);
8928 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8929 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8930 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8931 aopPut (result, zero, LSB);
8936 /* 1 <= shCount <= 7 */
8937 else if (shCount <= 2)
8939 shiftLLong (left, result, LSB);
8941 shiftLLong (result, result, LSB);
8943 /* 3 <= shCount <= 7, optimize */
8946 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8947 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8948 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8952 /*-----------------------------------------------------------------*/
8953 /* genLeftShiftLiteral - left shifting by known count */
8954 /*-----------------------------------------------------------------*/
8956 genLeftShiftLiteral (operand * left,
8961 int shCount = (int) ulFromVal (AOP (right)->aopu.aop_lit);
8964 D (emitcode (";", "genLeftShiftLiteral"));
8966 freeAsmop (right, NULL, ic, TRUE);
8968 aopOp (left, ic, FALSE);
8969 aopOp (result, ic, FALSE);
8971 size = getSize (operandType (result));
8974 emitcode ("; shift left ", "result %d, left %d", size,
8978 /* I suppose that the left size >= result size */
8983 movLeft2Result (left, size, result, size, 0);
8986 else if (shCount >= (size * 8))
8990 aopPut (result, zero, size);
8998 genlshOne (result, left, shCount);
9002 genlshTwo (result, left, shCount);
9006 genlshFour (result, left, shCount);
9009 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9010 "*** ack! mystery literal shift!\n");
9014 freeAsmop (result, NULL, ic, TRUE);
9015 freeAsmop (left, NULL, ic, TRUE);
9018 /*-----------------------------------------------------------------*/
9019 /* genLeftShift - generates code for left shifting */
9020 /*-----------------------------------------------------------------*/
9022 genLeftShift (iCode * ic)
9024 operand *left, *right, *result;
9027 symbol *tlbl, *tlbl1;
9030 D (emitcode (";", "genLeftShift"));
9032 right = IC_RIGHT (ic);
9033 left = IC_LEFT (ic);
9034 result = IC_RESULT (ic);
9036 aopOp (right, ic, FALSE);
9038 /* if the shift count is known then do it
9039 as efficiently as possible */
9040 if (AOP_TYPE (right) == AOP_LIT)
9042 genLeftShiftLiteral (left, right, result, ic);
9046 /* shift count is unknown then we have to form
9047 a loop get the loop count in B : Note: we take
9048 only the lower order byte since shifting
9049 more that 32 bits make no sense anyway, ( the
9050 largest size of an object can be only 32 bits ) */
9053 MOVB (aopGet (right, 0, FALSE, FALSE));
9054 emitcode ("inc", "b");
9055 freeAsmop (right, NULL, ic, TRUE);
9056 aopOp (left, ic, FALSE);
9057 aopOp (result, ic, FALSE);
9059 /* now move the left to the result if they are not the same */
9060 if (!sameRegs (AOP (left), AOP (result)) &&
9061 AOP_SIZE (result) > 1)
9064 size = AOP_SIZE (result);
9068 l = aopGet (left, offset, FALSE, TRUE);
9069 if (*l == '@' && (IS_AOP_PREG (result)))
9072 emitcode ("mov", "a,%s", l);
9073 aopPut (result, "a", offset);
9076 aopPut (result, l, offset);
9081 tlbl = newiTempLabel (NULL);
9082 size = AOP_SIZE (result);
9084 tlbl1 = newiTempLabel (NULL);
9086 /* if it is only one byte then */
9089 symbol *tlbl1 = newiTempLabel (NULL);
9091 l = aopGet (left, 0, FALSE, FALSE);
9093 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9095 emitcode ("add", "a,acc");
9097 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9099 aopPut (result, "a", 0);
9103 reAdjustPreg (AOP (result));
9105 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9107 l = aopGet (result, offset, FALSE, FALSE);
9109 emitcode ("add", "a,acc");
9110 aopPut (result, "a", offset++);
9113 l = aopGet (result, offset, FALSE, FALSE);
9115 emitcode ("rlc", "a");
9116 aopPut (result, "a", offset++);
9118 reAdjustPreg (AOP (result));
9121 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9124 freeAsmop (result, NULL, ic, TRUE);
9125 freeAsmop (left, NULL, ic, TRUE);
9128 /*-----------------------------------------------------------------*/
9129 /* genrshOne - right shift a one byte quantity by known count */
9130 /*-----------------------------------------------------------------*/
9132 genrshOne (operand * result, operand * left,
9133 int shCount, int sign)
9135 D (emitcode (";", "genrshOne"));
9137 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9140 /*-----------------------------------------------------------------*/
9141 /* genrshTwo - right shift two bytes by known amount != 0 */
9142 /*-----------------------------------------------------------------*/
9144 genrshTwo (operand * result, operand * left,
9145 int shCount, int sign)
9147 D (emitcode (";", "genrshTwo"));
9149 /* if shCount >= 8 */
9154 shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
9156 movLeft2Result (left, MSB16, result, LSB, sign);
9157 addSign (result, MSB16, sign);
9160 /* 1 <= shCount <= 7 */
9162 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9165 /*-----------------------------------------------------------------*/
9166 /* shiftRLong - shift right one long from left to result */
9167 /* offl = LSB or MSB16 */
9168 /*-----------------------------------------------------------------*/
9170 shiftRLong (operand * left, int offl,
9171 operand * result, int sign)
9173 bool overlapping = regsInCommon (left, result) || operandsEqu(left, result);
9175 if (overlapping && offl>1)
9177 // we are in big trouble, but this shouldn't happen
9178 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9181 MOVA (aopGet (left, MSB32, FALSE, FALSE));
9188 emitcode ("rlc", "a");
9189 emitcode ("subb", "a,acc");
9190 if (overlapping && sameByte (AOP (left), MSB32, AOP (result), MSB32))
9192 xch_a_aopGet (left, MSB32, FALSE, FALSE);
9196 aopPut (result, "a", MSB32);
9197 MOVA (aopGet (left, MSB32, FALSE, FALSE));
9202 if (aopPutUsesAcc (result, zero, MSB32))
9204 emitcode("xch", "a,b");
9205 aopPut (result, zero, MSB32);
9206 emitcode("xch", "a,b");
9210 aopPut (result, zero, MSB32);
9217 emitcode ("clr", "c");
9221 emitcode ("mov", "c,acc.7");
9224 emitcode ("rrc", "a");
9226 if (overlapping && offl==MSB16 &&
9227 sameByte (AOP (left), MSB24, AOP (result), MSB32-offl))
9229 xch_a_aopGet (left, MSB24, FALSE, FALSE);
9233 aopPut (result, "a", MSB32 - offl);
9234 MOVA (aopGet (left, MSB24, FALSE, FALSE));
9237 emitcode ("rrc", "a");
9238 if (overlapping && offl==MSB16 &&
9239 sameByte (AOP (left), MSB16, AOP (result), MSB24-offl))
9241 xch_a_aopGet (left, MSB16, FALSE, FALSE);
9245 aopPut (result, "a", MSB24 - offl);
9246 MOVA (aopGet (left, MSB16, FALSE, FALSE));
9249 emitcode ("rrc", "a");
9252 aopPut (result, "a", MSB16 - offl);
9257 sameByte (AOP (left), LSB, AOP (result), MSB16-offl))
9259 xch_a_aopGet (left, LSB, FALSE, FALSE);
9263 aopPut (result, "a", MSB16 - offl);
9264 MOVA (aopGet (left, LSB, FALSE, FALSE));
9266 emitcode ("rrc", "a");
9267 aopPut (result, "a", LSB);
9271 /*-----------------------------------------------------------------*/
9272 /* genrshFour - shift four byte by a known amount != 0 */
9273 /*-----------------------------------------------------------------*/
9275 genrshFour (operand * result, operand * left,
9276 int shCount, int sign)
9278 D (emitcode (";", "genrshFour"));
9280 /* if shifting more that 3 bytes */
9285 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9287 movLeft2Result (left, MSB32, result, LSB, sign);
9288 addSign (result, MSB16, sign);
9290 else if (shCount >= 16)
9294 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9297 movLeft2Result (left, MSB24, result, LSB, 0);
9298 movLeft2Result (left, MSB32, result, MSB16, sign);
9300 addSign (result, MSB24, sign);
9302 else if (shCount >= 8)
9307 shiftRLong (left, MSB16, result, sign);
9309 else if (shCount == 0)
9311 movLeft2Result (left, MSB16, result, LSB, 0);
9312 movLeft2Result (left, MSB24, result, MSB16, 0);
9313 movLeft2Result (left, MSB32, result, MSB24, sign);
9314 addSign (result, MSB32, sign);
9318 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9319 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9320 /* the last shift is signed */
9321 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9322 addSign (result, MSB32, sign);
9327 /* 1 <= shCount <= 7 */
9330 shiftRLong (left, LSB, result, sign);
9332 shiftRLong (result, LSB, result, sign);
9336 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9337 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9338 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9343 /*-----------------------------------------------------------------*/
9344 /* genRightShiftLiteral - right shifting by known count */
9345 /*-----------------------------------------------------------------*/
9347 genRightShiftLiteral (operand * left,
9353 int shCount = (int) ulFromVal (AOP (right)->aopu.aop_lit);
9356 D (emitcode (";", "genRightShiftLiteral"));
9358 freeAsmop (right, NULL, ic, TRUE);
9360 aopOp (left, ic, FALSE);
9361 aopOp (result, ic, FALSE);
9364 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9368 size = getDataSize (left);
9369 /* test the LEFT size !!! */
9371 /* I suppose that the left size >= result size */
9374 size = getDataSize (result);
9376 movLeft2Result (left, size, result, size, 0);
9379 else if (shCount >= (size * 8))
9383 /* get sign in acc.7 */
9384 MOVA (aopGet (left, size - 1, FALSE, FALSE));
9386 addSign (result, LSB, sign);
9393 genrshOne (result, left, shCount, sign);
9397 genrshTwo (result, left, shCount, sign);
9401 genrshFour (result, left, shCount, sign);
9407 freeAsmop (result, NULL, ic, TRUE);
9408 freeAsmop (left, NULL, ic, TRUE);
9411 /*-----------------------------------------------------------------*/
9412 /* genSignedRightShift - right shift of signed number */
9413 /*-----------------------------------------------------------------*/
9415 genSignedRightShift (iCode * ic)
9417 operand *right, *left, *result;
9420 symbol *tlbl, *tlbl1;
9423 D (emitcode (";", "genSignedRightShift"));
9425 /* we do it the hard way put the shift count in b
9426 and loop thru preserving the sign */
9428 right = IC_RIGHT (ic);
9429 left = IC_LEFT (ic);
9430 result = IC_RESULT (ic);
9432 aopOp (right, ic, FALSE);
9435 if (AOP_TYPE (right) == AOP_LIT)
9437 genRightShiftLiteral (left, right, result, ic, 1);
9440 /* shift count is unknown then we have to form
9441 a loop get the loop count in B : Note: we take
9442 only the lower order byte since shifting
9443 more that 32 bits make no sense anyway, ( the
9444 largest size of an object can be only 32 bits ) */
9447 MOVB (aopGet (right, 0, FALSE, FALSE));
9448 emitcode ("inc", "b");
9449 freeAsmop (right, NULL, ic, TRUE);
9450 aopOp (left, ic, FALSE);
9451 aopOp (result, ic, FALSE);
9453 /* now move the left to the result if they are not the
9455 if (!sameRegs (AOP (left), AOP (result)) &&
9456 AOP_SIZE (result) > 1)
9459 size = AOP_SIZE (result);
9463 l = aopGet (left, offset, FALSE, TRUE);
9464 if (*l == '@' && IS_AOP_PREG (result))
9467 emitcode ("mov", "a,%s", l);
9468 aopPut (result, "a", offset);
9471 aopPut (result, l, offset);
9476 /* mov the highest order bit to OVR */
9477 tlbl = newiTempLabel (NULL);
9478 tlbl1 = newiTempLabel (NULL);
9480 size = AOP_SIZE (result);
9482 MOVA (aopGet (left, offset, FALSE, FALSE));
9483 emitcode ("rlc", "a");
9484 emitcode ("mov", "ov,c");
9485 /* if it is only one byte then */
9488 l = aopGet (left, 0, FALSE, FALSE);
9490 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9492 emitcode ("mov", "c,ov");
9493 emitcode ("rrc", "a");
9495 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9497 aopPut (result, "a", 0);
9501 reAdjustPreg (AOP (result));
9502 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9504 emitcode ("mov", "c,ov");
9507 l = aopGet (result, offset, FALSE, FALSE);
9509 emitcode ("rrc", "a");
9510 aopPut (result, "a", offset--);
9512 reAdjustPreg (AOP (result));
9514 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9518 freeAsmop (result, NULL, ic, TRUE);
9519 freeAsmop (left, NULL, ic, TRUE);
9522 /*-----------------------------------------------------------------*/
9523 /* genRightShift - generate code for right shifting */
9524 /*-----------------------------------------------------------------*/
9526 genRightShift (iCode * ic)
9528 operand *right, *left, *result;
9532 symbol *tlbl, *tlbl1;
9535 D (emitcode (";", "genRightShift"));
9537 /* if signed then we do it the hard way preserve the
9538 sign bit moving it inwards */
9539 letype = getSpec (operandType (IC_LEFT (ic)));
9541 if (!SPEC_USIGN (letype))
9543 genSignedRightShift (ic);
9547 /* signed & unsigned types are treated the same : i.e. the
9548 signed is NOT propagated inwards : quoting from the
9549 ANSI - standard : "for E1 >> E2, is equivalent to division
9550 by 2**E2 if unsigned or if it has a non-negative value,
9551 otherwise the result is implementation defined ", MY definition
9552 is that the sign does not get propagated */
9554 right = IC_RIGHT (ic);
9555 left = IC_LEFT (ic);
9556 result = IC_RESULT (ic);
9558 aopOp (right, ic, FALSE);
9560 /* if the shift count is known then do it
9561 as efficiently as possible */
9562 if (AOP_TYPE (right) == AOP_LIT)
9564 genRightShiftLiteral (left, right, result, ic, 0);
9568 /* shift count is unknown then we have to form
9569 a loop get the loop count in B : Note: we take
9570 only the lower order byte since shifting
9571 more that 32 bits make no sense anyway, ( the
9572 largest size of an object can be only 32 bits ) */
9575 MOVB (aopGet (right, 0, FALSE, FALSE));
9576 emitcode ("inc", "b");
9577 freeAsmop (right, NULL, ic, TRUE);
9578 aopOp (left, ic, FALSE);
9579 aopOp (result, ic, FALSE);
9581 /* now move the left to the result if they are not the
9583 if (!sameRegs (AOP (left), AOP (result)) &&
9584 AOP_SIZE (result) > 1)
9586 size = AOP_SIZE (result);
9590 l = aopGet (left, offset, FALSE, TRUE);
9591 if (*l == '@' && IS_AOP_PREG (result))
9594 emitcode ("mov", "a,%s", l);
9595 aopPut (result, "a", offset);
9598 aopPut (result, l, offset);
9603 tlbl = newiTempLabel (NULL);
9604 tlbl1 = newiTempLabel (NULL);
9605 size = AOP_SIZE (result);
9608 /* if it is only one byte then */
9611 l = aopGet (left, 0, FALSE, FALSE);
9613 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9616 emitcode ("rrc", "a");
9618 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9620 aopPut (result, "a", 0);
9624 reAdjustPreg (AOP (result));
9625 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9630 l = aopGet (result, offset, FALSE, FALSE);
9632 emitcode ("rrc", "a");
9633 aopPut (result, "a", offset--);
9635 reAdjustPreg (AOP (result));
9638 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9642 freeAsmop (result, NULL, ic, TRUE);
9643 freeAsmop (left, NULL, ic, TRUE);
9646 /*-----------------------------------------------------------------*/
9647 /* emitPtrByteGet - emits code to get a byte into A through a */
9648 /* pointer register (R0, R1, or DPTR). The */
9649 /* original value of A can be preserved in B. */
9650 /*-----------------------------------------------------------------*/
9652 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9659 emitcode ("mov", "b,a");
9660 emitcode ("mov", "a,@%s", rname);
9665 emitcode ("mov", "b,a");
9666 emitcode ("movx", "a,@%s", rname);
9671 emitcode ("mov", "b,a");
9672 emitcode ("movx", "a,@dptr");
9677 emitcode ("mov", "b,a");
9678 emitcode ("clr", "a");
9679 emitcode ("movc", "a,@a+dptr");
9685 emitcode ("push", "b");
9686 emitcode ("push", "acc");
9688 emitcode ("lcall", "__gptrget");
9690 emitcode ("pop", "b");
9695 /*-----------------------------------------------------------------*/
9696 /* emitPtrByteSet - emits code to set a byte from src through a */
9697 /* pointer register (R0, R1, or DPTR). */
9698 /*-----------------------------------------------------------------*/
9700 emitPtrByteSet (char *rname, int p_type, char *src)
9709 emitcode ("mov", "@%s,a", rname);
9712 emitcode ("mov", "@%s,%s", rname, src);
9717 emitcode ("movx", "@%s,a", rname);
9722 emitcode ("movx", "@dptr,a");
9727 emitcode ("lcall", "__gptrput");
9732 /*-----------------------------------------------------------------*/
9733 /* genUnpackBits - generates code for unpacking bits */
9734 /*-----------------------------------------------------------------*/
9736 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9738 int offset = 0; /* result byte offset */
9739 int rsize; /* result size */
9740 int rlen = 0; /* remaining bitfield length */
9741 sym_link *etype; /* bitfield type information */
9742 int blen; /* bitfield length */
9743 int bstr; /* bitfield starting bit within byte */
9746 D(emitcode (";", "genUnpackBits"));
9748 etype = getSpec (operandType (result));
9749 rsize = getSize (operandType (result));
9750 blen = SPEC_BLEN (etype);
9751 bstr = SPEC_BSTR (etype);
9753 if (ifx && blen <= 8)
9755 emitPtrByteGet (rname, ptype, FALSE);
9758 SNPRINTF (buffer, sizeof(buffer),
9760 genIfxJump (ifx, buffer, NULL, NULL, NULL);
9765 emitcode ("anl", "a,#0x%02x",
9766 (((unsigned char) -1) >> (8 - blen)) << bstr);
9767 genIfxJump (ifx, "a", NULL, NULL, NULL);
9773 /* If the bitfield length is less than a byte */
9776 emitPtrByteGet (rname, ptype, FALSE);
9778 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9779 if (!SPEC_USIGN (etype))
9781 /* signed bitfield */
9782 symbol *tlbl = newiTempLabel (NULL);
9784 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9785 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9788 aopPut (result, "a", offset++);
9792 /* Bit field did not fit in a byte. Copy all
9793 but the partial byte at the end. */
9794 for (rlen=blen;rlen>=8;rlen-=8)
9796 emitPtrByteGet (rname, ptype, FALSE);
9797 aopPut (result, "a", offset++);
9799 emitcode ("inc", "%s", rname);
9802 /* Handle the partial byte at the end */
9805 emitPtrByteGet (rname, ptype, FALSE);
9806 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9807 if (!SPEC_USIGN (etype))
9809 /* signed bitfield */
9810 symbol *tlbl = newiTempLabel (NULL);
9812 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9813 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9816 aopPut (result, "a", offset++);
9824 if (SPEC_USIGN (etype))
9828 /* signed bitfield: sign extension with 0x00 or 0xff */
9829 emitcode ("rlc", "a");
9830 emitcode ("subb", "a,acc");
9836 aopPut (result, source, offset++);
9841 /*-----------------------------------------------------------------*/
9842 /* genDataPointerGet - generates code when ptr offset is known */
9843 /*-----------------------------------------------------------------*/
9845 genDataPointerGet (operand * left,
9851 int size, offset = 0;
9853 D (emitcode (";", "genDataPointerGet"));
9855 aopOp (result, ic, TRUE);
9857 /* get the string representation of the name */
9858 l = aopGet (left, 0, FALSE, TRUE);
9860 size = AOP_SIZE (result);
9865 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
9869 SNPRINTF (buffer, sizeof(buffer), "%s", l);
9871 aopPut (result, buffer, offset++);
9874 freeAsmop (result, NULL, ic, TRUE);
9875 freeAsmop (left, NULL, ic, TRUE);
9878 /*-----------------------------------------------------------------*/
9879 /* genNearPointerGet - emitcode for near pointer fetch */
9880 /*-----------------------------------------------------------------*/
9882 genNearPointerGet (operand * left,
9891 sym_link *rtype, *retype;
9892 sym_link *ltype = operandType (left);
9895 D (emitcode (";", "genNearPointerGet"));
9897 rtype = operandType (result);
9898 retype = getSpec (rtype);
9900 aopOp (left, ic, FALSE);
9902 /* if left is rematerialisable and
9903 result is not bitfield variable type and
9904 the left is pointer to data space i.e
9905 lower 128 bytes of space */
9906 if (AOP_TYPE (left) == AOP_IMMD &&
9907 !IS_BITFIELD (retype) &&
9908 DCL_TYPE (ltype) == POINTER)
9910 genDataPointerGet (left, result, ic);
9914 /* if the value is already in a pointer register
9915 then don't need anything more */
9916 if (!AOP_INPREG (AOP (left)))
9918 if (IS_AOP_PREG (left))
9920 // Aha, it is a pointer, just in disguise.
9921 rname = aopGet (left, 0, FALSE, FALSE);
9924 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9925 __FILE__, __LINE__);
9930 emitcode ("mov", "a%s,%s", rname + 1, rname);
9931 rname++; // skip the '@'.
9936 /* otherwise get a free pointer register */
9938 preg = getFreePtr (ic, &aop, FALSE);
9939 emitcode ("mov", "%s,%s",
9941 aopGet (left, 0, FALSE, TRUE));
9946 rname = aopGet (left, 0, FALSE, FALSE);
9948 //aopOp (result, ic, FALSE);
9949 aopOp (result, ic, result?TRUE:FALSE);
9951 /* if bitfield then unpack the bits */
9952 if (IS_BITFIELD (retype))
9953 genUnpackBits (result, rname, POINTER, ifx);
9956 /* we have can just get the values */
9957 int size = AOP_SIZE (result);
9962 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9965 emitcode ("mov", "a,@%s", rname);
9967 aopPut (result, "a", offset);
9971 SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
9972 aopPut (result, buffer, offset);
9976 emitcode ("inc", "%s", rname);
9980 /* now some housekeeping stuff */
9981 if (aop) /* we had to allocate for this iCode */
9983 if (pi) { /* post increment present */
9984 aopPut (left, rname, 0);
9986 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9990 /* we did not allocate which means left
9991 already in a pointer register, then
9992 if size > 0 && this could be used again
9993 we have to point it back to where it
9995 if ((AOP_SIZE (result) > 1 &&
9996 !OP_SYMBOL (left)->remat &&
9997 (OP_SYMBOL (left)->liveTo > ic->seq ||
10001 int size = AOP_SIZE (result) - 1;
10003 emitcode ("dec", "%s", rname);
10007 if (ifx && !ifx->generated)
10009 genIfxJump (ifx, "a", left, NULL, result);
10013 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
10014 freeAsmop (left, NULL, ic, TRUE);
10015 if (pi) pi->generated = 1;
10018 /*-----------------------------------------------------------------*/
10019 /* genPagedPointerGet - emitcode for paged pointer fetch */
10020 /*-----------------------------------------------------------------*/
10022 genPagedPointerGet (operand * left,
10031 sym_link *rtype, *retype;
10033 D (emitcode (";", "genPagedPointerGet"));
10035 rtype = operandType (result);
10036 retype = getSpec (rtype);
10038 aopOp (left, ic, FALSE);
10040 /* if the value is already in a pointer register
10041 then don't need anything more */
10042 if (!AOP_INPREG (AOP (left)))
10044 /* otherwise get a free pointer register */
10045 aop = newAsmop (0);
10046 preg = getFreePtr (ic, &aop, FALSE);
10047 emitcode ("mov", "%s,%s",
10049 aopGet (left, 0, FALSE, TRUE));
10050 rname = preg->name;
10053 rname = aopGet (left, 0, FALSE, FALSE);
10055 aopOp (result, ic, FALSE);
10057 /* if bitfield then unpack the bits */
10058 if (IS_BITFIELD (retype))
10059 genUnpackBits (result, rname, PPOINTER, ifx);
10062 /* we have can just get the values */
10063 int size = AOP_SIZE (result);
10069 emitcode ("movx", "a,@%s", rname);
10071 aopPut (result, "a", offset);
10076 emitcode ("inc", "%s", rname);
10080 /* now some housekeeping stuff */
10081 if (aop) /* we had to allocate for this iCode */
10084 aopPut (left, rname, 0);
10085 freeAsmop (NULL, aop, ic, TRUE);
10089 /* we did not allocate which means left
10090 already in a pointer register, then
10091 if size > 0 && this could be used again
10092 we have to point it back to where it
10094 if ((AOP_SIZE (result) > 1 &&
10095 !OP_SYMBOL (left)->remat &&
10096 (OP_SYMBOL (left)->liveTo > ic->seq ||
10100 int size = AOP_SIZE (result) - 1;
10102 emitcode ("dec", "%s", rname);
10106 if (ifx && !ifx->generated)
10108 genIfxJump (ifx, "a", left, NULL, result);
10112 freeAsmop (result, NULL, ic, TRUE);
10113 freeAsmop (left, NULL, ic, TRUE);
10114 if (pi) pi->generated = 1;
10117 /*--------------------------------------------------------------------*/
10118 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
10119 /*--------------------------------------------------------------------*/
10121 loadDptrFromOperand (operand *op, bool loadBToo)
10123 if (AOP_TYPE (op) != AOP_STR)
10125 /* if this is rematerializable */
10126 if (AOP_TYPE (op) == AOP_IMMD)
10128 emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
10131 if (AOP(op)->aopu.aop_immd.from_cast_remat)
10132 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
10135 wassertl(FALSE, "need pointerCode");
10136 emitcode (";", "mov b,???");
10137 /* genPointerGet and genPointerSet originally did different
10138 ** things for this case. Both seem wrong.
10139 ** from genPointerGet:
10140 ** emitcode ("mov", "b,#%d", pointerCode (retype));
10141 ** from genPointerSet:
10142 ** emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
10147 else if (AOP_TYPE (op) == AOP_DPTR)
10151 MOVA (aopGet (op, 0, FALSE, FALSE));
10152 emitcode ("push", "acc");
10153 MOVA (aopGet (op, 1, FALSE, FALSE));
10154 emitcode ("push", "acc");
10155 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10156 emitcode ("pop", "dph");
10157 emitcode ("pop", "dpl");
10161 MOVA (aopGet (op, 0, FALSE, FALSE));
10162 emitcode ("push", "acc");
10163 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10164 emitcode ("pop", "dpl");
10168 { /* we need to get it byte by byte */
10169 emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
10170 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10172 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10177 /*-----------------------------------------------------------------*/
10178 /* genFarPointerGet - get value from far space */
10179 /*-----------------------------------------------------------------*/
10181 genFarPointerGet (operand * left,
10182 operand * result, iCode * ic, iCode * pi, iCode * ifx)
10185 sym_link *retype = getSpec (operandType (result));
10187 D (emitcode (";", "genFarPointerGet"));
10189 aopOp (left, ic, FALSE);
10190 loadDptrFromOperand (left, FALSE);
10192 /* so dptr now contains the address */
10193 aopOp (result, ic, FALSE);
10195 /* if bit then unpack */
10196 if (IS_BITFIELD (retype))
10197 genUnpackBits (result, "dptr", FPOINTER, ifx);
10200 size = AOP_SIZE (result);
10205 emitcode ("movx", "a,@dptr");
10207 aopPut (result, "a", offset++);
10209 emitcode ("inc", "dptr");
10213 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10215 aopPut (left, "dpl", 0);
10216 aopPut (left, "dph", 1);
10220 if (ifx && !ifx->generated)
10222 genIfxJump (ifx, "a", left, NULL, result);
10225 freeAsmop (result, NULL, ic, TRUE);
10226 freeAsmop (left, NULL, ic, TRUE);
10229 /*-----------------------------------------------------------------*/
10230 /* genCodePointerGet - get value from code space */
10231 /*-----------------------------------------------------------------*/
10233 genCodePointerGet (operand * left,
10234 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10237 sym_link *retype = getSpec (operandType (result));
10239 D (emitcode (";", "genCodePointerGet"));
10241 aopOp (left, ic, FALSE);
10242 loadDptrFromOperand (left, FALSE);
10244 /* so dptr now contains the address */
10245 aopOp (result, ic, FALSE);
10247 /* if bit then unpack */
10248 if (IS_BITFIELD (retype))
10249 genUnpackBits (result, "dptr", CPOINTER, ifx);
10252 size = AOP_SIZE (result);
10257 emitcode ("clr", "a");
10258 emitcode ("movc", "a,@a+dptr");
10260 aopPut (result, "a", offset++);
10262 emitcode ("inc", "dptr");
10266 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10268 aopPut (left, "dpl", 0);
10269 aopPut (left, "dph", 1);
10273 if (ifx && !ifx->generated)
10275 genIfxJump (ifx, "a", left, NULL, result);
10278 freeAsmop (result, NULL, ic, TRUE);
10279 freeAsmop (left, NULL, ic, TRUE);
10282 /*-----------------------------------------------------------------*/
10283 /* genGenPointerGet - get value from generic pointer space */
10284 /*-----------------------------------------------------------------*/
10286 genGenPointerGet (operand * left,
10287 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10290 sym_link *retype = getSpec (operandType (result));
10292 D (emitcode (";", "genGenPointerGet"));
10294 aopOp (left, ic, FALSE);
10295 loadDptrFromOperand (left, TRUE);
10297 /* so dptr now contains the address */
10298 aopOp (result, ic, FALSE);
10300 /* if bit then unpack */
10301 if (IS_BITFIELD (retype))
10303 genUnpackBits (result, "dptr", GPOINTER, ifx);
10307 size = AOP_SIZE (result);
10312 emitcode ("lcall", "__gptrget");
10314 aopPut (result, "a", offset++);
10316 emitcode ("inc", "dptr");
10320 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10322 aopPut (left, "dpl", 0);
10323 aopPut (left, "dph", 1);
10327 if (ifx && !ifx->generated)
10329 genIfxJump (ifx, "a", left, NULL, result);
10332 freeAsmop (result, NULL, ic, TRUE);
10333 freeAsmop (left, NULL, ic, TRUE);
10336 /*-----------------------------------------------------------------*/
10337 /* genPointerGet - generate code for pointer get */
10338 /*-----------------------------------------------------------------*/
10340 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
10342 operand *left, *result;
10343 sym_link *type, *etype;
10346 D (emitcode (";", "genPointerGet"));
10348 left = IC_LEFT (ic);
10349 result = IC_RESULT (ic);
10351 if (getSize (operandType (result))>1)
10354 /* depending on the type of pointer we need to
10355 move it to the correct pointer register */
10356 type = operandType (left);
10357 etype = getSpec (type);
10358 /* if left is of type of pointer then it is simple */
10359 if (IS_PTR (type) && !IS_FUNC (type->next))
10361 p_type = DCL_TYPE (type);
10365 /* we have to go by the storage class */
10366 p_type = PTR_TYPE (SPEC_OCLS (etype));
10369 /* special case when cast remat */
10370 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10371 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10373 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10374 type = operandType (left);
10375 p_type = DCL_TYPE (type);
10377 /* now that we have the pointer type we assign
10378 the pointer values */
10384 genNearPointerGet (left, result, ic, pi, ifx);
10388 genPagedPointerGet (left, result, ic, pi, ifx);
10392 genFarPointerGet (left, result, ic, pi, ifx);
10396 genCodePointerGet (left, result, ic, pi, ifx);
10400 genGenPointerGet (left, result, ic, pi, ifx);
10406 /*-----------------------------------------------------------------*/
10407 /* genPackBits - generates code for packed bit storage */
10408 /*-----------------------------------------------------------------*/
10410 genPackBits (sym_link * etype,
10412 char *rname, int p_type)
10414 int offset = 0; /* source byte offset */
10415 int rlen = 0; /* remaining bitfield length */
10416 int blen; /* bitfield length */
10417 int bstr; /* bitfield starting bit within byte */
10418 int litval; /* source literal value (if AOP_LIT) */
10419 unsigned char mask; /* bitmask within current byte */
10421 D(emitcode (";", "genPackBits"));
10423 blen = SPEC_BLEN (etype);
10424 bstr = SPEC_BSTR (etype);
10426 /* If the bitfield length is less than a byte */
10429 mask = ((unsigned char) (0xFF << (blen + bstr)) |
10430 (unsigned char) (0xFF >> (8 - bstr)));
10432 if (AOP_TYPE (right) == AOP_LIT)
10434 /* Case with a bitfield length <8 and literal source
10436 litval = (int) ulFromVal (AOP (right)->aopu.aop_lit);
10438 litval &= (~mask) & 0xff;
10439 emitPtrByteGet (rname, p_type, FALSE);
10440 if ((mask|litval)!=0xff)
10441 emitcode ("anl","a,#0x%02x", mask);
10443 emitcode ("orl","a,#0x%02x", litval);
10447 if ((blen==1) && (p_type!=GPOINTER))
10449 /* Case with a bitfield length == 1 and no generic pointer
10451 if (AOP_TYPE (right) == AOP_CRY)
10452 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10455 MOVA (aopGet (right, 0, FALSE, FALSE));
10456 emitcode ("rrc","a");
10458 emitPtrByteGet (rname, p_type, FALSE);
10459 emitcode ("mov","acc.%d,c",bstr);
10464 /* Case with a bitfield length < 8 and arbitrary source
10466 MOVA (aopGet (right, 0, FALSE, FALSE));
10467 /* shift and mask source value */
10469 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10471 pushedB = pushB ();
10472 /* transfer A to B and get next byte */
10473 emitPtrByteGet (rname, p_type, TRUE);
10475 emitcode ("anl", "a,#0x%02x", mask);
10476 emitcode ("orl", "a,b");
10477 if (p_type == GPOINTER)
10478 emitcode ("pop", "b");
10484 emitPtrByteSet (rname, p_type, "a");
10488 /* Bit length is greater than 7 bits. In this case, copy */
10489 /* all except the partial byte at the end */
10490 for (rlen=blen;rlen>=8;rlen-=8)
10492 emitPtrByteSet (rname, p_type,
10493 aopGet (right, offset++, FALSE, TRUE) );
10495 emitcode ("inc", "%s", rname);
10498 /* If there was a partial byte at the end */
10501 mask = (((unsigned char) -1 << rlen) & 0xff);
10503 if (AOP_TYPE (right) == AOP_LIT)
10505 /* Case with partial byte and literal source
10507 litval = (int) ulFromVal (AOP (right)->aopu.aop_lit);
10508 litval >>= (blen-rlen);
10509 litval &= (~mask) & 0xff;
10510 emitPtrByteGet (rname, p_type, FALSE);
10511 if ((mask|litval)!=0xff)
10512 emitcode ("anl","a,#0x%02x", mask);
10514 emitcode ("orl","a,#0x%02x", litval);
10519 /* Case with partial byte and arbitrary source
10521 MOVA (aopGet (right, offset++, FALSE, FALSE));
10522 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10524 pushedB = pushB ();
10525 /* transfer A to B and get next byte */
10526 emitPtrByteGet (rname, p_type, TRUE);
10528 emitcode ("anl", "a,#0x%02x", mask);
10529 emitcode ("orl", "a,b");
10530 if (p_type == GPOINTER)
10531 emitcode ("pop", "b");
10535 emitPtrByteSet (rname, p_type, "a");
10540 /*-----------------------------------------------------------------*/
10541 /* genDataPointerSet - remat pointer to data space */
10542 /*-----------------------------------------------------------------*/
10544 genDataPointerSet (operand * right,
10548 int size, offset = 0;
10549 char *l, buffer[256];
10551 D (emitcode (";", "genDataPointerSet"));
10553 aopOp (right, ic, FALSE);
10555 l = aopGet (result, 0, FALSE, TRUE);
10557 size = max (AOP_SIZE (right), AOP_SIZE (result));
10561 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
10563 SNPRINTF (buffer, sizeof(buffer), "%s", l);
10564 emitcode ("mov", "%s,%s", buffer,
10565 aopGet (right, offset++, FALSE, FALSE));
10568 freeAsmop (right, NULL, ic, TRUE);
10569 freeAsmop (result, NULL, ic, TRUE);
10572 /*-----------------------------------------------------------------*/
10573 /* genNearPointerSet - emitcode for near pointer put */
10574 /*-----------------------------------------------------------------*/
10576 genNearPointerSet (operand * right,
10584 sym_link *retype, *letype;
10585 sym_link *ptype = operandType (result);
10587 D (emitcode (";", "genNearPointerSet"));
10589 retype = getSpec (operandType (right));
10590 letype = getSpec (ptype);
10592 aopOp (result, ic, FALSE);
10594 /* if the result is rematerializable &
10595 in data space & not a bit variable */
10596 if (AOP_TYPE (result) == AOP_IMMD &&
10597 DCL_TYPE (ptype) == POINTER &&
10598 !IS_BITVAR (retype) &&
10599 !IS_BITVAR (letype))
10601 genDataPointerSet (right, result, ic);
10605 /* if the value is already in a pointer register
10606 then don't need anything more */
10607 if (!AOP_INPREG (AOP (result)))
10610 //AOP_TYPE (result) == AOP_STK
10611 IS_AOP_PREG(result)
10614 // Aha, it is a pointer, just in disguise.
10615 rname = aopGet (result, 0, FALSE, FALSE);
10618 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10619 __FILE__, __LINE__);
10624 emitcode ("mov", "a%s,%s", rname + 1, rname);
10625 rname++; // skip the '@'.
10630 /* otherwise get a free pointer register */
10631 aop = newAsmop (0);
10632 preg = getFreePtr (ic, &aop, FALSE);
10633 emitcode ("mov", "%s,%s",
10635 aopGet (result, 0, FALSE, TRUE));
10636 rname = preg->name;
10641 rname = aopGet (result, 0, FALSE, FALSE);
10644 aopOp (right, ic, FALSE);
10646 /* if bitfield then unpack the bits */
10647 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10648 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10651 /* we can just get the values */
10652 int size = AOP_SIZE (right);
10657 l = aopGet (right, offset, FALSE, TRUE);
10658 if ((*l == '@') || (strcmp (l, "acc") == 0))
10661 emitcode ("mov", "@%s,a", rname);
10664 emitcode ("mov", "@%s,%s", rname, l);
10666 emitcode ("inc", "%s", rname);
10671 /* now some housekeeping stuff */
10672 if (aop) /* we had to allocate for this iCode */
10675 aopPut (result, rname, 0);
10676 freeAsmop (NULL, aop, ic, TRUE);
10680 /* we did not allocate which means left
10681 already in a pointer register, then
10682 if size > 0 && this could be used again
10683 we have to point it back to where it
10685 if ((AOP_SIZE (right) > 1 &&
10686 !OP_SYMBOL (result)->remat &&
10687 (OP_SYMBOL (result)->liveTo > ic->seq ||
10691 int size = AOP_SIZE (right) - 1;
10693 emitcode ("dec", "%s", rname);
10700 freeAsmop (right, NULL, ic, TRUE);
10701 freeAsmop (result, NULL, ic, TRUE);
10704 /*-----------------------------------------------------------------*/
10705 /* genPagedPointerSet - emitcode for Paged pointer put */
10706 /*-----------------------------------------------------------------*/
10708 genPagedPointerSet (operand * right,
10716 sym_link *retype, *letype;
10718 D (emitcode (";", "genPagedPointerSet"));
10720 retype = getSpec (operandType (right));
10721 letype = getSpec (operandType (result));
10723 aopOp (result, ic, FALSE);
10725 /* if the value is already in a pointer register
10726 then don't need anything more */
10727 if (!AOP_INPREG (AOP (result)))
10729 /* otherwise get a free pointer register */
10730 aop = newAsmop (0);
10731 preg = getFreePtr (ic, &aop, FALSE);
10732 emitcode ("mov", "%s,%s",
10734 aopGet (result, 0, FALSE, TRUE));
10735 rname = preg->name;
10738 rname = aopGet (result, 0, FALSE, FALSE);
10740 aopOp (right, ic, FALSE);
10742 /* if bitfield then unpack the bits */
10743 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10744 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10747 /* we have can just get the values */
10748 int size = AOP_SIZE (right);
10753 l = aopGet (right, offset, FALSE, TRUE);
10755 emitcode ("movx", "@%s,a", rname);
10758 emitcode ("inc", "%s", rname);
10764 /* now some housekeeping stuff */
10765 if (aop) /* we had to allocate for this iCode */
10768 aopPut (result, rname, 0);
10769 freeAsmop (NULL, aop, ic, TRUE);
10773 /* we did not allocate which means left
10774 already in a pointer register, then
10775 if size > 0 && this could be used again
10776 we have to point it back to where it
10778 if (AOP_SIZE (right) > 1 &&
10779 !OP_SYMBOL (result)->remat &&
10780 (OP_SYMBOL (result)->liveTo > ic->seq ||
10783 int size = AOP_SIZE (right) - 1;
10785 emitcode ("dec", "%s", rname);
10790 if (pi) pi->generated = 1;
10791 freeAsmop (result, NULL, ic, TRUE);
10792 freeAsmop (right, NULL, ic, TRUE);
10795 /*-----------------------------------------------------------------*/
10796 /* genFarPointerSet - set value from far space */
10797 /*-----------------------------------------------------------------*/
10799 genFarPointerSet (operand * right,
10800 operand * result, iCode * ic, iCode * pi)
10803 sym_link *retype = getSpec (operandType (right));
10804 sym_link *letype = getSpec (operandType (result));
10806 D(emitcode (";", "genFarPointerSet"));
10808 aopOp (result, ic, FALSE);
10809 loadDptrFromOperand (result, FALSE);
10811 /* so dptr now contains the address */
10812 aopOp (right, ic, FALSE);
10814 /* if bit then unpack */
10815 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10816 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10819 size = AOP_SIZE (right);
10824 char *l = aopGet (right, offset++, FALSE, FALSE);
10826 emitcode ("movx", "@dptr,a");
10828 emitcode ("inc", "dptr");
10831 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10832 aopPut (result, "dpl", 0);
10833 aopPut (result, "dph", 1);
10836 freeAsmop (result, NULL, ic, TRUE);
10837 freeAsmop (right, NULL, ic, TRUE);
10840 /*-----------------------------------------------------------------*/
10841 /* genGenPointerSet - set value from generic pointer space */
10842 /*-----------------------------------------------------------------*/
10844 genGenPointerSet (operand * right,
10845 operand * result, iCode * ic, iCode * pi)
10848 sym_link *retype = getSpec (operandType (right));
10849 sym_link *letype = getSpec (operandType (result));
10851 D (emitcode (";", "genGenPointerSet"));
10853 aopOp (result, ic, FALSE);
10854 loadDptrFromOperand (result, TRUE);
10856 /* so dptr now contains the address */
10857 aopOp (right, ic, FALSE);
10859 /* if bit then unpack */
10860 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10862 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10866 size = AOP_SIZE (right);
10871 char *l = aopGet (right, offset++, FALSE, FALSE);
10873 emitcode ("lcall", "__gptrput");
10875 emitcode ("inc", "dptr");
10879 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10880 aopPut (result, "dpl", 0);
10881 aopPut (result, "dph", 1);
10884 freeAsmop (result, NULL, ic, TRUE);
10885 freeAsmop (right, NULL, ic, TRUE);
10888 /*-----------------------------------------------------------------*/
10889 /* genPointerSet - stores the value into a pointer location */
10890 /*-----------------------------------------------------------------*/
10892 genPointerSet (iCode * ic, iCode *pi)
10894 operand *right, *result;
10895 sym_link *type, *etype;
10898 D (emitcode (";", "genPointerSet"));
10900 right = IC_RIGHT (ic);
10901 result = IC_RESULT (ic);
10903 /* depending on the type of pointer we need to
10904 move it to the correct pointer register */
10905 type = operandType (result);
10906 etype = getSpec (type);
10907 /* if left is of type of pointer then it is simple */
10908 if (IS_PTR (type) && !IS_FUNC (type->next))
10910 p_type = DCL_TYPE (type);
10914 /* we have to go by the storage class */
10915 p_type = PTR_TYPE (SPEC_OCLS (etype));
10918 /* special case when cast remat */
10919 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10920 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10921 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10922 type = operandType (result);
10923 p_type = DCL_TYPE (type);
10926 /* now that we have the pointer type we assign
10927 the pointer values */
10933 genNearPointerSet (right, result, ic, pi);
10937 genPagedPointerSet (right, result, ic, pi);
10941 genFarPointerSet (right, result, ic, pi);
10945 genGenPointerSet (right, result, ic, pi);
10949 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10950 "genPointerSet: illegal pointer type");
10954 /*-----------------------------------------------------------------*/
10955 /* genIfx - generate code for Ifx statement */
10956 /*-----------------------------------------------------------------*/
10958 genIfx (iCode * ic, iCode * popIc)
10960 operand *cond = IC_COND (ic);
10964 D (emitcode (";", "genIfx"));
10966 aopOp (cond, ic, FALSE);
10968 /* get the value into acc */
10969 if (AOP_TYPE (cond) != AOP_CRY)
10976 if (AOP(cond)->aopu.aop_dir)
10977 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10980 /* the result is now in the accumulator or a directly addressable bit */
10981 freeAsmop (cond, NULL, ic, TRUE);
10983 /* if there was something to be popped then do it */
10987 /* if the condition is a bit variable */
10989 genIfxJump(ic, dup, NULL, NULL, NULL);
10990 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10991 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10992 else if (isbit && !IS_ITEMP (cond))
10993 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10995 genIfxJump (ic, "a", NULL, NULL, NULL);
11000 /*-----------------------------------------------------------------*/
11001 /* genAddrOf - generates code for address of */
11002 /*-----------------------------------------------------------------*/
11004 genAddrOf (iCode * ic)
11006 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
11009 D (emitcode (";", "genAddrOf"));
11011 aopOp (IC_RESULT (ic), ic, FALSE);
11013 /* if the operand is on the stack then we
11014 need to get the stack offset of this
11018 /* if it has an offset then we need to compute it */
11021 int stack_offset = ((sym->stack < 0) ?
11022 ((char) (sym->stack - _G.nRegsSaved)) :
11023 ((char) sym->stack)) & 0xff;
11024 if ((abs(stack_offset) == 1) &&
11025 !AOP_NEEDSACC(IC_RESULT (ic)) &&
11026 !isOperandVolatile (IC_RESULT (ic), FALSE))
11028 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
11029 if (stack_offset > 0)
11030 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
11032 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
11036 emitcode ("mov", "a,%s", SYM_BP (sym));
11037 emitcode ("add", "a,#0x%02x", stack_offset & 0xff);
11038 aopPut (IC_RESULT (ic), "a", 0);
11043 /* we can just move _bp */
11044 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
11046 /* fill the result with zero */
11047 size = AOP_SIZE (IC_RESULT (ic)) - 1;
11052 aopPut (IC_RESULT (ic), zero, offset++);
11057 /* object not on stack then we need the name */
11058 size = AOP_SIZE (IC_RESULT (ic));
11063 char s[SDCC_NAME_MAX];
11065 sprintf (s, "#(%s >> %d)",
11069 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11070 aopPut (IC_RESULT (ic), s, offset++);
11074 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11078 /*-----------------------------------------------------------------*/
11079 /* genFarFarAssign - assignment when both are in far space */
11080 /*-----------------------------------------------------------------*/
11082 genFarFarAssign (operand * result, operand * right, iCode * ic)
11084 int size = AOP_SIZE (right);
11088 D (emitcode (";", "genFarFarAssign"));
11090 /* first push the right side on to the stack */
11093 l = aopGet (right, offset++, FALSE, FALSE);
11095 emitcode ("push", "acc");
11098 freeAsmop (right, NULL, ic, FALSE);
11099 /* now assign DPTR to result */
11100 aopOp (result, ic, FALSE);
11101 size = AOP_SIZE (result);
11104 emitcode ("pop", "acc");
11105 aopPut (result, "a", --offset);
11107 freeAsmop (result, NULL, ic, FALSE);
11110 /*-----------------------------------------------------------------*/
11111 /* genAssign - generate code for assignment */
11112 /*-----------------------------------------------------------------*/
11114 genAssign (iCode * ic)
11116 operand *result, *right;
11118 unsigned long lit = 0L;
11120 D (emitcode (";", "genAssign"));
11122 result = IC_RESULT (ic);
11123 right = IC_RIGHT (ic);
11125 /* if they are the same */
11126 if (operandsEqu (result, right) &&
11127 !isOperandVolatile (result, FALSE) &&
11128 !isOperandVolatile (right, FALSE))
11131 aopOp (right, ic, FALSE);
11133 /* special case both in far space */
11134 if (AOP_TYPE (right) == AOP_DPTR &&
11135 IS_TRUE_SYMOP (result) &&
11136 isOperandInFarSpace (result))
11138 genFarFarAssign (result, right, ic);
11142 aopOp (result, ic, TRUE);
11144 /* if they are the same registers */
11145 if (sameRegs (AOP (right), AOP (result)) &&
11146 !isOperandVolatile (result, FALSE) &&
11147 !isOperandVolatile (right, FALSE))
11150 /* if the result is a bit */
11151 if (AOP_TYPE (result) == AOP_CRY)
11153 assignBit (result, right);
11157 /* bit variables done */
11159 size = AOP_SIZE (result);
11161 if (AOP_TYPE (right) == AOP_LIT)
11162 lit = ulFromVal (AOP (right)->aopu.aop_lit);
11165 (AOP_TYPE (result) != AOP_REG) &&
11166 (AOP_TYPE (right) == AOP_LIT) &&
11167 !IS_FLOAT (operandType (right)) &&
11170 while ((size) && (lit))
11173 aopGet (right, offset, FALSE, FALSE),
11179 /* And now fill the rest with zeros. */
11182 emitcode ("clr", "a");
11186 aopPut (result, "a", offset);
11195 aopGet (right, offset, FALSE, FALSE),
11202 freeAsmop (result, NULL, ic, TRUE);
11203 freeAsmop (right, NULL, ic, TRUE);
11206 /*-----------------------------------------------------------------*/
11207 /* genJumpTab - generates code for jump table */
11208 /*-----------------------------------------------------------------*/
11210 genJumpTab (iCode * ic)
11212 symbol *jtab,*jtablo,*jtabhi;
11214 unsigned int count;
11216 D (emitcode (";", "genJumpTab"));
11218 count = elementsInSet( IC_JTLABELS (ic) );
11222 /* this algorithm needs 9 cycles and 7 + 3*n bytes
11223 if the switch argument is in a register.
11224 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
11225 /* Peephole may not convert ljmp to sjmp or ret
11226 labelIsReturnOnly & labelInRange must check
11227 currPl->ic->op != JUMPTABLE */
11228 aopOp (IC_JTCOND (ic), ic, FALSE);
11229 /* get the condition into accumulator */
11230 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11232 /* multiply by three */
11233 if (aopGetUsesAcc (IC_JTCOND (ic), 0))
11235 emitcode ("mov", "b,#3");
11236 emitcode ("mul", "ab");
11240 emitcode ("add", "a,acc");
11241 emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
11243 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11245 jtab = newiTempLabel (NULL);
11246 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
11247 emitcode ("jmp", "@a+dptr");
11249 /* now generate the jump labels */
11250 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11251 jtab = setNextItem (IC_JTLABELS (ic)))
11252 emitcode ("ljmp", "%05d$", jtab->key + 100);
11256 /* this algorithm needs 14 cycles and 13 + 2*n bytes
11257 if the switch argument is in a register.
11258 For n>6 this algorithm may be more compact */
11259 jtablo = newiTempLabel (NULL);
11260 jtabhi = newiTempLabel (NULL);
11262 /* get the condition into accumulator.
11263 Using b as temporary storage, if register push/pop is needed */
11264 aopOp (IC_JTCOND (ic), ic, FALSE);
11265 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11266 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
11267 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
11269 // (MB) what if B is in use???
11270 wassertl(!BINUSE, "B was in use");
11271 emitcode ("mov", "b,%s", l);
11274 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11278 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
11279 emitcode ("movc", "a,@a+pc");
11280 emitcode ("push", "acc");
11283 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
11284 emitcode ("movc", "a,@a+pc");
11285 emitcode ("push", "acc");
11289 /* this scales up to n<=255, but needs two more bytes
11290 and changes dptr */
11291 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
11292 emitcode ("movc", "a,@a+dptr");
11293 emitcode ("push", "acc");
11296 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
11297 emitcode ("movc", "a,@a+dptr");
11298 emitcode ("push", "acc");
11301 emitcode ("ret", "");
11303 /* now generate jump table, LSB */
11304 emitLabel (jtablo);
11305 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11306 jtab = setNextItem (IC_JTLABELS (ic)))
11307 emitcode (".db", "%05d$", jtab->key + 100);
11309 /* now generate jump table, MSB */
11310 emitLabel (jtabhi);
11311 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11312 jtab = setNextItem (IC_JTLABELS (ic)))
11313 emitcode (".db", "%05d$>>8", jtab->key + 100);
11317 /*-----------------------------------------------------------------*/
11318 /* genCast - gen code for casting */
11319 /*-----------------------------------------------------------------*/
11321 genCast (iCode * ic)
11323 operand *result = IC_RESULT (ic);
11324 sym_link *ctype = operandType (IC_LEFT (ic));
11325 sym_link *rtype = operandType (IC_RIGHT (ic));
11326 operand *right = IC_RIGHT (ic);
11329 D (emitcode (";", "genCast"));
11331 /* if they are equivalent then do nothing */
11332 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11335 aopOp (right, ic, FALSE);
11336 aopOp (result, ic, FALSE);
11338 /* if the result is a bit (and not a bitfield) */
11339 if (IS_BIT (OP_SYMBOL (result)->type))
11341 assignBit (result, right);
11345 /* if they are the same size : or less */
11346 if (AOP_SIZE (result) <= AOP_SIZE (right))
11349 /* if they are in the same place */
11350 if (sameRegs (AOP (right), AOP (result)))
11353 /* if they in different places then copy */
11354 size = AOP_SIZE (result);
11359 aopGet (right, offset, FALSE, FALSE),
11366 /* if the result is of type pointer */
11367 if (IS_PTR (ctype))
11371 sym_link *type = operandType (right);
11372 sym_link *etype = getSpec (type);
11374 /* pointer to generic pointer */
11375 if (IS_GENPTR (ctype))
11379 p_type = DCL_TYPE (type);
11383 if (SPEC_SCLS(etype)==S_REGISTER) {
11384 // let's assume it is a generic pointer
11387 /* we have to go by the storage class */
11388 p_type = PTR_TYPE (SPEC_OCLS (etype));
11392 /* the first two bytes are known */
11393 size = GPTRSIZE - 1;
11398 aopGet (right, offset, FALSE, FALSE),
11402 /* the last byte depending on type */
11404 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11409 // pointerTypeToGPByte will have bitched.
11413 sprintf(gpValStr, "#0x%x", gpVal);
11414 aopPut (result, gpValStr, GPTRSIZE - 1);
11419 /* just copy the pointers */
11420 size = AOP_SIZE (result);
11425 aopGet (right, offset, FALSE, FALSE),
11432 /* so we now know that the size of destination is greater
11433 than the size of the source */
11434 /* we move to result for the size of source */
11435 size = AOP_SIZE (right);
11440 aopGet (right, offset, FALSE, FALSE),
11445 /* now depending on the sign of the source && destination */
11446 size = AOP_SIZE (result) - AOP_SIZE (right);
11447 /* if unsigned or not an integral type */
11448 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11451 aopPut (result, zero, offset++);
11455 /* we need to extend the sign :{ */
11456 char *l = aopGet (right, AOP_SIZE (right) - 1,
11459 emitcode ("rlc", "a");
11460 emitcode ("subb", "a,acc");
11462 aopPut (result, "a", offset++);
11465 /* we are done hurray !!!! */
11468 freeAsmop (result, NULL, ic, TRUE);
11469 freeAsmop (right, NULL, ic, TRUE);
11472 /*-----------------------------------------------------------------*/
11473 /* genDjnz - generate decrement & jump if not zero instrucion */
11474 /*-----------------------------------------------------------------*/
11476 genDjnz (iCode * ic, iCode * ifx)
11478 symbol *lbl, *lbl1;
11482 /* if the if condition has a false label
11483 then we cannot save */
11484 if (IC_FALSE (ifx))
11487 /* if the minus is not of the form a = a - 1 */
11488 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11489 !IS_OP_LITERAL (IC_RIGHT (ic)))
11492 if (operandLitValue (IC_RIGHT (ic)) != 1)
11495 /* if the size of this greater than one then no
11497 if (getSize (operandType (IC_RESULT (ic))) > 1)
11500 /* otherwise we can save BIG */
11502 D (emitcode (";", "genDjnz"));
11504 lbl = newiTempLabel (NULL);
11505 lbl1 = newiTempLabel (NULL);
11507 aopOp (IC_RESULT (ic), ic, FALSE);
11509 if (AOP_NEEDSACC(IC_RESULT(ic)))
11511 /* If the result is accessed indirectly via
11512 * the accumulator, we must explicitly write
11513 * it back after the decrement.
11515 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11517 if (strcmp(rByte, "a"))
11519 /* Something is hopelessly wrong */
11520 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11521 __FILE__, __LINE__);
11522 /* We can just give up; the generated code will be inefficient,
11523 * but what the hey.
11525 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11528 emitcode ("dec", "%s", rByte);
11529 aopPut (IC_RESULT (ic), rByte, 0);
11530 emitcode ("jnz", "%05d$", lbl->key + 100);
11532 else if (IS_AOP_PREG (IC_RESULT (ic)))
11534 emitcode ("dec", "%s",
11535 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11536 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11537 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11538 ifx->generated = 1;
11539 emitcode ("jnz", "%05d$", lbl->key + 100);
11543 emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11546 emitcode ("sjmp", "%05d$", lbl1->key + 100);
11548 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11551 if (!ifx->generated)
11552 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11553 ifx->generated = 1;
11557 /*-----------------------------------------------------------------*/
11558 /* genReceive - generate code for a receive iCode */
11559 /*-----------------------------------------------------------------*/
11561 genReceive (iCode * ic)
11563 int size = getSize (operandType (IC_RESULT (ic)));
11566 D (emitcode (";", "genReceive"));
11568 if (ic->argreg == 1)
11569 { /* first parameter */
11570 if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11571 isOperandInPagedSpace (IC_RESULT (ic))) &&
11572 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11573 IS_TRUE_SYMOP (IC_RESULT (ic))))
11576 int receivingA = 0;
11579 for (offset = 0; offset<size; offset++)
11580 if (!strcmp (fReturn[offset], "a"))
11585 if (size==1 || getTempRegs(tempRegs, size-1, ic))
11587 for (offset = size-1; offset>0; offset--)
11588 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11589 emitcode("mov","a,%s", fReturn[0]);
11591 aopOp (IC_RESULT (ic), ic, FALSE);
11593 aopPut (IC_RESULT (ic), "a", offset);
11594 for (offset = 1; offset<size; offset++)
11595 aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset);
11601 if (getTempRegs(tempRegs, size, ic))
11603 for (offset = 0; offset<size; offset++)
11604 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11605 aopOp (IC_RESULT (ic), ic, FALSE);
11606 for (offset = 0; offset<size; offset++)
11607 aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset);
11612 offset = fReturnSizeMCS51 - size;
11615 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11616 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11619 aopOp (IC_RESULT (ic), ic, FALSE);
11620 size = AOP_SIZE (IC_RESULT (ic));
11624 emitcode ("pop", "acc");
11625 aopPut (IC_RESULT (ic), "a", offset++);
11631 aopOp (IC_RESULT (ic), ic, FALSE);
11633 assignResultValue (IC_RESULT (ic), NULL);
11636 else if (ic->argreg > 12)
11637 { /* bit parameters */
11638 regs *reg = OP_SYMBOL (IC_RESULT (ic))->regs[0];
11641 if (!reg || reg->rIdx != ic->argreg-5)
11643 aopOp (IC_RESULT (ic), ic, FALSE);
11644 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11645 outBitC(IC_RESULT (ic));
11649 { /* other parameters */
11651 aopOp (IC_RESULT (ic), ic, FALSE);
11652 rb1off = ic->argreg;
11655 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
11660 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11663 /*-----------------------------------------------------------------*/
11664 /* genDummyRead - generate code for dummy read of volatiles */
11665 /*-----------------------------------------------------------------*/
11667 genDummyRead (iCode * ic)
11672 D (emitcode(";", "genDummyRead"));
11674 op = IC_RIGHT (ic);
11675 if (op && IS_SYMOP (op))
11677 aopOp (op, ic, FALSE);
11679 /* if the result is a bit */
11680 if (AOP_TYPE (op) == AOP_CRY)
11681 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11684 /* bit variables done */
11686 size = AOP_SIZE (op);
11690 MOVA (aopGet (op, offset, FALSE, FALSE));
11695 freeAsmop (op, NULL, ic, TRUE);
11699 if (op && IS_SYMOP (op))
11701 aopOp (op, ic, FALSE);
11703 /* if the result is a bit */
11704 if (AOP_TYPE (op) == AOP_CRY)
11705 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11708 /* bit variables done */
11710 size = AOP_SIZE (op);
11714 MOVA (aopGet (op, offset, FALSE, FALSE));
11719 freeAsmop (op, NULL, ic, TRUE);
11723 /*-----------------------------------------------------------------*/
11724 /* genCritical - generate code for start of a critical sequence */
11725 /*-----------------------------------------------------------------*/
11727 genCritical (iCode *ic)
11729 symbol *tlbl = newiTempLabel (NULL);
11731 D (emitcode(";", "genCritical"));
11733 if (IC_RESULT (ic))
11735 aopOp (IC_RESULT (ic), ic, TRUE);
11736 aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
11737 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11738 aopPut (IC_RESULT (ic), zero, 0);
11740 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11744 emitcode ("setb", "c");
11745 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11746 emitcode ("clr", "c");
11748 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11752 /*-----------------------------------------------------------------*/
11753 /* genEndCritical - generate code for end of a critical sequence */
11754 /*-----------------------------------------------------------------*/
11756 genEndCritical (iCode *ic)
11758 D(emitcode(";", "genEndCritical"));
11762 aopOp (IC_RIGHT (ic), ic, FALSE);
11763 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11765 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11766 emitcode ("mov", "ea,c");
11770 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11771 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11772 emitcode ("rrc", "a");
11773 emitcode ("mov", "ea,c");
11775 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11779 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11780 emitcode ("mov", "ea,c");
11784 /*-----------------------------------------------------------------*/
11785 /* gen51Code - generate code for 8051 based controllers */
11786 /*-----------------------------------------------------------------*/
11788 gen51Code (iCode * lic)
11792 /* int cseq = 0; */
11794 _G.currentFunc = NULL;
11795 lineHead = lineCurr = NULL;
11797 /* print the allocation information */
11798 if (allocInfo && currFunc)
11799 printAllocInfo (currFunc, codeOutBuf);
11800 /* if debug information required */
11801 if (options.debug && currFunc)
11803 debugFile->writeFunction (currFunc, lic);
11805 /* stack pointer name */
11806 if (options.useXstack)
11812 for (ic = lic; ic; ic = ic->next)
11814 _G.current_iCode = ic;
11816 if (ic->lineno && cln != ic->lineno)
11820 debugFile->writeCLine (ic);
11822 if (!options.noCcodeInAsm) {
11823 emitcode (";", "%s:%d: %s", ic->filename, ic->lineno,
11824 printCLine(ic->filename, ic->lineno));
11829 if (ic->seqPoint && ic->seqPoint != cseq)
11831 emitcode (";", "sequence point %d", ic->seqPoint);
11832 cseq = ic->seqPoint;
11835 if (options.iCodeInAsm) {
11836 char regsInUse[80];
11841 for (i=0; i<8; i++) {
11842 sprintf (®sInUse[i],
11843 "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11846 strcpy (regsInUse, "--------");
11847 for (i=0; i < 8; i++) {
11848 if (bitVectBitValue (ic->rMask, i))
11850 int offset = regs8051[i].offset;
11851 regsInUse[offset] = offset + '0'; /* show rMask */
11855 iLine = printILine(ic);
11856 emitcode(";", "[%s] ic:%d: %s", regsInUse, ic->seq, iLine);
11859 /* if the result is marked as
11860 spilt and rematerializable or code for
11861 this has already been generated then
11863 if (resultRemat (ic) || ic->generated)
11866 /* depending on the operation */
11886 /* IPOP happens only when trying to restore a
11887 spilt live range, if there is an ifx statement
11888 following this pop then the if statement might
11889 be using some of the registers being popped which
11890 would destory the contents of the register so
11891 we need to check for this condition and handle it */
11893 ic->next->op == IFX &&
11894 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11895 genIfx (ic->next, ic);
11913 genEndFunction (ic);
11933 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11950 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11954 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11961 /* note these two are xlated by algebraic equivalence
11962 in decorateType() in SDCCast.c */
11963 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11964 "got '>=' or '<=' shouldn't have come here");
11968 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11980 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11984 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11988 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
12024 genRightShift (ic);
12027 case GET_VALUE_AT_ADDRESS:
12029 hasInc (IC_LEFT (ic), ic,
12030 getSize (operandType (IC_RESULT (ic)))),
12031 ifxForOp (IC_RESULT (ic), ic) );
12035 if (POINTER_SET (ic))
12037 hasInc (IC_RESULT (ic), ic,
12038 getSize (operandType (IC_RIGHT (ic)))));
12064 addSet (&_G.sendSet, ic);
12067 case DUMMY_READ_VOLATILE:
12076 genEndCritical (ic);
12088 _G.current_iCode = NULL;
12090 /* now we are ready to call the
12091 peep hole optimizer */
12092 if (!options.nopeep)
12093 peepHole (&lineHead);
12095 /* now do the actual printing */
12096 printLine (lineHead, codeOutBuf);