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 = aopForSym (ic, sym->usl.spillLoc, result);
1010 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1012 /* Don't reuse the new aop, go with the last one */
1013 sym->usl.spillLoc->aop = oldAsmOp;
1015 aop->size = getSize (sym->type);
1019 /* else must be a dummy iTemp */
1020 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1021 aop->size = getSize (sym->type);
1025 /* if the type is a bit register */
1026 if (sym->regType == REG_BIT)
1028 sym->aop = op->aop = aop = newAsmop (AOP_CRY);
1029 aop->size = sym->nRegs;//1???
1030 aop->aopu.aop_reg[0] = sym->regs[0];
1031 aop->aopu.aop_dir = sym->regs[0]->name;
1035 /* must be in a register */
1036 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1037 aop->size = sym->nRegs;
1038 for (i = 0; i < sym->nRegs; i++)
1039 aop->aopu.aop_reg[i] = sym->regs[i];
1042 /*-----------------------------------------------------------------*/
1043 /* freeAsmop - free up the asmop given to an operand */
1044 /*-----------------------------------------------------------------*/
1046 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1063 /* depending on the asmop type only three cases need work
1064 AOP_R0, AOP_R1 & AOP_STK */
1070 emitcode ("mov", "r0,b");
1073 else if (_G.r0Pushed)
1077 emitcode ("pop", "ar0");
1081 bitVectUnSetBit (ic->rUsed, R0_IDX);
1087 emitcode ("mov", "r1,b");
1090 else if (_G.r1Pushed)
1094 emitcode ("pop", "ar1");
1098 bitVectUnSetBit (ic->rUsed, R1_IDX);
1104 int stk = aop->aopu.aop_stk + aop->size - 1;
1105 bitVectUnSetBit (ic->rUsed, R0_IDX);
1106 bitVectUnSetBit (ic->rUsed, R1_IDX);
1108 getFreePtr (ic, &aop, FALSE);
1112 emitcode ("mov", "a,_bp");
1113 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1114 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1118 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1123 emitcode ("pop", "acc");
1124 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1127 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1130 freeAsmop (op, NULL, ic, TRUE);
1133 emitcode ("pop", "ar1");
1138 emitcode ("pop", "ar0");
1146 /* all other cases just dealloc */
1152 OP_SYMBOL (op)->aop = NULL;
1153 /* if the symbol has a spill */
1155 SPIL_LOC (op)->aop = NULL;
1160 /*------------------------------------------------------------------*/
1161 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
1162 /* pop r0 or r1 off stack if pushed */
1163 /*------------------------------------------------------------------*/
1165 freeForBranchAsmop (operand * op)
1177 if (!aop->allocated)
1185 emitcode ("mov", "r0,b");
1187 else if (_G.r0Pushed)
1189 emitcode ("pop", "ar0");
1196 emitcode ("mov", "r1,b");
1198 else if (_G.r1Pushed)
1200 emitcode ("pop", "ar1");
1207 int stk = aop->aopu.aop_stk + aop->size - 1;
1209 emitcode ("mov", "b,r0");
1212 emitcode ("mov", "a,_bp");
1213 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1214 emitcode ("mov", "r0,a");
1218 emitcode ("mov", "r0,_bp");
1223 emitcode ("pop", "acc");
1224 emitcode ("mov", "@r0,a");
1227 emitcode ("dec", "r0");
1229 emitcode ("mov", "r0,b");
1235 /*-----------------------------------------------------------------*/
1236 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
1237 /* clobber the accumulator */
1238 /*-----------------------------------------------------------------*/
1240 aopGetUsesAcc (operand * oper, int offset)
1242 asmop * aop = AOP (oper);
1244 if (offset > (aop->size - 1))
1262 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1273 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1279 /* Error case --- will have been caught already */
1285 /*-------------------------------------------------------------------*/
1286 /* aopGet - for fetching value of the aop */
1287 /*-------------------------------------------------------------------*/
1289 aopGet (operand * oper, int offset, bool bit16, bool dname)
1291 asmop * aop = AOP (oper);
1293 /* offset is greater than
1295 if (offset > (aop->size - 1) &&
1296 aop->type != AOP_LIT)
1299 /* depending on type */
1307 /* if we need to increment it */
1308 while (offset > aop->coff)
1310 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1314 while (offset < aop->coff)
1316 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1323 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1324 return (dname ? "acc" : "a");
1326 SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1327 return Safe_strdup(buffer);
1330 if (aop->code && aop->coff==0 && offset>=1) {
1331 emitcode ("mov", "a,#0x%02x", offset);
1332 emitcode ("movc", "a,@a+dptr");
1333 return (dname ? "acc" : "a");
1336 while (offset > aop->coff)
1338 emitcode ("inc", "dptr");
1342 while (offset < aop->coff)
1344 emitcode ("lcall", "__decdptr");
1351 emitcode ("clr", "a");
1352 emitcode ("movc", "a,@a+dptr");
1356 emitcode ("movx", "a,@dptr");
1358 return (dname ? "acc" : "a");
1361 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1363 SNPRINTF(buffer, sizeof(buffer),
1364 "%s",aop->aopu.aop_immd.aop_immd2);
1368 SNPRINTF(buffer, sizeof(buffer),
1369 "#%s", aop->aopu.aop_immd.aop_immd1);
1373 SNPRINTF (buffer, sizeof(buffer),
1375 aop->aopu.aop_immd.aop_immd1,
1380 SNPRINTF (buffer, sizeof(buffer),
1382 aop->aopu.aop_immd.aop_immd1);
1384 return Safe_strdup(buffer);
1387 if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
1389 SNPRINTF (buffer, sizeof(buffer),
1391 aop->aopu.aop_dir, offset * 8);
1395 SNPRINTF (buffer, sizeof(buffer),
1402 SNPRINTF (buffer, sizeof(buffer),
1407 return Safe_strdup(buffer);
1411 return aop->aopu.aop_reg[offset]->dname;
1413 return aop->aopu.aop_reg[offset]->name;
1416 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1417 emitcode ("clr", "a");
1418 emitcode ("rlc", "a");
1419 return (dname ? "acc" : "a");
1422 if (!offset && dname)
1424 return aop->aopu.aop_str[offset];
1427 return aopLiteral (aop->aopu.aop_lit, offset);
1431 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1435 return aop->aopu.aop_str[offset];
1439 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1440 "aopget got unsupported aop->type");
1444 /*-----------------------------------------------------------------*/
1445 /* aopPutUsesAcc - indicates ahead of time whether aopPut() will */
1446 /* clobber the accumulator */
1447 /*-----------------------------------------------------------------*/
1449 aopPutUsesAcc (operand * oper, const char *s, int offset)
1451 asmop * aop = AOP (oper);
1453 if (offset > (aop->size - 1))
1463 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1469 return ((aop->paged) || (*s == '@'));
1473 return (!aop->aopu.aop_dir || strcmp(s, aop->aopu.aop_dir));
1481 /* Error case --- will have been caught already */
1487 /*-----------------------------------------------------------------*/
1488 /* aopPut - puts a string for a aop and indicates if acc is in use */
1489 /*-----------------------------------------------------------------*/
1491 aopPut (operand * result, const char *s, int offset)
1493 bool bvolatile = isOperandVolatile (result, FALSE);
1494 bool accuse = FALSE;
1495 asmop * aop = AOP (result);
1496 const char *d = NULL;
1498 if (aop->size && offset > (aop->size - 1))
1500 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1501 "aopPut got offset > aop->size");
1505 /* will assign value to value */
1506 /* depending on where it is ofcourse */
1510 MOVA (s); /* read s in case it was volatile */
1515 if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1517 SNPRINTF (buffer, sizeof(buffer),
1519 aop->aopu.aop_dir, offset * 8);
1523 SNPRINTF (buffer, sizeof(buffer),
1525 aop->aopu.aop_dir, offset);
1529 SNPRINTF (buffer, sizeof(buffer),
1534 if (strcmp (buffer, s) || bvolatile)
1536 emitcode ("mov", "%s,%s", buffer, s);
1538 if (!strcmp (buffer, "acc"))
1545 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1546 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1549 strcmp (s, "r0") == 0 ||
1550 strcmp (s, "r1") == 0 ||
1551 strcmp (s, "r2") == 0 ||
1552 strcmp (s, "r3") == 0 ||
1553 strcmp (s, "r4") == 0 ||
1554 strcmp (s, "r5") == 0 ||
1555 strcmp (s, "r6") == 0 ||
1556 strcmp (s, "r7") == 0)
1558 emitcode ("mov", "%s,%s",
1559 aop->aopu.aop_reg[offset]->dname, s);
1563 emitcode ("mov", "%s,%s",
1564 aop->aopu.aop_reg[offset]->name, s);
1572 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1573 "aopPut writing to code space");
1577 while (offset > aop->coff)
1580 emitcode ("inc", "dptr");
1583 while (offset < aop->coff)
1586 emitcode ("lcall", "__decdptr");
1591 /* if not in accumulator */
1594 emitcode ("movx", "@dptr,a");
1599 while (offset > aop->coff)
1602 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1604 while (offset < aop->coff)
1607 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1614 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1619 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1621 else if (strcmp (s, "r0") == 0 ||
1622 strcmp (s, "r1") == 0 ||
1623 strcmp (s, "r2") == 0 ||
1624 strcmp (s, "r3") == 0 ||
1625 strcmp (s, "r4") == 0 ||
1626 strcmp (s, "r5") == 0 ||
1627 strcmp (s, "r6") == 0 ||
1628 strcmp (s, "r7") == 0)
1631 SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1632 emitcode ("mov", "@%s,%s",
1633 aop->aopu.aop_ptr->name, buffer);
1637 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1642 if (strcmp (s, "a") == 0)
1644 emitcode ("push", "acc");
1649 emitcode ("push", "acc");
1651 else if (strcmp (s, "r0") == 0 ||
1652 strcmp (s, "r1") == 0 ||
1653 strcmp (s, "r2") == 0 ||
1654 strcmp (s, "r3") == 0 ||
1655 strcmp (s, "r4") == 0 ||
1656 strcmp (s, "r5") == 0 ||
1657 strcmp (s, "r6") == 0 ||
1658 strcmp (s, "r7") == 0)
1661 SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1662 emitcode ("push", buffer);
1666 emitcode ("push", s);
1672 // destination is carry for return-use-only
1673 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 if (op && IS_GENPTR (operandType (op)) && (AOP_SIZE (op) == GPTRSIZE))
1803 /*-----------------------------------------------------------------*/
1804 /* getDataSize - get the operand data size */
1805 /*-----------------------------------------------------------------*/
1807 getDataSize (operand * op)
1809 int size = AOP_SIZE (op);
1811 if (size == GPTRSIZE)
1813 sym_link *type = operandType (op);
1814 if (IS_GENPTR (type))
1816 /* generic pointer; arithmetic operations
1817 * should ignore the high byte (pointer type).
1825 /*-----------------------------------------------------------------*/
1826 /* outAcc - output Acc */
1827 /*-----------------------------------------------------------------*/
1829 outAcc (operand * result)
1832 size = getDataSize (result);
1835 aopPut (result, "a", 0);
1838 /* unsigned or positive */
1841 aopPut (result, zero, offset++);
1846 /*-----------------------------------------------------------------*/
1847 /* outBitC - output a bit C */
1848 /*-----------------------------------------------------------------*/
1850 outBitC (operand * result)
1852 /* if the result is bit */
1853 if (AOP_TYPE (result) == AOP_CRY)
1855 if (!IS_OP_RUONLY (result))
1856 aopPut (result, "c", 0);
1858 else if (AOP_TYPE (result) != AOP_DUMMY)
1860 emitcode ("clr", "a");
1861 emitcode ("rlc", "a");
1866 /*-----------------------------------------------------------------*/
1867 /* toBoolean - emit code for orl a,operator(sizeop) */
1868 /*-----------------------------------------------------------------*/
1870 toBoolean (operand * oper)
1872 int size = AOP_SIZE (oper) - 1;
1874 bool AccUsed = FALSE;
1877 while (!AccUsed && size--)
1879 AccUsed |= aopGetUsesAcc(oper, offset++);
1882 size = AOP_SIZE (oper) - 1;
1884 MOVA (aopGet (oper, 0, FALSE, FALSE));
1885 if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1888 emitcode("mov", "b,a");
1891 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1892 emitcode ("orl", "b,a");
1894 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1895 emitcode ("orl", "a,b");
1902 emitcode ("orl", "a,%s",
1903 aopGet (oper, offset++, FALSE, FALSE));
1908 /*-----------------------------------------------------------------*/
1909 /* toCarry - make boolean and move into carry */
1910 /*-----------------------------------------------------------------*/
1912 toCarry (operand * oper)
1914 /* if the operand is a literal then
1915 we know what the value is */
1916 if (AOP_TYPE (oper) == AOP_LIT)
1918 if ((int) operandLitValue (oper))
1923 else if (AOP_TYPE (oper) == AOP_CRY)
1925 emitcode ("mov", "c,%s", oper->aop->aopu.aop_dir);
1929 /* or the operand into a */
1931 /* set C, if a >= 1 */
1932 emitcode ("add", "a,#0xff");
1936 /*-----------------------------------------------------------------*/
1937 /* assignBit - assign operand to bit operand */
1938 /*-----------------------------------------------------------------*/
1940 assignBit (operand * result, operand * right)
1942 /* if the right side is a literal then
1943 we know what the value is */
1944 if (AOP_TYPE (right) == AOP_LIT)
1946 if ((int) operandLitValue (right))
1947 aopPut (result, one, 0);
1949 aopPut (result, zero, 0);
1954 aopPut (result, "c", 0);
1959 /*-------------------------------------------------------------------*/
1960 /* xch_a_aopGet - for exchanging acc with value of the aop */
1961 /*-------------------------------------------------------------------*/
1963 xch_a_aopGet (operand * oper, int offset, bool bit16, bool dname)
1967 if (aopGetUsesAcc (oper, offset))
1969 emitcode("mov", "b,a");
1970 MOVA (aopGet (oper, offset, bit16, dname));
1971 emitcode("xch", "a,b");
1972 aopPut (oper, "a", offset);
1973 emitcode("xch", "a,b");
1978 l = aopGet (oper, offset, bit16, dname);
1979 emitcode("xch", "a,%s", l);
1985 /*-----------------------------------------------------------------*/
1986 /* genNot - generate code for ! operation */
1987 /*-----------------------------------------------------------------*/
1993 D (emitcode (";", "genNot"));
1995 /* assign asmOps to operand & result */
1996 aopOp (IC_LEFT (ic), ic, FALSE);
1997 aopOp (IC_RESULT (ic), ic, TRUE);
1999 /* if in bit space then a special case */
2000 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2002 /* if left==result then cpl bit */
2003 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2005 emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2009 toCarry (IC_LEFT (ic));
2010 emitcode ("cpl", "c");
2011 outBitC (IC_RESULT (ic));
2016 toBoolean (IC_LEFT (ic));
2018 /* set C, if a == 0 */
2019 tlbl = newiTempLabel (NULL);
2020 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
2022 outBitC (IC_RESULT (ic));
2025 /* release the aops */
2026 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2027 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2031 /*-----------------------------------------------------------------*/
2032 /* genCpl - generate code for complement */
2033 /*-----------------------------------------------------------------*/
2040 sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
2042 D(emitcode (";", "genCpl"));
2044 /* assign asmOps to operand & result */
2045 aopOp (IC_LEFT (ic), ic, FALSE);
2046 aopOp (IC_RESULT (ic), ic, TRUE);
2048 /* special case if in bit space */
2049 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2053 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
2054 (SPEC_USIGN (letype) && IS_CHAR (letype)))
2056 /* promotion rules are responsible for this strange result:
2057 bit -> int -> ~int -> bit
2058 uchar -> int -> ~int -> bit
2060 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
2064 tlbl=newiTempLabel(NULL);
2065 l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
2066 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
2067 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
2068 IS_AOP_PREG (IC_LEFT (ic)))
2070 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
2075 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
2078 outBitC (IC_RESULT(ic));
2082 size = AOP_SIZE (IC_RESULT (ic));
2085 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2087 emitcode ("cpl", "a");
2088 aopPut (IC_RESULT (ic), "a", offset++);
2093 /* release the aops */
2094 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2095 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2098 /*-----------------------------------------------------------------*/
2099 /* genUminusFloat - unary minus for floating points */
2100 /*-----------------------------------------------------------------*/
2102 genUminusFloat (operand * op, operand * result)
2104 int size, offset = 0;
2107 D (emitcode (";", "genUminusFloat"));
2109 /* for this we just copy and then flip the bit */
2111 size = AOP_SIZE (op) - 1;
2116 aopGet (op, offset, FALSE, FALSE),
2121 l = aopGet (op, offset, FALSE, FALSE);
2124 emitcode ("cpl", "acc.7");
2125 aopPut (result, "a", offset);
2128 /*-----------------------------------------------------------------*/
2129 /* genUminus - unary minus code generation */
2130 /*-----------------------------------------------------------------*/
2132 genUminus (iCode * ic)
2137 D (emitcode (";", "genUminus"));
2140 aopOp (IC_LEFT (ic), ic, FALSE);
2141 aopOp (IC_RESULT (ic), ic, TRUE);
2143 /* if both in bit space then special
2145 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2146 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2149 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2150 emitcode ("cpl", "c");
2151 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2155 optype = operandType (IC_LEFT (ic));
2157 /* if float then do float stuff */
2158 if (IS_FLOAT (optype))
2160 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2164 /* otherwise subtract from zero */
2165 size = AOP_SIZE (IC_LEFT (ic));
2169 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2170 if (!strcmp (l, "a"))
2174 emitcode ("cpl", "a");
2175 emitcode ("addc", "a,#0x00");
2181 emitcode ("clr", "a");
2182 emitcode ("subb", "a,%s", l);
2184 aopPut (IC_RESULT (ic), "a", offset++);
2187 /* if any remaining bytes in the result */
2188 /* we just need to propagate the sign */
2189 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2191 emitcode ("rlc", "a");
2192 emitcode ("subb", "a,acc");
2194 aopPut (IC_RESULT (ic), "a", offset++);
2198 /* release the aops */
2199 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2200 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2203 /*-----------------------------------------------------------------*/
2204 /* saveRegisters - will look for a call and save the registers */
2205 /*-----------------------------------------------------------------*/
2207 saveRegisters (iCode * lic)
2214 for (ic = lic; ic; ic = ic->next)
2215 if (ic->op == CALL || ic->op == PCALL)
2220 fprintf (stderr, "found parameter push with no function call\n");
2224 /* if the registers have been saved already or don't need to be then
2228 if (IS_SYMOP(IC_LEFT(ic)) &&
2229 (IFFUNC_CALLEESAVES (OP_SYMBOL (IC_LEFT (ic))->type) ||
2230 IFFUNC_ISNAKED (OP_SYM_TYPE (IC_LEFT (ic)))))
2233 /* save the registers in use at this time but skip the
2234 ones for the result */
2235 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2236 mcs51_rUmaskForOp (IC_RESULT(ic)));
2239 if (options.useXstack)
2241 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2242 int nBits = bitVectnBitsOn (rsavebits);
2243 int count = bitVectnBitsOn (rsave);
2247 count = count - nBits + 1;
2248 /* remove all but the first bits as they are pushed all at once */
2249 rsave = bitVectCplAnd (rsave, rsavebits);
2250 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2252 freeBitVect (rsavebits);
2256 regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2257 if (reg->type == REG_BIT)
2259 emitcode ("mov", "a,%s", reg->base);
2263 emitcode ("mov", "a,%s", reg->name);
2265 emitcode ("mov", "r0,%s", spname);
2266 emitcode ("inc", "%s", spname);// allocate before use
2267 emitcode ("movx", "@r0,a");
2268 if (bitVectBitValue (rsave, R0_IDX))
2269 emitcode ("mov", "r0,a");
2271 else if (count != 0)
2273 if (bitVectBitValue (rsave, R0_IDX))
2275 emitcode ("push", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2277 emitcode ("mov", "r0,%s", spname);
2279 emitcode ("add", "a,#0x%02x", count);
2280 emitcode ("mov", "%s,a", spname);
2281 for (i = 0; i < mcs51_nRegs; i++)
2283 if (bitVectBitValue (rsave, i))
2285 regs * reg = REG_WITH_INDEX (i);
2288 emitcode ("pop", "acc");
2289 emitcode ("push", "acc");
2291 else if (reg->type == REG_BIT)
2293 emitcode ("mov", "a,%s", reg->base);
2297 emitcode ("mov", "a,%s", reg->name);
2299 emitcode ("movx", "@r0,a");
2302 emitcode ("inc", "r0");
2306 if (bitVectBitValue (rsave, R0_IDX))
2308 emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2314 bool bits_pushed = FALSE;
2315 for (i = 0; i < mcs51_nRegs; i++)
2317 if (bitVectBitValue (rsave, i))
2319 bits_pushed = pushReg (i, bits_pushed);
2323 freeBitVect (rsave);
2326 /*-----------------------------------------------------------------*/
2327 /* unsaveRegisters - pop the pushed registers */
2328 /*-----------------------------------------------------------------*/
2330 unsaveRegisters (iCode * ic)
2335 /* restore the registers in use at this time but skip the
2336 ones for the result */
2337 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2338 mcs51_rUmaskForOp (IC_RESULT(ic)));
2340 if (options.useXstack)
2342 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2343 int nBits = bitVectnBitsOn (rsavebits);
2344 int count = bitVectnBitsOn (rsave);
2348 count = count - nBits + 1;
2349 /* remove all but the first bits as they are popped all at once */
2350 rsave = bitVectCplAnd (rsave, rsavebits);
2351 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2353 freeBitVect (rsavebits);
2357 regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2358 emitcode ("mov", "r0,%s", spname);
2359 emitcode ("dec", "r0");
2360 emitcode ("movx", "a,@r0");
2361 if (reg->type == REG_BIT)
2363 emitcode ("mov", "%s,a", reg->base);
2367 emitcode ("mov", "%s,a", reg->name);
2369 emitcode ("dec", "%s", spname);
2371 else if (count != 0)
2373 emitcode ("mov", "r0,%s", spname);
2374 for (i = mcs51_nRegs; i >= 0; i--)
2376 if (bitVectBitValue (rsave, i))
2378 regs * reg = REG_WITH_INDEX (i);
2379 emitcode ("dec", "r0");
2380 emitcode ("movx", "a,@r0");
2383 emitcode ("push", "acc");
2385 else if (reg->type == REG_BIT)
2387 emitcode ("mov", "%s,a", reg->base);
2391 emitcode ("mov", "%s,a", reg->name);
2395 emitcode ("mov", "%s,r0", spname);
2396 if (bitVectBitValue (rsave, R0_IDX))
2398 emitcode ("pop", "ar0");
2404 bool bits_popped = FALSE;
2405 for (i = mcs51_nRegs; i >= 0; i--)
2407 if (bitVectBitValue (rsave, i))
2409 bits_popped = popReg (i, bits_popped);
2413 freeBitVect (rsave);
2417 /*-----------------------------------------------------------------*/
2419 /*-----------------------------------------------------------------*/
2421 pushSide (operand * oper, int size, iCode * ic)
2424 int nPushed = _G.r0Pushed + _G.r1Pushed;
2426 aopOp (oper, ic, FALSE);
2428 if (nPushed != _G.r0Pushed + _G.r1Pushed)
2430 while (offset < size)
2432 char *l = aopGet (oper, offset, FALSE, TRUE);
2433 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2435 freeAsmop (oper, NULL, ic, TRUE);
2437 while (offset < size)
2439 emitcode ("push", "%s", fReturn[offset++]);
2446 char *l = aopGet (oper, offset++, FALSE, TRUE);
2447 if (AOP_TYPE (oper) != AOP_REG &&
2448 AOP_TYPE (oper) != AOP_DIR &&
2452 emitcode ("push", "acc");
2456 emitcode ("push", "%s", l);
2460 freeAsmop (oper, NULL, ic, TRUE);
2463 /*-----------------------------------------------------------------*/
2464 /* assignResultValue - also indicates if acc is in use afterwards */
2465 /*-----------------------------------------------------------------*/
2467 assignResultValue (operand * oper, operand * func)
2470 int size = AOP_SIZE (oper);
2471 bool accuse = FALSE;
2472 bool pushedA = FALSE;
2474 if (func && IS_BIT (OP_SYM_ETYPE (func)))
2480 if ((size > 3) && aopPutUsesAcc (oper, fReturn[offset], offset))
2482 emitcode ("push", "acc");
2487 if ((offset == 3) && pushedA)
2488 emitcode ("pop", "acc");
2489 accuse |= aopPut (oper, fReturn[offset], offset);
2496 /*-----------------------------------------------------------------*/
2497 /* genXpush - pushes onto the external stack */
2498 /*-----------------------------------------------------------------*/
2500 genXpush (iCode * ic)
2502 asmop *aop = newAsmop (0);
2504 int size, offset = 0;
2506 D (emitcode (";", "genXpush"));
2508 aopOp (IC_LEFT (ic), ic, FALSE);
2509 r = getFreePtr (ic, &aop, FALSE);
2511 size = AOP_SIZE (IC_LEFT (ic));
2515 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2516 emitcode ("mov", "%s,%s", r->name, spname);
2517 emitcode ("inc", "%s", spname); // allocate space first
2518 emitcode ("movx", "@%s,a", r->name);
2522 // allocate space first
2523 emitcode ("mov", "%s,%s", r->name, spname);
2525 emitcode ("add", "a,#0x%02x", size);
2526 emitcode ("mov", "%s,a", spname);
2530 MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2531 emitcode ("movx", "@%s,a", r->name);
2532 emitcode ("inc", "%s", r->name);
2536 freeAsmop (NULL, aop, ic, TRUE);
2537 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2540 /*-----------------------------------------------------------------*/
2541 /* genIpush - generate code for pushing this gets a little complex */
2542 /*-----------------------------------------------------------------*/
2544 genIpush (iCode * ic)
2546 int size, offset = 0;
2550 D (emitcode (";", "genIpush"));
2552 /* if this is not a parm push : ie. it is spill push
2553 and spill push is always done on the local stack */
2557 /* and the item is spilt then do nothing */
2558 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2561 aopOp (IC_LEFT (ic), ic, FALSE);
2562 size = AOP_SIZE (IC_LEFT (ic));
2563 /* push it on the stack */
2566 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2572 emitcode ("push", "%s", l);
2577 /* this is a parameter push: in this case we call
2578 the routine to find the call and save those
2579 registers that need to be saved */
2582 /* if use external stack then call the external
2583 stack pushing routine */
2584 if (options.useXstack)
2590 /* then do the push */
2591 aopOp (IC_LEFT (ic), ic, FALSE);
2593 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2594 size = AOP_SIZE (IC_LEFT (ic));
2598 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2599 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2600 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR)
2602 if (strcmp (l, prev) || *l == '@')
2604 emitcode ("push", "acc");
2608 emitcode ("push", "%s", l);
2613 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2616 /*-----------------------------------------------------------------*/
2617 /* genIpop - recover the registers: can happen only for spilling */
2618 /*-----------------------------------------------------------------*/
2620 genIpop (iCode * ic)
2624 D (emitcode (";", "genIpop"));
2626 /* if the temp was not pushed then */
2627 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2630 aopOp (IC_LEFT (ic), ic, FALSE);
2631 size = AOP_SIZE (IC_LEFT (ic));
2632 offset = (size - 1);
2635 emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2639 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2642 /*-----------------------------------------------------------------*/
2643 /* popForBranch - recover the spilt registers for a branch */
2644 /*-----------------------------------------------------------------*/
2646 popForBranch (iCode * ic, bool markGenerated)
2648 while (ic && ic->op == IPOP)
2652 ic->generated = 1; /* mark the icode as generated */
2657 /*-----------------------------------------------------------------*/
2658 /* saveRBank - saves an entire register bank on the stack */
2659 /*-----------------------------------------------------------------*/
2661 saveRBank (int bank, iCode * ic, bool pushPsw)
2664 int count = 8 + (pushPsw ? 1 : 0);
2668 if (options.useXstack)
2672 /* Assume r0 is available for use. */
2673 r = REG_WITH_INDEX (R0_IDX);
2678 r = getFreePtr (ic, &aop, FALSE);
2680 // allocate space first
2681 emitcode ("mov", "%s,%s", r->name, spname);
2683 emitcode ("add", "a,#0x%02x", count);
2684 emitcode ("mov", "%s,a", spname);
2687 for (i = 0; i < 8; i++)
2689 if (options.useXstack)
2691 emitcode ("mov", "a,(%s+%d)",
2692 regs8051[i].base, 8 * bank + regs8051[i].offset);
2693 emitcode ("movx", "@%s,a", r->name);
2695 emitcode ("inc", "%s", r->name);
2698 emitcode ("push", "(%s+%d)",
2699 regs8051[i].base, 8 * bank + regs8051[i].offset);
2704 if (options.useXstack)
2706 emitcode ("mov", "a,psw");
2707 emitcode ("movx", "@%s,a", r->name);
2711 emitcode ("push", "psw");
2714 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2719 freeAsmop (NULL, aop, ic, TRUE);
2728 /*-----------------------------------------------------------------*/
2729 /* unsaveRBank - restores the register bank from stack */
2730 /*-----------------------------------------------------------------*/
2732 unsaveRBank (int bank, iCode * ic, bool popPsw)
2738 if (options.useXstack)
2742 /* Assume r0 is available for use. */
2743 r = REG_WITH_INDEX (R0_IDX);;
2748 r = getFreePtr (ic, &aop, FALSE);
2750 emitcode ("mov", "%s,%s", r->name, spname);
2755 if (options.useXstack)
2757 emitcode ("dec", "%s", r->name);
2758 emitcode ("movx", "a,@%s", r->name);
2759 emitcode ("mov", "psw,a");
2763 emitcode ("pop", "psw");
2767 for (i = 7; i >= 0; i--)
2769 if (options.useXstack)
2771 emitcode ("dec", "%s", r->name);
2772 emitcode ("movx", "a,@%s", r->name);
2773 emitcode ("mov", "(%s+%d),a",
2774 regs8051[i].base, 8 * bank + regs8051[i].offset);
2778 emitcode ("pop", "(%s+%d)",
2779 regs8051[i].base, 8 * bank + regs8051[i].offset);
2783 if (options.useXstack)
2785 emitcode ("mov", "%s,%s", spname, r->name);
2790 freeAsmop (NULL, aop, ic, TRUE);
2794 /*-----------------------------------------------------------------*/
2795 /* genSend - gen code for SEND */
2796 /*-----------------------------------------------------------------*/
2797 static void genSend(set *sendSet)
2802 /* first we do all bit parameters */
2803 for (sic = setFirstItem (sendSet); sic;
2804 sic = setNextItem (sendSet))
2806 if (sic->argreg > 12)
2808 int bit = sic->argreg-13;
2810 aopOp (IC_LEFT (sic), sic, FALSE);
2812 /* if left is a literal then
2813 we know what the value is */
2814 if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2816 if (((int) operandLitValue (IC_LEFT (sic))))
2817 emitcode ("setb", "b[%d]", bit);
2819 emitcode ("clr", "b[%d]", bit);
2824 toCarry (IC_LEFT (sic));
2825 emitcode ("mov", "b[%d],c", bit);
2830 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2834 if (options.useXstack || bit_count)
2836 saveRegisters (setFirstItem (sendSet));
2841 emitcode ("mov", "bits,b");
2844 /* then we do all other parameters */
2845 for (sic = setFirstItem (sendSet); sic;
2846 sic = setNextItem (sendSet))
2848 if (sic->argreg <= 12)
2850 int size, offset = 0;
2851 aopOp (IC_LEFT (sic), sic, FALSE);
2852 size = AOP_SIZE (IC_LEFT (sic));
2854 if (sic->argreg == 1)
2858 char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2859 if (strcmp (l, fReturn[offset]))
2861 emitcode ("mov", "%s,%s", fReturn[offset], l);
2870 emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2871 aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2875 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2880 /*-----------------------------------------------------------------*/
2881 /* selectRegBank - emit code to select the register bank */
2882 /*-----------------------------------------------------------------*/
2884 selectRegBank (short bank, bool keepFlags)
2886 /* if f.e. result is in carry */
2889 emitcode ("anl", "psw,#0xE7");
2891 emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2895 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2899 /*-----------------------------------------------------------------*/
2900 /* genCall - generates a call statement */
2901 /*-----------------------------------------------------------------*/
2903 genCall (iCode * ic)
2907 // bool restoreBank = FALSE;
2908 bool swapBanks = FALSE;
2909 bool accuse = FALSE;
2910 bool accPushed = FALSE;
2911 bool resultInF0 = FALSE;
2912 bool assignResultGenerated = FALSE;
2914 D (emitcode (";", "genCall"));
2916 dtype = operandType (IC_LEFT (ic));
2917 etype = getSpec(dtype);
2918 /* if send set is not empty then assign */
2921 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2922 genSend(reverseSet(_G.sendSet));
2924 genSend(_G.sendSet);
2929 /* if we are calling a not _naked function that is not using
2930 the same register bank then we need to save the
2931 destination registers on the stack */
2932 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2933 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2934 !IFFUNC_ISISR (dtype))
2939 /* if caller saves & we have not saved then */
2945 emitcode ("mov", "psw,#0x%02x", ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2949 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2951 if (IFFUNC_CALLEESAVES(dtype))
2953 werror (E_BANKED_WITH_CALLEESAVES);
2957 char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2958 OP_SYMBOL (IC_LEFT (ic))->rname :
2959 OP_SYMBOL (IC_LEFT (ic))->name);
2961 emitcode ("mov", "r0,#%s", l);
2962 emitcode ("mov", "r1,#(%s >> 8)", l);
2963 emitcode ("mov", "r2,#(%s >> 16)", l);
2964 emitcode ("lcall", "__sdcc_banked_call");
2969 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2970 OP_SYMBOL (IC_LEFT (ic))->rname :
2971 OP_SYMBOL (IC_LEFT (ic))->name));
2976 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2979 /* if we need assign a result value */
2980 if ((IS_ITEMP (IC_RESULT (ic)) &&
2981 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2982 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2983 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2984 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2985 IS_TRUE_SYMOP (IC_RESULT (ic)))
2989 aopOp (IC_RESULT (ic), ic, FALSE);
2992 accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2993 assignResultGenerated = TRUE;
2995 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2998 /* adjust the stack for parameters if required */
3002 if (ic->parmBytes > 3)
3006 emitcode ("push", "acc");
3009 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3010 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3011 !assignResultGenerated)
3013 emitcode ("mov", "F0,c");
3017 emitcode ("mov", "a,%s", spname);
3018 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3019 emitcode ("mov", "%s,a", spname);
3021 /* unsaveRegisters from xstack needs acc, but */
3022 /* unsaveRegisters from stack needs this popped */
3023 if (accPushed && !options.useXstack)
3025 emitcode ("pop", "acc");
3030 for (i = 0; i < ic->parmBytes; i++)
3031 emitcode ("dec", "%s", spname);
3034 /* if we had saved some registers then unsave them */
3035 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3037 if (accuse && !accPushed && options.useXstack)
3039 /* xstack needs acc, but doesn't touch normal stack */
3040 emitcode ("push", "acc");
3043 unsaveRegisters (ic);
3046 // /* if register bank was saved then pop them */
3048 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
3050 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
3053 emitcode ("mov", "c,F0");
3055 aopOp (IC_RESULT (ic), ic, FALSE);
3056 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3057 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3061 emitcode ("pop", "acc");
3064 /*-----------------------------------------------------------------*/
3065 /* genPcall - generates a call by pointer statement */
3066 /*-----------------------------------------------------------------*/
3068 genPcall (iCode * ic)
3072 symbol *rlbl = newiTempLabel (NULL);
3073 // bool restoreBank=FALSE;
3074 bool swapBanks = FALSE;
3075 bool resultInF0 = FALSE;
3077 D (emitcode (";", "genPcall"));
3079 dtype = operandType (IC_LEFT (ic))->next;
3080 etype = getSpec(dtype);
3081 /* if caller saves & we have not saved then */
3085 /* if we are calling a not _naked function that is not using
3086 the same register bank then we need to save the
3087 destination registers on the stack */
3088 if (currFunc && dtype && !IFFUNC_ISNAKED (dtype) &&
3089 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
3090 !IFFUNC_ISISR (dtype))
3092 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3093 // restoreBank=TRUE;
3095 // need caution message to user here
3098 if (IS_LITERAL (etype))
3100 /* if send set is not empty then assign */
3103 genSend(reverseSet(_G.sendSet));
3109 emitcode ("mov", "psw,#0x%02x",
3110 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3113 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT (getSpec(dtype)))
3115 if (IFFUNC_CALLEESAVES (dtype))
3117 werror (E_BANKED_WITH_CALLEESAVES);
3121 char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
3123 emitcode ("mov", "r0,#%s", l);
3124 emitcode ("mov", "r1,#(%s >> 8)", l);
3125 emitcode ("mov", "r2,#(%s >> 16)", l);
3126 emitcode ("lcall", "__sdcc_banked_call");
3131 emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
3136 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT (getSpec(dtype)))
3138 if (IFFUNC_CALLEESAVES (dtype))
3140 werror (E_BANKED_WITH_CALLEESAVES);
3144 aopOp (IC_LEFT (ic), ic, FALSE);
3148 /* what if aopGet needs r0 or r1 ??? */
3149 emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3150 emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3151 emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3155 int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
3156 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3157 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3158 emitcode ("mov", "0x%02x,%s", reg, aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3161 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3163 /* if send set is not empty then assign */
3166 genSend(reverseSet(_G.sendSet));
3172 emitcode ("mov", "psw,#0x%02x",
3173 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3177 emitcode ("lcall", "__sdcc_banked_call");
3180 else if (_G.sendSet)
3182 /* push the return address on to the stack */
3183 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
3184 emitcode ("push", "acc");
3185 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
3186 emitcode ("push", "acc");
3188 /* now push the function address */
3189 pushSide (IC_LEFT (ic), FPTRSIZE, ic);
3191 /* if send set is not empty then assign */
3194 genSend(reverseSet(_G.sendSet));
3200 emitcode ("mov", "psw,#0x%02x",
3201 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3205 emitcode ("ret", "");
3208 else /* the send set is empty */
3211 /* now get the calling address into dptr */
3212 aopOp (IC_LEFT (ic), ic, FALSE);
3214 l = aopGet (IC_LEFT (ic), 0, FALSE, FALSE);
3215 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3217 emitcode ("mov", "r0,%s", l);
3218 l = aopGet (IC_LEFT (ic), 1, FALSE, FALSE);
3219 emitcode ("mov", "dph,%s", l);
3220 emitcode ("mov", "dpl,r0");
3224 emitcode ("mov", "dpl,%s", l);
3225 l = aopGet (IC_LEFT (ic), 1, FALSE, FALSE);
3226 emitcode ("mov", "dph,%s", l);
3229 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3233 emitcode ("mov", "psw,#0x%02x",
3234 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3238 emitcode ("lcall", "__sdcc_call_dptr");
3243 selectRegBank (FUNC_REGBANK (currFunc->type), IS_BIT (etype));
3246 /* if we need assign a result value */
3247 if ((IS_ITEMP (IC_RESULT (ic)) &&
3248 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3249 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3250 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3251 IS_TRUE_SYMOP (IC_RESULT (ic)))
3255 aopOp (IC_RESULT (ic), ic, FALSE);
3258 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3260 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3263 /* adjust the stack for parameters if required */
3267 if (ic->parmBytes > 3)
3269 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3270 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3272 emitcode ("mov", "F0,c");
3276 emitcode ("mov", "a,%s", spname);
3277 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3278 emitcode ("mov", "%s,a", spname);
3281 for (i = 0; i < ic->parmBytes; i++)
3282 emitcode ("dec", "%s", spname);
3285 // /* if register bank was saved then unsave them */
3287 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3289 /* if we had saved some registers then unsave them */
3290 if (ic->regsSaved && !IFFUNC_CALLEESAVES (dtype))
3291 unsaveRegisters (ic);
3293 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3296 emitcode ("mov", "c,F0");
3298 aopOp (IC_RESULT (ic), ic, FALSE);
3299 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3300 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3304 /*-----------------------------------------------------------------*/
3305 /* resultRemat - result is rematerializable */
3306 /*-----------------------------------------------------------------*/
3308 resultRemat (iCode * ic)
3310 if (SKIP_IC (ic) || ic->op == IFX)
3313 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3315 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3316 if (sym->remat && !POINTER_SET (ic))
3323 /*-----------------------------------------------------------------*/
3324 /* inExcludeList - return 1 if the string is in exclude Reg list */
3325 /*-----------------------------------------------------------------*/
3327 regsCmp(void *p1, void *p2)
3329 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3333 inExcludeList (char *s)
3335 const char *p = setFirstItem(options.excludeRegsSet);
3337 if (p == NULL || STRCASECMP(p, "none") == 0)
3341 return isinSetWith(options.excludeRegsSet, s, regsCmp);
3344 /*-----------------------------------------------------------------*/
3345 /* genFunction - generated code for function entry */
3346 /*-----------------------------------------------------------------*/
3348 genFunction (iCode * ic)
3350 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3352 bool switchedPSW = FALSE;
3353 int calleesaves_saved_register = -1;
3354 int stackAdjust = sym->stack;
3355 int accIsFree = sym->recvSize < 4;
3356 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3357 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3360 /* create the function header */
3361 emitcode (";", "-----------------------------------------");
3362 emitcode (";", " function %s", sym->name);
3363 emitcode (";", "-----------------------------------------");
3365 emitcode ("", "%s:", sym->rname);
3366 lineCurr->isLabel = 1;
3367 ftype = operandType (IC_LEFT (ic));
3368 _G.currentFunc = sym;
3370 if (IFFUNC_ISNAKED(ftype))
3372 emitcode(";", "naked function: no prologue.");
3376 /* here we need to generate the equates for the
3377 register bank if required */
3378 if (FUNC_REGBANK (ftype) != rbank)
3382 rbank = FUNC_REGBANK (ftype);
3383 for (i = 0; i < mcs51_nRegs; i++)
3385 if (regs8051[i].type != REG_BIT)
3387 if (strcmp (regs8051[i].base, "0") == 0)
3388 emitcode ("", "%s = 0x%02x",
3390 8 * rbank + regs8051[i].offset);
3392 emitcode ("", "%s = %s + 0x%02x",
3395 8 * rbank + regs8051[i].offset);
3400 /* if this is an interrupt service routine then
3401 save acc, b, dpl, dph */
3402 if (IFFUNC_ISISR (sym->type))
3406 rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), sym->regsUsed);
3407 if (IFFUNC_HASFCALL(sym->type) || !bitVectIsZero (rsavebits))
3409 emitcode ("push", "bits");
3412 freeBitVect (rsavebits);
3414 if (!inExcludeList ("acc"))
3415 emitcode ("push", "acc");
3416 if (!inExcludeList ("b"))
3417 emitcode ("push", "b");
3418 if (!inExcludeList ("dpl"))
3419 emitcode ("push", "dpl");
3420 if (!inExcludeList ("dph"))
3421 emitcode ("push", "dph");
3422 /* if this isr has no bank i.e. is going to
3423 run with bank 0 , then we need to save more
3425 if (!FUNC_REGBANK (sym->type))
3429 /* if this function does not call any other
3430 function then we can be economical and
3431 save only those registers that are used */
3432 if (!IFFUNC_HASFCALL(sym->type))
3434 /* if any registers used */
3437 /* save the registers used */
3438 for (i = 0; i < sym->regsUsed->size; i++)
3440 if (bitVectBitValue (sym->regsUsed, i))
3447 /* this function has a function call. We cannot
3448 determine register usage so we will have to push the
3450 saveRBank (0, ic, FALSE);
3451 if (options.parms_in_bank1)
3453 for (i=0; i < 8 ; i++ )
3455 emitcode ("push","%s",rb1regs[i]);
3462 /* This ISR uses a non-zero bank.
3464 * We assume that the bank is available for our
3467 * However, if this ISR calls a function which uses some
3468 * other bank, we must save that bank entirely.
3470 unsigned long banksToSave = 0;
3472 if (IFFUNC_HASFCALL(sym->type))
3475 #define MAX_REGISTER_BANKS 4
3480 for (i = ic; i; i = i->next)
3482 if (i->op == ENDFUNCTION)
3484 /* we got to the end OK. */
3492 dtype = operandType (IC_LEFT(i));
3494 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3496 /* Mark this bank for saving. */
3497 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3499 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3503 banksToSave |= (1 << FUNC_REGBANK(dtype));
3506 /* And note that we don't need to do it in
3514 /* This is a mess; we have no idea what
3515 * register bank the called function might
3518 * The only thing I can think of to do is
3519 * throw a warning and hope.
3521 werror(W_FUNCPTR_IN_USING_ISR);
3525 if (banksToSave && options.useXstack)
3527 /* Since we aren't passing it an ic,
3528 * saveRBank will assume r0 is available to abuse.
3530 * So switch to our (trashable) bank now, so
3531 * the caller's R0 isn't trashed.
3533 emitcode ("push", "psw");
3534 emitcode ("mov", "psw,#0x%02x",
3535 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3539 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3541 if (banksToSave & (1 << ix))
3543 saveRBank(ix, NULL, FALSE);
3547 // TODO: this needs a closer look
3548 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3551 /* Set the register bank to the desired value if nothing else */
3552 /* has done so yet. */
3555 emitcode ("push", "psw");
3556 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3561 /* This is a non-ISR function. The caller has already switched register */
3562 /* banks, if necessary, so just handle the callee-saves option. */
3564 /* if callee-save to be used for this function
3565 then save the registers being used in this function */
3566 if (IFFUNC_CALLEESAVES(sym->type))
3570 /* if any registers used */
3573 bool bits_pushed = FALSE;
3574 /* save the registers used */
3575 for (i = 0; i < sym->regsUsed->size; i++)
3577 if (bitVectBitValue (sym->regsUsed, i))
3579 /* remember one saved register for later usage */
3580 if (calleesaves_saved_register < 0)
3581 calleesaves_saved_register = i;
3582 bits_pushed = pushReg (i, bits_pushed);
3592 if (options.useXstack)
3594 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3596 emitcode ("mov", "r0,%s", spname);
3597 emitcode ("inc", "%s", spname);
3598 emitcode ("xch", "a,_bpx");
3599 emitcode ("movx", "@r0,a");
3600 emitcode ("inc", "r0");
3601 emitcode ("mov", "a,r0");
3602 emitcode ("xch", "a,_bpx");
3606 emitcode ("push", "_bp"); /* save the callers stack */
3607 emitcode ("mov", "_bp,sp");
3612 if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3614 /* set up the stack */
3615 emitcode ("push", "_bp"); /* save the callers stack */
3616 emitcode ("mov", "_bp,sp");
3621 /* For some cases it is worthwhile to perform a RECEIVE iCode */
3622 /* before setting up the stack frame completely. */
3623 if (ric && ric->argreg == 1 && IC_RESULT (ric))
3625 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3629 if (rsym && rsym->regType == REG_CND)
3631 if (rsym && (rsym->accuse || rsym->ruonly))
3633 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3634 rsym = rsym->usl.spillLoc;
3637 /* If the RECEIVE operand immediately spills to the first entry on the */
3638 /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3639 /* rather than the usual @r0/r1 machinations. */
3640 if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3644 _G.current_iCode = ric;
3645 D(emitcode (";", "genReceive"));
3646 for (ofs=0; ofs < sym->recvSize; ofs++)
3648 if (!strcmp (fReturn[ofs], "a"))
3649 emitcode ("push", "acc");
3651 emitcode ("push", fReturn[ofs]);
3653 stackAdjust -= sym->recvSize;
3656 assert (stackAdjust>=0);
3659 _G.current_iCode = ic;
3663 /* If the RECEIVE operand is 4 registers, we can do the moves now */
3664 /* to free up the accumulator. */
3665 else if (rsym && rsym->nRegs && sym->recvSize == 4)
3669 _G.current_iCode = ric;
3670 D(emitcode (";", "genReceive"));
3671 for (ofs=0; ofs < sym->recvSize; ofs++)
3673 emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3675 _G.current_iCode = ic;
3681 /* adjust the stack for the function */
3684 int i = stackAdjust;
3686 werror (W_STACK_OVERFLOW, sym->name);
3688 if (i > 3 && accIsFree)
3690 emitcode ("mov", "a,sp");
3691 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3692 emitcode ("mov", "sp,a");
3696 /* The accumulator is not free, so we will need another register */
3697 /* to clobber. No need to worry about a possible conflict with */
3698 /* the above early RECEIVE optimizations since they would have */
3699 /* freed the accumulator if they were generated. */
3701 if (IFFUNC_CALLEESAVES(sym->type))
3703 /* if it's a callee-saves function we need a saved register */
3704 if (calleesaves_saved_register >= 0)
3706 emitcode ("mov", "%s,a", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3707 emitcode ("mov", "a,sp");
3708 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3709 emitcode ("mov", "sp,a");
3710 emitcode ("mov", "a,%s", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3713 /* do it the hard way */
3715 emitcode ("inc", "sp");
3719 /* not callee-saves, we can clobber r0 */
3720 emitcode ("mov", "r0,a");
3721 emitcode ("mov", "a,sp");
3722 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3723 emitcode ("mov", "sp,a");
3724 emitcode ("mov", "a,r0");
3729 emitcode ("inc", "sp");
3734 char i = ((char) sym->xstack & 0xff);
3736 if (i > 3 && accIsFree)
3738 emitcode ("mov", "a,_spx");
3739 emitcode ("add", "a,#0x%02x", i & 0xff);
3740 emitcode ("mov", "_spx,a");
3744 emitcode ("push", "acc");
3745 emitcode ("mov", "a,_spx");
3746 emitcode ("add", "a,#0x%02x", i & 0xff);
3747 emitcode ("mov", "_spx,a");
3748 emitcode ("pop", "acc");
3753 emitcode ("inc", "_spx");
3757 /* if critical function then turn interrupts off */
3758 if (IFFUNC_ISCRITICAL (ftype))
3760 symbol *tlbl = newiTempLabel (NULL);
3761 emitcode ("setb", "c");
3762 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3763 emitcode ("clr", "c");
3765 emitcode ("push", "psw"); /* save old ea via c in psw */
3769 /*-----------------------------------------------------------------*/
3770 /* genEndFunction - generates epilogue for functions */
3771 /*-----------------------------------------------------------------*/
3773 genEndFunction (iCode * ic)
3775 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3776 lineNode *lnp = lineCurr;
3778 bitVect *regsUsedPrologue;
3779 bitVect *regsUnneeded;
3782 _G.currentFunc = NULL;
3783 if (IFFUNC_ISNAKED(sym->type))
3785 emitcode(";", "naked function: no epilogue.");
3786 if (options.debug && currFunc)
3787 debugFile->writeEndFunction (currFunc, ic, 0);
3791 if (IFFUNC_ISCRITICAL (sym->type))
3793 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3795 emitcode ("rlc", "a"); /* save c in a */
3796 emitcode ("pop", "psw"); /* restore ea via c in psw */
3797 emitcode ("mov", "ea,c");
3798 emitcode ("rrc", "a"); /* restore c from a */
3802 emitcode ("pop", "psw"); /* restore ea via c in psw */
3803 emitcode ("mov", "ea,c");
3807 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3809 if (options.useXstack)
3813 emitcode ("mov", "sp,_bp");
3814 emitcode ("pop", "_bp");
3816 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3818 emitcode ("xch", "a,_bpx");
3819 emitcode ("mov", "r0,a");
3820 emitcode ("dec", "r0");
3821 emitcode ("movx", "a,@r0");
3822 emitcode ("xch", "a,_bpx");
3823 emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3826 else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3829 emitcode ("mov", "sp,_bp");
3830 emitcode ("pop", "_bp");
3834 /* restore the register bank */
3835 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3837 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3838 || !options.useXstack)
3840 /* Special case of ISR using non-zero bank with useXstack
3843 emitcode ("pop", "psw");
3847 if (IFFUNC_ISISR (sym->type))
3851 /* now we need to restore the registers */
3852 /* if this isr has no bank i.e. is going to
3853 run with bank 0 , then we need to save more
3855 if (!FUNC_REGBANK (sym->type))
3858 /* if this function does not call any other
3859 function then we can be economical and
3860 save only those registers that are used */
3861 if (!IFFUNC_HASFCALL(sym->type))
3863 /* if any registers used */
3866 /* save the registers used */
3867 for (i = sym->regsUsed->size; i >= 0; i--)
3869 if (bitVectBitValue (sym->regsUsed, i))
3876 if (options.parms_in_bank1)
3878 for (i = 7 ; i >= 0 ; i-- )
3880 emitcode ("pop","%s",rb1regs[i]);
3883 /* this function has a function call. We cannot
3884 determine register usage so we will have to pop the
3886 unsaveRBank (0, ic, FALSE);
3891 /* This ISR uses a non-zero bank.
3893 * Restore any register banks saved by genFunction
3896 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3899 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3901 if (savedBanks & (1 << ix))
3903 unsaveRBank(ix, NULL, FALSE);
3907 if (options.useXstack)
3909 /* Restore bank AFTER calling unsaveRBank,
3910 * since it can trash r0.
3912 emitcode ("pop", "psw");
3916 if (!inExcludeList ("dph"))
3917 emitcode ("pop", "dph");
3918 if (!inExcludeList ("dpl"))
3919 emitcode ("pop", "dpl");
3920 if (!inExcludeList ("b"))
3921 emitcode ("pop", "b");
3922 if (!inExcludeList ("acc"))
3923 emitcode ("pop", "acc");
3925 rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), sym->regsUsed);
3926 if (IFFUNC_HASFCALL(sym->type) || !bitVectIsZero (rsavebits))
3927 emitcode ("pop", "bits");
3928 freeBitVect (rsavebits);
3930 /* if debug then send end of function */
3931 if (options.debug && currFunc)
3933 debugFile->writeEndFunction (currFunc, ic, 1);
3936 emitcode ("reti", "");
3940 if (IFFUNC_CALLEESAVES(sym->type))
3944 /* if any registers used */
3947 /* save the registers used */
3948 for (i = sym->regsUsed->size; i >= 0; i--)
3950 if (bitVectBitValue (sym->regsUsed, i) ||
3951 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3952 emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
3955 else if (mcs51_ptrRegReq)
3957 emitcode ("pop", "%s", REG_WITH_INDEX (R1_IDX)->dname);
3958 emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
3963 /* if debug then send end of function */
3964 if (options.debug && currFunc)
3966 debugFile->writeEndFunction (currFunc, ic, 1);
3969 if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3971 emitcode ("ljmp", "__sdcc_banked_ret");
3975 emitcode ("ret", "");
3979 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3982 /* If this was an interrupt handler using bank 0 that called another */
3983 /* function, then all registers must be saved; nothing to optimized. */
3984 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3985 && !FUNC_REGBANK(sym->type))
3988 /* There are no push/pops to optimize if not callee-saves or ISR */
3989 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3992 /* If there were stack parameters, we cannot optimize without also */
3993 /* fixing all of the stack offsets; this is too dificult to consider. */
3994 if (FUNC_HASSTACKPARM(sym->type))
3997 /* Compute the registers actually used */
3998 regsUsed = newBitVect (mcs51_nRegs);
3999 regsUsedPrologue = newBitVect (mcs51_nRegs);
4002 if (lnp->ic && lnp->ic->op == FUNCTION)
4003 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
4005 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
4007 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
4008 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
4015 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
4016 && !bitVectBitValue (regsUsed, CND_IDX))
4018 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
4019 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
4020 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
4021 bitVectUnSetBit (regsUsed, CND_IDX);
4024 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
4026 /* If this was an interrupt handler that called another function */
4027 /* function, then assume A, B, DPH, & DPL may be modified by it. */
4028 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
4030 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
4031 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
4032 regsUsed = bitVectSetBit (regsUsed, B_IDX);
4033 regsUsed = bitVectSetBit (regsUsed, A_IDX);
4034 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
4037 /* Remove the unneeded push/pops */
4038 regsUnneeded = newBitVect (mcs51_nRegs);
4041 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
4043 if (!strncmp(lnp->line, "push", 4))
4045 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
4046 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4048 connectLine (lnp->prev, lnp->next);
4049 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4052 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
4054 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
4055 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4057 connectLine (lnp->prev, lnp->next);
4058 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4065 for (idx = 0; idx < regsUnneeded->size; idx++)
4066 if (bitVectBitValue (regsUnneeded, idx))
4067 emitcode (";", "eliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
4069 freeBitVect (regsUnneeded);
4070 freeBitVect (regsUsed);
4071 freeBitVect (regsUsedPrologue);
4074 /*-----------------------------------------------------------------*/
4075 /* genRet - generate code for return statement */
4076 /*-----------------------------------------------------------------*/
4080 int size, offset = 0, pushed = 0;
4082 D (emitcode (";", "genRet"));
4084 /* if we have no return value then
4085 just generate the "ret" */
4089 /* we have something to return then
4090 move the return value into place */
4091 aopOp (IC_LEFT (ic), ic, FALSE);
4092 size = AOP_SIZE (IC_LEFT (ic));
4094 if (IS_BIT(_G.currentFunc->etype))
4096 if (!IS_OP_RUONLY (IC_LEFT (ic)))
4097 toCarry (IC_LEFT (ic));
4104 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
4107 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
4108 emitcode ("push", "%s", l);
4113 l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
4114 if (strcmp (fReturn[offset], l))
4115 emitcode ("mov", "%s,%s", fReturn[offset++], l);
4122 if (strcmp (fReturn[pushed], "a"))
4123 emitcode ("pop", fReturn[pushed]);
4125 emitcode ("pop", "acc");
4128 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
4131 /* generate a jump to the return label
4132 if the next is not the return statement */
4133 if (!(ic->next && ic->next->op == LABEL &&
4134 IC_LABEL (ic->next) == returnLabel))
4136 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
4140 /*-----------------------------------------------------------------*/
4141 /* genLabel - generates a label */
4142 /*-----------------------------------------------------------------*/
4144 genLabel (iCode * ic)
4146 /* special case never generate */
4147 if (IC_LABEL (ic) == entryLabel)
4150 emitLabel (IC_LABEL (ic));
4153 /*-----------------------------------------------------------------*/
4154 /* genGoto - generates a ljmp */
4155 /*-----------------------------------------------------------------*/
4157 genGoto (iCode * ic)
4159 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
4162 /*-----------------------------------------------------------------*/
4163 /* findLabelBackwards: walks back through the iCode chain looking */
4164 /* for the given label. Returns number of iCode instructions */
4165 /* between that label and given ic. */
4166 /* Returns zero if label not found. */
4167 /*-----------------------------------------------------------------*/
4169 findLabelBackwards (iCode * ic, int key)
4178 /* If we have any pushes or pops, we cannot predict the distance.
4179 I don't like this at all, this should be dealt with in the
4181 if (ic->op == IPUSH || ic->op == IPOP) {
4185 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4194 /*-----------------------------------------------------------------*/
4195 /* genPlusIncr :- does addition with increment if possible */
4196 /*-----------------------------------------------------------------*/
4198 genPlusIncr (iCode * ic)
4200 unsigned int icount;
4201 unsigned int size = getDataSize (IC_RESULT (ic));
4203 /* will try to generate an increment */
4204 /* if the right side is not a literal
4206 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4209 icount = (unsigned int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4211 D(emitcode (";","genPlusIncr"));
4213 /* if increment >=16 bits in register or direct space */
4214 if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG ||
4215 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4216 (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4217 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4218 !isOperandVolatile (IC_RESULT (ic), FALSE) &&
4227 /* If the next instruction is a goto and the goto target
4228 * is < 10 instructions previous to this, we can generate
4229 * jumps straight to that target.
4231 if (ic->next && ic->next->op == GOTO
4232 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4233 && labelRange <= 10)
4235 D (emitcode (";", "tail increment optimized (range %d)", labelRange));
4236 tlbl = IC_LABEL (ic->next);
4241 tlbl = newiTempLabel (NULL);
4244 l = aopGet (IC_RESULT (ic), LSB, FALSE, FALSE);
4245 emitcode ("inc", "%s", l);
4246 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4247 IS_AOP_PREG (IC_RESULT (ic)))
4249 emitcode ("cjne", "%s,#0x00,%05d$", l, tlbl->key + 100);
4253 emitcode ("clr", "a");
4254 emitcode ("cjne", "a,%s,%05d$", l, tlbl->key + 100);
4257 l = aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE);
4258 emitcode ("inc", "%s", l);
4261 if (!strcmp(l, "acc"))
4263 emitcode("jnz", "!tlabel", tlbl->key + 100);
4265 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4266 IS_AOP_PREG (IC_RESULT (ic)))
4268 emitcode ("cjne", "%s,#0x00,%05d$", l, tlbl->key + 100);
4272 emitcode ("cjne", "a,%s,%05d$", l, tlbl->key + 100);
4275 l = aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE);
4276 emitcode ("inc", "%s", l);
4280 if (!strcmp(l, "acc"))
4282 emitcode("jnz", "!tlabel", tlbl->key + 100);
4284 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4285 IS_AOP_PREG (IC_RESULT (ic)))
4287 emitcode ("cjne", "%s,#0x00,%05d$", l, tlbl->key + 100);
4291 emitcode ("cjne", "a,%s,%05d$", l, tlbl->key + 100);
4294 l = aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE);
4295 emitcode ("inc", "%s", l);
4305 /* if result is dptr */
4306 if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
4307 (AOP_SIZE (IC_RESULT (ic)) == 2) &&
4308 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
4309 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
4311 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4317 if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
4320 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0);
4321 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1);
4323 emitcode ("inc", "dptr");
4328 /* if the literal value of the right hand side
4329 is greater than 4 then it is not worth it */
4333 /* if the sizes are greater than 1 then we cannot */
4334 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4335 AOP_SIZE (IC_LEFT (ic)) > 1)
4338 /* we can if the aops of the left & result match or
4339 if they are in registers and the registers are the
4341 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4345 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4346 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4347 aopPut (IC_RESULT (ic), "a", 0);
4353 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4362 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4363 emitcode ("inc", "a");
4364 aopPut (IC_RESULT (ic), "a", 0);
4371 /*-----------------------------------------------------------------*/
4372 /* outBitAcc - output a bit in acc */
4373 /*-----------------------------------------------------------------*/
4375 outBitAcc (operand * result)
4377 symbol *tlbl = newiTempLabel (NULL);
4378 /* if the result is a bit */
4379 if (AOP_TYPE (result) == AOP_CRY)
4381 aopPut (result, "a", 0);
4385 emitcode ("jz", "%05d$", tlbl->key + 100);
4386 emitcode ("mov", "a,%s", one);
4392 /*-----------------------------------------------------------------*/
4393 /* genPlusBits - generates code for addition of two bits */
4394 /*-----------------------------------------------------------------*/
4396 genPlusBits (iCode * ic)
4398 D (emitcode (";", "genPlusBits"));
4400 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4401 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4403 symbol *lbl = newiTempLabel (NULL);
4404 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4405 emitcode ("cpl", "c");
4407 outBitC (IC_RESULT (ic));
4411 emitcode ("clr", "a");
4412 emitcode ("rlc", "a");
4413 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4414 emitcode ("addc", "a,%s", zero);
4415 outAcc (IC_RESULT (ic));
4420 /* This is the original version of this code.
4422 * This is being kept around for reference,
4423 * because I am not entirely sure I got it right...
4426 adjustArithmeticResult (iCode * ic)
4428 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4429 AOP_SIZE (IC_LEFT (ic)) == 3 &&
4430 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4431 aopPut (IC_RESULT (ic),
4432 aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4435 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4436 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4437 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4438 aopPut (IC_RESULT (ic),
4439 aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4442 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4443 AOP_SIZE (IC_LEFT (ic)) < 3 &&
4444 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4445 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4446 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4449 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4450 aopPut (IC_RESULT (ic), buffer, 2);
4454 /* This is the pure and virtuous version of this code.
4455 * I'm pretty certain it's right, but not enough to toss the old
4459 adjustArithmeticResult (iCode * ic)
4461 if (opIsGptr (IC_RESULT (ic)))
4465 if (opIsGptr (IC_LEFT (ic)))
4467 if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4469 aopPut (IC_RESULT (ic),
4470 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4476 if (opIsGptr (IC_RIGHT (ic)))
4478 if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4480 aopPut (IC_RESULT (ic),
4481 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4487 if (IC_LEFT (ic) && AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4488 IC_RIGHT (ic) && AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4489 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4490 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4492 SNPRINTF (buffer, sizeof(buffer),
4493 "#0x%02x", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4494 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4497 if (IC_LEFT (ic) && AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4498 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4500 SNPRINTF (buffer, sizeof(buffer),
4501 "#0x%02x", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4502 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4505 if (IC_RIGHT (ic) && AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4506 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4508 SNPRINTF (buffer, sizeof(buffer),
4509 "#0x%02x", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_RIGHT (ic)))), NULL, NULL));
4510 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4517 /*-----------------------------------------------------------------*/
4518 /* genPlus - generates code for addition */
4519 /*-----------------------------------------------------------------*/
4521 genPlus (iCode * ic)
4523 int size, offset = 0;
4526 bool swappedLR = FALSE;
4527 operand *leftOp, *rightOp;
4530 D (emitcode (";", "genPlus"));
4532 /* special cases :- */
4534 aopOp (IC_LEFT (ic), ic, FALSE);
4535 aopOp (IC_RIGHT (ic), ic, FALSE);
4536 aopOp (IC_RESULT (ic), ic, TRUE);
4538 /* if literal, literal on the right or
4539 if left requires ACC or right is already
4541 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4542 (AOP_NEEDSACC (IC_LEFT (ic))) ||
4543 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4545 operand *t = IC_RIGHT (ic);
4546 IC_RIGHT (ic) = IC_LEFT (ic);
4551 /* if both left & right are in bit
4553 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4554 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4560 /* if left in bit space & right literal */
4561 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4562 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4564 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4565 /* if result in bit space */
4566 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4568 if (ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4569 emitcode ("cpl", "c");
4570 outBitC (IC_RESULT (ic));
4574 size = getDataSize (IC_RESULT (ic));
4577 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4578 emitcode ("addc", "a,%s", zero);
4579 aopPut (IC_RESULT (ic), "a", offset++);
4585 /* if I can do an increment instead
4586 of add then GOOD for ME */
4587 if (genPlusIncr (ic) == TRUE)
4590 size = getDataSize (IC_RESULT (ic));
4591 leftOp = IC_LEFT(ic);
4592 rightOp = IC_RIGHT(ic);
4595 /* if this is an add for an array access
4596 at a 256 byte boundary */
4598 && AOP_TYPE (op) == AOP_IMMD
4600 && IS_SPEC (OP_SYM_ETYPE (op))
4601 && SPEC_ABSA (OP_SYM_ETYPE (op))
4602 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4605 D(emitcode (";", "genPlus aligned array"));
4606 aopPut (IC_RESULT (ic),
4607 aopGet (rightOp, 0, FALSE, FALSE),
4610 if( 1 == getDataSize (IC_RIGHT (ic)) )
4612 aopPut (IC_RESULT (ic),
4613 aopGet (leftOp, 1, FALSE, FALSE),
4618 MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4619 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4620 aopPut (IC_RESULT (ic), "a", 1);
4625 /* if the lower bytes of a literal are zero skip the addition */
4626 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4628 while ((0 == ((unsigned int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4629 (skip_bytes+1 < size))
4634 D(emitcode (";", "genPlus shortcut"));
4639 if( offset >= skip_bytes )
4641 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4644 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4646 emitcode("xch", "a,b");
4647 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4648 emitcode (add, "a,b");
4651 else if (aopGetUsesAcc (leftOp, offset))
4653 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4654 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4658 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4659 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4661 aopPut (IC_RESULT (ic), "a", offset);
4662 add = "addc"; /* further adds must propagate carry */
4666 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4667 isOperandVolatile (IC_RESULT (ic), FALSE))
4670 aopPut (IC_RESULT (ic),
4671 aopGet (leftOp, offset, FALSE, FALSE),
4678 adjustArithmeticResult (ic);
4681 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4684 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4685 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4689 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4690 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4694 /*-----------------------------------------------------------------*/
4695 /* genMinusDec :- does subtraction with decrement if possible */
4696 /*-----------------------------------------------------------------*/
4698 genMinusDec (iCode * ic)
4700 unsigned int icount;
4701 unsigned int size = getDataSize (IC_RESULT (ic));
4703 /* will try to generate an increment */
4704 /* if the right side is not a literal
4706 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4709 /* if the literal value of the right hand side
4710 is greater than 4 then it is not worth it */
4711 if ((icount = (unsigned int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4714 D (emitcode (";", "genMinusDec"));
4716 /* if decrement >=16 bits in register or direct space */
4717 if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG ||
4718 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4719 (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4720 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4729 /* If the next instruction is a goto and the goto target
4730 * is <= 10 instructions previous to this, we can generate
4731 * jumps straight to that target.
4733 if (ic->next && ic->next->op == GOTO
4734 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4735 && labelRange <= 10)
4737 D (emitcode (";", "tail decrement optimized (range %d)", labelRange));
4738 tlbl = IC_LABEL (ic->next);
4743 tlbl = newiTempLabel (NULL);
4747 l = aopGet (IC_RESULT (ic), LSB, FALSE, FALSE);
4748 emitcode ("dec", "%s", l);
4750 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4751 IS_AOP_PREG (IC_RESULT (ic)))
4753 emitcode ("cjne", "%s,#0xff,%05d$", l, tlbl->key + 100);
4757 emitcode ("mov", "a,#0xff");
4758 emitcode ("cjne", "a,%s,%05d$", l, tlbl->key + 100);
4760 l = aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE);
4761 emitcode ("dec", "%s", l);
4764 if (!strcmp(l, "acc"))
4766 emitcode("jnz", "!tlabel", tlbl->key + 100);
4768 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4769 IS_AOP_PREG (IC_RESULT (ic)))
4771 emitcode ("cjne", "%s,#0xff,%05d$", l, tlbl->key + 100);
4775 emitcode ("cjne", "a,%s,%05d$", l, tlbl->key + 100);
4777 l = aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE);
4778 emitcode ("dec", "%s", l);
4782 if (!strcmp(l, "acc"))
4784 emitcode("jnz", "!tlabel", tlbl->key + 100);
4786 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4787 IS_AOP_PREG (IC_RESULT (ic)))
4789 emitcode ("cjne", "%s,#0xff,%05d$", l, tlbl->key + 100);
4793 emitcode ("cjne", "a,%s,%05d$", l, tlbl->key + 100);
4795 l = aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE);
4796 emitcode ("dec", "%s", l);
4805 /* if the sizes are greater than 1 then we cannot */
4806 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4807 AOP_SIZE (IC_LEFT (ic)) > 1)
4810 /* we can if the aops of the left & result match or
4811 if they are in registers and the registers are the
4813 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4817 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4819 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4824 l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
4829 emitcode ("dec", "%s", l);
4832 if (AOP_NEEDSACC (IC_RESULT (ic)))
4833 aopPut (IC_RESULT (ic), "a", 0);
4840 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4841 emitcode ("dec", "a");
4842 aopPut (IC_RESULT (ic), "a", 0);
4849 /*-----------------------------------------------------------------*/
4850 /* addSign - complete with sign */
4851 /*-----------------------------------------------------------------*/
4853 addSign (operand * result, int offset, int sign)
4855 int size = (getDataSize (result) - offset);
4860 emitcode ("rlc", "a");
4861 emitcode ("subb", "a,acc");
4864 aopPut (result, "a", offset++);
4871 aopPut (result, zero, offset++);
4877 /*-----------------------------------------------------------------*/
4878 /* genMinusBits - generates code for subtraction of two bits */
4879 /*-----------------------------------------------------------------*/
4881 genMinusBits (iCode * ic)
4883 symbol *lbl = newiTempLabel (NULL);
4885 D (emitcode (";", "genMinusBits"));
4887 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4889 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4890 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4891 emitcode ("cpl", "c");
4893 outBitC (IC_RESULT (ic));
4897 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4898 emitcode ("subb", "a,acc");
4899 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4900 emitcode ("inc", "a");
4902 aopPut (IC_RESULT (ic), "a", 0);
4903 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4907 /*-----------------------------------------------------------------*/
4908 /* genMinus - generates code for subtraction */
4909 /*-----------------------------------------------------------------*/
4911 genMinus (iCode * ic)
4913 int size, offset = 0;
4915 D (emitcode (";", "genMinus"));
4917 aopOp (IC_LEFT (ic), ic, FALSE);
4918 aopOp (IC_RIGHT (ic), ic, FALSE);
4919 aopOp (IC_RESULT (ic), ic, TRUE);
4921 /* special cases :- */
4922 /* if both left & right are in bit space */
4923 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4924 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4930 /* if I can do an decrement instead
4931 of subtract then GOOD for ME */
4932 if (genMinusDec (ic) == TRUE)
4935 size = getDataSize (IC_RESULT (ic));
4937 /* if literal, add a,#-lit, else normal subb */
4938 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4940 unsigned long lit = 0L;
4941 bool useCarry = FALSE;
4943 lit = ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4948 if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4950 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4951 if (!offset && !size && lit== (unsigned long) -1)
4953 emitcode ("dec", "a");
4957 /* first add without previous c */
4958 emitcode ("add", "a,#0x%02x",
4959 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4964 emitcode ("addc", "a,#0x%02x",
4965 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4967 aopPut (IC_RESULT (ic), "a", offset++);
4971 /* no need to add zeroes */
4972 if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4974 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4983 operand *leftOp, *rightOp;
4985 leftOp = IC_LEFT(ic);
4986 rightOp = IC_RIGHT(ic);
4990 if (aopGetUsesAcc(rightOp, offset)) {
4991 if (aopGetUsesAcc(leftOp, offset)) {
4994 MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4996 emitcode ("mov", "b,a");
4999 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
5000 emitcode ("subb", "a,b");
5003 /* reverse subtraction with 2's complement */
5005 emitcode( "setb", "c");
5007 emitcode( "cpl", "c");
5008 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
5009 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
5010 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
5011 emitcode("cpl", "a");
5012 if (size) /* skip if last byte */
5013 emitcode( "cpl", "c");
5016 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
5019 emitcode ("subb", "a,%s",
5020 aopGet(rightOp, offset, FALSE, TRUE));
5023 aopPut (IC_RESULT (ic), "a", offset++);
5027 adjustArithmeticResult (ic);
5030 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5031 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5032 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5036 /*-----------------------------------------------------------------*/
5037 /* genMultbits :- multiplication of bits */
5038 /*-----------------------------------------------------------------*/
5040 genMultbits (operand * left,
5044 D (emitcode (";", "genMultbits"));
5046 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5047 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5051 /*-----------------------------------------------------------------*/
5052 /* genMultOneByte : 8*8=8/16 bit multiplication */
5053 /*-----------------------------------------------------------------*/
5055 genMultOneByte (operand * left,
5060 int size = AOP_SIZE (result);
5061 bool runtimeSign, compiletimeSign;
5062 bool lUnsigned, rUnsigned, pushedB;
5064 D (emitcode (";", "genMultOneByte"));
5066 if (size < 1 || size > 2)
5068 /* this should never happen */
5069 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
5070 AOP_SIZE(result), __FILE__, lineno);
5074 /* (if two literals: the value is computed before) */
5075 /* if one literal, literal on the right */
5076 if (AOP_TYPE (left) == AOP_LIT)
5081 /* emitcode (";", "swapped left and right"); */
5083 /* if no literal, unsigned on the right: shorter code */
5084 if ( AOP_TYPE (right) != AOP_LIT
5085 && SPEC_USIGN (getSpec (operandType (left))))
5092 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5093 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5097 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
5098 no need to take care about the signedness! */
5099 || (lUnsigned && rUnsigned))
5101 /* just an unsigned 8 * 8 = 8 multiply
5103 /* emitcode (";","unsigned"); */
5104 /* TODO: check for accumulator clash between left & right aops? */
5106 if (AOP_TYPE (right) == AOP_LIT)
5108 /* moving to accumulator first helps peepholes */
5109 MOVA (aopGet (left, 0, FALSE, FALSE));
5110 MOVB (aopGet (right, 0, FALSE, FALSE));
5114 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5115 MOVA (aopGet (left, 0, FALSE, FALSE));
5118 emitcode ("mul", "ab");
5119 aopPut (result, "a", 0);
5121 aopPut (result, "b", 1);
5127 /* we have to do a signed multiply */
5128 /* emitcode (";", "signed"); */
5130 /* now sign adjust for both left & right */
5132 /* let's see what's needed: */
5133 /* apply negative sign during runtime */
5134 runtimeSign = FALSE;
5135 /* negative sign from literals */
5136 compiletimeSign = FALSE;
5140 if (AOP_TYPE(left) == AOP_LIT)
5142 /* signed literal */
5143 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5145 compiletimeSign = TRUE;
5148 /* signed but not literal */
5154 if (AOP_TYPE(right) == AOP_LIT)
5156 /* signed literal */
5157 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
5159 compiletimeSign ^= TRUE;
5162 /* signed but not literal */
5166 /* initialize F0, which stores the runtime sign */
5169 if (compiletimeSign)
5170 emitcode ("setb", "F0"); /* set sign flag */
5172 emitcode ("clr", "F0"); /* reset sign flag */
5175 /* save the signs of the operands */
5176 if (AOP_TYPE(right) == AOP_LIT)
5178 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
5180 if (!rUnsigned && val < 0)
5181 emitcode ("mov", "b,#0x%02x", -val);
5183 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5185 else /* ! literal */
5187 if (rUnsigned) /* emitcode (";", "signed"); */
5188 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5191 MOVA (aopGet (right, 0, FALSE, FALSE));
5192 lbl = newiTempLabel (NULL);
5193 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5194 emitcode ("cpl", "F0"); /* complement sign flag */
5195 emitcode ("cpl", "a"); /* 2's complement */
5196 emitcode ("inc", "a");
5198 emitcode ("mov", "b,a");
5202 if (AOP_TYPE(left) == AOP_LIT)
5204 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5206 if (!lUnsigned && val < 0)
5207 emitcode ("mov", "a,#0x%02x", -val);
5209 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5211 else /* ! literal */
5213 MOVA (aopGet (left, 0, FALSE, FALSE));
5217 lbl = newiTempLabel (NULL);
5218 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5219 emitcode ("cpl", "F0"); /* complement sign flag */
5220 emitcode ("cpl", "a"); /* 2's complement */
5221 emitcode ("inc", "a");
5226 /* now the multiplication */
5227 emitcode ("mul", "ab");
5228 if (runtimeSign || compiletimeSign)
5230 lbl = newiTempLabel (NULL);
5232 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5233 emitcode ("cpl", "a"); /* lsb 2's complement */
5235 emitcode ("inc", "a"); /* inc doesn't set carry flag */
5238 emitcode ("add", "a,#0x01"); /* this sets carry flag */
5239 emitcode ("xch", "a,b");
5240 emitcode ("cpl", "a"); /* msb 2's complement */
5241 emitcode ("addc", "a,#0x00");
5242 emitcode ("xch", "a,b");
5246 aopPut (result, "a", 0);
5248 aopPut (result, "b", 1);
5253 /*-----------------------------------------------------------------*/
5254 /* genMult - generates code for multiplication */
5255 /*-----------------------------------------------------------------*/
5257 genMult (iCode * ic)
5259 operand *left = IC_LEFT (ic);
5260 operand *right = IC_RIGHT (ic);
5261 operand *result = IC_RESULT (ic);
5263 D (emitcode (";", "genMult"));
5265 /* assign the asmops */
5266 aopOp (left, ic, FALSE);
5267 aopOp (right, ic, FALSE);
5268 aopOp (result, ic, TRUE);
5270 /* special cases first */
5272 if (AOP_TYPE (left) == AOP_CRY &&
5273 AOP_TYPE (right) == AOP_CRY)
5275 genMultbits (left, right, result);
5279 /* if both are of size == 1 */
5280 #if 0 // one of them can be a sloc shared with the result
5281 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
5283 if (getSize(operandType(left)) == 1 &&
5284 getSize(operandType(right)) == 1)
5287 genMultOneByte (left, right, result);
5291 /* should have been converted to function call */
5292 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
5293 getSize(OP_SYMBOL(right)->type));
5297 freeAsmop (result, NULL, ic, TRUE);
5298 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5299 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5302 /*-----------------------------------------------------------------*/
5303 /* genDivbits :- division of bits */
5304 /*-----------------------------------------------------------------*/
5306 genDivbits (operand * left,
5313 D(emitcode (";", "genDivbits"));
5317 /* the result must be bit */
5318 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5319 l = aopGet (left, 0, FALSE, FALSE);
5323 emitcode ("div", "ab");
5324 emitcode ("rrc", "a");
5328 aopPut (result, "c", 0);
5331 /*-----------------------------------------------------------------*/
5332 /* genDivOneByte : 8 bit division */
5333 /*-----------------------------------------------------------------*/
5335 genDivOneByte (operand * left,
5339 bool lUnsigned, rUnsigned, pushedB;
5340 bool runtimeSign, compiletimeSign;
5341 bool accuse = FALSE;
5342 bool pushedA = FALSE;
5346 D(emitcode (";", "genDivOneByte"));
5348 /* Why is it necessary that genDivOneByte() can return an int result?
5351 volatile unsigned char uc;
5352 volatile signed char sc1, sc2;
5365 In all cases a one byte result would overflow, the following cast to int
5366 would return the wrong result.
5368 Two possible solution:
5369 a) cast operands to int, if ((unsigned) / (signed)) or
5370 ((signed) / (signed))
5371 b) return an 16 bit signed int; this is what we're doing here!
5374 size = AOP_SIZE (result) - 1;
5376 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5377 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5381 /* signed or unsigned */
5382 if (lUnsigned && rUnsigned)
5384 /* unsigned is easy */
5385 MOVB (aopGet (right, 0, FALSE, FALSE));
5386 MOVA (aopGet (left, 0, FALSE, FALSE));
5387 emitcode ("div", "ab");
5388 aopPut (result, "a", 0);
5390 aopPut (result, zero, offset++);
5396 /* signed is a little bit more difficult */
5398 /* now sign adjust for both left & right */
5400 /* let's see what's needed: */
5401 /* apply negative sign during runtime */
5402 runtimeSign = FALSE;
5403 /* negative sign from literals */
5404 compiletimeSign = FALSE;
5408 if (AOP_TYPE(left) == AOP_LIT)
5410 /* signed literal */
5411 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5413 compiletimeSign = TRUE;
5416 /* signed but not literal */
5422 if (AOP_TYPE(right) == AOP_LIT)
5424 /* signed literal */
5425 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
5427 compiletimeSign ^= TRUE;
5430 /* signed but not literal */
5434 /* initialize F0, which stores the runtime sign */
5437 if (compiletimeSign)
5438 emitcode ("setb", "F0"); /* set sign flag */
5440 emitcode ("clr", "F0"); /* reset sign flag */
5443 /* save the signs of the operands */
5444 if (AOP_TYPE(right) == AOP_LIT)
5446 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
5448 if (!rUnsigned && val < 0)
5449 emitcode ("mov", "b,#0x%02x", -val);
5451 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5453 else /* ! literal */
5456 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5459 MOVA (aopGet (right, 0, FALSE, FALSE));
5460 lbl = newiTempLabel (NULL);
5461 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5462 emitcode ("cpl", "F0"); /* complement sign flag */
5463 emitcode ("cpl", "a"); /* 2's complement */
5464 emitcode ("inc", "a");
5466 emitcode ("mov", "b,a");
5470 if (AOP_TYPE(left) == AOP_LIT)
5472 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5474 if (!lUnsigned && val < 0)
5475 emitcode ("mov", "a,#0x%02x", -val);
5477 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5479 else /* ! literal */
5481 MOVA (aopGet (left, 0, FALSE, FALSE));
5485 lbl = newiTempLabel (NULL);
5486 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5487 emitcode ("cpl", "F0"); /* complement sign flag */
5488 emitcode ("cpl", "a"); /* 2's complement */
5489 emitcode ("inc", "a");
5494 /* now the division */
5495 emitcode ("div", "ab");
5497 if (runtimeSign || compiletimeSign)
5499 lbl = newiTempLabel (NULL);
5501 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5502 emitcode ("cpl", "a"); /* lsb 2's complement */
5503 emitcode ("inc", "a");
5506 accuse = aopPut (result, "a", 0);
5509 /* msb is 0x00 or 0xff depending on the sign */
5514 emitcode ("push", "acc");
5517 emitcode ("mov", "c,F0");
5518 emitcode ("subb", "a,acc");
5520 aopPut (result, "a", offset++);
5522 else /* compiletimeSign */
5524 if (aopPutUsesAcc (result, "#0xff", offset))
5526 emitcode ("push", "acc");
5530 aopPut (result, "#0xff", offset++);
5536 aopPut (result, "a", 0);
5538 aopPut (result, zero, offset++);
5542 emitcode ("pop", "acc");
5546 /*-----------------------------------------------------------------*/
5547 /* genDiv - generates code for division */
5548 /*-----------------------------------------------------------------*/
5552 operand *left = IC_LEFT (ic);
5553 operand *right = IC_RIGHT (ic);
5554 operand *result = IC_RESULT (ic);
5556 D (emitcode (";", "genDiv"));
5558 /* assign the asmops */
5559 aopOp (left, ic, FALSE);
5560 aopOp (right, ic, FALSE);
5561 aopOp (result, ic, TRUE);
5563 /* special cases first */
5565 if (AOP_TYPE (left) == AOP_CRY &&
5566 AOP_TYPE (right) == AOP_CRY)
5568 genDivbits (left, right, result);
5572 /* if both are of size == 1 */
5573 if (AOP_SIZE (left) == 1 &&
5574 AOP_SIZE (right) == 1)
5576 genDivOneByte (left, right, result);
5580 /* should have been converted to function call */
5583 freeAsmop (result, NULL, ic, TRUE);
5584 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5585 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5588 /*-----------------------------------------------------------------*/
5589 /* genModbits :- modulus of bits */
5590 /*-----------------------------------------------------------------*/
5592 genModbits (operand * left,
5599 D (emitcode (";", "genModbits"));
5603 /* the result must be bit */
5604 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5605 l = aopGet (left, 0, FALSE, FALSE);
5609 emitcode ("div", "ab");
5610 emitcode ("mov", "a,b");
5611 emitcode ("rrc", "a");
5615 aopPut (result, "c", 0);
5618 /*-----------------------------------------------------------------*/
5619 /* genModOneByte : 8 bit modulus */
5620 /*-----------------------------------------------------------------*/
5622 genModOneByte (operand * left,
5626 bool lUnsigned, rUnsigned, pushedB;
5627 bool runtimeSign, compiletimeSign;
5631 D (emitcode (";", "genModOneByte"));
5633 size = AOP_SIZE (result) - 1;
5635 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5636 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5638 /* if right is a literal, check it for 2^n */
5639 if (AOP_TYPE(right) == AOP_LIT)
5641 unsigned char val = abs((int) operandLitValue(right));
5642 symbol *lbl2 = NULL;
5646 case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5655 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5656 "modulus of unsigned char by 2^n literal shouldn't be processed here");
5657 /* because iCode should have been changed to genAnd */
5658 /* see file "SDCCopt.c", function "convertToFcall()" */
5660 MOVA (aopGet (left, 0, FALSE, FALSE));
5661 emitcode ("mov", "c,acc.7");
5662 emitcode ("anl", "a,#0x%02x", val - 1);
5663 lbl = newiTempLabel (NULL);
5664 emitcode ("jz", "%05d$", (lbl->key + 100));
5665 emitcode ("jnc", "%05d$", (lbl->key + 100));
5666 emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5672 aopPut (result, "a", 0);
5674 aopPut (result, "#0xff", offs2++);
5675 lbl2 = newiTempLabel (NULL);
5676 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5679 aopPut (result, "a", 0);
5681 aopPut (result, zero, offset++);
5695 /* signed or unsigned */
5696 if (lUnsigned && rUnsigned)
5698 /* unsigned is easy */
5699 MOVB (aopGet (right, 0, FALSE, FALSE));
5700 MOVA (aopGet (left, 0, FALSE, FALSE));
5701 emitcode ("div", "ab");
5702 aopPut (result, "b", 0);
5704 aopPut (result, zero, offset++);
5710 /* signed is a little bit more difficult */
5712 /* now sign adjust for both left & right */
5714 /* modulus: sign of the right operand has no influence on the result! */
5715 if (AOP_TYPE(right) == AOP_LIT)
5717 signed char val = (char) operandLitValue(right);
5719 if (!rUnsigned && val < 0)
5720 emitcode ("mov", "b,#0x%02x", -val);
5722 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5724 else /* not literal */
5727 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5730 MOVA (aopGet (right, 0, FALSE, FALSE));
5731 lbl = newiTempLabel (NULL);
5732 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5733 emitcode ("cpl", "a"); /* 2's complement */
5734 emitcode ("inc", "a");
5736 emitcode ("mov", "b,a");
5740 /* let's see what's needed: */
5741 /* apply negative sign during runtime */
5742 runtimeSign = FALSE;
5743 /* negative sign from literals */
5744 compiletimeSign = FALSE;
5746 /* sign adjust left side */
5747 if (AOP_TYPE(left) == AOP_LIT)
5749 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5751 if (!lUnsigned && val < 0)
5753 compiletimeSign = TRUE; /* set sign flag */
5754 emitcode ("mov", "a,#0x%02x", -val);
5757 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5759 else /* ! literal */
5761 MOVA (aopGet (left, 0, FALSE, FALSE));
5766 emitcode ("clr", "F0"); /* clear sign flag */
5768 lbl = newiTempLabel (NULL);
5769 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5770 emitcode ("setb", "F0"); /* set sign flag */
5771 emitcode ("cpl", "a"); /* 2's complement */
5772 emitcode ("inc", "a");
5777 /* now the modulus */
5778 emitcode ("div", "ab");
5780 if (runtimeSign || compiletimeSign)
5782 emitcode ("mov", "a,b");
5783 lbl = newiTempLabel (NULL);
5785 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5786 emitcode ("cpl", "a"); /* 2's complement */
5787 emitcode ("inc", "a");
5790 aopPut (result, "a", 0);
5793 /* msb is 0x00 or 0xff depending on the sign */
5796 emitcode ("mov", "c,F0");
5797 emitcode ("subb", "a,acc");
5799 aopPut (result, "a", offset++);
5801 else /* compiletimeSign */
5803 aopPut (result, "#0xff", offset++);
5808 aopPut (result, "b", 0);
5810 aopPut (result, zero, offset++);
5816 /*-----------------------------------------------------------------*/
5817 /* genMod - generates code for division */
5818 /*-----------------------------------------------------------------*/
5822 operand *left = IC_LEFT (ic);
5823 operand *right = IC_RIGHT (ic);
5824 operand *result = IC_RESULT (ic);
5826 D (emitcode (";", "genMod"));
5828 /* assign the asmops */
5829 aopOp (left, ic, FALSE);
5830 aopOp (right, ic, FALSE);
5831 aopOp (result, ic, TRUE);
5833 /* special cases first */
5835 if (AOP_TYPE (left) == AOP_CRY &&
5836 AOP_TYPE (right) == AOP_CRY)
5838 genModbits (left, right, result);
5842 /* if both are of size == 1 */
5843 if (AOP_SIZE (left) == 1 &&
5844 AOP_SIZE (right) == 1)
5846 genModOneByte (left, right, result);
5850 /* should have been converted to function call */
5854 freeAsmop (result, NULL, ic, TRUE);
5855 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5856 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5859 /*-----------------------------------------------------------------*/
5860 /* genIfxJump :- will create a jump depending on the ifx */
5861 /*-----------------------------------------------------------------*/
5863 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result, iCode *popIc)
5866 symbol *tlbl = newiTempLabel (NULL);
5869 /* if there is something to be popped then do it first */
5870 popForBranch (popIc, TRUE);
5872 D (emitcode (";", "genIfxJump"));
5874 /* if true label then we jump if condition
5878 jlbl = IC_TRUE (ic);
5879 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5880 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5884 /* false label is present */
5885 jlbl = IC_FALSE (ic);
5886 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5887 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5889 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5890 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5892 emitcode (inst, "%05d$", tlbl->key + 100);
5893 freeForBranchAsmop (result);
5894 freeForBranchAsmop (right);
5895 freeForBranchAsmop (left);
5896 emitcode ("ljmp", "%05d$", jlbl->key + 100);
5899 /* mark the icode as generated */
5903 /*-----------------------------------------------------------------*/
5904 /* genCmp :- greater or less than comparison */
5905 /*-----------------------------------------------------------------*/
5907 genCmp (operand * left, operand * right,
5908 operand * result, iCode * ifx, int sign, iCode *ic)
5910 int size, offset = 0;
5911 unsigned long lit = 0L;
5914 D (emitcode (";", "genCmp"));
5916 /* if left & right are bit variables */
5917 if (AOP_TYPE (left) == AOP_CRY &&
5918 AOP_TYPE (right) == AOP_CRY)
5920 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5921 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5925 /* subtract right from left if at the
5926 end the carry flag is set then we know that
5927 left is greater than right */
5928 size = max (AOP_SIZE (left), AOP_SIZE (right));
5930 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5931 if ((size == 1) && !sign &&
5932 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5934 symbol *lbl = newiTempLabel (NULL);
5935 emitcode ("cjne", "%s,%s,%05d$",
5936 aopGet (left, offset, FALSE, FALSE),
5937 aopGet (right, offset, FALSE, FALSE),
5943 if (AOP_TYPE (right) == AOP_LIT)
5945 lit = ulFromVal (AOP (right)->aopu.aop_lit);
5946 /* optimize if(x < 0) or if(x >= 0) */
5955 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5956 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5958 genIfxJump (ifx, "acc.7", left, right, result, ic->next);
5959 freeAsmop (right, NULL, ic, TRUE);
5960 freeAsmop (left, NULL, ic, TRUE);
5966 emitcode ("rlc", "a");
5973 int bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5974 while (size && (bytelit == 0))
5977 bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5983 MOVA (aopGet (left, offset, FALSE, FALSE));
5984 if (sign && size == 0)
5986 emitcode ("xrl", "a,#0x80");
5987 emitcode ("subb", "a,#0x%02x",
5988 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5992 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
6002 bool pushedB = FALSE;
6003 rightInB = aopGetUsesAcc(right, offset);
6007 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
6009 MOVA (aopGet (left, offset, FALSE, FALSE));
6010 if (sign && size == 0)
6012 emitcode ("xrl", "a,#0x80");
6017 MOVB (aopGet (right, offset, FALSE, FALSE));
6019 emitcode ("xrl", "b,#0x80");
6020 emitcode ("subb", "a,b");
6025 emitcode ("subb", "a,b");
6027 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
6037 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6038 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6039 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6045 /* if the result is used in the next
6046 ifx conditional branch then generate
6047 code a little differently */
6050 genIfxJump (ifx, "c", NULL, NULL, result, ic->next);
6056 /* leave the result in acc */
6060 /*-----------------------------------------------------------------*/
6061 /* genCmpGt :- greater than comparison */
6062 /*-----------------------------------------------------------------*/
6064 genCmpGt (iCode * ic, iCode * ifx)
6066 operand *left, *right, *result;
6067 sym_link *letype, *retype;
6070 D (emitcode (";", "genCmpGt"));
6072 left = IC_LEFT (ic);
6073 right = IC_RIGHT (ic);
6074 result = IC_RESULT (ic);
6076 letype = getSpec (operandType (left));
6077 retype = getSpec (operandType (right));
6078 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
6079 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
6080 /* assign the asmops */
6081 aopOp (result, ic, TRUE);
6082 aopOp (left, ic, FALSE);
6083 aopOp (right, ic, FALSE);
6085 genCmp (right, left, result, ifx, sign, ic);
6087 freeAsmop (result, NULL, ic, TRUE);
6090 /*-----------------------------------------------------------------*/
6091 /* genCmpLt - less than comparisons */
6092 /*-----------------------------------------------------------------*/
6094 genCmpLt (iCode * ic, iCode * ifx)
6096 operand *left, *right, *result;
6097 sym_link *letype, *retype;
6100 D (emitcode (";", "genCmpLt"));
6102 left = IC_LEFT (ic);
6103 right = IC_RIGHT (ic);
6104 result = IC_RESULT (ic);
6106 letype = getSpec (operandType (left));
6107 retype = getSpec (operandType (right));
6108 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
6109 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
6110 /* assign the asmops */
6111 aopOp (result, ic, TRUE);
6112 aopOp (left, ic, FALSE);
6113 aopOp (right, ic, FALSE);
6115 genCmp (left, right, result, ifx, sign, ic);
6117 freeAsmop (result, NULL, ic, TRUE);
6120 /*-----------------------------------------------------------------*/
6121 /* gencjneshort - compare and jump if not equal */
6122 /*-----------------------------------------------------------------*/
6124 gencjneshort (operand * left, operand * right, symbol * lbl)
6126 int size = max (AOP_SIZE (left), AOP_SIZE (right));
6128 unsigned long lit = 0L;
6130 D (emitcode (";", "gencjneshort"));
6132 /* if the left side is a literal or
6133 if the right is in a pointer register and left
6135 if ((AOP_TYPE (left) == AOP_LIT) ||
6136 (AOP_TYPE (left) == AOP_IMMD) ||
6137 (AOP_TYPE (left) == AOP_DIR) ||
6138 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6145 if (AOP_TYPE (right) == AOP_LIT)
6146 lit = ulFromVal (AOP (right)->aopu.aop_lit);
6148 /* if the right side is a literal then anything goes */
6149 if (AOP_TYPE (right) == AOP_LIT &&
6150 AOP_TYPE (left) != AOP_DIR &&
6151 AOP_TYPE (left) != AOP_IMMD)
6155 emitcode ("cjne", "%s,%s,%05d$",
6156 aopGet (left, offset, FALSE, FALSE),
6157 aopGet (right, offset, FALSE, FALSE),
6163 /* if the right side is in a register or in direct space or
6164 if the left is a pointer register & right is not */
6165 else if (AOP_TYPE (right) == AOP_REG ||
6166 AOP_TYPE (right) == AOP_DIR ||
6167 AOP_TYPE (right) == AOP_LIT ||
6168 AOP_TYPE (right) == AOP_IMMD ||
6169 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6170 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6174 MOVA (aopGet (left, offset, FALSE, FALSE));
6175 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6176 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6177 emitcode ("jnz", "%05d$", lbl->key + 100);
6179 emitcode ("cjne", "a,%s,%05d$",
6180 aopGet (right, offset, FALSE, TRUE),
6187 /* right is a pointer reg need both a & b */
6190 //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
6191 wassertl(!BINUSE, "B was in use");
6192 MOVB (aopGet (left, offset, FALSE, FALSE));
6193 MOVA (aopGet (right, offset, FALSE, FALSE));
6194 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
6200 /*-----------------------------------------------------------------*/
6201 /* gencjne - compare and jump if not equal */
6202 /*-----------------------------------------------------------------*/
6204 gencjne (operand * left, operand * right, symbol * lbl, bool useCarry)
6206 symbol *tlbl = newiTempLabel (NULL);
6208 D (emitcode (";", "gencjne"));
6210 gencjneshort (left, right, lbl);
6216 emitcode ("sjmp", "%05d$", tlbl->key + 100);
6225 /*-----------------------------------------------------------------*/
6226 /* genCmpEq - generates code for equal to */
6227 /*-----------------------------------------------------------------*/
6229 genCmpEq (iCode * ic, iCode * ifx)
6231 bool swappedLR = FALSE;
6232 operand *left, *right, *result;
6233 iCode * popIc = ic->next;
6235 D (emitcode (";", "genCmpEq"));
6237 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6238 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6239 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6241 /* if literal, literal on the right or
6242 if the right is in a pointer register and left
6244 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6245 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6247 operand *t = IC_RIGHT (ic);
6248 IC_RIGHT (ic) = IC_LEFT (ic);
6253 if (ifx && !AOP_SIZE (result))
6256 /* if they are both bit variables */
6257 if (AOP_TYPE (left) == AOP_CRY &&
6258 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6260 if (AOP_TYPE (right) == AOP_LIT)
6262 unsigned long lit = ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6265 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6266 emitcode ("cpl", "c");
6270 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6274 emitcode ("clr", "c");
6276 /* AOP_TYPE(right) == AOP_CRY */
6280 symbol *lbl = newiTempLabel (NULL);
6281 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6282 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6283 emitcode ("cpl", "c");
6286 /* if true label then we jump if condition
6288 tlbl = newiTempLabel (NULL);
6291 emitcode ("jnc", "%05d$", tlbl->key + 100);
6292 freeForBranchAsmop (result);
6293 freeForBranchAsmop (right);
6294 freeForBranchAsmop (left);
6295 popForBranch (popIc, FALSE);
6296 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6300 emitcode ("jc", "%05d$", tlbl->key + 100);
6301 freeForBranchAsmop (result);
6302 freeForBranchAsmop (right);
6303 freeForBranchAsmop (left);
6304 popForBranch (popIc, FALSE);
6305 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6311 tlbl = newiTempLabel (NULL);
6312 gencjneshort (left, right, tlbl);
6315 freeForBranchAsmop (result);
6316 freeForBranchAsmop (right);
6317 freeForBranchAsmop (left);
6318 popForBranch (popIc, FALSE);
6319 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6324 symbol *lbl = newiTempLabel (NULL);
6325 emitcode ("sjmp", "%05d$", lbl->key + 100);
6327 freeForBranchAsmop (result);
6328 freeForBranchAsmop (right);
6329 freeForBranchAsmop (left);
6330 popForBranch (popIc, FALSE);
6331 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6335 /* mark the icode as generated */
6340 /* if they are both bit variables */
6341 if (AOP_TYPE (left) == AOP_CRY &&
6342 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6344 if (AOP_TYPE (right) == AOP_LIT)
6346 unsigned long lit = ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6349 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6350 emitcode ("cpl", "c");
6354 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6358 emitcode ("clr", "c");
6360 /* AOP_TYPE(right) == AOP_CRY */
6364 symbol *lbl = newiTempLabel (NULL);
6365 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6366 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6367 emitcode ("cpl", "c");
6371 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6378 genIfxJump (ifx, "c", left, right, result, popIc);
6381 /* if the result is used in an arithmetic operation
6382 then put the result in place */
6387 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6389 gencjne (left, right, newiTempLabel (NULL), TRUE);
6390 aopPut (result, "c", 0);
6393 gencjne (left, right, newiTempLabel (NULL), FALSE);
6396 genIfxJump (ifx, "a", left, right, result, popIc);
6399 /* if the result is used in an arithmetic operation
6400 then put the result in place */
6401 if (AOP_TYPE (result) != AOP_CRY)
6403 /* leave the result in acc */
6407 freeAsmop (result, NULL, ic, TRUE);
6410 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6411 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6415 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6416 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6420 /*-----------------------------------------------------------------*/
6421 /* ifxForOp - returns the icode containing the ifx for operand */
6422 /*-----------------------------------------------------------------*/
6424 ifxForOp (operand * op, iCode * ic)
6428 /* if true symbol then needs to be assigned */
6429 if (IS_TRUE_SYMOP (op))
6432 /* if this has register type condition and
6433 while skipping ipop's (see bug 1509084),
6434 the next instruction is ifx with the same operand
6435 and live to of the operand is upto the ifx only then */
6436 for (ifxIc = ic->next; ifxIc && ifxIc->op == IPOP; ifxIc = ifxIc->next);
6437 if (ifxIc && ifxIc->op == IFX &&
6438 IC_COND (ifxIc)->key == op->key &&
6439 OP_SYMBOL (op)->liveTo <= ifxIc->seq)
6445 /*-----------------------------------------------------------------*/
6446 /* hasInc - operand is incremented before any other use */
6447 /*-----------------------------------------------------------------*/
6449 hasInc (operand *op, iCode *ic, int osize)
6451 sym_link *type = operandType(op);
6452 sym_link *retype = getSpec (type);
6453 iCode *lic = ic->next;
6456 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6457 if (!IS_SYMOP(op)) return NULL;
6459 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6460 if (IS_AGGREGATE(type->next)) return NULL;
6461 if (osize != (isize = getSize(type->next))) return NULL;
6465 /* if operand of the form op = op + <sizeof *op> */
6466 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6467 isOperandEqual(IC_RESULT(lic),op) &&
6468 isOperandLiteral(IC_RIGHT(lic)) &&
6469 operandLitValue(IC_RIGHT(lic)) == isize)
6473 /* if the operand used or deffed */
6474 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key)
6478 /* if GOTO or IFX */
6479 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6485 /*-----------------------------------------------------------------*/
6486 /* genAndOp - for && operation */
6487 /*-----------------------------------------------------------------*/
6489 genAndOp (iCode * ic)
6491 operand *left, *right, *result;
6494 D (emitcode (";", "genAndOp"));
6496 /* note here that && operations that are in an
6497 if statement are taken away by backPatchLabels
6498 only those used in arthmetic operations remain */
6499 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6500 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6501 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6503 /* if both are bit variables */
6504 if (AOP_TYPE (left) == AOP_CRY &&
6505 AOP_TYPE (right) == AOP_CRY)
6507 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6508 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6513 tlbl = newiTempLabel (NULL);
6515 emitcode ("jz", "%05d$", tlbl->key + 100);
6521 freeAsmop (result, NULL, ic, TRUE);
6522 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6523 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6527 /*-----------------------------------------------------------------*/
6528 /* genOrOp - for || operation */
6529 /*-----------------------------------------------------------------*/
6531 genOrOp (iCode * ic)
6533 operand *left, *right, *result;
6536 D (emitcode (";", "genOrOp"));
6538 /* note here that || operations that are in an
6539 if statement are taken away by backPatchLabels
6540 only those used in arthmetic operations remain */
6541 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6542 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6543 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6545 /* if both are bit variables */
6546 if (AOP_TYPE (left) == AOP_CRY &&
6547 AOP_TYPE (right) == AOP_CRY)
6549 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6550 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6555 tlbl = newiTempLabel (NULL);
6557 emitcode ("jnz", "%05d$", tlbl->key + 100);
6563 freeAsmop (result, NULL, ic, TRUE);
6564 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6565 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6568 /*-----------------------------------------------------------------*/
6569 /* isLiteralBit - test if lit == 2^n */
6570 /*-----------------------------------------------------------------*/
6572 isLiteralBit (unsigned long lit)
6574 unsigned long pw[32] =
6575 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6576 0x100L, 0x200L, 0x400L, 0x800L,
6577 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6578 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6579 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6580 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6581 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6584 for (idx = 0; idx < 32; idx++)
6590 /*-----------------------------------------------------------------*/
6591 /* continueIfTrue - */
6592 /*-----------------------------------------------------------------*/
6594 continueIfTrue (iCode * ic)
6597 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6601 /*-----------------------------------------------------------------*/
6603 /*-----------------------------------------------------------------*/
6605 jumpIfTrue (iCode * ic)
6608 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6612 /*-----------------------------------------------------------------*/
6613 /* jmpTrueOrFalse - */
6614 /*-----------------------------------------------------------------*/
6616 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6618 // ugly but optimized by peephole
6621 symbol *nlbl = newiTempLabel (NULL);
6622 emitcode ("sjmp", "%05d$", nlbl->key + 100);
6624 freeForBranchAsmop (result);
6625 freeForBranchAsmop (right);
6626 freeForBranchAsmop (left);
6627 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6632 freeForBranchAsmop (result);
6633 freeForBranchAsmop (right);
6634 freeForBranchAsmop (left);
6635 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6641 /*-----------------------------------------------------------------*/
6642 /* genAnd - code for and */
6643 /*-----------------------------------------------------------------*/
6645 genAnd (iCode * ic, iCode * ifx)
6647 operand *left, *right, *result;
6648 int size, offset = 0;
6649 unsigned long lit = 0L;
6653 D (emitcode (";", "genAnd"));
6655 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6656 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6657 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6660 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
6662 AOP_TYPE (left), AOP_TYPE (right));
6663 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
6665 AOP_SIZE (left), AOP_SIZE (right));
6668 /* if left is a literal & right is not then exchange them */
6669 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6670 AOP_NEEDSACC (left))
6672 operand *tmp = right;
6677 /* if result = right then exchange left and right */
6678 if (sameRegs (AOP (result), AOP (right)))
6680 operand *tmp = right;
6685 /* if right is bit then exchange them */
6686 if (AOP_TYPE (right) == AOP_CRY &&
6687 AOP_TYPE (left) != AOP_CRY)
6689 operand *tmp = right;
6693 if (AOP_TYPE (right) == AOP_LIT)
6694 lit = ulFromVal (AOP (right)->aopu.aop_lit);
6696 size = AOP_SIZE (result);
6699 // result = bit & yy;
6700 if (AOP_TYPE (left) == AOP_CRY)
6702 // c = bit & literal;
6703 if (AOP_TYPE (right) == AOP_LIT)
6707 if (size && sameRegs (AOP (result), AOP (left)))
6710 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6715 if (size && (AOP_TYPE (result) == AOP_CRY))
6717 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6720 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6725 emitcode ("clr", "c");
6730 if (AOP_TYPE (right) == AOP_CRY)
6733 if (IS_OP_ACCUSE (left))
6735 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6739 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6740 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6746 MOVA (aopGet (right, 0, FALSE, FALSE));
6748 emitcode ("rrc", "a");
6749 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6757 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6758 genIfxJump (ifx, "c", left, right, result, ic->next);
6762 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6763 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6764 if ((AOP_TYPE (right) == AOP_LIT) &&
6765 (AOP_TYPE (result) == AOP_CRY) &&
6766 (AOP_TYPE (left) != AOP_CRY))
6768 int posbit = isLiteralBit (lit);
6773 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6777 switch (posbit & 0x07)
6779 case 0: emitcode ("rrc", "a");
6781 case 7: emitcode ("rlc", "a");
6783 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6792 SNPRINTF (buffer, sizeof(buffer),
6793 "acc.%d", posbit & 0x07);
6794 genIfxJump (ifx, buffer, left, right, result, ic->next);
6797 {// what is this case? just found it in ds390/gen.c
6798 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6805 symbol *tlbl = newiTempLabel (NULL);
6806 int sizel = AOP_SIZE (left);
6808 emitcode ("setb", "c");
6811 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6813 MOVA (aopGet (left, offset, FALSE, FALSE));
6815 if ((posbit = isLiteralBit (bytelit)) != 0)
6816 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6819 if (bytelit != 0x0FFL)
6820 emitcode ("anl", "a,%s",
6821 aopGet (right, offset, FALSE, TRUE));
6822 emitcode ("jnz", "%05d$", tlbl->key + 100);
6827 // bit = left & literal
6830 emitcode ("clr", "c");
6833 // if(left & literal)
6837 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6847 /* if left is same as result */
6848 if (sameRegs (AOP (result), AOP (left)))
6850 for (; size--; offset++)
6852 if (AOP_TYPE (right) == AOP_LIT)
6854 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6855 if (bytelit == 0x0FF)
6857 /* dummy read of volatile operand */
6858 if (isOperandVolatile (left, FALSE))
6859 MOVA (aopGet (left, offset, FALSE, FALSE));
6863 else if (bytelit == 0)
6865 aopPut (result, zero, offset);
6867 else if (IS_AOP_PREG (result))
6869 MOVA (aopGet (left, offset, FALSE, TRUE));
6870 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6871 aopPut (result, "a", offset);
6874 emitcode ("anl", "%s,%s",
6875 aopGet (left, offset, FALSE, TRUE),
6876 aopGet (right, offset, FALSE, FALSE));
6880 if (AOP_TYPE (left) == AOP_ACC)
6883 emitcode("mov", "a,b");
6884 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6886 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6888 MOVB (aopGet (left, offset, FALSE, FALSE));
6889 MOVA (aopGet (right, offset, FALSE, FALSE));
6890 emitcode ("anl", "a,b");
6891 aopPut (result, "a", offset);
6893 else if (aopGetUsesAcc (left, offset))
6895 MOVA (aopGet (left, offset, FALSE, FALSE));
6896 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6897 aopPut (result, "a", offset);
6901 MOVA (aopGet (right, offset, FALSE, FALSE));
6902 if (IS_AOP_PREG (result))
6904 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6905 aopPut (result, "a", offset);
6908 emitcode ("anl", "%s,a", aopGet (left, offset, FALSE, TRUE));
6915 // left & result in different registers
6916 if (AOP_TYPE (result) == AOP_CRY)
6919 // if(size), result in bit
6920 // if(!size && ifx), conditional oper: if(left & right)
6921 symbol *tlbl = newiTempLabel (NULL);
6922 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6924 emitcode ("setb", "c");
6927 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6928 && AOP_TYPE(left)==AOP_ACC)
6931 emitcode("mov", "a,b");
6932 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6934 else if (AOP_TYPE(left)==AOP_ACC)
6938 bool pushedB = pushB ();
6939 emitcode("mov", "b,a");
6940 MOVA (aopGet (right, offset, FALSE, FALSE));
6941 emitcode("anl", "a,b");
6946 MOVA (aopGet (right, offset, FALSE, FALSE));
6947 emitcode("anl", "a,b");
6950 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6952 MOVB (aopGet (left, offset, FALSE, FALSE));
6953 MOVA (aopGet (right, offset, FALSE, FALSE));
6954 emitcode ("anl", "a,b");
6956 else if (aopGetUsesAcc (left, offset))
6958 MOVA (aopGet (left, offset, FALSE, FALSE));
6959 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6963 MOVA (aopGet (right, offset, FALSE, FALSE));
6964 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6967 emitcode ("jnz", "%05d$", tlbl->key + 100);
6977 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6983 for (; (size--); offset++)
6986 // result = left & right
6987 if (AOP_TYPE (right) == AOP_LIT)
6989 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6990 if (bytelit == 0x0FF)
6993 aopGet (left, offset, FALSE, FALSE),
6997 else if (bytelit == 0)
6999 /* dummy read of volatile operand */
7000 if (isOperandVolatile (left, FALSE))
7001 MOVA (aopGet (left, offset, FALSE, FALSE));
7002 aopPut (result, zero, offset);
7005 else if (AOP_TYPE (left) == AOP_ACC)
7009 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7010 aopPut (result, "a", offset);
7015 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
7016 aopPut (result, "b", offset);
7021 // faster than result <- left, anl result,right
7022 // and better if result is SFR
7023 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7024 && AOP_TYPE(left)==AOP_ACC)
7027 emitcode("mov", "a,b");
7028 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7030 else if (AOP_TYPE(left)==AOP_ACC)
7034 bool pushedB = pushB ();
7035 emitcode("mov", "b,a");
7036 MOVA (aopGet (right, offset, FALSE, FALSE));
7037 emitcode("anl", "a,b");
7042 MOVA (aopGet (right, offset, FALSE, FALSE));
7043 emitcode("anl", "a,b");
7046 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7048 MOVB (aopGet (left, offset, FALSE, FALSE));
7049 MOVA (aopGet (right, offset, FALSE, FALSE));
7050 emitcode ("anl", "a,b");
7052 else if (aopGetUsesAcc (left, offset))
7054 MOVA (aopGet (left, offset, FALSE, FALSE));
7055 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7059 MOVA (aopGet (right, offset, FALSE, FALSE));
7060 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7062 aopPut (result, "a", offset);
7068 freeAsmop (result, NULL, ic, TRUE);
7069 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7070 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7073 /*-----------------------------------------------------------------*/
7074 /* genOr - code for or */
7075 /*-----------------------------------------------------------------*/
7077 genOr (iCode * ic, iCode * ifx)
7079 operand *left, *right, *result;
7080 int size, offset = 0;
7081 unsigned long lit = 0L;
7084 D (emitcode (";", "genOr"));
7086 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7087 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7088 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7091 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
7093 AOP_TYPE (left), AOP_TYPE (right));
7094 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
7096 AOP_SIZE (left), AOP_SIZE (right));
7099 /* if left is a literal & right is not then exchange them */
7100 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7101 AOP_NEEDSACC (left))
7103 operand *tmp = right;
7108 /* if result = right then exchange them */
7109 if (sameRegs (AOP (result), AOP (right)))
7111 operand *tmp = right;
7116 /* if right is bit then exchange them */
7117 if (AOP_TYPE (right) == AOP_CRY &&
7118 AOP_TYPE (left) != AOP_CRY)
7120 operand *tmp = right;
7124 if (AOP_TYPE (right) == AOP_LIT)
7125 lit = ulFromVal (AOP (right)->aopu.aop_lit);
7127 size = AOP_SIZE (result);
7131 if (AOP_TYPE (left) == AOP_CRY)
7133 if (AOP_TYPE (right) == AOP_LIT)
7135 // c = bit | literal;
7138 // lit != 0 => result = 1
7139 if (AOP_TYPE (result) == AOP_CRY)
7142 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7144 continueIfTrue (ifx);
7147 emitcode ("setb", "c");
7151 // lit == 0 => result = left
7152 if (size && sameRegs (AOP (result), AOP (left)))
7154 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7159 if (AOP_TYPE (right) == AOP_CRY)
7162 if (IS_OP_ACCUSE (left))
7164 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
7168 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7169 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7175 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7177 symbol *tlbl = newiTempLabel (NULL);
7178 emitcode ("jb", "%s,%05d$",
7179 AOP (left)->aopu.aop_dir, tlbl->key + 100);
7181 emitcode ("jnz", "%05d$", tlbl->key + 100);
7182 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7188 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7197 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7198 genIfxJump (ifx, "c", left, right, result, ic->next);
7202 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7203 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7204 if ((AOP_TYPE (right) == AOP_LIT) &&
7205 (AOP_TYPE (result) == AOP_CRY) &&
7206 (AOP_TYPE (left) != AOP_CRY))
7212 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7214 continueIfTrue (ifx);
7219 // lit = 0, result = boolean(left)
7221 emitcode ("setb", "c");
7225 symbol *tlbl = newiTempLabel (NULL);
7226 emitcode ("jnz", "%05d$", tlbl->key + 100);
7231 { /* FIXME, thats pretty fishy, check for ifx!=0, testcase .. */
7232 genIfxJump (ifx, "a", left, right, result, ic->next);
7240 /* if left is same as result */
7241 if (sameRegs (AOP (result), AOP (left)))
7243 for (; size--; offset++)
7245 if (AOP_TYPE (right) == AOP_LIT)
7247 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7250 /* dummy read of volatile operand */
7251 if (isOperandVolatile (left, FALSE))
7252 MOVA (aopGet (left, offset, FALSE, FALSE));
7256 else if (bytelit == 0x0FF)
7258 aopPut (result, "#0xff", offset);
7260 else if (IS_AOP_PREG (left))
7262 MOVA (aopGet (left, offset, FALSE, TRUE));
7263 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7264 aopPut (result, "a", offset);
7268 emitcode ("orl", "%s,%s",
7269 aopGet (left, offset, FALSE, TRUE),
7270 aopGet (right, offset, FALSE, FALSE));
7275 if (AOP_TYPE (left) == AOP_ACC)
7278 emitcode("mov", "a,b");
7279 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7281 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7283 MOVB (aopGet (left, offset, FALSE, FALSE));
7284 MOVA (aopGet (right, offset, FALSE, FALSE));
7285 emitcode ("orl", "a,b");
7286 aopPut (result, "a", offset);
7288 else if (aopGetUsesAcc (left, offset))
7290 MOVA (aopGet (left, offset, FALSE, FALSE));
7291 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7292 aopPut (result, "a", offset);
7296 MOVA (aopGet (right, offset, FALSE, FALSE));
7297 if (IS_AOP_PREG (left))
7299 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7300 aopPut (result, "a", offset);
7304 emitcode ("orl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7312 // left & result in different registers
7313 if (AOP_TYPE (result) == AOP_CRY)
7316 // if(size), result in bit
7317 // if(!size && ifx), conditional oper: if(left | right)
7318 symbol *tlbl = newiTempLabel (NULL);
7319 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7321 emitcode ("setb", "c");
7324 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7325 && AOP_TYPE(left)==AOP_ACC)
7328 emitcode("mov", "a,b");
7329 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7331 else if (AOP_TYPE(left)==AOP_ACC)
7335 bool pushedB = pushB ();
7336 emitcode("mov", "b,a");
7337 MOVA (aopGet (right, offset, FALSE, FALSE));
7338 emitcode("orl", "a,b");
7343 MOVA (aopGet (right, offset, FALSE, FALSE));
7344 emitcode("orl", "a,b");
7347 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7349 MOVB (aopGet (left, offset, FALSE, FALSE));
7350 MOVA (aopGet (right, offset, FALSE, FALSE));
7351 emitcode ("orl", "a,b");
7353 else if (aopGetUsesAcc (left, offset))
7355 MOVA (aopGet (left, offset, FALSE, FALSE));
7356 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7360 MOVA (aopGet (right, offset, FALSE, FALSE));
7361 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7364 emitcode ("jnz", "%05d$", tlbl->key + 100);
7374 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7380 for (; (size--); offset++)
7383 // result = left | right
7384 if (AOP_TYPE (right) == AOP_LIT)
7386 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7390 aopGet (left, offset, FALSE, FALSE),
7394 else if (bytelit == 0x0FF)
7396 /* dummy read of volatile operand */
7397 if (isOperandVolatile (left, FALSE))
7398 MOVA (aopGet (left, offset, FALSE, FALSE));
7399 aopPut (result, "#0xff", offset);
7403 // faster than result <- left, orl result,right
7404 // and better if result is SFR
7405 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7406 && AOP_TYPE(left)==AOP_ACC)
7409 emitcode("mov", "a,b");
7410 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7412 else if (AOP_TYPE(left)==AOP_ACC)
7416 bool pushedB = pushB ();
7417 emitcode("mov", "b,a");
7418 MOVA (aopGet (right, offset, FALSE, FALSE));
7419 emitcode("orl", "a,b");
7424 MOVA (aopGet (right, offset, FALSE, FALSE));
7425 emitcode("orl", "a,b");
7428 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7430 MOVB (aopGet (left, offset, FALSE, FALSE));
7431 MOVA (aopGet (right, offset, FALSE, FALSE));
7432 emitcode ("orl", "a,b");
7434 else if (aopGetUsesAcc (left, offset))
7436 MOVA (aopGet (left, offset, FALSE, FALSE));
7437 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7441 MOVA (aopGet (right, offset, FALSE, FALSE));
7442 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7444 aopPut (result, "a", offset);
7450 freeAsmop (result, NULL, ic, TRUE);
7451 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7452 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7455 /*-----------------------------------------------------------------*/
7456 /* genXor - code for xclusive or */
7457 /*-----------------------------------------------------------------*/
7459 genXor (iCode * ic, iCode * ifx)
7461 operand *left, *right, *result;
7462 int size, offset = 0;
7463 unsigned long lit = 0L;
7466 D (emitcode (";", "genXor"));
7468 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7469 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7470 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7473 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
7475 AOP_TYPE (left), AOP_TYPE (right));
7476 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
7478 AOP_SIZE (left), AOP_SIZE (right));
7481 /* if left is a literal & right is not ||
7482 if left needs acc & right does not */
7483 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7484 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7486 operand *tmp = right;
7491 /* if result = right then exchange them */
7492 if (sameRegs (AOP (result), AOP (right)))
7494 operand *tmp = right;
7499 /* if right is bit then exchange them */
7500 if (AOP_TYPE (right) == AOP_CRY &&
7501 AOP_TYPE (left) != AOP_CRY)
7503 operand *tmp = right;
7508 if (AOP_TYPE (right) == AOP_LIT)
7509 lit = ulFromVal (AOP (right)->aopu.aop_lit);
7511 size = AOP_SIZE (result);
7515 if (AOP_TYPE (left) == AOP_CRY)
7517 if (AOP_TYPE (right) == AOP_LIT)
7519 // c = bit & literal;
7522 // lit>>1 != 0 => result = 1
7523 if (AOP_TYPE (result) == AOP_CRY)
7526 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7528 continueIfTrue (ifx);
7531 emitcode ("setb", "c");
7538 // lit == 0, result = left
7539 if (size && sameRegs (AOP (result), AOP (left)))
7541 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7545 // lit == 1, result = not(left)
7546 if (size && sameRegs (AOP (result), AOP (left)))
7548 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7553 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7554 emitcode ("cpl", "c");
7562 symbol *tlbl = newiTempLabel (NULL);
7563 if (AOP_TYPE (right) == AOP_CRY)
7566 if (IS_OP_ACCUSE (left))
7567 {// left already is in the carry
7568 operand *tmp = right;
7582 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7583 emitcode ("cpl", "c");
7591 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7592 genIfxJump (ifx, "c", left, right, result, ic->next);
7596 /* if left is same as result */
7597 if (sameRegs (AOP (result), AOP (left)))
7599 for (; size--; offset++)
7601 if (AOP_TYPE (right) == AOP_LIT)
7603 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7606 /* dummy read of volatile operand */
7607 if (isOperandVolatile (left, FALSE))
7608 MOVA (aopGet (left, offset, FALSE, FALSE));
7612 else if (IS_AOP_PREG (left))
7614 MOVA (aopGet (left, offset, FALSE, TRUE));
7615 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7616 aopPut (result, "a", offset);
7620 emitcode ("xrl", "%s,%s",
7621 aopGet (left, offset, FALSE, TRUE),
7622 aopGet (right, offset, FALSE, FALSE));
7627 if (AOP_TYPE (left) == AOP_ACC)
7630 emitcode("mov", "a,b");
7631 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7633 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7635 MOVB (aopGet (left, offset, FALSE, FALSE));
7636 MOVA (aopGet (right, offset, FALSE, FALSE));
7637 emitcode ("xrl", "a,b");
7638 aopPut (result, "a", offset);
7640 else if (aopGetUsesAcc (left, offset))
7642 MOVA (aopGet (left, offset, FALSE, FALSE));
7643 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7644 aopPut (result, "a", offset);
7648 MOVA (aopGet (right, offset, FALSE, FALSE));
7649 if (IS_AOP_PREG (left))
7651 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7652 aopPut (result, "a", offset);
7655 emitcode ("xrl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7662 // left & result in different registers
7663 if (AOP_TYPE (result) == AOP_CRY)
7666 // if(size), result in bit
7667 // if(!size && ifx), conditional oper: if(left ^ right)
7668 symbol *tlbl = newiTempLabel (NULL);
7669 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7672 emitcode ("setb", "c");
7675 if ((AOP_TYPE (right) == AOP_LIT) &&
7676 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7678 MOVA (aopGet (left, offset, FALSE, FALSE));
7680 else if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7681 && AOP_TYPE(left)==AOP_ACC)
7684 emitcode("mov", "a,b");
7685 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7687 else if (AOP_TYPE(left)==AOP_ACC)
7691 bool pushedB = pushB ();
7692 emitcode("mov", "b,a");
7693 MOVA (aopGet (right, offset, FALSE, FALSE));
7694 emitcode("xrl", "a,b");
7699 MOVA (aopGet (right, offset, FALSE, FALSE));
7700 emitcode("xrl", "a,b");
7703 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7705 MOVB (aopGet (left, offset, FALSE, FALSE));
7706 MOVA (aopGet (right, offset, FALSE, FALSE));
7707 emitcode ("xrl", "a,b");
7709 else if (aopGetUsesAcc (left, offset))
7711 MOVA (aopGet (left, offset, FALSE, FALSE));
7712 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7716 MOVA (aopGet (right, offset, FALSE, FALSE));
7717 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7720 emitcode ("jnz", "%05d$", tlbl->key + 100);
7730 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7734 for (; (size--); offset++)
7737 // result = left ^ right
7738 if (AOP_TYPE (right) == AOP_LIT)
7740 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7744 aopGet (left, offset, FALSE, FALSE),
7749 // faster than result <- left, xrl result,right
7750 // and better if result is SFR
7751 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7752 && AOP_TYPE(left)==AOP_ACC)
7755 emitcode("mov", "a,b");
7756 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7758 else if (AOP_TYPE(left)==AOP_ACC)
7762 bool pushedB = pushB ();
7763 emitcode("mov", "b,a");
7764 MOVA (aopGet (right, offset, FALSE, FALSE));
7765 emitcode("xrl", "a,b");
7770 MOVA (aopGet (right, offset, FALSE, FALSE));
7771 emitcode("xrl", "a,b");
7774 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7776 MOVB (aopGet (left, offset, FALSE, FALSE));
7777 MOVA (aopGet (right, offset, FALSE, FALSE));
7778 emitcode ("xrl", "a,b");
7780 else if (aopGetUsesAcc (left, offset))
7782 MOVA (aopGet (left, offset, FALSE, FALSE));
7783 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7787 MOVA (aopGet (right, offset, FALSE, FALSE));
7788 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7790 aopPut (result, "a", offset);
7796 freeAsmop (result, NULL, ic, TRUE);
7797 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7798 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7801 /*-----------------------------------------------------------------*/
7802 /* genInline - write the inline code out */
7803 /*-----------------------------------------------------------------*/
7805 genInline (iCode * ic)
7807 char *buffer, *bp, *bp1;
7808 bool inComment = FALSE;
7810 D (emitcode (";", "genInline"));
7812 _G.inLine += (!options.asmpeep);
7814 buffer = bp = bp1 = Safe_strdup (IC_INLINE (ic));
7816 /* emit each line as a code */
7834 /* Add \n for labels, not dirs such as c:\mydir */
7835 if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
7853 _G.inLine -= (!options.asmpeep);
7856 /*-----------------------------------------------------------------*/
7857 /* genRRC - rotate right with carry */
7858 /*-----------------------------------------------------------------*/
7862 operand *left, *result;
7866 D (emitcode (";", "genRRC"));
7868 /* rotate right with carry */
7869 left = IC_LEFT (ic);
7870 result = IC_RESULT (ic);
7871 aopOp (left, ic, FALSE);
7872 aopOp (result, ic, FALSE);
7874 /* move it to the result */
7875 size = AOP_SIZE (result);
7877 if (size == 1) { /* special case for 1 byte */
7878 l = aopGet (left, offset, FALSE, FALSE);
7880 emitcode ("rr", "a");
7883 /* no need to clear carry, bit7 will be written later */
7886 l = aopGet (left, offset, FALSE, FALSE);
7888 emitcode ("rrc", "a");
7889 if (AOP_SIZE (result) > 1)
7890 aopPut (result, "a", offset--);
7892 /* now we need to put the carry into the
7893 highest order byte of the result */
7894 if (AOP_SIZE (result) > 1)
7896 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7899 emitcode ("mov", "acc.7,c");
7901 aopPut (result, "a", AOP_SIZE (result) - 1);
7902 freeAsmop (result, NULL, ic, TRUE);
7903 freeAsmop (left, NULL, ic, TRUE);
7906 /*-----------------------------------------------------------------*/
7907 /* genRLC - generate code for rotate left with carry */
7908 /*-----------------------------------------------------------------*/
7912 operand *left, *result;
7916 D (emitcode (";", "genRLC"));
7918 /* rotate right with carry */
7919 left = IC_LEFT (ic);
7920 result = IC_RESULT (ic);
7921 aopOp (left, ic, FALSE);
7922 aopOp (result, ic, FALSE);
7924 /* move it to the result */
7925 size = AOP_SIZE (result);
7929 l = aopGet (left, offset, FALSE, FALSE);
7931 if (size == 0) { /* special case for 1 byte */
7935 emitcode("rlc","a"); /* bit0 will be written later */
7936 if (AOP_SIZE (result) > 1)
7938 aopPut (result, "a", offset++);
7943 l = aopGet (left, offset, FALSE, FALSE);
7945 emitcode ("rlc", "a");
7946 if (AOP_SIZE (result) > 1)
7947 aopPut (result, "a", offset++);
7950 /* now we need to put the carry into the
7951 highest order byte of the result */
7952 if (AOP_SIZE (result) > 1)
7954 l = aopGet (result, 0, FALSE, FALSE);
7957 emitcode ("mov", "acc.0,c");
7959 aopPut (result, "a", 0);
7960 freeAsmop (result, NULL, ic, TRUE);
7961 freeAsmop (left, NULL, ic, TRUE);
7964 /*-----------------------------------------------------------------*/
7965 /* genGetHbit - generates code get highest order bit */
7966 /*-----------------------------------------------------------------*/
7968 genGetHbit (iCode * ic)
7970 operand *left, *result;
7972 D (emitcode (";", "genGetHbit"));
7974 left = IC_LEFT (ic);
7975 result = IC_RESULT (ic);
7976 aopOp (left, ic, FALSE);
7977 aopOp (result, ic, FALSE);
7979 /* get the highest order byte into a */
7980 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7981 if (AOP_TYPE (result) == AOP_CRY)
7983 emitcode ("rlc", "a");
7988 emitcode ("rl", "a");
7989 emitcode ("anl", "a,#0x01");
7993 freeAsmop (result, NULL, ic, TRUE);
7994 freeAsmop (left, NULL, ic, TRUE);
7997 /*-----------------------------------------------------------------*/
7998 /* genGetAbit - generates code get a single bit */
7999 /*-----------------------------------------------------------------*/
8001 genGetAbit (iCode * ic)
8003 operand *left, *right, *result;
8006 D (emitcode (";", "genGetAbit"));
8008 left = IC_LEFT (ic);
8009 right = IC_RIGHT (ic);
8010 result = IC_RESULT (ic);
8011 aopOp (left, ic, FALSE);
8012 aopOp (right, ic, FALSE);
8013 aopOp (result, ic, FALSE);
8015 shCount = (int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
8017 /* get the needed byte into a */
8018 MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
8020 if (AOP_TYPE (result) == AOP_CRY)
8023 emitcode ("rlc", "a");
8024 else if ((shCount) == 0)
8025 emitcode ("rrc", "a");
8027 emitcode ("mov", "c,acc[%d]", shCount);
8035 emitcode ("rr", "a");
8038 emitcode ("rr", "a");
8041 emitcode ("anl", "a,#0x01");
8045 emitcode ("mov", "c,acc[%d]", shCount);
8046 emitcode ("clr", "a");
8047 emitcode ("rlc", "a");
8050 emitcode ("swap", "a");
8051 emitcode ("anl", "a,#0x01");
8054 emitcode ("rl", "a");
8057 emitcode ("rl", "a");
8058 emitcode ("anl", "a,#0x01");
8064 freeAsmop (result, NULL, ic, TRUE);
8065 freeAsmop (right, NULL, ic, TRUE);
8066 freeAsmop (left, NULL, ic, TRUE);
8069 /*-----------------------------------------------------------------*/
8070 /* genGetByte - generates code get a single byte */
8071 /*-----------------------------------------------------------------*/
8073 genGetByte (iCode * ic)
8075 operand *left, *right, *result;
8078 D (emitcode (";", "genGetByte"));
8080 left = IC_LEFT (ic);
8081 right = IC_RIGHT (ic);
8082 result = IC_RESULT (ic);
8083 aopOp (left, ic, FALSE);
8084 aopOp (right, ic, FALSE);
8085 aopOp (result, ic, FALSE);
8087 offset = (int) ulFromVal (AOP (right)->aopu.aop_lit) / 8;
8089 aopGet (left, offset, FALSE, FALSE),
8092 freeAsmop (result, NULL, ic, TRUE);
8093 freeAsmop (right, NULL, ic, TRUE);
8094 freeAsmop (left, NULL, ic, TRUE);
8097 /*-----------------------------------------------------------------*/
8098 /* genGetWord - generates code get two bytes */
8099 /*-----------------------------------------------------------------*/
8101 genGetWord (iCode * ic)
8103 operand *left, *right, *result;
8106 D (emitcode (";", "genGetWord"));
8108 left = IC_LEFT (ic);
8109 right = IC_RIGHT (ic);
8110 result = IC_RESULT (ic);
8111 aopOp (left, ic, FALSE);
8112 aopOp (right, ic, FALSE);
8113 aopOp (result, ic, FALSE);
8115 offset = (int) ulFromVal (AOP (right)->aopu.aop_lit) / 8;
8117 aopGet (left, offset, FALSE, FALSE),
8120 aopGet (left, offset+1, FALSE, FALSE),
8123 freeAsmop (result, NULL, ic, TRUE);
8124 freeAsmop (right, NULL, ic, TRUE);
8125 freeAsmop (left, NULL, ic, TRUE);
8128 /*-----------------------------------------------------------------*/
8129 /* genSwap - generates code to swap nibbles or bytes */
8130 /*-----------------------------------------------------------------*/
8132 genSwap (iCode * ic)
8134 operand *left, *result;
8136 D(emitcode (";", "genSwap"));
8138 left = IC_LEFT (ic);
8139 result = IC_RESULT (ic);
8140 aopOp (left, ic, FALSE);
8141 aopOp (result, ic, FALSE);
8143 switch (AOP_SIZE (left))
8145 case 1: /* swap nibbles in byte */
8146 MOVA (aopGet (left, 0, FALSE, FALSE));
8147 emitcode ("swap", "a");
8148 aopPut (result, "a", 0);
8150 case 2: /* swap bytes in word */
8151 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
8153 MOVA (aopGet (left, 0, FALSE, FALSE));
8154 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8155 aopPut (result, "a", 1);
8157 else if (operandsEqu (left, result))
8160 bool pushedB = FALSE, leftInB = FALSE;
8162 MOVA (aopGet (left, 0, FALSE, FALSE));
8163 if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
8166 emitcode ("mov", "b,a");
8170 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8171 aopPut (result, reg, 1);
8178 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8179 aopPut (result, aopGet (left, 0, FALSE, FALSE), 1);
8183 wassertl(FALSE, "unsupported SWAP operand size");
8186 freeAsmop (result, NULL, ic, TRUE);
8187 freeAsmop (left, NULL, ic, TRUE);
8190 /*-----------------------------------------------------------------*/
8191 /* AccRol - rotate left accumulator by known count */
8192 /*-----------------------------------------------------------------*/
8194 AccRol (int shCount)
8196 shCount &= 0x0007; // shCount : 0..7
8203 emitcode ("rl", "a");
8206 emitcode ("rl", "a");
8207 emitcode ("rl", "a");
8210 emitcode ("swap", "a");
8211 emitcode ("rr", "a");
8214 emitcode ("swap", "a");
8217 emitcode ("swap", "a");
8218 emitcode ("rl", "a");
8221 emitcode ("rr", "a");
8222 emitcode ("rr", "a");
8225 emitcode ("rr", "a");
8230 /*-----------------------------------------------------------------*/
8231 /* AccLsh - left shift accumulator by known count */
8232 /*-----------------------------------------------------------------*/
8234 AccLsh (int shCount)
8239 emitcode ("add", "a,acc");
8240 else if (shCount == 2)
8242 emitcode ("add", "a,acc");
8243 emitcode ("add", "a,acc");
8247 /* rotate left accumulator */
8249 /* and kill the lower order bits */
8250 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
8255 /*-----------------------------------------------------------------*/
8256 /* AccRsh - right shift accumulator by known count */
8257 /*-----------------------------------------------------------------*/
8259 AccRsh (int shCount)
8266 emitcode ("rrc", "a");
8270 /* rotate right accumulator */
8271 AccRol (8 - shCount);
8272 /* and kill the higher order bits */
8273 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8278 /*-----------------------------------------------------------------*/
8279 /* AccSRsh - signed right shift accumulator by known count */
8280 /*-----------------------------------------------------------------*/
8282 AccSRsh (int shCount)
8289 emitcode ("mov", "c,acc.7");
8290 emitcode ("rrc", "a");
8292 else if (shCount == 2)
8294 emitcode ("mov", "c,acc.7");
8295 emitcode ("rrc", "a");
8296 emitcode ("mov", "c,acc.7");
8297 emitcode ("rrc", "a");
8301 tlbl = newiTempLabel (NULL);
8302 /* rotate right accumulator */
8303 AccRol (8 - shCount);
8304 /* and kill the higher order bits */
8305 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8306 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8307 emitcode ("orl", "a,#0x%02x",
8308 (unsigned char) ~SRMask[shCount]);
8314 /*-----------------------------------------------------------------*/
8315 /* shiftR1Left2Result - shift right one byte from left to result */
8316 /*-----------------------------------------------------------------*/
8318 shiftR1Left2Result (operand * left, int offl,
8319 operand * result, int offr,
8320 int shCount, int sign)
8322 MOVA (aopGet (left, offl, FALSE, FALSE));
8323 /* shift right accumulator */
8328 aopPut (result, "a", offr);
8331 /*-----------------------------------------------------------------*/
8332 /* shiftL1Left2Result - shift left one byte from left to result */
8333 /*-----------------------------------------------------------------*/
8335 shiftL1Left2Result (operand * left, int offl,
8336 operand * result, int offr, int shCount)
8339 l = aopGet (left, offl, FALSE, FALSE);
8341 /* shift left accumulator */
8343 aopPut (result, "a", offr);
8346 /*-----------------------------------------------------------------*/
8347 /* movLeft2Result - move byte from left to result */
8348 /*-----------------------------------------------------------------*/
8350 movLeft2Result (operand * left, int offl,
8351 operand * result, int offr, int sign)
8354 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8356 l = aopGet (left, offl, FALSE, FALSE);
8358 if (*l == '@' && (IS_AOP_PREG (result)))
8360 emitcode ("mov", "a,%s", l);
8361 aopPut (result, "a", offr);
8367 aopPut (result, l, offr);
8371 /* MSB sign in acc.7 ! */
8372 if (getDataSize (left) == offl + 1)
8375 aopPut (result, "a", offr);
8382 /*-----------------------------------------------------------------*/
8383 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
8384 /*-----------------------------------------------------------------*/
8388 emitcode ("rrc", "a");
8389 emitcode ("xch", "a,%s", x);
8390 emitcode ("rrc", "a");
8391 emitcode ("xch", "a,%s", x);
8394 /*-----------------------------------------------------------------*/
8395 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
8396 /*-----------------------------------------------------------------*/
8400 emitcode ("xch", "a,%s", x);
8401 emitcode ("rlc", "a");
8402 emitcode ("xch", "a,%s", x);
8403 emitcode ("rlc", "a");
8406 /*-----------------------------------------------------------------*/
8407 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8408 /*-----------------------------------------------------------------*/
8412 emitcode ("xch", "a,%s", x);
8413 emitcode ("add", "a,acc");
8414 emitcode ("xch", "a,%s", x);
8415 emitcode ("rlc", "a");
8418 /*-----------------------------------------------------------------*/
8419 /* AccAXLsh - left shift a:x by known count (0..7) */
8420 /*-----------------------------------------------------------------*/
8422 AccAXLsh (char *x, int shCount)
8437 case 5: // AAAAABBB:CCCCCDDD
8439 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8441 emitcode ("anl", "a,#0x%02x",
8442 SLMask[shCount]); // BBB00000:CCCCCDDD
8444 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8446 AccRol (shCount); // DDDCCCCC:BBB00000
8448 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8450 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8452 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8454 emitcode ("anl", "a,#0x%02x",
8455 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8457 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8459 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8462 case 6: // AAAAAABB:CCCCCCDD
8463 emitcode ("anl", "a,#0x%02x",
8464 SRMask[shCount]); // 000000BB:CCCCCCDD
8465 emitcode ("mov", "c,acc.0"); // c = B
8466 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8468 AccAXRrl1 (x); // BCCCCCCD:D000000B
8469 AccAXRrl1 (x); // BBCCCCCC:DD000000
8471 emitcode("rrc","a");
8472 emitcode("xch","a,%s", x);
8473 emitcode("rrc","a");
8474 emitcode("mov","c,acc.0"); //<< get correct bit
8475 emitcode("xch","a,%s", x);
8477 emitcode("rrc","a");
8478 emitcode("xch","a,%s", x);
8479 emitcode("rrc","a");
8480 emitcode("xch","a,%s", x);
8483 case 7: // a:x <<= 7
8485 emitcode ("anl", "a,#0x%02x",
8486 SRMask[shCount]); // 0000000B:CCCCCCCD
8488 emitcode ("mov", "c,acc.0"); // c = B
8490 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
8492 AccAXRrl1 (x); // BCCCCCCC:D0000000
8500 /*-----------------------------------------------------------------*/
8501 /* AccAXRsh - right shift a:x known count (0..7) */
8502 /*-----------------------------------------------------------------*/
8504 AccAXRsh (char *x, int shCount)
8512 AccAXRrl1 (x); // 0->a:x
8517 AccAXRrl1 (x); // 0->a:x
8520 AccAXRrl1 (x); // 0->a:x
8525 case 5: // AAAAABBB:CCCCCDDD = a:x
8527 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8529 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8531 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8533 emitcode ("anl", "a,#0x%02x",
8534 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8536 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8538 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8540 emitcode ("anl", "a,#0x%02x",
8541 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8543 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8545 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8547 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8550 case 6: // AABBBBBB:CCDDDDDD
8552 emitcode ("mov", "c,acc.7");
8553 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8555 emitcode ("mov", "c,acc.7");
8556 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8558 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8560 emitcode ("anl", "a,#0x%02x",
8561 SRMask[shCount]); // 000000AA:BBBBBBCC
8564 case 7: // ABBBBBBB:CDDDDDDD
8566 emitcode ("mov", "c,acc.7"); // c = A
8568 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8570 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8572 emitcode ("anl", "a,#0x%02x",
8573 SRMask[shCount]); // 0000000A:BBBBBBBC
8581 /*-----------------------------------------------------------------*/
8582 /* AccAXRshS - right shift signed a:x known count (0..7) */
8583 /*-----------------------------------------------------------------*/
8585 AccAXRshS (char *x, int shCount)
8593 emitcode ("mov", "c,acc.7");
8594 AccAXRrl1 (x); // s->a:x
8598 emitcode ("mov", "c,acc.7");
8599 AccAXRrl1 (x); // s->a:x
8601 emitcode ("mov", "c,acc.7");
8602 AccAXRrl1 (x); // s->a:x
8607 case 5: // AAAAABBB:CCCCCDDD = a:x
8609 tlbl = newiTempLabel (NULL);
8610 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8612 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8614 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8616 emitcode ("anl", "a,#0x%02x",
8617 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8619 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8621 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8623 emitcode ("anl", "a,#0x%02x",
8624 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8626 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8628 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8630 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8632 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8633 emitcode ("orl", "a,#0x%02x",
8634 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8637 break; // SSSSAAAA:BBBCCCCC
8639 case 6: // AABBBBBB:CCDDDDDD
8641 tlbl = newiTempLabel (NULL);
8642 emitcode ("mov", "c,acc.7");
8643 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8645 emitcode ("mov", "c,acc.7");
8646 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8648 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8650 emitcode ("anl", "a,#0x%02x",
8651 SRMask[shCount]); // 000000AA:BBBBBBCC
8653 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8654 emitcode ("orl", "a,#0x%02x",
8655 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8659 case 7: // ABBBBBBB:CDDDDDDD
8661 tlbl = newiTempLabel (NULL);
8662 emitcode ("mov", "c,acc.7"); // c = A
8664 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8666 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8668 emitcode ("anl", "a,#0x%02x",
8669 SRMask[shCount]); // 0000000A:BBBBBBBC
8671 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8672 emitcode ("orl", "a,#0x%02x",
8673 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8682 /*-----------------------------------------------------------------*/
8683 /* shiftL2Left2Result - shift left two bytes from left to result */
8684 /*-----------------------------------------------------------------*/
8686 shiftL2Left2Result (operand * left, int offl,
8687 operand * result, int offr, int shCount)
8690 bool pushedB = FALSE;
8693 if (sameRegs (AOP (result), AOP (left)) &&
8694 ((offl + MSB16) == offr))
8696 /* don't crash result[offr] */
8697 MOVA (aopGet (left, offl, FALSE, FALSE));
8698 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8699 usedB = !strncmp(x, "b", 1);
8701 else if (aopGetUsesAcc (result, offr))
8703 movLeft2Result (left, offl, result, offr, 0);
8706 emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8707 MOVA (aopGet (result, offr, FALSE, FALSE));
8708 emitcode ("xch", "a,b");
8713 movLeft2Result (left, offl, result, offr, 0);
8714 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8715 x = aopGet (result, offr, FALSE, FALSE);
8717 /* ax << shCount (x = lsb(result)) */
8718 AccAXLsh (x, shCount);
8721 emitcode ("xch", "a,b");
8722 aopPut (result, "a", offr);
8723 aopPut (result, "b", offr + MSB16);
8728 aopPut (result, "a", offr + MSB16);
8733 /*-----------------------------------------------------------------*/
8734 /* shiftR2Left2Result - shift right two bytes from left to result */
8735 /*-----------------------------------------------------------------*/
8737 shiftR2Left2Result (operand * left, int offl,
8738 operand * result, int offr,
8739 int shCount, int sign)
8742 bool pushedB = FALSE;
8745 if (sameRegs (AOP (result), AOP (left)) &&
8746 ((offl + MSB16) == offr))
8748 /* don't crash result[offr] */
8749 MOVA (aopGet (left, offl, FALSE, FALSE));
8750 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8751 usedB = !strncmp(x, "b", 1);
8753 else if (aopGetUsesAcc (result, offr))
8755 movLeft2Result (left, offl, result, offr, 0);
8758 emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8759 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8764 movLeft2Result (left, offl, result, offr, 0);
8765 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8766 x = aopGet (result, offr, FALSE, FALSE);
8768 /* a:x >> shCount (x = lsb(result)) */
8770 AccAXRshS (x, shCount);
8772 AccAXRsh (x, shCount);
8775 emitcode ("xch", "a,b");
8776 aopPut (result, "a", offr);
8777 emitcode ("xch", "a,b");
8780 if (getDataSize (result) > 1)
8781 aopPut (result, "a", offr + MSB16);
8784 /*-----------------------------------------------------------------*/
8785 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8786 /*-----------------------------------------------------------------*/
8788 shiftLLeftOrResult (operand * left, int offl,
8789 operand * result, int offr, int shCount)
8791 MOVA (aopGet (left, offl, FALSE, FALSE));
8792 /* shift left accumulator */
8794 /* or with result */
8795 if (aopGetUsesAcc (result, offr))
8797 emitcode ("xch", "a,b");
8798 MOVA (aopGet (result, offr, FALSE, FALSE));
8799 emitcode ("orl", "a,b");
8803 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8805 /* back to result */
8806 aopPut (result, "a", offr);
8809 /*-----------------------------------------------------------------*/
8810 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8811 /*-----------------------------------------------------------------*/
8813 shiftRLeftOrResult (operand * left, int offl,
8814 operand * result, int offr, int shCount)
8816 MOVA (aopGet (left, offl, FALSE, FALSE));
8817 /* shift right accumulator */
8819 /* or with result */
8820 if (aopGetUsesAcc(result, offr))
8822 emitcode ("xch", "a,b");
8823 MOVA (aopGet (result, offr, FALSE, FALSE));
8824 emitcode ("orl", "a,b");
8828 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8830 /* back to result */
8831 aopPut (result, "a", offr);
8834 /*-----------------------------------------------------------------*/
8835 /* genlshOne - left shift a one byte quantity by known count */
8836 /*-----------------------------------------------------------------*/
8838 genlshOne (operand * result, operand * left, int shCount)
8840 D (emitcode (";", "genlshOne"));
8842 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8845 /*-----------------------------------------------------------------*/
8846 /* genlshTwo - left shift two bytes by known amount != 0 */
8847 /*-----------------------------------------------------------------*/
8849 genlshTwo (operand * result, operand * left, int shCount)
8853 D (emitcode (";", "genlshTwo"));
8855 size = getDataSize (result);
8857 /* if shCount >= 8 */
8866 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8870 movLeft2Result (left, LSB, result, MSB16, 0);
8873 aopPut (result, zero, LSB);
8876 /* 1 <= shCount <= 7 */
8880 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8882 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8886 /*-----------------------------------------------------------------*/
8887 /* shiftLLong - shift left one long from left to result */
8888 /* offl = LSB or MSB16 */
8889 /*-----------------------------------------------------------------*/
8891 shiftLLong (operand * left, operand * result, int offr)
8894 int size = AOP_SIZE (result);
8896 if (size >= LSB + offr)
8898 l = aopGet (left, LSB, FALSE, FALSE);
8900 emitcode ("add", "a,acc");
8901 if (sameRegs (AOP (left), AOP (result)) &&
8902 size >= MSB16 + offr && offr != LSB)
8903 xch_a_aopGet (left, LSB + offr, FALSE, FALSE);
8905 aopPut (result, "a", LSB + offr);
8908 if (size >= MSB16 + offr)
8910 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8912 l = aopGet (left, MSB16, FALSE, FALSE);
8915 emitcode ("rlc", "a");
8916 if (sameRegs (AOP (left), AOP (result)) &&
8917 size >= MSB24 + offr && offr != LSB)
8918 xch_a_aopGet (left, MSB16 + offr, FALSE, FALSE);
8920 aopPut (result, "a", MSB16 + offr);
8923 if (size >= MSB24 + offr)
8925 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8927 l = aopGet (left, MSB24, FALSE, FALSE);
8930 emitcode ("rlc", "a");
8931 if (sameRegs (AOP (left), AOP (result)) &&
8932 size >= MSB32 + offr && offr != LSB)
8933 xch_a_aopGet (left, MSB24 + offr, FALSE, FALSE);
8935 aopPut (result, "a", MSB24 + offr);
8938 if (size > MSB32 + offr)
8940 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8942 l = aopGet (left, MSB32, FALSE, FALSE);
8945 emitcode ("rlc", "a");
8946 aopPut (result, "a", MSB32 + offr);
8949 aopPut (result, zero, LSB);
8952 /*-----------------------------------------------------------------*/
8953 /* genlshFour - shift four byte by a known amount != 0 */
8954 /*-----------------------------------------------------------------*/
8956 genlshFour (operand * result, operand * left, int shCount)
8960 D (emitcode (";", "genlshFour"));
8962 size = AOP_SIZE (result);
8964 /* if shifting more that 3 bytes */
8969 /* lowest order of left goes to the highest
8970 order of the destination */
8971 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8973 movLeft2Result (left, LSB, result, MSB32, 0);
8974 aopPut (result, zero, LSB);
8975 aopPut (result, zero, MSB16);
8976 aopPut (result, zero, MSB24);
8980 /* more than two bytes */
8981 else if (shCount >= 16)
8983 /* lower order two bytes goes to higher order two bytes */
8985 /* if some more remaining */
8987 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8990 movLeft2Result (left, MSB16, result, MSB32, 0);
8991 movLeft2Result (left, LSB, result, MSB24, 0);
8993 aopPut (result, zero, MSB16);
8994 aopPut (result, zero, LSB);
8998 /* if more than 1 byte */
8999 else if (shCount >= 8)
9001 /* lower order three bytes goes to higher order three bytes */
9006 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
9008 movLeft2Result (left, LSB, result, MSB16, 0);
9014 movLeft2Result (left, MSB24, result, MSB32, 0);
9015 movLeft2Result (left, MSB16, result, MSB24, 0);
9016 movLeft2Result (left, LSB, result, MSB16, 0);
9017 aopPut (result, zero, LSB);
9019 else if (shCount == 1)
9020 shiftLLong (left, result, MSB16);
9023 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
9024 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
9025 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
9026 aopPut (result, zero, LSB);
9031 /* 1 <= shCount <= 7 */
9032 else if (shCount <= 2)
9034 shiftLLong (left, result, LSB);
9036 shiftLLong (result, result, LSB);
9038 /* 3 <= shCount <= 7, optimize */
9041 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
9042 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
9043 shiftL2Left2Result (left, LSB, result, LSB, shCount);
9047 /*-----------------------------------------------------------------*/
9048 /* genLeftShiftLiteral - left shifting by known count */
9049 /*-----------------------------------------------------------------*/
9051 genLeftShiftLiteral (operand * left,
9056 int shCount = (int) ulFromVal (AOP (right)->aopu.aop_lit);
9059 D (emitcode (";", "genLeftShiftLiteral"));
9061 freeAsmop (right, NULL, ic, TRUE);
9063 aopOp (left, ic, FALSE);
9064 aopOp (result, ic, FALSE);
9066 size = getSize (operandType (result));
9069 emitcode ("; shift left ", "result %d, left %d", size,
9073 /* I suppose that the left size >= result size */
9078 movLeft2Result (left, size, result, size, 0);
9081 else if (shCount >= (size * 8))
9085 aopPut (result, zero, size);
9093 genlshOne (result, left, shCount);
9097 genlshTwo (result, left, shCount);
9101 genlshFour (result, left, shCount);
9104 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9105 "*** ack! mystery literal shift!\n");
9109 freeAsmop (result, NULL, ic, TRUE);
9110 freeAsmop (left, NULL, ic, TRUE);
9113 /*-----------------------------------------------------------------*/
9114 /* genLeftShift - generates code for left shifting */
9115 /*-----------------------------------------------------------------*/
9117 genLeftShift (iCode * ic)
9119 operand *left, *right, *result;
9122 symbol *tlbl, *tlbl1;
9125 D (emitcode (";", "genLeftShift"));
9127 right = IC_RIGHT (ic);
9128 left = IC_LEFT (ic);
9129 result = IC_RESULT (ic);
9131 aopOp (right, ic, FALSE);
9133 /* if the shift count is known then do it
9134 as efficiently as possible */
9135 if (AOP_TYPE (right) == AOP_LIT)
9137 genLeftShiftLiteral (left, right, result, ic);
9141 /* shift count is unknown then we have to form
9142 a loop get the loop count in B : Note: we take
9143 only the lower order byte since shifting
9144 more that 32 bits make no sense anyway, ( the
9145 largest size of an object can be only 32 bits ) */
9148 MOVB (aopGet (right, 0, FALSE, FALSE));
9149 emitcode ("inc", "b");
9150 freeAsmop (right, NULL, ic, TRUE);
9151 aopOp (left, ic, FALSE);
9152 aopOp (result, ic, FALSE);
9154 /* now move the left to the result if they are not the same */
9155 if (!sameRegs (AOP (left), AOP (result)) &&
9156 AOP_SIZE (result) > 1)
9159 size = AOP_SIZE (result);
9163 l = aopGet (left, offset, FALSE, TRUE);
9164 if (*l == '@' && (IS_AOP_PREG (result)))
9167 emitcode ("mov", "a,%s", l);
9168 aopPut (result, "a", offset);
9171 aopPut (result, l, offset);
9176 tlbl = newiTempLabel (NULL);
9177 size = AOP_SIZE (result);
9179 tlbl1 = newiTempLabel (NULL);
9181 /* if it is only one byte then */
9184 symbol *tlbl1 = newiTempLabel (NULL);
9186 l = aopGet (left, 0, FALSE, FALSE);
9188 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9190 emitcode ("add", "a,acc");
9192 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9194 aopPut (result, "a", 0);
9198 reAdjustPreg (AOP (result));
9200 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9202 l = aopGet (result, offset, FALSE, FALSE);
9204 emitcode ("add", "a,acc");
9205 aopPut (result, "a", offset++);
9208 l = aopGet (result, offset, FALSE, FALSE);
9210 emitcode ("rlc", "a");
9211 aopPut (result, "a", offset++);
9213 reAdjustPreg (AOP (result));
9216 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9219 freeAsmop (result, NULL, ic, TRUE);
9220 freeAsmop (left, NULL, ic, TRUE);
9223 /*-----------------------------------------------------------------*/
9224 /* genrshOne - right shift a one byte quantity by known count */
9225 /*-----------------------------------------------------------------*/
9227 genrshOne (operand * result, operand * left,
9228 int shCount, int sign)
9230 D (emitcode (";", "genrshOne"));
9232 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9235 /*-----------------------------------------------------------------*/
9236 /* genrshTwo - right shift two bytes by known amount != 0 */
9237 /*-----------------------------------------------------------------*/
9239 genrshTwo (operand * result, operand * left,
9240 int shCount, int sign)
9242 D (emitcode (";", "genrshTwo"));
9244 /* if shCount >= 8 */
9249 shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
9251 movLeft2Result (left, MSB16, result, LSB, sign);
9252 addSign (result, MSB16, sign);
9255 /* 1 <= shCount <= 7 */
9257 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9260 /*-----------------------------------------------------------------*/
9261 /* shiftRLong - shift right one long from left to result */
9262 /* offl = LSB or MSB16 */
9263 /*-----------------------------------------------------------------*/
9265 shiftRLong (operand * left, int offl,
9266 operand * result, int sign)
9268 bool overlapping = regsInCommon (left, result) || operandsEqu(left, result);
9270 if (overlapping && offl>1)
9272 // we are in big trouble, but this shouldn't happen
9273 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9276 MOVA (aopGet (left, MSB32, FALSE, FALSE));
9283 emitcode ("rlc", "a");
9284 emitcode ("subb", "a,acc");
9285 if (overlapping && sameByte (AOP (left), MSB32, AOP (result), MSB32))
9287 xch_a_aopGet (left, MSB32, FALSE, FALSE);
9291 aopPut (result, "a", MSB32);
9292 MOVA (aopGet (left, MSB32, FALSE, FALSE));
9297 if (aopPutUsesAcc (result, zero, MSB32))
9299 emitcode("xch", "a,b");
9300 aopPut (result, zero, MSB32);
9301 emitcode("xch", "a,b");
9305 aopPut (result, zero, MSB32);
9312 emitcode ("clr", "c");
9316 emitcode ("mov", "c,acc.7");
9319 emitcode ("rrc", "a");
9321 if (overlapping && offl==MSB16 &&
9322 sameByte (AOP (left), MSB24, AOP (result), MSB32-offl))
9324 xch_a_aopGet (left, MSB24, FALSE, FALSE);
9328 aopPut (result, "a", MSB32 - offl);
9329 MOVA (aopGet (left, MSB24, FALSE, FALSE));
9332 emitcode ("rrc", "a");
9333 if (overlapping && offl==MSB16 &&
9334 sameByte (AOP (left), MSB16, AOP (result), MSB24-offl))
9336 xch_a_aopGet (left, MSB16, FALSE, FALSE);
9340 aopPut (result, "a", MSB24 - offl);
9341 MOVA (aopGet (left, MSB16, FALSE, FALSE));
9344 emitcode ("rrc", "a");
9347 aopPut (result, "a", MSB16 - offl);
9352 sameByte (AOP (left), LSB, AOP (result), MSB16-offl))
9354 xch_a_aopGet (left, LSB, FALSE, FALSE);
9358 aopPut (result, "a", MSB16 - offl);
9359 MOVA (aopGet (left, LSB, FALSE, FALSE));
9361 emitcode ("rrc", "a");
9362 aopPut (result, "a", LSB);
9366 /*-----------------------------------------------------------------*/
9367 /* genrshFour - shift four byte by a known amount != 0 */
9368 /*-----------------------------------------------------------------*/
9370 genrshFour (operand * result, operand * left,
9371 int shCount, int sign)
9373 D (emitcode (";", "genrshFour"));
9375 /* if shifting more that 3 bytes */
9380 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9382 movLeft2Result (left, MSB32, result, LSB, sign);
9383 addSign (result, MSB16, sign);
9385 else if (shCount >= 16)
9389 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9392 movLeft2Result (left, MSB24, result, LSB, 0);
9393 movLeft2Result (left, MSB32, result, MSB16, sign);
9395 addSign (result, MSB24, sign);
9397 else if (shCount >= 8)
9402 shiftRLong (left, MSB16, result, sign);
9404 else if (shCount == 0)
9406 movLeft2Result (left, MSB16, result, LSB, 0);
9407 movLeft2Result (left, MSB24, result, MSB16, 0);
9408 movLeft2Result (left, MSB32, result, MSB24, sign);
9409 addSign (result, MSB32, sign);
9413 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9414 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9415 /* the last shift is signed */
9416 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9417 addSign (result, MSB32, sign);
9422 /* 1 <= shCount <= 7 */
9425 shiftRLong (left, LSB, result, sign);
9427 shiftRLong (result, LSB, result, sign);
9431 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9432 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9433 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9438 /*-----------------------------------------------------------------*/
9439 /* genRightShiftLiteral - right shifting by known count */
9440 /*-----------------------------------------------------------------*/
9442 genRightShiftLiteral (operand * left,
9448 int shCount = (int) ulFromVal (AOP (right)->aopu.aop_lit);
9451 D (emitcode (";", "genRightShiftLiteral"));
9453 freeAsmop (right, NULL, ic, TRUE);
9455 aopOp (left, ic, FALSE);
9456 aopOp (result, ic, FALSE);
9459 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9463 size = getDataSize (left);
9464 /* test the LEFT size !!! */
9466 /* I suppose that the left size >= result size */
9469 size = getDataSize (result);
9471 movLeft2Result (left, size, result, size, 0);
9473 else if (shCount >= (size * 8))
9477 /* get sign in acc.7 */
9478 MOVA (aopGet (left, size - 1, FALSE, FALSE));
9480 addSign (result, LSB, sign);
9487 genrshOne (result, left, shCount, sign);
9491 genrshTwo (result, left, shCount, sign);
9495 genrshFour (result, left, shCount, sign);
9501 freeAsmop (result, NULL, ic, TRUE);
9502 freeAsmop (left, NULL, ic, TRUE);
9505 /*-----------------------------------------------------------------*/
9506 /* genSignedRightShift - right shift of signed number */
9507 /*-----------------------------------------------------------------*/
9509 genSignedRightShift (iCode * ic)
9511 operand *right, *left, *result;
9514 symbol *tlbl, *tlbl1;
9517 D (emitcode (";", "genSignedRightShift"));
9519 /* we do it the hard way put the shift count in b
9520 and loop thru preserving the sign */
9522 right = IC_RIGHT (ic);
9523 left = IC_LEFT (ic);
9524 result = IC_RESULT (ic);
9526 aopOp (right, ic, FALSE);
9529 if (AOP_TYPE (right) == AOP_LIT)
9531 genRightShiftLiteral (left, right, result, ic, 1);
9534 /* shift count is unknown then we have to form
9535 a loop get the loop count in B : Note: we take
9536 only the lower order byte since shifting
9537 more that 32 bits make no sense anyway, ( the
9538 largest size of an object can be only 32 bits ) */
9541 MOVB (aopGet (right, 0, FALSE, FALSE));
9542 emitcode ("inc", "b");
9543 freeAsmop (right, NULL, ic, TRUE);
9544 aopOp (left, ic, FALSE);
9545 aopOp (result, ic, FALSE);
9547 /* now move the left to the result if they are not the
9549 if (!sameRegs (AOP (left), AOP (result)) &&
9550 AOP_SIZE (result) > 1)
9553 size = AOP_SIZE (result);
9557 l = aopGet (left, offset, FALSE, TRUE);
9558 if (*l == '@' && IS_AOP_PREG (result))
9561 emitcode ("mov", "a,%s", l);
9562 aopPut (result, "a", offset);
9565 aopPut (result, l, offset);
9570 /* mov the highest order bit to OVR */
9571 tlbl = newiTempLabel (NULL);
9572 tlbl1 = newiTempLabel (NULL);
9574 size = AOP_SIZE (result);
9576 MOVA (aopGet (left, offset, FALSE, FALSE));
9577 emitcode ("rlc", "a");
9578 emitcode ("mov", "ov,c");
9579 /* if it is only one byte then */
9582 l = aopGet (left, 0, FALSE, FALSE);
9584 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9586 emitcode ("mov", "c,ov");
9587 emitcode ("rrc", "a");
9589 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9591 aopPut (result, "a", 0);
9595 reAdjustPreg (AOP (result));
9596 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9598 emitcode ("mov", "c,ov");
9601 l = aopGet (result, offset, FALSE, FALSE);
9603 emitcode ("rrc", "a");
9604 aopPut (result, "a", offset--);
9606 reAdjustPreg (AOP (result));
9608 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9612 freeAsmop (result, NULL, ic, TRUE);
9613 freeAsmop (left, NULL, ic, TRUE);
9616 /*-----------------------------------------------------------------*/
9617 /* genRightShift - generate code for right shifting */
9618 /*-----------------------------------------------------------------*/
9620 genRightShift (iCode * ic)
9622 operand *right, *left, *result;
9626 symbol *tlbl, *tlbl1;
9629 D (emitcode (";", "genRightShift"));
9631 /* if signed then we do it the hard way preserve the
9632 sign bit moving it inwards */
9633 letype = getSpec (operandType (IC_LEFT (ic)));
9635 if (!SPEC_USIGN (letype))
9637 genSignedRightShift (ic);
9641 /* signed & unsigned types are treated the same : i.e. the
9642 signed is NOT propagated inwards : quoting from the
9643 ANSI - standard : "for E1 >> E2, is equivalent to division
9644 by 2**E2 if unsigned or if it has a non-negative value,
9645 otherwise the result is implementation defined ", MY definition
9646 is that the sign does not get propagated */
9648 right = IC_RIGHT (ic);
9649 left = IC_LEFT (ic);
9650 result = IC_RESULT (ic);
9652 aopOp (right, ic, FALSE);
9654 /* if the shift count is known then do it
9655 as efficiently as possible */
9656 if (AOP_TYPE (right) == AOP_LIT)
9658 genRightShiftLiteral (left, right, result, ic, 0);
9662 /* shift count is unknown then we have to form
9663 a loop get the loop count in B : Note: we take
9664 only the lower order byte since shifting
9665 more that 32 bits make no sense anyway, ( the
9666 largest size of an object can be only 32 bits ) */
9669 MOVB (aopGet (right, 0, FALSE, FALSE));
9670 emitcode ("inc", "b");
9671 freeAsmop (right, NULL, ic, TRUE);
9672 aopOp (left, ic, FALSE);
9673 aopOp (result, ic, FALSE);
9675 /* now move the left to the result if they are not the
9677 if (!sameRegs (AOP (left), AOP (result)) &&
9678 AOP_SIZE (result) > 1)
9680 size = AOP_SIZE (result);
9684 l = aopGet (left, offset, FALSE, TRUE);
9685 if (*l == '@' && IS_AOP_PREG (result))
9688 emitcode ("mov", "a,%s", l);
9689 aopPut (result, "a", offset);
9692 aopPut (result, l, offset);
9697 tlbl = newiTempLabel (NULL);
9698 tlbl1 = newiTempLabel (NULL);
9699 size = AOP_SIZE (result);
9702 /* if it is only one byte then */
9705 l = aopGet (left, 0, FALSE, FALSE);
9707 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9710 emitcode ("rrc", "a");
9712 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9714 aopPut (result, "a", 0);
9718 reAdjustPreg (AOP (result));
9719 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9724 l = aopGet (result, offset, FALSE, FALSE);
9726 emitcode ("rrc", "a");
9727 aopPut (result, "a", offset--);
9729 reAdjustPreg (AOP (result));
9732 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9736 freeAsmop (result, NULL, ic, TRUE);
9737 freeAsmop (left, NULL, ic, TRUE);
9740 /*-----------------------------------------------------------------*/
9741 /* emitPtrByteGet - emits code to get a byte into A through a */
9742 /* pointer register (R0, R1, or DPTR). The */
9743 /* original value of A can be preserved in B. */
9744 /*-----------------------------------------------------------------*/
9746 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9753 emitcode ("mov", "b,a");
9754 emitcode ("mov", "a,@%s", rname);
9759 emitcode ("mov", "b,a");
9760 emitcode ("movx", "a,@%s", rname);
9765 emitcode ("mov", "b,a");
9766 emitcode ("movx", "a,@dptr");
9771 emitcode ("mov", "b,a");
9772 emitcode ("clr", "a");
9773 emitcode ("movc", "a,@a+dptr");
9779 emitcode ("push", "b");
9780 emitcode ("push", "acc");
9782 emitcode ("lcall", "__gptrget");
9784 emitcode ("pop", "b");
9789 /*-----------------------------------------------------------------*/
9790 /* emitPtrByteSet - emits code to set a byte from src through a */
9791 /* pointer register (R0, R1, or DPTR). */
9792 /*-----------------------------------------------------------------*/
9794 emitPtrByteSet (char *rname, int p_type, char *src)
9803 emitcode ("mov", "@%s,a", rname);
9806 emitcode ("mov", "@%s,%s", rname, src);
9811 emitcode ("movx", "@%s,a", rname);
9816 emitcode ("movx", "@dptr,a");
9821 emitcode ("lcall", "__gptrput");
9826 /*-----------------------------------------------------------------*/
9827 /* genUnpackBits - generates code for unpacking bits */
9828 /*-----------------------------------------------------------------*/
9830 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9832 int offset = 0; /* result byte offset */
9833 int rsize; /* result size */
9834 int rlen = 0; /* remaining bitfield length */
9835 sym_link *etype; /* bitfield type information */
9836 int blen; /* bitfield length */
9837 int bstr; /* bitfield starting bit within byte */
9838 static char* const accBits[] = {"acc.0", "acc.1", "acc.2", "acc.3",
9839 "acc.4", "acc.5", "acc.6", "acc.7"};
9841 D(emitcode (";", "genUnpackBits"));
9843 etype = getSpec (operandType (result));
9844 rsize = getSize (operandType (result));
9845 blen = SPEC_BLEN (etype);
9846 bstr = SPEC_BSTR (etype);
9848 if (ifx && blen <= 8)
9850 emitPtrByteGet (rname, ptype, FALSE);
9853 return accBits[bstr];;
9858 emitcode ("anl", "a,#0x%02x",
9859 (((unsigned char) -1) >> (8 - blen)) << bstr);
9865 /* If the bitfield length is less than a byte */
9868 emitPtrByteGet (rname, ptype, FALSE);
9870 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9871 if (!SPEC_USIGN (etype))
9873 /* signed bitfield */
9874 symbol *tlbl = newiTempLabel (NULL);
9876 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9877 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9880 aopPut (result, "a", offset++);
9884 /* Bit field did not fit in a byte. Copy all
9885 but the partial byte at the end. */
9886 for (rlen=blen;rlen>=8;rlen-=8)
9888 emitPtrByteGet (rname, ptype, FALSE);
9889 aopPut (result, "a", offset++);
9891 emitcode ("inc", "%s", rname);
9894 /* Handle the partial byte at the end */
9897 emitPtrByteGet (rname, ptype, FALSE);
9898 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9899 if (!SPEC_USIGN (etype))
9901 /* signed bitfield */
9902 symbol *tlbl = newiTempLabel (NULL);
9904 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9905 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9908 aopPut (result, "a", offset++);
9916 if (SPEC_USIGN (etype))
9920 /* signed bitfield: sign extension with 0x00 or 0xff */
9921 emitcode ("rlc", "a");
9922 emitcode ("subb", "a,acc");
9928 aopPut (result, source, offset++);
9934 /*-----------------------------------------------------------------*/
9935 /* genDataPointerGet - generates code when ptr offset is known */
9936 /*-----------------------------------------------------------------*/
9938 genDataPointerGet (operand * left,
9944 int size, offset = 0;
9946 D (emitcode (";", "genDataPointerGet"));
9948 aopOp (result, ic, TRUE);
9950 /* get the string representation of the name */
9951 l = aopGet (left, 0, FALSE, TRUE);
9953 size = AOP_SIZE (result);
9958 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
9962 SNPRINTF (buffer, sizeof(buffer), "%s", l);
9964 aopPut (result, buffer, offset++);
9967 freeAsmop (result, NULL, ic, TRUE);
9968 freeAsmop (left, NULL, ic, TRUE);
9971 /*-----------------------------------------------------------------*/
9972 /* genNearPointerGet - emitcode for near pointer fetch */
9973 /*-----------------------------------------------------------------*/
9975 genNearPointerGet (operand * left,
9984 char *ifxCond = "a";
9985 sym_link *rtype, *retype;
9986 sym_link *ltype = operandType (left);
9988 D (emitcode (";", "genNearPointerGet"));
9990 rtype = operandType (result);
9991 retype = getSpec (rtype);
9993 aopOp (left, ic, FALSE);
9995 /* if left is rematerialisable and
9996 result is not bitfield variable type and
9997 the left is pointer to data space i.e
9998 lower 128 bytes of space */
9999 if (AOP_TYPE (left) == AOP_IMMD &&
10000 !IS_BITFIELD (retype) &&
10001 DCL_TYPE (ltype) == POINTER)
10003 genDataPointerGet (left, result, ic);
10007 //aopOp (result, ic, FALSE);
10008 aopOp (result, ic, result?TRUE:FALSE);
10010 /* if the value is already in a pointer register
10011 then don't need anything more */
10012 if (!AOP_INPREG (AOP (left)))
10014 if (IS_AOP_PREG (left))
10016 // Aha, it is a pointer, just in disguise.
10017 rname = aopGet (left, 0, FALSE, FALSE);
10018 if (strcmp (rname, "a") == 0)
10020 // It's in pdata or on xstack
10021 rname = AOP (left)->aopu.aop_ptr->name;
10022 emitcode ("mov", "%s,a", rname);
10024 else if (*rname != '@')
10026 fprintf(stderr, "probable internal error: unexpected rname '%s' @ %s:%d\n",
10027 rname, __FILE__, __LINE__);
10032 emitcode ("mov", "a%s,%s", rname + 1, rname);
10033 rname++; // skip the '@'.
10038 /* otherwise get a free pointer register */
10039 aop = newAsmop (0);
10040 preg = getFreePtr (ic, &aop, FALSE);
10041 emitcode ("mov", "%s,%s",
10043 aopGet (left, 0, FALSE, TRUE));
10044 rname = preg->name;
10048 rname = aopGet (left, 0, FALSE, FALSE);
10050 /* if bitfield then unpack the bits */
10051 if (IS_BITFIELD (retype))
10052 ifxCond = genUnpackBits (result, rname, POINTER, ifx);
10055 /* we have can just get the values */
10056 int size = AOP_SIZE (result);
10061 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
10064 emitcode ("mov", "a,@%s", rname);
10066 aopPut (result, "a", offset);
10072 SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
10073 aopPut (result, buffer, offset);
10077 emitcode ("inc", "%s", rname);
10081 /* now some housekeeping stuff */
10082 if (aop) /* we had to allocate for this iCode */
10084 if (pi) { /* post increment present */
10085 aopPut (left, rname, 0);
10087 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
10091 /* we did not allocate which means left
10092 already in a pointer register, then
10093 if size > 0 && this could be used again
10094 we have to point it back to where it
10096 if ((AOP_SIZE (result) > 1 &&
10097 !OP_SYMBOL (left)->remat &&
10098 (OP_SYMBOL (left)->liveTo > ic->seq ||
10102 int size = AOP_SIZE (result) - 1;
10104 emitcode ("dec", "%s", rname);
10108 if (ifx && !ifx->generated)
10110 genIfxJump (ifx, ifxCond, left, NULL, result, ic->next);
10114 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
10115 freeAsmop (left, NULL, ic, TRUE);
10116 if (pi) pi->generated = 1;
10119 /*-----------------------------------------------------------------*/
10120 /* genPagedPointerGet - emitcode for paged pointer fetch */
10121 /*-----------------------------------------------------------------*/
10123 genPagedPointerGet (operand * left,
10132 char *ifxCond = "a";
10133 sym_link *rtype, *retype;
10135 D (emitcode (";", "genPagedPointerGet"));
10137 rtype = operandType (result);
10138 retype = getSpec (rtype);
10140 aopOp (left, ic, FALSE);
10142 aopOp (result, ic, FALSE);
10144 /* if the value is already in a pointer register
10145 then don't need anything more */
10146 if (!AOP_INPREG (AOP (left)))
10148 /* otherwise get a free pointer register */
10149 aop = newAsmop (0);
10150 preg = getFreePtr (ic, &aop, FALSE);
10151 emitcode ("mov", "%s,%s",
10153 aopGet (left, 0, FALSE, TRUE));
10154 rname = preg->name;
10157 rname = aopGet (left, 0, FALSE, FALSE);
10159 /* if bitfield then unpack the bits */
10160 if (IS_BITFIELD (retype))
10161 ifxCond = genUnpackBits (result, rname, PPOINTER, ifx);
10164 /* we have can just get the values */
10165 int size = AOP_SIZE (result);
10171 emitcode ("movx", "a,@%s", rname);
10173 aopPut (result, "a", offset);
10178 emitcode ("inc", "%s", rname);
10182 /* now some housekeeping stuff */
10183 if (aop) /* we had to allocate for this iCode */
10186 aopPut (left, rname, 0);
10187 freeAsmop (NULL, aop, ic, TRUE);
10191 /* we did not allocate which means left
10192 already in a pointer register, then
10193 if size > 0 && this could be used again
10194 we have to point it back to where it
10196 if ((AOP_SIZE (result) > 1 &&
10197 !OP_SYMBOL (left)->remat &&
10198 (OP_SYMBOL (left)->liveTo > ic->seq ||
10202 int size = AOP_SIZE (result) - 1;
10204 emitcode ("dec", "%s", rname);
10208 if (ifx && !ifx->generated)
10210 genIfxJump (ifx, ifxCond, left, NULL, result, ic->next);
10214 freeAsmop (result, NULL, ic, TRUE);
10215 freeAsmop (left, NULL, ic, TRUE);
10216 if (pi) pi->generated = 1;
10219 /*--------------------------------------------------------------------*/
10220 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
10221 /*--------------------------------------------------------------------*/
10223 loadDptrFromOperand (operand *op, bool loadBToo)
10225 if (AOP_TYPE (op) != AOP_STR)
10227 /* if this is rematerializable */
10228 if (AOP_TYPE (op) == AOP_IMMD)
10230 emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
10233 if (AOP(op)->aopu.aop_immd.from_cast_remat)
10234 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
10237 wassertl(FALSE, "need pointerCode");
10238 emitcode (";", "mov b,???");
10239 /* genPointerGet and genPointerSet originally did different
10240 ** things for this case. Both seem wrong.
10241 ** from genPointerGet:
10242 ** emitcode ("mov", "b,#%d", pointerCode (retype));
10243 ** from genPointerSet:
10244 ** emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
10249 else if (AOP_TYPE (op) == AOP_DPTR)
10253 MOVA (aopGet (op, 0, FALSE, FALSE));
10254 emitcode ("push", "acc");
10255 MOVA (aopGet (op, 1, FALSE, FALSE));
10256 emitcode ("push", "acc");
10257 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10258 emitcode ("pop", "dph");
10259 emitcode ("pop", "dpl");
10263 MOVA (aopGet (op, 0, FALSE, FALSE));
10264 emitcode ("push", "acc");
10265 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10266 emitcode ("pop", "dpl");
10270 { /* we need to get it byte by byte */
10271 emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
10272 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10274 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10279 /*-----------------------------------------------------------------*/
10280 /* genFarPointerGet - get value from far space */
10281 /*-----------------------------------------------------------------*/
10283 genFarPointerGet (operand * left,
10284 operand * result, iCode * ic, iCode * pi, iCode * ifx)
10287 char *ifxCond = "a";
10288 sym_link *retype = getSpec (operandType (result));
10290 D (emitcode (";", "genFarPointerGet"));
10292 aopOp (left, ic, FALSE);
10293 loadDptrFromOperand (left, FALSE);
10295 /* so dptr now contains the address */
10296 aopOp (result, ic, FALSE);
10298 /* if bit then unpack */
10299 if (IS_BITFIELD (retype))
10300 ifxCond = genUnpackBits (result, "dptr", FPOINTER, ifx);
10303 size = AOP_SIZE (result);
10308 emitcode ("movx", "a,@dptr");
10310 aopPut (result, "a", offset++);
10312 emitcode ("inc", "dptr");
10316 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10318 aopPut (left, "dpl", 0);
10319 aopPut (left, "dph", 1);
10323 if (ifx && !ifx->generated)
10325 genIfxJump (ifx, ifxCond, left, NULL, result, ic->next);
10328 freeAsmop (result, NULL, ic, TRUE);
10329 freeAsmop (left, NULL, ic, TRUE);
10332 /*-----------------------------------------------------------------*/
10333 /* genCodePointerGet - get value from code space */
10334 /*-----------------------------------------------------------------*/
10336 genCodePointerGet (operand * left,
10337 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10340 char *ifxCond = "a";
10341 sym_link *retype = getSpec (operandType (result));
10343 D (emitcode (";", "genCodePointerGet"));
10345 aopOp (left, ic, FALSE);
10346 loadDptrFromOperand (left, FALSE);
10348 /* so dptr now contains the address */
10349 aopOp (result, ic, FALSE);
10351 /* if bit then unpack */
10352 if (IS_BITFIELD (retype))
10353 ifxCond = genUnpackBits (result, "dptr", CPOINTER, ifx);
10356 size = AOP_SIZE (result);
10361 emitcode ("clr", "a");
10362 emitcode ("movc", "a,@a+dptr");
10364 aopPut (result, "a", offset++);
10366 emitcode ("inc", "dptr");
10370 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10372 aopPut (left, "dpl", 0);
10373 aopPut (left, "dph", 1);
10377 if (ifx && !ifx->generated)
10379 genIfxJump (ifx, ifxCond, left, NULL, result, ic->next);
10382 freeAsmop (result, NULL, ic, TRUE);
10383 freeAsmop (left, NULL, ic, TRUE);
10386 /*-----------------------------------------------------------------*/
10387 /* genGenPointerGet - get value from generic pointer space */
10388 /*-----------------------------------------------------------------*/
10390 genGenPointerGet (operand * left,
10391 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10394 char *ifxCond = "a";
10395 sym_link *retype = getSpec (operandType (result));
10397 D (emitcode (";", "genGenPointerGet"));
10399 aopOp (left, ic, FALSE);
10400 loadDptrFromOperand (left, TRUE);
10402 /* so dptr now contains the address */
10403 aopOp (result, ic, FALSE);
10405 /* if bit then unpack */
10406 if (IS_BITFIELD (retype))
10408 ifxCond = genUnpackBits (result, "dptr", GPOINTER, ifx);
10412 size = AOP_SIZE (result);
10417 emitcode ("lcall", "__gptrget");
10419 aopPut (result, "a", offset++);
10421 emitcode ("inc", "dptr");
10425 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10427 aopPut (left, "dpl", 0);
10428 aopPut (left, "dph", 1);
10432 if (ifx && !ifx->generated)
10434 genIfxJump (ifx, ifxCond, left, NULL, result, ic->next);
10437 freeAsmop (result, NULL, ic, TRUE);
10438 freeAsmop (left, NULL, ic, TRUE);
10441 /*-----------------------------------------------------------------*/
10442 /* genPointerGet - generate code for pointer get */
10443 /*-----------------------------------------------------------------*/
10445 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
10447 operand *left, *result;
10448 sym_link *type, *etype;
10451 D (emitcode (";", "genPointerGet"));
10453 left = IC_LEFT (ic);
10454 result = IC_RESULT (ic);
10456 if (getSize (operandType (result))>1)
10459 /* depending on the type of pointer we need to
10460 move it to the correct pointer register */
10461 type = operandType (left);
10462 etype = getSpec (type);
10463 /* if left is of type of pointer then it is simple */
10464 if (IS_PTR (type) && !IS_FUNC (type->next))
10466 p_type = DCL_TYPE (type);
10470 /* we have to go by the storage class */
10471 p_type = PTR_TYPE (SPEC_OCLS (etype));
10474 /* special case when cast remat */
10475 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10476 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10478 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10479 type = operandType (left);
10480 p_type = DCL_TYPE (type);
10482 /* now that we have the pointer type we assign
10483 the pointer values */
10489 genNearPointerGet (left, result, ic, pi, ifx);
10493 genPagedPointerGet (left, result, ic, pi, ifx);
10497 genFarPointerGet (left, result, ic, pi, ifx);
10501 genCodePointerGet (left, result, ic, pi, ifx);
10505 genGenPointerGet (left, result, ic, pi, ifx);
10511 /*-----------------------------------------------------------------*/
10512 /* genPackBits - generates code for packed bit storage */
10513 /*-----------------------------------------------------------------*/
10515 genPackBits (sym_link * etype,
10517 char *rname, int p_type)
10519 int offset = 0; /* source byte offset */
10520 int rlen = 0; /* remaining bitfield length */
10521 int blen; /* bitfield length */
10522 int bstr; /* bitfield starting bit within byte */
10523 int litval; /* source literal value (if AOP_LIT) */
10524 unsigned char mask; /* bitmask within current byte */
10526 D(emitcode (";", "genPackBits"));
10528 blen = SPEC_BLEN (etype);
10529 bstr = SPEC_BSTR (etype);
10531 /* If the bitfield length is less than a byte */
10534 mask = ((unsigned char) (0xFF << (blen + bstr)) |
10535 (unsigned char) (0xFF >> (8 - bstr)));
10537 if (AOP_TYPE (right) == AOP_LIT)
10539 /* Case with a bitfield length <8 and literal source
10541 litval = (int) ulFromVal (AOP (right)->aopu.aop_lit);
10543 litval &= (~mask) & 0xff;
10544 emitPtrByteGet (rname, p_type, FALSE);
10545 if ((mask|litval)!=0xff)
10546 emitcode ("anl","a,#0x%02x", mask);
10548 emitcode ("orl","a,#0x%02x", litval);
10552 if ((blen==1) && (p_type!=GPOINTER))
10554 /* Case with a bitfield length == 1 and no generic pointer
10556 if (AOP_TYPE (right) == AOP_CRY)
10557 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10560 MOVA (aopGet (right, 0, FALSE, FALSE));
10561 emitcode ("rrc","a");
10563 emitPtrByteGet (rname, p_type, FALSE);
10564 emitcode ("mov","acc.%d,c",bstr);
10569 /* Case with a bitfield length < 8 and arbitrary source
10571 MOVA (aopGet (right, 0, FALSE, FALSE));
10572 /* shift and mask source value */
10574 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10576 pushedB = pushB ();
10577 /* transfer A to B and get next byte */
10578 emitPtrByteGet (rname, p_type, TRUE);
10580 emitcode ("anl", "a,#0x%02x", mask);
10581 emitcode ("orl", "a,b");
10582 if (p_type == GPOINTER)
10583 emitcode ("pop", "b");
10589 emitPtrByteSet (rname, p_type, "a");
10593 /* Bit length is greater than 7 bits. In this case, copy */
10594 /* all except the partial byte at the end */
10595 for (rlen=blen;rlen>=8;rlen-=8)
10597 emitPtrByteSet (rname, p_type,
10598 aopGet (right, offset++, FALSE, TRUE) );
10600 emitcode ("inc", "%s", rname);
10603 /* If there was a partial byte at the end */
10606 mask = (((unsigned char) -1 << rlen) & 0xff);
10608 if (AOP_TYPE (right) == AOP_LIT)
10610 /* Case with partial byte and literal source
10612 litval = (int) ulFromVal (AOP (right)->aopu.aop_lit);
10613 litval >>= (blen-rlen);
10614 litval &= (~mask) & 0xff;
10615 emitPtrByteGet (rname, p_type, FALSE);
10616 if ((mask|litval)!=0xff)
10617 emitcode ("anl","a,#0x%02x", mask);
10619 emitcode ("orl","a,#0x%02x", litval);
10624 /* Case with partial byte and arbitrary source
10626 MOVA (aopGet (right, offset++, FALSE, FALSE));
10627 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10629 pushedB = pushB ();
10630 /* transfer A to B and get next byte */
10631 emitPtrByteGet (rname, p_type, TRUE);
10633 emitcode ("anl", "a,#0x%02x", mask);
10634 emitcode ("orl", "a,b");
10635 if (p_type == GPOINTER)
10636 emitcode ("pop", "b");
10640 emitPtrByteSet (rname, p_type, "a");
10645 /*-----------------------------------------------------------------*/
10646 /* genDataPointerSet - remat pointer to data space */
10647 /*-----------------------------------------------------------------*/
10649 genDataPointerSet (operand * right,
10653 int size, offset = 0;
10654 char *l, buffer[256];
10656 D (emitcode (";", "genDataPointerSet"));
10658 aopOp (right, ic, FALSE);
10660 l = aopGet (result, 0, FALSE, TRUE);
10662 size = max (AOP_SIZE (right), AOP_SIZE (result));
10666 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
10668 SNPRINTF (buffer, sizeof(buffer), "%s", l);
10669 emitcode ("mov", "%s,%s", buffer,
10670 aopGet (right, offset++, FALSE, FALSE));
10673 freeAsmop (right, NULL, ic, TRUE);
10674 freeAsmop (result, NULL, ic, TRUE);
10677 /*-----------------------------------------------------------------*/
10678 /* genNearPointerSet - emitcode for near pointer put */
10679 /*-----------------------------------------------------------------*/
10681 genNearPointerSet (operand * right,
10689 sym_link *retype, *letype;
10690 sym_link *ptype = operandType (result);
10692 D (emitcode (";", "genNearPointerSet"));
10694 retype = getSpec (operandType (right));
10695 letype = getSpec (ptype);
10697 aopOp (result, ic, FALSE);
10699 /* if the result is rematerializable &
10700 in data space & not a bit variable */
10701 if (AOP_TYPE (result) == AOP_IMMD &&
10702 DCL_TYPE (ptype) == POINTER &&
10703 !IS_BITVAR (retype) &&
10704 !IS_BITVAR (letype))
10706 genDataPointerSet (right, result, ic);
10710 /* if the value is already in a pointer register
10711 then don't need anything more */
10712 if (!AOP_INPREG (AOP (result)))
10714 if (IS_AOP_PREG (result))
10716 // Aha, it is a pointer, just in disguise.
10717 rname = aopGet (result, 0, FALSE, FALSE);
10718 if (strcmp (rname, "a") == 0)
10720 // It's in pdata or on xstack
10721 rname = AOP (result)->aopu.aop_ptr->name;
10722 emitcode ("mov", "%s,a", rname);
10724 else if (*rname != '@')
10726 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10727 __FILE__, __LINE__);
10732 emitcode ("mov", "a%s,%s", rname + 1, rname);
10733 rname++; // skip the '@'.
10738 /* otherwise get a free pointer register */
10739 aop = newAsmop (0);
10740 preg = getFreePtr (ic, &aop, FALSE);
10741 emitcode ("mov", "%s,%s",
10743 aopGet (result, 0, FALSE, TRUE));
10744 rname = preg->name;
10749 rname = aopGet (result, 0, FALSE, FALSE);
10752 aopOp (right, ic, FALSE);
10754 /* if bitfield then unpack the bits */
10755 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10756 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10759 /* we can just get the values */
10760 int size = AOP_SIZE (right);
10765 l = aopGet (right, offset, FALSE, TRUE);
10766 if ((*l == '@') || (strcmp (l, "acc") == 0))
10769 emitcode ("mov", "@%s,a", rname);
10772 emitcode ("mov", "@%s,%s", rname, l);
10774 emitcode ("inc", "%s", rname);
10779 /* now some housekeeping stuff */
10780 if (aop) /* we had to allocate for this iCode */
10783 aopPut (result, rname, 0);
10784 freeAsmop (NULL, aop, ic, TRUE);
10788 /* we did not allocate which means left
10789 already in a pointer register, then
10790 if size > 0 && this could be used again
10791 we have to point it back to where it
10793 if ((AOP_SIZE (right) > 1 &&
10794 !OP_SYMBOL (result)->remat &&
10795 (OP_SYMBOL (result)->liveTo > ic->seq ||
10799 int size = AOP_SIZE (right) - 1;
10801 emitcode ("dec", "%s", rname);
10808 freeAsmop (right, NULL, ic, TRUE);
10809 freeAsmop (result, NULL, ic, TRUE);
10812 /*-----------------------------------------------------------------*/
10813 /* genPagedPointerSet - emitcode for Paged pointer put */
10814 /*-----------------------------------------------------------------*/
10816 genPagedPointerSet (operand * right,
10824 sym_link *retype, *letype;
10826 D (emitcode (";", "genPagedPointerSet"));
10828 retype = getSpec (operandType (right));
10829 letype = getSpec (operandType (result));
10831 aopOp (result, ic, FALSE);
10833 /* if the value is already in a pointer register
10834 then don't need anything more */
10835 if (!AOP_INPREG (AOP (result)))
10837 if (IS_AOP_PREG (result))
10839 // Aha, it is a pointer, just in disguise.
10840 rname = aopGet (result, 0, FALSE, FALSE);
10843 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10844 __FILE__, __LINE__);
10849 emitcode ("mov", "a%s,%s", rname + 1, rname);
10850 rname++; // skip the '@'.
10855 /* otherwise get a free pointer register */
10856 aop = newAsmop (0);
10857 preg = getFreePtr (ic, &aop, FALSE);
10858 emitcode ("mov", "%s,%s",
10860 aopGet (result, 0, FALSE, TRUE));
10861 rname = preg->name;
10866 rname = aopGet (result, 0, FALSE, FALSE);
10869 aopOp (right, ic, FALSE);
10871 /* if bitfield then unpack the bits */
10872 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10873 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10876 /* we can just get the values */
10877 int size = AOP_SIZE (right);
10882 l = aopGet (right, offset, FALSE, TRUE);
10884 emitcode ("movx", "@%s,a", rname);
10886 emitcode ("inc", "%s", rname);
10891 /* now some housekeeping stuff */
10892 if (aop) /* we had to allocate for this iCode */
10895 aopPut (result, rname, 0);
10896 freeAsmop (NULL, aop, ic, TRUE);
10900 /* we did not allocate which means left
10901 already in a pointer register, then
10902 if size > 0 && this could be used again
10903 we have to point it back to where it
10905 if (AOP_SIZE (right) > 1 &&
10906 !OP_SYMBOL (result)->remat &&
10907 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth) &&
10910 int size = AOP_SIZE (right) - 1;
10912 emitcode ("dec", "%s", rname);
10919 freeAsmop (right, NULL, ic, TRUE);
10920 freeAsmop (result, NULL, ic, TRUE);
10923 /*-----------------------------------------------------------------*/
10924 /* genFarPointerSet - set value from far space */
10925 /*-----------------------------------------------------------------*/
10927 genFarPointerSet (operand * right,
10928 operand * result, iCode * ic, iCode * pi)
10931 sym_link *retype = getSpec (operandType (right));
10932 sym_link *letype = getSpec (operandType (result));
10934 D(emitcode (";", "genFarPointerSet"));
10936 aopOp (result, ic, FALSE);
10937 loadDptrFromOperand (result, FALSE);
10939 /* so dptr now contains the address */
10940 aopOp (right, ic, FALSE);
10942 /* if bit then unpack */
10943 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10944 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10947 size = AOP_SIZE (right);
10952 char *l = aopGet (right, offset++, FALSE, FALSE);
10954 emitcode ("movx", "@dptr,a");
10956 emitcode ("inc", "dptr");
10959 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10960 aopPut (result, "dpl", 0);
10961 aopPut (result, "dph", 1);
10964 freeAsmop (result, NULL, ic, TRUE);
10965 freeAsmop (right, NULL, ic, TRUE);
10968 /*-----------------------------------------------------------------*/
10969 /* genGenPointerSet - set value from generic pointer space */
10970 /*-----------------------------------------------------------------*/
10972 genGenPointerSet (operand * right,
10973 operand * result, iCode * ic, iCode * pi)
10976 sym_link *retype = getSpec (operandType (right));
10977 sym_link *letype = getSpec (operandType (result));
10979 D (emitcode (";", "genGenPointerSet"));
10981 aopOp (result, ic, FALSE);
10982 loadDptrFromOperand (result, TRUE);
10984 /* so dptr now contains the address */
10985 aopOp (right, ic, FALSE);
10987 /* if bit then unpack */
10988 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10990 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10994 size = AOP_SIZE (right);
10999 char *l = aopGet (right, offset++, FALSE, FALSE);
11001 emitcode ("lcall", "__gptrput");
11003 emitcode ("inc", "dptr");
11007 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
11008 aopPut (result, "dpl", 0);
11009 aopPut (result, "dph", 1);
11012 freeAsmop (result, NULL, ic, TRUE);
11013 freeAsmop (right, NULL, ic, TRUE);
11016 /*-----------------------------------------------------------------*/
11017 /* genPointerSet - stores the value into a pointer location */
11018 /*-----------------------------------------------------------------*/
11020 genPointerSet (iCode * ic, iCode *pi)
11022 operand *right, *result;
11023 sym_link *type, *etype;
11026 D (emitcode (";", "genPointerSet"));
11028 right = IC_RIGHT (ic);
11029 result = IC_RESULT (ic);
11031 /* depending on the type of pointer we need to
11032 move it to the correct pointer register */
11033 type = operandType (result);
11034 etype = getSpec (type);
11035 /* if left is of type of pointer then it is simple */
11036 if (IS_PTR (type) && !IS_FUNC (type->next))
11038 p_type = DCL_TYPE (type);
11042 /* we have to go by the storage class */
11043 p_type = PTR_TYPE (SPEC_OCLS (etype));
11046 /* special case when cast remat */
11047 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
11048 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
11049 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
11050 type = operandType (result);
11051 p_type = DCL_TYPE (type);
11054 /* now that we have the pointer type we assign
11055 the pointer values */
11061 genNearPointerSet (right, result, ic, pi);
11065 genPagedPointerSet (right, result, ic, pi);
11069 genFarPointerSet (right, result, ic, pi);
11073 genGenPointerSet (right, result, ic, pi);
11077 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11078 "genPointerSet: illegal pointer type");
11082 /*-----------------------------------------------------------------*/
11083 /* genIfx - generate code for Ifx statement */
11084 /*-----------------------------------------------------------------*/
11086 genIfx (iCode * ic, iCode * popIc)
11088 operand *cond = IC_COND (ic);
11092 D (emitcode (";", "genIfx"));
11094 aopOp (cond, ic, FALSE);
11096 /* get the value into acc */
11097 if (AOP_TYPE (cond) != AOP_CRY)
11104 if (AOP(cond)->aopu.aop_dir)
11105 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
11108 /* the result is now in the accumulator or a directly addressable bit */
11109 freeAsmop (cond, NULL, ic, TRUE);
11111 /* if the condition is a bit variable */
11113 genIfxJump(ic, dup, NULL, NULL, NULL, popIc);
11114 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
11115 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL, popIc);
11116 else if (isbit && !IS_ITEMP (cond))
11117 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL, popIc);
11119 genIfxJump (ic, "a", NULL, NULL, NULL, popIc);
11124 /*-----------------------------------------------------------------*/
11125 /* genAddrOf - generates code for address of */
11126 /*-----------------------------------------------------------------*/
11128 genAddrOf (iCode * ic)
11130 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
11133 D (emitcode (";", "genAddrOf"));
11135 aopOp (IC_RESULT (ic), ic, FALSE);
11137 /* if the operand is on the stack then we
11138 need to get the stack offset of this
11142 /* if it has an offset then we need to compute it */
11145 int stack_offset = ((sym->stack < 0) ?
11146 ((char) (sym->stack - _G.nRegsSaved)) :
11147 ((char) sym->stack)) & 0xff;
11148 if ((abs(stack_offset) == 1) &&
11149 !AOP_NEEDSACC(IC_RESULT (ic)) &&
11150 !isOperandVolatile (IC_RESULT (ic), FALSE))
11152 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
11153 if (stack_offset > 0)
11154 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
11156 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
11160 emitcode ("mov", "a,%s", SYM_BP (sym));
11161 emitcode ("add", "a,#0x%02x", stack_offset & 0xff);
11162 aopPut (IC_RESULT (ic), "a", 0);
11167 /* we can just move _bp */
11168 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
11170 /* fill the result with zero */
11171 size = AOP_SIZE (IC_RESULT (ic)) - 1;
11176 aopPut (IC_RESULT (ic), zero, offset++);
11181 /* object not on stack then we need the name */
11182 size = getDataSize (IC_RESULT (ic));
11187 char s[SDCC_NAME_MAX];
11190 sprintf (s, "#(%s >> %d)",
11196 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11198 aopPut (IC_RESULT (ic), s, offset++);
11200 if (opIsGptr (IC_RESULT (ic)))
11203 SNPRINTF (buffer, sizeof(buffer),
11204 "#0x%02x", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
11205 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
11209 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11212 /*-----------------------------------------------------------------*/
11213 /* genFarFarAssign - assignment when both are in far space */
11214 /*-----------------------------------------------------------------*/
11216 genFarFarAssign (operand * result, operand * right, iCode * ic)
11218 int size = AOP_SIZE (right);
11222 D (emitcode (";", "genFarFarAssign"));
11224 /* first push the right side on to the stack */
11227 l = aopGet (right, offset++, FALSE, FALSE);
11229 emitcode ("push", "acc");
11232 freeAsmop (right, NULL, ic, FALSE);
11233 /* now assign DPTR to result */
11234 aopOp (result, ic, FALSE);
11235 size = AOP_SIZE (result);
11238 emitcode ("pop", "acc");
11239 aopPut (result, "a", --offset);
11241 freeAsmop (result, NULL, ic, FALSE);
11244 /*-----------------------------------------------------------------*/
11245 /* genAssign - generate code for assignment */
11246 /*-----------------------------------------------------------------*/
11248 genAssign (iCode * ic)
11250 operand *result, *right;
11252 unsigned long lit = 0L;
11254 D (emitcode (";", "genAssign"));
11256 result = IC_RESULT (ic);
11257 right = IC_RIGHT (ic);
11259 /* if they are the same */
11260 if (operandsEqu (result, right) &&
11261 !isOperandVolatile (result, FALSE) &&
11262 !isOperandVolatile (right, FALSE))
11265 aopOp (right, ic, FALSE);
11267 /* special case both in far space */
11268 if (AOP_TYPE (right) == AOP_DPTR &&
11269 IS_TRUE_SYMOP (result) &&
11270 isOperandInFarSpace (result))
11272 genFarFarAssign (result, right, ic);
11276 aopOp (result, ic, TRUE);
11278 /* if they are the same registers */
11279 if (sameRegs (AOP (right), AOP (result)) &&
11280 !isOperandVolatile (result, FALSE) &&
11281 !isOperandVolatile (right, FALSE))
11284 /* if the result is a bit */
11285 if (AOP_TYPE (result) == AOP_CRY)
11287 assignBit (result, right);
11291 /* bit variables done */
11293 size = getDataSize (result);
11295 if (AOP_TYPE (right) == AOP_LIT)
11296 lit = ulFromVal (AOP (right)->aopu.aop_lit);
11299 (AOP_TYPE (result) != AOP_REG) &&
11300 (AOP_TYPE (right) == AOP_LIT) &&
11301 !IS_FLOAT (operandType (right)) &&
11304 while ((size) && (lit))
11307 aopGet (right, offset, FALSE, FALSE),
11313 /* And now fill the rest with zeros. */
11316 emitcode ("clr", "a");
11320 aopPut (result, "a", offset);
11329 aopGet (right, offset, FALSE, FALSE),
11334 adjustArithmeticResult (ic);
11337 freeAsmop (result, NULL, ic, TRUE);
11338 freeAsmop (right, NULL, ic, TRUE);
11341 /*-----------------------------------------------------------------*/
11342 /* genJumpTab - generates code for jump table */
11343 /*-----------------------------------------------------------------*/
11345 genJumpTab (iCode * ic)
11347 symbol *jtab,*jtablo,*jtabhi;
11349 unsigned int count;
11351 D (emitcode (";", "genJumpTab"));
11353 count = elementsInSet( IC_JTLABELS (ic) );
11357 /* this algorithm needs 9 cycles and 7 + 3*n bytes
11358 if the switch argument is in a register.
11359 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
11360 /* Peephole may not convert ljmp to sjmp or ret
11361 labelIsReturnOnly & labelInRange must check
11362 currPl->ic->op != JUMPTABLE */
11363 aopOp (IC_JTCOND (ic), ic, FALSE);
11364 /* get the condition into accumulator */
11365 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11367 /* multiply by three */
11368 if (aopGetUsesAcc (IC_JTCOND (ic), 0))
11370 emitcode ("mov", "b,#0x03");
11371 emitcode ("mul", "ab");
11375 emitcode ("add", "a,acc");
11376 emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
11378 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11380 jtab = newiTempLabel (NULL);
11381 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
11382 emitcode ("jmp", "@a+dptr");
11384 /* now generate the jump labels */
11385 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11386 jtab = setNextItem (IC_JTLABELS (ic)))
11387 emitcode ("ljmp", "%05d$", jtab->key + 100);
11391 /* this algorithm needs 14 cycles and 13 + 2*n bytes
11392 if the switch argument is in a register.
11393 For n>6 this algorithm may be more compact */
11394 jtablo = newiTempLabel (NULL);
11395 jtabhi = newiTempLabel (NULL);
11397 /* get the condition into accumulator.
11398 Using b as temporary storage, if register push/pop is needed */
11399 aopOp (IC_JTCOND (ic), ic, FALSE);
11400 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11401 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
11402 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
11404 // (MB) what if B is in use???
11405 wassertl(!BINUSE, "B was in use");
11406 emitcode ("mov", "b,%s", l);
11409 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11413 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
11414 emitcode ("movc", "a,@a+pc");
11415 emitcode ("push", "acc");
11418 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
11419 emitcode ("movc", "a,@a+pc");
11420 emitcode ("push", "acc");
11424 /* this scales up to n<=255, but needs two more bytes
11425 and changes dptr */
11426 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
11427 emitcode ("movc", "a,@a+dptr");
11428 emitcode ("push", "acc");
11431 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
11432 emitcode ("movc", "a,@a+dptr");
11433 emitcode ("push", "acc");
11436 emitcode ("ret", "");
11438 /* now generate jump table, LSB */
11439 emitLabel (jtablo);
11440 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11441 jtab = setNextItem (IC_JTLABELS (ic)))
11442 emitcode (".db", "%05d$", jtab->key + 100);
11444 /* now generate jump table, MSB */
11445 emitLabel (jtabhi);
11446 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11447 jtab = setNextItem (IC_JTLABELS (ic)))
11448 emitcode (".db", "%05d$>>8", jtab->key + 100);
11452 /*-----------------------------------------------------------------*/
11453 /* genCast - gen code for casting */
11454 /*-----------------------------------------------------------------*/
11456 genCast (iCode * ic)
11458 operand *result = IC_RESULT (ic);
11459 sym_link *ctype = operandType (IC_LEFT (ic));
11460 sym_link *rtype = operandType (IC_RIGHT (ic));
11461 operand *right = IC_RIGHT (ic);
11464 D (emitcode (";", "genCast"));
11466 /* if they are equivalent then do nothing */
11467 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11470 aopOp (right, ic, FALSE);
11471 aopOp (result, ic, FALSE);
11473 /* if the result is a bit (and not a bitfield) */
11474 if (IS_BIT (OP_SYMBOL (result)->type))
11476 assignBit (result, right);
11480 /* if they are the same size : or less */
11481 if (AOP_SIZE (result) <= AOP_SIZE (right))
11484 /* if they are in the same place */
11485 if (sameRegs (AOP (right), AOP (result)))
11488 /* if they in different places then copy */
11489 size = AOP_SIZE (result);
11494 aopGet (right, offset, FALSE, FALSE),
11501 /* if the result is of type pointer */
11502 if (IS_PTR (ctype))
11505 sym_link *type = operandType (right);
11506 sym_link *etype = getSpec (type);
11508 /* pointer to generic pointer */
11509 if (IS_GENPTR (ctype))
11513 p_type = DCL_TYPE (type);
11517 if (SPEC_SCLS(etype)==S_REGISTER) {
11518 // let's assume it is a generic pointer
11521 /* we have to go by the storage class */
11522 p_type = PTR_TYPE (SPEC_OCLS (etype));
11526 /* the first two bytes are known */
11527 size = GPTRSIZE - 1;
11532 aopGet (right, offset, FALSE, FALSE),
11536 /* the last byte depending on type */
11538 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11543 // pointerTypeToGPByte will have bitched.
11547 sprintf(gpValStr, "#0x%02x", gpVal);
11548 aopPut (result, gpValStr, GPTRSIZE - 1);
11553 /* just copy the pointers */
11554 size = AOP_SIZE (result);
11559 aopGet (right, offset, FALSE, FALSE),
11566 /* so we now know that the size of destination is greater
11567 than the size of the source */
11568 /* we move to result for the size of source */
11569 size = AOP_SIZE (right);
11574 aopGet (right, offset, FALSE, FALSE),
11579 /* now depending on the sign of the source && destination */
11580 size = AOP_SIZE (result) - AOP_SIZE (right);
11581 /* if unsigned or not an integral type */
11582 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11585 aopPut (result, zero, offset++);
11589 /* we need to extend the sign :{ */
11590 char *l = aopGet (right, AOP_SIZE (right) - 1,
11593 emitcode ("rlc", "a");
11594 emitcode ("subb", "a,acc");
11596 aopPut (result, "a", offset++);
11599 /* we are done hurray !!!! */
11602 freeAsmop (result, NULL, ic, TRUE);
11603 freeAsmop (right, NULL, ic, TRUE);
11606 /*-----------------------------------------------------------------*/
11607 /* genDjnz - generate decrement & jump if not zero instrucion */
11608 /*-----------------------------------------------------------------*/
11610 genDjnz (iCode * ic, iCode * ifx)
11612 symbol *lbl, *lbl1;
11616 /* if the if condition has a false label
11617 then we cannot save */
11618 if (IC_FALSE (ifx))
11621 /* if the minus is not of the form a = a - 1 */
11622 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11623 !IS_OP_LITERAL (IC_RIGHT (ic)))
11626 if (operandLitValue (IC_RIGHT (ic)) != 1)
11629 /* if the size of this greater than one then no
11631 if (getSize (operandType (IC_RESULT (ic))) > 1)
11634 /* otherwise we can save BIG */
11636 D (emitcode (";", "genDjnz"));
11638 lbl = newiTempLabel (NULL);
11639 lbl1 = newiTempLabel (NULL);
11641 aopOp (IC_RESULT (ic), ic, FALSE);
11643 if (AOP_NEEDSACC(IC_RESULT(ic)))
11645 /* If the result is accessed indirectly via
11646 * the accumulator, we must explicitly write
11647 * it back after the decrement.
11649 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11651 if (strcmp(rByte, "a"))
11653 /* Something is hopelessly wrong */
11654 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11655 __FILE__, __LINE__);
11656 /* We can just give up; the generated code will be inefficient,
11657 * but what the hey.
11659 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11662 emitcode ("dec", "%s", rByte);
11663 aopPut (IC_RESULT (ic), rByte, 0);
11664 emitcode ("jnz", "%05d$", lbl->key + 100);
11666 else if (IS_AOP_PREG (IC_RESULT (ic)))
11668 emitcode ("dec", "%s",
11669 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11670 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11671 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11672 ifx->generated = 1;
11673 emitcode ("jnz", "%05d$", lbl->key + 100);
11677 emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11680 emitcode ("sjmp", "%05d$", lbl1->key + 100);
11682 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11685 if (!ifx->generated)
11686 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11687 ifx->generated = 1;
11691 /*-----------------------------------------------------------------*/
11692 /* genReceive - generate code for a receive iCode */
11693 /*-----------------------------------------------------------------*/
11695 genReceive (iCode * ic)
11697 int size = getSize (operandType (IC_RESULT (ic)));
11700 D (emitcode (";", "genReceive"));
11702 if (ic->argreg == 1)
11703 { /* first parameter */
11704 if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11705 isOperandInPagedSpace (IC_RESULT (ic))) &&
11706 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11707 IS_TRUE_SYMOP (IC_RESULT (ic))))
11710 int receivingA = 0;
11713 for (offset = 0; offset<size; offset++)
11714 if (!strcmp (fReturn[offset], "a"))
11719 if (size==1 || getTempRegs(tempRegs, size-1, ic))
11721 for (offset = size-1; offset>0; offset--)
11722 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11723 emitcode("mov","a,%s", fReturn[0]);
11725 aopOp (IC_RESULT (ic), ic, FALSE);
11727 aopPut (IC_RESULT (ic), "a", offset);
11728 for (offset = 1; offset<size; offset++)
11729 aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset);
11735 if (getTempRegs(tempRegs, size, ic))
11737 for (offset = 0; offset<size; offset++)
11738 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11739 aopOp (IC_RESULT (ic), ic, FALSE);
11740 for (offset = 0; offset<size; offset++)
11741 aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset);
11746 offset = fReturnSizeMCS51 - size;
11749 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11750 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11753 aopOp (IC_RESULT (ic), ic, FALSE);
11754 size = AOP_SIZE (IC_RESULT (ic));
11758 emitcode ("pop", "acc");
11759 aopPut (IC_RESULT (ic), "a", offset++);
11765 aopOp (IC_RESULT (ic), ic, FALSE);
11767 assignResultValue (IC_RESULT (ic), NULL);
11770 else if (ic->argreg > 12)
11771 { /* bit parameters */
11772 regs *reg = OP_SYMBOL (IC_RESULT (ic))->regs[0];
11775 if (!reg || reg->rIdx != ic->argreg-5)
11777 aopOp (IC_RESULT (ic), ic, FALSE);
11778 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11779 outBitC(IC_RESULT (ic));
11783 { /* other parameters */
11785 aopOp (IC_RESULT (ic), ic, FALSE);
11786 rb1off = ic->argreg;
11789 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
11794 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11797 /*-----------------------------------------------------------------*/
11798 /* genDummyRead - generate code for dummy read of volatiles */
11799 /*-----------------------------------------------------------------*/
11801 genDummyRead (iCode * ic)
11806 D (emitcode(";", "genDummyRead"));
11808 op = IC_RIGHT (ic);
11809 if (op && IS_SYMOP (op))
11811 aopOp (op, ic, FALSE);
11813 /* if the result is a bit */
11814 if (AOP_TYPE (op) == AOP_CRY)
11815 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11818 /* bit variables done */
11820 size = AOP_SIZE (op);
11824 MOVA (aopGet (op, offset, FALSE, FALSE));
11829 freeAsmop (op, NULL, ic, TRUE);
11833 if (op && IS_SYMOP (op))
11835 aopOp (op, ic, FALSE);
11837 /* if the result is a bit */
11838 if (AOP_TYPE (op) == AOP_CRY)
11839 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11842 /* bit variables done */
11844 size = AOP_SIZE (op);
11848 MOVA (aopGet (op, offset, FALSE, FALSE));
11853 freeAsmop (op, NULL, ic, TRUE);
11857 /*-----------------------------------------------------------------*/
11858 /* genCritical - generate code for start of a critical sequence */
11859 /*-----------------------------------------------------------------*/
11861 genCritical (iCode *ic)
11863 symbol *tlbl = newiTempLabel (NULL);
11865 D (emitcode(";", "genCritical"));
11867 if (IC_RESULT (ic))
11869 aopOp (IC_RESULT (ic), ic, TRUE);
11870 aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
11871 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11872 aopPut (IC_RESULT (ic), zero, 0);
11874 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11878 emitcode ("setb", "c");
11879 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11880 emitcode ("clr", "c");
11882 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11886 /*-----------------------------------------------------------------*/
11887 /* genEndCritical - generate code for end of a critical sequence */
11888 /*-----------------------------------------------------------------*/
11890 genEndCritical (iCode *ic)
11892 D(emitcode(";", "genEndCritical"));
11896 aopOp (IC_RIGHT (ic), ic, FALSE);
11897 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11899 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11900 emitcode ("mov", "ea,c");
11904 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11905 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11906 emitcode ("rrc", "a");
11907 emitcode ("mov", "ea,c");
11909 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11913 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11914 emitcode ("mov", "ea,c");
11918 /*-----------------------------------------------------------------*/
11919 /* gen51Code - generate code for 8051 based controllers */
11920 /*-----------------------------------------------------------------*/
11922 gen51Code (iCode * lic)
11926 /* int cseq = 0; */
11928 _G.currentFunc = NULL;
11929 lineHead = lineCurr = NULL;
11931 /* print the allocation information */
11932 if (allocInfo && currFunc)
11933 printAllocInfo (currFunc, codeOutBuf);
11934 /* if debug information required */
11935 if (options.debug && currFunc)
11937 debugFile->writeFunction (currFunc, lic);
11939 /* stack pointer name */
11940 if (options.useXstack)
11946 for (ic = lic; ic; ic = ic->next)
11948 _G.current_iCode = ic;
11950 if (ic->lineno && cln != ic->lineno)
11954 debugFile->writeCLine (ic);
11956 if (!options.noCcodeInAsm) {
11957 emitcode (";", "%s:%d: %s", ic->filename, ic->lineno,
11958 printCLine(ic->filename, ic->lineno));
11963 if (ic->seqPoint && ic->seqPoint != cseq)
11965 emitcode (";", "sequence point %d", ic->seqPoint);
11966 cseq = ic->seqPoint;
11969 if (options.iCodeInAsm) {
11970 char regsInUse[80];
11975 for (i=0; i<8; i++) {
11976 sprintf (®sInUse[i],
11977 "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11980 strcpy (regsInUse, "--------");
11981 for (i=0; i < 8; i++) {
11982 if (bitVectBitValue (ic->rMask, i))
11984 int offset = regs8051[i].offset;
11985 regsInUse[offset] = offset + '0'; /* show rMask */
11989 iLine = printILine(ic);
11990 emitcode(";", "[%s] ic:%d: %s", regsInUse, ic->seq, iLine);
11993 /* if the result is marked as
11994 spilt and rematerializable or code for
11995 this has already been generated then
11997 if (resultRemat (ic) || ic->generated)
12000 /* depending on the operation */
12021 iCode *ifxIc, *popIc;
12022 bool CommonRegs = FALSE;
12024 /* IPOP happens only when trying to restore a
12025 spilt live range, if there is an ifx statement
12026 following this pop (or several) then the if statement might
12027 be using some of the registers being popped which
12028 would destory the contents of the register so
12029 we need to check for this condition and handle it */
12030 for (ifxIc = ic->next; ifxIc && ifxIc->op == IPOP; ifxIc = ifxIc->next);
12031 for (popIc = ic; popIc && popIc->op == IPOP; popIc = popIc->next)
12032 CommonRegs |= (ifxIc && ifxIc->op == IFX && !ifxIc->generated &&
12033 regsInCommon (IC_LEFT (popIc), IC_COND (ifxIc)));
12035 genIfx (ifxIc, ic);
12054 genEndFunction (ic);
12074 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
12091 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
12095 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
12102 /* note these two are xlated by algebraic equivalence
12103 in decorateType() in SDCCast.c */
12104 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12105 "got '>=' or '<=' shouldn't have come here");
12109 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
12121 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
12125 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
12129 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
12165 genRightShift (ic);
12168 case GET_VALUE_AT_ADDRESS:
12170 hasInc (IC_LEFT (ic), ic,
12171 getSize (operandType (IC_RESULT (ic)))),
12172 ifxForOp (IC_RESULT (ic), ic) );
12176 if (POINTER_SET (ic))
12178 hasInc (IC_RESULT (ic), ic,
12179 getSize (operandType (IC_RIGHT (ic)))));
12205 addSet (&_G.sendSet, ic);
12208 case DUMMY_READ_VOLATILE:
12217 genEndCritical (ic);
12229 _G.current_iCode = NULL;
12231 /* now we are ready to call the
12232 peep hole optimizer */
12233 if (!options.nopeep)
12234 peepHole (&lineHead);
12236 /* now do the actual printing */
12237 printLine (lineHead, codeOutBuf);