1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for 8051
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
27 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
28 Made everything static
29 -------------------------------------------------------------------------*/
31 #define D(x) do if (options.verboseAsm) {x;} while(0)
37 #include "SDCCglobl.h"
41 #include "SDCCpeeph.h"
45 #include "dbuf_string.h"
47 char *aopLiteral (value * val, int offset);
48 char *aopLiteralLong (value * val, int offset, int size);
51 /* this is the down and dirty file with all kinds of
52 kludgy & hacky stuff. This is what it is all about
53 CODE GENERATION for a specific MCU . some of the
54 routines may be reusable, will have to see */
56 static char *zero = "#0x00";
57 static char *one = "#0x01";
61 {"dpl", "dph", "b", "a"};
62 unsigned fReturnSizeMCS51 = 4; /* shared with ralloc.c */
63 char **fReturn = fReturn8051;
64 static char *accUse[] =
67 static unsigned short rbank = -1;
69 #define REG_WITH_INDEX mcs51_regWithIdx
71 #define AOP(op) op->aop
72 #define AOP_TYPE(op) AOP(op)->type
73 #define AOP_SIZE(op) AOP(op)->size
74 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
75 AOP_TYPE(x) == AOP_R0))
77 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
78 AOP_TYPE(x) == AOP_DPTR || \
81 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
82 (x->aopu.aop_reg[0] == REG_WITH_INDEX(R0_IDX) || \
83 x->aopu.aop_reg[0] == REG_WITH_INDEX(R1_IDX) )))
85 #define SYM_BP(sym) (SPEC_OCLS (sym->etype)->paged ? "_bpx" : "_bp")
87 #define R0INB _G.bu.bs.r0InB
88 #define R1INB _G.bu.bs.r1InB
89 #define OPINB _G.bu.bs.OpInB
90 #define BINUSE _G.bu.BInUse
100 short r0InB : 2;//2 so we can see it overflow
101 short r1InB : 2;//2 so we can see it overflow
102 short OpInB : 2;//2 so we can see it overflow
111 iCode *current_iCode;
116 static char *rb1regs[] = {
117 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7",
118 "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7"
121 extern struct dbuf_s *codeOutBuf;
123 #define RESULTONSTACK(x) \
124 (IC_RESULT(x) && IC_RESULT(x)->aop && \
125 IC_RESULT(x)->aop->type == AOP_STK )
127 #define MOVA(x) mova(x) /* use function to avoid multiple eval */
128 #define MOVB(x) movb(x)
130 #define CLRC emitcode("clr","c")
131 #define SETC emitcode("setb","c")
133 static lineNode *lineHead = NULL;
134 static lineNode *lineCurr = NULL;
136 static unsigned char SLMask[] =
137 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
138 0xE0, 0xC0, 0x80, 0x00};
139 static unsigned char SRMask[] =
140 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
141 0x07, 0x03, 0x01, 0x00};
148 /*-----------------------------------------------------------------*/
149 /* emitcode - writes the code into a file : for now it is simple */
150 /*-----------------------------------------------------------------*/
152 emitcode (const char *inst, const char *fmt,...)
156 const char *lbp, *lb;
158 dbuf_init (&dbuf, INITIAL_INLINEASM);
164 dbuf_append_str (&dbuf, inst);
168 dbuf_append_char (&dbuf, '\t');
169 dbuf_tvprintf (&dbuf, fmt, ap);
174 dbuf_tvprintf (&dbuf, fmt, ap);
177 lbp = lb = dbuf_c_str(&dbuf);
179 while (isspace ((unsigned char)*lbp))
188 lineCurr = (lineCurr ?
189 connectLine (lineCurr, newLineNode (lb)) :
190 (lineHead = newLineNode (lb)));
192 lineCurr->isInline = _G.inLine;
193 lineCurr->isDebug = _G.debugLine;
194 lineCurr->ic = _G.current_iCode;
195 lineCurr->isComment = (*lbp==';');
204 emitLabel (symbol *tlbl)
206 emitcode ("", "%05d$:", tlbl->key + 100);
207 lineCurr->isLabel = 1;
210 /*-----------------------------------------------------------------*/
211 /* mcs51_emitDebuggerSymbol - associate the current code location */
212 /* with a debugger symbol */
213 /*-----------------------------------------------------------------*/
215 mcs51_emitDebuggerSymbol (char * debugSym)
218 emitcode ("", "%s ==.", debugSym);
222 /*-----------------------------------------------------------------*/
223 /* mova - moves specified value into accumulator */
224 /*-----------------------------------------------------------------*/
228 /* do some early peephole optimization */
229 if (!strncmp(x, "a", 2) || !strncmp(x, "acc", 4))
232 /* if it is a literal mov try to get it cheaper */
237 emitcode("mov", "a,%s", x);
240 /*-----------------------------------------------------------------*/
241 /* movb - moves specified value into register b */
242 /*-----------------------------------------------------------------*/
246 /* do some early peephole optimization */
247 if (!strncmp(x, "b", 2))
250 /* if it is a literal mov try to get it cheaper */
253 emitcode("mov","b,%s", rtrackGetLit(x));
257 emitcode("mov","b,%s", x);
260 /*-----------------------------------------------------------------*/
261 /* pushB - saves register B if necessary */
262 /*-----------------------------------------------------------------*/
266 bool pushedB = FALSE;
270 emitcode ("push", "b");
271 // printf("B was in use !\n");
281 /*-----------------------------------------------------------------*/
282 /* popB - restores value of register B if necessary */
283 /*-----------------------------------------------------------------*/
289 emitcode ("pop", "b");
297 /*-----------------------------------------------------------------*/
298 /* pushReg - saves register */
299 /*-----------------------------------------------------------------*/
301 pushReg (int index, bool bits_pushed)
303 regs * reg = REG_WITH_INDEX (index);
304 if (reg->type == REG_BIT)
307 emitcode ("push", "%s", reg->base);
311 emitcode ("push", "%s", reg->dname);
315 /*-----------------------------------------------------------------*/
316 /* popReg - restores register */
317 /*-----------------------------------------------------------------*/
319 popReg (int index, bool bits_popped)
321 regs * reg = REG_WITH_INDEX (index);
322 if (reg->type == REG_BIT)
325 emitcode ("pop", "%s", reg->base);
329 emitcode ("pop", "%s", reg->dname);
333 /*-----------------------------------------------------------------*/
334 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
335 /*-----------------------------------------------------------------*/
337 getFreePtr (iCode * ic, asmop ** aopp, bool result)
342 /* the logic: if r0 & r1 used in the instruction
343 then we are in trouble otherwise */
345 /* first check if r0 & r1 are used by this
346 instruction, in which case we are in trouble */
347 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
348 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
353 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
354 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
356 /* if no usage of r0 then return it */
359 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
360 (*aopp)->type = AOP_R0;
362 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
365 /* if no usage of r1 then return it */
368 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
369 (*aopp)->type = AOP_R1;
371 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R1_IDX);
374 /* now we know they both have usage */
375 /* if r0 not used in this instruction */
378 /* push it if not already pushed */
381 MOVB (REG_WITH_INDEX (R0_IDX)->dname);
384 else if (!_G.r0Pushed)
386 emitcode ("push", "%s",
387 REG_WITH_INDEX (R0_IDX)->dname);
391 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
392 (*aopp)->type = AOP_R0;
394 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
397 /* if r1 not used then */
401 /* push it if not already pushed */
404 MOVB (REG_WITH_INDEX (R1_IDX)->dname);
407 else if (!_G.r1Pushed)
409 emitcode ("push", "%s",
410 REG_WITH_INDEX (R1_IDX)->dname);
414 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
415 (*aopp)->type = AOP_R1;
416 return REG_WITH_INDEX (R1_IDX);
420 /* I said end of world, but not quite end of world yet */
421 /* if this is a result then we can push it on the stack */
424 (*aopp)->type = AOP_STK;
427 /* in the case that result AND left AND right needs a pointer reg
428 we can safely use the result's */
429 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX))
431 (*aopp)->type = AOP_R0;
432 return REG_WITH_INDEX (R0_IDX);
434 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX))
436 (*aopp)->type = AOP_R1;
437 return REG_WITH_INDEX (R1_IDX);
440 /* now this is REALLY the end of the world */
441 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
442 "getFreePtr should never reach here");
447 /*-----------------------------------------------------------------*/
448 /* getTempRegs - initialize an array of pointers to GPR registers */
449 /* that are not in use. Returns 1 if the requested */
450 /* number of registers were available, 0 otherwise. */
451 /*-----------------------------------------------------------------*/
453 getTempRegs(regs **tempRegs, int size, iCode *ic)
460 ic = _G.current_iCode;
466 freeRegs = newBitVect(8);
467 bitVectSetBit (freeRegs, R2_IDX);
468 bitVectSetBit (freeRegs, R3_IDX);
469 bitVectSetBit (freeRegs, R4_IDX);
470 bitVectSetBit (freeRegs, R5_IDX);
471 bitVectSetBit (freeRegs, R6_IDX);
472 bitVectSetBit (freeRegs, R7_IDX);
474 if (IFFUNC_CALLEESAVES(_G.currentFunc->type))
476 bitVect * newfreeRegs;
477 newfreeRegs = bitVectIntersect (freeRegs, _G.currentFunc->regsUsed);
478 freeBitVect(freeRegs);
479 freeRegs = newfreeRegs;
481 freeRegs = bitVectCplAnd (freeRegs, ic->rMask);
484 for (i=0; i<freeRegs->size; i++)
486 if (bitVectBitValue(freeRegs,i))
487 tempRegs[offset++] = REG_WITH_INDEX(i);
490 freeBitVect(freeRegs);
495 freeBitVect(freeRegs);
500 /*-----------------------------------------------------------------*/
501 /* newAsmop - creates a new asmOp */
502 /*-----------------------------------------------------------------*/
504 newAsmop (short type)
508 aop = Safe_calloc (1, sizeof (asmop));
514 /*-----------------------------------------------------------------*/
515 /* pointerCode - returns the code for a pointer type */
516 /*-----------------------------------------------------------------*/
518 pointerCode (sym_link * etype)
521 return PTR_TYPE (SPEC_OCLS (etype));
525 /*-----------------------------------------------------------------*/
526 /* leftRightUseAcc - returns size of accumulator use by operands */
527 /*-----------------------------------------------------------------*/
529 leftRightUseAcc(iCode *ic)
538 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
539 "null iCode pointer");
546 if (IS_OP_ACCUSE (op))
549 size = getSize (OP_SYMBOL (op)->type);
554 else if (ic->op == JUMPTABLE)
557 if (IS_OP_ACCUSE (op))
560 size = getSize (OP_SYMBOL (op)->type);
568 if (IS_OP_ACCUSE (op))
571 size = getSize (OP_SYMBOL (op)->type);
576 if (IS_OP_ACCUSE (op))
579 size = getSize (OP_SYMBOL (op)->type);
591 /*-----------------------------------------------------------------*/
592 /* aopForSym - for a true symbol */
593 /*-----------------------------------------------------------------*/
595 aopForSym (iCode * ic, symbol * sym, bool result)
599 bool accuse = leftRightUseAcc (ic) || _G.accInUse;
601 wassertl (ic != NULL, "Got a null iCode");
602 wassertl (sym != NULL, "Got a null symbol");
604 space = SPEC_OCLS (sym->etype);
606 /* if already has one */
609 sym->aop->allocated++;
613 /* assign depending on the storage class */
614 /* if it is on the stack or indirectly addressable */
615 /* space we need to assign either r0 or r1 to it */
616 if (sym->onStack || sym->iaccess)
618 sym->aop = aop = newAsmop (0);
619 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
620 aop->size = getSize (sym->type);
622 /* now assign the address of the variable to
623 the pointer register */
624 if (aop->type != AOP_STK)
628 signed char offset = ((sym->stack < 0) ?
629 ((signed char) (sym->stack - _G.nRegsSaved)) :
630 ((signed char) sym->stack)) & 0xff;
632 if ((abs(offset) <= 3) ||
633 (accuse && (abs(offset) <= 7)))
635 emitcode ("mov", "%s,%s",
636 aop->aopu.aop_ptr->name, SYM_BP (sym));
639 emitcode ("dec", aop->aopu.aop_ptr->name);
644 emitcode ("inc", aop->aopu.aop_ptr->name);
651 emitcode ("push", "acc");
652 emitcode ("mov", "a,%s", SYM_BP (sym));
653 emitcode ("add", "a,#0x%02x", offset & 0xff);
654 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
656 emitcode ("pop", "acc");
661 emitcode ("mov", "%s,#%s",
662 aop->aopu.aop_ptr->name,
665 aop->paged = space->paged;
668 aop->aopu.aop_stk = sym->stack;
672 /* if in bit space */
673 if (IN_BITSPACE (space))
675 sym->aop = aop = newAsmop (AOP_CRY);
676 aop->aopu.aop_dir = sym->rname;
677 aop->size = getSize (sym->type);
680 /* if it is in direct space */
681 if (IN_DIRSPACE (space))
683 //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
684 //printTypeChainRaw(sym->type, NULL);
685 //printf("space = %s\n", space ? space->sname : "NULL");
686 sym->aop = aop = newAsmop (AOP_DIR);
687 aop->aopu.aop_dir = sym->rname;
688 aop->size = getSize (sym->type);
692 /* special case for a function */
693 if (IS_FUNC (sym->type))
695 sym->aop = aop = newAsmop (AOP_IMMD);
696 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
697 aop->size = getSize (sym->type);
701 /* only remaining is far space */
702 /* in which case DPTR gets the address */
703 sym->aop = aop = newAsmop (AOP_DPTR);
704 emitcode ("mov", "dptr,#%s", sym->rname);
705 aop->size = getSize (sym->type);
707 /* if it is in code space */
708 if (IN_CODESPACE (space))
714 /*-----------------------------------------------------------------*/
715 /* aopForRemat - rematerializes an object */
716 /*-----------------------------------------------------------------*/
718 aopForRemat (symbol * sym)
720 iCode *ic = sym->rematiCode;
721 asmop *aop = newAsmop (AOP_IMMD);
728 val += (int) operandLitValue (IC_RIGHT (ic));
729 else if (ic->op == '-')
730 val -= (int) operandLitValue (IC_RIGHT (ic));
731 else if (IS_CAST_ICODE(ic))
733 sym_link *from_type = operandType(IC_RIGHT(ic));
734 aop->aopu.aop_immd.from_cast_remat = 1;
735 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
736 ptr_type = pointerTypeToGPByte (DCL_TYPE(from_type), NULL, NULL);
741 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
746 SNPRINTF (buffer, sizeof(buffer),
748 OP_SYMBOL (IC_LEFT (ic))->rname,
749 val >= 0 ? '+' : '-',
754 strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
757 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
758 /* set immd2 field if required */
759 if (aop->aopu.aop_immd.from_cast_remat)
761 SNPRINTF (buffer, sizeof(buffer), "#0x%02x", ptr_type);
762 aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
768 /*-----------------------------------------------------------------*/
769 /* regsInCommon - two operands have some registers in common */
770 /*-----------------------------------------------------------------*/
772 regsInCommon (operand * op1, operand * op2)
777 /* if they have registers in common */
778 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
781 sym1 = OP_SYMBOL (op1);
782 sym2 = OP_SYMBOL (op2);
784 if (sym1->nRegs == 0 || sym2->nRegs == 0)
787 for (i = 0; i < sym1->nRegs; i++)
793 for (j = 0; j < sym2->nRegs; j++)
798 if (sym2->regs[j] == sym1->regs[i])
806 /*-----------------------------------------------------------------*/
807 /* operandsEqu - equivalent */
808 /*-----------------------------------------------------------------*/
810 operandsEqu (operand * op1, operand * op2)
814 /* if they're not symbols */
815 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
818 sym1 = OP_SYMBOL (op1);
819 sym2 = OP_SYMBOL (op2);
821 /* if both are itemps & one is spilt
822 and the other is not then false */
823 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
824 sym1->isspilt != sym2->isspilt)
827 /* if they are the same */
831 /* if they have the same rname */
832 if (sym1->rname[0] && sym2->rname[0] &&
833 strcmp (sym1->rname, sym2->rname) == 0 &&
834 !(IS_PARM (op2) && IS_ITEMP (op1)))
837 /* if left is a tmp & right is not */
838 if (IS_ITEMP (op1) &&
841 (sym1->usl.spillLoc == sym2))
844 if (IS_ITEMP (op2) &&
848 (sym2->usl.spillLoc == sym1))
854 /*-----------------------------------------------------------------*/
855 /* sameByte - two asmops have the same address at given offsets */
856 /*-----------------------------------------------------------------*/
858 sameByte (asmop * aop1, int off1, asmop * aop2, int off2)
860 if (aop1 == aop2 && off1 == off2)
863 if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
866 if (aop1->type != aop2->type)
869 if (aop1->aopu.aop_reg[off1] != aop2->aopu.aop_reg[off2])
875 /*-----------------------------------------------------------------*/
876 /* sameRegs - two asmops have the same registers */
877 /*-----------------------------------------------------------------*/
879 sameRegs (asmop * aop1, asmop * aop2)
886 if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
889 if (aop1->type != aop2->type)
892 if (aop1->size != aop2->size)
895 for (i = 0; i < aop1->size; i++)
896 if (aop1->aopu.aop_reg[i] != aop2->aopu.aop_reg[i])
902 /*-----------------------------------------------------------------*/
903 /* aopOp - allocates an asmop for an operand : */
904 /*-----------------------------------------------------------------*/
906 aopOp (operand * op, iCode * ic, bool result)
915 /* if this a literal */
916 if (IS_OP_LITERAL (op))
918 op->aop = aop = newAsmop (AOP_LIT);
919 aop->aopu.aop_lit = op->operand.valOperand;
920 aop->size = getSize (operandType (op));
924 /* if already has a asmop then continue */
927 op->aop->allocated++;
931 /* if the underlying symbol has a aop */
932 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
934 op->aop = OP_SYMBOL (op)->aop;
935 op->aop->allocated++;
939 /* if this is a true symbol */
940 if (IS_TRUE_SYMOP (op))
942 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
946 /* this is a temporary : this has
952 e) can be a return use only */
954 sym = OP_SYMBOL (op);
956 /* if the type is a conditional */
957 if (sym->regType == REG_CND)
959 sym->aop = op->aop = aop = newAsmop (AOP_CRY);
960 aop->size = sym->ruonly ? 1 : 0;
964 /* if it is spilt then two situations
966 b) has a spill location */
967 if (sym->isspilt || sym->nRegs == 0)
970 /* rematerialize it NOW */
973 sym->aop = op->aop = aop = aopForRemat (sym);
974 aop->size = operandSize (op);
981 sym->aop = op->aop = aop = newAsmop (AOP_ACC);
982 aop->size = getSize (sym->type);
983 for (i = 0; i < 2; i++)
984 aop->aopu.aop_str[i] = accUse[i];
992 sym->aop = op->aop = aop = newAsmop (AOP_STR);
993 aop->size = getSize (sym->type);
994 for (i = 0; i < fReturnSizeMCS51; i++)
995 aop->aopu.aop_str[i] = fReturn[i];
999 if (sym->usl.spillLoc)
1001 asmop *oldAsmOp = NULL;
1003 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1005 /* force a new aop if sizes differ */
1006 oldAsmOp = sym->usl.spillLoc->aop;
1007 sym->usl.spillLoc->aop = NULL;
1009 sym->aop = op->aop = aop = aopForSym (ic, sym->usl.spillLoc, result);
1010 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1012 /* Don't reuse the new aop, go with the last one */
1013 sym->usl.spillLoc->aop = oldAsmOp;
1015 aop->size = getSize (sym->type);
1019 /* else must be a dummy iTemp */
1020 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1021 aop->size = getSize (sym->type);
1025 /* if the type is a bit register */
1026 if (sym->regType == REG_BIT)
1028 sym->aop = op->aop = aop = newAsmop (AOP_CRY);
1029 aop->size = sym->nRegs;//1???
1030 aop->aopu.aop_reg[0] = sym->regs[0];
1031 aop->aopu.aop_dir = sym->regs[0]->name;
1035 /* must be in a register */
1036 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1037 aop->size = sym->nRegs;
1038 for (i = 0; i < sym->nRegs; i++)
1039 aop->aopu.aop_reg[i] = sym->regs[i];
1042 /*-----------------------------------------------------------------*/
1043 /* freeAsmop - free up the asmop given to an operand */
1044 /*-----------------------------------------------------------------*/
1046 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1063 /* depending on the asmop type only three cases need work
1064 AOP_R0, AOP_R1 & AOP_STK */
1070 emitcode ("mov", "r0,b");
1073 else if (_G.r0Pushed)
1077 emitcode ("pop", "ar0");
1081 bitVectUnSetBit (ic->rUsed, R0_IDX);
1087 emitcode ("mov", "r1,b");
1090 else if (_G.r1Pushed)
1094 emitcode ("pop", "ar1");
1098 bitVectUnSetBit (ic->rUsed, R1_IDX);
1104 int stk = aop->aopu.aop_stk + aop->size - 1;
1105 bitVectUnSetBit (ic->rUsed, R0_IDX);
1106 bitVectUnSetBit (ic->rUsed, R1_IDX);
1108 getFreePtr (ic, &aop, FALSE);
1112 emitcode ("mov", "a,_bp");
1113 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1114 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1118 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1123 emitcode ("pop", "acc");
1124 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1127 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1130 freeAsmop (op, NULL, ic, TRUE);
1133 emitcode ("pop", "ar1");
1138 emitcode ("pop", "ar0");
1146 /* all other cases just dealloc */
1152 OP_SYMBOL (op)->aop = NULL;
1153 /* if the symbol has a spill */
1155 SPIL_LOC (op)->aop = NULL;
1160 /*------------------------------------------------------------------*/
1161 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
1162 /* pop r0 or r1 off stack if pushed */
1163 /*------------------------------------------------------------------*/
1165 freeForBranchAsmop (operand * op)
1177 if (!aop->allocated)
1185 emitcode ("mov", "r0,b");
1187 else if (_G.r0Pushed)
1189 emitcode ("pop", "ar0");
1196 emitcode ("mov", "r1,b");
1198 else if (_G.r1Pushed)
1200 emitcode ("pop", "ar1");
1207 int stk = aop->aopu.aop_stk + aop->size - 1;
1209 emitcode ("mov", "b,r0");
1212 emitcode ("mov", "a,_bp");
1213 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1214 emitcode ("mov", "r0,a");
1218 emitcode ("mov", "r0,_bp");
1223 emitcode ("pop", "acc");
1224 emitcode ("mov", "@r0,a");
1227 emitcode ("dec", "r0");
1229 emitcode ("mov", "r0,b");
1235 /*-----------------------------------------------------------------*/
1236 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
1237 /* clobber the accumulator */
1238 /*-----------------------------------------------------------------*/
1240 aopGetUsesAcc (operand * oper, int offset)
1242 asmop * aop = AOP (oper);
1244 if (offset > (aop->size - 1))
1262 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1273 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1279 /* Error case --- will have been caught already */
1285 /*-------------------------------------------------------------------*/
1286 /* aopGet - for fetching value of the aop */
1287 /*-------------------------------------------------------------------*/
1289 aopGet (operand * oper, int offset, bool bit16, bool dname)
1291 asmop * aop = AOP (oper);
1293 /* offset is greater than
1295 if (offset > (aop->size - 1) &&
1296 aop->type != AOP_LIT)
1299 /* depending on type */
1307 /* if we need to increment it */
1308 while (offset > aop->coff)
1310 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1314 while (offset < aop->coff)
1316 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1323 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1324 return (dname ? "acc" : "a");
1326 SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1327 return Safe_strdup(buffer);
1330 if (aop->code && aop->coff==0 && offset>=1) {
1331 emitcode ("mov", "a,#0x%02x", offset);
1332 emitcode ("movc", "a,@a+dptr");
1333 return (dname ? "acc" : "a");
1336 while (offset > aop->coff)
1338 emitcode ("inc", "dptr");
1342 while (offset < aop->coff)
1344 emitcode ("lcall", "__decdptr");
1351 emitcode ("clr", "a");
1352 emitcode ("movc", "a,@a+dptr");
1356 emitcode ("movx", "a,@dptr");
1358 return (dname ? "acc" : "a");
1361 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1363 SNPRINTF(buffer, sizeof(buffer),
1364 "%s",aop->aopu.aop_immd.aop_immd2);
1368 SNPRINTF(buffer, sizeof(buffer),
1369 "#%s", aop->aopu.aop_immd.aop_immd1);
1373 SNPRINTF (buffer, sizeof(buffer),
1375 aop->aopu.aop_immd.aop_immd1,
1380 SNPRINTF (buffer, sizeof(buffer),
1382 aop->aopu.aop_immd.aop_immd1);
1384 return Safe_strdup(buffer);
1387 if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
1389 SNPRINTF (buffer, sizeof(buffer),
1391 aop->aopu.aop_dir, offset * 8);
1395 SNPRINTF (buffer, sizeof(buffer),
1402 SNPRINTF (buffer, sizeof(buffer),
1407 return Safe_strdup(buffer);
1411 return aop->aopu.aop_reg[offset]->dname;
1413 return aop->aopu.aop_reg[offset]->name;
1416 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1417 emitcode ("clr", "a");
1418 emitcode ("rlc", "a");
1419 return (dname ? "acc" : "a");
1422 if (!offset && dname)
1424 return aop->aopu.aop_str[offset];
1427 return aopLiteral (aop->aopu.aop_lit, offset);
1431 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1435 return aop->aopu.aop_str[offset];
1439 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1440 "aopget got unsupported aop->type");
1444 /*-----------------------------------------------------------------*/
1445 /* aopPutUsesAcc - indicates ahead of time whether aopPut() will */
1446 /* clobber the accumulator */
1447 /*-----------------------------------------------------------------*/
1449 aopPutUsesAcc (operand * oper, const char *s, int offset)
1451 asmop * aop = AOP (oper);
1453 if (offset > (aop->size - 1))
1463 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1469 return ((aop->paged) || (*s == '@'));
1473 return (!aop->aopu.aop_dir || strcmp(s, aop->aopu.aop_dir));
1481 /* Error case --- will have been caught already */
1487 /*-----------------------------------------------------------------*/
1488 /* aopPut - puts a string for a aop and indicates if acc is in use */
1489 /*-----------------------------------------------------------------*/
1491 aopPut (operand * result, const char *s, int offset)
1493 bool bvolatile = isOperandVolatile (result, FALSE);
1494 bool accuse = FALSE;
1495 asmop * aop = AOP (result);
1496 const char *d = NULL;
1498 if (aop->size && offset > (aop->size - 1))
1500 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1501 "aopPut got offset > aop->size");
1505 /* will assign value to value */
1506 /* depending on where it is ofcourse */
1510 MOVA (s); /* read s in case it was volatile */
1515 if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1517 SNPRINTF (buffer, sizeof(buffer),
1519 aop->aopu.aop_dir, offset * 8);
1523 SNPRINTF (buffer, sizeof(buffer),
1525 aop->aopu.aop_dir, offset);
1529 SNPRINTF (buffer, sizeof(buffer),
1534 if (strcmp (buffer, s) || bvolatile)
1536 emitcode ("mov", "%s,%s", buffer, s);
1538 if (!strcmp (buffer, "acc"))
1545 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1546 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1549 strcmp (s, "r0") == 0 ||
1550 strcmp (s, "r1") == 0 ||
1551 strcmp (s, "r2") == 0 ||
1552 strcmp (s, "r3") == 0 ||
1553 strcmp (s, "r4") == 0 ||
1554 strcmp (s, "r5") == 0 ||
1555 strcmp (s, "r6") == 0 ||
1556 strcmp (s, "r7") == 0)
1558 emitcode ("mov", "%s,%s",
1559 aop->aopu.aop_reg[offset]->dname, s);
1563 emitcode ("mov", "%s,%s",
1564 aop->aopu.aop_reg[offset]->name, s);
1572 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1573 "aopPut writing to code space");
1577 while (offset > aop->coff)
1580 emitcode ("inc", "dptr");
1583 while (offset < aop->coff)
1586 emitcode ("lcall", "__decdptr");
1591 /* if not in accumulator */
1594 emitcode ("movx", "@dptr,a");
1599 while (offset > aop->coff)
1602 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1604 while (offset < aop->coff)
1607 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1614 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1619 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1621 else if (strcmp (s, "r0") == 0 ||
1622 strcmp (s, "r1") == 0 ||
1623 strcmp (s, "r2") == 0 ||
1624 strcmp (s, "r3") == 0 ||
1625 strcmp (s, "r4") == 0 ||
1626 strcmp (s, "r5") == 0 ||
1627 strcmp (s, "r6") == 0 ||
1628 strcmp (s, "r7") == 0)
1631 SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1632 emitcode ("mov", "@%s,%s",
1633 aop->aopu.aop_ptr->name, buffer);
1637 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1642 if (strcmp (s, "a") == 0)
1644 emitcode ("push", "acc");
1649 emitcode ("push", "acc");
1651 else if (strcmp (s, "r0") == 0 ||
1652 strcmp (s, "r1") == 0 ||
1653 strcmp (s, "r2") == 0 ||
1654 strcmp (s, "r3") == 0 ||
1655 strcmp (s, "r4") == 0 ||
1656 strcmp (s, "r5") == 0 ||
1657 strcmp (s, "r6") == 0 ||
1658 strcmp (s, "r7") == 0)
1661 SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1662 emitcode ("push", buffer);
1666 emitcode ("push", s);
1672 // destination is carry for return-use-only
1673 d = (IS_OP_RUONLY (result)) ? "c" : aop->aopu.aop_dir;
1675 // source is no literal and not in carry
1676 if ((s != zero) && (s != one) && strcmp (s, "c"))
1679 /* set C, if a >= 1 */
1680 emitcode ("add", "a,#0xff");
1683 // now source is zero, one or carry
1685 /* if result no bit variable */
1688 if (!strcmp (s, "c"))
1690 /* inefficient: move carry into A and use jz/jnz */
1691 emitcode ("clr", "a");
1692 emitcode ("rlc", "a");
1702 emitcode ("clr", "%s", d);
1704 emitcode ("setb", "%s", d);
1705 else if (strcmp (s, d))
1706 emitcode ("mov", "%s,c", d);
1711 if (strcmp (aop->aopu.aop_str[offset], s) || bvolatile)
1712 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1718 if (!offset && (strcmp (s, "acc") == 0) && !bvolatile)
1721 if (strcmp (aop->aopu.aop_str[offset], s) && !bvolatile)
1722 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1726 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1727 "aopPut got unsupported aop->type");
1736 /*-----------------------------------------------------------------*/
1737 /* pointToEnd :- points to the last byte of the operand */
1738 /*-----------------------------------------------------------------*/
1740 pointToEnd (asmop * aop)
1746 aop->coff = count = (aop->size - 1);
1752 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1756 emitcode ("inc", "dptr");
1763 /*-----------------------------------------------------------------*/
1764 /* reAdjustPreg - points a register back to where it should */
1765 /*-----------------------------------------------------------------*/
1767 reAdjustPreg (asmop * aop)
1769 if ((aop->coff==0) || (aop->size <= 1))
1777 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1782 emitcode ("lcall", "__decdptr");
1789 /*-----------------------------------------------------------------*/
1790 /* opIsGptr: returns non-zero if the passed operand is */
1791 /* a generic pointer type. */
1792 /*-----------------------------------------------------------------*/
1794 opIsGptr (operand * op)
1796 if (op && IS_GENPTR (operandType (op)) && (AOP_SIZE (op) == GPTRSIZE))
1803 /*-----------------------------------------------------------------*/
1804 /* getDataSize - get the operand data size */
1805 /*-----------------------------------------------------------------*/
1807 getDataSize (operand * op)
1809 int size = AOP_SIZE (op);
1811 if (size == GPTRSIZE)
1813 sym_link *type = operandType (op);
1814 if (IS_GENPTR (type))
1816 /* generic pointer; arithmetic operations
1817 * should ignore the high byte (pointer type).
1825 /*-----------------------------------------------------------------*/
1826 /* outAcc - output Acc */
1827 /*-----------------------------------------------------------------*/
1829 outAcc (operand * result)
1832 size = getDataSize (result);
1835 aopPut (result, "a", 0);
1838 /* unsigned or positive */
1841 aopPut (result, zero, offset++);
1846 /*-----------------------------------------------------------------*/
1847 /* outBitC - output a bit C */
1848 /*-----------------------------------------------------------------*/
1850 outBitC (operand * result)
1852 /* if the result is bit */
1853 if (AOP_TYPE (result) == AOP_CRY)
1855 if (!IS_OP_RUONLY (result))
1856 aopPut (result, "c", 0);
1858 else if (AOP_TYPE (result) != AOP_DUMMY)
1860 emitcode ("clr", "a");
1861 emitcode ("rlc", "a");
1866 /*-----------------------------------------------------------------*/
1867 /* toBoolean - emit code for orl a,operator(sizeop) */
1868 /*-----------------------------------------------------------------*/
1870 toBoolean (operand * oper)
1872 int size = AOP_SIZE (oper) - 1;
1874 bool AccUsed = FALSE;
1877 while (!AccUsed && size--)
1879 AccUsed |= aopGetUsesAcc(oper, offset++);
1882 size = AOP_SIZE (oper) - 1;
1884 MOVA (aopGet (oper, 0, FALSE, FALSE));
1885 if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1888 emitcode("mov", "b,a");
1891 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1892 emitcode ("orl", "b,a");
1894 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1895 emitcode ("orl", "a,b");
1902 emitcode ("orl", "a,%s",
1903 aopGet (oper, offset++, FALSE, FALSE));
1908 /*-----------------------------------------------------------------*/
1909 /* toCarry - make boolean and move into carry */
1910 /*-----------------------------------------------------------------*/
1912 toCarry (operand * oper)
1914 /* if the operand is a literal then
1915 we know what the value is */
1916 if (AOP_TYPE (oper) == AOP_LIT)
1918 if ((int) operandLitValue (oper))
1923 else if (AOP_TYPE (oper) == AOP_CRY)
1925 emitcode ("mov", "c,%s", oper->aop->aopu.aop_dir);
1929 /* or the operand into a */
1931 /* set C, if a >= 1 */
1932 emitcode ("add", "a,#0xff");
1936 /*-----------------------------------------------------------------*/
1937 /* assignBit - assign operand to bit operand */
1938 /*-----------------------------------------------------------------*/
1940 assignBit (operand * result, operand * right)
1942 /* if the right side is a literal then
1943 we know what the value is */
1944 if (AOP_TYPE (right) == AOP_LIT)
1946 if ((int) operandLitValue (right))
1947 aopPut (result, one, 0);
1949 aopPut (result, zero, 0);
1954 aopPut (result, "c", 0);
1959 /*-------------------------------------------------------------------*/
1960 /* xch_a_aopGet - for exchanging acc with value of the aop */
1961 /*-------------------------------------------------------------------*/
1963 xch_a_aopGet (operand * oper, int offset, bool bit16, bool dname)
1967 if (aopGetUsesAcc (oper, offset))
1969 emitcode("mov", "b,a");
1970 MOVA (aopGet (oper, offset, bit16, dname));
1971 emitcode("xch", "a,b");
1972 aopPut (oper, "a", offset);
1973 emitcode("xch", "a,b");
1978 l = aopGet (oper, offset, bit16, dname);
1979 emitcode("xch", "a,%s", l);
1985 /*-----------------------------------------------------------------*/
1986 /* genNot - generate code for ! operation */
1987 /*-----------------------------------------------------------------*/
1993 D (emitcode (";", "genNot"));
1995 /* assign asmOps to operand & result */
1996 aopOp (IC_LEFT (ic), ic, FALSE);
1997 aopOp (IC_RESULT (ic), ic, TRUE);
1999 /* if in bit space then a special case */
2000 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2002 /* if left==result then cpl bit */
2003 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2005 emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2009 toCarry (IC_LEFT (ic));
2010 emitcode ("cpl", "c");
2011 outBitC (IC_RESULT (ic));
2016 toBoolean (IC_LEFT (ic));
2018 /* set C, if a == 0 */
2019 tlbl = newiTempLabel (NULL);
2020 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
2022 outBitC (IC_RESULT (ic));
2025 /* release the aops */
2026 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2027 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2031 /*-----------------------------------------------------------------*/
2032 /* genCpl - generate code for complement */
2033 /*-----------------------------------------------------------------*/
2040 sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
2042 D(emitcode (";", "genCpl"));
2044 /* assign asmOps to operand & result */
2045 aopOp (IC_LEFT (ic), ic, FALSE);
2046 aopOp (IC_RESULT (ic), ic, TRUE);
2048 /* special case if in bit space */
2049 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2053 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
2054 (SPEC_USIGN (letype) && IS_CHAR (letype)))
2056 /* promotion rules are responsible for this strange result:
2057 bit -> int -> ~int -> bit
2058 uchar -> int -> ~int -> bit
2060 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
2064 tlbl=newiTempLabel(NULL);
2065 l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
2066 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
2067 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
2068 IS_AOP_PREG (IC_LEFT (ic)))
2070 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
2075 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
2078 outBitC (IC_RESULT(ic));
2082 size = AOP_SIZE (IC_RESULT (ic));
2085 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2087 emitcode ("cpl", "a");
2088 aopPut (IC_RESULT (ic), "a", offset++);
2093 /* release the aops */
2094 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2095 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2098 /*-----------------------------------------------------------------*/
2099 /* genUminusFloat - unary minus for floating points */
2100 /*-----------------------------------------------------------------*/
2102 genUminusFloat (operand * op, operand * result)
2104 int size, offset = 0;
2107 D (emitcode (";", "genUminusFloat"));
2109 /* for this we just copy and then flip the bit */
2111 size = AOP_SIZE (op) - 1;
2116 aopGet (op, offset, FALSE, FALSE),
2121 l = aopGet (op, offset, FALSE, FALSE);
2124 emitcode ("cpl", "acc.7");
2125 aopPut (result, "a", offset);
2128 /*-----------------------------------------------------------------*/
2129 /* genUminus - unary minus code generation */
2130 /*-----------------------------------------------------------------*/
2132 genUminus (iCode * ic)
2137 D (emitcode (";", "genUminus"));
2140 aopOp (IC_LEFT (ic), ic, FALSE);
2141 aopOp (IC_RESULT (ic), ic, TRUE);
2143 /* if both in bit space then special
2145 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2146 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2149 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2150 emitcode ("cpl", "c");
2151 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2155 optype = operandType (IC_LEFT (ic));
2157 /* if float then do float stuff */
2158 if (IS_FLOAT (optype))
2160 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2164 /* otherwise subtract from zero */
2165 size = AOP_SIZE (IC_LEFT (ic));
2169 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2170 if (!strcmp (l, "a"))
2174 emitcode ("cpl", "a");
2175 emitcode ("addc", "a,#0x00");
2181 emitcode ("clr", "a");
2182 emitcode ("subb", "a,%s", l);
2184 aopPut (IC_RESULT (ic), "a", offset++);
2187 /* if any remaining bytes in the result */
2188 /* we just need to propagate the sign */
2189 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2191 emitcode ("rlc", "a");
2192 emitcode ("subb", "a,acc");
2194 aopPut (IC_RESULT (ic), "a", offset++);
2198 /* release the aops */
2199 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2200 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2203 /*-----------------------------------------------------------------*/
2204 /* saveRegisters - will look for a call and save the registers */
2205 /*-----------------------------------------------------------------*/
2207 saveRegisters (iCode * lic)
2214 for (ic = lic; ic; ic = ic->next)
2215 if (ic->op == CALL || ic->op == PCALL)
2220 fprintf (stderr, "found parameter push with no function call\n");
2224 /* if the registers have been saved already or don't need to be then
2228 if (IS_SYMOP(IC_LEFT(ic)) &&
2229 (IFFUNC_CALLEESAVES (OP_SYMBOL (IC_LEFT (ic))->type) ||
2230 IFFUNC_ISNAKED (OP_SYM_TYPE (IC_LEFT (ic)))))
2233 /* save the registers in use at this time but skip the
2234 ones for the result */
2235 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2236 mcs51_rUmaskForOp (IC_RESULT(ic)));
2239 if (options.useXstack)
2241 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2242 int nBits = bitVectnBitsOn (rsavebits);
2243 int count = bitVectnBitsOn (rsave);
2247 count = count - nBits + 1;
2248 /* remove all but the first bits as they are pushed all at once */
2249 rsave = bitVectCplAnd (rsave, rsavebits);
2250 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2252 freeBitVect (rsavebits);
2256 regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2257 if (reg->type == REG_BIT)
2259 emitcode ("mov", "a,%s", reg->base);
2263 emitcode ("mov", "a,%s", reg->name);
2265 emitcode ("mov", "r0,%s", spname);
2266 emitcode ("inc", "%s", spname);// allocate before use
2267 emitcode ("movx", "@r0,a");
2268 if (bitVectBitValue (rsave, R0_IDX))
2269 emitcode ("mov", "r0,a");
2271 else if (count != 0)
2273 if (bitVectBitValue (rsave, R0_IDX))
2275 emitcode ("push", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2277 emitcode ("mov", "r0,%s", spname);
2279 emitcode ("add", "a,#0x%02x", count);
2280 emitcode ("mov", "%s,a", spname);
2281 for (i = 0; i < mcs51_nRegs; i++)
2283 if (bitVectBitValue (rsave, i))
2285 regs * reg = REG_WITH_INDEX (i);
2288 emitcode ("pop", "acc");
2289 emitcode ("push", "acc");
2291 else if (reg->type == REG_BIT)
2293 emitcode ("mov", "a,%s", reg->base);
2297 emitcode ("mov", "a,%s", reg->name);
2299 emitcode ("movx", "@r0,a");
2302 emitcode ("inc", "r0");
2306 if (bitVectBitValue (rsave, R0_IDX))
2308 emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2314 bool bits_pushed = FALSE;
2315 for (i = 0; i < mcs51_nRegs; i++)
2317 if (bitVectBitValue (rsave, i))
2319 bits_pushed = pushReg (i, bits_pushed);
2323 freeBitVect (rsave);
2326 /*-----------------------------------------------------------------*/
2327 /* unsaveRegisters - pop the pushed registers */
2328 /*-----------------------------------------------------------------*/
2330 unsaveRegisters (iCode * ic)
2335 /* restore the registers in use at this time but skip the
2336 ones for the result */
2337 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2338 mcs51_rUmaskForOp (IC_RESULT(ic)));
2340 if (options.useXstack)
2342 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2343 int nBits = bitVectnBitsOn (rsavebits);
2344 int count = bitVectnBitsOn (rsave);
2348 count = count - nBits + 1;
2349 /* remove all but the first bits as they are popped all at once */
2350 rsave = bitVectCplAnd (rsave, rsavebits);
2351 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2353 freeBitVect (rsavebits);
2357 regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2358 emitcode ("mov", "r0,%s", spname);
2359 emitcode ("dec", "r0");
2360 emitcode ("movx", "a,@r0");
2361 if (reg->type == REG_BIT)
2363 emitcode ("mov", "%s,a", reg->base);
2367 emitcode ("mov", "%s,a", reg->name);
2369 emitcode ("dec", "%s", spname);
2371 else if (count != 0)
2373 emitcode ("mov", "r0,%s", spname);
2374 for (i = mcs51_nRegs; i >= 0; i--)
2376 if (bitVectBitValue (rsave, i))
2378 regs * reg = REG_WITH_INDEX (i);
2379 emitcode ("dec", "r0");
2380 emitcode ("movx", "a,@r0");
2383 emitcode ("push", "acc");
2385 else if (reg->type == REG_BIT)
2387 emitcode ("mov", "%s,a", reg->base);
2391 emitcode ("mov", "%s,a", reg->name);
2395 emitcode ("mov", "%s,r0", spname);
2396 if (bitVectBitValue (rsave, R0_IDX))
2398 emitcode ("pop", "ar0");
2404 bool bits_popped = FALSE;
2405 for (i = mcs51_nRegs; i >= 0; i--)
2407 if (bitVectBitValue (rsave, i))
2409 bits_popped = popReg (i, bits_popped);
2413 freeBitVect (rsave);
2417 /*-----------------------------------------------------------------*/
2419 /*-----------------------------------------------------------------*/
2421 pushSide (operand * oper, int size, iCode * ic)
2424 int nPushed = _G.r0Pushed + _G.r1Pushed;
2426 aopOp (oper, ic, FALSE);
2428 if (nPushed != _G.r0Pushed + _G.r1Pushed)
2430 while (offset < size)
2432 char *l = aopGet (oper, offset, FALSE, TRUE);
2433 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2435 freeAsmop (oper, NULL, ic, TRUE);
2437 while (offset < size)
2439 emitcode ("push", "%s", fReturn[offset++]);
2446 char *l = aopGet (oper, offset++, FALSE, TRUE);
2447 if (AOP_TYPE (oper) != AOP_REG &&
2448 AOP_TYPE (oper) != AOP_DIR &&
2452 emitcode ("push", "acc");
2456 emitcode ("push", "%s", l);
2460 freeAsmop (oper, NULL, ic, TRUE);
2463 /*-----------------------------------------------------------------*/
2464 /* assignResultValue - also indicates if acc is in use afterwards */
2465 /*-----------------------------------------------------------------*/
2467 assignResultValue (operand * oper, operand * func)
2470 int size = AOP_SIZE (oper);
2471 bool accuse = FALSE;
2472 bool pushedA = FALSE;
2474 if (func && IS_BIT (OP_SYM_ETYPE (func)))
2480 if ((size > 3) && aopPutUsesAcc (oper, fReturn[offset], offset))
2482 emitcode ("push", "acc");
2487 if ((offset == 3) && pushedA)
2488 emitcode ("pop", "acc");
2489 accuse |= aopPut (oper, fReturn[offset], offset);
2496 /*-----------------------------------------------------------------*/
2497 /* genXpush - pushes onto the external stack */
2498 /*-----------------------------------------------------------------*/
2500 genXpush (iCode * ic)
2502 asmop *aop = newAsmop (0);
2504 int size, offset = 0;
2506 D (emitcode (";", "genXpush"));
2508 aopOp (IC_LEFT (ic), ic, FALSE);
2509 r = getFreePtr (ic, &aop, FALSE);
2511 size = AOP_SIZE (IC_LEFT (ic));
2515 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2516 emitcode ("mov", "%s,%s", r->name, spname);
2517 emitcode ("inc", "%s", spname); // allocate space first
2518 emitcode ("movx", "@%s,a", r->name);
2522 // allocate space first
2523 emitcode ("mov", "%s,%s", r->name, spname);
2525 emitcode ("add", "a,#0x%02x", size);
2526 emitcode ("mov", "%s,a", spname);
2530 MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2531 emitcode ("movx", "@%s,a", r->name);
2532 emitcode ("inc", "%s", r->name);
2536 freeAsmop (NULL, aop, ic, TRUE);
2537 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2540 /*-----------------------------------------------------------------*/
2541 /* genIpush - generate code for pushing this gets a little complex */
2542 /*-----------------------------------------------------------------*/
2544 genIpush (iCode * ic)
2546 int size, offset = 0;
2550 D (emitcode (";", "genIpush"));
2552 /* if this is not a parm push : ie. it is spill push
2553 and spill push is always done on the local stack */
2557 /* and the item is spilt then do nothing */
2558 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2561 aopOp (IC_LEFT (ic), ic, FALSE);
2562 size = AOP_SIZE (IC_LEFT (ic));
2563 /* push it on the stack */
2566 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2572 emitcode ("push", "%s", l);
2577 /* this is a parameter push: in this case we call
2578 the routine to find the call and save those
2579 registers that need to be saved */
2582 /* if use external stack then call the external
2583 stack pushing routine */
2584 if (options.useXstack)
2590 /* then do the push */
2591 aopOp (IC_LEFT (ic), ic, FALSE);
2593 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2594 size = AOP_SIZE (IC_LEFT (ic));
2598 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2599 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2600 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR)
2602 if (strcmp (l, prev) || *l == '@')
2604 emitcode ("push", "acc");
2608 emitcode ("push", "%s", l);
2613 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2616 /*-----------------------------------------------------------------*/
2617 /* genIpop - recover the registers: can happen only for spilling */
2618 /*-----------------------------------------------------------------*/
2620 genIpop (iCode * ic)
2624 D (emitcode (";", "genIpop"));
2626 /* if the temp was not pushed then */
2627 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2630 aopOp (IC_LEFT (ic), ic, FALSE);
2631 size = AOP_SIZE (IC_LEFT (ic));
2632 offset = (size - 1);
2635 emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2639 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2642 /*-----------------------------------------------------------------*/
2643 /* popForBranch - recover the spilt registers for a branch */
2644 /*-----------------------------------------------------------------*/
2646 popForBranch (iCode * ic, bool markGenerated)
2648 while (ic && ic->op == IPOP)
2652 ic->generated = 1; /* mark the icode as generated */
2657 /*-----------------------------------------------------------------*/
2658 /* saveRBank - saves an entire register bank on the stack */
2659 /*-----------------------------------------------------------------*/
2661 saveRBank (int bank, iCode * ic, bool pushPsw)
2664 int count = 8 + (pushPsw ? 1 : 0);
2668 if (options.useXstack)
2672 /* Assume r0 is available for use. */
2673 r = REG_WITH_INDEX (R0_IDX);
2678 r = getFreePtr (ic, &aop, FALSE);
2680 // allocate space first
2681 emitcode ("mov", "%s,%s", r->name, spname);
2683 emitcode ("add", "a,#0x%02x", count);
2684 emitcode ("mov", "%s,a", spname);
2687 for (i = 0; i < 8; i++)
2689 if (options.useXstack)
2691 emitcode ("mov", "a,(%s+%d)",
2692 regs8051[i].base, 8 * bank + regs8051[i].offset);
2693 emitcode ("movx", "@%s,a", r->name);
2695 emitcode ("inc", "%s", r->name);
2698 emitcode ("push", "(%s+%d)",
2699 regs8051[i].base, 8 * bank + regs8051[i].offset);
2704 if (options.useXstack)
2706 emitcode ("mov", "a,psw");
2707 emitcode ("movx", "@%s,a", r->name);
2711 emitcode ("push", "psw");
2714 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2719 freeAsmop (NULL, aop, ic, TRUE);
2728 /*-----------------------------------------------------------------*/
2729 /* unsaveRBank - restores the register bank from stack */
2730 /*-----------------------------------------------------------------*/
2732 unsaveRBank (int bank, iCode * ic, bool popPsw)
2738 if (options.useXstack)
2742 /* Assume r0 is available for use. */
2743 r = REG_WITH_INDEX (R0_IDX);;
2748 r = getFreePtr (ic, &aop, FALSE);
2750 emitcode ("mov", "%s,%s", r->name, spname);
2755 if (options.useXstack)
2757 emitcode ("dec", "%s", r->name);
2758 emitcode ("movx", "a,@%s", r->name);
2759 emitcode ("mov", "psw,a");
2763 emitcode ("pop", "psw");
2767 for (i = 7; i >= 0; i--)
2769 if (options.useXstack)
2771 emitcode ("dec", "%s", r->name);
2772 emitcode ("movx", "a,@%s", r->name);
2773 emitcode ("mov", "(%s+%d),a",
2774 regs8051[i].base, 8 * bank + regs8051[i].offset);
2778 emitcode ("pop", "(%s+%d)",
2779 regs8051[i].base, 8 * bank + regs8051[i].offset);
2783 if (options.useXstack)
2785 emitcode ("mov", "%s,%s", spname, r->name);
2790 freeAsmop (NULL, aop, ic, TRUE);
2794 /*-----------------------------------------------------------------*/
2795 /* genSend - gen code for SEND */
2796 /*-----------------------------------------------------------------*/
2797 static void genSend(set *sendSet)
2802 /* first we do all bit parameters */
2803 for (sic = setFirstItem (sendSet); sic;
2804 sic = setNextItem (sendSet))
2806 if (sic->argreg > 12)
2808 int bit = sic->argreg-13;
2810 aopOp (IC_LEFT (sic), sic, FALSE);
2812 /* if left is a literal then
2813 we know what the value is */
2814 if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2816 if (((int) operandLitValue (IC_LEFT (sic))))
2817 emitcode ("setb", "b[%d]", bit);
2819 emitcode ("clr", "b[%d]", bit);
2824 toCarry (IC_LEFT (sic));
2825 emitcode ("mov", "b[%d],c", bit);
2830 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2834 if (options.useXstack || bit_count)
2836 saveRegisters (setFirstItem (sendSet));
2841 emitcode ("mov", "bits,b");
2844 /* then we do all other parameters */
2845 for (sic = setFirstItem (sendSet); sic;
2846 sic = setNextItem (sendSet))
2848 if (sic->argreg <= 12)
2850 int size, offset = 0;
2851 aopOp (IC_LEFT (sic), sic, FALSE);
2852 size = AOP_SIZE (IC_LEFT (sic));
2854 if (sic->argreg == 1)
2858 char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2859 if (strcmp (l, fReturn[offset]))
2861 emitcode ("mov", "%s,%s", fReturn[offset], l);
2870 emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2871 aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2875 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2880 /*-----------------------------------------------------------------*/
2881 /* selectRegBank - emit code to select the register bank */
2882 /*-----------------------------------------------------------------*/
2884 selectRegBank (short bank, bool keepFlags)
2886 /* if f.e. result is in carry */
2889 emitcode ("anl", "psw,#0xE7");
2891 emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2895 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2899 /*-----------------------------------------------------------------*/
2900 /* genCall - generates a call statement */
2901 /*-----------------------------------------------------------------*/
2903 genCall (iCode * ic)
2907 // bool restoreBank = FALSE;
2908 bool swapBanks = FALSE;
2909 bool accuse = FALSE;
2910 bool accPushed = FALSE;
2911 bool resultInF0 = FALSE;
2912 bool assignResultGenerated = FALSE;
2914 D (emitcode (";", "genCall"));
2916 dtype = operandType (IC_LEFT (ic));
2917 etype = getSpec(dtype);
2918 /* if send set is not empty then assign */
2921 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2922 genSend(reverseSet(_G.sendSet));
2924 genSend(_G.sendSet);
2929 /* if we are calling a not _naked function that is not using
2930 the same register bank then we need to save the
2931 destination registers on the stack */
2932 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2933 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2934 !IFFUNC_ISISR (dtype))
2939 /* if caller saves & we have not saved then */
2945 emitcode ("mov", "psw,#0x%02x", ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2949 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2951 if (IFFUNC_CALLEESAVES(dtype))
2953 werror (E_BANKED_WITH_CALLEESAVES);
2957 char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2958 OP_SYMBOL (IC_LEFT (ic))->rname :
2959 OP_SYMBOL (IC_LEFT (ic))->name);
2961 emitcode ("mov", "r0,#%s", l);
2962 emitcode ("mov", "r1,#(%s >> 8)", l);
2963 emitcode ("mov", "r2,#(%s >> 16)", l);
2964 emitcode ("lcall", "__sdcc_banked_call");
2969 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2970 OP_SYMBOL (IC_LEFT (ic))->rname :
2971 OP_SYMBOL (IC_LEFT (ic))->name));
2976 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2979 /* if we need assign a result value */
2980 if ((IS_ITEMP (IC_RESULT (ic)) &&
2981 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2982 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2983 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2984 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2985 IS_TRUE_SYMOP (IC_RESULT (ic)))
2989 aopOp (IC_RESULT (ic), ic, FALSE);
2992 accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2993 assignResultGenerated = TRUE;
2995 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2998 /* adjust the stack for parameters if required */
3002 if (ic->parmBytes > 3)
3006 emitcode ("push", "acc");
3009 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3010 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3011 !assignResultGenerated)
3013 emitcode ("mov", "F0,c");
3017 emitcode ("mov", "a,%s", spname);
3018 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3019 emitcode ("mov", "%s,a", spname);
3021 /* unsaveRegisters from xstack needs acc, but */
3022 /* unsaveRegisters from stack needs this popped */
3023 if (accPushed && !options.useXstack)
3025 emitcode ("pop", "acc");
3030 for (i = 0; i < ic->parmBytes; i++)
3031 emitcode ("dec", "%s", spname);
3034 /* if we had saved some registers then unsave them */
3035 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3037 if (accuse && !accPushed && options.useXstack)
3039 /* xstack needs acc, but doesn't touch normal stack */
3040 emitcode ("push", "acc");
3043 unsaveRegisters (ic);
3046 // /* if register bank was saved then pop them */
3048 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
3050 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
3053 emitcode ("mov", "c,F0");
3055 aopOp (IC_RESULT (ic), ic, FALSE);
3056 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3057 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3061 emitcode ("pop", "acc");
3064 /*-----------------------------------------------------------------*/
3065 /* genPcall - generates a call by pointer statement */
3066 /*-----------------------------------------------------------------*/
3068 genPcall (iCode * ic)
3072 symbol *rlbl = newiTempLabel (NULL);
3073 // bool restoreBank=FALSE;
3074 bool swapBanks = FALSE;
3075 bool resultInF0 = FALSE;
3077 D (emitcode (";", "genPcall"));
3079 dtype = operandType (IC_LEFT (ic))->next;
3080 etype = getSpec(dtype);
3081 /* if caller saves & we have not saved then */
3085 /* if we are calling a not _naked function that is not using
3086 the same register bank then we need to save the
3087 destination registers on the stack */
3088 if (currFunc && dtype && !IFFUNC_ISNAKED (dtype) &&
3089 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
3090 !IFFUNC_ISISR (dtype))
3092 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3093 // restoreBank=TRUE;
3095 // need caution message to user here
3098 if (IS_LITERAL (etype))
3100 /* if send set is not empty then assign */
3103 genSend(reverseSet(_G.sendSet));
3109 emitcode ("mov", "psw,#0x%02x",
3110 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3113 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT (getSpec(dtype)))
3115 if (IFFUNC_CALLEESAVES (dtype))
3117 werror (E_BANKED_WITH_CALLEESAVES);
3121 char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
3123 emitcode ("mov", "r0,#%s", l);
3124 emitcode ("mov", "r1,#(%s >> 8)", l);
3125 emitcode ("mov", "r2,#(%s >> 16)", l);
3126 emitcode ("lcall", "__sdcc_banked_call");
3131 emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
3136 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT (getSpec(dtype)))
3138 if (IFFUNC_CALLEESAVES (dtype))
3140 werror (E_BANKED_WITH_CALLEESAVES);
3144 aopOp (IC_LEFT (ic), ic, FALSE);
3148 /* what if aopGet needs r0 or r1 ??? */
3149 emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3150 emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3151 emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3155 int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
3156 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3157 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3158 emitcode ("mov", "0x%02x,%s", reg, aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3161 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3163 /* if send set is not empty then assign */
3166 genSend(reverseSet(_G.sendSet));
3172 emitcode ("mov", "psw,#0x%02x",
3173 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3177 emitcode ("lcall", "__sdcc_banked_call");
3180 else if (_G.sendSet)
3182 /* push the return address on to the stack */
3183 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
3184 emitcode ("push", "acc");
3185 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
3186 emitcode ("push", "acc");
3188 /* now push the function address */
3189 pushSide (IC_LEFT (ic), FPTRSIZE, ic);
3191 /* if send set is not empty then assign */
3194 genSend(reverseSet(_G.sendSet));
3200 emitcode ("mov", "psw,#0x%02x",
3201 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3205 emitcode ("ret", "");
3208 else /* the send set is empty */
3211 /* now get the calling address into dptr */
3212 aopOp (IC_LEFT (ic), ic, FALSE);
3214 l = aopGet (IC_LEFT (ic), 0, FALSE, FALSE);
3215 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3217 emitcode ("mov", "r0,%s", l);
3218 l = aopGet (IC_LEFT (ic), 1, FALSE, FALSE);
3219 emitcode ("mov", "dph,%s", l);
3220 emitcode ("mov", "dpl,r0");
3224 emitcode ("mov", "dpl,%s", l);
3225 l = aopGet (IC_LEFT (ic), 1, FALSE, FALSE);
3226 emitcode ("mov", "dph,%s", l);
3229 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3233 emitcode ("mov", "psw,#0x%02x",
3234 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3238 emitcode ("lcall", "__sdcc_call_dptr");
3243 selectRegBank (FUNC_REGBANK (currFunc->type), IS_BIT (etype));
3246 /* if we need assign a result value */
3247 if ((IS_ITEMP (IC_RESULT (ic)) &&
3248 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3249 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3250 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3251 IS_TRUE_SYMOP (IC_RESULT (ic)))
3255 aopOp (IC_RESULT (ic), ic, FALSE);
3258 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3260 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3263 /* adjust the stack for parameters if required */
3267 if (ic->parmBytes > 3)
3269 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3270 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3272 emitcode ("mov", "F0,c");
3276 emitcode ("mov", "a,%s", spname);
3277 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3278 emitcode ("mov", "%s,a", spname);
3281 for (i = 0; i < ic->parmBytes; i++)
3282 emitcode ("dec", "%s", spname);
3285 // /* if register bank was saved then unsave them */
3287 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3289 /* if we had saved some registers then unsave them */
3290 if (ic->regsSaved && !IFFUNC_CALLEESAVES (dtype))
3291 unsaveRegisters (ic);
3293 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3296 emitcode ("mov", "c,F0");
3298 aopOp (IC_RESULT (ic), ic, FALSE);
3299 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3300 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3304 /*-----------------------------------------------------------------*/
3305 /* resultRemat - result is rematerializable */
3306 /*-----------------------------------------------------------------*/
3308 resultRemat (iCode * ic)
3310 if (SKIP_IC (ic) || ic->op == IFX)
3313 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3315 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3316 if (sym->remat && !POINTER_SET (ic))
3323 /*-----------------------------------------------------------------*/
3324 /* inExcludeList - return 1 if the string is in exclude Reg list */
3325 /*-----------------------------------------------------------------*/
3327 regsCmp(void *p1, void *p2)
3329 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3333 inExcludeList (char *s)
3335 const char *p = setFirstItem(options.excludeRegsSet);
3337 if (p == NULL || STRCASECMP(p, "none") == 0)
3341 return isinSetWith(options.excludeRegsSet, s, regsCmp);
3344 /*-----------------------------------------------------------------*/
3345 /* genFunction - generated code for function entry */
3346 /*-----------------------------------------------------------------*/
3348 genFunction (iCode * ic)
3350 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3352 bool switchedPSW = FALSE;
3353 int calleesaves_saved_register = -1;
3354 int stackAdjust = sym->stack;
3355 int accIsFree = sym->recvSize < 4;
3356 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3357 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3360 /* create the function header */
3361 emitcode (";", "-----------------------------------------");
3362 emitcode (";", " function %s", sym->name);
3363 emitcode (";", "-----------------------------------------");
3365 emitcode ("", "%s:", sym->rname);
3366 lineCurr->isLabel = 1;
3367 ftype = operandType (IC_LEFT (ic));
3368 _G.currentFunc = sym;
3370 if (IFFUNC_ISNAKED(ftype))
3372 emitcode(";", "naked function: no prologue.");
3376 /* here we need to generate the equates for the
3377 register bank if required */
3378 if (FUNC_REGBANK (ftype) != rbank)
3382 rbank = FUNC_REGBANK (ftype);
3383 for (i = 0; i < mcs51_nRegs; i++)
3385 if (regs8051[i].type != REG_BIT)
3387 if (strcmp (regs8051[i].base, "0") == 0)
3388 emitcode ("", "%s = 0x%02x",
3390 8 * rbank + regs8051[i].offset);
3392 emitcode ("", "%s = %s + 0x%02x",
3395 8 * rbank + regs8051[i].offset);
3400 /* if this is an interrupt service routine then
3401 save acc, b, dpl, dph */
3402 if (IFFUNC_ISISR (sym->type))
3406 rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), sym->regsUsed);
3407 if (IFFUNC_HASFCALL(sym->type) || !bitVectIsZero (rsavebits))
3409 emitcode ("push", "bits");
3412 freeBitVect (rsavebits);
3414 if (!inExcludeList ("acc"))
3415 emitcode ("push", "acc");
3416 if (!inExcludeList ("b"))
3417 emitcode ("push", "b");
3418 if (!inExcludeList ("dpl"))
3419 emitcode ("push", "dpl");
3420 if (!inExcludeList ("dph"))
3421 emitcode ("push", "dph");
3422 /* if this isr has no bank i.e. is going to
3423 run with bank 0 , then we need to save more
3425 if (!FUNC_REGBANK (sym->type))
3429 /* if this function does not call any other
3430 function then we can be economical and
3431 save only those registers that are used */
3432 if (!IFFUNC_HASFCALL(sym->type))
3434 /* if any registers used */
3437 /* save the registers used */
3438 for (i = 0; i < sym->regsUsed->size; i++)
3440 if (bitVectBitValue (sym->regsUsed, i))
3447 /* this function has a function call. We cannot
3448 determine register usage so we will have to push the
3450 saveRBank (0, ic, FALSE);
3451 if (options.parms_in_bank1)
3453 for (i=0; i < 8 ; i++ )
3455 emitcode ("push","%s",rb1regs[i]);
3462 /* This ISR uses a non-zero bank.
3464 * We assume that the bank is available for our
3467 * However, if this ISR calls a function which uses some
3468 * other bank, we must save that bank entirely.
3470 unsigned long banksToSave = 0;
3472 if (IFFUNC_HASFCALL(sym->type))
3475 #define MAX_REGISTER_BANKS 4
3480 for (i = ic; i; i = i->next)
3482 if (i->op == ENDFUNCTION)
3484 /* we got to the end OK. */
3492 dtype = operandType (IC_LEFT(i));
3494 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3496 /* Mark this bank for saving. */
3497 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3499 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3503 banksToSave |= (1 << FUNC_REGBANK(dtype));
3506 /* And note that we don't need to do it in
3514 /* This is a mess; we have no idea what
3515 * register bank the called function might
3518 * The only thing I can think of to do is
3519 * throw a warning and hope.
3521 werror(W_FUNCPTR_IN_USING_ISR);
3525 if (banksToSave && options.useXstack)
3527 /* Since we aren't passing it an ic,
3528 * saveRBank will assume r0 is available to abuse.
3530 * So switch to our (trashable) bank now, so
3531 * the caller's R0 isn't trashed.
3533 emitcode ("push", "psw");
3534 emitcode ("mov", "psw,#0x%02x",
3535 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3539 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3541 if (banksToSave & (1 << ix))
3543 saveRBank(ix, NULL, FALSE);
3547 // TODO: this needs a closer look
3548 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3551 /* Set the register bank to the desired value if nothing else */
3552 /* has done so yet. */
3555 emitcode ("push", "psw");
3556 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3561 /* This is a non-ISR function. The caller has already switched register */
3562 /* banks, if necessary, so just handle the callee-saves option. */
3564 /* if callee-save to be used for this function
3565 then save the registers being used in this function */
3566 if (IFFUNC_CALLEESAVES(sym->type))
3570 /* if any registers used */
3573 bool bits_pushed = FALSE;
3574 /* save the registers used */
3575 for (i = 0; i < sym->regsUsed->size; i++)
3577 if (bitVectBitValue (sym->regsUsed, i))
3579 /* remember one saved register for later usage */
3580 if (calleesaves_saved_register < 0)
3581 calleesaves_saved_register = i;
3582 bits_pushed = pushReg (i, bits_pushed);
3592 if (options.useXstack)
3594 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3596 emitcode ("mov", "r0,%s", spname);
3597 emitcode ("inc", "%s", spname);
3598 emitcode ("xch", "a,_bpx");
3599 emitcode ("movx", "@r0,a");
3600 emitcode ("inc", "r0");
3601 emitcode ("mov", "a,r0");
3602 emitcode ("xch", "a,_bpx");
3606 emitcode ("push", "_bp"); /* save the callers stack */
3607 emitcode ("mov", "_bp,sp");
3612 if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3614 /* set up the stack */
3615 emitcode ("push", "_bp"); /* save the callers stack */
3616 emitcode ("mov", "_bp,sp");
3621 /* For some cases it is worthwhile to perform a RECEIVE iCode */
3622 /* before setting up the stack frame completely. */
3623 if (ric && ric->argreg == 1 && IC_RESULT (ric))
3625 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3629 if (rsym && rsym->regType == REG_CND)
3631 if (rsym && (rsym->accuse || rsym->ruonly))
3633 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3634 rsym = rsym->usl.spillLoc;
3637 /* If the RECEIVE operand immediately spills to the first entry on the */
3638 /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3639 /* rather than the usual @r0/r1 machinations. */
3640 if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3644 _G.current_iCode = ric;
3645 D(emitcode (";", "genReceive"));
3646 for (ofs=0; ofs < sym->recvSize; ofs++)
3648 if (!strcmp (fReturn[ofs], "a"))
3649 emitcode ("push", "acc");
3651 emitcode ("push", fReturn[ofs]);
3653 stackAdjust -= sym->recvSize;
3656 assert (stackAdjust>=0);
3659 _G.current_iCode = ic;
3663 /* If the RECEIVE operand is 4 registers, we can do the moves now */
3664 /* to free up the accumulator. */
3665 else if (rsym && rsym->nRegs && sym->recvSize == 4)
3669 _G.current_iCode = ric;
3670 D(emitcode (";", "genReceive"));
3671 for (ofs=0; ofs < sym->recvSize; ofs++)
3673 emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3675 _G.current_iCode = ic;
3681 /* adjust the stack for the function */
3684 int i = stackAdjust;
3686 werror (W_STACK_OVERFLOW, sym->name);
3688 if (i > 3 && accIsFree)
3690 emitcode ("mov", "a,sp");
3691 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3692 emitcode ("mov", "sp,a");
3696 /* The accumulator is not free, so we will need another register */
3697 /* to clobber. No need to worry about a possible conflict with */
3698 /* the above early RECEIVE optimizations since they would have */
3699 /* freed the accumulator if they were generated. */
3701 if (IFFUNC_CALLEESAVES(sym->type))
3703 /* if it's a callee-saves function we need a saved register */
3704 if (calleesaves_saved_register >= 0)
3706 emitcode ("mov", "%s,a", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3707 emitcode ("mov", "a,sp");
3708 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3709 emitcode ("mov", "sp,a");
3710 emitcode ("mov", "a,%s", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3713 /* do it the hard way */
3715 emitcode ("inc", "sp");
3719 /* not callee-saves, we can clobber r0 */
3720 emitcode ("mov", "r0,a");
3721 emitcode ("mov", "a,sp");
3722 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3723 emitcode ("mov", "sp,a");
3724 emitcode ("mov", "a,r0");
3729 emitcode ("inc", "sp");
3734 char i = ((char) sym->xstack & 0xff);
3736 if (i > 3 && accIsFree)
3738 emitcode ("mov", "a,_spx");
3739 emitcode ("add", "a,#0x%02x", i & 0xff);
3740 emitcode ("mov", "_spx,a");
3744 emitcode ("push", "acc");
3745 emitcode ("mov", "a,_spx");
3746 emitcode ("add", "a,#0x%02x", i & 0xff);
3747 emitcode ("mov", "_spx,a");
3748 emitcode ("pop", "acc");
3753 emitcode ("inc", "_spx");
3757 /* if critical function then turn interrupts off */
3758 if (IFFUNC_ISCRITICAL (ftype))
3760 symbol *tlbl = newiTempLabel (NULL);
3761 emitcode ("setb", "c");
3762 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3763 emitcode ("clr", "c");
3765 emitcode ("push", "psw"); /* save old ea via c in psw */
3769 /*-----------------------------------------------------------------*/
3770 /* genEndFunction - generates epilogue for functions */
3771 /*-----------------------------------------------------------------*/
3773 genEndFunction (iCode * ic)
3775 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3776 lineNode *lnp = lineCurr;
3778 bitVect *regsUsedPrologue;
3779 bitVect *regsUnneeded;
3782 _G.currentFunc = NULL;
3783 if (IFFUNC_ISNAKED(sym->type))
3785 emitcode(";", "naked function: no epilogue.");
3786 if (options.debug && currFunc)
3787 debugFile->writeEndFunction (currFunc, ic, 0);
3791 if (IFFUNC_ISCRITICAL (sym->type))
3793 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3795 emitcode ("rlc", "a"); /* save c in a */
3796 emitcode ("pop", "psw"); /* restore ea via c in psw */
3797 emitcode ("mov", "ea,c");
3798 emitcode ("rrc", "a"); /* restore c from a */
3802 emitcode ("pop", "psw"); /* restore ea via c in psw */
3803 emitcode ("mov", "ea,c");
3807 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3809 if (options.useXstack)
3813 emitcode ("mov", "sp,_bp");
3814 emitcode ("pop", "_bp");
3816 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3818 emitcode ("xch", "a,_bpx");
3819 emitcode ("mov", "r0,a");
3820 emitcode ("dec", "r0");
3821 emitcode ("movx", "a,@r0");
3822 emitcode ("xch", "a,_bpx");
3823 emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3826 else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3829 emitcode ("mov", "sp,_bp");
3830 emitcode ("pop", "_bp");
3834 /* restore the register bank */
3835 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3837 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3838 || !options.useXstack)
3840 /* Special case of ISR using non-zero bank with useXstack
3843 emitcode ("pop", "psw");
3847 if (IFFUNC_ISISR (sym->type))
3851 /* now we need to restore the registers */
3852 /* if this isr has no bank i.e. is going to
3853 run with bank 0 , then we need to save more
3855 if (!FUNC_REGBANK (sym->type))
3858 /* if this function does not call any other
3859 function then we can be economical and
3860 save only those registers that are used */
3861 if (!IFFUNC_HASFCALL(sym->type))
3863 /* if any registers used */
3866 /* save the registers used */
3867 for (i = sym->regsUsed->size; i >= 0; i--)
3869 if (bitVectBitValue (sym->regsUsed, i))
3876 if (options.parms_in_bank1)
3878 for (i = 7 ; i >= 0 ; i-- )
3880 emitcode ("pop","%s",rb1regs[i]);
3883 /* this function has a function call. We cannot
3884 determine register usage so we will have to pop the
3886 unsaveRBank (0, ic, FALSE);
3891 /* This ISR uses a non-zero bank.
3893 * Restore any register banks saved by genFunction
3896 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3899 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3901 if (savedBanks & (1 << ix))
3903 unsaveRBank(ix, NULL, FALSE);
3907 if (options.useXstack)
3909 /* Restore bank AFTER calling unsaveRBank,
3910 * since it can trash r0.
3912 emitcode ("pop", "psw");
3916 if (!inExcludeList ("dph"))
3917 emitcode ("pop", "dph");
3918 if (!inExcludeList ("dpl"))
3919 emitcode ("pop", "dpl");
3920 if (!inExcludeList ("b"))
3921 emitcode ("pop", "b");
3922 if (!inExcludeList ("acc"))
3923 emitcode ("pop", "acc");
3925 rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), sym->regsUsed);
3926 if (IFFUNC_HASFCALL(sym->type) || !bitVectIsZero (rsavebits))
3927 emitcode ("pop", "bits");
3928 freeBitVect (rsavebits);
3930 /* if debug then send end of function */
3931 if (options.debug && currFunc)
3933 debugFile->writeEndFunction (currFunc, ic, 1);
3936 emitcode ("reti", "");
3940 if (IFFUNC_CALLEESAVES(sym->type))
3944 /* if any registers used */
3947 /* save the registers used */
3948 for (i = sym->regsUsed->size; i >= 0; i--)
3950 if (bitVectBitValue (sym->regsUsed, i) ||
3951 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3952 emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
3955 else if (mcs51_ptrRegReq)
3957 emitcode ("pop", "%s", REG_WITH_INDEX (R1_IDX)->dname);
3958 emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
3963 /* if debug then send end of function */
3964 if (options.debug && currFunc)
3966 debugFile->writeEndFunction (currFunc, ic, 1);
3969 if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3971 emitcode ("ljmp", "__sdcc_banked_ret");
3975 emitcode ("ret", "");
3979 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3982 /* If this was an interrupt handler using bank 0 that called another */
3983 /* function, then all registers must be saved; nothing to optimized. */
3984 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3985 && !FUNC_REGBANK(sym->type))
3988 /* There are no push/pops to optimize if not callee-saves or ISR */
3989 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3992 /* If there were stack parameters, we cannot optimize without also */
3993 /* fixing all of the stack offsets; this is too dificult to consider. */
3994 if (FUNC_HASSTACKPARM(sym->type))
3997 /* Compute the registers actually used */
3998 regsUsed = newBitVect (mcs51_nRegs);
3999 regsUsedPrologue = newBitVect (mcs51_nRegs);
4002 if (lnp->ic && lnp->ic->op == FUNCTION)
4003 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
4005 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
4007 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
4008 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
4015 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
4016 && !bitVectBitValue (regsUsed, CND_IDX))
4018 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
4019 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
4020 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
4021 bitVectUnSetBit (regsUsed, CND_IDX);
4024 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
4026 /* If this was an interrupt handler that called another function */
4027 /* function, then assume A, B, DPH, & DPL may be modified by it. */
4028 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
4030 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
4031 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
4032 regsUsed = bitVectSetBit (regsUsed, B_IDX);
4033 regsUsed = bitVectSetBit (regsUsed, A_IDX);
4034 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
4037 /* Remove the unneeded push/pops */
4038 regsUnneeded = newBitVect (mcs51_nRegs);
4041 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
4043 if (!strncmp(lnp->line, "push", 4))
4045 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
4046 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4048 connectLine (lnp->prev, lnp->next);
4049 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4052 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
4054 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
4055 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4057 connectLine (lnp->prev, lnp->next);
4058 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4065 for (idx = 0; idx < regsUnneeded->size; idx++)
4066 if (bitVectBitValue (regsUnneeded, idx))
4067 emitcode (";", "eliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
4069 freeBitVect (regsUnneeded);
4070 freeBitVect (regsUsed);
4071 freeBitVect (regsUsedPrologue);
4074 /*-----------------------------------------------------------------*/
4075 /* genRet - generate code for return statement */
4076 /*-----------------------------------------------------------------*/
4080 int size, offset = 0, pushed = 0;
4082 D (emitcode (";", "genRet"));
4084 /* if we have no return value then
4085 just generate the "ret" */
4089 /* we have something to return then
4090 move the return value into place */
4091 aopOp (IC_LEFT (ic), ic, FALSE);
4092 size = AOP_SIZE (IC_LEFT (ic));
4094 if (IS_BIT(_G.currentFunc->etype))
4096 if (!IS_OP_RUONLY (IC_LEFT (ic)))
4097 toCarry (IC_LEFT (ic));
4104 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
4107 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
4108 emitcode ("push", "%s", l);
4113 l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
4114 if (strcmp (fReturn[offset], l))
4115 emitcode ("mov", "%s,%s", fReturn[offset++], l);
4122 if (strcmp (fReturn[pushed], "a"))
4123 emitcode ("pop", fReturn[pushed]);
4125 emitcode ("pop", "acc");
4128 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
4131 /* generate a jump to the return label
4132 if the next is not the return statement */
4133 if (!(ic->next && ic->next->op == LABEL &&
4134 IC_LABEL (ic->next) == returnLabel))
4136 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
4140 /*-----------------------------------------------------------------*/
4141 /* genLabel - generates a label */
4142 /*-----------------------------------------------------------------*/
4144 genLabel (iCode * ic)
4146 /* special case never generate */
4147 if (IC_LABEL (ic) == entryLabel)
4150 emitLabel (IC_LABEL (ic));
4153 /*-----------------------------------------------------------------*/
4154 /* genGoto - generates a ljmp */
4155 /*-----------------------------------------------------------------*/
4157 genGoto (iCode * ic)
4159 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
4162 /*-----------------------------------------------------------------*/
4163 /* findLabelBackwards: walks back through the iCode chain looking */
4164 /* for the given label. Returns number of iCode instructions */
4165 /* between that label and given ic. */
4166 /* Returns zero if label not found. */
4167 /*-----------------------------------------------------------------*/
4169 findLabelBackwards (iCode * ic, int key)
4178 /* If we have any pushes or pops, we cannot predict the distance.
4179 I don't like this at all, this should be dealt with in the
4181 if (ic->op == IPUSH || ic->op == IPOP) {
4185 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4194 /*-----------------------------------------------------------------*/
4195 /* genPlusIncr :- does addition with increment if possible */
4196 /*-----------------------------------------------------------------*/
4198 genPlusIncr (iCode * ic)
4200 unsigned int icount;
4201 unsigned int size = getDataSize (IC_RESULT (ic));
4203 /* will try to generate an increment */
4204 /* if the right side is not a literal
4206 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4209 icount = (unsigned int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4211 D(emitcode (";","genPlusIncr"));
4213 /* if increment >=16 bits in register or direct space */
4214 if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG ||
4215 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4216 (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4217 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4218 !isOperandVolatile (IC_RESULT (ic), FALSE) &&
4227 /* If the next instruction is a goto and the goto target
4228 * is < 10 instructions previous to this, we can generate
4229 * jumps straight to that target.
4231 if (ic->next && ic->next->op == GOTO
4232 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4233 && labelRange <= 10)
4235 D (emitcode (";", "tail increment optimized (range %d)", labelRange));
4236 tlbl = IC_LABEL (ic->next);
4241 tlbl = newiTempLabel (NULL);
4244 l = aopGet (IC_RESULT (ic), LSB, FALSE, FALSE);
4245 emitcode ("inc", "%s", l);
4246 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4247 IS_AOP_PREG (IC_RESULT (ic)))
4249 emitcode ("cjne", "%s,#0x00,%05d$", l, tlbl->key + 100);
4253 emitcode ("clr", "a");
4254 emitcode ("cjne", "a,%s,%05d$", l, tlbl->key + 100);
4257 l = aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE);
4258 emitcode ("inc", "%s", l);
4261 if (!strcmp(l, "acc"))
4263 emitcode("jnz", "!tlabel", tlbl->key + 100);
4265 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4266 IS_AOP_PREG (IC_RESULT (ic)))
4268 emitcode ("cjne", "%s,#0x00,%05d$", l, tlbl->key + 100);
4272 emitcode ("cjne", "a,%s,%05d$", l, tlbl->key + 100);
4275 l = aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE);
4276 emitcode ("inc", "%s", l);
4280 if (!strcmp(l, "acc"))
4282 emitcode("jnz", "!tlabel", tlbl->key + 100);
4284 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4285 IS_AOP_PREG (IC_RESULT (ic)))
4287 emitcode ("cjne", "%s,#0x00,%05d$", l, tlbl->key + 100);
4291 emitcode ("cjne", "a,%s,%05d$", l, tlbl->key + 100);
4294 l = aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE);
4295 emitcode ("inc", "%s", l);
4305 /* if result is dptr */
4306 if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
4307 (AOP_SIZE (IC_RESULT (ic)) == 2) &&
4308 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
4309 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
4311 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4317 if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
4320 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0);
4321 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1);
4323 emitcode ("inc", "dptr");
4328 /* if the literal value of the right hand side
4329 is greater than 4 then it is not worth it */
4333 /* if the sizes are greater than 1 then we cannot */
4334 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4335 AOP_SIZE (IC_LEFT (ic)) > 1)
4338 /* we can if the aops of the left & result match or
4339 if they are in registers and the registers are the
4341 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4345 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4346 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4347 aopPut (IC_RESULT (ic), "a", 0);
4353 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4362 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4363 emitcode ("inc", "a");
4364 aopPut (IC_RESULT (ic), "a", 0);
4371 /*-----------------------------------------------------------------*/
4372 /* outBitAcc - output a bit in acc */
4373 /*-----------------------------------------------------------------*/
4375 outBitAcc (operand * result)
4377 symbol *tlbl = newiTempLabel (NULL);
4378 /* if the result is a bit */
4379 if (AOP_TYPE (result) == AOP_CRY)
4381 aopPut (result, "a", 0);
4385 emitcode ("jz", "%05d$", tlbl->key + 100);
4386 emitcode ("mov", "a,%s", one);
4392 /*-----------------------------------------------------------------*/
4393 /* genPlusBits - generates code for addition of two bits */
4394 /*-----------------------------------------------------------------*/
4396 genPlusBits (iCode * ic)
4398 D (emitcode (";", "genPlusBits"));
4400 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4401 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4403 symbol *lbl = newiTempLabel (NULL);
4404 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4405 emitcode ("cpl", "c");
4407 outBitC (IC_RESULT (ic));
4411 emitcode ("clr", "a");
4412 emitcode ("rlc", "a");
4413 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4414 emitcode ("addc", "a,%s", zero);
4415 outAcc (IC_RESULT (ic));
4420 /* This is the original version of this code.
4422 * This is being kept around for reference,
4423 * because I am not entirely sure I got it right...
4426 adjustArithmeticResult (iCode * ic)
4428 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4429 AOP_SIZE (IC_LEFT (ic)) == 3 &&
4430 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4431 aopPut (IC_RESULT (ic),
4432 aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4435 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4436 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4437 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4438 aopPut (IC_RESULT (ic),
4439 aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4442 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4443 AOP_SIZE (IC_LEFT (ic)) < 3 &&
4444 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4445 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4446 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4449 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4450 aopPut (IC_RESULT (ic), buffer, 2);
4454 /* This is the pure and virtuous version of this code.
4455 * I'm pretty certain it's right, but not enough to toss the old
4459 adjustArithmeticResult (iCode * ic)
4461 if (opIsGptr (IC_RESULT (ic)))
4465 if (opIsGptr (IC_LEFT (ic)))
4467 if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4469 aopPut (IC_RESULT (ic),
4470 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4476 if (opIsGptr (IC_RIGHT (ic)))
4478 if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4480 aopPut (IC_RESULT (ic),
4481 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4487 if (IC_LEFT (ic) && AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4488 IC_RIGHT (ic) && AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4489 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4490 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4492 SNPRINTF (buffer, sizeof(buffer),
4493 "#0x%02x", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4494 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4497 if (IC_LEFT (ic) && AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4498 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4500 SNPRINTF (buffer, sizeof(buffer),
4501 "#0x%02x", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4502 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4505 if (IC_RIGHT (ic) && AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4506 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4508 SNPRINTF (buffer, sizeof(buffer),
4509 "#0x%02x", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_RIGHT (ic)))), NULL, NULL));
4510 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4517 /*-----------------------------------------------------------------*/
4518 /* genPlus - generates code for addition */
4519 /*-----------------------------------------------------------------*/
4521 genPlus (iCode * ic)
4523 int size, offset = 0;
4526 bool swappedLR = FALSE;
4527 operand *leftOp, *rightOp;
4530 D (emitcode (";", "genPlus"));
4532 /* special cases :- */
4534 aopOp (IC_LEFT (ic), ic, FALSE);
4535 aopOp (IC_RIGHT (ic), ic, FALSE);
4536 aopOp (IC_RESULT (ic), ic, TRUE);
4538 /* if literal, literal on the right or
4539 if left requires ACC or right is already
4541 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4542 (AOP_NEEDSACC (IC_LEFT (ic))) ||
4543 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4545 operand *t = IC_RIGHT (ic);
4546 IC_RIGHT (ic) = IC_LEFT (ic);
4551 /* if both left & right are in bit
4553 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4554 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4560 /* if left in bit space & right literal */
4561 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4562 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4564 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4565 /* if result in bit space */
4566 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4568 if (ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4569 emitcode ("cpl", "c");
4570 outBitC (IC_RESULT (ic));
4574 size = getDataSize (IC_RESULT (ic));
4577 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4578 emitcode ("addc", "a,%s", zero);
4579 aopPut (IC_RESULT (ic), "a", offset++);
4585 /* if I can do an increment instead
4586 of add then GOOD for ME */
4587 if (genPlusIncr (ic) == TRUE)
4590 size = getDataSize (IC_RESULT (ic));
4591 leftOp = IC_LEFT(ic);
4592 rightOp = IC_RIGHT(ic);
4595 /* if this is an add for an array access
4596 at a 256 byte boundary */
4598 && AOP_TYPE (op) == AOP_IMMD
4600 && IS_SPEC (OP_SYM_ETYPE (op))
4601 && SPEC_ABSA (OP_SYM_ETYPE (op))
4602 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4605 D(emitcode (";", "genPlus aligned array"));
4606 aopPut (IC_RESULT (ic),
4607 aopGet (rightOp, 0, FALSE, FALSE),
4610 if( 1 == getDataSize (IC_RIGHT (ic)) )
4612 aopPut (IC_RESULT (ic),
4613 aopGet (leftOp, 1, FALSE, FALSE),
4618 MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4619 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4620 aopPut (IC_RESULT (ic), "a", 1);
4625 /* if the lower bytes of a literal are zero skip the addition */
4626 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4628 while ((0 == ((unsigned int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4629 (skip_bytes+1 < size))
4634 D(emitcode (";", "genPlus shortcut"));
4639 if( offset >= skip_bytes )
4641 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4644 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4646 emitcode("xch", "a,b");
4647 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4648 emitcode (add, "a,b");
4651 else if (aopGetUsesAcc (leftOp, offset))
4653 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4654 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4658 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4659 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4661 aopPut (IC_RESULT (ic), "a", offset);
4662 add = "addc"; /* further adds must propagate carry */
4666 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4667 isOperandVolatile (IC_RESULT (ic), FALSE))
4670 aopPut (IC_RESULT (ic),
4671 aopGet (leftOp, offset, FALSE, FALSE),
4678 adjustArithmeticResult (ic);
4681 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4684 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4685 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4689 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4690 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4694 /*-----------------------------------------------------------------*/
4695 /* genMinusDec :- does subtraction with decrement if possible */
4696 /*-----------------------------------------------------------------*/
4698 genMinusDec (iCode * ic)
4700 unsigned int icount;
4701 unsigned int size = getDataSize (IC_RESULT (ic));
4703 /* will try to generate an increment */
4704 /* if the right side is not a literal
4706 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4709 /* if the literal value of the right hand side
4710 is greater than 4 then it is not worth it */
4711 if ((icount = (unsigned int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4714 D (emitcode (";", "genMinusDec"));
4716 /* if decrement >=16 bits in register or direct space */
4717 if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG ||
4718 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4719 (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4720 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4729 /* If the next instruction is a goto and the goto target
4730 * is <= 10 instructions previous to this, we can generate
4731 * jumps straight to that target.
4733 if (ic->next && ic->next->op == GOTO
4734 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4735 && labelRange <= 10)
4737 D (emitcode (";", "tail decrement optimized (range %d)", labelRange));
4738 tlbl = IC_LABEL (ic->next);
4743 tlbl = newiTempLabel (NULL);
4747 l = aopGet (IC_RESULT (ic), LSB, FALSE, FALSE);
4748 emitcode ("dec", "%s", l);
4750 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4751 IS_AOP_PREG (IC_RESULT (ic)))
4753 emitcode ("cjne", "%s,#0xff,%05d$", l, tlbl->key + 100);
4757 emitcode ("mov", "a,#0xff");
4758 emitcode ("cjne", "a,%s,%05d$", l, tlbl->key + 100);
4760 l = aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE);
4761 emitcode ("dec", "%s", l);
4764 if (!strcmp(l, "acc"))
4766 emitcode("jnz", "!tlabel", tlbl->key + 100);
4768 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4769 IS_AOP_PREG (IC_RESULT (ic)))
4771 emitcode ("cjne", "%s,#0xff,%05d$", l, tlbl->key + 100);
4775 emitcode ("cjne", "a,%s,%05d$", l, tlbl->key + 100);
4777 l = aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE);
4778 emitcode ("dec", "%s", l);
4782 if (!strcmp(l, "acc"))
4784 emitcode("jnz", "!tlabel", tlbl->key + 100);
4786 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4787 IS_AOP_PREG (IC_RESULT (ic)))
4789 emitcode ("cjne", "%s,#0xff,%05d$", l, tlbl->key + 100);
4793 emitcode ("cjne", "a,%s,%05d$", l, tlbl->key + 100);
4795 l = aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE);
4796 emitcode ("dec", "%s", l);
4805 /* if the sizes are greater than 1 then we cannot */
4806 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4807 AOP_SIZE (IC_LEFT (ic)) > 1)
4810 /* we can if the aops of the left & result match or
4811 if they are in registers and the registers are the
4813 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4817 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4819 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4824 l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
4829 emitcode ("dec", "%s", l);
4832 if (AOP_NEEDSACC (IC_RESULT (ic)))
4833 aopPut (IC_RESULT (ic), "a", 0);
4840 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4841 emitcode ("dec", "a");
4842 aopPut (IC_RESULT (ic), "a", 0);
4849 /*-----------------------------------------------------------------*/
4850 /* addSign - complete with sign */
4851 /*-----------------------------------------------------------------*/
4853 addSign (operand * result, int offset, int sign)
4855 int size = (getDataSize (result) - offset);
4860 emitcode ("rlc", "a");
4861 emitcode ("subb", "a,acc");
4864 aopPut (result, "a", offset++);
4871 aopPut (result, zero, offset++);
4877 /*-----------------------------------------------------------------*/
4878 /* genMinusBits - generates code for subtraction of two bits */
4879 /*-----------------------------------------------------------------*/
4881 genMinusBits (iCode * ic)
4883 symbol *lbl = newiTempLabel (NULL);
4885 D (emitcode (";", "genMinusBits"));
4887 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4889 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4890 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4891 emitcode ("cpl", "c");
4893 outBitC (IC_RESULT (ic));
4897 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4898 emitcode ("subb", "a,acc");
4899 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4900 emitcode ("inc", "a");
4902 aopPut (IC_RESULT (ic), "a", 0);
4903 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4907 /*-----------------------------------------------------------------*/
4908 /* genMinus - generates code for subtraction */
4909 /*-----------------------------------------------------------------*/
4911 genMinus (iCode * ic)
4913 int size, offset = 0;
4915 D (emitcode (";", "genMinus"));
4917 aopOp (IC_LEFT (ic), ic, FALSE);
4918 aopOp (IC_RIGHT (ic), ic, FALSE);
4919 aopOp (IC_RESULT (ic), ic, TRUE);
4921 /* special cases :- */
4922 /* if both left & right are in bit space */
4923 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4924 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4930 /* if I can do an decrement instead
4931 of subtract then GOOD for ME */
4932 if (genMinusDec (ic) == TRUE)
4935 size = getDataSize (IC_RESULT (ic));
4937 /* if literal, add a,#-lit, else normal subb */
4938 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4940 unsigned long lit = 0L;
4941 bool useCarry = FALSE;
4943 lit = ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4948 if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4950 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4951 if (!offset && !size && lit== (unsigned long) -1)
4953 emitcode ("dec", "a");
4957 /* first add without previous c */
4958 emitcode ("add", "a,#0x%02x",
4959 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4964 emitcode ("addc", "a,#0x%02x",
4965 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4967 aopPut (IC_RESULT (ic), "a", offset++);
4971 /* no need to add zeroes */
4972 if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4974 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4983 operand *leftOp, *rightOp;
4985 leftOp = IC_LEFT(ic);
4986 rightOp = IC_RIGHT(ic);
4990 if (aopGetUsesAcc(rightOp, offset)) {
4991 if (aopGetUsesAcc(leftOp, offset)) {
4994 MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4996 emitcode ("mov", "b,a");
4999 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
5000 emitcode ("subb", "a,b");
5003 /* reverse subtraction with 2's complement */
5005 emitcode( "setb", "c");
5007 emitcode( "cpl", "c");
5008 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
5009 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
5010 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
5011 emitcode("cpl", "a");
5012 if (size) /* skip if last byte */
5013 emitcode( "cpl", "c");
5016 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
5019 emitcode ("subb", "a,%s",
5020 aopGet(rightOp, offset, FALSE, TRUE));
5023 aopPut (IC_RESULT (ic), "a", offset++);
5027 adjustArithmeticResult (ic);
5030 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5031 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5032 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5036 /*-----------------------------------------------------------------*/
5037 /* genMultbits :- multiplication of bits */
5038 /*-----------------------------------------------------------------*/
5040 genMultbits (operand * left,
5044 D (emitcode (";", "genMultbits"));
5046 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5047 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5051 /*-----------------------------------------------------------------*/
5052 /* genMultOneByte : 8*8=8/16 bit multiplication */
5053 /*-----------------------------------------------------------------*/
5055 genMultOneByte (operand * left,
5060 int size = AOP_SIZE (result);
5061 bool runtimeSign, compiletimeSign;
5062 bool lUnsigned, rUnsigned, pushedB;
5064 D (emitcode (";", "genMultOneByte"));
5066 if (size < 1 || size > 2)
5068 /* this should never happen */
5069 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
5070 AOP_SIZE(result), __FILE__, lineno);
5074 /* (if two literals: the value is computed before) */
5075 /* if one literal, literal on the right */
5076 if (AOP_TYPE (left) == AOP_LIT)
5081 /* emitcode (";", "swapped left and right"); */
5083 /* if no literal, unsigned on the right: shorter code */
5084 if ( AOP_TYPE (right) != AOP_LIT
5085 && SPEC_USIGN (getSpec (operandType (left))))
5092 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5093 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5097 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
5098 no need to take care about the signedness! */
5099 || (lUnsigned && rUnsigned))
5101 /* just an unsigned 8 * 8 = 8 multiply
5103 /* emitcode (";","unsigned"); */
5104 /* TODO: check for accumulator clash between left & right aops? */
5106 if (AOP_TYPE (right) == AOP_LIT)
5108 /* moving to accumulator first helps peepholes */
5109 MOVA (aopGet (left, 0, FALSE, FALSE));
5110 MOVB (aopGet (right, 0, FALSE, FALSE));
5114 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5115 MOVA (aopGet (left, 0, FALSE, FALSE));
5118 emitcode ("mul", "ab");
5119 aopPut (result, "a", 0);
5121 aopPut (result, "b", 1);
5127 /* we have to do a signed multiply */
5128 /* emitcode (";", "signed"); */
5130 /* now sign adjust for both left & right */
5132 /* let's see what's needed: */
5133 /* apply negative sign during runtime */
5134 runtimeSign = FALSE;
5135 /* negative sign from literals */
5136 compiletimeSign = FALSE;
5140 if (AOP_TYPE(left) == AOP_LIT)
5142 /* signed literal */
5143 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5145 compiletimeSign = TRUE;
5148 /* signed but not literal */
5154 if (AOP_TYPE(right) == AOP_LIT)
5156 /* signed literal */
5157 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
5159 compiletimeSign ^= TRUE;
5162 /* signed but not literal */
5166 /* initialize F0, which stores the runtime sign */
5169 if (compiletimeSign)
5170 emitcode ("setb", "F0"); /* set sign flag */
5172 emitcode ("clr", "F0"); /* reset sign flag */
5175 /* save the signs of the operands */
5176 if (AOP_TYPE(right) == AOP_LIT)
5178 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
5180 if (!rUnsigned && val < 0)
5181 emitcode ("mov", "b,#0x%02x", -val);
5183 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5185 else /* ! literal */
5187 if (rUnsigned) /* emitcode (";", "signed"); */
5188 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5191 MOVA (aopGet (right, 0, FALSE, FALSE));
5192 lbl = newiTempLabel (NULL);
5193 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5194 emitcode ("cpl", "F0"); /* complement sign flag */
5195 emitcode ("cpl", "a"); /* 2's complement */
5196 emitcode ("inc", "a");
5198 emitcode ("mov", "b,a");
5202 if (AOP_TYPE(left) == AOP_LIT)
5204 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5206 if (!lUnsigned && val < 0)
5207 emitcode ("mov", "a,#0x%02x", -val);
5209 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5211 else /* ! literal */
5213 MOVA (aopGet (left, 0, FALSE, FALSE));
5217 lbl = newiTempLabel (NULL);
5218 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5219 emitcode ("cpl", "F0"); /* complement sign flag */
5220 emitcode ("cpl", "a"); /* 2's complement */
5221 emitcode ("inc", "a");
5226 /* now the multiplication */
5227 emitcode ("mul", "ab");
5228 if (runtimeSign || compiletimeSign)
5230 lbl = newiTempLabel (NULL);
5232 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5233 emitcode ("cpl", "a"); /* lsb 2's complement */
5235 emitcode ("inc", "a"); /* inc doesn't set carry flag */
5238 emitcode ("add", "a,#0x01"); /* this sets carry flag */
5239 emitcode ("xch", "a,b");
5240 emitcode ("cpl", "a"); /* msb 2's complement */
5241 emitcode ("addc", "a,#0x00");
5242 emitcode ("xch", "a,b");
5246 aopPut (result, "a", 0);
5248 aopPut (result, "b", 1);
5253 /*-----------------------------------------------------------------*/
5254 /* genMult - generates code for multiplication */
5255 /*-----------------------------------------------------------------*/
5257 genMult (iCode * ic)
5259 operand *left = IC_LEFT (ic);
5260 operand *right = IC_RIGHT (ic);
5261 operand *result = IC_RESULT (ic);
5263 D (emitcode (";", "genMult"));
5265 /* assign the asmops */
5266 aopOp (left, ic, FALSE);
5267 aopOp (right, ic, FALSE);
5268 aopOp (result, ic, TRUE);
5270 /* special cases first */
5272 if (AOP_TYPE (left) == AOP_CRY &&
5273 AOP_TYPE (right) == AOP_CRY)
5275 genMultbits (left, right, result);
5279 /* if both are of size == 1 */
5280 #if 0 // one of them can be a sloc shared with the result
5281 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
5283 if (getSize(operandType(left)) == 1 &&
5284 getSize(operandType(right)) == 1)
5287 genMultOneByte (left, right, result);
5291 /* should have been converted to function call */
5292 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
5293 getSize(OP_SYMBOL(right)->type));
5297 freeAsmop (result, NULL, ic, TRUE);
5298 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5299 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5302 /*-----------------------------------------------------------------*/
5303 /* genDivbits :- division of bits */
5304 /*-----------------------------------------------------------------*/
5306 genDivbits (operand * left,
5313 D(emitcode (";", "genDivbits"));
5317 /* the result must be bit */
5318 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5319 l = aopGet (left, 0, FALSE, FALSE);
5323 emitcode ("div", "ab");
5324 emitcode ("rrc", "a");
5328 aopPut (result, "c", 0);
5331 /*-----------------------------------------------------------------*/
5332 /* genDivOneByte : 8 bit division */
5333 /*-----------------------------------------------------------------*/
5335 genDivOneByte (operand * left,
5339 bool lUnsigned, rUnsigned, pushedB;
5340 bool runtimeSign, compiletimeSign;
5341 bool accuse = FALSE;
5342 bool pushedA = FALSE;
5346 D(emitcode (";", "genDivOneByte"));
5348 /* Why is it necessary that genDivOneByte() can return an int result?
5351 volatile unsigned char uc;
5352 volatile signed char sc1, sc2;
5365 In all cases a one byte result would overflow, the following cast to int
5366 would return the wrong result.
5368 Two possible solution:
5369 a) cast operands to int, if ((unsigned) / (signed)) or
5370 ((signed) / (signed))
5371 b) return an 16 bit signed int; this is what we're doing here!
5374 size = AOP_SIZE (result) - 1;
5376 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5377 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5381 /* signed or unsigned */
5382 if (lUnsigned && rUnsigned)
5384 /* unsigned is easy */
5385 MOVB (aopGet (right, 0, FALSE, FALSE));
5386 MOVA (aopGet (left, 0, FALSE, FALSE));
5387 emitcode ("div", "ab");
5388 aopPut (result, "a", 0);
5390 aopPut (result, zero, offset++);
5396 /* signed is a little bit more difficult */
5398 /* now sign adjust for both left & right */
5400 /* let's see what's needed: */
5401 /* apply negative sign during runtime */
5402 runtimeSign = FALSE;
5403 /* negative sign from literals */
5404 compiletimeSign = FALSE;
5408 if (AOP_TYPE(left) == AOP_LIT)
5410 /* signed literal */
5411 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5413 compiletimeSign = TRUE;
5416 /* signed but not literal */
5422 if (AOP_TYPE(right) == AOP_LIT)
5424 /* signed literal */
5425 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
5427 compiletimeSign ^= TRUE;
5430 /* signed but not literal */
5434 /* initialize F0, which stores the runtime sign */
5437 if (compiletimeSign)
5438 emitcode ("setb", "F0"); /* set sign flag */
5440 emitcode ("clr", "F0"); /* reset sign flag */
5443 /* save the signs of the operands */
5444 if (AOP_TYPE(right) == AOP_LIT)
5446 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
5448 if (!rUnsigned && val < 0)
5449 emitcode ("mov", "b,#0x%02x", -val);
5451 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5453 else /* ! literal */
5456 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5459 MOVA (aopGet (right, 0, FALSE, FALSE));
5460 lbl = newiTempLabel (NULL);
5461 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5462 emitcode ("cpl", "F0"); /* complement sign flag */
5463 emitcode ("cpl", "a"); /* 2's complement */
5464 emitcode ("inc", "a");
5466 emitcode ("mov", "b,a");
5470 if (AOP_TYPE(left) == AOP_LIT)
5472 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5474 if (!lUnsigned && val < 0)
5475 emitcode ("mov", "a,#0x%02x", -val);
5477 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5479 else /* ! literal */
5481 MOVA (aopGet (left, 0, FALSE, FALSE));
5485 lbl = newiTempLabel (NULL);
5486 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5487 emitcode ("cpl", "F0"); /* complement sign flag */
5488 emitcode ("cpl", "a"); /* 2's complement */
5489 emitcode ("inc", "a");
5494 /* now the division */
5495 emitcode ("div", "ab");
5497 if (runtimeSign || compiletimeSign)
5499 lbl = newiTempLabel (NULL);
5501 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5502 emitcode ("cpl", "a"); /* lsb 2's complement */
5503 emitcode ("inc", "a");
5506 accuse = aopPut (result, "a", 0);
5509 /* msb is 0x00 or 0xff depending on the sign */
5514 emitcode ("push", "acc");
5517 emitcode ("mov", "c,F0");
5518 emitcode ("subb", "a,acc");
5520 aopPut (result, "a", offset++);
5522 else /* compiletimeSign */
5524 if (aopPutUsesAcc (result, "#0xff", offset))
5526 emitcode ("push", "acc");
5530 aopPut (result, "#0xff", offset++);
5536 aopPut (result, "a", 0);
5538 aopPut (result, zero, offset++);
5542 emitcode ("pop", "acc");
5546 /*-----------------------------------------------------------------*/
5547 /* genDiv - generates code for division */
5548 /*-----------------------------------------------------------------*/
5552 operand *left = IC_LEFT (ic);
5553 operand *right = IC_RIGHT (ic);
5554 operand *result = IC_RESULT (ic);
5556 D (emitcode (";", "genDiv"));
5558 /* assign the asmops */
5559 aopOp (left, ic, FALSE);
5560 aopOp (right, ic, FALSE);
5561 aopOp (result, ic, TRUE);
5563 /* special cases first */
5565 if (AOP_TYPE (left) == AOP_CRY &&
5566 AOP_TYPE (right) == AOP_CRY)
5568 genDivbits (left, right, result);
5572 /* if both are of size == 1 */
5573 if (AOP_SIZE (left) == 1 &&
5574 AOP_SIZE (right) == 1)
5576 genDivOneByte (left, right, result);
5580 /* should have been converted to function call */
5583 freeAsmop (result, NULL, ic, TRUE);
5584 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5585 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5588 /*-----------------------------------------------------------------*/
5589 /* genModbits :- modulus of bits */
5590 /*-----------------------------------------------------------------*/
5592 genModbits (operand * left,
5599 D (emitcode (";", "genModbits"));
5603 /* the result must be bit */
5604 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5605 l = aopGet (left, 0, FALSE, FALSE);
5609 emitcode ("div", "ab");
5610 emitcode ("mov", "a,b");
5611 emitcode ("rrc", "a");
5615 aopPut (result, "c", 0);
5618 /*-----------------------------------------------------------------*/
5619 /* genModOneByte : 8 bit modulus */
5620 /*-----------------------------------------------------------------*/
5622 genModOneByte (operand * left,
5626 bool lUnsigned, rUnsigned, pushedB;
5627 bool runtimeSign, compiletimeSign;
5631 D (emitcode (";", "genModOneByte"));
5633 size = AOP_SIZE (result) - 1;
5635 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5636 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5638 /* if right is a literal, check it for 2^n */
5639 if (AOP_TYPE(right) == AOP_LIT)
5641 unsigned char val = abs((int) operandLitValue(right));
5642 symbol *lbl2 = NULL;
5646 case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5655 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5656 "modulus of unsigned char by 2^n literal shouldn't be processed here");
5657 /* because iCode should have been changed to genAnd */
5658 /* see file "SDCCopt.c", function "convertToFcall()" */
5660 MOVA (aopGet (left, 0, FALSE, FALSE));
5661 emitcode ("mov", "c,acc.7");
5662 emitcode ("anl", "a,#0x%02x", val - 1);
5663 lbl = newiTempLabel (NULL);
5664 emitcode ("jz", "%05d$", (lbl->key + 100));
5665 emitcode ("jnc", "%05d$", (lbl->key + 100));
5666 emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5672 aopPut (result, "a", 0);
5674 aopPut (result, "#0xff", offs2++);
5675 lbl2 = newiTempLabel (NULL);
5676 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5679 aopPut (result, "a", 0);
5681 aopPut (result, zero, offset++);
5695 /* signed or unsigned */
5696 if (lUnsigned && rUnsigned)
5698 /* unsigned is easy */
5699 MOVB (aopGet (right, 0, FALSE, FALSE));
5700 MOVA (aopGet (left, 0, FALSE, FALSE));
5701 emitcode ("div", "ab");
5702 aopPut (result, "b", 0);
5704 aopPut (result, zero, offset++);
5710 /* signed is a little bit more difficult */
5712 /* now sign adjust for both left & right */
5714 /* modulus: sign of the right operand has no influence on the result! */
5715 if (AOP_TYPE(right) == AOP_LIT)
5717 signed char val = (char) operandLitValue(right);
5719 if (!rUnsigned && val < 0)
5720 emitcode ("mov", "b,#0x%02x", -val);
5722 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5724 else /* not literal */
5727 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5730 MOVA (aopGet (right, 0, FALSE, FALSE));
5731 lbl = newiTempLabel (NULL);
5732 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5733 emitcode ("cpl", "a"); /* 2's complement */
5734 emitcode ("inc", "a");
5736 emitcode ("mov", "b,a");
5740 /* let's see what's needed: */
5741 /* apply negative sign during runtime */
5742 runtimeSign = FALSE;
5743 /* negative sign from literals */
5744 compiletimeSign = FALSE;
5746 /* sign adjust left side */
5747 if (AOP_TYPE(left) == AOP_LIT)
5749 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5751 if (!lUnsigned && val < 0)
5753 compiletimeSign = TRUE; /* set sign flag */
5754 emitcode ("mov", "a,#0x%02x", -val);
5757 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5759 else /* ! literal */
5761 MOVA (aopGet (left, 0, FALSE, FALSE));
5766 emitcode ("clr", "F0"); /* clear sign flag */
5768 lbl = newiTempLabel (NULL);
5769 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5770 emitcode ("setb", "F0"); /* set sign flag */
5771 emitcode ("cpl", "a"); /* 2's complement */
5772 emitcode ("inc", "a");
5777 /* now the modulus */
5778 emitcode ("div", "ab");
5780 if (runtimeSign || compiletimeSign)
5782 emitcode ("mov", "a,b");
5783 lbl = newiTempLabel (NULL);
5785 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5786 emitcode ("cpl", "a"); /* 2's complement */
5787 emitcode ("inc", "a");
5790 aopPut (result, "a", 0);
5793 /* msb is 0x00 or 0xff depending on the sign */
5796 emitcode ("mov", "c,F0");
5797 emitcode ("subb", "a,acc");
5799 aopPut (result, "a", offset++);
5801 else /* compiletimeSign */
5803 aopPut (result, "#0xff", offset++);
5808 aopPut (result, "b", 0);
5810 aopPut (result, zero, offset++);
5816 /*-----------------------------------------------------------------*/
5817 /* genMod - generates code for division */
5818 /*-----------------------------------------------------------------*/
5822 operand *left = IC_LEFT (ic);
5823 operand *right = IC_RIGHT (ic);
5824 operand *result = IC_RESULT (ic);
5826 D (emitcode (";", "genMod"));
5828 /* assign the asmops */
5829 aopOp (left, ic, FALSE);
5830 aopOp (right, ic, FALSE);
5831 aopOp (result, ic, TRUE);
5833 /* special cases first */
5835 if (AOP_TYPE (left) == AOP_CRY &&
5836 AOP_TYPE (right) == AOP_CRY)
5838 genModbits (left, right, result);
5842 /* if both are of size == 1 */
5843 if (AOP_SIZE (left) == 1 &&
5844 AOP_SIZE (right) == 1)
5846 genModOneByte (left, right, result);
5850 /* should have been converted to function call */
5854 freeAsmop (result, NULL, ic, TRUE);
5855 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5856 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5859 /*-----------------------------------------------------------------*/
5860 /* genIfxJump :- will create a jump depending on the ifx */
5861 /*-----------------------------------------------------------------*/
5863 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result, iCode *popIc)
5866 symbol *tlbl = newiTempLabel (NULL);
5869 /* if there is something to be popped then do it first */
5870 popForBranch (popIc, TRUE);
5872 D (emitcode (";", "genIfxJump"));
5874 /* if true label then we jump if condition
5878 jlbl = IC_TRUE (ic);
5879 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5880 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5884 /* false label is present */
5885 jlbl = IC_FALSE (ic);
5886 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5887 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5889 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5890 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5892 emitcode (inst, "%05d$", tlbl->key + 100);
5893 freeForBranchAsmop (result);
5894 freeForBranchAsmop (right);
5895 freeForBranchAsmop (left);
5896 emitcode ("ljmp", "%05d$", jlbl->key + 100);
5899 /* mark the icode as generated */
5903 /*-----------------------------------------------------------------*/
5904 /* genCmp :- greater or less than comparison */
5905 /*-----------------------------------------------------------------*/
5907 genCmp (operand * left, operand * right,
5908 operand * result, iCode * ifx, int sign, iCode *ic)
5910 int size, offset = 0;
5911 unsigned long lit = 0L;
5914 D (emitcode (";", "genCmp"));
5916 /* if left & right are bit variables */
5917 if (AOP_TYPE (left) == AOP_CRY &&
5918 AOP_TYPE (right) == AOP_CRY)
5920 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5921 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5925 /* subtract right from left if at the
5926 end the carry flag is set then we know that
5927 left is greater than right */
5928 size = max (AOP_SIZE (left), AOP_SIZE (right));
5930 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5931 if ((size == 1) && !sign &&
5932 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5934 symbol *lbl = newiTempLabel (NULL);
5935 emitcode ("cjne", "%s,%s,%05d$",
5936 aopGet (left, offset, FALSE, FALSE),
5937 aopGet (right, offset, FALSE, FALSE),
5943 if (AOP_TYPE (right) == AOP_LIT)
5945 lit = ulFromVal (AOP (right)->aopu.aop_lit);
5946 /* optimize if(x < 0) or if(x >= 0) */
5955 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5956 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5958 genIfxJump (ifx, "acc.7", left, right, result, ic->next);
5959 freeAsmop (right, NULL, ic, TRUE);
5960 freeAsmop (left, NULL, ic, TRUE);
5966 emitcode ("rlc", "a");
5973 int bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5974 while (size && (bytelit == 0))
5977 bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5983 MOVA (aopGet (left, offset, FALSE, FALSE));
5984 if (sign && size == 0)
5986 emitcode ("xrl", "a,#0x80");
5987 emitcode ("subb", "a,#0x%02x",
5988 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5992 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
6002 bool pushedB = FALSE;
6003 rightInB = aopGetUsesAcc(right, offset);
6007 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
6009 MOVA (aopGet (left, offset, FALSE, FALSE));
6010 if (sign && size == 0)
6012 emitcode ("xrl", "a,#0x80");
6017 MOVB (aopGet (right, offset, FALSE, FALSE));
6019 emitcode ("xrl", "b,#0x80");
6020 emitcode ("subb", "a,b");
6025 emitcode ("subb", "a,b");
6027 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
6037 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6038 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6039 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6045 /* if the result is used in the next
6046 ifx conditional branch then generate
6047 code a little differently */
6050 genIfxJump (ifx, "c", NULL, NULL, result, ic->next);
6056 /* leave the result in acc */
6060 /*-----------------------------------------------------------------*/
6061 /* genCmpGt :- greater than comparison */
6062 /*-----------------------------------------------------------------*/
6064 genCmpGt (iCode * ic, iCode * ifx)
6066 operand *left, *right, *result;
6067 sym_link *letype, *retype;
6070 D (emitcode (";", "genCmpGt"));
6072 left = IC_LEFT (ic);
6073 right = IC_RIGHT (ic);
6074 result = IC_RESULT (ic);
6076 letype = getSpec (operandType (left));
6077 retype = getSpec (operandType (right));
6078 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
6079 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
6080 /* assign the asmops */
6081 aopOp (result, ic, TRUE);
6082 aopOp (left, ic, FALSE);
6083 aopOp (right, ic, FALSE);
6085 genCmp (right, left, result, ifx, sign, ic);
6087 freeAsmop (result, NULL, ic, TRUE);
6090 /*-----------------------------------------------------------------*/
6091 /* genCmpLt - less than comparisons */
6092 /*-----------------------------------------------------------------*/
6094 genCmpLt (iCode * ic, iCode * ifx)
6096 operand *left, *right, *result;
6097 sym_link *letype, *retype;
6100 D (emitcode (";", "genCmpLt"));
6102 left = IC_LEFT (ic);
6103 right = IC_RIGHT (ic);
6104 result = IC_RESULT (ic);
6106 letype = getSpec (operandType (left));
6107 retype = getSpec (operandType (right));
6108 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
6109 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
6110 /* assign the asmops */
6111 aopOp (result, ic, TRUE);
6112 aopOp (left, ic, FALSE);
6113 aopOp (right, ic, FALSE);
6115 genCmp (left, right, result, ifx, sign, ic);
6117 freeAsmop (result, NULL, ic, TRUE);
6120 /*-----------------------------------------------------------------*/
6121 /* gencjneshort - compare and jump if not equal */
6122 /*-----------------------------------------------------------------*/
6124 gencjneshort (operand * left, operand * right, symbol * lbl)
6126 int size = max (AOP_SIZE (left), AOP_SIZE (right));
6128 unsigned long lit = 0L;
6130 D (emitcode (";", "gencjneshort"));
6132 /* if the left side is a literal or
6133 if the right is in a pointer register and left
6135 if ((AOP_TYPE (left) == AOP_LIT) ||
6136 (AOP_TYPE (left) == AOP_IMMD) ||
6137 (AOP_TYPE (left) == AOP_DIR) ||
6138 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6145 if (AOP_TYPE (right) == AOP_LIT)
6146 lit = ulFromVal (AOP (right)->aopu.aop_lit);
6148 /* if the right side is a literal then anything goes */
6149 if (AOP_TYPE (right) == AOP_LIT &&
6150 AOP_TYPE (left) != AOP_DIR &&
6151 AOP_TYPE (left) != AOP_IMMD)
6155 emitcode ("cjne", "%s,%s,%05d$",
6156 aopGet (left, offset, FALSE, FALSE),
6157 aopGet (right, offset, FALSE, FALSE),
6163 /* if the right side is in a register or in direct space or
6164 if the left is a pointer register & right is not */
6165 else if (AOP_TYPE (right) == AOP_REG ||
6166 AOP_TYPE (right) == AOP_DIR ||
6167 AOP_TYPE (right) == AOP_LIT ||
6168 AOP_TYPE (right) == AOP_IMMD ||
6169 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6170 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6174 MOVA (aopGet (left, offset, FALSE, FALSE));
6175 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6176 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6177 emitcode ("jnz", "%05d$", lbl->key + 100);
6179 emitcode ("cjne", "a,%s,%05d$",
6180 aopGet (right, offset, FALSE, TRUE),
6187 /* right is a pointer reg need both a & b */
6190 //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
6191 wassertl(!BINUSE, "B was in use");
6192 MOVB (aopGet (left, offset, FALSE, FALSE));
6193 MOVA (aopGet (right, offset, FALSE, FALSE));
6194 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
6200 /*-----------------------------------------------------------------*/
6201 /* gencjne - compare and jump if not equal */
6202 /*-----------------------------------------------------------------*/
6204 gencjne (operand * left, operand * right, symbol * lbl, bool useCarry)
6206 symbol *tlbl = newiTempLabel (NULL);
6208 D (emitcode (";", "gencjne"));
6210 gencjneshort (left, right, lbl);
6216 emitcode ("sjmp", "%05d$", tlbl->key + 100);
6225 /*-----------------------------------------------------------------*/
6226 /* genCmpEq - generates code for equal to */
6227 /*-----------------------------------------------------------------*/
6229 genCmpEq (iCode * ic, iCode * ifx)
6231 bool swappedLR = FALSE;
6232 operand *left, *right, *result;
6233 iCode * popIc = ic->next;
6235 D (emitcode (";", "genCmpEq"));
6237 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6238 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6239 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6241 /* if literal, literal on the right or
6242 if the right is in a pointer register and left
6244 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6245 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6247 operand *t = IC_RIGHT (ic);
6248 IC_RIGHT (ic) = IC_LEFT (ic);
6253 if (ifx && !AOP_SIZE (result))
6256 /* if they are both bit variables */
6257 if (AOP_TYPE (left) == AOP_CRY &&
6258 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6260 if (AOP_TYPE (right) == AOP_LIT)
6262 unsigned long lit = ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6265 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6266 emitcode ("cpl", "c");
6270 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6274 emitcode ("clr", "c");
6276 /* AOP_TYPE(right) == AOP_CRY */
6280 symbol *lbl = newiTempLabel (NULL);
6281 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6282 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6283 emitcode ("cpl", "c");
6286 /* if true label then we jump if condition
6288 tlbl = newiTempLabel (NULL);
6291 emitcode ("jnc", "%05d$", tlbl->key + 100);
6292 freeForBranchAsmop (result);
6293 freeForBranchAsmop (right);
6294 freeForBranchAsmop (left);
6295 popForBranch (popIc, FALSE);
6296 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6300 emitcode ("jc", "%05d$", tlbl->key + 100);
6301 freeForBranchAsmop (result);
6302 freeForBranchAsmop (right);
6303 freeForBranchAsmop (left);
6304 popForBranch (popIc, FALSE);
6305 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6311 tlbl = newiTempLabel (NULL);
6312 gencjneshort (left, right, tlbl);
6315 freeForBranchAsmop (result);
6316 freeForBranchAsmop (right);
6317 freeForBranchAsmop (left);
6318 popForBranch (popIc, FALSE);
6319 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6324 symbol *lbl = newiTempLabel (NULL);
6325 emitcode ("sjmp", "%05d$", lbl->key + 100);
6327 freeForBranchAsmop (result);
6328 freeForBranchAsmop (right);
6329 freeForBranchAsmop (left);
6330 popForBranch (popIc, FALSE);
6331 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6335 /* mark the icode as generated */
6340 /* if they are both bit variables */
6341 if (AOP_TYPE (left) == AOP_CRY &&
6342 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6344 if (AOP_TYPE (right) == AOP_LIT)
6346 unsigned long lit = ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6349 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6350 emitcode ("cpl", "c");
6354 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6358 emitcode ("clr", "c");
6360 /* AOP_TYPE(right) == AOP_CRY */
6364 symbol *lbl = newiTempLabel (NULL);
6365 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6366 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6367 emitcode ("cpl", "c");
6371 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6378 genIfxJump (ifx, "c", left, right, result, popIc);
6381 /* if the result is used in an arithmetic operation
6382 then put the result in place */
6387 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6389 gencjne (left, right, newiTempLabel (NULL), TRUE);
6390 aopPut (result, "c", 0);
6393 gencjne (left, right, newiTempLabel (NULL), FALSE);
6396 genIfxJump (ifx, "a", left, right, result, popIc);
6399 /* if the result is used in an arithmetic operation
6400 then put the result in place */
6401 if (AOP_TYPE (result) != AOP_CRY)
6403 /* leave the result in acc */
6407 freeAsmop (result, NULL, ic, TRUE);
6410 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6411 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6415 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6416 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6420 /*-----------------------------------------------------------------*/
6421 /* ifxForOp - returns the icode containing the ifx for operand */
6422 /*-----------------------------------------------------------------*/
6424 ifxForOp (operand * op, iCode * ic)
6428 /* if true symbol then needs to be assigned */
6429 if (IS_TRUE_SYMOP (op))
6432 /* if this has register type condition and
6433 while skipping ipop's (see bug 1509084),
6434 the next instruction is ifx with the same operand
6435 and live to of the operand is upto the ifx only then */
6436 for (ifxIc = ic->next; ifxIc && ifxIc->op == IPOP; ifxIc = ifxIc->next);
6437 if (ifxIc && ifxIc->op == IFX &&
6438 IC_COND (ifxIc)->key == op->key &&
6439 OP_SYMBOL (op)->liveTo <= ifxIc->seq)
6445 /*-----------------------------------------------------------------*/
6446 /* hasInc - operand is incremented before any other use */
6447 /*-----------------------------------------------------------------*/
6449 hasInc (operand *op, iCode *ic, int osize)
6451 sym_link *type = operandType(op);
6452 sym_link *retype = getSpec (type);
6453 iCode *lic = ic->next;
6456 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6457 if (!IS_SYMOP(op)) return NULL;
6459 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6460 if (IS_AGGREGATE(type->next)) return NULL;
6461 if (osize != (isize = getSize(type->next))) return NULL;
6465 /* if operand of the form op = op + <sizeof *op> */
6466 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6467 isOperandEqual(IC_RESULT(lic),op) &&
6468 isOperandLiteral(IC_RIGHT(lic)) &&
6469 operandLitValue(IC_RIGHT(lic)) == isize)
6473 /* if the operand used or deffed */
6474 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key)
6478 /* if GOTO or IFX */
6479 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6485 /*-----------------------------------------------------------------*/
6486 /* genAndOp - for && operation */
6487 /*-----------------------------------------------------------------*/
6489 genAndOp (iCode * ic)
6491 operand *left, *right, *result;
6494 D (emitcode (";", "genAndOp"));
6496 /* note here that && operations that are in an
6497 if statement are taken away by backPatchLabels
6498 only those used in arthmetic operations remain */
6499 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6500 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6501 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6503 /* if both are bit variables */
6504 if (AOP_TYPE (left) == AOP_CRY &&
6505 AOP_TYPE (right) == AOP_CRY)
6507 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6508 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6513 tlbl = newiTempLabel (NULL);
6515 emitcode ("jz", "%05d$", tlbl->key + 100);
6521 freeAsmop (result, NULL, ic, TRUE);
6522 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6523 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6527 /*-----------------------------------------------------------------*/
6528 /* genOrOp - for || operation */
6529 /*-----------------------------------------------------------------*/
6531 genOrOp (iCode * ic)
6533 operand *left, *right, *result;
6536 D (emitcode (";", "genOrOp"));
6538 /* note here that || operations that are in an
6539 if statement are taken away by backPatchLabels
6540 only those used in arthmetic operations remain */
6541 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6542 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6543 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6545 /* if both are bit variables */
6546 if (AOP_TYPE (left) == AOP_CRY &&
6547 AOP_TYPE (right) == AOP_CRY)
6549 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6550 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6555 tlbl = newiTempLabel (NULL);
6557 emitcode ("jnz", "%05d$", tlbl->key + 100);
6563 freeAsmop (result, NULL, ic, TRUE);
6564 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6565 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6568 /*-----------------------------------------------------------------*/
6569 /* isLiteralBit - test if lit == 2^n */
6570 /*-----------------------------------------------------------------*/
6572 isLiteralBit (unsigned long lit)
6574 unsigned long pw[32] =
6575 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6576 0x100L, 0x200L, 0x400L, 0x800L,
6577 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6578 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6579 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6580 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6581 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6584 for (idx = 0; idx < 32; idx++)
6590 /*-----------------------------------------------------------------*/
6591 /* continueIfTrue - */
6592 /*-----------------------------------------------------------------*/
6594 continueIfTrue (iCode * ic)
6597 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6601 /*-----------------------------------------------------------------*/
6603 /*-----------------------------------------------------------------*/
6605 jumpIfTrue (iCode * ic)
6608 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6612 /*-----------------------------------------------------------------*/
6613 /* jmpTrueOrFalse - */
6614 /*-----------------------------------------------------------------*/
6616 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6618 // ugly but optimized by peephole
6621 symbol *nlbl = newiTempLabel (NULL);
6622 emitcode ("sjmp", "%05d$", nlbl->key + 100);
6624 freeForBranchAsmop (result);
6625 freeForBranchAsmop (right);
6626 freeForBranchAsmop (left);
6627 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6632 freeForBranchAsmop (result);
6633 freeForBranchAsmop (right);
6634 freeForBranchAsmop (left);
6635 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6641 /*-----------------------------------------------------------------*/
6642 /* genAnd - code for and */
6643 /*-----------------------------------------------------------------*/
6645 genAnd (iCode * ic, iCode * ifx)
6647 operand *left, *right, *result;
6648 int size, offset = 0;
6649 unsigned long lit = 0L;
6653 D (emitcode (";", "genAnd"));
6655 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6656 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6657 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6660 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
6662 AOP_TYPE (left), AOP_TYPE (right));
6663 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
6665 AOP_SIZE (left), AOP_SIZE (right));
6668 /* if left is a literal & right is not then exchange them */
6669 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6670 AOP_NEEDSACC (left))
6672 operand *tmp = right;
6677 /* if result = right then exchange left and right */
6678 if (sameRegs (AOP (result), AOP (right)))
6680 operand *tmp = right;
6685 /* if right is bit then exchange them */
6686 if (AOP_TYPE (right) == AOP_CRY &&
6687 AOP_TYPE (left) != AOP_CRY)
6689 operand *tmp = right;
6693 if (AOP_TYPE (right) == AOP_LIT)
6694 lit = ulFromVal (AOP (right)->aopu.aop_lit);
6696 size = AOP_SIZE (result);
6699 // result = bit & yy;
6700 if (AOP_TYPE (left) == AOP_CRY)
6702 // c = bit & literal;
6703 if (AOP_TYPE (right) == AOP_LIT)
6707 if (size && sameRegs (AOP (result), AOP (left)))
6710 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6715 if (size && (AOP_TYPE (result) == AOP_CRY))
6717 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6720 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6725 emitcode ("clr", "c");
6730 if (AOP_TYPE (right) == AOP_CRY)
6733 if (IS_OP_ACCUSE (left))
6735 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6739 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6740 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6746 MOVA (aopGet (right, 0, FALSE, FALSE));
6748 emitcode ("rrc", "a");
6749 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6757 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6758 genIfxJump (ifx, "c", left, right, result, ic->next);
6762 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6763 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6764 if ((AOP_TYPE (right) == AOP_LIT) &&
6765 (AOP_TYPE (result) == AOP_CRY) &&
6766 (AOP_TYPE (left) != AOP_CRY))
6768 int posbit = isLiteralBit (lit);
6773 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6777 switch (posbit & 0x07)
6779 case 0: emitcode ("rrc", "a");
6781 case 7: emitcode ("rlc", "a");
6783 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6792 SNPRINTF (buffer, sizeof(buffer),
6793 "acc.%d", posbit & 0x07);
6794 genIfxJump (ifx, buffer, left, right, result, ic->next);
6797 {// what is this case? just found it in ds390/gen.c
6798 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6805 symbol *tlbl = newiTempLabel (NULL);
6806 int sizel = AOP_SIZE (left);
6808 emitcode ("setb", "c");
6811 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6813 MOVA (aopGet (left, offset, FALSE, FALSE));
6815 if ((posbit = isLiteralBit (bytelit)) != 0)
6816 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6819 if (bytelit != 0x0FFL)
6820 emitcode ("anl", "a,%s",
6821 aopGet (right, offset, FALSE, TRUE));
6822 emitcode ("jnz", "%05d$", tlbl->key + 100);
6827 // bit = left & literal
6830 emitcode ("clr", "c");
6833 // if(left & literal)
6837 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6847 /* if left is same as result */
6848 if (sameRegs (AOP (result), AOP (left)))
6850 for (; size--; offset++)
6852 if (AOP_TYPE (right) == AOP_LIT)
6854 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6855 if (bytelit == 0x0FF)
6857 /* dummy read of volatile operand */
6858 if (isOperandVolatile (left, FALSE))
6859 MOVA (aopGet (left, offset, FALSE, FALSE));
6863 else if (bytelit == 0)
6865 aopPut (result, zero, offset);
6867 else if (IS_AOP_PREG (result))
6869 MOVA (aopGet (left, offset, FALSE, TRUE));
6870 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6871 aopPut (result, "a", offset);
6874 emitcode ("anl", "%s,%s",
6875 aopGet (left, offset, FALSE, TRUE),
6876 aopGet (right, offset, FALSE, FALSE));
6880 if (AOP_TYPE (left) == AOP_ACC)
6883 emitcode("mov", "a,b");
6884 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6886 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6888 MOVB (aopGet (left, offset, FALSE, FALSE));
6889 MOVA (aopGet (right, offset, FALSE, FALSE));
6890 emitcode ("anl", "a,b");
6891 aopPut (result, "a", offset);
6893 else if (aopGetUsesAcc (left, offset))
6895 MOVA (aopGet (left, offset, FALSE, FALSE));
6896 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6897 aopPut (result, "a", offset);
6901 MOVA (aopGet (right, offset, FALSE, FALSE));
6902 if (IS_AOP_PREG (result))
6904 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6905 aopPut (result, "a", offset);
6908 emitcode ("anl", "%s,a", aopGet (left, offset, FALSE, TRUE));
6915 // left & result in different registers
6916 if (AOP_TYPE (result) == AOP_CRY)
6919 // if(size), result in bit
6920 // if(!size && ifx), conditional oper: if(left & right)
6921 symbol *tlbl = newiTempLabel (NULL);
6922 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6924 emitcode ("setb", "c");
6927 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6928 && AOP_TYPE(left)==AOP_ACC)
6931 emitcode("mov", "a,b");
6932 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6934 else if (AOP_TYPE(left)==AOP_ACC)
6938 bool pushedB = pushB ();
6939 emitcode("mov", "b,a");
6940 MOVA (aopGet (right, offset, FALSE, FALSE));
6941 emitcode("anl", "a,b");
6946 MOVA (aopGet (right, offset, FALSE, FALSE));
6947 emitcode("anl", "a,b");
6950 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6952 MOVB (aopGet (left, offset, FALSE, FALSE));
6953 MOVA (aopGet (right, offset, FALSE, FALSE));
6954 emitcode ("anl", "a,b");
6956 else if (aopGetUsesAcc (left, offset))
6958 MOVA (aopGet (left, offset, FALSE, FALSE));
6959 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6963 MOVA (aopGet (right, offset, FALSE, FALSE));
6964 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6967 emitcode ("jnz", "%05d$", tlbl->key + 100);
6977 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6983 for (; (size--); offset++)
6986 // result = left & right
6987 if (AOP_TYPE (right) == AOP_LIT)
6989 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6990 if (bytelit == 0x0FF)
6993 aopGet (left, offset, FALSE, FALSE),
6997 else if (bytelit == 0)
6999 /* dummy read of volatile operand */
7000 if (isOperandVolatile (left, FALSE))
7001 MOVA (aopGet (left, offset, FALSE, FALSE));
7002 aopPut (result, zero, offset);
7005 else if (AOP_TYPE (left) == AOP_ACC)
7009 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7010 aopPut (result, "a", offset);
7015 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
7016 aopPut (result, "b", offset);
7021 // faster than result <- left, anl result,right
7022 // and better if result is SFR
7023 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7024 && AOP_TYPE(left)==AOP_ACC)
7027 emitcode("mov", "a,b");
7028 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7030 else if (AOP_TYPE(left)==AOP_ACC)
7034 bool pushedB = pushB ();
7035 emitcode("mov", "b,a");
7036 MOVA (aopGet (right, offset, FALSE, FALSE));
7037 emitcode("anl", "a,b");
7042 MOVA (aopGet (right, offset, FALSE, FALSE));
7043 emitcode("anl", "a,b");
7046 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7048 MOVB (aopGet (left, offset, FALSE, FALSE));
7049 MOVA (aopGet (right, offset, FALSE, FALSE));
7050 emitcode ("anl", "a,b");
7052 else if (aopGetUsesAcc (left, offset))
7054 MOVA (aopGet (left, offset, FALSE, FALSE));
7055 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7059 MOVA (aopGet (right, offset, FALSE, FALSE));
7060 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7062 aopPut (result, "a", offset);
7068 freeAsmop (result, NULL, ic, TRUE);
7069 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7070 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7073 /*-----------------------------------------------------------------*/
7074 /* genOr - code for or */
7075 /*-----------------------------------------------------------------*/
7077 genOr (iCode * ic, iCode * ifx)
7079 operand *left, *right, *result;
7080 int size, offset = 0;
7081 unsigned long lit = 0L;
7084 D (emitcode (";", "genOr"));
7086 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7087 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7088 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7091 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
7093 AOP_TYPE (left), AOP_TYPE (right));
7094 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
7096 AOP_SIZE (left), AOP_SIZE (right));
7099 /* if left is a literal & right is not then exchange them */
7100 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7101 AOP_NEEDSACC (left))
7103 operand *tmp = right;
7108 /* if result = right then exchange them */
7109 if (sameRegs (AOP (result), AOP (right)))
7111 operand *tmp = right;
7116 /* if right is bit then exchange them */
7117 if (AOP_TYPE (right) == AOP_CRY &&
7118 AOP_TYPE (left) != AOP_CRY)
7120 operand *tmp = right;
7124 if (AOP_TYPE (right) == AOP_LIT)
7125 lit = ulFromVal (AOP (right)->aopu.aop_lit);
7127 size = AOP_SIZE (result);
7131 if (AOP_TYPE (left) == AOP_CRY)
7133 if (AOP_TYPE (right) == AOP_LIT)
7135 // c = bit | literal;
7138 // lit != 0 => result = 1
7139 if (AOP_TYPE (result) == AOP_CRY)
7142 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7144 continueIfTrue (ifx);
7147 emitcode ("setb", "c");
7151 // lit == 0 => result = left
7152 if (size && sameRegs (AOP (result), AOP (left)))
7154 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7159 if (AOP_TYPE (right) == AOP_CRY)
7162 if (IS_OP_ACCUSE (left))
7164 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
7168 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7169 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7175 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7177 symbol *tlbl = newiTempLabel (NULL);
7178 emitcode ("jb", "%s,%05d$",
7179 AOP (left)->aopu.aop_dir, tlbl->key + 100);
7181 emitcode ("jnz", "%05d$", tlbl->key + 100);
7182 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7188 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7197 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7198 genIfxJump (ifx, "c", left, right, result, ic->next);
7202 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7203 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7204 if ((AOP_TYPE (right) == AOP_LIT) &&
7205 (AOP_TYPE (result) == AOP_CRY) &&
7206 (AOP_TYPE (left) != AOP_CRY))
7212 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7214 continueIfTrue (ifx);
7219 // lit = 0, result = boolean(left)
7221 emitcode ("setb", "c");
7225 symbol *tlbl = newiTempLabel (NULL);
7226 emitcode ("jnz", "%05d$", tlbl->key + 100);
7232 genIfxJump (ifx, "a", left, right, result, ic->next);
7240 /* if left is same as result */
7241 if (sameRegs (AOP (result), AOP (left)))
7243 for (; size--; offset++)
7245 if (AOP_TYPE (right) == AOP_LIT)
7247 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7250 /* dummy read of volatile operand */
7251 if (isOperandVolatile (left, FALSE))
7252 MOVA (aopGet (left, offset, FALSE, FALSE));
7256 else if (bytelit == 0x0FF)
7258 aopPut (result, "#0xff", offset);
7260 else if (IS_AOP_PREG (left))
7262 MOVA (aopGet (left, offset, FALSE, TRUE));
7263 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7264 aopPut (result, "a", offset);
7268 emitcode ("orl", "%s,%s",
7269 aopGet (left, offset, FALSE, TRUE),
7270 aopGet (right, offset, FALSE, FALSE));
7275 if (AOP_TYPE (left) == AOP_ACC)
7278 emitcode("mov", "a,b");
7279 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7281 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7283 MOVB (aopGet (left, offset, FALSE, FALSE));
7284 MOVA (aopGet (right, offset, FALSE, FALSE));
7285 emitcode ("orl", "a,b");
7286 aopPut (result, "a", offset);
7288 else if (aopGetUsesAcc (left, offset))
7290 MOVA (aopGet (left, offset, FALSE, FALSE));
7291 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7292 aopPut (result, "a", offset);
7296 MOVA (aopGet (right, offset, FALSE, FALSE));
7297 if (IS_AOP_PREG (left))
7299 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7300 aopPut (result, "a", offset);
7304 emitcode ("orl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7312 // left & result in different registers
7313 if (AOP_TYPE (result) == AOP_CRY)
7316 // if(size), result in bit
7317 // if(!size && ifx), conditional oper: if(left | right)
7318 symbol *tlbl = newiTempLabel (NULL);
7319 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7321 emitcode ("setb", "c");
7324 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7325 && AOP_TYPE(left)==AOP_ACC)
7328 emitcode("mov", "a,b");
7329 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7331 else if (AOP_TYPE(left)==AOP_ACC)
7335 bool pushedB = pushB ();
7336 emitcode("mov", "b,a");
7337 MOVA (aopGet (right, offset, FALSE, FALSE));
7338 emitcode("orl", "a,b");
7343 MOVA (aopGet (right, offset, FALSE, FALSE));
7344 emitcode("orl", "a,b");
7347 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7349 MOVB (aopGet (left, offset, FALSE, FALSE));
7350 MOVA (aopGet (right, offset, FALSE, FALSE));
7351 emitcode ("orl", "a,b");
7353 else if (aopGetUsesAcc (left, offset))
7355 MOVA (aopGet (left, offset, FALSE, FALSE));
7356 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7360 MOVA (aopGet (right, offset, FALSE, FALSE));
7361 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7364 emitcode ("jnz", "%05d$", tlbl->key + 100);
7374 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7380 for (; (size--); offset++)
7383 // result = left | right
7384 if (AOP_TYPE (right) == AOP_LIT)
7386 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7390 aopGet (left, offset, FALSE, FALSE),
7394 else if (bytelit == 0x0FF)
7396 /* dummy read of volatile operand */
7397 if (isOperandVolatile (left, FALSE))
7398 MOVA (aopGet (left, offset, FALSE, FALSE));
7399 aopPut (result, "#0xff", offset);
7403 // faster than result <- left, orl result,right
7404 // and better if result is SFR
7405 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7406 && AOP_TYPE(left)==AOP_ACC)
7409 emitcode("mov", "a,b");
7410 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7412 else if (AOP_TYPE(left)==AOP_ACC)
7416 bool pushedB = pushB ();
7417 emitcode("mov", "b,a");
7418 MOVA (aopGet (right, offset, FALSE, FALSE));
7419 emitcode("orl", "a,b");
7424 MOVA (aopGet (right, offset, FALSE, FALSE));
7425 emitcode("orl", "a,b");
7428 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7430 MOVB (aopGet (left, offset, FALSE, FALSE));
7431 MOVA (aopGet (right, offset, FALSE, FALSE));
7432 emitcode ("orl", "a,b");
7434 else if (aopGetUsesAcc (left, offset))
7436 MOVA (aopGet (left, offset, FALSE, FALSE));
7437 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7441 MOVA (aopGet (right, offset, FALSE, FALSE));
7442 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7444 aopPut (result, "a", offset);
7450 freeAsmop (result, NULL, ic, TRUE);
7451 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7452 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7455 /*-----------------------------------------------------------------*/
7456 /* genXor - code for xclusive or */
7457 /*-----------------------------------------------------------------*/
7459 genXor (iCode * ic, iCode * ifx)
7461 operand *left, *right, *result;
7462 int size, offset = 0;
7463 unsigned long lit = 0L;
7466 D (emitcode (";", "genXor"));
7468 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7469 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7470 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7473 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
7475 AOP_TYPE (left), AOP_TYPE (right));
7476 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
7478 AOP_SIZE (left), AOP_SIZE (right));
7481 /* if left is a literal & right is not ||
7482 if left needs acc & right does not */
7483 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7484 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7486 operand *tmp = right;
7491 /* if result = right then exchange them */
7492 if (sameRegs (AOP (result), AOP (right)))
7494 operand *tmp = right;
7499 /* if right is bit then exchange them */
7500 if (AOP_TYPE (right) == AOP_CRY &&
7501 AOP_TYPE (left) != AOP_CRY)
7503 operand *tmp = right;
7508 if (AOP_TYPE (right) == AOP_LIT)
7509 lit = ulFromVal (AOP (right)->aopu.aop_lit);
7511 size = AOP_SIZE (result);
7515 if (AOP_TYPE (left) == AOP_CRY)
7517 if (AOP_TYPE (right) == AOP_LIT)
7519 // c = bit & literal;
7522 // lit>>1 != 0 => result = 1
7523 if (AOP_TYPE (result) == AOP_CRY)
7526 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7528 continueIfTrue (ifx);
7531 emitcode ("setb", "c");
7538 // lit == 0, result = left
7539 if (size && sameRegs (AOP (result), AOP (left)))
7541 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7545 // lit == 1, result = not(left)
7546 if (size && sameRegs (AOP (result), AOP (left)))
7548 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7553 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7554 emitcode ("cpl", "c");
7562 symbol *tlbl = newiTempLabel (NULL);
7563 if (AOP_TYPE (right) == AOP_CRY)
7566 if (IS_OP_ACCUSE (left))
7567 {// left already is in the carry
7568 operand *tmp = right;
7582 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7583 emitcode ("cpl", "c");
7591 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7592 genIfxJump (ifx, "c", left, right, result, ic->next);
7596 /* if left is same as result */
7597 if (sameRegs (AOP (result), AOP (left)))
7599 for (; size--; offset++)
7601 if (AOP_TYPE (right) == AOP_LIT)
7603 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7606 /* dummy read of volatile operand */
7607 if (isOperandVolatile (left, FALSE))
7608 MOVA (aopGet (left, offset, FALSE, FALSE));
7612 else if (IS_AOP_PREG (left))
7614 MOVA (aopGet (left, offset, FALSE, TRUE));
7615 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7616 aopPut (result, "a", offset);
7620 emitcode ("xrl", "%s,%s",
7621 aopGet (left, offset, FALSE, TRUE),
7622 aopGet (right, offset, FALSE, FALSE));
7627 if (AOP_TYPE (left) == AOP_ACC)
7630 emitcode("mov", "a,b");
7631 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7633 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7635 MOVB (aopGet (left, offset, FALSE, FALSE));
7636 MOVA (aopGet (right, offset, FALSE, FALSE));
7637 emitcode ("xrl", "a,b");
7638 aopPut (result, "a", offset);
7640 else if (aopGetUsesAcc (left, offset))
7642 MOVA (aopGet (left, offset, FALSE, FALSE));
7643 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7644 aopPut (result, "a", offset);
7648 MOVA (aopGet (right, offset, FALSE, FALSE));
7649 if (IS_AOP_PREG (left))
7651 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7652 aopPut (result, "a", offset);
7655 emitcode ("xrl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7662 // left & result in different registers
7663 if (AOP_TYPE (result) == AOP_CRY)
7666 // if(size), result in bit
7667 // if(!size && ifx), conditional oper: if(left ^ right)
7668 symbol *tlbl = newiTempLabel (NULL);
7669 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7672 emitcode ("setb", "c");
7675 if ((AOP_TYPE (right) == AOP_LIT) &&
7676 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7678 MOVA (aopGet (left, offset, FALSE, FALSE));
7680 else if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7681 && AOP_TYPE(left)==AOP_ACC)
7684 emitcode("mov", "a,b");
7685 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7687 else if (AOP_TYPE(left)==AOP_ACC)
7691 bool pushedB = pushB ();
7692 emitcode("mov", "b,a");
7693 MOVA (aopGet (right, offset, FALSE, FALSE));
7694 emitcode("xrl", "a,b");
7699 MOVA (aopGet (right, offset, FALSE, FALSE));
7700 emitcode("xrl", "a,b");
7703 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7705 MOVB (aopGet (left, offset, FALSE, FALSE));
7706 MOVA (aopGet (right, offset, FALSE, FALSE));
7707 emitcode ("xrl", "a,b");
7709 else if (aopGetUsesAcc (left, offset))
7711 MOVA (aopGet (left, offset, FALSE, FALSE));
7712 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7716 MOVA (aopGet (right, offset, FALSE, FALSE));
7717 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7720 emitcode ("jnz", "%05d$", tlbl->key + 100);
7730 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7734 for (; (size--); offset++)
7737 // result = left ^ right
7738 if (AOP_TYPE (right) == AOP_LIT)
7740 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7744 aopGet (left, offset, FALSE, FALSE),
7749 // faster than result <- left, xrl result,right
7750 // and better if result is SFR
7751 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7752 && AOP_TYPE(left)==AOP_ACC)
7755 emitcode("mov", "a,b");
7756 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7758 else if (AOP_TYPE(left)==AOP_ACC)
7762 bool pushedB = pushB ();
7763 emitcode("mov", "b,a");
7764 MOVA (aopGet (right, offset, FALSE, FALSE));
7765 emitcode("xrl", "a,b");
7770 MOVA (aopGet (right, offset, FALSE, FALSE));
7771 emitcode("xrl", "a,b");
7774 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7776 MOVB (aopGet (left, offset, FALSE, FALSE));
7777 MOVA (aopGet (right, offset, FALSE, FALSE));
7778 emitcode ("xrl", "a,b");
7780 else if (aopGetUsesAcc (left, offset))
7782 MOVA (aopGet (left, offset, FALSE, FALSE));
7783 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7787 MOVA (aopGet (right, offset, FALSE, FALSE));
7788 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7790 aopPut (result, "a", offset);
7796 freeAsmop (result, NULL, ic, TRUE);
7797 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7798 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7801 /*-----------------------------------------------------------------*/
7802 /* genInline - write the inline code out */
7803 /*-----------------------------------------------------------------*/
7805 genInline (iCode * ic)
7807 char *buffer, *bp, *bp1;
7808 bool inComment = FALSE;
7810 D (emitcode (";", "genInline"));
7812 _G.inLine += (!options.asmpeep);
7814 buffer = bp = bp1 = Safe_strdup (IC_INLINE (ic));
7816 /* emit each line as a code */
7834 /* Add \n for labels, not dirs such as c:\mydir */
7835 if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
7853 _G.inLine -= (!options.asmpeep);
7856 /*-----------------------------------------------------------------*/
7857 /* genRRC - rotate right with carry */
7858 /*-----------------------------------------------------------------*/
7862 operand *left, *result;
7866 D (emitcode (";", "genRRC"));
7868 /* rotate right with carry */
7869 left = IC_LEFT (ic);
7870 result = IC_RESULT (ic);
7871 aopOp (left, ic, FALSE);
7872 aopOp (result, ic, FALSE);
7874 /* move it to the result */
7875 size = AOP_SIZE (result);
7877 if (size == 1) { /* special case for 1 byte */
7878 l = aopGet (left, offset, FALSE, FALSE);
7880 emitcode ("rr", "a");
7883 /* no need to clear carry, bit7 will be written later */
7886 l = aopGet (left, offset, FALSE, FALSE);
7888 emitcode ("rrc", "a");
7889 if (AOP_SIZE (result) > 1)
7890 aopPut (result, "a", offset--);
7892 /* now we need to put the carry into the
7893 highest order byte of the result */
7894 if (AOP_SIZE (result) > 1)
7896 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7899 emitcode ("mov", "acc.7,c");
7901 aopPut (result, "a", AOP_SIZE (result) - 1);
7902 freeAsmop (result, NULL, ic, TRUE);
7903 freeAsmop (left, NULL, ic, TRUE);
7906 /*-----------------------------------------------------------------*/
7907 /* genRLC - generate code for rotate left with carry */
7908 /*-----------------------------------------------------------------*/
7912 operand *left, *result;
7916 D (emitcode (";", "genRLC"));
7918 /* rotate right with carry */
7919 left = IC_LEFT (ic);
7920 result = IC_RESULT (ic);
7921 aopOp (left, ic, FALSE);
7922 aopOp (result, ic, FALSE);
7924 /* move it to the result */
7925 size = AOP_SIZE (result);
7929 l = aopGet (left, offset, FALSE, FALSE);
7931 if (size == 0) { /* special case for 1 byte */
7935 emitcode("rlc","a"); /* bit0 will be written later */
7936 if (AOP_SIZE (result) > 1)
7938 aopPut (result, "a", offset++);
7943 l = aopGet (left, offset, FALSE, FALSE);
7945 emitcode ("rlc", "a");
7946 if (AOP_SIZE (result) > 1)
7947 aopPut (result, "a", offset++);
7950 /* now we need to put the carry into the
7951 highest order byte of the result */
7952 if (AOP_SIZE (result) > 1)
7954 l = aopGet (result, 0, FALSE, FALSE);
7957 emitcode ("mov", "acc.0,c");
7959 aopPut (result, "a", 0);
7960 freeAsmop (result, NULL, ic, TRUE);
7961 freeAsmop (left, NULL, ic, TRUE);
7964 /*-----------------------------------------------------------------*/
7965 /* genGetHbit - generates code get highest order bit */
7966 /*-----------------------------------------------------------------*/
7968 genGetHbit (iCode * ic)
7970 operand *left, *result;
7972 D (emitcode (";", "genGetHbit"));
7974 left = IC_LEFT (ic);
7975 result = IC_RESULT (ic);
7976 aopOp (left, ic, FALSE);
7977 aopOp (result, ic, FALSE);
7979 /* get the highest order byte into a */
7980 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7981 if (AOP_TYPE (result) == AOP_CRY)
7983 emitcode ("rlc", "a");
7988 emitcode ("rl", "a");
7989 emitcode ("anl", "a,#0x01");
7993 freeAsmop (result, NULL, ic, TRUE);
7994 freeAsmop (left, NULL, ic, TRUE);
7997 /*-----------------------------------------------------------------*/
7998 /* genGetAbit - generates code get a single bit */
7999 /*-----------------------------------------------------------------*/
8001 genGetAbit (iCode * ic)
8003 operand *left, *right, *result;
8006 D (emitcode (";", "genGetAbit"));
8008 left = IC_LEFT (ic);
8009 right = IC_RIGHT (ic);
8010 result = IC_RESULT (ic);
8011 aopOp (left, ic, FALSE);
8012 aopOp (right, ic, FALSE);
8013 aopOp (result, ic, FALSE);
8015 shCount = (int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
8017 /* get the needed byte into a */
8018 MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
8020 if (AOP_TYPE (result) == AOP_CRY)
8023 emitcode ("rlc", "a");
8024 else if ((shCount) == 0)
8025 emitcode ("rrc", "a");
8027 emitcode ("mov", "c,acc[%d]", shCount);
8035 emitcode ("rr", "a");
8038 emitcode ("rr", "a");
8041 emitcode ("anl", "a,#0x01");
8045 emitcode ("mov", "c,acc[%d]", shCount);
8046 emitcode ("clr", "a");
8047 emitcode ("rlc", "a");
8050 emitcode ("swap", "a");
8051 emitcode ("anl", "a,#0x01");
8054 emitcode ("rl", "a");
8057 emitcode ("rl", "a");
8058 emitcode ("anl", "a,#0x01");
8064 freeAsmop (result, NULL, ic, TRUE);
8065 freeAsmop (right, NULL, ic, TRUE);
8066 freeAsmop (left, NULL, ic, TRUE);
8069 /*-----------------------------------------------------------------*/
8070 /* genGetByte - generates code get a single byte */
8071 /*-----------------------------------------------------------------*/
8073 genGetByte (iCode * ic)
8075 operand *left, *right, *result;
8078 D (emitcode (";", "genGetByte"));
8080 left = IC_LEFT (ic);
8081 right = IC_RIGHT (ic);
8082 result = IC_RESULT (ic);
8083 aopOp (left, ic, FALSE);
8084 aopOp (right, ic, FALSE);
8085 aopOp (result, ic, FALSE);
8087 offset = (int) ulFromVal (AOP (right)->aopu.aop_lit) / 8;
8089 aopGet (left, offset, FALSE, FALSE),
8092 freeAsmop (result, NULL, ic, TRUE);
8093 freeAsmop (right, NULL, ic, TRUE);
8094 freeAsmop (left, NULL, ic, TRUE);
8097 /*-----------------------------------------------------------------*/
8098 /* genGetWord - generates code get two bytes */
8099 /*-----------------------------------------------------------------*/
8101 genGetWord (iCode * ic)
8103 operand *left, *right, *result;
8106 D (emitcode (";", "genGetWord"));
8108 left = IC_LEFT (ic);
8109 right = IC_RIGHT (ic);
8110 result = IC_RESULT (ic);
8111 aopOp (left, ic, FALSE);
8112 aopOp (right, ic, FALSE);
8113 aopOp (result, ic, FALSE);
8115 offset = (int) ulFromVal (AOP (right)->aopu.aop_lit) / 8;
8117 aopGet (left, offset, FALSE, FALSE),
8120 aopGet (left, offset+1, FALSE, FALSE),
8123 freeAsmop (result, NULL, ic, TRUE);
8124 freeAsmop (right, NULL, ic, TRUE);
8125 freeAsmop (left, NULL, ic, TRUE);
8128 /*-----------------------------------------------------------------*/
8129 /* genSwap - generates code to swap nibbles or bytes */
8130 /*-----------------------------------------------------------------*/
8132 genSwap (iCode * ic)
8134 operand *left, *result;
8136 D(emitcode (";", "genSwap"));
8138 left = IC_LEFT (ic);
8139 result = IC_RESULT (ic);
8140 aopOp (left, ic, FALSE);
8141 aopOp (result, ic, FALSE);
8143 switch (AOP_SIZE (left))
8145 case 1: /* swap nibbles in byte */
8146 MOVA (aopGet (left, 0, FALSE, FALSE));
8147 emitcode ("swap", "a");
8148 aopPut (result, "a", 0);
8150 case 2: /* swap bytes in word */
8151 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
8153 MOVA (aopGet (left, 0, FALSE, FALSE));
8154 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8155 aopPut (result, "a", 1);
8157 else if (operandsEqu (left, result))
8160 bool pushedB = FALSE, leftInB = FALSE;
8162 MOVA (aopGet (left, 0, FALSE, FALSE));
8163 if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
8166 emitcode ("mov", "b,a");
8170 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8171 aopPut (result, reg, 1);
8178 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8179 aopPut (result, aopGet (left, 0, FALSE, FALSE), 1);
8183 wassertl(FALSE, "unsupported SWAP operand size");
8186 freeAsmop (result, NULL, ic, TRUE);
8187 freeAsmop (left, NULL, ic, TRUE);
8190 /*-----------------------------------------------------------------*/
8191 /* AccRol - rotate left accumulator by known count */
8192 /*-----------------------------------------------------------------*/
8194 AccRol (int shCount)
8196 shCount &= 0x0007; // shCount : 0..7
8203 emitcode ("rl", "a");
8206 emitcode ("rl", "a");
8207 emitcode ("rl", "a");
8210 emitcode ("swap", "a");
8211 emitcode ("rr", "a");
8214 emitcode ("swap", "a");
8217 emitcode ("swap", "a");
8218 emitcode ("rl", "a");
8221 emitcode ("rr", "a");
8222 emitcode ("rr", "a");
8225 emitcode ("rr", "a");
8230 /*-----------------------------------------------------------------*/
8231 /* AccLsh - left shift accumulator by known count */
8232 /*-----------------------------------------------------------------*/
8234 AccLsh (int shCount)
8239 emitcode ("add", "a,acc");
8240 else if (shCount == 2)
8242 emitcode ("add", "a,acc");
8243 emitcode ("add", "a,acc");
8247 /* rotate left accumulator */
8249 /* and kill the lower order bits */
8250 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
8255 /*-----------------------------------------------------------------*/
8256 /* AccRsh - right shift accumulator by known count */
8257 /*-----------------------------------------------------------------*/
8259 AccRsh (int shCount)
8266 emitcode ("rrc", "a");
8270 /* rotate right accumulator */
8271 AccRol (8 - shCount);
8272 /* and kill the higher order bits */
8273 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8278 /*-----------------------------------------------------------------*/
8279 /* AccSRsh - signed right shift accumulator by known count */
8280 /*-----------------------------------------------------------------*/
8282 AccSRsh (int shCount)
8289 emitcode ("mov", "c,acc.7");
8290 emitcode ("rrc", "a");
8292 else if (shCount == 2)
8294 emitcode ("mov", "c,acc.7");
8295 emitcode ("rrc", "a");
8296 emitcode ("mov", "c,acc.7");
8297 emitcode ("rrc", "a");
8301 tlbl = newiTempLabel (NULL);
8302 /* rotate right accumulator */
8303 AccRol (8 - shCount);
8304 /* and kill the higher order bits */
8305 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8306 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8307 emitcode ("orl", "a,#0x%02x",
8308 (unsigned char) ~SRMask[shCount]);
8314 /*-----------------------------------------------------------------*/
8315 /* shiftR1Left2Result - shift right one byte from left to result */
8316 /*-----------------------------------------------------------------*/
8318 shiftR1Left2Result (operand * left, int offl,
8319 operand * result, int offr,
8320 int shCount, int sign)
8322 MOVA (aopGet (left, offl, FALSE, FALSE));
8323 /* shift right accumulator */
8328 aopPut (result, "a", offr);
8331 /*-----------------------------------------------------------------*/
8332 /* shiftL1Left2Result - shift left one byte from left to result */
8333 /*-----------------------------------------------------------------*/
8335 shiftL1Left2Result (operand * left, int offl,
8336 operand * result, int offr, int shCount)
8339 l = aopGet (left, offl, FALSE, FALSE);
8341 /* shift left accumulator */
8343 aopPut (result, "a", offr);
8346 /*-----------------------------------------------------------------*/
8347 /* movLeft2Result - move byte from left to result */
8348 /*-----------------------------------------------------------------*/
8350 movLeft2Result (operand * left, int offl,
8351 operand * result, int offr, int sign)
8354 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8356 l = aopGet (left, offl, FALSE, FALSE);
8358 if (*l == '@' && (IS_AOP_PREG (result)))
8360 emitcode ("mov", "a,%s", l);
8361 aopPut (result, "a", offr);
8367 aopPut (result, l, offr);
8371 /* MSB sign in acc.7 ! */
8372 if (getDataSize (left) == offl + 1)
8375 aopPut (result, "a", offr);
8382 /*-----------------------------------------------------------------*/
8383 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
8384 /*-----------------------------------------------------------------*/
8388 emitcode ("rrc", "a");
8389 emitcode ("xch", "a,%s", x);
8390 emitcode ("rrc", "a");
8391 emitcode ("xch", "a,%s", x);
8394 /*-----------------------------------------------------------------*/
8395 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
8396 /*-----------------------------------------------------------------*/
8400 emitcode ("xch", "a,%s", x);
8401 emitcode ("rlc", "a");
8402 emitcode ("xch", "a,%s", x);
8403 emitcode ("rlc", "a");
8406 /*-----------------------------------------------------------------*/
8407 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8408 /*-----------------------------------------------------------------*/
8412 emitcode ("xch", "a,%s", x);
8413 emitcode ("add", "a,acc");
8414 emitcode ("xch", "a,%s", x);
8415 emitcode ("rlc", "a");
8418 /*-----------------------------------------------------------------*/
8419 /* AccAXLsh - left shift a:x by known count (0..7) */
8420 /*-----------------------------------------------------------------*/
8422 AccAXLsh (char *x, int shCount)
8437 case 5: // AAAAABBB:CCCCCDDD
8439 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8441 emitcode ("anl", "a,#0x%02x",
8442 SLMask[shCount]); // BBB00000:CCCCCDDD
8444 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8446 AccRol (shCount); // DDDCCCCC:BBB00000
8448 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8450 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8452 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8454 emitcode ("anl", "a,#0x%02x",
8455 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8457 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8459 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8462 case 6: // AAAAAABB:CCCCCCDD
8463 emitcode ("anl", "a,#0x%02x",
8464 SRMask[shCount]); // 000000BB:CCCCCCDD
8465 emitcode ("mov", "c,acc.0"); // c = B
8466 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8468 AccAXRrl1 (x); // BCCCCCCD:D000000B
8469 AccAXRrl1 (x); // BBCCCCCC:DD000000
8471 emitcode("rrc","a");
8472 emitcode("xch","a,%s", x);
8473 emitcode("rrc","a");
8474 emitcode("mov","c,acc.0"); //<< get correct bit
8475 emitcode("xch","a,%s", x);
8477 emitcode("rrc","a");
8478 emitcode("xch","a,%s", x);
8479 emitcode("rrc","a");
8480 emitcode("xch","a,%s", x);
8483 case 7: // a:x <<= 7
8485 emitcode ("anl", "a,#0x%02x",
8486 SRMask[shCount]); // 0000000B:CCCCCCCD
8488 emitcode ("mov", "c,acc.0"); // c = B
8490 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
8492 AccAXRrl1 (x); // BCCCCCCC:D0000000
8500 /*-----------------------------------------------------------------*/
8501 /* AccAXRsh - right shift a:x known count (0..7) */
8502 /*-----------------------------------------------------------------*/
8504 AccAXRsh (char *x, int shCount)
8512 AccAXRrl1 (x); // 0->a:x
8517 AccAXRrl1 (x); // 0->a:x
8520 AccAXRrl1 (x); // 0->a:x
8525 case 5: // AAAAABBB:CCCCCDDD = a:x
8527 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8529 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8531 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8533 emitcode ("anl", "a,#0x%02x",
8534 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8536 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8538 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8540 emitcode ("anl", "a,#0x%02x",
8541 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8543 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8545 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8547 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8550 case 6: // AABBBBBB:CCDDDDDD
8552 emitcode ("mov", "c,acc.7");
8553 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8555 emitcode ("mov", "c,acc.7");
8556 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8558 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8560 emitcode ("anl", "a,#0x%02x",
8561 SRMask[shCount]); // 000000AA:BBBBBBCC
8564 case 7: // ABBBBBBB:CDDDDDDD
8566 emitcode ("mov", "c,acc.7"); // c = A
8568 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8570 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8572 emitcode ("anl", "a,#0x%02x",
8573 SRMask[shCount]); // 0000000A:BBBBBBBC
8581 /*-----------------------------------------------------------------*/
8582 /* AccAXRshS - right shift signed a:x known count (0..7) */
8583 /*-----------------------------------------------------------------*/
8585 AccAXRshS (char *x, int shCount)
8593 emitcode ("mov", "c,acc.7");
8594 AccAXRrl1 (x); // s->a:x
8598 emitcode ("mov", "c,acc.7");
8599 AccAXRrl1 (x); // s->a:x
8601 emitcode ("mov", "c,acc.7");
8602 AccAXRrl1 (x); // s->a:x
8607 case 5: // AAAAABBB:CCCCCDDD = a:x
8609 tlbl = newiTempLabel (NULL);
8610 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8612 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8614 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8616 emitcode ("anl", "a,#0x%02x",
8617 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8619 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8621 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8623 emitcode ("anl", "a,#0x%02x",
8624 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8626 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8628 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8630 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8632 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8633 emitcode ("orl", "a,#0x%02x",
8634 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8637 break; // SSSSAAAA:BBBCCCCC
8639 case 6: // AABBBBBB:CCDDDDDD
8641 tlbl = newiTempLabel (NULL);
8642 emitcode ("mov", "c,acc.7");
8643 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8645 emitcode ("mov", "c,acc.7");
8646 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8648 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8650 emitcode ("anl", "a,#0x%02x",
8651 SRMask[shCount]); // 000000AA:BBBBBBCC
8653 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8654 emitcode ("orl", "a,#0x%02x",
8655 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8659 case 7: // ABBBBBBB:CDDDDDDD
8661 tlbl = newiTempLabel (NULL);
8662 emitcode ("mov", "c,acc.7"); // c = A
8664 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8666 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8668 emitcode ("anl", "a,#0x%02x",
8669 SRMask[shCount]); // 0000000A:BBBBBBBC
8671 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8672 emitcode ("orl", "a,#0x%02x",
8673 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8682 /*-----------------------------------------------------------------*/
8683 /* shiftL2Left2Result - shift left two bytes from left to result */
8684 /*-----------------------------------------------------------------*/
8686 shiftL2Left2Result (operand * left, int offl,
8687 operand * result, int offr, int shCount)
8690 bool pushedB = FALSE;
8693 if (sameRegs (AOP (result), AOP (left)) &&
8694 ((offl + MSB16) == offr))
8696 /* don't crash result[offr] */
8697 MOVA (aopGet (left, offl, FALSE, FALSE));
8698 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8699 usedB = !strncmp(x, "b", 1);
8701 else if (aopGetUsesAcc (result, offr))
8703 movLeft2Result (left, offl, result, offr, 0);
8706 emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8707 MOVA (aopGet (result, offr, FALSE, FALSE));
8708 emitcode ("xch", "a,b");
8713 movLeft2Result (left, offl, result, offr, 0);
8714 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8715 x = aopGet (result, offr, FALSE, FALSE);
8717 /* ax << shCount (x = lsb(result)) */
8718 AccAXLsh (x, shCount);
8721 emitcode ("xch", "a,b");
8722 aopPut (result, "a", offr);
8723 aopPut (result, "b", offr + MSB16);
8728 aopPut (result, "a", offr + MSB16);
8733 /*-----------------------------------------------------------------*/
8734 /* shiftR2Left2Result - shift right two bytes from left to result */
8735 /*-----------------------------------------------------------------*/
8737 shiftR2Left2Result (operand * left, int offl,
8738 operand * result, int offr,
8739 int shCount, int sign)
8742 bool pushedB = FALSE;
8745 if (sameRegs (AOP (result), AOP (left)) &&
8746 ((offl + MSB16) == offr))
8748 /* don't crash result[offr] */
8749 MOVA (aopGet (left, offl, FALSE, FALSE));
8750 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8751 usedB = !strncmp(x, "b", 1);
8753 else if (aopGetUsesAcc (result, offr))
8755 movLeft2Result (left, offl, result, offr, 0);
8758 emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8759 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8764 movLeft2Result (left, offl, result, offr, 0);
8765 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8766 x = aopGet (result, offr, FALSE, FALSE);
8768 /* a:x >> shCount (x = lsb(result)) */
8770 AccAXRshS (x, shCount);
8772 AccAXRsh (x, shCount);
8775 emitcode ("xch", "a,b");
8776 aopPut (result, "a", offr);
8777 emitcode ("xch", "a,b");
8780 if (getDataSize (result) > 1)
8781 aopPut (result, "a", offr + MSB16);
8784 /*-----------------------------------------------------------------*/
8785 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8786 /*-----------------------------------------------------------------*/
8788 shiftLLeftOrResult (operand * left, int offl,
8789 operand * result, int offr, int shCount)
8791 MOVA (aopGet (left, offl, FALSE, FALSE));
8792 /* shift left accumulator */
8794 /* or with result */
8795 if (aopGetUsesAcc (result, offr))
8797 emitcode ("xch", "a,b");
8798 MOVA (aopGet (result, offr, FALSE, FALSE));
8799 emitcode ("orl", "a,b");
8803 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8805 /* back to result */
8806 aopPut (result, "a", offr);
8809 /*-----------------------------------------------------------------*/
8810 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8811 /*-----------------------------------------------------------------*/
8813 shiftRLeftOrResult (operand * left, int offl,
8814 operand * result, int offr, int shCount)
8816 MOVA (aopGet (left, offl, FALSE, FALSE));
8817 /* shift right accumulator */
8819 /* or with result */
8820 if (aopGetUsesAcc(result, offr))
8822 emitcode ("xch", "a,b");
8823 MOVA (aopGet (result, offr, FALSE, FALSE));
8824 emitcode ("orl", "a,b");
8828 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8830 /* back to result */
8831 aopPut (result, "a", offr);
8834 /*-----------------------------------------------------------------*/
8835 /* genlshOne - left shift a one byte quantity by known count */
8836 /*-----------------------------------------------------------------*/
8838 genlshOne (operand * result, operand * left, int shCount)
8840 D (emitcode (";", "genlshOne"));
8842 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8845 /*-----------------------------------------------------------------*/
8846 /* genlshTwo - left shift two bytes by known amount != 0 */
8847 /*-----------------------------------------------------------------*/
8849 genlshTwo (operand * result, operand * left, int shCount)
8853 D (emitcode (";", "genlshTwo"));
8855 size = getDataSize (result);
8857 /* if shCount >= 8 */
8866 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8870 movLeft2Result (left, LSB, result, MSB16, 0);
8873 aopPut (result, zero, LSB);
8876 /* 1 <= shCount <= 7 */
8880 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8882 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8886 /*-----------------------------------------------------------------*/
8887 /* shiftLLong - shift left one long from left to result */
8888 /* offl = LSB or MSB16 */
8889 /*-----------------------------------------------------------------*/
8891 shiftLLong (operand * left, operand * result, int offr)
8894 int size = AOP_SIZE (result);
8896 if (size >= LSB + offr)
8898 l = aopGet (left, LSB, FALSE, FALSE);
8900 emitcode ("add", "a,acc");
8901 if (sameRegs (AOP (left), AOP (result)) &&
8902 size >= MSB16 + offr && offr != LSB)
8903 xch_a_aopGet (left, LSB + offr, FALSE, FALSE);
8905 aopPut (result, "a", LSB + offr);
8908 if (size >= MSB16 + offr)
8910 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8912 l = aopGet (left, MSB16, FALSE, FALSE);
8915 emitcode ("rlc", "a");
8916 if (sameRegs (AOP (left), AOP (result)) &&
8917 size >= MSB24 + offr && offr != LSB)
8918 xch_a_aopGet (left, MSB16 + offr, FALSE, FALSE);
8920 aopPut (result, "a", MSB16 + offr);
8923 if (size >= MSB24 + offr)
8925 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8927 l = aopGet (left, MSB24, FALSE, FALSE);
8930 emitcode ("rlc", "a");
8931 if (sameRegs (AOP (left), AOP (result)) &&
8932 size >= MSB32 + offr && offr != LSB)
8933 xch_a_aopGet (left, MSB24 + offr, FALSE, FALSE);
8935 aopPut (result, "a", MSB24 + offr);
8938 if (size > MSB32 + offr)
8940 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8942 l = aopGet (left, MSB32, FALSE, FALSE);
8945 emitcode ("rlc", "a");
8946 aopPut (result, "a", MSB32 + offr);
8949 aopPut (result, zero, LSB);
8952 /*-----------------------------------------------------------------*/
8953 /* genlshFour - shift four byte by a known amount != 0 */
8954 /*-----------------------------------------------------------------*/
8956 genlshFour (operand * result, operand * left, int shCount)
8960 D (emitcode (";", "genlshFour"));
8962 size = AOP_SIZE (result);
8964 /* if shifting more that 3 bytes */
8969 /* lowest order of left goes to the highest
8970 order of the destination */
8971 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8973 movLeft2Result (left, LSB, result, MSB32, 0);
8974 aopPut (result, zero, LSB);
8975 aopPut (result, zero, MSB16);
8976 aopPut (result, zero, MSB24);
8980 /* more than two bytes */
8981 else if (shCount >= 16)
8983 /* lower order two bytes goes to higher order two bytes */
8985 /* if some more remaining */
8987 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8990 movLeft2Result (left, MSB16, result, MSB32, 0);
8991 movLeft2Result (left, LSB, result, MSB24, 0);
8993 aopPut (result, zero, MSB16);
8994 aopPut (result, zero, LSB);
8998 /* if more than 1 byte */
8999 else if (shCount >= 8)
9001 /* lower order three bytes goes to higher order three bytes */
9006 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
9008 movLeft2Result (left, LSB, result, MSB16, 0);
9014 movLeft2Result (left, MSB24, result, MSB32, 0);
9015 movLeft2Result (left, MSB16, result, MSB24, 0);
9016 movLeft2Result (left, LSB, result, MSB16, 0);
9017 aopPut (result, zero, LSB);
9019 else if (shCount == 1)
9020 shiftLLong (left, result, MSB16);
9023 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
9024 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
9025 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
9026 aopPut (result, zero, LSB);
9031 /* 1 <= shCount <= 7 */
9032 else if (shCount <= 2)
9034 shiftLLong (left, result, LSB);
9036 shiftLLong (result, result, LSB);
9038 /* 3 <= shCount <= 7, optimize */
9041 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
9042 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
9043 shiftL2Left2Result (left, LSB, result, LSB, shCount);
9047 /*-----------------------------------------------------------------*/
9048 /* genLeftShiftLiteral - left shifting by known count */
9049 /*-----------------------------------------------------------------*/
9051 genLeftShiftLiteral (operand * left,
9056 int shCount = (int) ulFromVal (AOP (right)->aopu.aop_lit);
9059 D (emitcode (";", "genLeftShiftLiteral"));
9061 freeAsmop (right, NULL, ic, TRUE);
9063 aopOp (left, ic, FALSE);
9064 aopOp (result, ic, FALSE);
9066 size = getSize (operandType (result));
9069 emitcode ("; shift left ", "result %d, left %d", size,
9073 /* I suppose that the left size >= result size */
9078 movLeft2Result (left, size, result, size, 0);
9081 else if (shCount >= (size * 8))
9085 aopPut (result, zero, size);
9093 genlshOne (result, left, shCount);
9097 genlshTwo (result, left, shCount);
9101 genlshFour (result, left, shCount);
9104 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9105 "*** ack! mystery literal shift!\n");
9109 freeAsmop (result, NULL, ic, TRUE);
9110 freeAsmop (left, NULL, ic, TRUE);
9113 /*-----------------------------------------------------------------*/
9114 /* genLeftShift - generates code for left shifting */
9115 /*-----------------------------------------------------------------*/
9117 genLeftShift (iCode * ic)
9119 operand *left, *right, *result;
9122 symbol *tlbl, *tlbl1;
9125 D (emitcode (";", "genLeftShift"));
9127 right = IC_RIGHT (ic);
9128 left = IC_LEFT (ic);
9129 result = IC_RESULT (ic);
9131 aopOp (right, ic, FALSE);
9133 /* if the shift count is known then do it
9134 as efficiently as possible */
9135 if (AOP_TYPE (right) == AOP_LIT)
9137 genLeftShiftLiteral (left, right, result, ic);
9141 /* shift count is unknown then we have to form
9142 a loop get the loop count in B : Note: we take
9143 only the lower order byte since shifting
9144 more that 32 bits make no sense anyway, ( the
9145 largest size of an object can be only 32 bits ) */
9148 MOVB (aopGet (right, 0, FALSE, FALSE));
9149 emitcode ("inc", "b");
9150 freeAsmop (right, NULL, ic, TRUE);
9151 aopOp (left, ic, FALSE);
9152 aopOp (result, ic, FALSE);
9154 /* now move the left to the result if they are not the same */
9155 if (!sameRegs (AOP (left), AOP (result)) &&
9156 AOP_SIZE (result) > 1)
9159 size = AOP_SIZE (result);
9163 l = aopGet (left, offset, FALSE, TRUE);
9164 if (*l == '@' && (IS_AOP_PREG (result)))
9167 emitcode ("mov", "a,%s", l);
9168 aopPut (result, "a", offset);
9171 aopPut (result, l, offset);
9176 tlbl = newiTempLabel (NULL);
9177 size = AOP_SIZE (result);
9179 tlbl1 = newiTempLabel (NULL);
9181 /* if it is only one byte then */
9184 symbol *tlbl1 = newiTempLabel (NULL);
9186 l = aopGet (left, 0, FALSE, FALSE);
9188 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9190 emitcode ("add", "a,acc");
9192 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9194 aopPut (result, "a", 0);
9198 reAdjustPreg (AOP (result));
9200 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9202 l = aopGet (result, offset, FALSE, FALSE);
9204 emitcode ("add", "a,acc");
9205 aopPut (result, "a", offset++);
9208 l = aopGet (result, offset, FALSE, FALSE);
9210 emitcode ("rlc", "a");
9211 aopPut (result, "a", offset++);
9213 reAdjustPreg (AOP (result));
9216 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9219 freeAsmop (result, NULL, ic, TRUE);
9220 freeAsmop (left, NULL, ic, TRUE);
9223 /*-----------------------------------------------------------------*/
9224 /* genrshOne - right shift a one byte quantity by known count */
9225 /*-----------------------------------------------------------------*/
9227 genrshOne (operand * result, operand * left,
9228 int shCount, int sign)
9230 D (emitcode (";", "genrshOne"));
9232 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9235 /*-----------------------------------------------------------------*/
9236 /* genrshTwo - right shift two bytes by known amount != 0 */
9237 /*-----------------------------------------------------------------*/
9239 genrshTwo (operand * result, operand * left,
9240 int shCount, int sign)
9242 D (emitcode (";", "genrshTwo"));
9244 /* if shCount >= 8 */
9249 shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
9251 movLeft2Result (left, MSB16, result, LSB, sign);
9252 addSign (result, MSB16, sign);
9255 /* 1 <= shCount <= 7 */
9257 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9260 /*-----------------------------------------------------------------*/
9261 /* shiftRLong - shift right one long from left to result */
9262 /* offl = LSB or MSB16 */
9263 /*-----------------------------------------------------------------*/
9265 shiftRLong (operand * left, int offl,
9266 operand * result, int sign)
9268 bool overlapping = regsInCommon (left, result) || operandsEqu(left, result);
9270 if (overlapping && offl>1)
9272 // we are in big trouble, but this shouldn't happen
9273 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9276 MOVA (aopGet (left, MSB32, FALSE, FALSE));
9283 emitcode ("rlc", "a");
9284 emitcode ("subb", "a,acc");
9285 if (overlapping && sameByte (AOP (left), MSB32, AOP (result), MSB32))
9287 xch_a_aopGet (left, MSB32, FALSE, FALSE);
9291 aopPut (result, "a", MSB32);
9292 MOVA (aopGet (left, MSB32, FALSE, FALSE));
9297 if (aopPutUsesAcc (result, zero, MSB32))
9299 emitcode("xch", "a,b");
9300 aopPut (result, zero, MSB32);
9301 emitcode("xch", "a,b");
9305 aopPut (result, zero, MSB32);
9312 emitcode ("clr", "c");
9316 emitcode ("mov", "c,acc.7");
9319 emitcode ("rrc", "a");
9321 if (overlapping && offl==MSB16 &&
9322 sameByte (AOP (left), MSB24, AOP (result), MSB32-offl))
9324 xch_a_aopGet (left, MSB24, FALSE, FALSE);
9328 aopPut (result, "a", MSB32 - offl);
9329 MOVA (aopGet (left, MSB24, FALSE, FALSE));
9332 emitcode ("rrc", "a");
9333 if (overlapping && offl==MSB16 &&
9334 sameByte (AOP (left), MSB16, AOP (result), MSB24-offl))
9336 xch_a_aopGet (left, MSB16, FALSE, FALSE);
9340 aopPut (result, "a", MSB24 - offl);
9341 MOVA (aopGet (left, MSB16, FALSE, FALSE));
9344 emitcode ("rrc", "a");
9347 aopPut (result, "a", MSB16 - offl);
9352 sameByte (AOP (left), LSB, AOP (result), MSB16-offl))
9354 xch_a_aopGet (left, LSB, FALSE, FALSE);
9358 aopPut (result, "a", MSB16 - offl);
9359 MOVA (aopGet (left, LSB, FALSE, FALSE));
9361 emitcode ("rrc", "a");
9362 aopPut (result, "a", LSB);
9366 /*-----------------------------------------------------------------*/
9367 /* genrshFour - shift four byte by a known amount != 0 */
9368 /*-----------------------------------------------------------------*/
9370 genrshFour (operand * result, operand * left,
9371 int shCount, int sign)
9373 D (emitcode (";", "genrshFour"));
9375 /* if shifting more that 3 bytes */
9380 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9382 movLeft2Result (left, MSB32, result, LSB, sign);
9383 addSign (result, MSB16, sign);
9385 else if (shCount >= 16)
9389 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9392 movLeft2Result (left, MSB24, result, LSB, 0);
9393 movLeft2Result (left, MSB32, result, MSB16, sign);
9395 addSign (result, MSB24, sign);
9397 else if (shCount >= 8)
9402 shiftRLong (left, MSB16, result, sign);
9404 else if (shCount == 0)
9406 movLeft2Result (left, MSB16, result, LSB, 0);
9407 movLeft2Result (left, MSB24, result, MSB16, 0);
9408 movLeft2Result (left, MSB32, result, MSB24, sign);
9409 addSign (result, MSB32, sign);
9413 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9414 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9415 /* the last shift is signed */
9416 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9417 addSign (result, MSB32, sign);
9422 /* 1 <= shCount <= 7 */
9425 shiftRLong (left, LSB, result, sign);
9427 shiftRLong (result, LSB, result, sign);
9431 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9432 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9433 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9438 /*-----------------------------------------------------------------*/
9439 /* genRightShiftLiteral - right shifting by known count */
9440 /*-----------------------------------------------------------------*/
9442 genRightShiftLiteral (operand * left,
9448 int shCount = (int) ulFromVal (AOP (right)->aopu.aop_lit);
9451 D (emitcode (";", "genRightShiftLiteral"));
9453 freeAsmop (right, NULL, ic, TRUE);
9455 aopOp (left, ic, FALSE);
9456 aopOp (result, ic, FALSE);
9459 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9463 size = getDataSize (left);
9464 /* test the LEFT size !!! */
9466 /* I suppose that the left size >= result size */
9469 size = getDataSize (result);
9471 movLeft2Result (left, size, result, size, 0);
9473 else if (shCount >= (size * 8))
9477 /* get sign in acc.7 */
9478 MOVA (aopGet (left, size - 1, FALSE, FALSE));
9480 addSign (result, LSB, sign);
9487 genrshOne (result, left, shCount, sign);
9491 genrshTwo (result, left, shCount, sign);
9495 genrshFour (result, left, shCount, sign);
9501 freeAsmop (result, NULL, ic, TRUE);
9502 freeAsmop (left, NULL, ic, TRUE);
9505 /*-----------------------------------------------------------------*/
9506 /* genSignedRightShift - right shift of signed number */
9507 /*-----------------------------------------------------------------*/
9509 genSignedRightShift (iCode * ic)
9511 operand *right, *left, *result;
9514 symbol *tlbl, *tlbl1;
9517 D (emitcode (";", "genSignedRightShift"));
9519 /* we do it the hard way put the shift count in b
9520 and loop thru preserving the sign */
9522 right = IC_RIGHT (ic);
9523 left = IC_LEFT (ic);
9524 result = IC_RESULT (ic);
9526 aopOp (right, ic, FALSE);
9529 if (AOP_TYPE (right) == AOP_LIT)
9531 genRightShiftLiteral (left, right, result, ic, 1);
9534 /* shift count is unknown then we have to form
9535 a loop get the loop count in B : Note: we take
9536 only the lower order byte since shifting
9537 more that 32 bits make no sense anyway, ( the
9538 largest size of an object can be only 32 bits ) */
9541 MOVB (aopGet (right, 0, FALSE, FALSE));
9542 emitcode ("inc", "b");
9543 freeAsmop (right, NULL, ic, TRUE);
9544 aopOp (left, ic, FALSE);
9545 aopOp (result, ic, FALSE);
9547 /* now move the left to the result if they are not the
9549 if (!sameRegs (AOP (left), AOP (result)) &&
9550 AOP_SIZE (result) > 1)
9553 size = AOP_SIZE (result);
9557 l = aopGet (left, offset, FALSE, TRUE);
9558 if (*l == '@' && IS_AOP_PREG (result))
9561 emitcode ("mov", "a,%s", l);
9562 aopPut (result, "a", offset);
9565 aopPut (result, l, offset);
9570 /* mov the highest order bit to OVR */
9571 tlbl = newiTempLabel (NULL);
9572 tlbl1 = newiTempLabel (NULL);
9574 size = AOP_SIZE (result);
9576 MOVA (aopGet (left, offset, FALSE, FALSE));
9577 emitcode ("rlc", "a");
9578 emitcode ("mov", "ov,c");
9579 /* if it is only one byte then */
9582 l = aopGet (left, 0, FALSE, FALSE);
9584 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9586 emitcode ("mov", "c,ov");
9587 emitcode ("rrc", "a");
9589 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9591 aopPut (result, "a", 0);
9595 reAdjustPreg (AOP (result));
9596 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9598 emitcode ("mov", "c,ov");
9601 l = aopGet (result, offset, FALSE, FALSE);
9603 emitcode ("rrc", "a");
9604 aopPut (result, "a", offset--);
9606 reAdjustPreg (AOP (result));
9608 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9612 freeAsmop (result, NULL, ic, TRUE);
9613 freeAsmop (left, NULL, ic, TRUE);
9616 /*-----------------------------------------------------------------*/
9617 /* genRightShift - generate code for right shifting */
9618 /*-----------------------------------------------------------------*/
9620 genRightShift (iCode * ic)
9622 operand *right, *left, *result;
9626 symbol *tlbl, *tlbl1;
9629 D (emitcode (";", "genRightShift"));
9631 /* if signed then we do it the hard way preserve the
9632 sign bit moving it inwards */
9633 letype = getSpec (operandType (IC_LEFT (ic)));
9635 if (!SPEC_USIGN (letype))
9637 genSignedRightShift (ic);
9641 /* signed & unsigned types are treated the same : i.e. the
9642 signed is NOT propagated inwards : quoting from the
9643 ANSI - standard : "for E1 >> E2, is equivalent to division
9644 by 2**E2 if unsigned or if it has a non-negative value,
9645 otherwise the result is implementation defined ", MY definition
9646 is that the sign does not get propagated */
9648 right = IC_RIGHT (ic);
9649 left = IC_LEFT (ic);
9650 result = IC_RESULT (ic);
9652 aopOp (right, ic, FALSE);
9654 /* if the shift count is known then do it
9655 as efficiently as possible */
9656 if (AOP_TYPE (right) == AOP_LIT)
9658 genRightShiftLiteral (left, right, result, ic, 0);
9662 /* shift count is unknown then we have to form
9663 a loop get the loop count in B : Note: we take
9664 only the lower order byte since shifting
9665 more that 32 bits make no sense anyway, ( the
9666 largest size of an object can be only 32 bits ) */
9669 MOVB (aopGet (right, 0, FALSE, FALSE));
9670 emitcode ("inc", "b");
9671 freeAsmop (right, NULL, ic, TRUE);
9672 aopOp (left, ic, FALSE);
9673 aopOp (result, ic, FALSE);
9675 /* now move the left to the result if they are not the
9677 if (!sameRegs (AOP (left), AOP (result)) &&
9678 AOP_SIZE (result) > 1)
9680 size = AOP_SIZE (result);
9684 l = aopGet (left, offset, FALSE, TRUE);
9685 if (*l == '@' && IS_AOP_PREG (result))
9688 emitcode ("mov", "a,%s", l);
9689 aopPut (result, "a", offset);
9692 aopPut (result, l, offset);
9697 tlbl = newiTempLabel (NULL);
9698 tlbl1 = newiTempLabel (NULL);
9699 size = AOP_SIZE (result);
9702 /* if it is only one byte then */
9705 l = aopGet (left, 0, FALSE, FALSE);
9707 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9710 emitcode ("rrc", "a");
9712 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9714 aopPut (result, "a", 0);
9718 reAdjustPreg (AOP (result));
9719 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9724 l = aopGet (result, offset, FALSE, FALSE);
9726 emitcode ("rrc", "a");
9727 aopPut (result, "a", offset--);
9729 reAdjustPreg (AOP (result));
9732 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9736 freeAsmop (result, NULL, ic, TRUE);
9737 freeAsmop (left, NULL, ic, TRUE);
9740 /*-----------------------------------------------------------------*/
9741 /* emitPtrByteGet - emits code to get a byte into A through a */
9742 /* pointer register (R0, R1, or DPTR). The */
9743 /* original value of A can be preserved in B. */
9744 /*-----------------------------------------------------------------*/
9746 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9753 emitcode ("mov", "b,a");
9754 emitcode ("mov", "a,@%s", rname);
9759 emitcode ("mov", "b,a");
9760 emitcode ("movx", "a,@%s", rname);
9765 emitcode ("mov", "b,a");
9766 emitcode ("movx", "a,@dptr");
9771 emitcode ("mov", "b,a");
9772 emitcode ("clr", "a");
9773 emitcode ("movc", "a,@a+dptr");
9779 emitcode ("push", "b");
9780 emitcode ("push", "acc");
9782 emitcode ("lcall", "__gptrget");
9784 emitcode ("pop", "b");
9789 /*-----------------------------------------------------------------*/
9790 /* emitPtrByteSet - emits code to set a byte from src through a */
9791 /* pointer register (R0, R1, or DPTR). */
9792 /*-----------------------------------------------------------------*/
9794 emitPtrByteSet (char *rname, int p_type, char *src)
9803 emitcode ("mov", "@%s,a", rname);
9806 emitcode ("mov", "@%s,%s", rname, src);
9811 emitcode ("movx", "@%s,a", rname);
9816 emitcode ("movx", "@dptr,a");
9821 emitcode ("lcall", "__gptrput");
9826 /*-----------------------------------------------------------------*/
9827 /* genUnpackBits - generates code for unpacking bits */
9828 /*-----------------------------------------------------------------*/
9830 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9832 int offset = 0; /* result byte offset */
9833 int rsize; /* result size */
9834 int rlen = 0; /* remaining bitfield length */
9835 sym_link *etype; /* bitfield type information */
9836 int blen; /* bitfield length */
9837 int bstr; /* bitfield starting bit within byte */
9838 static char* const accBits[] = {"acc.0", "acc.1", "acc.2", "acc.3",
9839 "acc.4", "acc.5", "acc.6", "acc.7"};
9841 D(emitcode (";", "genUnpackBits"));
9843 etype = getSpec (operandType (result));
9844 rsize = getSize (operandType (result));
9845 blen = SPEC_BLEN (etype);
9846 bstr = SPEC_BSTR (etype);
9848 if (ifx && blen <= 8)
9850 emitPtrByteGet (rname, ptype, FALSE);
9853 return accBits[bstr];;
9858 emitcode ("anl", "a,#0x%02x",
9859 (((unsigned char) -1) >> (8 - blen)) << bstr);
9865 /* If the bitfield length is less than a byte */
9868 emitPtrByteGet (rname, ptype, FALSE);
9870 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9871 if (!SPEC_USIGN (etype))
9873 /* signed bitfield */
9874 symbol *tlbl = newiTempLabel (NULL);
9876 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9877 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9880 aopPut (result, "a", offset++);
9884 /* Bit field did not fit in a byte. Copy all
9885 but the partial byte at the end. */
9886 for (rlen=blen;rlen>=8;rlen-=8)
9888 emitPtrByteGet (rname, ptype, FALSE);
9889 aopPut (result, "a", offset++);
9891 emitcode ("inc", "%s", rname);
9894 /* Handle the partial byte at the end */
9897 emitPtrByteGet (rname, ptype, FALSE);
9898 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9899 if (!SPEC_USIGN (etype))
9901 /* signed bitfield */
9902 symbol *tlbl = newiTempLabel (NULL);
9904 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9905 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9908 aopPut (result, "a", offset++);
9916 if (SPEC_USIGN (etype))
9920 /* signed bitfield: sign extension with 0x00 or 0xff */
9921 emitcode ("rlc", "a");
9922 emitcode ("subb", "a,acc");
9928 aopPut (result, source, offset++);
9934 /*-----------------------------------------------------------------*/
9935 /* genDataPointerGet - generates code when ptr offset is known */
9936 /*-----------------------------------------------------------------*/
9938 genDataPointerGet (operand * left,
9944 int size, offset = 0;
9946 D (emitcode (";", "genDataPointerGet"));
9948 aopOp (result, ic, TRUE);
9950 /* get the string representation of the name */
9951 l = aopGet (left, 0, FALSE, TRUE);
9953 size = AOP_SIZE (result);
9958 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
9962 SNPRINTF (buffer, sizeof(buffer), "%s", l);
9964 aopPut (result, buffer, offset++);
9967 freeAsmop (result, NULL, ic, TRUE);
9968 freeAsmop (left, NULL, ic, TRUE);
9971 /*-----------------------------------------------------------------*/
9972 /* genNearPointerGet - emitcode for near pointer fetch */
9973 /*-----------------------------------------------------------------*/
9975 genNearPointerGet (operand * left,
9984 char *ifxCond = "a";
9985 sym_link *rtype, *retype;
9986 sym_link *ltype = operandType (left);
9988 D (emitcode (";", "genNearPointerGet"));
9990 rtype = operandType (result);
9991 retype = getSpec (rtype);
9993 aopOp (left, ic, FALSE);
9995 /* if left is rematerialisable and
9996 result is not bitfield variable type and
9997 the left is pointer to data space i.e
9998 lower 128 bytes of space */
9999 if (AOP_TYPE (left) == AOP_IMMD &&
10000 !IS_BITFIELD (retype) &&
10001 DCL_TYPE (ltype) == POINTER)
10003 genDataPointerGet (left, result, ic);
10007 //aopOp (result, ic, FALSE);
10008 aopOp (result, ic, result?TRUE:FALSE);
10010 /* if the value is already in a pointer register
10011 then don't need anything more */
10012 if (!AOP_INPREG (AOP (left)))
10014 if (IS_AOP_PREG (left))
10016 // Aha, it is a pointer, just in disguise.
10017 rname = aopGet (left, 0, FALSE, FALSE);
10020 fprintf(stderr, "probable internal error: unexpected rname '%s' @ %s:%d\n",
10021 rname, __FILE__, __LINE__);
10026 emitcode ("mov", "a%s,%s", rname + 1, rname);
10027 rname++; // skip the '@'.
10032 /* otherwise get a free pointer register */
10033 aop = newAsmop (0);
10034 preg = getFreePtr (ic, &aop, FALSE);
10035 emitcode ("mov", "%s,%s",
10037 aopGet (left, 0, FALSE, TRUE));
10038 rname = preg->name;
10042 rname = aopGet (left, 0, FALSE, FALSE);
10044 /* if bitfield then unpack the bits */
10045 if (IS_BITFIELD (retype))
10046 ifxCond = genUnpackBits (result, rname, POINTER, ifx);
10049 /* we have can just get the values */
10050 int size = AOP_SIZE (result);
10055 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
10058 emitcode ("mov", "a,@%s", rname);
10060 aopPut (result, "a", offset);
10066 SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
10067 aopPut (result, buffer, offset);
10071 emitcode ("inc", "%s", rname);
10075 /* now some housekeeping stuff */
10076 if (aop) /* we had to allocate for this iCode */
10078 if (pi) { /* post increment present */
10079 aopPut (left, rname, 0);
10081 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
10085 /* we did not allocate which means left
10086 already in a pointer register, then
10087 if size > 0 && this could be used again
10088 we have to point it back to where it
10090 if ((AOP_SIZE (result) > 1 &&
10091 !OP_SYMBOL (left)->remat &&
10092 (OP_SYMBOL (left)->liveTo > ic->seq ||
10096 int size = AOP_SIZE (result) - 1;
10098 emitcode ("dec", "%s", rname);
10102 if (ifx && !ifx->generated)
10104 genIfxJump (ifx, ifxCond, left, NULL, result, ic->next);
10108 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
10109 freeAsmop (left, NULL, ic, TRUE);
10110 if (pi) pi->generated = 1;
10113 /*-----------------------------------------------------------------*/
10114 /* genPagedPointerGet - emitcode for paged pointer fetch */
10115 /*-----------------------------------------------------------------*/
10117 genPagedPointerGet (operand * left,
10126 char *ifxCond = "a";
10127 sym_link *rtype, *retype;
10129 D (emitcode (";", "genPagedPointerGet"));
10131 rtype = operandType (result);
10132 retype = getSpec (rtype);
10134 aopOp (left, ic, FALSE);
10136 aopOp (result, ic, FALSE);
10138 /* if the value is already in a pointer register
10139 then don't need anything more */
10140 if (!AOP_INPREG (AOP (left)))
10142 /* otherwise get a free pointer register */
10143 aop = newAsmop (0);
10144 preg = getFreePtr (ic, &aop, FALSE);
10145 emitcode ("mov", "%s,%s",
10147 aopGet (left, 0, FALSE, TRUE));
10148 rname = preg->name;
10151 rname = aopGet (left, 0, FALSE, FALSE);
10153 /* if bitfield then unpack the bits */
10154 if (IS_BITFIELD (retype))
10155 ifxCond = genUnpackBits (result, rname, PPOINTER, ifx);
10158 /* we have can just get the values */
10159 int size = AOP_SIZE (result);
10165 emitcode ("movx", "a,@%s", rname);
10167 aopPut (result, "a", offset);
10172 emitcode ("inc", "%s", rname);
10176 /* now some housekeeping stuff */
10177 if (aop) /* we had to allocate for this iCode */
10180 aopPut (left, rname, 0);
10181 freeAsmop (NULL, aop, ic, TRUE);
10185 /* we did not allocate which means left
10186 already in a pointer register, then
10187 if size > 0 && this could be used again
10188 we have to point it back to where it
10190 if ((AOP_SIZE (result) > 1 &&
10191 !OP_SYMBOL (left)->remat &&
10192 (OP_SYMBOL (left)->liveTo > ic->seq ||
10196 int size = AOP_SIZE (result) - 1;
10198 emitcode ("dec", "%s", rname);
10202 if (ifx && !ifx->generated)
10204 genIfxJump (ifx, ifxCond, left, NULL, result, ic->next);
10208 freeAsmop (result, NULL, ic, TRUE);
10209 freeAsmop (left, NULL, ic, TRUE);
10210 if (pi) pi->generated = 1;
10213 /*--------------------------------------------------------------------*/
10214 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
10215 /*--------------------------------------------------------------------*/
10217 loadDptrFromOperand (operand *op, bool loadBToo)
10219 if (AOP_TYPE (op) != AOP_STR)
10221 /* if this is rematerializable */
10222 if (AOP_TYPE (op) == AOP_IMMD)
10224 emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
10227 if (AOP(op)->aopu.aop_immd.from_cast_remat)
10228 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
10231 wassertl(FALSE, "need pointerCode");
10232 emitcode (";", "mov b,???");
10233 /* genPointerGet and genPointerSet originally did different
10234 ** things for this case. Both seem wrong.
10235 ** from genPointerGet:
10236 ** emitcode ("mov", "b,#%d", pointerCode (retype));
10237 ** from genPointerSet:
10238 ** emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
10243 else if (AOP_TYPE (op) == AOP_DPTR)
10247 MOVA (aopGet (op, 0, FALSE, FALSE));
10248 emitcode ("push", "acc");
10249 MOVA (aopGet (op, 1, FALSE, FALSE));
10250 emitcode ("push", "acc");
10251 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10252 emitcode ("pop", "dph");
10253 emitcode ("pop", "dpl");
10257 MOVA (aopGet (op, 0, FALSE, FALSE));
10258 emitcode ("push", "acc");
10259 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10260 emitcode ("pop", "dpl");
10264 { /* we need to get it byte by byte */
10265 emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
10266 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10268 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10273 /*-----------------------------------------------------------------*/
10274 /* genFarPointerGet - get value from far space */
10275 /*-----------------------------------------------------------------*/
10277 genFarPointerGet (operand * left,
10278 operand * result, iCode * ic, iCode * pi, iCode * ifx)
10281 char *ifxCond = "a";
10282 sym_link *retype = getSpec (operandType (result));
10284 D (emitcode (";", "genFarPointerGet"));
10286 aopOp (left, ic, FALSE);
10287 loadDptrFromOperand (left, FALSE);
10289 /* so dptr now contains the address */
10290 aopOp (result, ic, FALSE);
10292 /* if bit then unpack */
10293 if (IS_BITFIELD (retype))
10294 ifxCond = genUnpackBits (result, "dptr", FPOINTER, ifx);
10297 size = AOP_SIZE (result);
10302 emitcode ("movx", "a,@dptr");
10304 aopPut (result, "a", offset++);
10306 emitcode ("inc", "dptr");
10310 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10312 aopPut (left, "dpl", 0);
10313 aopPut (left, "dph", 1);
10317 if (ifx && !ifx->generated)
10319 genIfxJump (ifx, ifxCond, left, NULL, result, ic->next);
10322 freeAsmop (result, NULL, ic, TRUE);
10323 freeAsmop (left, NULL, ic, TRUE);
10326 /*-----------------------------------------------------------------*/
10327 /* genCodePointerGet - get value from code space */
10328 /*-----------------------------------------------------------------*/
10330 genCodePointerGet (operand * left,
10331 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10334 char *ifxCond = "a";
10335 sym_link *retype = getSpec (operandType (result));
10337 D (emitcode (";", "genCodePointerGet"));
10339 aopOp (left, ic, FALSE);
10340 loadDptrFromOperand (left, FALSE);
10342 /* so dptr now contains the address */
10343 aopOp (result, ic, FALSE);
10345 /* if bit then unpack */
10346 if (IS_BITFIELD (retype))
10347 ifxCond = genUnpackBits (result, "dptr", CPOINTER, ifx);
10350 size = AOP_SIZE (result);
10355 emitcode ("clr", "a");
10356 emitcode ("movc", "a,@a+dptr");
10358 aopPut (result, "a", offset++);
10360 emitcode ("inc", "dptr");
10364 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10366 aopPut (left, "dpl", 0);
10367 aopPut (left, "dph", 1);
10371 if (ifx && !ifx->generated)
10373 genIfxJump (ifx, ifxCond, left, NULL, result, ic->next);
10376 freeAsmop (result, NULL, ic, TRUE);
10377 freeAsmop (left, NULL, ic, TRUE);
10380 /*-----------------------------------------------------------------*/
10381 /* genGenPointerGet - get value from generic pointer space */
10382 /*-----------------------------------------------------------------*/
10384 genGenPointerGet (operand * left,
10385 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10388 char *ifxCond = "a";
10389 sym_link *retype = getSpec (operandType (result));
10391 D (emitcode (";", "genGenPointerGet"));
10393 aopOp (left, ic, FALSE);
10394 loadDptrFromOperand (left, TRUE);
10396 /* so dptr now contains the address */
10397 aopOp (result, ic, FALSE);
10399 /* if bit then unpack */
10400 if (IS_BITFIELD (retype))
10402 ifxCond = genUnpackBits (result, "dptr", GPOINTER, ifx);
10406 size = AOP_SIZE (result);
10411 emitcode ("lcall", "__gptrget");
10413 aopPut (result, "a", offset++);
10415 emitcode ("inc", "dptr");
10419 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10421 aopPut (left, "dpl", 0);
10422 aopPut (left, "dph", 1);
10426 if (ifx && !ifx->generated)
10428 genIfxJump (ifx, ifxCond, left, NULL, result, ic->next);
10431 freeAsmop (result, NULL, ic, TRUE);
10432 freeAsmop (left, NULL, ic, TRUE);
10435 /*-----------------------------------------------------------------*/
10436 /* genPointerGet - generate code for pointer get */
10437 /*-----------------------------------------------------------------*/
10439 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
10441 operand *left, *result;
10442 sym_link *type, *etype;
10445 D (emitcode (";", "genPointerGet"));
10447 left = IC_LEFT (ic);
10448 result = IC_RESULT (ic);
10450 if (getSize (operandType (result))>1)
10453 /* depending on the type of pointer we need to
10454 move it to the correct pointer register */
10455 type = operandType (left);
10456 etype = getSpec (type);
10457 /* if left is of type of pointer then it is simple */
10458 if (IS_PTR (type) && !IS_FUNC (type->next))
10460 p_type = DCL_TYPE (type);
10464 /* we have to go by the storage class */
10465 p_type = PTR_TYPE (SPEC_OCLS (etype));
10468 /* special case when cast remat */
10469 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10470 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10472 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10473 type = operandType (left);
10474 p_type = DCL_TYPE (type);
10476 /* now that we have the pointer type we assign
10477 the pointer values */
10483 genNearPointerGet (left, result, ic, pi, ifx);
10487 genPagedPointerGet (left, result, ic, pi, ifx);
10491 genFarPointerGet (left, result, ic, pi, ifx);
10495 genCodePointerGet (left, result, ic, pi, ifx);
10499 genGenPointerGet (left, result, ic, pi, ifx);
10505 /*-----------------------------------------------------------------*/
10506 /* genPackBits - generates code for packed bit storage */
10507 /*-----------------------------------------------------------------*/
10509 genPackBits (sym_link * etype,
10511 char *rname, int p_type)
10513 int offset = 0; /* source byte offset */
10514 int rlen = 0; /* remaining bitfield length */
10515 int blen; /* bitfield length */
10516 int bstr; /* bitfield starting bit within byte */
10517 int litval; /* source literal value (if AOP_LIT) */
10518 unsigned char mask; /* bitmask within current byte */
10520 D(emitcode (";", "genPackBits"));
10522 blen = SPEC_BLEN (etype);
10523 bstr = SPEC_BSTR (etype);
10525 /* If the bitfield length is less than a byte */
10528 mask = ((unsigned char) (0xFF << (blen + bstr)) |
10529 (unsigned char) (0xFF >> (8 - bstr)));
10531 if (AOP_TYPE (right) == AOP_LIT)
10533 /* Case with a bitfield length <8 and literal source
10535 litval = (int) ulFromVal (AOP (right)->aopu.aop_lit);
10537 litval &= (~mask) & 0xff;
10538 emitPtrByteGet (rname, p_type, FALSE);
10539 if ((mask|litval)!=0xff)
10540 emitcode ("anl","a,#0x%02x", mask);
10542 emitcode ("orl","a,#0x%02x", litval);
10546 if ((blen==1) && (p_type!=GPOINTER))
10548 /* Case with a bitfield length == 1 and no generic pointer
10550 if (AOP_TYPE (right) == AOP_CRY)
10551 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10554 MOVA (aopGet (right, 0, FALSE, FALSE));
10555 emitcode ("rrc","a");
10557 emitPtrByteGet (rname, p_type, FALSE);
10558 emitcode ("mov","acc.%d,c",bstr);
10563 /* Case with a bitfield length < 8 and arbitrary source
10565 MOVA (aopGet (right, 0, FALSE, FALSE));
10566 /* shift and mask source value */
10568 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10570 pushedB = pushB ();
10571 /* transfer A to B and get next byte */
10572 emitPtrByteGet (rname, p_type, TRUE);
10574 emitcode ("anl", "a,#0x%02x", mask);
10575 emitcode ("orl", "a,b");
10576 if (p_type == GPOINTER)
10577 emitcode ("pop", "b");
10583 emitPtrByteSet (rname, p_type, "a");
10587 /* Bit length is greater than 7 bits. In this case, copy */
10588 /* all except the partial byte at the end */
10589 for (rlen=blen;rlen>=8;rlen-=8)
10591 emitPtrByteSet (rname, p_type,
10592 aopGet (right, offset++, FALSE, TRUE) );
10594 emitcode ("inc", "%s", rname);
10597 /* If there was a partial byte at the end */
10600 mask = (((unsigned char) -1 << rlen) & 0xff);
10602 if (AOP_TYPE (right) == AOP_LIT)
10604 /* Case with partial byte and literal source
10606 litval = (int) ulFromVal (AOP (right)->aopu.aop_lit);
10607 litval >>= (blen-rlen);
10608 litval &= (~mask) & 0xff;
10609 emitPtrByteGet (rname, p_type, FALSE);
10610 if ((mask|litval)!=0xff)
10611 emitcode ("anl","a,#0x%02x", mask);
10613 emitcode ("orl","a,#0x%02x", litval);
10618 /* Case with partial byte and arbitrary source
10620 MOVA (aopGet (right, offset++, FALSE, FALSE));
10621 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10623 pushedB = pushB ();
10624 /* transfer A to B and get next byte */
10625 emitPtrByteGet (rname, p_type, TRUE);
10627 emitcode ("anl", "a,#0x%02x", mask);
10628 emitcode ("orl", "a,b");
10629 if (p_type == GPOINTER)
10630 emitcode ("pop", "b");
10634 emitPtrByteSet (rname, p_type, "a");
10639 /*-----------------------------------------------------------------*/
10640 /* genDataPointerSet - remat pointer to data space */
10641 /*-----------------------------------------------------------------*/
10643 genDataPointerSet (operand * right,
10647 int size, offset = 0;
10648 char *l, buffer[256];
10650 D (emitcode (";", "genDataPointerSet"));
10652 aopOp (right, ic, FALSE);
10654 l = aopGet (result, 0, FALSE, TRUE);
10656 size = max (AOP_SIZE (right), AOP_SIZE (result));
10660 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
10662 SNPRINTF (buffer, sizeof(buffer), "%s", l);
10663 emitcode ("mov", "%s,%s", buffer,
10664 aopGet (right, offset++, FALSE, FALSE));
10667 freeAsmop (right, NULL, ic, TRUE);
10668 freeAsmop (result, NULL, ic, TRUE);
10671 /*-----------------------------------------------------------------*/
10672 /* genNearPointerSet - emitcode for near pointer put */
10673 /*-----------------------------------------------------------------*/
10675 genNearPointerSet (operand * right,
10683 sym_link *retype, *letype;
10684 sym_link *ptype = operandType (result);
10686 D (emitcode (";", "genNearPointerSet"));
10688 retype = getSpec (operandType (right));
10689 letype = getSpec (ptype);
10691 aopOp (result, ic, FALSE);
10693 /* if the result is rematerializable &
10694 in data space & not a bit variable */
10695 if (AOP_TYPE (result) == AOP_IMMD &&
10696 DCL_TYPE (ptype) == POINTER &&
10697 !IS_BITVAR (retype) &&
10698 !IS_BITVAR (letype))
10700 genDataPointerSet (right, result, ic);
10704 /* if the value is already in a pointer register
10705 then don't need anything more */
10706 if (!AOP_INPREG (AOP (result)))
10708 if (IS_AOP_PREG (result))
10710 // Aha, it is a pointer, just in disguise.
10711 rname = aopGet (result, 0, FALSE, FALSE);
10714 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10715 __FILE__, __LINE__);
10720 emitcode ("mov", "a%s,%s", rname + 1, rname);
10721 rname++; // skip the '@'.
10726 /* otherwise get a free pointer register */
10727 aop = newAsmop (0);
10728 preg = getFreePtr (ic, &aop, FALSE);
10729 emitcode ("mov", "%s,%s",
10731 aopGet (result, 0, FALSE, TRUE));
10732 rname = preg->name;
10737 rname = aopGet (result, 0, FALSE, FALSE);
10740 aopOp (right, ic, FALSE);
10742 /* if bitfield then unpack the bits */
10743 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10744 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10747 /* we can just get the values */
10748 int size = AOP_SIZE (right);
10753 l = aopGet (right, offset, FALSE, TRUE);
10754 if ((*l == '@') || (strcmp (l, "acc") == 0))
10757 emitcode ("mov", "@%s,a", rname);
10760 emitcode ("mov", "@%s,%s", rname, l);
10762 emitcode ("inc", "%s", rname);
10767 /* now some housekeeping stuff */
10768 if (aop) /* we had to allocate for this iCode */
10771 aopPut (result, rname, 0);
10772 freeAsmop (NULL, aop, ic, TRUE);
10776 /* we did not allocate which means left
10777 already in a pointer register, then
10778 if size > 0 && this could be used again
10779 we have to point it back to where it
10781 if ((AOP_SIZE (right) > 1 &&
10782 !OP_SYMBOL (result)->remat &&
10783 (OP_SYMBOL (result)->liveTo > ic->seq ||
10787 int size = AOP_SIZE (right) - 1;
10789 emitcode ("dec", "%s", rname);
10796 freeAsmop (right, NULL, ic, TRUE);
10797 freeAsmop (result, NULL, ic, TRUE);
10800 /*-----------------------------------------------------------------*/
10801 /* genPagedPointerSet - emitcode for Paged pointer put */
10802 /*-----------------------------------------------------------------*/
10804 genPagedPointerSet (operand * right,
10812 sym_link *retype, *letype;
10814 D (emitcode (";", "genPagedPointerSet"));
10816 retype = getSpec (operandType (right));
10817 letype = getSpec (operandType (result));
10819 aopOp (result, ic, FALSE);
10821 /* if the value is already in a pointer register
10822 then don't need anything more */
10823 if (!AOP_INPREG (AOP (result)))
10825 if (IS_AOP_PREG (result))
10827 // Aha, it is a pointer, just in disguise.
10828 rname = aopGet (result, 0, FALSE, FALSE);
10831 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10832 __FILE__, __LINE__);
10837 emitcode ("mov", "a%s,%s", rname + 1, rname);
10838 rname++; // skip the '@'.
10843 /* otherwise get a free pointer register */
10844 aop = newAsmop (0);
10845 preg = getFreePtr (ic, &aop, FALSE);
10846 emitcode ("mov", "%s,%s",
10848 aopGet (result, 0, FALSE, TRUE));
10849 rname = preg->name;
10854 rname = aopGet (result, 0, FALSE, FALSE);
10857 aopOp (right, ic, FALSE);
10859 /* if bitfield then unpack the bits */
10860 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10861 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10864 /* we can just get the values */
10865 int size = AOP_SIZE (right);
10870 l = aopGet (right, offset, FALSE, TRUE);
10872 emitcode ("movx", "@%s,a", rname);
10874 emitcode ("inc", "%s", rname);
10879 /* now some housekeeping stuff */
10880 if (aop) /* we had to allocate for this iCode */
10883 aopPut (result, rname, 0);
10884 freeAsmop (NULL, aop, ic, TRUE);
10888 /* we did not allocate which means left
10889 already in a pointer register, then
10890 if size > 0 && this could be used again
10891 we have to point it back to where it
10893 if (AOP_SIZE (right) > 1 &&
10894 !OP_SYMBOL (result)->remat &&
10895 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth) &&
10898 int size = AOP_SIZE (right) - 1;
10900 emitcode ("dec", "%s", rname);
10907 freeAsmop (right, NULL, ic, TRUE);
10908 freeAsmop (result, NULL, ic, TRUE);
10911 /*-----------------------------------------------------------------*/
10912 /* genFarPointerSet - set value from far space */
10913 /*-----------------------------------------------------------------*/
10915 genFarPointerSet (operand * right,
10916 operand * result, iCode * ic, iCode * pi)
10919 sym_link *retype = getSpec (operandType (right));
10920 sym_link *letype = getSpec (operandType (result));
10922 D(emitcode (";", "genFarPointerSet"));
10924 aopOp (result, ic, FALSE);
10925 loadDptrFromOperand (result, FALSE);
10927 /* so dptr now contains the address */
10928 aopOp (right, ic, FALSE);
10930 /* if bit then unpack */
10931 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10932 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10935 size = AOP_SIZE (right);
10940 char *l = aopGet (right, offset++, FALSE, FALSE);
10942 emitcode ("movx", "@dptr,a");
10944 emitcode ("inc", "dptr");
10947 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10948 aopPut (result, "dpl", 0);
10949 aopPut (result, "dph", 1);
10952 freeAsmop (result, NULL, ic, TRUE);
10953 freeAsmop (right, NULL, ic, TRUE);
10956 /*-----------------------------------------------------------------*/
10957 /* genGenPointerSet - set value from generic pointer space */
10958 /*-----------------------------------------------------------------*/
10960 genGenPointerSet (operand * right,
10961 operand * result, iCode * ic, iCode * pi)
10964 sym_link *retype = getSpec (operandType (right));
10965 sym_link *letype = getSpec (operandType (result));
10967 D (emitcode (";", "genGenPointerSet"));
10969 aopOp (result, ic, FALSE);
10970 loadDptrFromOperand (result, TRUE);
10972 /* so dptr now contains the address */
10973 aopOp (right, ic, FALSE);
10975 /* if bit then unpack */
10976 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10978 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10982 size = AOP_SIZE (right);
10987 char *l = aopGet (right, offset++, FALSE, FALSE);
10989 emitcode ("lcall", "__gptrput");
10991 emitcode ("inc", "dptr");
10995 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10996 aopPut (result, "dpl", 0);
10997 aopPut (result, "dph", 1);
11000 freeAsmop (result, NULL, ic, TRUE);
11001 freeAsmop (right, NULL, ic, TRUE);
11004 /*-----------------------------------------------------------------*/
11005 /* genPointerSet - stores the value into a pointer location */
11006 /*-----------------------------------------------------------------*/
11008 genPointerSet (iCode * ic, iCode *pi)
11010 operand *right, *result;
11011 sym_link *type, *etype;
11014 D (emitcode (";", "genPointerSet"));
11016 right = IC_RIGHT (ic);
11017 result = IC_RESULT (ic);
11019 /* depending on the type of pointer we need to
11020 move it to the correct pointer register */
11021 type = operandType (result);
11022 etype = getSpec (type);
11023 /* if left is of type of pointer then it is simple */
11024 if (IS_PTR (type) && !IS_FUNC (type->next))
11026 p_type = DCL_TYPE (type);
11030 /* we have to go by the storage class */
11031 p_type = PTR_TYPE (SPEC_OCLS (etype));
11034 /* special case when cast remat */
11035 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
11036 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
11037 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
11038 type = operandType (result);
11039 p_type = DCL_TYPE (type);
11042 /* now that we have the pointer type we assign
11043 the pointer values */
11049 genNearPointerSet (right, result, ic, pi);
11053 genPagedPointerSet (right, result, ic, pi);
11057 genFarPointerSet (right, result, ic, pi);
11061 genGenPointerSet (right, result, ic, pi);
11065 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11066 "genPointerSet: illegal pointer type");
11070 /*-----------------------------------------------------------------*/
11071 /* genIfx - generate code for Ifx statement */
11072 /*-----------------------------------------------------------------*/
11074 genIfx (iCode * ic, iCode * popIc)
11076 operand *cond = IC_COND (ic);
11080 D (emitcode (";", "genIfx"));
11082 aopOp (cond, ic, FALSE);
11084 /* get the value into acc */
11085 if (AOP_TYPE (cond) != AOP_CRY)
11092 if (AOP(cond)->aopu.aop_dir)
11093 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
11096 /* the result is now in the accumulator or a directly addressable bit */
11097 freeAsmop (cond, NULL, ic, TRUE);
11099 /* if the condition is a bit variable */
11101 genIfxJump(ic, dup, NULL, NULL, NULL, popIc);
11102 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
11103 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL, popIc);
11104 else if (isbit && !IS_ITEMP (cond))
11105 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL, popIc);
11107 genIfxJump (ic, "a", NULL, NULL, NULL, popIc);
11112 /*-----------------------------------------------------------------*/
11113 /* genAddrOf - generates code for address of */
11114 /*-----------------------------------------------------------------*/
11116 genAddrOf (iCode * ic)
11118 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
11121 D (emitcode (";", "genAddrOf"));
11123 aopOp (IC_RESULT (ic), ic, FALSE);
11125 /* if the operand is on the stack then we
11126 need to get the stack offset of this
11130 /* if it has an offset then we need to compute it */
11133 int stack_offset = ((sym->stack < 0) ?
11134 ((char) (sym->stack - _G.nRegsSaved)) :
11135 ((char) sym->stack)) & 0xff;
11136 if ((abs(stack_offset) == 1) &&
11137 !AOP_NEEDSACC(IC_RESULT (ic)) &&
11138 !isOperandVolatile (IC_RESULT (ic), FALSE))
11140 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
11141 if (stack_offset > 0)
11142 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
11144 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
11148 emitcode ("mov", "a,%s", SYM_BP (sym));
11149 emitcode ("add", "a,#0x%02x", stack_offset & 0xff);
11150 aopPut (IC_RESULT (ic), "a", 0);
11155 /* we can just move _bp */
11156 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
11158 /* fill the result with zero */
11159 size = AOP_SIZE (IC_RESULT (ic)) - 1;
11164 aopPut (IC_RESULT (ic), zero, offset++);
11169 /* object not on stack then we need the name */
11170 size = getDataSize (IC_RESULT (ic));
11175 char s[SDCC_NAME_MAX];
11178 sprintf (s, "#(%s >> %d)",
11184 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11186 aopPut (IC_RESULT (ic), s, offset++);
11188 if (opIsGptr (IC_RESULT (ic)))
11191 SNPRINTF (buffer, sizeof(buffer),
11192 "#0x%02x", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
11193 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
11197 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11201 /*-----------------------------------------------------------------*/
11202 /* genFarFarAssign - assignment when both are in far space */
11203 /*-----------------------------------------------------------------*/
11205 genFarFarAssign (operand * result, operand * right, iCode * ic)
11207 int size = AOP_SIZE (right);
11211 D (emitcode (";", "genFarFarAssign"));
11213 /* first push the right side on to the stack */
11216 l = aopGet (right, offset++, FALSE, FALSE);
11218 emitcode ("push", "acc");
11221 freeAsmop (right, NULL, ic, FALSE);
11222 /* now assign DPTR to result */
11223 aopOp (result, ic, FALSE);
11224 size = AOP_SIZE (result);
11227 emitcode ("pop", "acc");
11228 aopPut (result, "a", --offset);
11230 freeAsmop (result, NULL, ic, FALSE);
11233 /*-----------------------------------------------------------------*/
11234 /* genAssign - generate code for assignment */
11235 /*-----------------------------------------------------------------*/
11237 genAssign (iCode * ic)
11239 operand *result, *right;
11241 unsigned long lit = 0L;
11243 D (emitcode (";", "genAssign"));
11245 result = IC_RESULT (ic);
11246 right = IC_RIGHT (ic);
11248 /* if they are the same */
11249 if (operandsEqu (result, right) &&
11250 !isOperandVolatile (result, FALSE) &&
11251 !isOperandVolatile (right, FALSE))
11254 aopOp (right, ic, FALSE);
11256 /* special case both in far space */
11257 if (AOP_TYPE (right) == AOP_DPTR &&
11258 IS_TRUE_SYMOP (result) &&
11259 isOperandInFarSpace (result))
11261 genFarFarAssign (result, right, ic);
11265 aopOp (result, ic, TRUE);
11267 /* if they are the same registers */
11268 if (sameRegs (AOP (right), AOP (result)) &&
11269 !isOperandVolatile (result, FALSE) &&
11270 !isOperandVolatile (right, FALSE))
11273 /* if the result is a bit */
11274 if (AOP_TYPE (result) == AOP_CRY)
11276 assignBit (result, right);
11280 /* bit variables done */
11282 size = getDataSize (result);
11284 if (AOP_TYPE (right) == AOP_LIT)
11285 lit = ulFromVal (AOP (right)->aopu.aop_lit);
11288 (AOP_TYPE (result) != AOP_REG) &&
11289 (AOP_TYPE (right) == AOP_LIT) &&
11290 !IS_FLOAT (operandType (right)) &&
11293 while ((size) && (lit))
11296 aopGet (right, offset, FALSE, FALSE),
11302 /* And now fill the rest with zeros. */
11305 emitcode ("clr", "a");
11309 aopPut (result, "a", offset);
11318 aopGet (right, offset, FALSE, FALSE),
11323 adjustArithmeticResult (ic);
11326 freeAsmop (result, NULL, ic, TRUE);
11327 freeAsmop (right, NULL, ic, TRUE);
11330 /*-----------------------------------------------------------------*/
11331 /* genJumpTab - generates code for jump table */
11332 /*-----------------------------------------------------------------*/
11334 genJumpTab (iCode * ic)
11336 symbol *jtab,*jtablo,*jtabhi;
11338 unsigned int count;
11340 D (emitcode (";", "genJumpTab"));
11342 count = elementsInSet( IC_JTLABELS (ic) );
11346 /* this algorithm needs 9 cycles and 7 + 3*n bytes
11347 if the switch argument is in a register.
11348 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
11349 /* Peephole may not convert ljmp to sjmp or ret
11350 labelIsReturnOnly & labelInRange must check
11351 currPl->ic->op != JUMPTABLE */
11352 aopOp (IC_JTCOND (ic), ic, FALSE);
11353 /* get the condition into accumulator */
11354 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11356 /* multiply by three */
11357 if (aopGetUsesAcc (IC_JTCOND (ic), 0))
11359 emitcode ("mov", "b,#0x03");
11360 emitcode ("mul", "ab");
11364 emitcode ("add", "a,acc");
11365 emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
11367 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11369 jtab = newiTempLabel (NULL);
11370 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
11371 emitcode ("jmp", "@a+dptr");
11373 /* now generate the jump labels */
11374 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11375 jtab = setNextItem (IC_JTLABELS (ic)))
11376 emitcode ("ljmp", "%05d$", jtab->key + 100);
11380 /* this algorithm needs 14 cycles and 13 + 2*n bytes
11381 if the switch argument is in a register.
11382 For n>6 this algorithm may be more compact */
11383 jtablo = newiTempLabel (NULL);
11384 jtabhi = newiTempLabel (NULL);
11386 /* get the condition into accumulator.
11387 Using b as temporary storage, if register push/pop is needed */
11388 aopOp (IC_JTCOND (ic), ic, FALSE);
11389 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11390 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
11391 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
11393 // (MB) what if B is in use???
11394 wassertl(!BINUSE, "B was in use");
11395 emitcode ("mov", "b,%s", l);
11398 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11402 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
11403 emitcode ("movc", "a,@a+pc");
11404 emitcode ("push", "acc");
11407 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
11408 emitcode ("movc", "a,@a+pc");
11409 emitcode ("push", "acc");
11413 /* this scales up to n<=255, but needs two more bytes
11414 and changes dptr */
11415 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
11416 emitcode ("movc", "a,@a+dptr");
11417 emitcode ("push", "acc");
11420 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
11421 emitcode ("movc", "a,@a+dptr");
11422 emitcode ("push", "acc");
11425 emitcode ("ret", "");
11427 /* now generate jump table, LSB */
11428 emitLabel (jtablo);
11429 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11430 jtab = setNextItem (IC_JTLABELS (ic)))
11431 emitcode (".db", "%05d$", jtab->key + 100);
11433 /* now generate jump table, MSB */
11434 emitLabel (jtabhi);
11435 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11436 jtab = setNextItem (IC_JTLABELS (ic)))
11437 emitcode (".db", "%05d$>>8", jtab->key + 100);
11441 /*-----------------------------------------------------------------*/
11442 /* genCast - gen code for casting */
11443 /*-----------------------------------------------------------------*/
11445 genCast (iCode * ic)
11447 operand *result = IC_RESULT (ic);
11448 sym_link *ctype = operandType (IC_LEFT (ic));
11449 sym_link *rtype = operandType (IC_RIGHT (ic));
11450 operand *right = IC_RIGHT (ic);
11453 D (emitcode (";", "genCast"));
11455 /* if they are equivalent then do nothing */
11456 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11459 aopOp (right, ic, FALSE);
11460 aopOp (result, ic, FALSE);
11462 /* if the result is a bit (and not a bitfield) */
11463 if (IS_BIT (OP_SYMBOL (result)->type))
11465 assignBit (result, right);
11469 /* if they are the same size : or less */
11470 if (AOP_SIZE (result) <= AOP_SIZE (right))
11473 /* if they are in the same place */
11474 if (sameRegs (AOP (right), AOP (result)))
11477 /* if they in different places then copy */
11478 size = AOP_SIZE (result);
11483 aopGet (right, offset, FALSE, FALSE),
11490 /* if the result is of type pointer */
11491 if (IS_PTR (ctype))
11495 sym_link *type = operandType (right);
11496 sym_link *etype = getSpec (type);
11498 /* pointer to generic pointer */
11499 if (IS_GENPTR (ctype))
11503 p_type = DCL_TYPE (type);
11507 if (SPEC_SCLS(etype)==S_REGISTER) {
11508 // let's assume it is a generic pointer
11511 /* we have to go by the storage class */
11512 p_type = PTR_TYPE (SPEC_OCLS (etype));
11516 /* the first two bytes are known */
11517 size = GPTRSIZE - 1;
11522 aopGet (right, offset, FALSE, FALSE),
11526 /* the last byte depending on type */
11528 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11533 // pointerTypeToGPByte will have bitched.
11537 sprintf(gpValStr, "#0x%02x", gpVal);
11538 aopPut (result, gpValStr, GPTRSIZE - 1);
11543 /* just copy the pointers */
11544 size = AOP_SIZE (result);
11549 aopGet (right, offset, FALSE, FALSE),
11556 /* so we now know that the size of destination is greater
11557 than the size of the source */
11558 /* we move to result for the size of source */
11559 size = AOP_SIZE (right);
11564 aopGet (right, offset, FALSE, FALSE),
11569 /* now depending on the sign of the source && destination */
11570 size = AOP_SIZE (result) - AOP_SIZE (right);
11571 /* if unsigned or not an integral type */
11572 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11575 aopPut (result, zero, offset++);
11579 /* we need to extend the sign :{ */
11580 char *l = aopGet (right, AOP_SIZE (right) - 1,
11583 emitcode ("rlc", "a");
11584 emitcode ("subb", "a,acc");
11586 aopPut (result, "a", offset++);
11589 /* we are done hurray !!!! */
11592 freeAsmop (result, NULL, ic, TRUE);
11593 freeAsmop (right, NULL, ic, TRUE);
11596 /*-----------------------------------------------------------------*/
11597 /* genDjnz - generate decrement & jump if not zero instrucion */
11598 /*-----------------------------------------------------------------*/
11600 genDjnz (iCode * ic, iCode * ifx)
11602 symbol *lbl, *lbl1;
11606 /* if the if condition has a false label
11607 then we cannot save */
11608 if (IC_FALSE (ifx))
11611 /* if the minus is not of the form a = a - 1 */
11612 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11613 !IS_OP_LITERAL (IC_RIGHT (ic)))
11616 if (operandLitValue (IC_RIGHT (ic)) != 1)
11619 /* if the size of this greater than one then no
11621 if (getSize (operandType (IC_RESULT (ic))) > 1)
11624 /* otherwise we can save BIG */
11626 D (emitcode (";", "genDjnz"));
11628 lbl = newiTempLabel (NULL);
11629 lbl1 = newiTempLabel (NULL);
11631 aopOp (IC_RESULT (ic), ic, FALSE);
11633 if (AOP_NEEDSACC(IC_RESULT(ic)))
11635 /* If the result is accessed indirectly via
11636 * the accumulator, we must explicitly write
11637 * it back after the decrement.
11639 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11641 if (strcmp(rByte, "a"))
11643 /* Something is hopelessly wrong */
11644 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11645 __FILE__, __LINE__);
11646 /* We can just give up; the generated code will be inefficient,
11647 * but what the hey.
11649 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11652 emitcode ("dec", "%s", rByte);
11653 aopPut (IC_RESULT (ic), rByte, 0);
11654 emitcode ("jnz", "%05d$", lbl->key + 100);
11656 else if (IS_AOP_PREG (IC_RESULT (ic)))
11658 emitcode ("dec", "%s",
11659 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11660 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11661 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11662 ifx->generated = 1;
11663 emitcode ("jnz", "%05d$", lbl->key + 100);
11667 emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11670 emitcode ("sjmp", "%05d$", lbl1->key + 100);
11672 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11675 if (!ifx->generated)
11676 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11677 ifx->generated = 1;
11681 /*-----------------------------------------------------------------*/
11682 /* genReceive - generate code for a receive iCode */
11683 /*-----------------------------------------------------------------*/
11685 genReceive (iCode * ic)
11687 int size = getSize (operandType (IC_RESULT (ic)));
11690 D (emitcode (";", "genReceive"));
11692 if (ic->argreg == 1)
11693 { /* first parameter */
11694 if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11695 isOperandInPagedSpace (IC_RESULT (ic))) &&
11696 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11697 IS_TRUE_SYMOP (IC_RESULT (ic))))
11700 int receivingA = 0;
11703 for (offset = 0; offset<size; offset++)
11704 if (!strcmp (fReturn[offset], "a"))
11709 if (size==1 || getTempRegs(tempRegs, size-1, ic))
11711 for (offset = size-1; offset>0; offset--)
11712 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11713 emitcode("mov","a,%s", fReturn[0]);
11715 aopOp (IC_RESULT (ic), ic, FALSE);
11717 aopPut (IC_RESULT (ic), "a", offset);
11718 for (offset = 1; offset<size; offset++)
11719 aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset);
11725 if (getTempRegs(tempRegs, size, ic))
11727 for (offset = 0; offset<size; offset++)
11728 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11729 aopOp (IC_RESULT (ic), ic, FALSE);
11730 for (offset = 0; offset<size; offset++)
11731 aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset);
11736 offset = fReturnSizeMCS51 - size;
11739 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11740 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11743 aopOp (IC_RESULT (ic), ic, FALSE);
11744 size = AOP_SIZE (IC_RESULT (ic));
11748 emitcode ("pop", "acc");
11749 aopPut (IC_RESULT (ic), "a", offset++);
11755 aopOp (IC_RESULT (ic), ic, FALSE);
11757 assignResultValue (IC_RESULT (ic), NULL);
11760 else if (ic->argreg > 12)
11761 { /* bit parameters */
11762 regs *reg = OP_SYMBOL (IC_RESULT (ic))->regs[0];
11765 if (!reg || reg->rIdx != ic->argreg-5)
11767 aopOp (IC_RESULT (ic), ic, FALSE);
11768 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11769 outBitC(IC_RESULT (ic));
11773 { /* other parameters */
11775 aopOp (IC_RESULT (ic), ic, FALSE);
11776 rb1off = ic->argreg;
11779 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
11784 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11787 /*-----------------------------------------------------------------*/
11788 /* genDummyRead - generate code for dummy read of volatiles */
11789 /*-----------------------------------------------------------------*/
11791 genDummyRead (iCode * ic)
11796 D (emitcode(";", "genDummyRead"));
11798 op = IC_RIGHT (ic);
11799 if (op && IS_SYMOP (op))
11801 aopOp (op, ic, FALSE);
11803 /* if the result is a bit */
11804 if (AOP_TYPE (op) == AOP_CRY)
11805 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11808 /* bit variables done */
11810 size = AOP_SIZE (op);
11814 MOVA (aopGet (op, offset, FALSE, FALSE));
11819 freeAsmop (op, NULL, ic, TRUE);
11823 if (op && IS_SYMOP (op))
11825 aopOp (op, ic, FALSE);
11827 /* if the result is a bit */
11828 if (AOP_TYPE (op) == AOP_CRY)
11829 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11832 /* bit variables done */
11834 size = AOP_SIZE (op);
11838 MOVA (aopGet (op, offset, FALSE, FALSE));
11843 freeAsmop (op, NULL, ic, TRUE);
11847 /*-----------------------------------------------------------------*/
11848 /* genCritical - generate code for start of a critical sequence */
11849 /*-----------------------------------------------------------------*/
11851 genCritical (iCode *ic)
11853 symbol *tlbl = newiTempLabel (NULL);
11855 D (emitcode(";", "genCritical"));
11857 if (IC_RESULT (ic))
11859 aopOp (IC_RESULT (ic), ic, TRUE);
11860 aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
11861 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11862 aopPut (IC_RESULT (ic), zero, 0);
11864 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11868 emitcode ("setb", "c");
11869 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11870 emitcode ("clr", "c");
11872 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11876 /*-----------------------------------------------------------------*/
11877 /* genEndCritical - generate code for end of a critical sequence */
11878 /*-----------------------------------------------------------------*/
11880 genEndCritical (iCode *ic)
11882 D(emitcode(";", "genEndCritical"));
11886 aopOp (IC_RIGHT (ic), ic, FALSE);
11887 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11889 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11890 emitcode ("mov", "ea,c");
11894 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11895 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11896 emitcode ("rrc", "a");
11897 emitcode ("mov", "ea,c");
11899 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11903 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11904 emitcode ("mov", "ea,c");
11908 /*-----------------------------------------------------------------*/
11909 /* gen51Code - generate code for 8051 based controllers */
11910 /*-----------------------------------------------------------------*/
11912 gen51Code (iCode * lic)
11916 /* int cseq = 0; */
11918 _G.currentFunc = NULL;
11919 lineHead = lineCurr = NULL;
11921 /* print the allocation information */
11922 if (allocInfo && currFunc)
11923 printAllocInfo (currFunc, codeOutBuf);
11924 /* if debug information required */
11925 if (options.debug && currFunc)
11927 debugFile->writeFunction (currFunc, lic);
11929 /* stack pointer name */
11930 if (options.useXstack)
11936 for (ic = lic; ic; ic = ic->next)
11938 _G.current_iCode = ic;
11940 if (ic->lineno && cln != ic->lineno)
11944 debugFile->writeCLine (ic);
11946 if (!options.noCcodeInAsm) {
11947 emitcode (";", "%s:%d: %s", ic->filename, ic->lineno,
11948 printCLine(ic->filename, ic->lineno));
11953 if (ic->seqPoint && ic->seqPoint != cseq)
11955 emitcode (";", "sequence point %d", ic->seqPoint);
11956 cseq = ic->seqPoint;
11959 if (options.iCodeInAsm) {
11960 char regsInUse[80];
11965 for (i=0; i<8; i++) {
11966 sprintf (®sInUse[i],
11967 "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11970 strcpy (regsInUse, "--------");
11971 for (i=0; i < 8; i++) {
11972 if (bitVectBitValue (ic->rMask, i))
11974 int offset = regs8051[i].offset;
11975 regsInUse[offset] = offset + '0'; /* show rMask */
11979 iLine = printILine(ic);
11980 emitcode(";", "[%s] ic:%d: %s", regsInUse, ic->seq, iLine);
11983 /* if the result is marked as
11984 spilt and rematerializable or code for
11985 this has already been generated then
11987 if (resultRemat (ic) || ic->generated)
11990 /* depending on the operation */
12011 iCode *ifxIc, *popIc;
12012 bool CommonRegs = FALSE;
12014 /* IPOP happens only when trying to restore a
12015 spilt live range, if there is an ifx statement
12016 following this pop (or several) then the if statement might
12017 be using some of the registers being popped which
12018 would destory the contents of the register so
12019 we need to check for this condition and handle it */
12020 for (ifxIc = ic->next; ifxIc && ifxIc->op == IPOP; ifxIc = ifxIc->next);
12021 for (popIc = ic; popIc && popIc->op == IPOP; popIc = popIc->next)
12022 CommonRegs |= (ifxIc && ifxIc->op == IFX && !ifxIc->generated &&
12023 regsInCommon (IC_LEFT (popIc), IC_COND (ifxIc)));
12025 genIfx (ifxIc, ic);
12044 genEndFunction (ic);
12064 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
12081 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
12085 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
12092 /* note these two are xlated by algebraic equivalence
12093 in decorateType() in SDCCast.c */
12094 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12095 "got '>=' or '<=' shouldn't have come here");
12099 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
12111 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
12115 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
12119 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
12155 genRightShift (ic);
12158 case GET_VALUE_AT_ADDRESS:
12160 hasInc (IC_LEFT (ic), ic,
12161 getSize (operandType (IC_RESULT (ic)))),
12162 ifxForOp (IC_RESULT (ic), ic) );
12166 if (POINTER_SET (ic))
12168 hasInc (IC_RESULT (ic), ic,
12169 getSize (operandType (IC_RIGHT (ic)))));
12195 addSet (&_G.sendSet, ic);
12198 case DUMMY_READ_VOLATILE:
12207 genEndCritical (ic);
12219 _G.current_iCode = NULL;
12221 /* now we are ready to call the
12222 peep hole optimizer */
12223 if (!options.nopeep)
12224 peepHole (&lineHead);
12226 /* now do the actual printing */
12227 printLine (lineHead, codeOutBuf);