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);
2836 saveRegisters (setFirstItem (sendSet));
2837 emitcode ("mov", "bits,b");
2840 /* then we do all other parameters */
2841 for (sic = setFirstItem (sendSet); sic;
2842 sic = setNextItem (sendSet))
2844 if (sic->argreg <= 12)
2846 int size, offset = 0;
2847 aopOp (IC_LEFT (sic), sic, FALSE);
2848 size = AOP_SIZE (IC_LEFT (sic));
2850 if (sic->argreg == 1)
2854 char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2855 if (strcmp (l, fReturn[offset]))
2857 emitcode ("mov", "%s,%s", fReturn[offset], l);
2866 emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2867 aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2871 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2876 /*-----------------------------------------------------------------*/
2877 /* selectRegBank - emit code to select the register bank */
2878 /*-----------------------------------------------------------------*/
2880 selectRegBank (short bank, bool keepFlags)
2882 /* if f.e. result is in carry */
2885 emitcode ("anl", "psw,#0xE7");
2887 emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2891 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2895 /*-----------------------------------------------------------------*/
2896 /* genCall - generates a call statement */
2897 /*-----------------------------------------------------------------*/
2899 genCall (iCode * ic)
2903 // bool restoreBank = FALSE;
2904 bool swapBanks = FALSE;
2905 bool accuse = FALSE;
2906 bool accPushed = FALSE;
2907 bool resultInF0 = FALSE;
2908 bool assignResultGenerated = FALSE;
2910 D (emitcode (";", "genCall"));
2912 dtype = operandType (IC_LEFT (ic));
2913 etype = getSpec(dtype);
2914 /* if send set is not empty then assign */
2917 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2918 genSend(reverseSet(_G.sendSet));
2920 genSend(_G.sendSet);
2925 /* if we are calling a not _naked function that is not using
2926 the same register bank then we need to save the
2927 destination registers on the stack */
2928 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2929 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2930 !IFFUNC_ISISR (dtype))
2935 /* if caller saves & we have not saved then */
2941 emitcode ("mov", "psw,#0x%02x", ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2945 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2947 if (IFFUNC_CALLEESAVES(dtype))
2949 werror (E_BANKED_WITH_CALLEESAVES);
2953 char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2954 OP_SYMBOL (IC_LEFT (ic))->rname :
2955 OP_SYMBOL (IC_LEFT (ic))->name);
2957 emitcode ("mov", "r0,#%s", l);
2958 emitcode ("mov", "r1,#(%s >> 8)", l);
2959 emitcode ("mov", "r2,#(%s >> 16)", l);
2960 emitcode ("lcall", "__sdcc_banked_call");
2965 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2966 OP_SYMBOL (IC_LEFT (ic))->rname :
2967 OP_SYMBOL (IC_LEFT (ic))->name));
2972 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2975 /* if we need assign a result value */
2976 if ((IS_ITEMP (IC_RESULT (ic)) &&
2977 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2978 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2979 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2980 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2981 IS_TRUE_SYMOP (IC_RESULT (ic)))
2985 aopOp (IC_RESULT (ic), ic, FALSE);
2988 accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2989 assignResultGenerated = TRUE;
2991 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2994 /* adjust the stack for parameters if required */
2998 if (ic->parmBytes > 3)
3002 emitcode ("push", "acc");
3005 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3006 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3007 !assignResultGenerated)
3009 emitcode ("mov", "F0,c");
3013 emitcode ("mov", "a,%s", spname);
3014 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3015 emitcode ("mov", "%s,a", spname);
3017 /* unsaveRegisters from xstack needs acc, but */
3018 /* unsaveRegisters from stack needs this popped */
3019 if (accPushed && !options.useXstack)
3021 emitcode ("pop", "acc");
3026 for (i = 0; i < ic->parmBytes; i++)
3027 emitcode ("dec", "%s", spname);
3030 /* if we had saved some registers then unsave them */
3031 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3033 if (accuse && !accPushed && options.useXstack)
3035 /* xstack needs acc, but doesn't touch normal stack */
3036 emitcode ("push", "acc");
3039 unsaveRegisters (ic);
3042 // /* if register bank was saved then pop them */
3044 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
3046 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
3049 emitcode ("mov", "c,F0");
3051 aopOp (IC_RESULT (ic), ic, FALSE);
3052 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3053 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3057 emitcode ("pop", "acc");
3060 /*-----------------------------------------------------------------*/
3061 /* genPcall - generates a call by pointer statement */
3062 /*-----------------------------------------------------------------*/
3064 genPcall (iCode * ic)
3068 symbol *rlbl = newiTempLabel (NULL);
3069 // bool restoreBank=FALSE;
3070 bool swapBanks = FALSE;
3071 bool resultInF0 = FALSE;
3073 D (emitcode (";", "genPcall"));
3075 dtype = operandType (IC_LEFT (ic))->next;
3076 etype = getSpec(dtype);
3077 /* if caller saves & we have not saved then */
3081 /* if we are calling a not _naked function that is not using
3082 the same register bank then we need to save the
3083 destination registers on the stack */
3084 if (currFunc && dtype && !IFFUNC_ISNAKED (dtype) &&
3085 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
3086 !IFFUNC_ISISR (dtype))
3088 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3089 // restoreBank=TRUE;
3091 // need caution message to user here
3094 if (IS_LITERAL (etype))
3096 /* if send set is not empty then assign */
3099 genSend(reverseSet(_G.sendSet));
3105 emitcode ("mov", "psw,#0x%02x",
3106 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3109 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT (getSpec(dtype)))
3111 if (IFFUNC_CALLEESAVES (dtype))
3113 werror (E_BANKED_WITH_CALLEESAVES);
3117 char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
3119 emitcode ("mov", "r0,#%s", l);
3120 emitcode ("mov", "r1,#(%s >> 8)", l);
3121 emitcode ("mov", "r2,#(%s >> 16)", l);
3122 emitcode ("lcall", "__sdcc_banked_call");
3127 emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
3132 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT (getSpec(dtype)))
3134 if (IFFUNC_CALLEESAVES (dtype))
3136 werror (E_BANKED_WITH_CALLEESAVES);
3140 aopOp (IC_LEFT (ic), ic, FALSE);
3144 /* what if aopGet needs r0 or r1 ??? */
3145 emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3146 emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3147 emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3151 int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
3152 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3153 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3154 emitcode ("mov", "0x%02x,%s", reg, aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3157 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3159 /* if send set is not empty then assign */
3162 genSend(reverseSet(_G.sendSet));
3168 emitcode ("mov", "psw,#0x%02x",
3169 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3173 emitcode ("lcall", "__sdcc_banked_call");
3176 else if (_G.sendSet)
3178 /* push the return address on to the stack */
3179 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
3180 emitcode ("push", "acc");
3181 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
3182 emitcode ("push", "acc");
3184 /* now push the function address */
3185 pushSide (IC_LEFT (ic), FPTRSIZE, ic);
3187 /* if send set is not empty then assign */
3190 genSend(reverseSet(_G.sendSet));
3196 emitcode ("mov", "psw,#0x%02x",
3197 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3201 emitcode ("ret", "");
3204 else /* the send set is empty */
3207 /* now get the calling address into dptr */
3208 aopOp (IC_LEFT (ic), ic, FALSE);
3210 l = aopGet (IC_LEFT (ic), 0, FALSE, FALSE);
3211 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3213 emitcode ("mov", "r0,%s", l);
3214 l = aopGet (IC_LEFT (ic), 1, FALSE, FALSE);
3215 emitcode ("mov", "dph,%s", l);
3216 emitcode ("mov", "dpl,r0");
3220 emitcode ("mov", "dpl,%s", l);
3221 l = aopGet (IC_LEFT (ic), 1, FALSE, FALSE);
3222 emitcode ("mov", "dph,%s", l);
3225 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3229 emitcode ("mov", "psw,#0x%02x",
3230 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3234 emitcode ("lcall", "__sdcc_call_dptr");
3239 selectRegBank (FUNC_REGBANK (currFunc->type), IS_BIT (etype));
3242 /* if we need assign a result value */
3243 if ((IS_ITEMP (IC_RESULT (ic)) &&
3244 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3245 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3246 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3247 IS_TRUE_SYMOP (IC_RESULT (ic)))
3251 aopOp (IC_RESULT (ic), ic, FALSE);
3254 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3256 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3259 /* adjust the stack for parameters if required */
3263 if (ic->parmBytes > 3)
3265 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3266 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3268 emitcode ("mov", "F0,c");
3272 emitcode ("mov", "a,%s", spname);
3273 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3274 emitcode ("mov", "%s,a", spname);
3277 for (i = 0; i < ic->parmBytes; i++)
3278 emitcode ("dec", "%s", spname);
3281 // /* if register bank was saved then unsave them */
3283 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3285 /* if we had saved some registers then unsave them */
3286 if (ic->regsSaved && !IFFUNC_CALLEESAVES (dtype))
3287 unsaveRegisters (ic);
3289 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3292 emitcode ("mov", "c,F0");
3294 aopOp (IC_RESULT (ic), ic, FALSE);
3295 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3296 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3300 /*-----------------------------------------------------------------*/
3301 /* resultRemat - result is rematerializable */
3302 /*-----------------------------------------------------------------*/
3304 resultRemat (iCode * ic)
3306 if (SKIP_IC (ic) || ic->op == IFX)
3309 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3311 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3312 if (sym->remat && !POINTER_SET (ic))
3319 /*-----------------------------------------------------------------*/
3320 /* inExcludeList - return 1 if the string is in exclude Reg list */
3321 /*-----------------------------------------------------------------*/
3323 regsCmp(void *p1, void *p2)
3325 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3329 inExcludeList (char *s)
3331 const char *p = setFirstItem(options.excludeRegsSet);
3333 if (p == NULL || STRCASECMP(p, "none") == 0)
3337 return isinSetWith(options.excludeRegsSet, s, regsCmp);
3340 /*-----------------------------------------------------------------*/
3341 /* genFunction - generated code for function entry */
3342 /*-----------------------------------------------------------------*/
3344 genFunction (iCode * ic)
3346 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3348 bool switchedPSW = FALSE;
3349 int calleesaves_saved_register = -1;
3350 int stackAdjust = sym->stack;
3351 int accIsFree = sym->recvSize < 4;
3352 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3353 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3356 /* create the function header */
3357 emitcode (";", "-----------------------------------------");
3358 emitcode (";", " function %s", sym->name);
3359 emitcode (";", "-----------------------------------------");
3361 emitcode ("", "%s:", sym->rname);
3362 lineCurr->isLabel = 1;
3363 ftype = operandType (IC_LEFT (ic));
3364 _G.currentFunc = sym;
3366 if (IFFUNC_ISNAKED(ftype))
3368 emitcode(";", "naked function: no prologue.");
3372 /* here we need to generate the equates for the
3373 register bank if required */
3374 if (FUNC_REGBANK (ftype) != rbank)
3378 rbank = FUNC_REGBANK (ftype);
3379 for (i = 0; i < mcs51_nRegs; i++)
3381 if (regs8051[i].type != REG_BIT)
3383 if (strcmp (regs8051[i].base, "0") == 0)
3384 emitcode ("", "%s = 0x%02x",
3386 8 * rbank + regs8051[i].offset);
3388 emitcode ("", "%s = %s + 0x%02x",
3391 8 * rbank + regs8051[i].offset);
3396 /* if this is an interrupt service routine then
3397 save acc, b, dpl, dph */
3398 if (IFFUNC_ISISR (sym->type))
3402 rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), sym->regsUsed);
3403 if (IFFUNC_HASFCALL(sym->type) || !bitVectIsZero (rsavebits))
3405 emitcode ("push", "bits");
3408 freeBitVect (rsavebits);
3410 if (!inExcludeList ("acc"))
3411 emitcode ("push", "acc");
3412 if (!inExcludeList ("b"))
3413 emitcode ("push", "b");
3414 if (!inExcludeList ("dpl"))
3415 emitcode ("push", "dpl");
3416 if (!inExcludeList ("dph"))
3417 emitcode ("push", "dph");
3418 /* if this isr has no bank i.e. is going to
3419 run with bank 0 , then we need to save more
3421 if (!FUNC_REGBANK (sym->type))
3425 /* if this function does not call any other
3426 function then we can be economical and
3427 save only those registers that are used */
3428 if (!IFFUNC_HASFCALL(sym->type))
3430 /* if any registers used */
3433 /* save the registers used */
3434 for (i = 0; i < sym->regsUsed->size; i++)
3436 if (bitVectBitValue (sym->regsUsed, i))
3443 /* this function has a function call. We cannot
3444 determine register usage so we will have to push the
3446 saveRBank (0, ic, FALSE);
3447 if (options.parms_in_bank1)
3449 for (i=0; i < 8 ; i++ )
3451 emitcode ("push","%s",rb1regs[i]);
3458 /* This ISR uses a non-zero bank.
3460 * We assume that the bank is available for our
3463 * However, if this ISR calls a function which uses some
3464 * other bank, we must save that bank entirely.
3466 unsigned long banksToSave = 0;
3468 if (IFFUNC_HASFCALL(sym->type))
3471 #define MAX_REGISTER_BANKS 4
3476 for (i = ic; i; i = i->next)
3478 if (i->op == ENDFUNCTION)
3480 /* we got to the end OK. */
3488 dtype = operandType (IC_LEFT(i));
3490 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3492 /* Mark this bank for saving. */
3493 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3495 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3499 banksToSave |= (1 << FUNC_REGBANK(dtype));
3502 /* And note that we don't need to do it in
3510 /* This is a mess; we have no idea what
3511 * register bank the called function might
3514 * The only thing I can think of to do is
3515 * throw a warning and hope.
3517 werror(W_FUNCPTR_IN_USING_ISR);
3521 if (banksToSave && options.useXstack)
3523 /* Since we aren't passing it an ic,
3524 * saveRBank will assume r0 is available to abuse.
3526 * So switch to our (trashable) bank now, so
3527 * the caller's R0 isn't trashed.
3529 emitcode ("push", "psw");
3530 emitcode ("mov", "psw,#0x%02x",
3531 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3535 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3537 if (banksToSave & (1 << ix))
3539 saveRBank(ix, NULL, FALSE);
3543 // TODO: this needs a closer look
3544 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3547 /* Set the register bank to the desired value if nothing else */
3548 /* has done so yet. */
3551 emitcode ("push", "psw");
3552 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3557 /* This is a non-ISR function. The caller has already switched register */
3558 /* banks, if necessary, so just handle the callee-saves option. */
3560 /* if callee-save to be used for this function
3561 then save the registers being used in this function */
3562 if (IFFUNC_CALLEESAVES(sym->type))
3566 /* if any registers used */
3569 bool bits_pushed = FALSE;
3570 /* save the registers used */
3571 for (i = 0; i < sym->regsUsed->size; i++)
3573 if (bitVectBitValue (sym->regsUsed, i))
3575 /* remember one saved register for later usage */
3576 if (calleesaves_saved_register < 0)
3577 calleesaves_saved_register = i;
3578 bits_pushed = pushReg (i, bits_pushed);
3588 if (options.useXstack)
3590 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3592 emitcode ("mov", "r0,%s", spname);
3593 emitcode ("inc", "%s", spname);
3594 emitcode ("xch", "a,_bpx");
3595 emitcode ("movx", "@r0,a");
3596 emitcode ("inc", "r0");
3597 emitcode ("mov", "a,r0");
3598 emitcode ("xch", "a,_bpx");
3602 emitcode ("push", "_bp"); /* save the callers stack */
3603 emitcode ("mov", "_bp,sp");
3608 if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3610 /* set up the stack */
3611 emitcode ("push", "_bp"); /* save the callers stack */
3612 emitcode ("mov", "_bp,sp");
3617 /* For some cases it is worthwhile to perform a RECEIVE iCode */
3618 /* before setting up the stack frame completely. */
3619 if (ric && ric->argreg == 1 && IC_RESULT (ric))
3621 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3625 if (rsym && rsym->regType == REG_CND)
3627 if (rsym && (rsym->accuse || rsym->ruonly))
3629 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3630 rsym = rsym->usl.spillLoc;
3633 /* If the RECEIVE operand immediately spills to the first entry on the */
3634 /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3635 /* rather than the usual @r0/r1 machinations. */
3636 if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3640 _G.current_iCode = ric;
3641 D(emitcode (";", "genReceive"));
3642 for (ofs=0; ofs < sym->recvSize; ofs++)
3644 if (!strcmp (fReturn[ofs], "a"))
3645 emitcode ("push", "acc");
3647 emitcode ("push", fReturn[ofs]);
3649 stackAdjust -= sym->recvSize;
3652 assert (stackAdjust>=0);
3655 _G.current_iCode = ic;
3659 /* If the RECEIVE operand is 4 registers, we can do the moves now */
3660 /* to free up the accumulator. */
3661 else if (rsym && rsym->nRegs && sym->recvSize == 4)
3665 _G.current_iCode = ric;
3666 D(emitcode (";", "genReceive"));
3667 for (ofs=0; ofs < sym->recvSize; ofs++)
3669 emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3671 _G.current_iCode = ic;
3677 /* adjust the stack for the function */
3680 int i = stackAdjust;
3682 werror (W_STACK_OVERFLOW, sym->name);
3684 if (i > 3 && accIsFree)
3686 emitcode ("mov", "a,sp");
3687 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3688 emitcode ("mov", "sp,a");
3692 /* The accumulator is not free, so we will need another register */
3693 /* to clobber. No need to worry about a possible conflict with */
3694 /* the above early RECEIVE optimizations since they would have */
3695 /* freed the accumulator if they were generated. */
3697 if (IFFUNC_CALLEESAVES(sym->type))
3699 /* if it's a callee-saves function we need a saved register */
3700 if (calleesaves_saved_register >= 0)
3702 emitcode ("mov", "%s,a", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3703 emitcode ("mov", "a,sp");
3704 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3705 emitcode ("mov", "sp,a");
3706 emitcode ("mov", "a,%s", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3709 /* do it the hard way */
3711 emitcode ("inc", "sp");
3715 /* not callee-saves, we can clobber r0 */
3716 emitcode ("mov", "r0,a");
3717 emitcode ("mov", "a,sp");
3718 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3719 emitcode ("mov", "sp,a");
3720 emitcode ("mov", "a,r0");
3725 emitcode ("inc", "sp");
3730 char i = ((char) sym->xstack & 0xff);
3732 if (i > 3 && accIsFree)
3734 emitcode ("mov", "a,_spx");
3735 emitcode ("add", "a,#0x%02x", i & 0xff);
3736 emitcode ("mov", "_spx,a");
3740 emitcode ("push", "acc");
3741 emitcode ("mov", "a,_spx");
3742 emitcode ("add", "a,#0x%02x", i & 0xff);
3743 emitcode ("mov", "_spx,a");
3744 emitcode ("pop", "acc");
3749 emitcode ("inc", "_spx");
3753 /* if critical function then turn interrupts off */
3754 if (IFFUNC_ISCRITICAL (ftype))
3756 symbol *tlbl = newiTempLabel (NULL);
3757 emitcode ("setb", "c");
3758 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3759 emitcode ("clr", "c");
3761 emitcode ("push", "psw"); /* save old ea via c in psw */
3765 /*-----------------------------------------------------------------*/
3766 /* genEndFunction - generates epilogue for functions */
3767 /*-----------------------------------------------------------------*/
3769 genEndFunction (iCode * ic)
3771 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3772 lineNode *lnp = lineCurr;
3774 bitVect *regsUsedPrologue;
3775 bitVect *regsUnneeded;
3778 _G.currentFunc = NULL;
3779 if (IFFUNC_ISNAKED(sym->type))
3781 emitcode(";", "naked function: no epilogue.");
3782 if (options.debug && currFunc)
3783 debugFile->writeEndFunction (currFunc, ic, 0);
3787 if (IFFUNC_ISCRITICAL (sym->type))
3789 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3791 emitcode ("rlc", "a"); /* save c in a */
3792 emitcode ("pop", "psw"); /* restore ea via c in psw */
3793 emitcode ("mov", "ea,c");
3794 emitcode ("rrc", "a"); /* restore c from a */
3798 emitcode ("pop", "psw"); /* restore ea via c in psw */
3799 emitcode ("mov", "ea,c");
3803 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3805 if (options.useXstack)
3809 emitcode ("mov", "sp,_bp");
3810 emitcode ("pop", "_bp");
3812 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3814 emitcode ("xch", "a,_bpx");
3815 emitcode ("mov", "r0,a");
3816 emitcode ("dec", "r0");
3817 emitcode ("movx", "a,@r0");
3818 emitcode ("xch", "a,_bpx");
3819 emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3822 else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3825 emitcode ("mov", "sp,_bp");
3826 emitcode ("pop", "_bp");
3830 /* restore the register bank */
3831 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3833 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3834 || !options.useXstack)
3836 /* Special case of ISR using non-zero bank with useXstack
3839 emitcode ("pop", "psw");
3843 if (IFFUNC_ISISR (sym->type))
3847 /* now we need to restore the registers */
3848 /* if this isr has no bank i.e. is going to
3849 run with bank 0 , then we need to save more
3851 if (!FUNC_REGBANK (sym->type))
3854 /* if this function does not call any other
3855 function then we can be economical and
3856 save only those registers that are used */
3857 if (!IFFUNC_HASFCALL(sym->type))
3859 /* if any registers used */
3862 /* save the registers used */
3863 for (i = sym->regsUsed->size; i >= 0; i--)
3865 if (bitVectBitValue (sym->regsUsed, i))
3872 if (options.parms_in_bank1)
3874 for (i = 7 ; i >= 0 ; i-- )
3876 emitcode ("pop","%s",rb1regs[i]);
3879 /* this function has a function call. We cannot
3880 determine register usage so we will have to pop the
3882 unsaveRBank (0, ic, FALSE);
3887 /* This ISR uses a non-zero bank.
3889 * Restore any register banks saved by genFunction
3892 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3895 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3897 if (savedBanks & (1 << ix))
3899 unsaveRBank(ix, NULL, FALSE);
3903 if (options.useXstack)
3905 /* Restore bank AFTER calling unsaveRBank,
3906 * since it can trash r0.
3908 emitcode ("pop", "psw");
3912 if (!inExcludeList ("dph"))
3913 emitcode ("pop", "dph");
3914 if (!inExcludeList ("dpl"))
3915 emitcode ("pop", "dpl");
3916 if (!inExcludeList ("b"))
3917 emitcode ("pop", "b");
3918 if (!inExcludeList ("acc"))
3919 emitcode ("pop", "acc");
3921 rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), sym->regsUsed);
3922 if (IFFUNC_HASFCALL(sym->type) || !bitVectIsZero (rsavebits))
3923 emitcode ("pop", "bits");
3924 freeBitVect (rsavebits);
3926 /* if debug then send end of function */
3927 if (options.debug && currFunc)
3929 debugFile->writeEndFunction (currFunc, ic, 1);
3932 emitcode ("reti", "");
3936 if (IFFUNC_CALLEESAVES(sym->type))
3940 /* if any registers used */
3943 /* save the registers used */
3944 for (i = sym->regsUsed->size; i >= 0; i--)
3946 if (bitVectBitValue (sym->regsUsed, i) ||
3947 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3948 emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
3951 else if (mcs51_ptrRegReq)
3953 emitcode ("pop", "%s", REG_WITH_INDEX (R1_IDX)->dname);
3954 emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
3959 /* if debug then send end of function */
3960 if (options.debug && currFunc)
3962 debugFile->writeEndFunction (currFunc, ic, 1);
3965 if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3967 emitcode ("ljmp", "__sdcc_banked_ret");
3971 emitcode ("ret", "");
3975 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3978 /* If this was an interrupt handler using bank 0 that called another */
3979 /* function, then all registers must be saved; nothing to optimized. */
3980 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3981 && !FUNC_REGBANK(sym->type))
3984 /* There are no push/pops to optimize if not callee-saves or ISR */
3985 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3988 /* If there were stack parameters, we cannot optimize without also */
3989 /* fixing all of the stack offsets; this is too dificult to consider. */
3990 if (FUNC_HASSTACKPARM(sym->type))
3993 /* Compute the registers actually used */
3994 regsUsed = newBitVect (mcs51_nRegs);
3995 regsUsedPrologue = newBitVect (mcs51_nRegs);
3998 if (lnp->ic && lnp->ic->op == FUNCTION)
3999 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
4001 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
4003 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
4004 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
4011 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
4012 && !bitVectBitValue (regsUsed, CND_IDX))
4014 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
4015 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
4016 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
4017 bitVectUnSetBit (regsUsed, CND_IDX);
4020 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
4022 /* If this was an interrupt handler that called another function */
4023 /* function, then assume A, B, DPH, & DPL may be modified by it. */
4024 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
4026 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
4027 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
4028 regsUsed = bitVectSetBit (regsUsed, B_IDX);
4029 regsUsed = bitVectSetBit (regsUsed, A_IDX);
4030 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
4033 /* Remove the unneeded push/pops */
4034 regsUnneeded = newBitVect (mcs51_nRegs);
4037 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
4039 if (!strncmp(lnp->line, "push", 4))
4041 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
4042 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4044 connectLine (lnp->prev, lnp->next);
4045 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4048 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
4050 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
4051 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4053 connectLine (lnp->prev, lnp->next);
4054 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4061 for (idx = 0; idx < regsUnneeded->size; idx++)
4062 if (bitVectBitValue (regsUnneeded, idx))
4063 emitcode (";", "eliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
4065 freeBitVect (regsUnneeded);
4066 freeBitVect (regsUsed);
4067 freeBitVect (regsUsedPrologue);
4070 /*-----------------------------------------------------------------*/
4071 /* genRet - generate code for return statement */
4072 /*-----------------------------------------------------------------*/
4076 int size, offset = 0, pushed = 0;
4078 D (emitcode (";", "genRet"));
4080 /* if we have no return value then
4081 just generate the "ret" */
4085 /* we have something to return then
4086 move the return value into place */
4087 aopOp (IC_LEFT (ic), ic, FALSE);
4088 size = AOP_SIZE (IC_LEFT (ic));
4090 if (IS_BIT(_G.currentFunc->etype))
4092 if (!IS_OP_RUONLY (IC_LEFT (ic)))
4093 toCarry (IC_LEFT (ic));
4100 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
4103 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
4104 emitcode ("push", "%s", l);
4109 l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
4110 if (strcmp (fReturn[offset], l))
4111 emitcode ("mov", "%s,%s", fReturn[offset++], l);
4118 if (strcmp (fReturn[pushed], "a"))
4119 emitcode ("pop", fReturn[pushed]);
4121 emitcode ("pop", "acc");
4124 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
4127 /* generate a jump to the return label
4128 if the next is not the return statement */
4129 if (!(ic->next && ic->next->op == LABEL &&
4130 IC_LABEL (ic->next) == returnLabel))
4132 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
4136 /*-----------------------------------------------------------------*/
4137 /* genLabel - generates a label */
4138 /*-----------------------------------------------------------------*/
4140 genLabel (iCode * ic)
4142 /* special case never generate */
4143 if (IC_LABEL (ic) == entryLabel)
4146 emitLabel (IC_LABEL (ic));
4149 /*-----------------------------------------------------------------*/
4150 /* genGoto - generates a ljmp */
4151 /*-----------------------------------------------------------------*/
4153 genGoto (iCode * ic)
4155 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
4158 /*-----------------------------------------------------------------*/
4159 /* findLabelBackwards: walks back through the iCode chain looking */
4160 /* for the given label. Returns number of iCode instructions */
4161 /* between that label and given ic. */
4162 /* Returns zero if label not found. */
4163 /*-----------------------------------------------------------------*/
4165 findLabelBackwards (iCode * ic, int key)
4174 /* If we have any pushes or pops, we cannot predict the distance.
4175 I don't like this at all, this should be dealt with in the
4177 if (ic->op == IPUSH || ic->op == IPOP) {
4181 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4190 /*-----------------------------------------------------------------*/
4191 /* genPlusIncr :- does addition with increment if possible */
4192 /*-----------------------------------------------------------------*/
4194 genPlusIncr (iCode * ic)
4196 unsigned int icount;
4197 unsigned int size = getDataSize (IC_RESULT (ic));
4199 /* will try to generate an increment */
4200 /* if the right side is not a literal
4202 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4205 icount = (unsigned int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4207 D(emitcode (";","genPlusIncr"));
4209 /* if increment >=16 bits in register or direct space */
4210 if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG ||
4211 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4212 (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4213 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4214 !isOperandVolatile (IC_RESULT (ic), FALSE) &&
4223 /* If the next instruction is a goto and the goto target
4224 * is < 10 instructions previous to this, we can generate
4225 * jumps straight to that target.
4227 if (ic->next && ic->next->op == GOTO
4228 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4229 && labelRange <= 10)
4231 D (emitcode (";", "tail increment optimized (range %d)", labelRange));
4232 tlbl = IC_LABEL (ic->next);
4237 tlbl = newiTempLabel (NULL);
4240 l = aopGet (IC_RESULT (ic), LSB, FALSE, FALSE);
4241 emitcode ("inc", "%s", l);
4242 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4243 IS_AOP_PREG (IC_RESULT (ic)))
4245 emitcode ("cjne", "%s,#0x00,%05d$", l, tlbl->key + 100);
4249 emitcode ("clr", "a");
4250 emitcode ("cjne", "a,%s,%05d$", l, tlbl->key + 100);
4253 l = aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE);
4254 emitcode ("inc", "%s", l);
4257 if (!strcmp(l, "acc"))
4259 emitcode("jnz", "!tlabel", tlbl->key + 100);
4261 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4262 IS_AOP_PREG (IC_RESULT (ic)))
4264 emitcode ("cjne", "%s,#0x00,%05d$", l, tlbl->key + 100);
4268 emitcode ("cjne", "a,%s,%05d$", l, tlbl->key + 100);
4271 l = aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE);
4272 emitcode ("inc", "%s", l);
4276 if (!strcmp(l, "acc"))
4278 emitcode("jnz", "!tlabel", tlbl->key + 100);
4280 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4281 IS_AOP_PREG (IC_RESULT (ic)))
4283 emitcode ("cjne", "%s,#0x00,%05d$", l, tlbl->key + 100);
4287 emitcode ("cjne", "a,%s,%05d$", l, tlbl->key + 100);
4290 l = aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE);
4291 emitcode ("inc", "%s", l);
4301 /* if result is dptr */
4302 if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
4303 (AOP_SIZE (IC_RESULT (ic)) == 2) &&
4304 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
4305 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
4307 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4313 if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
4316 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0);
4317 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1);
4319 emitcode ("inc", "dptr");
4324 /* if the literal value of the right hand side
4325 is greater than 4 then it is not worth it */
4329 /* if the sizes are greater than 1 then we cannot */
4330 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4331 AOP_SIZE (IC_LEFT (ic)) > 1)
4334 /* we can if the aops of the left & result match or
4335 if they are in registers and the registers are the
4337 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4341 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4342 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4343 aopPut (IC_RESULT (ic), "a", 0);
4349 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4358 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4359 emitcode ("inc", "a");
4360 aopPut (IC_RESULT (ic), "a", 0);
4367 /*-----------------------------------------------------------------*/
4368 /* outBitAcc - output a bit in acc */
4369 /*-----------------------------------------------------------------*/
4371 outBitAcc (operand * result)
4373 symbol *tlbl = newiTempLabel (NULL);
4374 /* if the result is a bit */
4375 if (AOP_TYPE (result) == AOP_CRY)
4377 aopPut (result, "a", 0);
4381 emitcode ("jz", "%05d$", tlbl->key + 100);
4382 emitcode ("mov", "a,%s", one);
4388 /*-----------------------------------------------------------------*/
4389 /* genPlusBits - generates code for addition of two bits */
4390 /*-----------------------------------------------------------------*/
4392 genPlusBits (iCode * ic)
4394 D (emitcode (";", "genPlusBits"));
4396 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4397 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4399 symbol *lbl = newiTempLabel (NULL);
4400 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4401 emitcode ("cpl", "c");
4403 outBitC (IC_RESULT (ic));
4407 emitcode ("clr", "a");
4408 emitcode ("rlc", "a");
4409 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4410 emitcode ("addc", "a,%s", zero);
4411 outAcc (IC_RESULT (ic));
4416 /* This is the original version of this code.
4418 * This is being kept around for reference,
4419 * because I am not entirely sure I got it right...
4422 adjustArithmeticResult (iCode * ic)
4424 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4425 AOP_SIZE (IC_LEFT (ic)) == 3 &&
4426 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4427 aopPut (IC_RESULT (ic),
4428 aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4431 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4432 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4433 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4434 aopPut (IC_RESULT (ic),
4435 aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4438 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4439 AOP_SIZE (IC_LEFT (ic)) < 3 &&
4440 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4441 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4442 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4445 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4446 aopPut (IC_RESULT (ic), buffer, 2);
4450 /* This is the pure and virtuous version of this code.
4451 * I'm pretty certain it's right, but not enough to toss the old
4455 adjustArithmeticResult (iCode * ic)
4457 if (opIsGptr (IC_RESULT (ic)))
4461 if (opIsGptr (IC_LEFT (ic)))
4463 if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4465 aopPut (IC_RESULT (ic),
4466 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4472 if (opIsGptr (IC_RIGHT (ic)))
4474 if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4476 aopPut (IC_RESULT (ic),
4477 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4483 if (IC_LEFT (ic) && AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4484 IC_RIGHT (ic) && AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4485 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4486 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4488 SNPRINTF (buffer, sizeof(buffer),
4489 "#0x%02x", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4490 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4493 if (IC_LEFT (ic) && AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4494 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4496 SNPRINTF (buffer, sizeof(buffer),
4497 "#0x%02x", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4498 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4501 if (IC_RIGHT (ic) && AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4502 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4504 SNPRINTF (buffer, sizeof(buffer),
4505 "#0x%02x", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_RIGHT (ic)))), NULL, NULL));
4506 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4513 /*-----------------------------------------------------------------*/
4514 /* genPlus - generates code for addition */
4515 /*-----------------------------------------------------------------*/
4517 genPlus (iCode * ic)
4519 int size, offset = 0;
4522 bool swappedLR = FALSE;
4523 operand *leftOp, *rightOp;
4526 D (emitcode (";", "genPlus"));
4528 /* special cases :- */
4530 aopOp (IC_LEFT (ic), ic, FALSE);
4531 aopOp (IC_RIGHT (ic), ic, FALSE);
4532 aopOp (IC_RESULT (ic), ic, TRUE);
4534 /* if literal, literal on the right or
4535 if left requires ACC or right is already
4537 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4538 (AOP_NEEDSACC (IC_LEFT (ic))) ||
4539 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4541 operand *t = IC_RIGHT (ic);
4542 IC_RIGHT (ic) = IC_LEFT (ic);
4547 /* if both left & right are in bit
4549 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4550 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4556 /* if left in bit space & right literal */
4557 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4558 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4560 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4561 /* if result in bit space */
4562 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4564 if (ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4565 emitcode ("cpl", "c");
4566 outBitC (IC_RESULT (ic));
4570 size = getDataSize (IC_RESULT (ic));
4573 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4574 emitcode ("addc", "a,%s", zero);
4575 aopPut (IC_RESULT (ic), "a", offset++);
4581 /* if I can do an increment instead
4582 of add then GOOD for ME */
4583 if (genPlusIncr (ic) == TRUE)
4586 size = getDataSize (IC_RESULT (ic));
4587 leftOp = IC_LEFT(ic);
4588 rightOp = IC_RIGHT(ic);
4591 /* if this is an add for an array access
4592 at a 256 byte boundary */
4594 && AOP_TYPE (op) == AOP_IMMD
4596 && IS_SPEC (OP_SYM_ETYPE (op))
4597 && SPEC_ABSA (OP_SYM_ETYPE (op))
4598 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4601 D(emitcode (";", "genPlus aligned array"));
4602 aopPut (IC_RESULT (ic),
4603 aopGet (rightOp, 0, FALSE, FALSE),
4606 if( 1 == getDataSize (IC_RIGHT (ic)) )
4608 aopPut (IC_RESULT (ic),
4609 aopGet (leftOp, 1, FALSE, FALSE),
4614 MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4615 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4616 aopPut (IC_RESULT (ic), "a", 1);
4621 /* if the lower bytes of a literal are zero skip the addition */
4622 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4624 while ((0 == ((unsigned int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4625 (skip_bytes+1 < size))
4630 D(emitcode (";", "genPlus shortcut"));
4635 if( offset >= skip_bytes )
4637 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4640 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4642 emitcode("xch", "a,b");
4643 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4644 emitcode (add, "a,b");
4647 else if (aopGetUsesAcc (leftOp, offset))
4649 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4650 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4654 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4655 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4657 aopPut (IC_RESULT (ic), "a", offset);
4658 add = "addc"; /* further adds must propagate carry */
4662 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4663 isOperandVolatile (IC_RESULT (ic), FALSE))
4666 aopPut (IC_RESULT (ic),
4667 aopGet (leftOp, offset, FALSE, FALSE),
4674 adjustArithmeticResult (ic);
4677 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4680 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4681 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4685 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4686 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4690 /*-----------------------------------------------------------------*/
4691 /* genMinusDec :- does subtraction with decrement if possible */
4692 /*-----------------------------------------------------------------*/
4694 genMinusDec (iCode * ic)
4696 unsigned int icount;
4697 unsigned int size = getDataSize (IC_RESULT (ic));
4699 /* will try to generate an increment */
4700 /* if the right side is not a literal
4702 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4705 /* if the literal value of the right hand side
4706 is greater than 4 then it is not worth it */
4707 if ((icount = (unsigned int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4710 D (emitcode (";", "genMinusDec"));
4712 /* if decrement >=16 bits in register or direct space */
4713 if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG ||
4714 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4715 (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4716 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4725 /* If the next instruction is a goto and the goto target
4726 * is <= 10 instructions previous to this, we can generate
4727 * jumps straight to that target.
4729 if (ic->next && ic->next->op == GOTO
4730 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4731 && labelRange <= 10)
4733 D (emitcode (";", "tail decrement optimized (range %d)", labelRange));
4734 tlbl = IC_LABEL (ic->next);
4739 tlbl = newiTempLabel (NULL);
4743 l = aopGet (IC_RESULT (ic), LSB, FALSE, FALSE);
4744 emitcode ("dec", "%s", l);
4746 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4747 IS_AOP_PREG (IC_RESULT (ic)))
4749 emitcode ("cjne", "%s,#0xff,%05d$", l, tlbl->key + 100);
4753 emitcode ("mov", "a,#0xff");
4754 emitcode ("cjne", "a,%s,%05d$", l, tlbl->key + 100);
4756 l = aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE);
4757 emitcode ("dec", "%s", l);
4760 if (!strcmp(l, "acc"))
4762 emitcode("jnz", "!tlabel", tlbl->key + 100);
4764 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4765 IS_AOP_PREG (IC_RESULT (ic)))
4767 emitcode ("cjne", "%s,#0xff,%05d$", l, tlbl->key + 100);
4771 emitcode ("cjne", "a,%s,%05d$", l, tlbl->key + 100);
4773 l = aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE);
4774 emitcode ("dec", "%s", l);
4778 if (!strcmp(l, "acc"))
4780 emitcode("jnz", "!tlabel", tlbl->key + 100);
4782 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4783 IS_AOP_PREG (IC_RESULT (ic)))
4785 emitcode ("cjne", "%s,#0xff,%05d$", l, tlbl->key + 100);
4789 emitcode ("cjne", "a,%s,%05d$", l, tlbl->key + 100);
4791 l = aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE);
4792 emitcode ("dec", "%s", l);
4801 /* if the sizes are greater than 1 then we cannot */
4802 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4803 AOP_SIZE (IC_LEFT (ic)) > 1)
4806 /* we can if the aops of the left & result match or
4807 if they are in registers and the registers are the
4809 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4813 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4815 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4820 l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
4825 emitcode ("dec", "%s", l);
4828 if (AOP_NEEDSACC (IC_RESULT (ic)))
4829 aopPut (IC_RESULT (ic), "a", 0);
4836 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4837 emitcode ("dec", "a");
4838 aopPut (IC_RESULT (ic), "a", 0);
4845 /*-----------------------------------------------------------------*/
4846 /* addSign - complete with sign */
4847 /*-----------------------------------------------------------------*/
4849 addSign (operand * result, int offset, int sign)
4851 int size = (getDataSize (result) - offset);
4856 emitcode ("rlc", "a");
4857 emitcode ("subb", "a,acc");
4860 aopPut (result, "a", offset++);
4867 aopPut (result, zero, offset++);
4873 /*-----------------------------------------------------------------*/
4874 /* genMinusBits - generates code for subtraction of two bits */
4875 /*-----------------------------------------------------------------*/
4877 genMinusBits (iCode * ic)
4879 symbol *lbl = newiTempLabel (NULL);
4881 D (emitcode (";", "genMinusBits"));
4883 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4885 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4886 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4887 emitcode ("cpl", "c");
4889 outBitC (IC_RESULT (ic));
4893 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4894 emitcode ("subb", "a,acc");
4895 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4896 emitcode ("inc", "a");
4898 aopPut (IC_RESULT (ic), "a", 0);
4899 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4903 /*-----------------------------------------------------------------*/
4904 /* genMinus - generates code for subtraction */
4905 /*-----------------------------------------------------------------*/
4907 genMinus (iCode * ic)
4909 int size, offset = 0;
4911 D (emitcode (";", "genMinus"));
4913 aopOp (IC_LEFT (ic), ic, FALSE);
4914 aopOp (IC_RIGHT (ic), ic, FALSE);
4915 aopOp (IC_RESULT (ic), ic, TRUE);
4917 /* special cases :- */
4918 /* if both left & right are in bit space */
4919 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4920 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4926 /* if I can do an decrement instead
4927 of subtract then GOOD for ME */
4928 if (genMinusDec (ic) == TRUE)
4931 size = getDataSize (IC_RESULT (ic));
4933 /* if literal, add a,#-lit, else normal subb */
4934 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4936 unsigned long lit = 0L;
4937 bool useCarry = FALSE;
4939 lit = ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4944 if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4946 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4947 if (!offset && !size && lit== (unsigned long) -1)
4949 emitcode ("dec", "a");
4953 /* first add without previous c */
4954 emitcode ("add", "a,#0x%02x",
4955 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4960 emitcode ("addc", "a,#0x%02x",
4961 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4963 aopPut (IC_RESULT (ic), "a", offset++);
4967 /* no need to add zeroes */
4968 if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4970 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4979 operand *leftOp, *rightOp;
4981 leftOp = IC_LEFT(ic);
4982 rightOp = IC_RIGHT(ic);
4986 if (aopGetUsesAcc(rightOp, offset)) {
4987 if (aopGetUsesAcc(leftOp, offset)) {
4990 MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4992 emitcode ("mov", "b,a");
4995 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4996 emitcode ("subb", "a,b");
4999 /* reverse subtraction with 2's complement */
5001 emitcode( "setb", "c");
5003 emitcode( "cpl", "c");
5004 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
5005 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
5006 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
5007 emitcode("cpl", "a");
5008 if (size) /* skip if last byte */
5009 emitcode( "cpl", "c");
5012 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
5015 emitcode ("subb", "a,%s",
5016 aopGet(rightOp, offset, FALSE, TRUE));
5019 aopPut (IC_RESULT (ic), "a", offset++);
5023 adjustArithmeticResult (ic);
5026 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5027 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5028 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5032 /*-----------------------------------------------------------------*/
5033 /* genMultbits :- multiplication of bits */
5034 /*-----------------------------------------------------------------*/
5036 genMultbits (operand * left,
5040 D (emitcode (";", "genMultbits"));
5042 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5043 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5047 /*-----------------------------------------------------------------*/
5048 /* genMultOneByte : 8*8=8/16 bit multiplication */
5049 /*-----------------------------------------------------------------*/
5051 genMultOneByte (operand * left,
5056 int size = AOP_SIZE (result);
5057 bool runtimeSign, compiletimeSign;
5058 bool lUnsigned, rUnsigned, pushedB;
5060 D (emitcode (";", "genMultOneByte"));
5062 if (size < 1 || size > 2)
5064 /* this should never happen */
5065 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
5066 AOP_SIZE(result), __FILE__, lineno);
5070 /* (if two literals: the value is computed before) */
5071 /* if one literal, literal on the right */
5072 if (AOP_TYPE (left) == AOP_LIT)
5077 /* emitcode (";", "swapped left and right"); */
5079 /* if no literal, unsigned on the right: shorter code */
5080 if ( AOP_TYPE (right) != AOP_LIT
5081 && SPEC_USIGN (getSpec (operandType (left))))
5088 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5089 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5093 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
5094 no need to take care about the signedness! */
5095 || (lUnsigned && rUnsigned))
5097 /* just an unsigned 8 * 8 = 8 multiply
5099 /* emitcode (";","unsigned"); */
5100 /* TODO: check for accumulator clash between left & right aops? */
5102 if (AOP_TYPE (right) == AOP_LIT)
5104 /* moving to accumulator first helps peepholes */
5105 MOVA (aopGet (left, 0, FALSE, FALSE));
5106 MOVB (aopGet (right, 0, FALSE, FALSE));
5110 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5111 MOVA (aopGet (left, 0, FALSE, FALSE));
5114 emitcode ("mul", "ab");
5115 aopPut (result, "a", 0);
5117 aopPut (result, "b", 1);
5123 /* we have to do a signed multiply */
5124 /* emitcode (";", "signed"); */
5126 /* now sign adjust for both left & right */
5128 /* let's see what's needed: */
5129 /* apply negative sign during runtime */
5130 runtimeSign = FALSE;
5131 /* negative sign from literals */
5132 compiletimeSign = FALSE;
5136 if (AOP_TYPE(left) == AOP_LIT)
5138 /* signed literal */
5139 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5141 compiletimeSign = TRUE;
5144 /* signed but not literal */
5150 if (AOP_TYPE(right) == AOP_LIT)
5152 /* signed literal */
5153 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
5155 compiletimeSign ^= TRUE;
5158 /* signed but not literal */
5162 /* initialize F0, which stores the runtime sign */
5165 if (compiletimeSign)
5166 emitcode ("setb", "F0"); /* set sign flag */
5168 emitcode ("clr", "F0"); /* reset sign flag */
5171 /* save the signs of the operands */
5172 if (AOP_TYPE(right) == AOP_LIT)
5174 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
5176 if (!rUnsigned && val < 0)
5177 emitcode ("mov", "b,#0x%02x", -val);
5179 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5181 else /* ! literal */
5183 if (rUnsigned) /* emitcode (";", "signed"); */
5184 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5187 MOVA (aopGet (right, 0, FALSE, FALSE));
5188 lbl = newiTempLabel (NULL);
5189 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5190 emitcode ("cpl", "F0"); /* complement sign flag */
5191 emitcode ("cpl", "a"); /* 2's complement */
5192 emitcode ("inc", "a");
5194 emitcode ("mov", "b,a");
5198 if (AOP_TYPE(left) == AOP_LIT)
5200 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5202 if (!lUnsigned && val < 0)
5203 emitcode ("mov", "a,#0x%02x", -val);
5205 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5207 else /* ! literal */
5209 MOVA (aopGet (left, 0, FALSE, FALSE));
5213 lbl = newiTempLabel (NULL);
5214 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5215 emitcode ("cpl", "F0"); /* complement sign flag */
5216 emitcode ("cpl", "a"); /* 2's complement */
5217 emitcode ("inc", "a");
5222 /* now the multiplication */
5223 emitcode ("mul", "ab");
5224 if (runtimeSign || compiletimeSign)
5226 lbl = newiTempLabel (NULL);
5228 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5229 emitcode ("cpl", "a"); /* lsb 2's complement */
5231 emitcode ("inc", "a"); /* inc doesn't set carry flag */
5234 emitcode ("add", "a,#0x01"); /* this sets carry flag */
5235 emitcode ("xch", "a,b");
5236 emitcode ("cpl", "a"); /* msb 2's complement */
5237 emitcode ("addc", "a,#0x00");
5238 emitcode ("xch", "a,b");
5242 aopPut (result, "a", 0);
5244 aopPut (result, "b", 1);
5249 /*-----------------------------------------------------------------*/
5250 /* genMult - generates code for multiplication */
5251 /*-----------------------------------------------------------------*/
5253 genMult (iCode * ic)
5255 operand *left = IC_LEFT (ic);
5256 operand *right = IC_RIGHT (ic);
5257 operand *result = IC_RESULT (ic);
5259 D (emitcode (";", "genMult"));
5261 /* assign the asmops */
5262 aopOp (left, ic, FALSE);
5263 aopOp (right, ic, FALSE);
5264 aopOp (result, ic, TRUE);
5266 /* special cases first */
5268 if (AOP_TYPE (left) == AOP_CRY &&
5269 AOP_TYPE (right) == AOP_CRY)
5271 genMultbits (left, right, result);
5275 /* if both are of size == 1 */
5276 #if 0 // one of them can be a sloc shared with the result
5277 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
5279 if (getSize(operandType(left)) == 1 &&
5280 getSize(operandType(right)) == 1)
5283 genMultOneByte (left, right, result);
5287 /* should have been converted to function call */
5288 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
5289 getSize(OP_SYMBOL(right)->type));
5293 freeAsmop (result, NULL, ic, TRUE);
5294 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5295 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5298 /*-----------------------------------------------------------------*/
5299 /* genDivbits :- division of bits */
5300 /*-----------------------------------------------------------------*/
5302 genDivbits (operand * left,
5309 D(emitcode (";", "genDivbits"));
5313 /* the result must be bit */
5314 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5315 l = aopGet (left, 0, FALSE, FALSE);
5319 emitcode ("div", "ab");
5320 emitcode ("rrc", "a");
5324 aopPut (result, "c", 0);
5327 /*-----------------------------------------------------------------*/
5328 /* genDivOneByte : 8 bit division */
5329 /*-----------------------------------------------------------------*/
5331 genDivOneByte (operand * left,
5335 bool lUnsigned, rUnsigned, pushedB;
5336 bool runtimeSign, compiletimeSign;
5337 bool accuse = FALSE;
5338 bool pushedA = FALSE;
5342 D(emitcode (";", "genDivOneByte"));
5344 /* Why is it necessary that genDivOneByte() can return an int result?
5347 volatile unsigned char uc;
5348 volatile signed char sc1, sc2;
5361 In all cases a one byte result would overflow, the following cast to int
5362 would return the wrong result.
5364 Two possible solution:
5365 a) cast operands to int, if ((unsigned) / (signed)) or
5366 ((signed) / (signed))
5367 b) return an 16 bit signed int; this is what we're doing here!
5370 size = AOP_SIZE (result) - 1;
5372 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5373 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5377 /* signed or unsigned */
5378 if (lUnsigned && rUnsigned)
5380 /* unsigned is easy */
5381 MOVB (aopGet (right, 0, FALSE, FALSE));
5382 MOVA (aopGet (left, 0, FALSE, FALSE));
5383 emitcode ("div", "ab");
5384 aopPut (result, "a", 0);
5386 aopPut (result, zero, offset++);
5392 /* signed is a little bit more difficult */
5394 /* now sign adjust for both left & right */
5396 /* let's see what's needed: */
5397 /* apply negative sign during runtime */
5398 runtimeSign = FALSE;
5399 /* negative sign from literals */
5400 compiletimeSign = FALSE;
5404 if (AOP_TYPE(left) == AOP_LIT)
5406 /* signed literal */
5407 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5409 compiletimeSign = TRUE;
5412 /* signed but not literal */
5418 if (AOP_TYPE(right) == AOP_LIT)
5420 /* signed literal */
5421 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
5423 compiletimeSign ^= TRUE;
5426 /* signed but not literal */
5430 /* initialize F0, which stores the runtime sign */
5433 if (compiletimeSign)
5434 emitcode ("setb", "F0"); /* set sign flag */
5436 emitcode ("clr", "F0"); /* reset sign flag */
5439 /* save the signs of the operands */
5440 if (AOP_TYPE(right) == AOP_LIT)
5442 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
5444 if (!rUnsigned && val < 0)
5445 emitcode ("mov", "b,#0x%02x", -val);
5447 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5449 else /* ! literal */
5452 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5455 MOVA (aopGet (right, 0, FALSE, FALSE));
5456 lbl = newiTempLabel (NULL);
5457 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5458 emitcode ("cpl", "F0"); /* complement sign flag */
5459 emitcode ("cpl", "a"); /* 2's complement */
5460 emitcode ("inc", "a");
5462 emitcode ("mov", "b,a");
5466 if (AOP_TYPE(left) == AOP_LIT)
5468 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5470 if (!lUnsigned && val < 0)
5471 emitcode ("mov", "a,#0x%02x", -val);
5473 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5475 else /* ! literal */
5477 MOVA (aopGet (left, 0, FALSE, FALSE));
5481 lbl = newiTempLabel (NULL);
5482 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5483 emitcode ("cpl", "F0"); /* complement sign flag */
5484 emitcode ("cpl", "a"); /* 2's complement */
5485 emitcode ("inc", "a");
5490 /* now the division */
5491 emitcode ("div", "ab");
5493 if (runtimeSign || compiletimeSign)
5495 lbl = newiTempLabel (NULL);
5497 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5498 emitcode ("cpl", "a"); /* lsb 2's complement */
5499 emitcode ("inc", "a");
5502 accuse = aopPut (result, "a", 0);
5505 /* msb is 0x00 or 0xff depending on the sign */
5510 emitcode ("push", "acc");
5513 emitcode ("mov", "c,F0");
5514 emitcode ("subb", "a,acc");
5516 aopPut (result, "a", offset++);
5518 else /* compiletimeSign */
5520 if (aopPutUsesAcc (result, "#0xff", offset))
5522 emitcode ("push", "acc");
5526 aopPut (result, "#0xff", offset++);
5532 aopPut (result, "a", 0);
5534 aopPut (result, zero, offset++);
5538 emitcode ("pop", "acc");
5542 /*-----------------------------------------------------------------*/
5543 /* genDiv - generates code for division */
5544 /*-----------------------------------------------------------------*/
5548 operand *left = IC_LEFT (ic);
5549 operand *right = IC_RIGHT (ic);
5550 operand *result = IC_RESULT (ic);
5552 D (emitcode (";", "genDiv"));
5554 /* assign the asmops */
5555 aopOp (left, ic, FALSE);
5556 aopOp (right, ic, FALSE);
5557 aopOp (result, ic, TRUE);
5559 /* special cases first */
5561 if (AOP_TYPE (left) == AOP_CRY &&
5562 AOP_TYPE (right) == AOP_CRY)
5564 genDivbits (left, right, result);
5568 /* if both are of size == 1 */
5569 if (AOP_SIZE (left) == 1 &&
5570 AOP_SIZE (right) == 1)
5572 genDivOneByte (left, right, result);
5576 /* should have been converted to function call */
5579 freeAsmop (result, NULL, ic, TRUE);
5580 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5581 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5584 /*-----------------------------------------------------------------*/
5585 /* genModbits :- modulus of bits */
5586 /*-----------------------------------------------------------------*/
5588 genModbits (operand * left,
5595 D (emitcode (";", "genModbits"));
5599 /* the result must be bit */
5600 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5601 l = aopGet (left, 0, FALSE, FALSE);
5605 emitcode ("div", "ab");
5606 emitcode ("mov", "a,b");
5607 emitcode ("rrc", "a");
5611 aopPut (result, "c", 0);
5614 /*-----------------------------------------------------------------*/
5615 /* genModOneByte : 8 bit modulus */
5616 /*-----------------------------------------------------------------*/
5618 genModOneByte (operand * left,
5622 bool lUnsigned, rUnsigned, pushedB;
5623 bool runtimeSign, compiletimeSign;
5627 D (emitcode (";", "genModOneByte"));
5629 size = AOP_SIZE (result) - 1;
5631 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5632 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5634 /* if right is a literal, check it for 2^n */
5635 if (AOP_TYPE(right) == AOP_LIT)
5637 unsigned char val = abs((int) operandLitValue(right));
5638 symbol *lbl2 = NULL;
5642 case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5651 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5652 "modulus of unsigned char by 2^n literal shouldn't be processed here");
5653 /* because iCode should have been changed to genAnd */
5654 /* see file "SDCCopt.c", function "convertToFcall()" */
5656 MOVA (aopGet (left, 0, FALSE, FALSE));
5657 emitcode ("mov", "c,acc.7");
5658 emitcode ("anl", "a,#0x%02x", val - 1);
5659 lbl = newiTempLabel (NULL);
5660 emitcode ("jz", "%05d$", (lbl->key + 100));
5661 emitcode ("jnc", "%05d$", (lbl->key + 100));
5662 emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5668 aopPut (result, "a", 0);
5670 aopPut (result, "#0xff", offs2++);
5671 lbl2 = newiTempLabel (NULL);
5672 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5675 aopPut (result, "a", 0);
5677 aopPut (result, zero, offset++);
5691 /* signed or unsigned */
5692 if (lUnsigned && rUnsigned)
5694 /* unsigned is easy */
5695 MOVB (aopGet (right, 0, FALSE, FALSE));
5696 MOVA (aopGet (left, 0, FALSE, FALSE));
5697 emitcode ("div", "ab");
5698 aopPut (result, "b", 0);
5700 aopPut (result, zero, offset++);
5706 /* signed is a little bit more difficult */
5708 /* now sign adjust for both left & right */
5710 /* modulus: sign of the right operand has no influence on the result! */
5711 if (AOP_TYPE(right) == AOP_LIT)
5713 signed char val = (char) operandLitValue(right);
5715 if (!rUnsigned && val < 0)
5716 emitcode ("mov", "b,#0x%02x", -val);
5718 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5720 else /* not literal */
5723 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5726 MOVA (aopGet (right, 0, FALSE, FALSE));
5727 lbl = newiTempLabel (NULL);
5728 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5729 emitcode ("cpl", "a"); /* 2's complement */
5730 emitcode ("inc", "a");
5732 emitcode ("mov", "b,a");
5736 /* let's see what's needed: */
5737 /* apply negative sign during runtime */
5738 runtimeSign = FALSE;
5739 /* negative sign from literals */
5740 compiletimeSign = FALSE;
5742 /* sign adjust left side */
5743 if (AOP_TYPE(left) == AOP_LIT)
5745 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5747 if (!lUnsigned && val < 0)
5749 compiletimeSign = TRUE; /* set sign flag */
5750 emitcode ("mov", "a,#0x%02x", -val);
5753 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5755 else /* ! literal */
5757 MOVA (aopGet (left, 0, FALSE, FALSE));
5762 emitcode ("clr", "F0"); /* clear sign flag */
5764 lbl = newiTempLabel (NULL);
5765 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5766 emitcode ("setb", "F0"); /* set sign flag */
5767 emitcode ("cpl", "a"); /* 2's complement */
5768 emitcode ("inc", "a");
5773 /* now the modulus */
5774 emitcode ("div", "ab");
5776 if (runtimeSign || compiletimeSign)
5778 emitcode ("mov", "a,b");
5779 lbl = newiTempLabel (NULL);
5781 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5782 emitcode ("cpl", "a"); /* 2's complement */
5783 emitcode ("inc", "a");
5786 aopPut (result, "a", 0);
5789 /* msb is 0x00 or 0xff depending on the sign */
5792 emitcode ("mov", "c,F0");
5793 emitcode ("subb", "a,acc");
5795 aopPut (result, "a", offset++);
5797 else /* compiletimeSign */
5799 aopPut (result, "#0xff", offset++);
5804 aopPut (result, "b", 0);
5806 aopPut (result, zero, offset++);
5812 /*-----------------------------------------------------------------*/
5813 /* genMod - generates code for division */
5814 /*-----------------------------------------------------------------*/
5818 operand *left = IC_LEFT (ic);
5819 operand *right = IC_RIGHT (ic);
5820 operand *result = IC_RESULT (ic);
5822 D (emitcode (";", "genMod"));
5824 /* assign the asmops */
5825 aopOp (left, ic, FALSE);
5826 aopOp (right, ic, FALSE);
5827 aopOp (result, ic, TRUE);
5829 /* special cases first */
5831 if (AOP_TYPE (left) == AOP_CRY &&
5832 AOP_TYPE (right) == AOP_CRY)
5834 genModbits (left, right, result);
5838 /* if both are of size == 1 */
5839 if (AOP_SIZE (left) == 1 &&
5840 AOP_SIZE (right) == 1)
5842 genModOneByte (left, right, result);
5846 /* should have been converted to function call */
5850 freeAsmop (result, NULL, ic, TRUE);
5851 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5852 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5855 /*-----------------------------------------------------------------*/
5856 /* genIfxJump :- will create a jump depending on the ifx */
5857 /*-----------------------------------------------------------------*/
5859 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result, iCode *popIc)
5862 symbol *tlbl = newiTempLabel (NULL);
5865 /* if there is something to be popped then do it first */
5866 popForBranch (popIc, TRUE);
5868 D (emitcode (";", "genIfxJump"));
5870 /* if true label then we jump if condition
5874 jlbl = IC_TRUE (ic);
5875 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5876 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5880 /* false label is present */
5881 jlbl = IC_FALSE (ic);
5882 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5883 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5885 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5886 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5888 emitcode (inst, "%05d$", tlbl->key + 100);
5889 freeForBranchAsmop (result);
5890 freeForBranchAsmop (right);
5891 freeForBranchAsmop (left);
5892 emitcode ("ljmp", "%05d$", jlbl->key + 100);
5895 /* mark the icode as generated */
5899 /*-----------------------------------------------------------------*/
5900 /* genCmp :- greater or less than comparison */
5901 /*-----------------------------------------------------------------*/
5903 genCmp (operand * left, operand * right,
5904 operand * result, iCode * ifx, int sign, iCode *ic)
5906 int size, offset = 0;
5907 unsigned long lit = 0L;
5910 D (emitcode (";", "genCmp"));
5912 /* if left & right are bit variables */
5913 if (AOP_TYPE (left) == AOP_CRY &&
5914 AOP_TYPE (right) == AOP_CRY)
5916 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5917 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5921 /* subtract right from left if at the
5922 end the carry flag is set then we know that
5923 left is greater than right */
5924 size = max (AOP_SIZE (left), AOP_SIZE (right));
5926 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5927 if ((size == 1) && !sign &&
5928 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5930 symbol *lbl = newiTempLabel (NULL);
5931 emitcode ("cjne", "%s,%s,%05d$",
5932 aopGet (left, offset, FALSE, FALSE),
5933 aopGet (right, offset, FALSE, FALSE),
5939 if (AOP_TYPE (right) == AOP_LIT)
5941 lit = ulFromVal (AOP (right)->aopu.aop_lit);
5942 /* optimize if(x < 0) or if(x >= 0) */
5951 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5952 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5954 genIfxJump (ifx, "acc.7", left, right, result, ic->next);
5955 freeAsmop (right, NULL, ic, TRUE);
5956 freeAsmop (left, NULL, ic, TRUE);
5962 emitcode ("rlc", "a");
5969 int bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5970 while (size && (bytelit == 0))
5973 bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5979 MOVA (aopGet (left, offset, FALSE, FALSE));
5980 if (sign && size == 0)
5982 emitcode ("xrl", "a,#0x80");
5983 emitcode ("subb", "a,#0x%02x",
5984 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5988 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5998 bool pushedB = FALSE;
5999 rightInB = aopGetUsesAcc(right, offset);
6003 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
6005 MOVA (aopGet (left, offset, FALSE, FALSE));
6006 if (sign && size == 0)
6008 emitcode ("xrl", "a,#0x80");
6013 MOVB (aopGet (right, offset, FALSE, FALSE));
6015 emitcode ("xrl", "b,#0x80");
6016 emitcode ("subb", "a,b");
6021 emitcode ("subb", "a,b");
6023 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
6033 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6034 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6035 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6041 /* if the result is used in the next
6042 ifx conditional branch then generate
6043 code a little differently */
6046 genIfxJump (ifx, "c", NULL, NULL, result, ic->next);
6052 /* leave the result in acc */
6056 /*-----------------------------------------------------------------*/
6057 /* genCmpGt :- greater than comparison */
6058 /*-----------------------------------------------------------------*/
6060 genCmpGt (iCode * ic, iCode * ifx)
6062 operand *left, *right, *result;
6063 sym_link *letype, *retype;
6066 D (emitcode (";", "genCmpGt"));
6068 left = IC_LEFT (ic);
6069 right = IC_RIGHT (ic);
6070 result = IC_RESULT (ic);
6072 letype = getSpec (operandType (left));
6073 retype = getSpec (operandType (right));
6074 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
6075 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
6076 /* assign the asmops */
6077 aopOp (result, ic, TRUE);
6078 aopOp (left, ic, FALSE);
6079 aopOp (right, ic, FALSE);
6081 genCmp (right, left, result, ifx, sign, ic);
6083 freeAsmop (result, NULL, ic, TRUE);
6086 /*-----------------------------------------------------------------*/
6087 /* genCmpLt - less than comparisons */
6088 /*-----------------------------------------------------------------*/
6090 genCmpLt (iCode * ic, iCode * ifx)
6092 operand *left, *right, *result;
6093 sym_link *letype, *retype;
6096 D (emitcode (";", "genCmpLt"));
6098 left = IC_LEFT (ic);
6099 right = IC_RIGHT (ic);
6100 result = IC_RESULT (ic);
6102 letype = getSpec (operandType (left));
6103 retype = getSpec (operandType (right));
6104 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
6105 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
6106 /* assign the asmops */
6107 aopOp (result, ic, TRUE);
6108 aopOp (left, ic, FALSE);
6109 aopOp (right, ic, FALSE);
6111 genCmp (left, right, result, ifx, sign, ic);
6113 freeAsmop (result, NULL, ic, TRUE);
6116 /*-----------------------------------------------------------------*/
6117 /* gencjneshort - compare and jump if not equal */
6118 /*-----------------------------------------------------------------*/
6120 gencjneshort (operand * left, operand * right, symbol * lbl)
6122 int size = max (AOP_SIZE (left), AOP_SIZE (right));
6124 unsigned long lit = 0L;
6126 D (emitcode (";", "gencjneshort"));
6128 /* if the left side is a literal or
6129 if the right is in a pointer register and left
6131 if ((AOP_TYPE (left) == AOP_LIT) ||
6132 (AOP_TYPE (left) == AOP_IMMD) ||
6133 (AOP_TYPE (left) == AOP_DIR) ||
6134 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6141 if (AOP_TYPE (right) == AOP_LIT)
6142 lit = ulFromVal (AOP (right)->aopu.aop_lit);
6144 /* if the right side is a literal then anything goes */
6145 if (AOP_TYPE (right) == AOP_LIT &&
6146 AOP_TYPE (left) != AOP_DIR &&
6147 AOP_TYPE (left) != AOP_IMMD)
6151 emitcode ("cjne", "%s,%s,%05d$",
6152 aopGet (left, offset, FALSE, FALSE),
6153 aopGet (right, offset, FALSE, FALSE),
6159 /* if the right side is in a register or in direct space or
6160 if the left is a pointer register & right is not */
6161 else if (AOP_TYPE (right) == AOP_REG ||
6162 AOP_TYPE (right) == AOP_DIR ||
6163 AOP_TYPE (right) == AOP_LIT ||
6164 AOP_TYPE (right) == AOP_IMMD ||
6165 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6166 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6170 MOVA (aopGet (left, offset, FALSE, FALSE));
6171 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6172 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6173 emitcode ("jnz", "%05d$", lbl->key + 100);
6175 emitcode ("cjne", "a,%s,%05d$",
6176 aopGet (right, offset, FALSE, TRUE),
6183 /* right is a pointer reg need both a & b */
6186 //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
6187 wassertl(!BINUSE, "B was in use");
6188 MOVB (aopGet (left, offset, FALSE, FALSE));
6189 MOVA (aopGet (right, offset, FALSE, FALSE));
6190 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
6196 /*-----------------------------------------------------------------*/
6197 /* gencjne - compare and jump if not equal */
6198 /*-----------------------------------------------------------------*/
6200 gencjne (operand * left, operand * right, symbol * lbl, bool useCarry)
6202 symbol *tlbl = newiTempLabel (NULL);
6204 D (emitcode (";", "gencjne"));
6206 gencjneshort (left, right, lbl);
6212 emitcode ("sjmp", "%05d$", tlbl->key + 100);
6221 /*-----------------------------------------------------------------*/
6222 /* genCmpEq - generates code for equal to */
6223 /*-----------------------------------------------------------------*/
6225 genCmpEq (iCode * ic, iCode * ifx)
6227 bool swappedLR = FALSE;
6228 operand *left, *right, *result;
6229 iCode * popIc = ic->next;
6231 D (emitcode (";", "genCmpEq"));
6233 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6234 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6235 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6237 /* if literal, literal on the right or
6238 if the right is in a pointer register and left
6240 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6241 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6243 operand *t = IC_RIGHT (ic);
6244 IC_RIGHT (ic) = IC_LEFT (ic);
6249 if (ifx && !AOP_SIZE (result))
6252 /* if they are both bit variables */
6253 if (AOP_TYPE (left) == AOP_CRY &&
6254 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6256 if (AOP_TYPE (right) == AOP_LIT)
6258 unsigned long lit = ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6261 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6262 emitcode ("cpl", "c");
6266 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6270 emitcode ("clr", "c");
6272 /* AOP_TYPE(right) == AOP_CRY */
6276 symbol *lbl = newiTempLabel (NULL);
6277 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6278 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6279 emitcode ("cpl", "c");
6282 /* if true label then we jump if condition
6284 tlbl = newiTempLabel (NULL);
6287 emitcode ("jnc", "%05d$", tlbl->key + 100);
6288 freeForBranchAsmop (result);
6289 freeForBranchAsmop (right);
6290 freeForBranchAsmop (left);
6291 popForBranch (popIc, FALSE);
6292 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6296 emitcode ("jc", "%05d$", tlbl->key + 100);
6297 freeForBranchAsmop (result);
6298 freeForBranchAsmop (right);
6299 freeForBranchAsmop (left);
6300 popForBranch (popIc, FALSE);
6301 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6307 tlbl = newiTempLabel (NULL);
6308 gencjneshort (left, right, tlbl);
6311 freeForBranchAsmop (result);
6312 freeForBranchAsmop (right);
6313 freeForBranchAsmop (left);
6314 popForBranch (popIc, FALSE);
6315 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6320 symbol *lbl = newiTempLabel (NULL);
6321 emitcode ("sjmp", "%05d$", lbl->key + 100);
6323 freeForBranchAsmop (result);
6324 freeForBranchAsmop (right);
6325 freeForBranchAsmop (left);
6326 popForBranch (popIc, FALSE);
6327 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6331 /* mark the icode as generated */
6336 /* if they are both bit variables */
6337 if (AOP_TYPE (left) == AOP_CRY &&
6338 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6340 if (AOP_TYPE (right) == AOP_LIT)
6342 unsigned long lit = ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6345 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6346 emitcode ("cpl", "c");
6350 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6354 emitcode ("clr", "c");
6356 /* AOP_TYPE(right) == AOP_CRY */
6360 symbol *lbl = newiTempLabel (NULL);
6361 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6362 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6363 emitcode ("cpl", "c");
6367 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6374 genIfxJump (ifx, "c", left, right, result, popIc);
6377 /* if the result is used in an arithmetic operation
6378 then put the result in place */
6383 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6385 gencjne (left, right, newiTempLabel (NULL), TRUE);
6386 aopPut (result, "c", 0);
6389 gencjne (left, right, newiTempLabel (NULL), FALSE);
6392 genIfxJump (ifx, "a", left, right, result, popIc);
6395 /* if the result is used in an arithmetic operation
6396 then put the result in place */
6397 if (AOP_TYPE (result) != AOP_CRY)
6399 /* leave the result in acc */
6403 freeAsmop (result, NULL, ic, TRUE);
6406 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6407 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6411 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6412 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6416 /*-----------------------------------------------------------------*/
6417 /* ifxForOp - returns the icode containing the ifx for operand */
6418 /*-----------------------------------------------------------------*/
6420 ifxForOp (operand * op, iCode * ic)
6424 /* if true symbol then needs to be assigned */
6425 if (IS_TRUE_SYMOP (op))
6428 /* if this has register type condition and
6429 while skipping ipop's (see bug 1509084),
6430 the next instruction is ifx with the same operand
6431 and live to of the operand is upto the ifx only then */
6432 for (ifxIc = ic->next; ifxIc && ifxIc->op == IPOP; ifxIc = ifxIc->next);
6433 if (ifxIc && ifxIc->op == IFX &&
6434 IC_COND (ifxIc)->key == op->key &&
6435 OP_SYMBOL (op)->liveTo <= ifxIc->seq)
6441 /*-----------------------------------------------------------------*/
6442 /* hasInc - operand is incremented before any other use */
6443 /*-----------------------------------------------------------------*/
6445 hasInc (operand *op, iCode *ic, int osize)
6447 sym_link *type = operandType(op);
6448 sym_link *retype = getSpec (type);
6449 iCode *lic = ic->next;
6452 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6453 if (!IS_SYMOP(op)) return NULL;
6455 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6456 if (IS_AGGREGATE(type->next)) return NULL;
6457 if (osize != (isize = getSize(type->next))) return NULL;
6461 /* if operand of the form op = op + <sizeof *op> */
6462 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6463 isOperandEqual(IC_RESULT(lic),op) &&
6464 isOperandLiteral(IC_RIGHT(lic)) &&
6465 operandLitValue(IC_RIGHT(lic)) == isize)
6469 /* if the operand used or deffed */
6470 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key)
6474 /* if GOTO or IFX */
6475 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6481 /*-----------------------------------------------------------------*/
6482 /* genAndOp - for && operation */
6483 /*-----------------------------------------------------------------*/
6485 genAndOp (iCode * ic)
6487 operand *left, *right, *result;
6490 D (emitcode (";", "genAndOp"));
6492 /* note here that && operations that are in an
6493 if statement are taken away by backPatchLabels
6494 only those used in arthmetic operations remain */
6495 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6496 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6497 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6499 /* if both are bit variables */
6500 if (AOP_TYPE (left) == AOP_CRY &&
6501 AOP_TYPE (right) == AOP_CRY)
6503 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6504 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6509 tlbl = newiTempLabel (NULL);
6511 emitcode ("jz", "%05d$", tlbl->key + 100);
6517 freeAsmop (result, NULL, ic, TRUE);
6518 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6519 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6523 /*-----------------------------------------------------------------*/
6524 /* genOrOp - for || operation */
6525 /*-----------------------------------------------------------------*/
6527 genOrOp (iCode * ic)
6529 operand *left, *right, *result;
6532 D (emitcode (";", "genOrOp"));
6534 /* note here that || operations that are in an
6535 if statement are taken away by backPatchLabels
6536 only those used in arthmetic operations remain */
6537 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6538 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6539 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6541 /* if both are bit variables */
6542 if (AOP_TYPE (left) == AOP_CRY &&
6543 AOP_TYPE (right) == AOP_CRY)
6545 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6546 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6551 tlbl = newiTempLabel (NULL);
6553 emitcode ("jnz", "%05d$", tlbl->key + 100);
6559 freeAsmop (result, NULL, ic, TRUE);
6560 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6561 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6564 /*-----------------------------------------------------------------*/
6565 /* isLiteralBit - test if lit == 2^n */
6566 /*-----------------------------------------------------------------*/
6568 isLiteralBit (unsigned long lit)
6570 unsigned long pw[32] =
6571 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6572 0x100L, 0x200L, 0x400L, 0x800L,
6573 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6574 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6575 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6576 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6577 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6580 for (idx = 0; idx < 32; idx++)
6586 /*-----------------------------------------------------------------*/
6587 /* continueIfTrue - */
6588 /*-----------------------------------------------------------------*/
6590 continueIfTrue (iCode * ic)
6593 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6597 /*-----------------------------------------------------------------*/
6599 /*-----------------------------------------------------------------*/
6601 jumpIfTrue (iCode * ic)
6604 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6608 /*-----------------------------------------------------------------*/
6609 /* jmpTrueOrFalse - */
6610 /*-----------------------------------------------------------------*/
6612 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6614 // ugly but optimized by peephole
6617 symbol *nlbl = newiTempLabel (NULL);
6618 emitcode ("sjmp", "%05d$", nlbl->key + 100);
6620 freeForBranchAsmop (result);
6621 freeForBranchAsmop (right);
6622 freeForBranchAsmop (left);
6623 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6628 freeForBranchAsmop (result);
6629 freeForBranchAsmop (right);
6630 freeForBranchAsmop (left);
6631 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6637 /*-----------------------------------------------------------------*/
6638 /* genAnd - code for and */
6639 /*-----------------------------------------------------------------*/
6641 genAnd (iCode * ic, iCode * ifx)
6643 operand *left, *right, *result;
6644 int size, offset = 0;
6645 unsigned long lit = 0L;
6649 D (emitcode (";", "genAnd"));
6651 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6652 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6653 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6656 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
6658 AOP_TYPE (left), AOP_TYPE (right));
6659 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
6661 AOP_SIZE (left), AOP_SIZE (right));
6664 /* if left is a literal & right is not then exchange them */
6665 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6666 AOP_NEEDSACC (left))
6668 operand *tmp = right;
6673 /* if result = right then exchange left and right */
6674 if (sameRegs (AOP (result), AOP (right)))
6676 operand *tmp = right;
6681 /* if right is bit then exchange them */
6682 if (AOP_TYPE (right) == AOP_CRY &&
6683 AOP_TYPE (left) != AOP_CRY)
6685 operand *tmp = right;
6689 if (AOP_TYPE (right) == AOP_LIT)
6690 lit = ulFromVal (AOP (right)->aopu.aop_lit);
6692 size = AOP_SIZE (result);
6695 // result = bit & yy;
6696 if (AOP_TYPE (left) == AOP_CRY)
6698 // c = bit & literal;
6699 if (AOP_TYPE (right) == AOP_LIT)
6703 if (size && sameRegs (AOP (result), AOP (left)))
6706 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6711 if (size && (AOP_TYPE (result) == AOP_CRY))
6713 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6716 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6721 emitcode ("clr", "c");
6726 if (AOP_TYPE (right) == AOP_CRY)
6729 if (IS_OP_ACCUSE (left))
6731 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6735 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6736 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6742 MOVA (aopGet (right, 0, FALSE, FALSE));
6744 emitcode ("rrc", "a");
6745 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6753 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6754 genIfxJump (ifx, "c", left, right, result, ic->next);
6758 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6759 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6760 if ((AOP_TYPE (right) == AOP_LIT) &&
6761 (AOP_TYPE (result) == AOP_CRY) &&
6762 (AOP_TYPE (left) != AOP_CRY))
6764 int posbit = isLiteralBit (lit);
6769 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6773 switch (posbit & 0x07)
6775 case 0: emitcode ("rrc", "a");
6777 case 7: emitcode ("rlc", "a");
6779 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6788 SNPRINTF (buffer, sizeof(buffer),
6789 "acc.%d", posbit & 0x07);
6790 genIfxJump (ifx, buffer, left, right, result, ic->next);
6793 {// what is this case? just found it in ds390/gen.c
6794 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6801 symbol *tlbl = newiTempLabel (NULL);
6802 int sizel = AOP_SIZE (left);
6804 emitcode ("setb", "c");
6807 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6809 MOVA (aopGet (left, offset, FALSE, FALSE));
6811 if ((posbit = isLiteralBit (bytelit)) != 0)
6812 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6815 if (bytelit != 0x0FFL)
6816 emitcode ("anl", "a,%s",
6817 aopGet (right, offset, FALSE, TRUE));
6818 emitcode ("jnz", "%05d$", tlbl->key + 100);
6823 // bit = left & literal
6826 emitcode ("clr", "c");
6829 // if(left & literal)
6833 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6843 /* if left is same as result */
6844 if (sameRegs (AOP (result), AOP (left)))
6846 for (; size--; offset++)
6848 if (AOP_TYPE (right) == AOP_LIT)
6850 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6851 if (bytelit == 0x0FF)
6853 /* dummy read of volatile operand */
6854 if (isOperandVolatile (left, FALSE))
6855 MOVA (aopGet (left, offset, FALSE, FALSE));
6859 else if (bytelit == 0)
6861 aopPut (result, zero, offset);
6863 else if (IS_AOP_PREG (result))
6865 MOVA (aopGet (left, offset, FALSE, TRUE));
6866 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6867 aopPut (result, "a", offset);
6870 emitcode ("anl", "%s,%s",
6871 aopGet (left, offset, FALSE, TRUE),
6872 aopGet (right, offset, FALSE, FALSE));
6876 if (AOP_TYPE (left) == AOP_ACC)
6879 emitcode("mov", "a,b");
6880 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6882 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6884 MOVB (aopGet (left, offset, FALSE, FALSE));
6885 MOVA (aopGet (right, offset, FALSE, FALSE));
6886 emitcode ("anl", "a,b");
6887 aopPut (result, "a", offset);
6889 else if (aopGetUsesAcc (left, offset))
6891 MOVA (aopGet (left, offset, FALSE, FALSE));
6892 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6893 aopPut (result, "a", offset);
6897 MOVA (aopGet (right, offset, FALSE, FALSE));
6898 if (IS_AOP_PREG (result))
6900 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6901 aopPut (result, "a", offset);
6904 emitcode ("anl", "%s,a", aopGet (left, offset, FALSE, TRUE));
6911 // left & result in different registers
6912 if (AOP_TYPE (result) == AOP_CRY)
6915 // if(size), result in bit
6916 // if(!size && ifx), conditional oper: if(left & right)
6917 symbol *tlbl = newiTempLabel (NULL);
6918 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6920 emitcode ("setb", "c");
6923 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6924 && AOP_TYPE(left)==AOP_ACC)
6927 emitcode("mov", "a,b");
6928 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6930 else if (AOP_TYPE(left)==AOP_ACC)
6934 bool pushedB = pushB ();
6935 emitcode("mov", "b,a");
6936 MOVA (aopGet (right, offset, FALSE, FALSE));
6937 emitcode("anl", "a,b");
6942 MOVA (aopGet (right, offset, FALSE, FALSE));
6943 emitcode("anl", "a,b");
6946 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6948 MOVB (aopGet (left, offset, FALSE, FALSE));
6949 MOVA (aopGet (right, offset, FALSE, FALSE));
6950 emitcode ("anl", "a,b");
6952 else if (aopGetUsesAcc (left, offset))
6954 MOVA (aopGet (left, offset, FALSE, FALSE));
6955 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6959 MOVA (aopGet (right, offset, FALSE, FALSE));
6960 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6963 emitcode ("jnz", "%05d$", tlbl->key + 100);
6973 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6979 for (; (size--); offset++)
6982 // result = left & right
6983 if (AOP_TYPE (right) == AOP_LIT)
6985 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6986 if (bytelit == 0x0FF)
6989 aopGet (left, offset, FALSE, FALSE),
6993 else if (bytelit == 0)
6995 /* dummy read of volatile operand */
6996 if (isOperandVolatile (left, FALSE))
6997 MOVA (aopGet (left, offset, FALSE, FALSE));
6998 aopPut (result, zero, offset);
7001 else if (AOP_TYPE (left) == AOP_ACC)
7005 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7006 aopPut (result, "a", offset);
7011 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
7012 aopPut (result, "b", offset);
7017 // faster than result <- left, anl result,right
7018 // and better if result is SFR
7019 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7020 && AOP_TYPE(left)==AOP_ACC)
7023 emitcode("mov", "a,b");
7024 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7026 else if (AOP_TYPE(left)==AOP_ACC)
7030 bool pushedB = pushB ();
7031 emitcode("mov", "b,a");
7032 MOVA (aopGet (right, offset, FALSE, FALSE));
7033 emitcode("anl", "a,b");
7038 MOVA (aopGet (right, offset, FALSE, FALSE));
7039 emitcode("anl", "a,b");
7042 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7044 MOVB (aopGet (left, offset, FALSE, FALSE));
7045 MOVA (aopGet (right, offset, FALSE, FALSE));
7046 emitcode ("anl", "a,b");
7048 else if (aopGetUsesAcc (left, offset))
7050 MOVA (aopGet (left, offset, FALSE, FALSE));
7051 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7055 MOVA (aopGet (right, offset, FALSE, FALSE));
7056 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7058 aopPut (result, "a", offset);
7064 freeAsmop (result, NULL, ic, TRUE);
7065 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7066 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7069 /*-----------------------------------------------------------------*/
7070 /* genOr - code for or */
7071 /*-----------------------------------------------------------------*/
7073 genOr (iCode * ic, iCode * ifx)
7075 operand *left, *right, *result;
7076 int size, offset = 0;
7077 unsigned long lit = 0L;
7080 D (emitcode (";", "genOr"));
7082 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7083 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7084 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7087 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
7089 AOP_TYPE (left), AOP_TYPE (right));
7090 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
7092 AOP_SIZE (left), AOP_SIZE (right));
7095 /* if left is a literal & right is not then exchange them */
7096 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7097 AOP_NEEDSACC (left))
7099 operand *tmp = right;
7104 /* if result = right then exchange them */
7105 if (sameRegs (AOP (result), AOP (right)))
7107 operand *tmp = right;
7112 /* if right is bit then exchange them */
7113 if (AOP_TYPE (right) == AOP_CRY &&
7114 AOP_TYPE (left) != AOP_CRY)
7116 operand *tmp = right;
7120 if (AOP_TYPE (right) == AOP_LIT)
7121 lit = ulFromVal (AOP (right)->aopu.aop_lit);
7123 size = AOP_SIZE (result);
7127 if (AOP_TYPE (left) == AOP_CRY)
7129 if (AOP_TYPE (right) == AOP_LIT)
7131 // c = bit | literal;
7134 // lit != 0 => result = 1
7135 if (AOP_TYPE (result) == AOP_CRY)
7138 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7140 continueIfTrue (ifx);
7143 emitcode ("setb", "c");
7147 // lit == 0 => result = left
7148 if (size && sameRegs (AOP (result), AOP (left)))
7150 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7155 if (AOP_TYPE (right) == AOP_CRY)
7158 if (IS_OP_ACCUSE (left))
7160 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
7164 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7165 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7171 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7173 symbol *tlbl = newiTempLabel (NULL);
7174 emitcode ("jb", "%s,%05d$",
7175 AOP (left)->aopu.aop_dir, tlbl->key + 100);
7177 emitcode ("jnz", "%05d$", tlbl->key + 100);
7178 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7184 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7193 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7194 genIfxJump (ifx, "c", left, right, result, ic->next);
7198 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7199 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7200 if ((AOP_TYPE (right) == AOP_LIT) &&
7201 (AOP_TYPE (result) == AOP_CRY) &&
7202 (AOP_TYPE (left) != AOP_CRY))
7208 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7210 continueIfTrue (ifx);
7215 // lit = 0, result = boolean(left)
7217 emitcode ("setb", "c");
7221 symbol *tlbl = newiTempLabel (NULL);
7222 emitcode ("jnz", "%05d$", tlbl->key + 100);
7228 genIfxJump (ifx, "a", left, right, result, ic->next);
7236 /* if left is same as result */
7237 if (sameRegs (AOP (result), AOP (left)))
7239 for (; size--; offset++)
7241 if (AOP_TYPE (right) == AOP_LIT)
7243 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7246 /* dummy read of volatile operand */
7247 if (isOperandVolatile (left, FALSE))
7248 MOVA (aopGet (left, offset, FALSE, FALSE));
7252 else if (bytelit == 0x0FF)
7254 aopPut (result, "#0xff", offset);
7256 else if (IS_AOP_PREG (left))
7258 MOVA (aopGet (left, offset, FALSE, TRUE));
7259 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7260 aopPut (result, "a", offset);
7264 emitcode ("orl", "%s,%s",
7265 aopGet (left, offset, FALSE, TRUE),
7266 aopGet (right, offset, FALSE, FALSE));
7271 if (AOP_TYPE (left) == AOP_ACC)
7274 emitcode("mov", "a,b");
7275 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7277 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7279 MOVB (aopGet (left, offset, FALSE, FALSE));
7280 MOVA (aopGet (right, offset, FALSE, FALSE));
7281 emitcode ("orl", "a,b");
7282 aopPut (result, "a", offset);
7284 else if (aopGetUsesAcc (left, offset))
7286 MOVA (aopGet (left, offset, FALSE, FALSE));
7287 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7288 aopPut (result, "a", offset);
7292 MOVA (aopGet (right, offset, FALSE, FALSE));
7293 if (IS_AOP_PREG (left))
7295 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7296 aopPut (result, "a", offset);
7300 emitcode ("orl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7308 // left & result in different registers
7309 if (AOP_TYPE (result) == AOP_CRY)
7312 // if(size), result in bit
7313 // if(!size && ifx), conditional oper: if(left | right)
7314 symbol *tlbl = newiTempLabel (NULL);
7315 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7317 emitcode ("setb", "c");
7320 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7321 && AOP_TYPE(left)==AOP_ACC)
7324 emitcode("mov", "a,b");
7325 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7327 else if (AOP_TYPE(left)==AOP_ACC)
7331 bool pushedB = pushB ();
7332 emitcode("mov", "b,a");
7333 MOVA (aopGet (right, offset, FALSE, FALSE));
7334 emitcode("orl", "a,b");
7339 MOVA (aopGet (right, offset, FALSE, FALSE));
7340 emitcode("orl", "a,b");
7343 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7345 MOVB (aopGet (left, offset, FALSE, FALSE));
7346 MOVA (aopGet (right, offset, FALSE, FALSE));
7347 emitcode ("orl", "a,b");
7349 else if (aopGetUsesAcc (left, offset))
7351 MOVA (aopGet (left, offset, FALSE, FALSE));
7352 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7356 MOVA (aopGet (right, offset, FALSE, FALSE));
7357 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7360 emitcode ("jnz", "%05d$", tlbl->key + 100);
7370 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7376 for (; (size--); offset++)
7379 // result = left | right
7380 if (AOP_TYPE (right) == AOP_LIT)
7382 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7386 aopGet (left, offset, FALSE, FALSE),
7390 else if (bytelit == 0x0FF)
7392 /* dummy read of volatile operand */
7393 if (isOperandVolatile (left, FALSE))
7394 MOVA (aopGet (left, offset, FALSE, FALSE));
7395 aopPut (result, "#0xff", offset);
7399 // faster than result <- left, orl result,right
7400 // and better if result is SFR
7401 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7402 && AOP_TYPE(left)==AOP_ACC)
7405 emitcode("mov", "a,b");
7406 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7408 else if (AOP_TYPE(left)==AOP_ACC)
7412 bool pushedB = pushB ();
7413 emitcode("mov", "b,a");
7414 MOVA (aopGet (right, offset, FALSE, FALSE));
7415 emitcode("orl", "a,b");
7420 MOVA (aopGet (right, offset, FALSE, FALSE));
7421 emitcode("orl", "a,b");
7424 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7426 MOVB (aopGet (left, offset, FALSE, FALSE));
7427 MOVA (aopGet (right, offset, FALSE, FALSE));
7428 emitcode ("orl", "a,b");
7430 else if (aopGetUsesAcc (left, offset))
7432 MOVA (aopGet (left, offset, FALSE, FALSE));
7433 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7437 MOVA (aopGet (right, offset, FALSE, FALSE));
7438 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7440 aopPut (result, "a", offset);
7446 freeAsmop (result, NULL, ic, TRUE);
7447 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7448 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7451 /*-----------------------------------------------------------------*/
7452 /* genXor - code for xclusive or */
7453 /*-----------------------------------------------------------------*/
7455 genXor (iCode * ic, iCode * ifx)
7457 operand *left, *right, *result;
7458 int size, offset = 0;
7459 unsigned long lit = 0L;
7462 D (emitcode (";", "genXor"));
7464 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7465 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7466 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7469 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
7471 AOP_TYPE (left), AOP_TYPE (right));
7472 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
7474 AOP_SIZE (left), AOP_SIZE (right));
7477 /* if left is a literal & right is not ||
7478 if left needs acc & right does not */
7479 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7480 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7482 operand *tmp = right;
7487 /* if result = right then exchange them */
7488 if (sameRegs (AOP (result), AOP (right)))
7490 operand *tmp = right;
7495 /* if right is bit then exchange them */
7496 if (AOP_TYPE (right) == AOP_CRY &&
7497 AOP_TYPE (left) != AOP_CRY)
7499 operand *tmp = right;
7504 if (AOP_TYPE (right) == AOP_LIT)
7505 lit = ulFromVal (AOP (right)->aopu.aop_lit);
7507 size = AOP_SIZE (result);
7511 if (AOP_TYPE (left) == AOP_CRY)
7513 if (AOP_TYPE (right) == AOP_LIT)
7515 // c = bit & literal;
7518 // lit>>1 != 0 => result = 1
7519 if (AOP_TYPE (result) == AOP_CRY)
7522 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7524 continueIfTrue (ifx);
7527 emitcode ("setb", "c");
7534 // lit == 0, result = left
7535 if (size && sameRegs (AOP (result), AOP (left)))
7537 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7541 // lit == 1, result = not(left)
7542 if (size && sameRegs (AOP (result), AOP (left)))
7544 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7549 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7550 emitcode ("cpl", "c");
7558 symbol *tlbl = newiTempLabel (NULL);
7559 if (AOP_TYPE (right) == AOP_CRY)
7562 if (IS_OP_ACCUSE (left))
7563 {// left already is in the carry
7564 operand *tmp = right;
7578 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7579 emitcode ("cpl", "c");
7587 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7588 genIfxJump (ifx, "c", left, right, result, ic->next);
7592 /* if left is same as result */
7593 if (sameRegs (AOP (result), AOP (left)))
7595 for (; size--; offset++)
7597 if (AOP_TYPE (right) == AOP_LIT)
7599 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7602 /* dummy read of volatile operand */
7603 if (isOperandVolatile (left, FALSE))
7604 MOVA (aopGet (left, offset, FALSE, FALSE));
7608 else if (IS_AOP_PREG (left))
7610 MOVA (aopGet (left, offset, FALSE, TRUE));
7611 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7612 aopPut (result, "a", offset);
7616 emitcode ("xrl", "%s,%s",
7617 aopGet (left, offset, FALSE, TRUE),
7618 aopGet (right, offset, FALSE, FALSE));
7623 if (AOP_TYPE (left) == AOP_ACC)
7626 emitcode("mov", "a,b");
7627 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7629 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7631 MOVB (aopGet (left, offset, FALSE, FALSE));
7632 MOVA (aopGet (right, offset, FALSE, FALSE));
7633 emitcode ("xrl", "a,b");
7634 aopPut (result, "a", offset);
7636 else if (aopGetUsesAcc (left, offset))
7638 MOVA (aopGet (left, offset, FALSE, FALSE));
7639 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7640 aopPut (result, "a", offset);
7644 MOVA (aopGet (right, offset, FALSE, FALSE));
7645 if (IS_AOP_PREG (left))
7647 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7648 aopPut (result, "a", offset);
7651 emitcode ("xrl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7658 // left & result in different registers
7659 if (AOP_TYPE (result) == AOP_CRY)
7662 // if(size), result in bit
7663 // if(!size && ifx), conditional oper: if(left ^ right)
7664 symbol *tlbl = newiTempLabel (NULL);
7665 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7668 emitcode ("setb", "c");
7671 if ((AOP_TYPE (right) == AOP_LIT) &&
7672 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7674 MOVA (aopGet (left, offset, FALSE, FALSE));
7676 else if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7677 && AOP_TYPE(left)==AOP_ACC)
7680 emitcode("mov", "a,b");
7681 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7683 else if (AOP_TYPE(left)==AOP_ACC)
7687 bool pushedB = pushB ();
7688 emitcode("mov", "b,a");
7689 MOVA (aopGet (right, offset, FALSE, FALSE));
7690 emitcode("xrl", "a,b");
7695 MOVA (aopGet (right, offset, FALSE, FALSE));
7696 emitcode("xrl", "a,b");
7699 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7701 MOVB (aopGet (left, offset, FALSE, FALSE));
7702 MOVA (aopGet (right, offset, FALSE, FALSE));
7703 emitcode ("xrl", "a,b");
7705 else if (aopGetUsesAcc (left, offset))
7707 MOVA (aopGet (left, offset, FALSE, FALSE));
7708 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7712 MOVA (aopGet (right, offset, FALSE, FALSE));
7713 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7716 emitcode ("jnz", "%05d$", tlbl->key + 100);
7726 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7730 for (; (size--); offset++)
7733 // result = left ^ right
7734 if (AOP_TYPE (right) == AOP_LIT)
7736 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7740 aopGet (left, offset, FALSE, FALSE),
7745 // faster than result <- left, xrl result,right
7746 // and better if result is SFR
7747 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7748 && AOP_TYPE(left)==AOP_ACC)
7751 emitcode("mov", "a,b");
7752 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7754 else if (AOP_TYPE(left)==AOP_ACC)
7758 bool pushedB = pushB ();
7759 emitcode("mov", "b,a");
7760 MOVA (aopGet (right, offset, FALSE, FALSE));
7761 emitcode("xrl", "a,b");
7766 MOVA (aopGet (right, offset, FALSE, FALSE));
7767 emitcode("xrl", "a,b");
7770 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7772 MOVB (aopGet (left, offset, FALSE, FALSE));
7773 MOVA (aopGet (right, offset, FALSE, FALSE));
7774 emitcode ("xrl", "a,b");
7776 else if (aopGetUsesAcc (left, offset))
7778 MOVA (aopGet (left, offset, FALSE, FALSE));
7779 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7783 MOVA (aopGet (right, offset, FALSE, FALSE));
7784 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7786 aopPut (result, "a", offset);
7792 freeAsmop (result, NULL, ic, TRUE);
7793 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7794 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7797 /*-----------------------------------------------------------------*/
7798 /* genInline - write the inline code out */
7799 /*-----------------------------------------------------------------*/
7801 genInline (iCode * ic)
7803 char *buffer, *bp, *bp1;
7804 bool inComment = FALSE;
7806 D (emitcode (";", "genInline"));
7808 _G.inLine += (!options.asmpeep);
7810 buffer = bp = bp1 = Safe_strdup (IC_INLINE (ic));
7812 /* emit each line as a code */
7830 /* Add \n for labels, not dirs such as c:\mydir */
7831 if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
7849 _G.inLine -= (!options.asmpeep);
7852 /*-----------------------------------------------------------------*/
7853 /* genRRC - rotate right with carry */
7854 /*-----------------------------------------------------------------*/
7858 operand *left, *result;
7862 D (emitcode (";", "genRRC"));
7864 /* rotate right with carry */
7865 left = IC_LEFT (ic);
7866 result = IC_RESULT (ic);
7867 aopOp (left, ic, FALSE);
7868 aopOp (result, ic, FALSE);
7870 /* move it to the result */
7871 size = AOP_SIZE (result);
7873 if (size == 1) { /* special case for 1 byte */
7874 l = aopGet (left, offset, FALSE, FALSE);
7876 emitcode ("rr", "a");
7879 /* no need to clear carry, bit7 will be written later */
7882 l = aopGet (left, offset, FALSE, FALSE);
7884 emitcode ("rrc", "a");
7885 if (AOP_SIZE (result) > 1)
7886 aopPut (result, "a", offset--);
7888 /* now we need to put the carry into the
7889 highest order byte of the result */
7890 if (AOP_SIZE (result) > 1)
7892 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7895 emitcode ("mov", "acc.7,c");
7897 aopPut (result, "a", AOP_SIZE (result) - 1);
7898 freeAsmop (result, NULL, ic, TRUE);
7899 freeAsmop (left, NULL, ic, TRUE);
7902 /*-----------------------------------------------------------------*/
7903 /* genRLC - generate code for rotate left with carry */
7904 /*-----------------------------------------------------------------*/
7908 operand *left, *result;
7912 D (emitcode (";", "genRLC"));
7914 /* rotate right with carry */
7915 left = IC_LEFT (ic);
7916 result = IC_RESULT (ic);
7917 aopOp (left, ic, FALSE);
7918 aopOp (result, ic, FALSE);
7920 /* move it to the result */
7921 size = AOP_SIZE (result);
7925 l = aopGet (left, offset, FALSE, FALSE);
7927 if (size == 0) { /* special case for 1 byte */
7931 emitcode("rlc","a"); /* bit0 will be written later */
7932 if (AOP_SIZE (result) > 1)
7934 aopPut (result, "a", offset++);
7939 l = aopGet (left, offset, FALSE, FALSE);
7941 emitcode ("rlc", "a");
7942 if (AOP_SIZE (result) > 1)
7943 aopPut (result, "a", offset++);
7946 /* now we need to put the carry into the
7947 highest order byte of the result */
7948 if (AOP_SIZE (result) > 1)
7950 l = aopGet (result, 0, FALSE, FALSE);
7953 emitcode ("mov", "acc.0,c");
7955 aopPut (result, "a", 0);
7956 freeAsmop (result, NULL, ic, TRUE);
7957 freeAsmop (left, NULL, ic, TRUE);
7960 /*-----------------------------------------------------------------*/
7961 /* genGetHbit - generates code get highest order bit */
7962 /*-----------------------------------------------------------------*/
7964 genGetHbit (iCode * ic)
7966 operand *left, *result;
7968 D (emitcode (";", "genGetHbit"));
7970 left = IC_LEFT (ic);
7971 result = IC_RESULT (ic);
7972 aopOp (left, ic, FALSE);
7973 aopOp (result, ic, FALSE);
7975 /* get the highest order byte into a */
7976 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7977 if (AOP_TYPE (result) == AOP_CRY)
7979 emitcode ("rlc", "a");
7984 emitcode ("rl", "a");
7985 emitcode ("anl", "a,#0x01");
7989 freeAsmop (result, NULL, ic, TRUE);
7990 freeAsmop (left, NULL, ic, TRUE);
7993 /*-----------------------------------------------------------------*/
7994 /* genGetAbit - generates code get a single bit */
7995 /*-----------------------------------------------------------------*/
7997 genGetAbit (iCode * ic)
7999 operand *left, *right, *result;
8002 D (emitcode (";", "genGetAbit"));
8004 left = IC_LEFT (ic);
8005 right = IC_RIGHT (ic);
8006 result = IC_RESULT (ic);
8007 aopOp (left, ic, FALSE);
8008 aopOp (right, ic, FALSE);
8009 aopOp (result, ic, FALSE);
8011 shCount = (int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
8013 /* get the needed byte into a */
8014 MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
8016 if (AOP_TYPE (result) == AOP_CRY)
8019 emitcode ("rlc", "a");
8020 else if ((shCount) == 0)
8021 emitcode ("rrc", "a");
8023 emitcode ("mov", "c,acc[%d]", shCount);
8031 emitcode ("rr", "a");
8034 emitcode ("rr", "a");
8037 emitcode ("anl", "a,#0x01");
8041 emitcode ("mov", "c,acc[%d]", shCount);
8042 emitcode ("clr", "a");
8043 emitcode ("rlc", "a");
8046 emitcode ("swap", "a");
8047 emitcode ("anl", "a,#0x01");
8050 emitcode ("rl", "a");
8053 emitcode ("rl", "a");
8054 emitcode ("anl", "a,#0x01");
8060 freeAsmop (result, NULL, ic, TRUE);
8061 freeAsmop (right, NULL, ic, TRUE);
8062 freeAsmop (left, NULL, ic, TRUE);
8065 /*-----------------------------------------------------------------*/
8066 /* genGetByte - generates code get a single byte */
8067 /*-----------------------------------------------------------------*/
8069 genGetByte (iCode * ic)
8071 operand *left, *right, *result;
8074 D (emitcode (";", "genGetByte"));
8076 left = IC_LEFT (ic);
8077 right = IC_RIGHT (ic);
8078 result = IC_RESULT (ic);
8079 aopOp (left, ic, FALSE);
8080 aopOp (right, ic, FALSE);
8081 aopOp (result, ic, FALSE);
8083 offset = (int) ulFromVal (AOP (right)->aopu.aop_lit) / 8;
8085 aopGet (left, offset, FALSE, FALSE),
8088 freeAsmop (result, NULL, ic, TRUE);
8089 freeAsmop (right, NULL, ic, TRUE);
8090 freeAsmop (left, NULL, ic, TRUE);
8093 /*-----------------------------------------------------------------*/
8094 /* genGetWord - generates code get two bytes */
8095 /*-----------------------------------------------------------------*/
8097 genGetWord (iCode * ic)
8099 operand *left, *right, *result;
8102 D (emitcode (";", "genGetWord"));
8104 left = IC_LEFT (ic);
8105 right = IC_RIGHT (ic);
8106 result = IC_RESULT (ic);
8107 aopOp (left, ic, FALSE);
8108 aopOp (right, ic, FALSE);
8109 aopOp (result, ic, FALSE);
8111 offset = (int) ulFromVal (AOP (right)->aopu.aop_lit) / 8;
8113 aopGet (left, offset, FALSE, FALSE),
8116 aopGet (left, offset+1, FALSE, FALSE),
8119 freeAsmop (result, NULL, ic, TRUE);
8120 freeAsmop (right, NULL, ic, TRUE);
8121 freeAsmop (left, NULL, ic, TRUE);
8124 /*-----------------------------------------------------------------*/
8125 /* genSwap - generates code to swap nibbles or bytes */
8126 /*-----------------------------------------------------------------*/
8128 genSwap (iCode * ic)
8130 operand *left, *result;
8132 D(emitcode (";", "genSwap"));
8134 left = IC_LEFT (ic);
8135 result = IC_RESULT (ic);
8136 aopOp (left, ic, FALSE);
8137 aopOp (result, ic, FALSE);
8139 switch (AOP_SIZE (left))
8141 case 1: /* swap nibbles in byte */
8142 MOVA (aopGet (left, 0, FALSE, FALSE));
8143 emitcode ("swap", "a");
8144 aopPut (result, "a", 0);
8146 case 2: /* swap bytes in word */
8147 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
8149 MOVA (aopGet (left, 0, FALSE, FALSE));
8150 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8151 aopPut (result, "a", 1);
8153 else if (operandsEqu (left, result))
8156 bool pushedB = FALSE, leftInB = FALSE;
8158 MOVA (aopGet (left, 0, FALSE, FALSE));
8159 if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
8162 emitcode ("mov", "b,a");
8166 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8167 aopPut (result, reg, 1);
8174 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8175 aopPut (result, aopGet (left, 0, FALSE, FALSE), 1);
8179 wassertl(FALSE, "unsupported SWAP operand size");
8182 freeAsmop (result, NULL, ic, TRUE);
8183 freeAsmop (left, NULL, ic, TRUE);
8186 /*-----------------------------------------------------------------*/
8187 /* AccRol - rotate left accumulator by known count */
8188 /*-----------------------------------------------------------------*/
8190 AccRol (int shCount)
8192 shCount &= 0x0007; // shCount : 0..7
8199 emitcode ("rl", "a");
8202 emitcode ("rl", "a");
8203 emitcode ("rl", "a");
8206 emitcode ("swap", "a");
8207 emitcode ("rr", "a");
8210 emitcode ("swap", "a");
8213 emitcode ("swap", "a");
8214 emitcode ("rl", "a");
8217 emitcode ("rr", "a");
8218 emitcode ("rr", "a");
8221 emitcode ("rr", "a");
8226 /*-----------------------------------------------------------------*/
8227 /* AccLsh - left shift accumulator by known count */
8228 /*-----------------------------------------------------------------*/
8230 AccLsh (int shCount)
8235 emitcode ("add", "a,acc");
8236 else if (shCount == 2)
8238 emitcode ("add", "a,acc");
8239 emitcode ("add", "a,acc");
8243 /* rotate left accumulator */
8245 /* and kill the lower order bits */
8246 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
8251 /*-----------------------------------------------------------------*/
8252 /* AccRsh - right shift accumulator by known count */
8253 /*-----------------------------------------------------------------*/
8255 AccRsh (int shCount)
8262 emitcode ("rrc", "a");
8266 /* rotate right accumulator */
8267 AccRol (8 - shCount);
8268 /* and kill the higher order bits */
8269 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8274 /*-----------------------------------------------------------------*/
8275 /* AccSRsh - signed right shift accumulator by known count */
8276 /*-----------------------------------------------------------------*/
8278 AccSRsh (int shCount)
8285 emitcode ("mov", "c,acc.7");
8286 emitcode ("rrc", "a");
8288 else if (shCount == 2)
8290 emitcode ("mov", "c,acc.7");
8291 emitcode ("rrc", "a");
8292 emitcode ("mov", "c,acc.7");
8293 emitcode ("rrc", "a");
8297 tlbl = newiTempLabel (NULL);
8298 /* rotate right accumulator */
8299 AccRol (8 - shCount);
8300 /* and kill the higher order bits */
8301 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8302 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8303 emitcode ("orl", "a,#0x%02x",
8304 (unsigned char) ~SRMask[shCount]);
8310 /*-----------------------------------------------------------------*/
8311 /* shiftR1Left2Result - shift right one byte from left to result */
8312 /*-----------------------------------------------------------------*/
8314 shiftR1Left2Result (operand * left, int offl,
8315 operand * result, int offr,
8316 int shCount, int sign)
8318 MOVA (aopGet (left, offl, FALSE, FALSE));
8319 /* shift right accumulator */
8324 aopPut (result, "a", offr);
8327 /*-----------------------------------------------------------------*/
8328 /* shiftL1Left2Result - shift left one byte from left to result */
8329 /*-----------------------------------------------------------------*/
8331 shiftL1Left2Result (operand * left, int offl,
8332 operand * result, int offr, int shCount)
8335 l = aopGet (left, offl, FALSE, FALSE);
8337 /* shift left accumulator */
8339 aopPut (result, "a", offr);
8342 /*-----------------------------------------------------------------*/
8343 /* movLeft2Result - move byte from left to result */
8344 /*-----------------------------------------------------------------*/
8346 movLeft2Result (operand * left, int offl,
8347 operand * result, int offr, int sign)
8350 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8352 l = aopGet (left, offl, FALSE, FALSE);
8354 if (*l == '@' && (IS_AOP_PREG (result)))
8356 emitcode ("mov", "a,%s", l);
8357 aopPut (result, "a", offr);
8363 aopPut (result, l, offr);
8367 /* MSB sign in acc.7 ! */
8368 if (getDataSize (left) == offl + 1)
8371 aopPut (result, "a", offr);
8378 /*-----------------------------------------------------------------*/
8379 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
8380 /*-----------------------------------------------------------------*/
8384 emitcode ("rrc", "a");
8385 emitcode ("xch", "a,%s", x);
8386 emitcode ("rrc", "a");
8387 emitcode ("xch", "a,%s", x);
8390 /*-----------------------------------------------------------------*/
8391 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
8392 /*-----------------------------------------------------------------*/
8396 emitcode ("xch", "a,%s", x);
8397 emitcode ("rlc", "a");
8398 emitcode ("xch", "a,%s", x);
8399 emitcode ("rlc", "a");
8402 /*-----------------------------------------------------------------*/
8403 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8404 /*-----------------------------------------------------------------*/
8408 emitcode ("xch", "a,%s", x);
8409 emitcode ("add", "a,acc");
8410 emitcode ("xch", "a,%s", x);
8411 emitcode ("rlc", "a");
8414 /*-----------------------------------------------------------------*/
8415 /* AccAXLsh - left shift a:x by known count (0..7) */
8416 /*-----------------------------------------------------------------*/
8418 AccAXLsh (char *x, int shCount)
8433 case 5: // AAAAABBB:CCCCCDDD
8435 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8437 emitcode ("anl", "a,#0x%02x",
8438 SLMask[shCount]); // BBB00000:CCCCCDDD
8440 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8442 AccRol (shCount); // DDDCCCCC:BBB00000
8444 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8446 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8448 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8450 emitcode ("anl", "a,#0x%02x",
8451 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8453 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8455 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8458 case 6: // AAAAAABB:CCCCCCDD
8459 emitcode ("anl", "a,#0x%02x",
8460 SRMask[shCount]); // 000000BB:CCCCCCDD
8461 emitcode ("mov", "c,acc.0"); // c = B
8462 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8464 AccAXRrl1 (x); // BCCCCCCD:D000000B
8465 AccAXRrl1 (x); // BBCCCCCC:DD000000
8467 emitcode("rrc","a");
8468 emitcode("xch","a,%s", x);
8469 emitcode("rrc","a");
8470 emitcode("mov","c,acc.0"); //<< get correct bit
8471 emitcode("xch","a,%s", x);
8473 emitcode("rrc","a");
8474 emitcode("xch","a,%s", x);
8475 emitcode("rrc","a");
8476 emitcode("xch","a,%s", x);
8479 case 7: // a:x <<= 7
8481 emitcode ("anl", "a,#0x%02x",
8482 SRMask[shCount]); // 0000000B:CCCCCCCD
8484 emitcode ("mov", "c,acc.0"); // c = B
8486 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
8488 AccAXRrl1 (x); // BCCCCCCC:D0000000
8496 /*-----------------------------------------------------------------*/
8497 /* AccAXRsh - right shift a:x known count (0..7) */
8498 /*-----------------------------------------------------------------*/
8500 AccAXRsh (char *x, int shCount)
8508 AccAXRrl1 (x); // 0->a:x
8513 AccAXRrl1 (x); // 0->a:x
8516 AccAXRrl1 (x); // 0->a:x
8521 case 5: // AAAAABBB:CCCCCDDD = a:x
8523 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8525 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8527 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8529 emitcode ("anl", "a,#0x%02x",
8530 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8532 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8534 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8536 emitcode ("anl", "a,#0x%02x",
8537 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8539 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8541 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8543 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8546 case 6: // AABBBBBB:CCDDDDDD
8548 emitcode ("mov", "c,acc.7");
8549 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8551 emitcode ("mov", "c,acc.7");
8552 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8554 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8556 emitcode ("anl", "a,#0x%02x",
8557 SRMask[shCount]); // 000000AA:BBBBBBCC
8560 case 7: // ABBBBBBB:CDDDDDDD
8562 emitcode ("mov", "c,acc.7"); // c = A
8564 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8566 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8568 emitcode ("anl", "a,#0x%02x",
8569 SRMask[shCount]); // 0000000A:BBBBBBBC
8577 /*-----------------------------------------------------------------*/
8578 /* AccAXRshS - right shift signed a:x known count (0..7) */
8579 /*-----------------------------------------------------------------*/
8581 AccAXRshS (char *x, int shCount)
8589 emitcode ("mov", "c,acc.7");
8590 AccAXRrl1 (x); // s->a:x
8594 emitcode ("mov", "c,acc.7");
8595 AccAXRrl1 (x); // s->a:x
8597 emitcode ("mov", "c,acc.7");
8598 AccAXRrl1 (x); // s->a:x
8603 case 5: // AAAAABBB:CCCCCDDD = a:x
8605 tlbl = newiTempLabel (NULL);
8606 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8608 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8610 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8612 emitcode ("anl", "a,#0x%02x",
8613 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8615 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8617 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8619 emitcode ("anl", "a,#0x%02x",
8620 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8622 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8624 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8626 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8628 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8629 emitcode ("orl", "a,#0x%02x",
8630 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8633 break; // SSSSAAAA:BBBCCCCC
8635 case 6: // AABBBBBB:CCDDDDDD
8637 tlbl = newiTempLabel (NULL);
8638 emitcode ("mov", "c,acc.7");
8639 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8641 emitcode ("mov", "c,acc.7");
8642 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8644 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8646 emitcode ("anl", "a,#0x%02x",
8647 SRMask[shCount]); // 000000AA:BBBBBBCC
8649 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8650 emitcode ("orl", "a,#0x%02x",
8651 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8655 case 7: // ABBBBBBB:CDDDDDDD
8657 tlbl = newiTempLabel (NULL);
8658 emitcode ("mov", "c,acc.7"); // c = A
8660 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8662 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8664 emitcode ("anl", "a,#0x%02x",
8665 SRMask[shCount]); // 0000000A:BBBBBBBC
8667 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8668 emitcode ("orl", "a,#0x%02x",
8669 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8678 /*-----------------------------------------------------------------*/
8679 /* shiftL2Left2Result - shift left two bytes from left to result */
8680 /*-----------------------------------------------------------------*/
8682 shiftL2Left2Result (operand * left, int offl,
8683 operand * result, int offr, int shCount)
8686 bool pushedB = FALSE;
8689 if (sameRegs (AOP (result), AOP (left)) &&
8690 ((offl + MSB16) == offr))
8692 /* don't crash result[offr] */
8693 MOVA (aopGet (left, offl, FALSE, FALSE));
8694 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8695 usedB = !strncmp(x, "b", 1);
8697 else if (aopGetUsesAcc (result, offr))
8699 movLeft2Result (left, offl, result, offr, 0);
8702 emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8703 MOVA (aopGet (result, offr, FALSE, FALSE));
8704 emitcode ("xch", "a,b");
8709 movLeft2Result (left, offl, result, offr, 0);
8710 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8711 x = aopGet (result, offr, FALSE, FALSE);
8713 /* ax << shCount (x = lsb(result)) */
8714 AccAXLsh (x, shCount);
8717 emitcode ("xch", "a,b");
8718 aopPut (result, "a", offr);
8719 aopPut (result, "b", offr + MSB16);
8724 aopPut (result, "a", offr + MSB16);
8729 /*-----------------------------------------------------------------*/
8730 /* shiftR2Left2Result - shift right two bytes from left to result */
8731 /*-----------------------------------------------------------------*/
8733 shiftR2Left2Result (operand * left, int offl,
8734 operand * result, int offr,
8735 int shCount, int sign)
8738 bool pushedB = FALSE;
8741 if (sameRegs (AOP (result), AOP (left)) &&
8742 ((offl + MSB16) == offr))
8744 /* don't crash result[offr] */
8745 MOVA (aopGet (left, offl, FALSE, FALSE));
8746 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8747 usedB = !strncmp(x, "b", 1);
8749 else if (aopGetUsesAcc (result, offr))
8751 movLeft2Result (left, offl, result, offr, 0);
8754 emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8755 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8760 movLeft2Result (left, offl, result, offr, 0);
8761 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8762 x = aopGet (result, offr, FALSE, FALSE);
8764 /* a:x >> shCount (x = lsb(result)) */
8766 AccAXRshS (x, shCount);
8768 AccAXRsh (x, shCount);
8771 emitcode ("xch", "a,b");
8772 aopPut (result, "a", offr);
8773 emitcode ("xch", "a,b");
8776 if (getDataSize (result) > 1)
8777 aopPut (result, "a", offr + MSB16);
8780 /*-----------------------------------------------------------------*/
8781 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8782 /*-----------------------------------------------------------------*/
8784 shiftLLeftOrResult (operand * left, int offl,
8785 operand * result, int offr, int shCount)
8787 MOVA (aopGet (left, offl, FALSE, FALSE));
8788 /* shift left accumulator */
8790 /* or with result */
8791 if (aopGetUsesAcc (result, offr))
8793 emitcode ("xch", "a,b");
8794 MOVA (aopGet (result, offr, FALSE, FALSE));
8795 emitcode ("orl", "a,b");
8799 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8801 /* back to result */
8802 aopPut (result, "a", offr);
8805 /*-----------------------------------------------------------------*/
8806 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8807 /*-----------------------------------------------------------------*/
8809 shiftRLeftOrResult (operand * left, int offl,
8810 operand * result, int offr, int shCount)
8812 MOVA (aopGet (left, offl, FALSE, FALSE));
8813 /* shift right accumulator */
8815 /* or with result */
8816 if (aopGetUsesAcc(result, offr))
8818 emitcode ("xch", "a,b");
8819 MOVA (aopGet (result, offr, FALSE, FALSE));
8820 emitcode ("orl", "a,b");
8824 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8826 /* back to result */
8827 aopPut (result, "a", offr);
8830 /*-----------------------------------------------------------------*/
8831 /* genlshOne - left shift a one byte quantity by known count */
8832 /*-----------------------------------------------------------------*/
8834 genlshOne (operand * result, operand * left, int shCount)
8836 D (emitcode (";", "genlshOne"));
8838 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8841 /*-----------------------------------------------------------------*/
8842 /* genlshTwo - left shift two bytes by known amount != 0 */
8843 /*-----------------------------------------------------------------*/
8845 genlshTwo (operand * result, operand * left, int shCount)
8849 D (emitcode (";", "genlshTwo"));
8851 size = getDataSize (result);
8853 /* if shCount >= 8 */
8862 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8866 movLeft2Result (left, LSB, result, MSB16, 0);
8869 aopPut (result, zero, LSB);
8872 /* 1 <= shCount <= 7 */
8876 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8878 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8882 /*-----------------------------------------------------------------*/
8883 /* shiftLLong - shift left one long from left to result */
8884 /* offl = LSB or MSB16 */
8885 /*-----------------------------------------------------------------*/
8887 shiftLLong (operand * left, operand * result, int offr)
8890 int size = AOP_SIZE (result);
8892 if (size >= LSB + offr)
8894 l = aopGet (left, LSB, FALSE, FALSE);
8896 emitcode ("add", "a,acc");
8897 if (sameRegs (AOP (left), AOP (result)) &&
8898 size >= MSB16 + offr && offr != LSB)
8899 xch_a_aopGet (left, LSB + offr, FALSE, FALSE);
8901 aopPut (result, "a", LSB + offr);
8904 if (size >= MSB16 + offr)
8906 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8908 l = aopGet (left, MSB16, FALSE, FALSE);
8911 emitcode ("rlc", "a");
8912 if (sameRegs (AOP (left), AOP (result)) &&
8913 size >= MSB24 + offr && offr != LSB)
8914 xch_a_aopGet (left, MSB16 + offr, FALSE, FALSE);
8916 aopPut (result, "a", MSB16 + offr);
8919 if (size >= MSB24 + offr)
8921 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8923 l = aopGet (left, MSB24, FALSE, FALSE);
8926 emitcode ("rlc", "a");
8927 if (sameRegs (AOP (left), AOP (result)) &&
8928 size >= MSB32 + offr && offr != LSB)
8929 xch_a_aopGet (left, MSB24 + offr, FALSE, FALSE);
8931 aopPut (result, "a", MSB24 + offr);
8934 if (size > MSB32 + offr)
8936 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8938 l = aopGet (left, MSB32, FALSE, FALSE);
8941 emitcode ("rlc", "a");
8942 aopPut (result, "a", MSB32 + offr);
8945 aopPut (result, zero, LSB);
8948 /*-----------------------------------------------------------------*/
8949 /* genlshFour - shift four byte by a known amount != 0 */
8950 /*-----------------------------------------------------------------*/
8952 genlshFour (operand * result, operand * left, int shCount)
8956 D (emitcode (";", "genlshFour"));
8958 size = AOP_SIZE (result);
8960 /* if shifting more that 3 bytes */
8965 /* lowest order of left goes to the highest
8966 order of the destination */
8967 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8969 movLeft2Result (left, LSB, result, MSB32, 0);
8970 aopPut (result, zero, LSB);
8971 aopPut (result, zero, MSB16);
8972 aopPut (result, zero, MSB24);
8976 /* more than two bytes */
8977 else if (shCount >= 16)
8979 /* lower order two bytes goes to higher order two bytes */
8981 /* if some more remaining */
8983 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8986 movLeft2Result (left, MSB16, result, MSB32, 0);
8987 movLeft2Result (left, LSB, result, MSB24, 0);
8989 aopPut (result, zero, MSB16);
8990 aopPut (result, zero, LSB);
8994 /* if more than 1 byte */
8995 else if (shCount >= 8)
8997 /* lower order three bytes goes to higher order three bytes */
9002 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
9004 movLeft2Result (left, LSB, result, MSB16, 0);
9010 movLeft2Result (left, MSB24, result, MSB32, 0);
9011 movLeft2Result (left, MSB16, result, MSB24, 0);
9012 movLeft2Result (left, LSB, result, MSB16, 0);
9013 aopPut (result, zero, LSB);
9015 else if (shCount == 1)
9016 shiftLLong (left, result, MSB16);
9019 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
9020 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
9021 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
9022 aopPut (result, zero, LSB);
9027 /* 1 <= shCount <= 7 */
9028 else if (shCount <= 2)
9030 shiftLLong (left, result, LSB);
9032 shiftLLong (result, result, LSB);
9034 /* 3 <= shCount <= 7, optimize */
9037 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
9038 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
9039 shiftL2Left2Result (left, LSB, result, LSB, shCount);
9043 /*-----------------------------------------------------------------*/
9044 /* genLeftShiftLiteral - left shifting by known count */
9045 /*-----------------------------------------------------------------*/
9047 genLeftShiftLiteral (operand * left,
9052 int shCount = (int) ulFromVal (AOP (right)->aopu.aop_lit);
9055 D (emitcode (";", "genLeftShiftLiteral"));
9057 freeAsmop (right, NULL, ic, TRUE);
9059 aopOp (left, ic, FALSE);
9060 aopOp (result, ic, FALSE);
9062 size = getSize (operandType (result));
9065 emitcode ("; shift left ", "result %d, left %d", size,
9069 /* I suppose that the left size >= result size */
9074 movLeft2Result (left, size, result, size, 0);
9077 else if (shCount >= (size * 8))
9081 aopPut (result, zero, size);
9089 genlshOne (result, left, shCount);
9093 genlshTwo (result, left, shCount);
9097 genlshFour (result, left, shCount);
9100 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9101 "*** ack! mystery literal shift!\n");
9105 freeAsmop (result, NULL, ic, TRUE);
9106 freeAsmop (left, NULL, ic, TRUE);
9109 /*-----------------------------------------------------------------*/
9110 /* genLeftShift - generates code for left shifting */
9111 /*-----------------------------------------------------------------*/
9113 genLeftShift (iCode * ic)
9115 operand *left, *right, *result;
9118 symbol *tlbl, *tlbl1;
9121 D (emitcode (";", "genLeftShift"));
9123 right = IC_RIGHT (ic);
9124 left = IC_LEFT (ic);
9125 result = IC_RESULT (ic);
9127 aopOp (right, ic, FALSE);
9129 /* if the shift count is known then do it
9130 as efficiently as possible */
9131 if (AOP_TYPE (right) == AOP_LIT)
9133 genLeftShiftLiteral (left, right, result, ic);
9137 /* shift count is unknown then we have to form
9138 a loop get the loop count in B : Note: we take
9139 only the lower order byte since shifting
9140 more that 32 bits make no sense anyway, ( the
9141 largest size of an object can be only 32 bits ) */
9144 MOVB (aopGet (right, 0, FALSE, FALSE));
9145 emitcode ("inc", "b");
9146 freeAsmop (right, NULL, ic, TRUE);
9147 aopOp (left, ic, FALSE);
9148 aopOp (result, ic, FALSE);
9150 /* now move the left to the result if they are not the same */
9151 if (!sameRegs (AOP (left), AOP (result)) &&
9152 AOP_SIZE (result) > 1)
9155 size = AOP_SIZE (result);
9159 l = aopGet (left, offset, FALSE, TRUE);
9160 if (*l == '@' && (IS_AOP_PREG (result)))
9163 emitcode ("mov", "a,%s", l);
9164 aopPut (result, "a", offset);
9167 aopPut (result, l, offset);
9172 tlbl = newiTempLabel (NULL);
9173 size = AOP_SIZE (result);
9175 tlbl1 = newiTempLabel (NULL);
9177 /* if it is only one byte then */
9180 symbol *tlbl1 = newiTempLabel (NULL);
9182 l = aopGet (left, 0, FALSE, FALSE);
9184 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9186 emitcode ("add", "a,acc");
9188 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9190 aopPut (result, "a", 0);
9194 reAdjustPreg (AOP (result));
9196 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9198 l = aopGet (result, offset, FALSE, FALSE);
9200 emitcode ("add", "a,acc");
9201 aopPut (result, "a", offset++);
9204 l = aopGet (result, offset, FALSE, FALSE);
9206 emitcode ("rlc", "a");
9207 aopPut (result, "a", offset++);
9209 reAdjustPreg (AOP (result));
9212 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9215 freeAsmop (result, NULL, ic, TRUE);
9216 freeAsmop (left, NULL, ic, TRUE);
9219 /*-----------------------------------------------------------------*/
9220 /* genrshOne - right shift a one byte quantity by known count */
9221 /*-----------------------------------------------------------------*/
9223 genrshOne (operand * result, operand * left,
9224 int shCount, int sign)
9226 D (emitcode (";", "genrshOne"));
9228 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9231 /*-----------------------------------------------------------------*/
9232 /* genrshTwo - right shift two bytes by known amount != 0 */
9233 /*-----------------------------------------------------------------*/
9235 genrshTwo (operand * result, operand * left,
9236 int shCount, int sign)
9238 D (emitcode (";", "genrshTwo"));
9240 /* if shCount >= 8 */
9245 shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
9247 movLeft2Result (left, MSB16, result, LSB, sign);
9248 addSign (result, MSB16, sign);
9251 /* 1 <= shCount <= 7 */
9253 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9256 /*-----------------------------------------------------------------*/
9257 /* shiftRLong - shift right one long from left to result */
9258 /* offl = LSB or MSB16 */
9259 /*-----------------------------------------------------------------*/
9261 shiftRLong (operand * left, int offl,
9262 operand * result, int sign)
9264 bool overlapping = regsInCommon (left, result) || operandsEqu(left, result);
9266 if (overlapping && offl>1)
9268 // we are in big trouble, but this shouldn't happen
9269 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9272 MOVA (aopGet (left, MSB32, FALSE, FALSE));
9279 emitcode ("rlc", "a");
9280 emitcode ("subb", "a,acc");
9281 if (overlapping && sameByte (AOP (left), MSB32, AOP (result), MSB32))
9283 xch_a_aopGet (left, MSB32, FALSE, FALSE);
9287 aopPut (result, "a", MSB32);
9288 MOVA (aopGet (left, MSB32, FALSE, FALSE));
9293 if (aopPutUsesAcc (result, zero, MSB32))
9295 emitcode("xch", "a,b");
9296 aopPut (result, zero, MSB32);
9297 emitcode("xch", "a,b");
9301 aopPut (result, zero, MSB32);
9308 emitcode ("clr", "c");
9312 emitcode ("mov", "c,acc.7");
9315 emitcode ("rrc", "a");
9317 if (overlapping && offl==MSB16 &&
9318 sameByte (AOP (left), MSB24, AOP (result), MSB32-offl))
9320 xch_a_aopGet (left, MSB24, FALSE, FALSE);
9324 aopPut (result, "a", MSB32 - offl);
9325 MOVA (aopGet (left, MSB24, FALSE, FALSE));
9328 emitcode ("rrc", "a");
9329 if (overlapping && offl==MSB16 &&
9330 sameByte (AOP (left), MSB16, AOP (result), MSB24-offl))
9332 xch_a_aopGet (left, MSB16, FALSE, FALSE);
9336 aopPut (result, "a", MSB24 - offl);
9337 MOVA (aopGet (left, MSB16, FALSE, FALSE));
9340 emitcode ("rrc", "a");
9343 aopPut (result, "a", MSB16 - offl);
9348 sameByte (AOP (left), LSB, AOP (result), MSB16-offl))
9350 xch_a_aopGet (left, LSB, FALSE, FALSE);
9354 aopPut (result, "a", MSB16 - offl);
9355 MOVA (aopGet (left, LSB, FALSE, FALSE));
9357 emitcode ("rrc", "a");
9358 aopPut (result, "a", LSB);
9362 /*-----------------------------------------------------------------*/
9363 /* genrshFour - shift four byte by a known amount != 0 */
9364 /*-----------------------------------------------------------------*/
9366 genrshFour (operand * result, operand * left,
9367 int shCount, int sign)
9369 D (emitcode (";", "genrshFour"));
9371 /* if shifting more that 3 bytes */
9376 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9378 movLeft2Result (left, MSB32, result, LSB, sign);
9379 addSign (result, MSB16, sign);
9381 else if (shCount >= 16)
9385 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9388 movLeft2Result (left, MSB24, result, LSB, 0);
9389 movLeft2Result (left, MSB32, result, MSB16, sign);
9391 addSign (result, MSB24, sign);
9393 else if (shCount >= 8)
9398 shiftRLong (left, MSB16, result, sign);
9400 else if (shCount == 0)
9402 movLeft2Result (left, MSB16, result, LSB, 0);
9403 movLeft2Result (left, MSB24, result, MSB16, 0);
9404 movLeft2Result (left, MSB32, result, MSB24, sign);
9405 addSign (result, MSB32, sign);
9409 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9410 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9411 /* the last shift is signed */
9412 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9413 addSign (result, MSB32, sign);
9418 /* 1 <= shCount <= 7 */
9421 shiftRLong (left, LSB, result, sign);
9423 shiftRLong (result, LSB, result, sign);
9427 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9428 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9429 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9434 /*-----------------------------------------------------------------*/
9435 /* genRightShiftLiteral - right shifting by known count */
9436 /*-----------------------------------------------------------------*/
9438 genRightShiftLiteral (operand * left,
9444 int shCount = (int) ulFromVal (AOP (right)->aopu.aop_lit);
9447 D (emitcode (";", "genRightShiftLiteral"));
9449 freeAsmop (right, NULL, ic, TRUE);
9451 aopOp (left, ic, FALSE);
9452 aopOp (result, ic, FALSE);
9455 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9459 size = getDataSize (left);
9460 /* test the LEFT size !!! */
9462 /* I suppose that the left size >= result size */
9465 size = getDataSize (result);
9467 movLeft2Result (left, size, result, size, 0);
9469 else if (shCount >= (size * 8))
9473 /* get sign in acc.7 */
9474 MOVA (aopGet (left, size - 1, FALSE, FALSE));
9476 addSign (result, LSB, sign);
9483 genrshOne (result, left, shCount, sign);
9487 genrshTwo (result, left, shCount, sign);
9491 genrshFour (result, left, shCount, sign);
9497 freeAsmop (result, NULL, ic, TRUE);
9498 freeAsmop (left, NULL, ic, TRUE);
9501 /*-----------------------------------------------------------------*/
9502 /* genSignedRightShift - right shift of signed number */
9503 /*-----------------------------------------------------------------*/
9505 genSignedRightShift (iCode * ic)
9507 operand *right, *left, *result;
9510 symbol *tlbl, *tlbl1;
9513 D (emitcode (";", "genSignedRightShift"));
9515 /* we do it the hard way put the shift count in b
9516 and loop thru preserving the sign */
9518 right = IC_RIGHT (ic);
9519 left = IC_LEFT (ic);
9520 result = IC_RESULT (ic);
9522 aopOp (right, ic, FALSE);
9525 if (AOP_TYPE (right) == AOP_LIT)
9527 genRightShiftLiteral (left, right, result, ic, 1);
9530 /* shift count is unknown then we have to form
9531 a loop get the loop count in B : Note: we take
9532 only the lower order byte since shifting
9533 more that 32 bits make no sense anyway, ( the
9534 largest size of an object can be only 32 bits ) */
9537 MOVB (aopGet (right, 0, FALSE, FALSE));
9538 emitcode ("inc", "b");
9539 freeAsmop (right, NULL, ic, TRUE);
9540 aopOp (left, ic, FALSE);
9541 aopOp (result, ic, FALSE);
9543 /* now move the left to the result if they are not the
9545 if (!sameRegs (AOP (left), AOP (result)) &&
9546 AOP_SIZE (result) > 1)
9549 size = AOP_SIZE (result);
9553 l = aopGet (left, offset, FALSE, TRUE);
9554 if (*l == '@' && IS_AOP_PREG (result))
9557 emitcode ("mov", "a,%s", l);
9558 aopPut (result, "a", offset);
9561 aopPut (result, l, offset);
9566 /* mov the highest order bit to OVR */
9567 tlbl = newiTempLabel (NULL);
9568 tlbl1 = newiTempLabel (NULL);
9570 size = AOP_SIZE (result);
9572 MOVA (aopGet (left, offset, FALSE, FALSE));
9573 emitcode ("rlc", "a");
9574 emitcode ("mov", "ov,c");
9575 /* if it is only one byte then */
9578 l = aopGet (left, 0, FALSE, FALSE);
9580 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9582 emitcode ("mov", "c,ov");
9583 emitcode ("rrc", "a");
9585 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9587 aopPut (result, "a", 0);
9591 reAdjustPreg (AOP (result));
9592 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9594 emitcode ("mov", "c,ov");
9597 l = aopGet (result, offset, FALSE, FALSE);
9599 emitcode ("rrc", "a");
9600 aopPut (result, "a", offset--);
9602 reAdjustPreg (AOP (result));
9604 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9608 freeAsmop (result, NULL, ic, TRUE);
9609 freeAsmop (left, NULL, ic, TRUE);
9612 /*-----------------------------------------------------------------*/
9613 /* genRightShift - generate code for right shifting */
9614 /*-----------------------------------------------------------------*/
9616 genRightShift (iCode * ic)
9618 operand *right, *left, *result;
9622 symbol *tlbl, *tlbl1;
9625 D (emitcode (";", "genRightShift"));
9627 /* if signed then we do it the hard way preserve the
9628 sign bit moving it inwards */
9629 letype = getSpec (operandType (IC_LEFT (ic)));
9631 if (!SPEC_USIGN (letype))
9633 genSignedRightShift (ic);
9637 /* signed & unsigned types are treated the same : i.e. the
9638 signed is NOT propagated inwards : quoting from the
9639 ANSI - standard : "for E1 >> E2, is equivalent to division
9640 by 2**E2 if unsigned or if it has a non-negative value,
9641 otherwise the result is implementation defined ", MY definition
9642 is that the sign does not get propagated */
9644 right = IC_RIGHT (ic);
9645 left = IC_LEFT (ic);
9646 result = IC_RESULT (ic);
9648 aopOp (right, ic, FALSE);
9650 /* if the shift count is known then do it
9651 as efficiently as possible */
9652 if (AOP_TYPE (right) == AOP_LIT)
9654 genRightShiftLiteral (left, right, result, ic, 0);
9658 /* shift count is unknown then we have to form
9659 a loop get the loop count in B : Note: we take
9660 only the lower order byte since shifting
9661 more that 32 bits make no sense anyway, ( the
9662 largest size of an object can be only 32 bits ) */
9665 MOVB (aopGet (right, 0, FALSE, FALSE));
9666 emitcode ("inc", "b");
9667 freeAsmop (right, NULL, ic, TRUE);
9668 aopOp (left, ic, FALSE);
9669 aopOp (result, ic, FALSE);
9671 /* now move the left to the result if they are not the
9673 if (!sameRegs (AOP (left), AOP (result)) &&
9674 AOP_SIZE (result) > 1)
9676 size = AOP_SIZE (result);
9680 l = aopGet (left, offset, FALSE, TRUE);
9681 if (*l == '@' && IS_AOP_PREG (result))
9684 emitcode ("mov", "a,%s", l);
9685 aopPut (result, "a", offset);
9688 aopPut (result, l, offset);
9693 tlbl = newiTempLabel (NULL);
9694 tlbl1 = newiTempLabel (NULL);
9695 size = AOP_SIZE (result);
9698 /* if it is only one byte then */
9701 l = aopGet (left, 0, FALSE, FALSE);
9703 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9706 emitcode ("rrc", "a");
9708 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9710 aopPut (result, "a", 0);
9714 reAdjustPreg (AOP (result));
9715 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9720 l = aopGet (result, offset, FALSE, FALSE);
9722 emitcode ("rrc", "a");
9723 aopPut (result, "a", offset--);
9725 reAdjustPreg (AOP (result));
9728 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9732 freeAsmop (result, NULL, ic, TRUE);
9733 freeAsmop (left, NULL, ic, TRUE);
9736 /*-----------------------------------------------------------------*/
9737 /* emitPtrByteGet - emits code to get a byte into A through a */
9738 /* pointer register (R0, R1, or DPTR). The */
9739 /* original value of A can be preserved in B. */
9740 /*-----------------------------------------------------------------*/
9742 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9749 emitcode ("mov", "b,a");
9750 emitcode ("mov", "a,@%s", rname);
9755 emitcode ("mov", "b,a");
9756 emitcode ("movx", "a,@%s", rname);
9761 emitcode ("mov", "b,a");
9762 emitcode ("movx", "a,@dptr");
9767 emitcode ("mov", "b,a");
9768 emitcode ("clr", "a");
9769 emitcode ("movc", "a,@a+dptr");
9775 emitcode ("push", "b");
9776 emitcode ("push", "acc");
9778 emitcode ("lcall", "__gptrget");
9780 emitcode ("pop", "b");
9785 /*-----------------------------------------------------------------*/
9786 /* emitPtrByteSet - emits code to set a byte from src through a */
9787 /* pointer register (R0, R1, or DPTR). */
9788 /*-----------------------------------------------------------------*/
9790 emitPtrByteSet (char *rname, int p_type, char *src)
9799 emitcode ("mov", "@%s,a", rname);
9802 emitcode ("mov", "@%s,%s", rname, src);
9807 emitcode ("movx", "@%s,a", rname);
9812 emitcode ("movx", "@dptr,a");
9817 emitcode ("lcall", "__gptrput");
9822 /*-----------------------------------------------------------------*/
9823 /* genUnpackBits - generates code for unpacking bits */
9824 /*-----------------------------------------------------------------*/
9826 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9828 int offset = 0; /* result byte offset */
9829 int rsize; /* result size */
9830 int rlen = 0; /* remaining bitfield length */
9831 sym_link *etype; /* bitfield type information */
9832 int blen; /* bitfield length */
9833 int bstr; /* bitfield starting bit within byte */
9834 static char* const accBits[] = {"acc.0", "acc.1", "acc.2", "acc.3",
9835 "acc.4", "acc.5", "acc.6", "acc.7"};
9837 D(emitcode (";", "genUnpackBits"));
9839 etype = getSpec (operandType (result));
9840 rsize = getSize (operandType (result));
9841 blen = SPEC_BLEN (etype);
9842 bstr = SPEC_BSTR (etype);
9844 if (ifx && blen <= 8)
9846 emitPtrByteGet (rname, ptype, FALSE);
9849 return accBits[bstr];;
9854 emitcode ("anl", "a,#0x%02x",
9855 (((unsigned char) -1) >> (8 - blen)) << bstr);
9861 /* If the bitfield length is less than a byte */
9864 emitPtrByteGet (rname, ptype, FALSE);
9866 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9867 if (!SPEC_USIGN (etype))
9869 /* signed bitfield */
9870 symbol *tlbl = newiTempLabel (NULL);
9872 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9873 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9876 aopPut (result, "a", offset++);
9880 /* Bit field did not fit in a byte. Copy all
9881 but the partial byte at the end. */
9882 for (rlen=blen;rlen>=8;rlen-=8)
9884 emitPtrByteGet (rname, ptype, FALSE);
9885 aopPut (result, "a", offset++);
9887 emitcode ("inc", "%s", rname);
9890 /* Handle the partial byte at the end */
9893 emitPtrByteGet (rname, ptype, FALSE);
9894 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9895 if (!SPEC_USIGN (etype))
9897 /* signed bitfield */
9898 symbol *tlbl = newiTempLabel (NULL);
9900 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9901 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9904 aopPut (result, "a", offset++);
9912 if (SPEC_USIGN (etype))
9916 /* signed bitfield: sign extension with 0x00 or 0xff */
9917 emitcode ("rlc", "a");
9918 emitcode ("subb", "a,acc");
9924 aopPut (result, source, offset++);
9930 /*-----------------------------------------------------------------*/
9931 /* genDataPointerGet - generates code when ptr offset is known */
9932 /*-----------------------------------------------------------------*/
9934 genDataPointerGet (operand * left,
9940 int size, offset = 0;
9942 D (emitcode (";", "genDataPointerGet"));
9944 aopOp (result, ic, TRUE);
9946 /* get the string representation of the name */
9947 l = aopGet (left, 0, FALSE, TRUE);
9949 size = AOP_SIZE (result);
9954 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
9958 SNPRINTF (buffer, sizeof(buffer), "%s", l);
9960 aopPut (result, buffer, offset++);
9963 freeAsmop (result, NULL, ic, TRUE);
9964 freeAsmop (left, NULL, ic, TRUE);
9967 /*-----------------------------------------------------------------*/
9968 /* genNearPointerGet - emitcode for near pointer fetch */
9969 /*-----------------------------------------------------------------*/
9971 genNearPointerGet (operand * left,
9980 char *ifxCond = "a";
9981 sym_link *rtype, *retype;
9982 sym_link *ltype = operandType (left);
9984 D (emitcode (";", "genNearPointerGet"));
9986 rtype = operandType (result);
9987 retype = getSpec (rtype);
9989 aopOp (left, ic, FALSE);
9991 /* if left is rematerialisable and
9992 result is not bitfield variable type and
9993 the left is pointer to data space i.e
9994 lower 128 bytes of space */
9995 if (AOP_TYPE (left) == AOP_IMMD &&
9996 !IS_BITFIELD (retype) &&
9997 DCL_TYPE (ltype) == POINTER)
9999 genDataPointerGet (left, result, ic);
10003 //aopOp (result, ic, FALSE);
10004 aopOp (result, ic, result?TRUE:FALSE);
10006 /* if the value is already in a pointer register
10007 then don't need anything more */
10008 if (!AOP_INPREG (AOP (left)))
10010 if (IS_AOP_PREG (left))
10012 // Aha, it is a pointer, just in disguise.
10013 rname = aopGet (left, 0, FALSE, FALSE);
10016 fprintf(stderr, "probable internal error: unexpected rname '%s' @ %s:%d\n",
10017 rname, __FILE__, __LINE__);
10022 emitcode ("mov", "a%s,%s", rname + 1, rname);
10023 rname++; // skip the '@'.
10028 /* otherwise get a free pointer register */
10029 aop = newAsmop (0);
10030 preg = getFreePtr (ic, &aop, FALSE);
10031 emitcode ("mov", "%s,%s",
10033 aopGet (left, 0, FALSE, TRUE));
10034 rname = preg->name;
10038 rname = aopGet (left, 0, FALSE, FALSE);
10040 /* if bitfield then unpack the bits */
10041 if (IS_BITFIELD (retype))
10042 ifxCond = genUnpackBits (result, rname, POINTER, ifx);
10045 /* we have can just get the values */
10046 int size = AOP_SIZE (result);
10051 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
10054 emitcode ("mov", "a,@%s", rname);
10056 aopPut (result, "a", offset);
10062 SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
10063 aopPut (result, buffer, offset);
10067 emitcode ("inc", "%s", rname);
10071 /* now some housekeeping stuff */
10072 if (aop) /* we had to allocate for this iCode */
10074 if (pi) { /* post increment present */
10075 aopPut (left, rname, 0);
10077 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
10081 /* we did not allocate which means left
10082 already in a pointer register, then
10083 if size > 0 && this could be used again
10084 we have to point it back to where it
10086 if ((AOP_SIZE (result) > 1 &&
10087 !OP_SYMBOL (left)->remat &&
10088 (OP_SYMBOL (left)->liveTo > ic->seq ||
10092 int size = AOP_SIZE (result) - 1;
10094 emitcode ("dec", "%s", rname);
10098 if (ifx && !ifx->generated)
10100 genIfxJump (ifx, ifxCond, left, NULL, result, ic->next);
10104 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
10105 freeAsmop (left, NULL, ic, TRUE);
10106 if (pi) pi->generated = 1;
10109 /*-----------------------------------------------------------------*/
10110 /* genPagedPointerGet - emitcode for paged pointer fetch */
10111 /*-----------------------------------------------------------------*/
10113 genPagedPointerGet (operand * left,
10122 char *ifxCond = "a";
10123 sym_link *rtype, *retype;
10125 D (emitcode (";", "genPagedPointerGet"));
10127 rtype = operandType (result);
10128 retype = getSpec (rtype);
10130 aopOp (left, ic, FALSE);
10132 aopOp (result, ic, FALSE);
10134 /* if the value is already in a pointer register
10135 then don't need anything more */
10136 if (!AOP_INPREG (AOP (left)))
10138 /* otherwise get a free pointer register */
10139 aop = newAsmop (0);
10140 preg = getFreePtr (ic, &aop, FALSE);
10141 emitcode ("mov", "%s,%s",
10143 aopGet (left, 0, FALSE, TRUE));
10144 rname = preg->name;
10147 rname = aopGet (left, 0, FALSE, FALSE);
10149 /* if bitfield then unpack the bits */
10150 if (IS_BITFIELD (retype))
10151 ifxCond = genUnpackBits (result, rname, PPOINTER, ifx);
10154 /* we have can just get the values */
10155 int size = AOP_SIZE (result);
10161 emitcode ("movx", "a,@%s", rname);
10163 aopPut (result, "a", offset);
10168 emitcode ("inc", "%s", rname);
10172 /* now some housekeeping stuff */
10173 if (aop) /* we had to allocate for this iCode */
10176 aopPut (left, rname, 0);
10177 freeAsmop (NULL, aop, ic, TRUE);
10181 /* we did not allocate which means left
10182 already in a pointer register, then
10183 if size > 0 && this could be used again
10184 we have to point it back to where it
10186 if ((AOP_SIZE (result) > 1 &&
10187 !OP_SYMBOL (left)->remat &&
10188 (OP_SYMBOL (left)->liveTo > ic->seq ||
10192 int size = AOP_SIZE (result) - 1;
10194 emitcode ("dec", "%s", rname);
10198 if (ifx && !ifx->generated)
10200 genIfxJump (ifx, ifxCond, left, NULL, result, ic->next);
10204 freeAsmop (result, NULL, ic, TRUE);
10205 freeAsmop (left, NULL, ic, TRUE);
10206 if (pi) pi->generated = 1;
10209 /*--------------------------------------------------------------------*/
10210 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
10211 /*--------------------------------------------------------------------*/
10213 loadDptrFromOperand (operand *op, bool loadBToo)
10215 if (AOP_TYPE (op) != AOP_STR)
10217 /* if this is rematerializable */
10218 if (AOP_TYPE (op) == AOP_IMMD)
10220 emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
10223 if (AOP(op)->aopu.aop_immd.from_cast_remat)
10224 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
10227 wassertl(FALSE, "need pointerCode");
10228 emitcode (";", "mov b,???");
10229 /* genPointerGet and genPointerSet originally did different
10230 ** things for this case. Both seem wrong.
10231 ** from genPointerGet:
10232 ** emitcode ("mov", "b,#%d", pointerCode (retype));
10233 ** from genPointerSet:
10234 ** emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
10239 else if (AOP_TYPE (op) == AOP_DPTR)
10243 MOVA (aopGet (op, 0, FALSE, FALSE));
10244 emitcode ("push", "acc");
10245 MOVA (aopGet (op, 1, FALSE, FALSE));
10246 emitcode ("push", "acc");
10247 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10248 emitcode ("pop", "dph");
10249 emitcode ("pop", "dpl");
10253 MOVA (aopGet (op, 0, FALSE, FALSE));
10254 emitcode ("push", "acc");
10255 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10256 emitcode ("pop", "dpl");
10260 { /* we need to get it byte by byte */
10261 emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
10262 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10264 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10269 /*-----------------------------------------------------------------*/
10270 /* genFarPointerGet - get value from far space */
10271 /*-----------------------------------------------------------------*/
10273 genFarPointerGet (operand * left,
10274 operand * result, iCode * ic, iCode * pi, iCode * ifx)
10277 char *ifxCond = "a";
10278 sym_link *retype = getSpec (operandType (result));
10280 D (emitcode (";", "genFarPointerGet"));
10282 aopOp (left, ic, FALSE);
10283 loadDptrFromOperand (left, FALSE);
10285 /* so dptr now contains the address */
10286 aopOp (result, ic, FALSE);
10288 /* if bit then unpack */
10289 if (IS_BITFIELD (retype))
10290 ifxCond = genUnpackBits (result, "dptr", FPOINTER, ifx);
10293 size = AOP_SIZE (result);
10298 emitcode ("movx", "a,@dptr");
10300 aopPut (result, "a", offset++);
10302 emitcode ("inc", "dptr");
10306 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10308 aopPut (left, "dpl", 0);
10309 aopPut (left, "dph", 1);
10313 if (ifx && !ifx->generated)
10315 genIfxJump (ifx, ifxCond, left, NULL, result, ic->next);
10318 freeAsmop (result, NULL, ic, TRUE);
10319 freeAsmop (left, NULL, ic, TRUE);
10322 /*-----------------------------------------------------------------*/
10323 /* genCodePointerGet - get value from code space */
10324 /*-----------------------------------------------------------------*/
10326 genCodePointerGet (operand * left,
10327 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10330 char *ifxCond = "a";
10331 sym_link *retype = getSpec (operandType (result));
10333 D (emitcode (";", "genCodePointerGet"));
10335 aopOp (left, ic, FALSE);
10336 loadDptrFromOperand (left, FALSE);
10338 /* so dptr now contains the address */
10339 aopOp (result, ic, FALSE);
10341 /* if bit then unpack */
10342 if (IS_BITFIELD (retype))
10343 ifxCond = genUnpackBits (result, "dptr", CPOINTER, ifx);
10346 size = AOP_SIZE (result);
10351 emitcode ("clr", "a");
10352 emitcode ("movc", "a,@a+dptr");
10354 aopPut (result, "a", offset++);
10356 emitcode ("inc", "dptr");
10360 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10362 aopPut (left, "dpl", 0);
10363 aopPut (left, "dph", 1);
10367 if (ifx && !ifx->generated)
10369 genIfxJump (ifx, ifxCond, left, NULL, result, ic->next);
10372 freeAsmop (result, NULL, ic, TRUE);
10373 freeAsmop (left, NULL, ic, TRUE);
10376 /*-----------------------------------------------------------------*/
10377 /* genGenPointerGet - get value from generic pointer space */
10378 /*-----------------------------------------------------------------*/
10380 genGenPointerGet (operand * left,
10381 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10384 char *ifxCond = "a";
10385 sym_link *retype = getSpec (operandType (result));
10387 D (emitcode (";", "genGenPointerGet"));
10389 aopOp (left, ic, FALSE);
10390 loadDptrFromOperand (left, TRUE);
10392 /* so dptr now contains the address */
10393 aopOp (result, ic, FALSE);
10395 /* if bit then unpack */
10396 if (IS_BITFIELD (retype))
10398 ifxCond = genUnpackBits (result, "dptr", GPOINTER, ifx);
10402 size = AOP_SIZE (result);
10407 emitcode ("lcall", "__gptrget");
10409 aopPut (result, "a", offset++);
10411 emitcode ("inc", "dptr");
10415 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10417 aopPut (left, "dpl", 0);
10418 aopPut (left, "dph", 1);
10422 if (ifx && !ifx->generated)
10424 genIfxJump (ifx, ifxCond, left, NULL, result, ic->next);
10427 freeAsmop (result, NULL, ic, TRUE);
10428 freeAsmop (left, NULL, ic, TRUE);
10431 /*-----------------------------------------------------------------*/
10432 /* genPointerGet - generate code for pointer get */
10433 /*-----------------------------------------------------------------*/
10435 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
10437 operand *left, *result;
10438 sym_link *type, *etype;
10441 D (emitcode (";", "genPointerGet"));
10443 left = IC_LEFT (ic);
10444 result = IC_RESULT (ic);
10446 if (getSize (operandType (result))>1)
10449 /* depending on the type of pointer we need to
10450 move it to the correct pointer register */
10451 type = operandType (left);
10452 etype = getSpec (type);
10453 /* if left is of type of pointer then it is simple */
10454 if (IS_PTR (type) && !IS_FUNC (type->next))
10456 p_type = DCL_TYPE (type);
10460 /* we have to go by the storage class */
10461 p_type = PTR_TYPE (SPEC_OCLS (etype));
10464 /* special case when cast remat */
10465 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10466 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10468 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10469 type = operandType (left);
10470 p_type = DCL_TYPE (type);
10472 /* now that we have the pointer type we assign
10473 the pointer values */
10479 genNearPointerGet (left, result, ic, pi, ifx);
10483 genPagedPointerGet (left, result, ic, pi, ifx);
10487 genFarPointerGet (left, result, ic, pi, ifx);
10491 genCodePointerGet (left, result, ic, pi, ifx);
10495 genGenPointerGet (left, result, ic, pi, ifx);
10501 /*-----------------------------------------------------------------*/
10502 /* genPackBits - generates code for packed bit storage */
10503 /*-----------------------------------------------------------------*/
10505 genPackBits (sym_link * etype,
10507 char *rname, int p_type)
10509 int offset = 0; /* source byte offset */
10510 int rlen = 0; /* remaining bitfield length */
10511 int blen; /* bitfield length */
10512 int bstr; /* bitfield starting bit within byte */
10513 int litval; /* source literal value (if AOP_LIT) */
10514 unsigned char mask; /* bitmask within current byte */
10516 D(emitcode (";", "genPackBits"));
10518 blen = SPEC_BLEN (etype);
10519 bstr = SPEC_BSTR (etype);
10521 /* If the bitfield length is less than a byte */
10524 mask = ((unsigned char) (0xFF << (blen + bstr)) |
10525 (unsigned char) (0xFF >> (8 - bstr)));
10527 if (AOP_TYPE (right) == AOP_LIT)
10529 /* Case with a bitfield length <8 and literal source
10531 litval = (int) ulFromVal (AOP (right)->aopu.aop_lit);
10533 litval &= (~mask) & 0xff;
10534 emitPtrByteGet (rname, p_type, FALSE);
10535 if ((mask|litval)!=0xff)
10536 emitcode ("anl","a,#0x%02x", mask);
10538 emitcode ("orl","a,#0x%02x", litval);
10542 if ((blen==1) && (p_type!=GPOINTER))
10544 /* Case with a bitfield length == 1 and no generic pointer
10546 if (AOP_TYPE (right) == AOP_CRY)
10547 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10550 MOVA (aopGet (right, 0, FALSE, FALSE));
10551 emitcode ("rrc","a");
10553 emitPtrByteGet (rname, p_type, FALSE);
10554 emitcode ("mov","acc.%d,c",bstr);
10559 /* Case with a bitfield length < 8 and arbitrary source
10561 MOVA (aopGet (right, 0, FALSE, FALSE));
10562 /* shift and mask source value */
10564 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10566 pushedB = pushB ();
10567 /* transfer A to B and get next byte */
10568 emitPtrByteGet (rname, p_type, TRUE);
10570 emitcode ("anl", "a,#0x%02x", mask);
10571 emitcode ("orl", "a,b");
10572 if (p_type == GPOINTER)
10573 emitcode ("pop", "b");
10579 emitPtrByteSet (rname, p_type, "a");
10583 /* Bit length is greater than 7 bits. In this case, copy */
10584 /* all except the partial byte at the end */
10585 for (rlen=blen;rlen>=8;rlen-=8)
10587 emitPtrByteSet (rname, p_type,
10588 aopGet (right, offset++, FALSE, TRUE) );
10590 emitcode ("inc", "%s", rname);
10593 /* If there was a partial byte at the end */
10596 mask = (((unsigned char) -1 << rlen) & 0xff);
10598 if (AOP_TYPE (right) == AOP_LIT)
10600 /* Case with partial byte and literal source
10602 litval = (int) ulFromVal (AOP (right)->aopu.aop_lit);
10603 litval >>= (blen-rlen);
10604 litval &= (~mask) & 0xff;
10605 emitPtrByteGet (rname, p_type, FALSE);
10606 if ((mask|litval)!=0xff)
10607 emitcode ("anl","a,#0x%02x", mask);
10609 emitcode ("orl","a,#0x%02x", litval);
10614 /* Case with partial byte and arbitrary source
10616 MOVA (aopGet (right, offset++, FALSE, FALSE));
10617 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10619 pushedB = pushB ();
10620 /* transfer A to B and get next byte */
10621 emitPtrByteGet (rname, p_type, TRUE);
10623 emitcode ("anl", "a,#0x%02x", mask);
10624 emitcode ("orl", "a,b");
10625 if (p_type == GPOINTER)
10626 emitcode ("pop", "b");
10630 emitPtrByteSet (rname, p_type, "a");
10635 /*-----------------------------------------------------------------*/
10636 /* genDataPointerSet - remat pointer to data space */
10637 /*-----------------------------------------------------------------*/
10639 genDataPointerSet (operand * right,
10643 int size, offset = 0;
10644 char *l, buffer[256];
10646 D (emitcode (";", "genDataPointerSet"));
10648 aopOp (right, ic, FALSE);
10650 l = aopGet (result, 0, FALSE, TRUE);
10652 size = max (AOP_SIZE (right), AOP_SIZE (result));
10656 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
10658 SNPRINTF (buffer, sizeof(buffer), "%s", l);
10659 emitcode ("mov", "%s,%s", buffer,
10660 aopGet (right, offset++, FALSE, FALSE));
10663 freeAsmop (right, NULL, ic, TRUE);
10664 freeAsmop (result, NULL, ic, TRUE);
10667 /*-----------------------------------------------------------------*/
10668 /* genNearPointerSet - emitcode for near pointer put */
10669 /*-----------------------------------------------------------------*/
10671 genNearPointerSet (operand * right,
10679 sym_link *retype, *letype;
10680 sym_link *ptype = operandType (result);
10682 D (emitcode (";", "genNearPointerSet"));
10684 retype = getSpec (operandType (right));
10685 letype = getSpec (ptype);
10687 aopOp (result, ic, FALSE);
10689 /* if the result is rematerializable &
10690 in data space & not a bit variable */
10691 if (AOP_TYPE (result) == AOP_IMMD &&
10692 DCL_TYPE (ptype) == POINTER &&
10693 !IS_BITVAR (retype) &&
10694 !IS_BITVAR (letype))
10696 genDataPointerSet (right, result, ic);
10700 /* if the value is already in a pointer register
10701 then don't need anything more */
10702 if (!AOP_INPREG (AOP (result)))
10704 if (IS_AOP_PREG (result))
10706 // Aha, it is a pointer, just in disguise.
10707 rname = aopGet (result, 0, FALSE, FALSE);
10710 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10711 __FILE__, __LINE__);
10716 emitcode ("mov", "a%s,%s", rname + 1, rname);
10717 rname++; // skip the '@'.
10722 /* otherwise get a free pointer register */
10723 aop = newAsmop (0);
10724 preg = getFreePtr (ic, &aop, FALSE);
10725 emitcode ("mov", "%s,%s",
10727 aopGet (result, 0, FALSE, TRUE));
10728 rname = preg->name;
10733 rname = aopGet (result, 0, FALSE, FALSE);
10736 aopOp (right, ic, FALSE);
10738 /* if bitfield then unpack the bits */
10739 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10740 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10743 /* we can just get the values */
10744 int size = AOP_SIZE (right);
10749 l = aopGet (right, offset, FALSE, TRUE);
10750 if ((*l == '@') || (strcmp (l, "acc") == 0))
10753 emitcode ("mov", "@%s,a", rname);
10756 emitcode ("mov", "@%s,%s", rname, l);
10758 emitcode ("inc", "%s", rname);
10763 /* now some housekeeping stuff */
10764 if (aop) /* we had to allocate for this iCode */
10767 aopPut (result, rname, 0);
10768 freeAsmop (NULL, aop, ic, TRUE);
10772 /* we did not allocate which means left
10773 already in a pointer register, then
10774 if size > 0 && this could be used again
10775 we have to point it back to where it
10777 if ((AOP_SIZE (right) > 1 &&
10778 !OP_SYMBOL (result)->remat &&
10779 (OP_SYMBOL (result)->liveTo > ic->seq ||
10783 int size = AOP_SIZE (right) - 1;
10785 emitcode ("dec", "%s", rname);
10792 freeAsmop (right, NULL, ic, TRUE);
10793 freeAsmop (result, NULL, ic, TRUE);
10796 /*-----------------------------------------------------------------*/
10797 /* genPagedPointerSet - emitcode for Paged pointer put */
10798 /*-----------------------------------------------------------------*/
10800 genPagedPointerSet (operand * right,
10808 sym_link *retype, *letype;
10810 D (emitcode (";", "genPagedPointerSet"));
10812 retype = getSpec (operandType (right));
10813 letype = getSpec (operandType (result));
10815 aopOp (result, ic, FALSE);
10817 /* if the value is already in a pointer register
10818 then don't need anything more */
10819 if (!AOP_INPREG (AOP (result)))
10821 if (IS_AOP_PREG (result))
10823 // Aha, it is a pointer, just in disguise.
10824 rname = aopGet (result, 0, FALSE, FALSE);
10827 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10828 __FILE__, __LINE__);
10833 emitcode ("mov", "a%s,%s", rname + 1, rname);
10834 rname++; // skip the '@'.
10839 /* otherwise get a free pointer register */
10840 aop = newAsmop (0);
10841 preg = getFreePtr (ic, &aop, FALSE);
10842 emitcode ("mov", "%s,%s",
10844 aopGet (result, 0, FALSE, TRUE));
10845 rname = preg->name;
10850 rname = aopGet (result, 0, FALSE, FALSE);
10853 aopOp (right, ic, FALSE);
10855 /* if bitfield then unpack the bits */
10856 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10857 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10860 /* we can just get the values */
10861 int size = AOP_SIZE (right);
10866 l = aopGet (right, offset, FALSE, TRUE);
10868 emitcode ("movx", "@%s,a", rname);
10870 emitcode ("inc", "%s", rname);
10875 /* now some housekeeping stuff */
10876 if (aop) /* we had to allocate for this iCode */
10879 aopPut (result, rname, 0);
10880 freeAsmop (NULL, aop, ic, TRUE);
10884 /* we did not allocate which means left
10885 already in a pointer register, then
10886 if size > 0 && this could be used again
10887 we have to point it back to where it
10889 if (AOP_SIZE (right) > 1 &&
10890 !OP_SYMBOL (result)->remat &&
10891 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth) &&
10894 int size = AOP_SIZE (right) - 1;
10896 emitcode ("dec", "%s", rname);
10903 freeAsmop (right, NULL, ic, TRUE);
10904 freeAsmop (result, NULL, ic, TRUE);
10907 /*-----------------------------------------------------------------*/
10908 /* genFarPointerSet - set value from far space */
10909 /*-----------------------------------------------------------------*/
10911 genFarPointerSet (operand * right,
10912 operand * result, iCode * ic, iCode * pi)
10915 sym_link *retype = getSpec (operandType (right));
10916 sym_link *letype = getSpec (operandType (result));
10918 D(emitcode (";", "genFarPointerSet"));
10920 aopOp (result, ic, FALSE);
10921 loadDptrFromOperand (result, FALSE);
10923 /* so dptr now contains the address */
10924 aopOp (right, ic, FALSE);
10926 /* if bit then unpack */
10927 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10928 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10931 size = AOP_SIZE (right);
10936 char *l = aopGet (right, offset++, FALSE, FALSE);
10938 emitcode ("movx", "@dptr,a");
10940 emitcode ("inc", "dptr");
10943 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10944 aopPut (result, "dpl", 0);
10945 aopPut (result, "dph", 1);
10948 freeAsmop (result, NULL, ic, TRUE);
10949 freeAsmop (right, NULL, ic, TRUE);
10952 /*-----------------------------------------------------------------*/
10953 /* genGenPointerSet - set value from generic pointer space */
10954 /*-----------------------------------------------------------------*/
10956 genGenPointerSet (operand * right,
10957 operand * result, iCode * ic, iCode * pi)
10960 sym_link *retype = getSpec (operandType (right));
10961 sym_link *letype = getSpec (operandType (result));
10963 D (emitcode (";", "genGenPointerSet"));
10965 aopOp (result, ic, FALSE);
10966 loadDptrFromOperand (result, TRUE);
10968 /* so dptr now contains the address */
10969 aopOp (right, ic, FALSE);
10971 /* if bit then unpack */
10972 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10974 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10978 size = AOP_SIZE (right);
10983 char *l = aopGet (right, offset++, FALSE, FALSE);
10985 emitcode ("lcall", "__gptrput");
10987 emitcode ("inc", "dptr");
10991 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10992 aopPut (result, "dpl", 0);
10993 aopPut (result, "dph", 1);
10996 freeAsmop (result, NULL, ic, TRUE);
10997 freeAsmop (right, NULL, ic, TRUE);
11000 /*-----------------------------------------------------------------*/
11001 /* genPointerSet - stores the value into a pointer location */
11002 /*-----------------------------------------------------------------*/
11004 genPointerSet (iCode * ic, iCode *pi)
11006 operand *right, *result;
11007 sym_link *type, *etype;
11010 D (emitcode (";", "genPointerSet"));
11012 right = IC_RIGHT (ic);
11013 result = IC_RESULT (ic);
11015 /* depending on the type of pointer we need to
11016 move it to the correct pointer register */
11017 type = operandType (result);
11018 etype = getSpec (type);
11019 /* if left is of type of pointer then it is simple */
11020 if (IS_PTR (type) && !IS_FUNC (type->next))
11022 p_type = DCL_TYPE (type);
11026 /* we have to go by the storage class */
11027 p_type = PTR_TYPE (SPEC_OCLS (etype));
11030 /* special case when cast remat */
11031 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
11032 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
11033 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
11034 type = operandType (result);
11035 p_type = DCL_TYPE (type);
11038 /* now that we have the pointer type we assign
11039 the pointer values */
11045 genNearPointerSet (right, result, ic, pi);
11049 genPagedPointerSet (right, result, ic, pi);
11053 genFarPointerSet (right, result, ic, pi);
11057 genGenPointerSet (right, result, ic, pi);
11061 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11062 "genPointerSet: illegal pointer type");
11066 /*-----------------------------------------------------------------*/
11067 /* genIfx - generate code for Ifx statement */
11068 /*-----------------------------------------------------------------*/
11070 genIfx (iCode * ic, iCode * popIc)
11072 operand *cond = IC_COND (ic);
11076 D (emitcode (";", "genIfx"));
11078 aopOp (cond, ic, FALSE);
11080 /* get the value into acc */
11081 if (AOP_TYPE (cond) != AOP_CRY)
11088 if (AOP(cond)->aopu.aop_dir)
11089 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
11092 /* the result is now in the accumulator or a directly addressable bit */
11093 freeAsmop (cond, NULL, ic, TRUE);
11095 /* if the condition is a bit variable */
11097 genIfxJump(ic, dup, NULL, NULL, NULL, popIc);
11098 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
11099 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL, popIc);
11100 else if (isbit && !IS_ITEMP (cond))
11101 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL, popIc);
11103 genIfxJump (ic, "a", NULL, NULL, NULL, popIc);
11108 /*-----------------------------------------------------------------*/
11109 /* genAddrOf - generates code for address of */
11110 /*-----------------------------------------------------------------*/
11112 genAddrOf (iCode * ic)
11114 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
11117 D (emitcode (";", "genAddrOf"));
11119 aopOp (IC_RESULT (ic), ic, FALSE);
11121 /* if the operand is on the stack then we
11122 need to get the stack offset of this
11126 /* if it has an offset then we need to compute it */
11129 int stack_offset = ((sym->stack < 0) ?
11130 ((char) (sym->stack - _G.nRegsSaved)) :
11131 ((char) sym->stack)) & 0xff;
11132 if ((abs(stack_offset) == 1) &&
11133 !AOP_NEEDSACC(IC_RESULT (ic)) &&
11134 !isOperandVolatile (IC_RESULT (ic), FALSE))
11136 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
11137 if (stack_offset > 0)
11138 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
11140 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
11144 emitcode ("mov", "a,%s", SYM_BP (sym));
11145 emitcode ("add", "a,#0x%02x", stack_offset & 0xff);
11146 aopPut (IC_RESULT (ic), "a", 0);
11151 /* we can just move _bp */
11152 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
11154 /* fill the result with zero */
11155 size = AOP_SIZE (IC_RESULT (ic)) - 1;
11160 aopPut (IC_RESULT (ic), zero, offset++);
11165 /* object not on stack then we need the name */
11166 size = getDataSize (IC_RESULT (ic));
11171 char s[SDCC_NAME_MAX];
11174 sprintf (s, "#(%s >> %d)",
11180 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11182 aopPut (IC_RESULT (ic), s, offset++);
11184 if (opIsGptr (IC_RESULT (ic)))
11187 SNPRINTF (buffer, sizeof(buffer),
11188 "#0x%02x", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
11189 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
11193 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11197 /*-----------------------------------------------------------------*/
11198 /* genFarFarAssign - assignment when both are in far space */
11199 /*-----------------------------------------------------------------*/
11201 genFarFarAssign (operand * result, operand * right, iCode * ic)
11203 int size = AOP_SIZE (right);
11207 D (emitcode (";", "genFarFarAssign"));
11209 /* first push the right side on to the stack */
11212 l = aopGet (right, offset++, FALSE, FALSE);
11214 emitcode ("push", "acc");
11217 freeAsmop (right, NULL, ic, FALSE);
11218 /* now assign DPTR to result */
11219 aopOp (result, ic, FALSE);
11220 size = AOP_SIZE (result);
11223 emitcode ("pop", "acc");
11224 aopPut (result, "a", --offset);
11226 freeAsmop (result, NULL, ic, FALSE);
11229 /*-----------------------------------------------------------------*/
11230 /* genAssign - generate code for assignment */
11231 /*-----------------------------------------------------------------*/
11233 genAssign (iCode * ic)
11235 operand *result, *right;
11237 unsigned long lit = 0L;
11239 D (emitcode (";", "genAssign"));
11241 result = IC_RESULT (ic);
11242 right = IC_RIGHT (ic);
11244 /* if they are the same */
11245 if (operandsEqu (result, right) &&
11246 !isOperandVolatile (result, FALSE) &&
11247 !isOperandVolatile (right, FALSE))
11250 aopOp (right, ic, FALSE);
11252 /* special case both in far space */
11253 if (AOP_TYPE (right) == AOP_DPTR &&
11254 IS_TRUE_SYMOP (result) &&
11255 isOperandInFarSpace (result))
11257 genFarFarAssign (result, right, ic);
11261 aopOp (result, ic, TRUE);
11263 /* if they are the same registers */
11264 if (sameRegs (AOP (right), AOP (result)) &&
11265 !isOperandVolatile (result, FALSE) &&
11266 !isOperandVolatile (right, FALSE))
11269 /* if the result is a bit */
11270 if (AOP_TYPE (result) == AOP_CRY)
11272 assignBit (result, right);
11276 /* bit variables done */
11278 size = getDataSize (result);
11280 if (AOP_TYPE (right) == AOP_LIT)
11281 lit = ulFromVal (AOP (right)->aopu.aop_lit);
11284 (AOP_TYPE (result) != AOP_REG) &&
11285 (AOP_TYPE (right) == AOP_LIT) &&
11286 !IS_FLOAT (operandType (right)) &&
11289 while ((size) && (lit))
11292 aopGet (right, offset, FALSE, FALSE),
11298 /* And now fill the rest with zeros. */
11301 emitcode ("clr", "a");
11305 aopPut (result, "a", offset);
11314 aopGet (right, offset, FALSE, FALSE),
11319 adjustArithmeticResult (ic);
11322 freeAsmop (result, NULL, ic, TRUE);
11323 freeAsmop (right, NULL, ic, TRUE);
11326 /*-----------------------------------------------------------------*/
11327 /* genJumpTab - generates code for jump table */
11328 /*-----------------------------------------------------------------*/
11330 genJumpTab (iCode * ic)
11332 symbol *jtab,*jtablo,*jtabhi;
11334 unsigned int count;
11336 D (emitcode (";", "genJumpTab"));
11338 count = elementsInSet( IC_JTLABELS (ic) );
11342 /* this algorithm needs 9 cycles and 7 + 3*n bytes
11343 if the switch argument is in a register.
11344 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
11345 /* Peephole may not convert ljmp to sjmp or ret
11346 labelIsReturnOnly & labelInRange must check
11347 currPl->ic->op != JUMPTABLE */
11348 aopOp (IC_JTCOND (ic), ic, FALSE);
11349 /* get the condition into accumulator */
11350 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11352 /* multiply by three */
11353 if (aopGetUsesAcc (IC_JTCOND (ic), 0))
11355 emitcode ("mov", "b,#0x03");
11356 emitcode ("mul", "ab");
11360 emitcode ("add", "a,acc");
11361 emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
11363 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11365 jtab = newiTempLabel (NULL);
11366 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
11367 emitcode ("jmp", "@a+dptr");
11369 /* now generate the jump labels */
11370 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11371 jtab = setNextItem (IC_JTLABELS (ic)))
11372 emitcode ("ljmp", "%05d$", jtab->key + 100);
11376 /* this algorithm needs 14 cycles and 13 + 2*n bytes
11377 if the switch argument is in a register.
11378 For n>6 this algorithm may be more compact */
11379 jtablo = newiTempLabel (NULL);
11380 jtabhi = newiTempLabel (NULL);
11382 /* get the condition into accumulator.
11383 Using b as temporary storage, if register push/pop is needed */
11384 aopOp (IC_JTCOND (ic), ic, FALSE);
11385 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11386 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
11387 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
11389 // (MB) what if B is in use???
11390 wassertl(!BINUSE, "B was in use");
11391 emitcode ("mov", "b,%s", l);
11394 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11398 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
11399 emitcode ("movc", "a,@a+pc");
11400 emitcode ("push", "acc");
11403 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
11404 emitcode ("movc", "a,@a+pc");
11405 emitcode ("push", "acc");
11409 /* this scales up to n<=255, but needs two more bytes
11410 and changes dptr */
11411 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
11412 emitcode ("movc", "a,@a+dptr");
11413 emitcode ("push", "acc");
11416 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
11417 emitcode ("movc", "a,@a+dptr");
11418 emitcode ("push", "acc");
11421 emitcode ("ret", "");
11423 /* now generate jump table, LSB */
11424 emitLabel (jtablo);
11425 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11426 jtab = setNextItem (IC_JTLABELS (ic)))
11427 emitcode (".db", "%05d$", jtab->key + 100);
11429 /* now generate jump table, MSB */
11430 emitLabel (jtabhi);
11431 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11432 jtab = setNextItem (IC_JTLABELS (ic)))
11433 emitcode (".db", "%05d$>>8", jtab->key + 100);
11437 /*-----------------------------------------------------------------*/
11438 /* genCast - gen code for casting */
11439 /*-----------------------------------------------------------------*/
11441 genCast (iCode * ic)
11443 operand *result = IC_RESULT (ic);
11444 sym_link *ctype = operandType (IC_LEFT (ic));
11445 sym_link *rtype = operandType (IC_RIGHT (ic));
11446 operand *right = IC_RIGHT (ic);
11449 D (emitcode (";", "genCast"));
11451 /* if they are equivalent then do nothing */
11452 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11455 aopOp (right, ic, FALSE);
11456 aopOp (result, ic, FALSE);
11458 /* if the result is a bit (and not a bitfield) */
11459 if (IS_BIT (OP_SYMBOL (result)->type))
11461 assignBit (result, right);
11465 /* if they are the same size : or less */
11466 if (AOP_SIZE (result) <= AOP_SIZE (right))
11469 /* if they are in the same place */
11470 if (sameRegs (AOP (right), AOP (result)))
11473 /* if they in different places then copy */
11474 size = AOP_SIZE (result);
11479 aopGet (right, offset, FALSE, FALSE),
11486 /* if the result is of type pointer */
11487 if (IS_PTR (ctype))
11491 sym_link *type = operandType (right);
11492 sym_link *etype = getSpec (type);
11494 /* pointer to generic pointer */
11495 if (IS_GENPTR (ctype))
11499 p_type = DCL_TYPE (type);
11503 if (SPEC_SCLS(etype)==S_REGISTER) {
11504 // let's assume it is a generic pointer
11507 /* we have to go by the storage class */
11508 p_type = PTR_TYPE (SPEC_OCLS (etype));
11512 /* the first two bytes are known */
11513 size = GPTRSIZE - 1;
11518 aopGet (right, offset, FALSE, FALSE),
11522 /* the last byte depending on type */
11524 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11529 // pointerTypeToGPByte will have bitched.
11533 sprintf(gpValStr, "#0x%02x", gpVal);
11534 aopPut (result, gpValStr, GPTRSIZE - 1);
11539 /* just copy the pointers */
11540 size = AOP_SIZE (result);
11545 aopGet (right, offset, FALSE, FALSE),
11552 /* so we now know that the size of destination is greater
11553 than the size of the source */
11554 /* we move to result for the size of source */
11555 size = AOP_SIZE (right);
11560 aopGet (right, offset, FALSE, FALSE),
11565 /* now depending on the sign of the source && destination */
11566 size = AOP_SIZE (result) - AOP_SIZE (right);
11567 /* if unsigned or not an integral type */
11568 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11571 aopPut (result, zero, offset++);
11575 /* we need to extend the sign :{ */
11576 char *l = aopGet (right, AOP_SIZE (right) - 1,
11579 emitcode ("rlc", "a");
11580 emitcode ("subb", "a,acc");
11582 aopPut (result, "a", offset++);
11585 /* we are done hurray !!!! */
11588 freeAsmop (result, NULL, ic, TRUE);
11589 freeAsmop (right, NULL, ic, TRUE);
11592 /*-----------------------------------------------------------------*/
11593 /* genDjnz - generate decrement & jump if not zero instrucion */
11594 /*-----------------------------------------------------------------*/
11596 genDjnz (iCode * ic, iCode * ifx)
11598 symbol *lbl, *lbl1;
11602 /* if the if condition has a false label
11603 then we cannot save */
11604 if (IC_FALSE (ifx))
11607 /* if the minus is not of the form a = a - 1 */
11608 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11609 !IS_OP_LITERAL (IC_RIGHT (ic)))
11612 if (operandLitValue (IC_RIGHT (ic)) != 1)
11615 /* if the size of this greater than one then no
11617 if (getSize (operandType (IC_RESULT (ic))) > 1)
11620 /* otherwise we can save BIG */
11622 D (emitcode (";", "genDjnz"));
11624 lbl = newiTempLabel (NULL);
11625 lbl1 = newiTempLabel (NULL);
11627 aopOp (IC_RESULT (ic), ic, FALSE);
11629 if (AOP_NEEDSACC(IC_RESULT(ic)))
11631 /* If the result is accessed indirectly via
11632 * the accumulator, we must explicitly write
11633 * it back after the decrement.
11635 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11637 if (strcmp(rByte, "a"))
11639 /* Something is hopelessly wrong */
11640 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11641 __FILE__, __LINE__);
11642 /* We can just give up; the generated code will be inefficient,
11643 * but what the hey.
11645 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11648 emitcode ("dec", "%s", rByte);
11649 aopPut (IC_RESULT (ic), rByte, 0);
11650 emitcode ("jnz", "%05d$", lbl->key + 100);
11652 else if (IS_AOP_PREG (IC_RESULT (ic)))
11654 emitcode ("dec", "%s",
11655 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11656 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11657 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11658 ifx->generated = 1;
11659 emitcode ("jnz", "%05d$", lbl->key + 100);
11663 emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11666 emitcode ("sjmp", "%05d$", lbl1->key + 100);
11668 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11671 if (!ifx->generated)
11672 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11673 ifx->generated = 1;
11677 /*-----------------------------------------------------------------*/
11678 /* genReceive - generate code for a receive iCode */
11679 /*-----------------------------------------------------------------*/
11681 genReceive (iCode * ic)
11683 int size = getSize (operandType (IC_RESULT (ic)));
11686 D (emitcode (";", "genReceive"));
11688 if (ic->argreg == 1)
11689 { /* first parameter */
11690 if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11691 isOperandInPagedSpace (IC_RESULT (ic))) &&
11692 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11693 IS_TRUE_SYMOP (IC_RESULT (ic))))
11696 int receivingA = 0;
11699 for (offset = 0; offset<size; offset++)
11700 if (!strcmp (fReturn[offset], "a"))
11705 if (size==1 || getTempRegs(tempRegs, size-1, ic))
11707 for (offset = size-1; offset>0; offset--)
11708 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11709 emitcode("mov","a,%s", fReturn[0]);
11711 aopOp (IC_RESULT (ic), ic, FALSE);
11713 aopPut (IC_RESULT (ic), "a", offset);
11714 for (offset = 1; offset<size; offset++)
11715 aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset);
11721 if (getTempRegs(tempRegs, size, ic))
11723 for (offset = 0; offset<size; offset++)
11724 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11725 aopOp (IC_RESULT (ic), ic, FALSE);
11726 for (offset = 0; offset<size; offset++)
11727 aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset);
11732 offset = fReturnSizeMCS51 - size;
11735 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11736 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11739 aopOp (IC_RESULT (ic), ic, FALSE);
11740 size = AOP_SIZE (IC_RESULT (ic));
11744 emitcode ("pop", "acc");
11745 aopPut (IC_RESULT (ic), "a", offset++);
11751 aopOp (IC_RESULT (ic), ic, FALSE);
11753 assignResultValue (IC_RESULT (ic), NULL);
11756 else if (ic->argreg > 12)
11757 { /* bit parameters */
11758 regs *reg = OP_SYMBOL (IC_RESULT (ic))->regs[0];
11761 if (!reg || reg->rIdx != ic->argreg-5)
11763 aopOp (IC_RESULT (ic), ic, FALSE);
11764 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11765 outBitC(IC_RESULT (ic));
11769 { /* other parameters */
11771 aopOp (IC_RESULT (ic), ic, FALSE);
11772 rb1off = ic->argreg;
11775 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
11780 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11783 /*-----------------------------------------------------------------*/
11784 /* genDummyRead - generate code for dummy read of volatiles */
11785 /*-----------------------------------------------------------------*/
11787 genDummyRead (iCode * ic)
11792 D (emitcode(";", "genDummyRead"));
11794 op = IC_RIGHT (ic);
11795 if (op && IS_SYMOP (op))
11797 aopOp (op, ic, FALSE);
11799 /* if the result is a bit */
11800 if (AOP_TYPE (op) == AOP_CRY)
11801 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11804 /* bit variables done */
11806 size = AOP_SIZE (op);
11810 MOVA (aopGet (op, offset, FALSE, FALSE));
11815 freeAsmop (op, NULL, ic, TRUE);
11819 if (op && IS_SYMOP (op))
11821 aopOp (op, ic, FALSE);
11823 /* if the result is a bit */
11824 if (AOP_TYPE (op) == AOP_CRY)
11825 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11828 /* bit variables done */
11830 size = AOP_SIZE (op);
11834 MOVA (aopGet (op, offset, FALSE, FALSE));
11839 freeAsmop (op, NULL, ic, TRUE);
11843 /*-----------------------------------------------------------------*/
11844 /* genCritical - generate code for start of a critical sequence */
11845 /*-----------------------------------------------------------------*/
11847 genCritical (iCode *ic)
11849 symbol *tlbl = newiTempLabel (NULL);
11851 D (emitcode(";", "genCritical"));
11853 if (IC_RESULT (ic))
11855 aopOp (IC_RESULT (ic), ic, TRUE);
11856 aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
11857 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11858 aopPut (IC_RESULT (ic), zero, 0);
11860 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11864 emitcode ("setb", "c");
11865 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11866 emitcode ("clr", "c");
11868 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11872 /*-----------------------------------------------------------------*/
11873 /* genEndCritical - generate code for end of a critical sequence */
11874 /*-----------------------------------------------------------------*/
11876 genEndCritical (iCode *ic)
11878 D(emitcode(";", "genEndCritical"));
11882 aopOp (IC_RIGHT (ic), ic, FALSE);
11883 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11885 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11886 emitcode ("mov", "ea,c");
11890 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11891 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11892 emitcode ("rrc", "a");
11893 emitcode ("mov", "ea,c");
11895 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11899 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11900 emitcode ("mov", "ea,c");
11904 /*-----------------------------------------------------------------*/
11905 /* gen51Code - generate code for 8051 based controllers */
11906 /*-----------------------------------------------------------------*/
11908 gen51Code (iCode * lic)
11912 /* int cseq = 0; */
11914 _G.currentFunc = NULL;
11915 lineHead = lineCurr = NULL;
11917 /* print the allocation information */
11918 if (allocInfo && currFunc)
11919 printAllocInfo (currFunc, codeOutBuf);
11920 /* if debug information required */
11921 if (options.debug && currFunc)
11923 debugFile->writeFunction (currFunc, lic);
11925 /* stack pointer name */
11926 if (options.useXstack)
11932 for (ic = lic; ic; ic = ic->next)
11934 _G.current_iCode = ic;
11936 if (ic->lineno && cln != ic->lineno)
11940 debugFile->writeCLine (ic);
11942 if (!options.noCcodeInAsm) {
11943 emitcode (";", "%s:%d: %s", ic->filename, ic->lineno,
11944 printCLine(ic->filename, ic->lineno));
11949 if (ic->seqPoint && ic->seqPoint != cseq)
11951 emitcode (";", "sequence point %d", ic->seqPoint);
11952 cseq = ic->seqPoint;
11955 if (options.iCodeInAsm) {
11956 char regsInUse[80];
11961 for (i=0; i<8; i++) {
11962 sprintf (®sInUse[i],
11963 "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11966 strcpy (regsInUse, "--------");
11967 for (i=0; i < 8; i++) {
11968 if (bitVectBitValue (ic->rMask, i))
11970 int offset = regs8051[i].offset;
11971 regsInUse[offset] = offset + '0'; /* show rMask */
11975 iLine = printILine(ic);
11976 emitcode(";", "[%s] ic:%d: %s", regsInUse, ic->seq, iLine);
11979 /* if the result is marked as
11980 spilt and rematerializable or code for
11981 this has already been generated then
11983 if (resultRemat (ic) || ic->generated)
11986 /* depending on the operation */
12007 iCode *ifxIc, *popIc;
12008 bool CommonRegs = FALSE;
12010 /* IPOP happens only when trying to restore a
12011 spilt live range, if there is an ifx statement
12012 following this pop (or several) then the if statement might
12013 be using some of the registers being popped which
12014 would destory the contents of the register so
12015 we need to check for this condition and handle it */
12016 for (ifxIc = ic->next; ifxIc && ifxIc->op == IPOP; ifxIc = ifxIc->next);
12017 for (popIc = ic; popIc && popIc->op == IPOP; popIc = popIc->next)
12018 CommonRegs |= (ifxIc && ifxIc->op == IFX && !ifxIc->generated &&
12019 regsInCommon (IC_LEFT (popIc), IC_COND (ifxIc)));
12021 genIfx (ifxIc, ic);
12040 genEndFunction (ic);
12060 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
12077 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
12081 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
12088 /* note these two are xlated by algebraic equivalence
12089 in decorateType() in SDCCast.c */
12090 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12091 "got '>=' or '<=' shouldn't have come here");
12095 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
12107 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
12111 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
12115 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
12151 genRightShift (ic);
12154 case GET_VALUE_AT_ADDRESS:
12156 hasInc (IC_LEFT (ic), ic,
12157 getSize (operandType (IC_RESULT (ic)))),
12158 ifxForOp (IC_RESULT (ic), ic) );
12162 if (POINTER_SET (ic))
12164 hasInc (IC_RESULT (ic), ic,
12165 getSize (operandType (IC_RIGHT (ic)))));
12191 addSet (&_G.sendSet, ic);
12194 case DUMMY_READ_VOLATILE:
12203 genEndCritical (ic);
12215 _G.current_iCode = NULL;
12217 /* now we are ready to call the
12218 peep hole optimizer */
12219 if (!options.nopeep)
12220 peepHole (&lineHead);
12222 /* now do the actual printing */
12223 printLine (lineHead, codeOutBuf);