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;
1674 // source is no literal and not in carry
1675 if ((s != zero) && (s != one) && strcmp (s, "c"))
1678 /* set C, if a >= 1 */
1679 emitcode ("add", "a,#0xff");
1682 // now source is zero, one or carry
1684 /* if result no bit variable */
1687 if (!strcmp (s, "c"))
1689 /* inefficient: move carry into A and use jz/jnz */
1690 emitcode ("clr", "a");
1691 emitcode ("rlc", "a");
1701 emitcode ("clr", "%s", d);
1703 emitcode ("setb", "%s", d);
1704 else if (strcmp (s, d))
1705 emitcode ("mov", "%s,c", d);
1710 if (strcmp (aop->aopu.aop_str[offset], s) || bvolatile)
1711 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1717 if (!offset && (strcmp (s, "acc") == 0) && !bvolatile)
1720 if (strcmp (aop->aopu.aop_str[offset], s) && !bvolatile)
1721 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1725 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1726 "aopPut got unsupported aop->type");
1735 /*-----------------------------------------------------------------*/
1736 /* pointToEnd :- points to the last byte of the operand */
1737 /*-----------------------------------------------------------------*/
1739 pointToEnd (asmop * aop)
1745 aop->coff = count = (aop->size - 1);
1751 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1755 emitcode ("inc", "dptr");
1762 /*-----------------------------------------------------------------*/
1763 /* reAdjustPreg - points a register back to where it should */
1764 /*-----------------------------------------------------------------*/
1766 reAdjustPreg (asmop * aop)
1768 if ((aop->coff==0) || (aop->size <= 1))
1776 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1781 emitcode ("lcall", "__decdptr");
1788 /*-----------------------------------------------------------------*/
1789 /* opIsGptr: returns non-zero if the passed operand is */
1790 /* a generic pointer type. */
1791 /*-----------------------------------------------------------------*/
1793 opIsGptr (operand * op)
1795 if (op && IS_GENPTR (operandType (op)) && (AOP_SIZE (op) == GPTRSIZE))
1802 /*-----------------------------------------------------------------*/
1803 /* getDataSize - get the operand data size */
1804 /*-----------------------------------------------------------------*/
1806 getDataSize (operand * op)
1808 int size = AOP_SIZE (op);
1810 if (size == GPTRSIZE)
1812 sym_link *type = operandType (op);
1813 if (IS_GENPTR (type))
1815 /* generic pointer; arithmetic operations
1816 * should ignore the high byte (pointer type).
1824 /*-----------------------------------------------------------------*/
1825 /* outAcc - output Acc */
1826 /*-----------------------------------------------------------------*/
1828 outAcc (operand * result)
1831 size = getDataSize (result);
1834 aopPut (result, "a", 0);
1837 /* unsigned or positive */
1840 aopPut (result, zero, offset++);
1845 /*-----------------------------------------------------------------*/
1846 /* outBitC - output a bit C */
1847 /*-----------------------------------------------------------------*/
1849 outBitC (operand * result)
1851 /* if the result is bit */
1852 if (AOP_TYPE (result) == AOP_CRY)
1854 if (!IS_OP_RUONLY (result))
1855 aopPut (result, "c", 0);
1857 else if (AOP_TYPE (result) != AOP_DUMMY)
1859 emitcode ("clr", "a");
1860 emitcode ("rlc", "a");
1865 /*-----------------------------------------------------------------*/
1866 /* toBoolean - emit code for orl a,operator(sizeop) */
1867 /*-----------------------------------------------------------------*/
1869 toBoolean (operand * oper)
1871 int size = AOP_SIZE (oper) - 1;
1873 bool AccUsed = FALSE;
1876 while (!AccUsed && size--)
1878 AccUsed |= aopGetUsesAcc(oper, offset++);
1881 size = AOP_SIZE (oper) - 1;
1883 MOVA (aopGet (oper, 0, FALSE, FALSE));
1884 if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1887 emitcode("mov", "b,a");
1890 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1891 emitcode ("orl", "b,a");
1893 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1894 emitcode ("orl", "a,b");
1901 emitcode ("orl", "a,%s",
1902 aopGet (oper, offset++, FALSE, FALSE));
1907 /*-----------------------------------------------------------------*/
1908 /* toCarry - make boolean and move into carry */
1909 /*-----------------------------------------------------------------*/
1911 toCarry (operand * oper)
1913 /* if the operand is a literal then
1914 we know what the value is */
1915 if (AOP_TYPE (oper) == AOP_LIT)
1917 if ((int) operandLitValue (oper))
1922 else if (AOP_TYPE (oper) == AOP_CRY)
1924 emitcode ("mov", "c,%s", oper->aop->aopu.aop_dir);
1928 /* or the operand into a */
1930 /* set C, if a >= 1 */
1931 emitcode ("add", "a,#0xff");
1935 /*-----------------------------------------------------------------*/
1936 /* assignBit - assign operand to bit operand */
1937 /*-----------------------------------------------------------------*/
1939 assignBit (operand * result, operand * right)
1941 /* if the right side is a literal then
1942 we know what the value is */
1943 if (AOP_TYPE (right) == AOP_LIT)
1945 if ((int) operandLitValue (right))
1946 aopPut (result, one, 0);
1948 aopPut (result, zero, 0);
1953 aopPut (result, "c", 0);
1958 /*-------------------------------------------------------------------*/
1959 /* xch_a_aopGet - for exchanging acc with value of the aop */
1960 /*-------------------------------------------------------------------*/
1962 xch_a_aopGet (operand * oper, int offset, bool bit16, bool dname)
1966 if (aopGetUsesAcc (oper, offset))
1968 emitcode("mov", "b,a");
1969 MOVA (aopGet (oper, offset, bit16, dname));
1970 emitcode("xch", "a,b");
1971 aopPut (oper, "a", offset);
1972 emitcode("xch", "a,b");
1977 l = aopGet (oper, offset, bit16, dname);
1978 emitcode("xch", "a,%s", l);
1984 /*-----------------------------------------------------------------*/
1985 /* genNot - generate code for ! operation */
1986 /*-----------------------------------------------------------------*/
1992 D (emitcode (";", "genNot"));
1994 /* assign asmOps to operand & result */
1995 aopOp (IC_LEFT (ic), ic, FALSE);
1996 aopOp (IC_RESULT (ic), ic, TRUE);
1998 /* if in bit space then a special case */
1999 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2001 /* if left==result then cpl bit */
2002 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2004 emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2008 toCarry (IC_LEFT (ic));
2009 emitcode ("cpl", "c");
2010 outBitC (IC_RESULT (ic));
2015 toBoolean (IC_LEFT (ic));
2017 /* set C, if a == 0 */
2018 tlbl = newiTempLabel (NULL);
2019 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
2021 outBitC (IC_RESULT (ic));
2024 /* release the aops */
2025 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2026 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2030 /*-----------------------------------------------------------------*/
2031 /* genCpl - generate code for complement */
2032 /*-----------------------------------------------------------------*/
2039 sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
2041 D(emitcode (";", "genCpl"));
2043 /* assign asmOps to operand & result */
2044 aopOp (IC_LEFT (ic), ic, FALSE);
2045 aopOp (IC_RESULT (ic), ic, TRUE);
2047 /* special case if in bit space */
2048 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2052 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
2053 (SPEC_USIGN (letype) && IS_CHAR (letype)))
2055 /* promotion rules are responsible for this strange result:
2056 bit -> int -> ~int -> bit
2057 uchar -> int -> ~int -> bit
2059 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
2063 tlbl=newiTempLabel(NULL);
2064 l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
2065 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
2066 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
2067 IS_AOP_PREG (IC_LEFT (ic)))
2069 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
2074 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
2077 outBitC (IC_RESULT(ic));
2081 size = AOP_SIZE (IC_RESULT (ic));
2084 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2086 emitcode ("cpl", "a");
2087 aopPut (IC_RESULT (ic), "a", offset++);
2092 /* release the aops */
2093 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2094 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2097 /*-----------------------------------------------------------------*/
2098 /* genUminusFloat - unary minus for floating points */
2099 /*-----------------------------------------------------------------*/
2101 genUminusFloat (operand * op, operand * result)
2103 int size, offset = 0;
2106 D (emitcode (";", "genUminusFloat"));
2108 /* for this we just copy and then flip the bit */
2110 size = AOP_SIZE (op) - 1;
2115 aopGet (op, offset, FALSE, FALSE),
2120 l = aopGet (op, offset, FALSE, FALSE);
2123 emitcode ("cpl", "acc.7");
2124 aopPut (result, "a", offset);
2127 /*-----------------------------------------------------------------*/
2128 /* genUminus - unary minus code generation */
2129 /*-----------------------------------------------------------------*/
2131 genUminus (iCode * ic)
2136 D (emitcode (";", "genUminus"));
2139 aopOp (IC_LEFT (ic), ic, FALSE);
2140 aopOp (IC_RESULT (ic), ic, TRUE);
2142 /* if both in bit space then special
2144 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2145 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2148 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2149 emitcode ("cpl", "c");
2150 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2154 optype = operandType (IC_LEFT (ic));
2156 /* if float then do float stuff */
2157 if (IS_FLOAT (optype))
2159 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2163 /* otherwise subtract from zero */
2164 size = AOP_SIZE (IC_LEFT (ic));
2168 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2169 if (!strcmp (l, "a"))
2173 emitcode ("cpl", "a");
2174 emitcode ("addc", "a,#0x00");
2180 emitcode ("clr", "a");
2181 emitcode ("subb", "a,%s", l);
2183 aopPut (IC_RESULT (ic), "a", offset++);
2186 /* if any remaining bytes in the result */
2187 /* we just need to propagate the sign */
2188 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2190 emitcode ("rlc", "a");
2191 emitcode ("subb", "a,acc");
2193 aopPut (IC_RESULT (ic), "a", offset++);
2197 /* release the aops */
2198 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2199 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2202 /*-----------------------------------------------------------------*/
2203 /* saveRegisters - will look for a call and save the registers */
2204 /*-----------------------------------------------------------------*/
2206 saveRegisters (iCode * lic)
2213 for (ic = lic; ic; ic = ic->next)
2214 if (ic->op == CALL || ic->op == PCALL)
2219 fprintf (stderr, "found parameter push with no function call\n");
2223 /* if the registers have been saved already or don't need to be then
2227 if (IS_SYMOP(IC_LEFT(ic)) &&
2228 (IFFUNC_CALLEESAVES (OP_SYMBOL (IC_LEFT (ic))->type) ||
2229 IFFUNC_ISNAKED (OP_SYM_TYPE (IC_LEFT (ic)))))
2232 /* save the registers in use at this time but skip the
2233 ones for the result */
2234 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2235 mcs51_rUmaskForOp (IC_RESULT(ic)));
2238 if (options.useXstack)
2240 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2241 int nBits = bitVectnBitsOn (rsavebits);
2242 int count = bitVectnBitsOn (rsave);
2246 count = count - nBits + 1;
2247 /* remove all but the first bits as they are pushed all at once */
2248 rsave = bitVectCplAnd (rsave, rsavebits);
2249 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2251 freeBitVect (rsavebits);
2255 regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2256 if (reg->type == REG_BIT)
2258 emitcode ("mov", "a,%s", reg->base);
2262 emitcode ("mov", "a,%s", reg->name);
2264 emitcode ("mov", "r0,%s", spname);
2265 emitcode ("inc", "%s", spname);// allocate before use
2266 emitcode ("movx", "@r0,a");
2267 if (bitVectBitValue (rsave, R0_IDX))
2268 emitcode ("mov", "r0,a");
2270 else if (count != 0)
2272 if (bitVectBitValue (rsave, R0_IDX))
2274 emitcode ("push", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2276 emitcode ("mov", "r0,%s", spname);
2278 emitcode ("add", "a,#0x%02x", count);
2279 emitcode ("mov", "%s,a", spname);
2280 for (i = 0; i < mcs51_nRegs; i++)
2282 if (bitVectBitValue (rsave, i))
2284 regs * reg = REG_WITH_INDEX (i);
2287 emitcode ("pop", "acc");
2288 emitcode ("push", "acc");
2290 else if (reg->type == REG_BIT)
2292 emitcode ("mov", "a,%s", reg->base);
2296 emitcode ("mov", "a,%s", reg->name);
2298 emitcode ("movx", "@r0,a");
2301 emitcode ("inc", "r0");
2305 if (bitVectBitValue (rsave, R0_IDX))
2307 emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2313 bool bits_pushed = FALSE;
2314 for (i = 0; i < mcs51_nRegs; i++)
2316 if (bitVectBitValue (rsave, i))
2318 bits_pushed = pushReg (i, bits_pushed);
2322 freeBitVect (rsave);
2325 /*-----------------------------------------------------------------*/
2326 /* unsaveRegisters - pop the pushed registers */
2327 /*-----------------------------------------------------------------*/
2329 unsaveRegisters (iCode * ic)
2334 /* restore the registers in use at this time but skip the
2335 ones for the result */
2336 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2337 mcs51_rUmaskForOp (IC_RESULT(ic)));
2339 if (options.useXstack)
2341 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2342 int nBits = bitVectnBitsOn (rsavebits);
2343 int count = bitVectnBitsOn (rsave);
2347 count = count - nBits + 1;
2348 /* remove all but the first bits as they are popped all at once */
2349 rsave = bitVectCplAnd (rsave, rsavebits);
2350 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2352 freeBitVect (rsavebits);
2356 regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2357 emitcode ("mov", "r0,%s", spname);
2358 emitcode ("dec", "r0");
2359 emitcode ("movx", "a,@r0");
2360 if (reg->type == REG_BIT)
2362 emitcode ("mov", "%s,a", reg->base);
2366 emitcode ("mov", "%s,a", reg->name);
2368 emitcode ("dec", "%s", spname);
2370 else if (count != 0)
2372 emitcode ("mov", "r0,%s", spname);
2373 for (i = mcs51_nRegs; i >= 0; i--)
2375 if (bitVectBitValue (rsave, i))
2377 regs * reg = REG_WITH_INDEX (i);
2378 emitcode ("dec", "r0");
2379 emitcode ("movx", "a,@r0");
2382 emitcode ("push", "acc");
2384 else if (reg->type == REG_BIT)
2386 emitcode ("mov", "%s,a", reg->base);
2390 emitcode ("mov", "%s,a", reg->name);
2394 emitcode ("mov", "%s,r0", spname);
2395 if (bitVectBitValue (rsave, R0_IDX))
2397 emitcode ("pop", "ar0");
2403 bool bits_popped = FALSE;
2404 for (i = mcs51_nRegs; i >= 0; i--)
2406 if (bitVectBitValue (rsave, i))
2408 bits_popped = popReg (i, bits_popped);
2412 freeBitVect (rsave);
2416 /*-----------------------------------------------------------------*/
2418 /*-----------------------------------------------------------------*/
2420 pushSide (operand * oper, int size, iCode * ic)
2423 int nPushed = _G.r0Pushed + _G.r1Pushed;
2425 aopOp (oper, ic, FALSE);
2427 if (nPushed != _G.r0Pushed + _G.r1Pushed)
2429 while (offset < size)
2431 char *l = aopGet (oper, offset, FALSE, TRUE);
2432 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2434 freeAsmop (oper, NULL, ic, TRUE);
2436 while (offset < size)
2438 emitcode ("push", "%s", fReturn[offset++]);
2445 char *l = aopGet (oper, offset++, FALSE, TRUE);
2446 if (AOP_TYPE (oper) != AOP_REG &&
2447 AOP_TYPE (oper) != AOP_DIR &&
2451 emitcode ("push", "acc");
2455 emitcode ("push", "%s", l);
2459 freeAsmop (oper, NULL, ic, TRUE);
2462 /*-----------------------------------------------------------------*/
2463 /* assignResultValue - also indicates if acc is in use afterwards */
2464 /*-----------------------------------------------------------------*/
2466 assignResultValue (operand * oper, operand * func)
2469 int size = AOP_SIZE (oper);
2470 bool accuse = FALSE;
2471 bool pushedA = FALSE;
2473 if (func && IS_BIT (OP_SYM_ETYPE (func)))
2479 if ((size > 3) && aopPutUsesAcc (oper, fReturn[offset], offset))
2481 emitcode ("push", "acc");
2486 if ((offset == 3) && pushedA)
2487 emitcode ("pop", "acc");
2488 accuse |= aopPut (oper, fReturn[offset], offset);
2495 /*-----------------------------------------------------------------*/
2496 /* genXpush - pushes onto the external stack */
2497 /*-----------------------------------------------------------------*/
2499 genXpush (iCode * ic)
2501 asmop *aop = newAsmop (0);
2503 int size, offset = 0;
2505 D (emitcode (";", "genXpush"));
2507 aopOp (IC_LEFT (ic), ic, FALSE);
2508 r = getFreePtr (ic, &aop, FALSE);
2510 size = AOP_SIZE (IC_LEFT (ic));
2514 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2515 emitcode ("mov", "%s,%s", r->name, spname);
2516 emitcode ("inc", "%s", spname); // allocate space first
2517 emitcode ("movx", "@%s,a", r->name);
2521 // allocate space first
2522 emitcode ("mov", "%s,%s", r->name, spname);
2524 emitcode ("add", "a,#0x%02x", size);
2525 emitcode ("mov", "%s,a", spname);
2529 MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2530 emitcode ("movx", "@%s,a", r->name);
2531 emitcode ("inc", "%s", r->name);
2535 freeAsmop (NULL, aop, ic, TRUE);
2536 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2539 /*-----------------------------------------------------------------*/
2540 /* genIpush - generate code for pushing this gets a little complex */
2541 /*-----------------------------------------------------------------*/
2543 genIpush (iCode * ic)
2545 int size, offset = 0;
2549 D (emitcode (";", "genIpush"));
2551 /* if this is not a parm push : ie. it is spill push
2552 and spill push is always done on the local stack */
2556 /* and the item is spilt then do nothing */
2557 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2560 aopOp (IC_LEFT (ic), ic, FALSE);
2561 size = AOP_SIZE (IC_LEFT (ic));
2562 /* push it on the stack */
2565 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2571 emitcode ("push", "%s", l);
2576 /* this is a parameter push: in this case we call
2577 the routine to find the call and save those
2578 registers that need to be saved */
2581 /* if use external stack then call the external
2582 stack pushing routine */
2583 if (options.useXstack)
2589 /* then do the push */
2590 aopOp (IC_LEFT (ic), ic, FALSE);
2592 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2593 size = AOP_SIZE (IC_LEFT (ic));
2597 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2598 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2599 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR)
2601 if (strcmp (l, prev) || *l == '@')
2603 emitcode ("push", "acc");
2607 emitcode ("push", "%s", l);
2612 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2615 /*-----------------------------------------------------------------*/
2616 /* genIpop - recover the registers: can happen only for spilling */
2617 /*-----------------------------------------------------------------*/
2619 genIpop (iCode * ic)
2623 D (emitcode (";", "genIpop"));
2625 /* if the temp was not pushed then */
2626 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2629 aopOp (IC_LEFT (ic), ic, FALSE);
2630 size = AOP_SIZE (IC_LEFT (ic));
2631 offset = (size - 1);
2634 emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2638 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2641 /*-----------------------------------------------------------------*/
2642 /* saveRBank - saves an entire register bank on the stack */
2643 /*-----------------------------------------------------------------*/
2645 saveRBank (int bank, iCode * ic, bool pushPsw)
2648 int count = 8 + (pushPsw ? 1 : 0);
2652 if (options.useXstack)
2656 /* Assume r0 is available for use. */
2657 r = REG_WITH_INDEX (R0_IDX);
2662 r = getFreePtr (ic, &aop, FALSE);
2664 // allocate space first
2665 emitcode ("mov", "%s,%s", r->name, spname);
2667 emitcode ("add", "a,#0x%02x", count);
2668 emitcode ("mov", "%s,a", spname);
2671 for (i = 0; i < 8; i++)
2673 if (options.useXstack)
2675 emitcode ("mov", "a,(%s+%d)",
2676 regs8051[i].base, 8 * bank + regs8051[i].offset);
2677 emitcode ("movx", "@%s,a", r->name);
2679 emitcode ("inc", "%s", r->name);
2682 emitcode ("push", "(%s+%d)",
2683 regs8051[i].base, 8 * bank + regs8051[i].offset);
2688 if (options.useXstack)
2690 emitcode ("mov", "a,psw");
2691 emitcode ("movx", "@%s,a", r->name);
2695 emitcode ("push", "psw");
2698 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2703 freeAsmop (NULL, aop, ic, TRUE);
2712 /*-----------------------------------------------------------------*/
2713 /* unsaveRBank - restores the register bank from stack */
2714 /*-----------------------------------------------------------------*/
2716 unsaveRBank (int bank, iCode * ic, bool popPsw)
2722 if (options.useXstack)
2726 /* Assume r0 is available for use. */
2727 r = REG_WITH_INDEX (R0_IDX);;
2732 r = getFreePtr (ic, &aop, FALSE);
2734 emitcode ("mov", "%s,%s", r->name, spname);
2739 if (options.useXstack)
2741 emitcode ("dec", "%s", r->name);
2742 emitcode ("movx", "a,@%s", r->name);
2743 emitcode ("mov", "psw,a");
2747 emitcode ("pop", "psw");
2751 for (i = 7; i >= 0; i--)
2753 if (options.useXstack)
2755 emitcode ("dec", "%s", r->name);
2756 emitcode ("movx", "a,@%s", r->name);
2757 emitcode ("mov", "(%s+%d),a",
2758 regs8051[i].base, 8 * bank + regs8051[i].offset);
2762 emitcode ("pop", "(%s+%d)",
2763 regs8051[i].base, 8 * bank + regs8051[i].offset);
2767 if (options.useXstack)
2769 emitcode ("mov", "%s,%s", spname, r->name);
2774 freeAsmop (NULL, aop, ic, TRUE);
2778 /*-----------------------------------------------------------------*/
2779 /* genSend - gen code for SEND */
2780 /*-----------------------------------------------------------------*/
2781 static void genSend(set *sendSet)
2786 /* first we do all bit parameters */
2787 for (sic = setFirstItem (sendSet); sic;
2788 sic = setNextItem (sendSet))
2790 if (sic->argreg > 12)
2792 int bit = sic->argreg-13;
2794 aopOp (IC_LEFT (sic), sic, FALSE);
2796 /* if left is a literal then
2797 we know what the value is */
2798 if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2800 if (((int) operandLitValue (IC_LEFT (sic))))
2801 emitcode ("setb", "b[%d]", bit);
2803 emitcode ("clr", "b[%d]", bit);
2808 toCarry (IC_LEFT (sic));
2809 emitcode ("mov", "b[%d],c", bit);
2814 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2820 saveRegisters (setFirstItem (sendSet));
2821 emitcode ("mov", "bits,b");
2824 /* then we do all other parameters */
2825 for (sic = setFirstItem (sendSet); sic;
2826 sic = setNextItem (sendSet))
2828 if (sic->argreg <= 12)
2830 int size, offset = 0;
2831 aopOp (IC_LEFT (sic), sic, FALSE);
2832 size = AOP_SIZE (IC_LEFT (sic));
2834 if (sic->argreg == 1)
2838 char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2839 if (strcmp (l, fReturn[offset]))
2841 emitcode ("mov", "%s,%s", fReturn[offset], l);
2850 emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2851 aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2855 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2860 /*-----------------------------------------------------------------*/
2861 /* selectRegBank - emit code to select the register bank */
2862 /*-----------------------------------------------------------------*/
2864 selectRegBank (short bank, bool keepFlags)
2866 /* if f.e. result is in carry */
2869 emitcode ("anl", "psw,#0xE7");
2871 emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2875 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2879 /*-----------------------------------------------------------------*/
2880 /* genCall - generates a call statement */
2881 /*-----------------------------------------------------------------*/
2883 genCall (iCode * ic)
2887 // bool restoreBank = FALSE;
2888 bool swapBanks = FALSE;
2889 bool accuse = FALSE;
2890 bool accPushed = FALSE;
2891 bool resultInF0 = FALSE;
2892 bool assignResultGenerated = FALSE;
2894 D (emitcode (";", "genCall"));
2896 dtype = operandType (IC_LEFT (ic));
2897 etype = getSpec(dtype);
2898 /* if send set is not empty then assign */
2901 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2902 genSend(reverseSet(_G.sendSet));
2904 genSend(_G.sendSet);
2909 /* if we are calling a not _naked function that is not using
2910 the same register bank then we need to save the
2911 destination registers on the stack */
2912 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2913 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2914 !IFFUNC_ISISR (dtype))
2919 /* if caller saves & we have not saved then */
2925 emitcode ("mov", "psw,#0x%02x",
2926 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2930 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2932 if (IFFUNC_CALLEESAVES(dtype))
2934 werror (E_BANKED_WITH_CALLEESAVES);
2938 char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2939 OP_SYMBOL (IC_LEFT (ic))->rname :
2940 OP_SYMBOL (IC_LEFT (ic))->name);
2942 emitcode ("mov", "r0,#%s", l);
2943 emitcode ("mov", "r1,#(%s >> 8)", l);
2944 emitcode ("mov", "r2,#(%s >> 16)", l);
2945 emitcode ("lcall", "__sdcc_banked_call");
2950 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2951 OP_SYMBOL (IC_LEFT (ic))->rname :
2952 OP_SYMBOL (IC_LEFT (ic))->name));
2957 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2960 /* if we need assign a result value */
2961 if ((IS_ITEMP (IC_RESULT (ic)) &&
2962 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2963 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2964 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2965 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2966 IS_TRUE_SYMOP (IC_RESULT (ic)))
2970 aopOp (IC_RESULT (ic), ic, FALSE);
2973 accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2974 assignResultGenerated = TRUE;
2976 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2979 /* adjust the stack for parameters if required */
2983 if (ic->parmBytes > 3)
2987 emitcode ("push", "acc");
2990 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2991 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2992 !assignResultGenerated)
2994 emitcode ("mov", "F0,c");
2998 emitcode ("mov", "a,%s", spname);
2999 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3000 emitcode ("mov", "%s,a", spname);
3002 /* unsaveRegisters from xstack needs acc, but */
3003 /* unsaveRegisters from stack needs this popped */
3004 if (accPushed && !options.useXstack)
3006 emitcode ("pop", "acc");
3011 for (i = 0; i < ic->parmBytes; i++)
3012 emitcode ("dec", "%s", spname);
3015 /* if we had saved some registers then unsave them */
3016 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3018 if (accuse && !accPushed && options.useXstack)
3020 /* xstack needs acc, but doesn't touch normal stack */
3021 emitcode ("push", "acc");
3024 unsaveRegisters (ic);
3027 // /* if register bank was saved then pop them */
3029 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
3031 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
3034 emitcode ("mov", "c,F0");
3036 aopOp (IC_RESULT (ic), ic, FALSE);
3037 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3038 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3042 emitcode ("pop", "acc");
3045 /*-----------------------------------------------------------------*/
3046 /* genPcall - generates a call by pointer statement */
3047 /*-----------------------------------------------------------------*/
3049 genPcall (iCode * ic)
3053 symbol *rlbl = newiTempLabel (NULL);
3054 // bool restoreBank=FALSE;
3055 bool swapBanks = FALSE;
3056 bool resultInF0 = FALSE;
3058 D (emitcode (";", "genPcall"));
3060 dtype = operandType (IC_LEFT (ic))->next;
3061 etype = getSpec(dtype);
3062 /* if caller saves & we have not saved then */
3066 /* if we are calling a not _naked function that is not using
3067 the same register bank then we need to save the
3068 destination registers on the stack */
3069 if (currFunc && dtype && !IFFUNC_ISNAKED (dtype) &&
3070 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
3071 !IFFUNC_ISISR (dtype))
3073 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3074 // restoreBank=TRUE;
3076 // need caution message to user here
3079 if (IS_LITERAL (etype))
3081 /* if send set is not empty then assign */
3084 genSend(reverseSet(_G.sendSet));
3090 emitcode ("mov", "psw,#0x%02x",
3091 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3094 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT (getSpec(dtype)))
3096 if (IFFUNC_CALLEESAVES (dtype))
3098 werror (E_BANKED_WITH_CALLEESAVES);
3102 char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
3104 emitcode ("mov", "r0,#%s", l);
3105 emitcode ("mov", "r1,#(%s >> 8)", l);
3106 emitcode ("mov", "r2,#(%s >> 16)", l);
3107 emitcode ("lcall", "__sdcc_banked_call");
3112 emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
3117 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT (getSpec(dtype)))
3119 if (IFFUNC_CALLEESAVES (dtype))
3121 werror (E_BANKED_WITH_CALLEESAVES);
3125 aopOp (IC_LEFT (ic), ic, FALSE);
3129 /* what if aopGet needs r0 or r1 ??? */
3130 emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3131 emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3132 emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3136 int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
3137 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3138 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3139 emitcode ("mov", "0x%02x,%s", reg, aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3142 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3144 /* if send set is not empty then assign */
3147 genSend(reverseSet(_G.sendSet));
3153 emitcode ("mov", "psw,#0x%02x",
3154 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3158 emitcode ("lcall", "__sdcc_banked_call");
3161 else if (_G.sendSet)
3163 /* push the return address on to the stack */
3164 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
3165 emitcode ("push", "acc");
3166 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
3167 emitcode ("push", "acc");
3169 /* now push the function address */
3170 pushSide (IC_LEFT (ic), FPTRSIZE, ic);
3172 /* if send set is not empty then assign */
3175 genSend(reverseSet(_G.sendSet));
3181 emitcode ("mov", "psw,#0x%02x",
3182 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3186 emitcode ("ret", "");
3189 else /* the send set is empty */
3192 /* now get the calling address into dptr */
3193 aopOp (IC_LEFT (ic), ic, FALSE);
3195 l = aopGet (IC_LEFT (ic), 0, FALSE, FALSE);
3196 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3198 emitcode ("mov", "r0,%s", l);
3199 l = aopGet (IC_LEFT (ic), 1, FALSE, FALSE);
3200 emitcode ("mov", "dph,%s", l);
3201 emitcode ("mov", "dpl,r0");
3205 emitcode ("mov", "dpl,%s", l);
3206 l = aopGet (IC_LEFT (ic), 1, FALSE, FALSE);
3207 emitcode ("mov", "dph,%s", l);
3210 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3214 emitcode ("mov", "psw,#0x%02x",
3215 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3219 emitcode ("lcall", "__sdcc_call_dptr");
3224 selectRegBank (FUNC_REGBANK (currFunc->type), IS_BIT (etype));
3227 /* if we need assign a result value */
3228 if ((IS_ITEMP (IC_RESULT (ic)) &&
3229 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3230 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3231 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3232 IS_TRUE_SYMOP (IC_RESULT (ic)))
3236 aopOp (IC_RESULT (ic), ic, FALSE);
3239 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3241 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3244 /* adjust the stack for parameters if required */
3248 if (ic->parmBytes > 3)
3250 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3251 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3253 emitcode ("mov", "F0,c");
3257 emitcode ("mov", "a,%s", spname);
3258 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3259 emitcode ("mov", "%s,a", spname);
3262 for (i = 0; i < ic->parmBytes; i++)
3263 emitcode ("dec", "%s", spname);
3266 // /* if register bank was saved then unsave them */
3268 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3270 /* if we had saved some registers then unsave them */
3271 if (ic->regsSaved && !IFFUNC_CALLEESAVES (dtype))
3272 unsaveRegisters (ic);
3274 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3277 emitcode ("mov", "c,F0");
3279 aopOp (IC_RESULT (ic), ic, FALSE);
3280 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3281 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3285 /*-----------------------------------------------------------------*/
3286 /* resultRemat - result is rematerializable */
3287 /*-----------------------------------------------------------------*/
3289 resultRemat (iCode * ic)
3291 if (SKIP_IC (ic) || ic->op == IFX)
3294 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3296 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3297 if (sym->remat && !POINTER_SET (ic))
3304 /*-----------------------------------------------------------------*/
3305 /* inExcludeList - return 1 if the string is in exclude Reg list */
3306 /*-----------------------------------------------------------------*/
3308 regsCmp(void *p1, void *p2)
3310 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3314 inExcludeList (char *s)
3316 const char *p = setFirstItem(options.excludeRegsSet);
3318 if (p == NULL || STRCASECMP(p, "none") == 0)
3322 return isinSetWith(options.excludeRegsSet, s, regsCmp);
3325 /*-----------------------------------------------------------------*/
3326 /* genFunction - generated code for function entry */
3327 /*-----------------------------------------------------------------*/
3329 genFunction (iCode * ic)
3331 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3333 bool switchedPSW = FALSE;
3334 int calleesaves_saved_register = -1;
3335 int stackAdjust = sym->stack;
3336 int accIsFree = sym->recvSize < 4;
3337 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3338 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3341 /* create the function header */
3342 emitcode (";", "-----------------------------------------");
3343 emitcode (";", " function %s", sym->name);
3344 emitcode (";", "-----------------------------------------");
3346 emitcode ("", "%s:", sym->rname);
3347 lineCurr->isLabel = 1;
3348 ftype = operandType (IC_LEFT (ic));
3349 _G.currentFunc = sym;
3351 if (IFFUNC_ISNAKED(ftype))
3353 emitcode(";", "naked function: no prologue.");
3357 /* here we need to generate the equates for the
3358 register bank if required */
3359 if (FUNC_REGBANK (ftype) != rbank)
3363 rbank = FUNC_REGBANK (ftype);
3364 for (i = 0; i < mcs51_nRegs; i++)
3366 if (regs8051[i].type != REG_BIT)
3368 if (strcmp (regs8051[i].base, "0") == 0)
3369 emitcode ("", "%s = 0x%02x",
3371 8 * rbank + regs8051[i].offset);
3373 emitcode ("", "%s = %s + 0x%02x",
3376 8 * rbank + regs8051[i].offset);
3381 /* if this is an interrupt service routine then
3382 save acc, b, dpl, dph */
3383 if (IFFUNC_ISISR (sym->type))
3387 rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), sym->regsUsed);
3388 if (IFFUNC_HASFCALL(sym->type) || !bitVectIsZero (rsavebits))
3390 emitcode ("push", "bits");
3393 freeBitVect (rsavebits);
3395 if (!inExcludeList ("acc"))
3396 emitcode ("push", "acc");
3397 if (!inExcludeList ("b"))
3398 emitcode ("push", "b");
3399 if (!inExcludeList ("dpl"))
3400 emitcode ("push", "dpl");
3401 if (!inExcludeList ("dph"))
3402 emitcode ("push", "dph");
3403 /* if this isr has no bank i.e. is going to
3404 run with bank 0 , then we need to save more
3406 if (!FUNC_REGBANK (sym->type))
3410 /* if this function does not call any other
3411 function then we can be economical and
3412 save only those registers that are used */
3413 if (!IFFUNC_HASFCALL(sym->type))
3415 /* if any registers used */
3418 /* save the registers used */
3419 for (i = 0; i < sym->regsUsed->size; i++)
3421 if (bitVectBitValue (sym->regsUsed, i))
3428 /* this function has a function call. We cannot
3429 determine register usage so we will have to push the
3431 saveRBank (0, ic, FALSE);
3432 if (options.parms_in_bank1) {
3433 for (i=0; i < 8 ; i++ ) {
3434 emitcode ("push","%s",rb1regs[i]);
3441 /* This ISR uses a non-zero bank.
3443 * We assume that the bank is available for our
3446 * However, if this ISR calls a function which uses some
3447 * other bank, we must save that bank entirely.
3449 unsigned long banksToSave = 0;
3451 if (IFFUNC_HASFCALL(sym->type))
3454 #define MAX_REGISTER_BANKS 4
3459 for (i = ic; i; i = i->next)
3461 if (i->op == ENDFUNCTION)
3463 /* we got to the end OK. */
3471 dtype = operandType (IC_LEFT(i));
3473 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3475 /* Mark this bank for saving. */
3476 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3478 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3482 banksToSave |= (1 << FUNC_REGBANK(dtype));
3485 /* And note that we don't need to do it in
3493 /* This is a mess; we have no idea what
3494 * register bank the called function might
3497 * The only thing I can think of to do is
3498 * throw a warning and hope.
3500 werror(W_FUNCPTR_IN_USING_ISR);
3504 if (banksToSave && options.useXstack)
3506 /* Since we aren't passing it an ic,
3507 * saveRBank will assume r0 is available to abuse.
3509 * So switch to our (trashable) bank now, so
3510 * the caller's R0 isn't trashed.
3512 emitcode ("push", "psw");
3513 emitcode ("mov", "psw,#0x%02x",
3514 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3518 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3520 if (banksToSave & (1 << ix))
3522 saveRBank(ix, NULL, FALSE);
3526 // TODO: this needs a closer look
3527 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3530 /* Set the register bank to the desired value if nothing else */
3531 /* has done so yet. */
3534 emitcode ("push", "psw");
3535 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3540 /* This is a non-ISR function. The caller has already switched register */
3541 /* banks, if necessary, so just handle the callee-saves option. */
3543 /* if callee-save to be used for this function
3544 then save the registers being used in this function */
3545 if (IFFUNC_CALLEESAVES(sym->type))
3549 /* if any registers used */
3552 bool bits_pushed = FALSE;
3553 /* save the registers used */
3554 for (i = 0; i < sym->regsUsed->size; i++)
3556 if (bitVectBitValue (sym->regsUsed, i))
3558 /* remember one saved register for later usage */
3559 if (calleesaves_saved_register < 0)
3560 calleesaves_saved_register = i;
3561 bits_pushed = pushReg (i, bits_pushed);
3571 if (options.useXstack)
3573 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3575 emitcode ("mov", "r0,%s", spname);
3576 emitcode ("inc", "%s", spname);
3577 emitcode ("xch", "a,_bpx");
3578 emitcode ("movx", "@r0,a");
3579 emitcode ("inc", "r0");
3580 emitcode ("mov", "a,r0");
3581 emitcode ("xch", "a,_bpx");
3585 emitcode ("push", "_bp"); /* save the callers stack */
3586 emitcode ("mov", "_bp,sp");
3591 if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3593 /* set up the stack */
3594 emitcode ("push", "_bp"); /* save the callers stack */
3595 emitcode ("mov", "_bp,sp");
3600 /* For some cases it is worthwhile to perform a RECEIVE iCode */
3601 /* before setting up the stack frame completely. */
3602 if (ric && ric->argreg == 1 && IC_RESULT (ric))
3604 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3608 if (rsym && rsym->regType == REG_CND)
3610 if (rsym && (rsym->accuse || rsym->ruonly))
3612 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3613 rsym = rsym->usl.spillLoc;
3616 /* If the RECEIVE operand immediately spills to the first entry on the */
3617 /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3618 /* rather than the usual @r0/r1 machinations. */
3619 if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3623 _G.current_iCode = ric;
3624 D(emitcode (";", "genReceive"));
3625 for (ofs=0; ofs < sym->recvSize; ofs++)
3627 if (!strcmp (fReturn[ofs], "a"))
3628 emitcode ("push", "acc");
3630 emitcode ("push", fReturn[ofs]);
3632 stackAdjust -= sym->recvSize;
3635 assert (stackAdjust>=0);
3638 _G.current_iCode = ic;
3642 /* If the RECEIVE operand is 4 registers, we can do the moves now */
3643 /* to free up the accumulator. */
3644 else if (rsym && rsym->nRegs && sym->recvSize == 4)
3648 _G.current_iCode = ric;
3649 D(emitcode (";", "genReceive"));
3650 for (ofs=0; ofs < sym->recvSize; ofs++)
3652 emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3654 _G.current_iCode = ic;
3660 /* adjust the stack for the function */
3663 int i = stackAdjust;
3665 werror (W_STACK_OVERFLOW, sym->name);
3667 if (i > 3 && accIsFree)
3669 emitcode ("mov", "a,sp");
3670 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3671 emitcode ("mov", "sp,a");
3675 /* The accumulator is not free, so we will need another register */
3676 /* to clobber. No need to worry about a possible conflict with */
3677 /* the above early RECEIVE optimizations since they would have */
3678 /* freed the accumulator if they were generated. */
3680 if (IFFUNC_CALLEESAVES(sym->type))
3682 /* if it's a callee-saves function we need a saved register */
3683 if (calleesaves_saved_register >= 0)
3685 emitcode ("mov", "%s,a", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3686 emitcode ("mov", "a,sp");
3687 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3688 emitcode ("mov", "sp,a");
3689 emitcode ("mov", "a,%s", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3692 /* do it the hard way */
3694 emitcode ("inc", "sp");
3698 /* not callee-saves, we can clobber r0 */
3699 emitcode ("mov", "r0,a");
3700 emitcode ("mov", "a,sp");
3701 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3702 emitcode ("mov", "sp,a");
3703 emitcode ("mov", "a,r0");
3708 emitcode ("inc", "sp");
3713 char i = ((char) sym->xstack & 0xff);
3715 if (i > 3 && accIsFree)
3717 emitcode ("mov", "a,_spx");
3718 emitcode ("add", "a,#0x%02x", i & 0xff);
3719 emitcode ("mov", "_spx,a");
3723 emitcode ("push", "acc");
3724 emitcode ("mov", "a,_spx");
3725 emitcode ("add", "a,#0x%02x", i & 0xff);
3726 emitcode ("mov", "_spx,a");
3727 emitcode ("pop", "acc");
3732 emitcode ("inc", "_spx");
3736 /* if critical function then turn interrupts off */
3737 if (IFFUNC_ISCRITICAL (ftype))
3739 symbol *tlbl = newiTempLabel (NULL);
3740 emitcode ("setb", "c");
3741 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3742 emitcode ("clr", "c");
3744 emitcode ("push", "psw"); /* save old ea via c in psw */
3748 /*-----------------------------------------------------------------*/
3749 /* genEndFunction - generates epilogue for functions */
3750 /*-----------------------------------------------------------------*/
3752 genEndFunction (iCode * ic)
3754 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3755 lineNode *lnp = lineCurr;
3757 bitVect *regsUsedPrologue;
3758 bitVect *regsUnneeded;
3761 _G.currentFunc = NULL;
3762 if (IFFUNC_ISNAKED(sym->type))
3764 emitcode(";", "naked function: no epilogue.");
3765 if (options.debug && currFunc)
3766 debugFile->writeEndFunction (currFunc, ic, 0);
3770 if (IFFUNC_ISCRITICAL (sym->type))
3772 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3774 emitcode ("rlc", "a"); /* save c in a */
3775 emitcode ("pop", "psw"); /* restore ea via c in psw */
3776 emitcode ("mov", "ea,c");
3777 emitcode ("rrc", "a"); /* restore c from a */
3781 emitcode ("pop", "psw"); /* restore ea via c in psw */
3782 emitcode ("mov", "ea,c");
3786 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3788 if (options.useXstack)
3792 emitcode ("mov", "sp,_bp");
3793 emitcode ("pop", "_bp");
3795 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3797 emitcode ("xch", "a,_bpx");
3798 emitcode ("mov", "r0,a");
3799 emitcode ("dec", "r0");
3800 emitcode ("movx", "a,@r0");
3801 emitcode ("xch", "a,_bpx");
3802 emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3805 else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3808 emitcode ("mov", "sp,_bp");
3809 emitcode ("pop", "_bp");
3813 /* restore the register bank */
3814 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3816 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3817 || !options.useXstack)
3819 /* Special case of ISR using non-zero bank with useXstack
3822 emitcode ("pop", "psw");
3826 if (IFFUNC_ISISR (sym->type))
3830 /* now we need to restore the registers */
3831 /* if this isr has no bank i.e. is going to
3832 run with bank 0 , then we need to save more
3834 if (!FUNC_REGBANK (sym->type))
3837 /* if this function does not call any other
3838 function then we can be economical and
3839 save only those registers that are used */
3840 if (!IFFUNC_HASFCALL(sym->type))
3842 /* if any registers used */
3845 /* save the registers used */
3846 for (i = sym->regsUsed->size; i >= 0; i--)
3848 if (bitVectBitValue (sym->regsUsed, i))
3855 if (options.parms_in_bank1) {
3856 for (i = 7 ; i >= 0 ; i-- ) {
3857 emitcode ("pop","%s",rb1regs[i]);
3860 /* this function has a function call. We cannot
3861 determine register usage so we will have to pop the
3863 unsaveRBank (0, ic, FALSE);
3868 /* This ISR uses a non-zero bank.
3870 * Restore any register banks saved by genFunction
3873 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3876 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3878 if (savedBanks & (1 << ix))
3880 unsaveRBank(ix, NULL, FALSE);
3884 if (options.useXstack)
3886 /* Restore bank AFTER calling unsaveRBank,
3887 * since it can trash r0.
3889 emitcode ("pop", "psw");
3893 if (!inExcludeList ("dph"))
3894 emitcode ("pop", "dph");
3895 if (!inExcludeList ("dpl"))
3896 emitcode ("pop", "dpl");
3897 if (!inExcludeList ("b"))
3898 emitcode ("pop", "b");
3899 if (!inExcludeList ("acc"))
3900 emitcode ("pop", "acc");
3902 rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), sym->regsUsed);
3903 if (IFFUNC_HASFCALL(sym->type) || !bitVectIsZero (rsavebits))
3904 emitcode ("pop", "bits");
3905 freeBitVect (rsavebits);
3907 /* if debug then send end of function */
3908 if (options.debug && currFunc)
3910 debugFile->writeEndFunction (currFunc, ic, 1);
3913 emitcode ("reti", "");
3917 if (IFFUNC_CALLEESAVES(sym->type))
3921 /* if any registers used */
3924 /* save the registers used */
3925 for (i = sym->regsUsed->size; i >= 0; i--)
3927 if (bitVectBitValue (sym->regsUsed, i) ||
3928 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3929 emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
3932 else if (mcs51_ptrRegReq)
3934 emitcode ("pop", "%s", REG_WITH_INDEX (R1_IDX)->dname);
3935 emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
3940 /* if debug then send end of function */
3941 if (options.debug && currFunc)
3943 debugFile->writeEndFunction (currFunc, ic, 1);
3946 if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3948 emitcode ("ljmp", "__sdcc_banked_ret");
3952 emitcode ("ret", "");
3956 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3959 /* If this was an interrupt handler using bank 0 that called another */
3960 /* function, then all registers must be saved; nothing to optimized. */
3961 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3962 && !FUNC_REGBANK(sym->type))
3965 /* There are no push/pops to optimize if not callee-saves or ISR */
3966 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3969 /* If there were stack parameters, we cannot optimize without also */
3970 /* fixing all of the stack offsets; this is too dificult to consider. */
3971 if (FUNC_HASSTACKPARM(sym->type))
3974 /* Compute the registers actually used */
3975 regsUsed = newBitVect (mcs51_nRegs);
3976 regsUsedPrologue = newBitVect (mcs51_nRegs);
3979 if (lnp->ic && lnp->ic->op == FUNCTION)
3980 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3982 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3984 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3985 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3992 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3993 && !bitVectBitValue (regsUsed, CND_IDX))
3995 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3996 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3997 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3998 bitVectUnSetBit (regsUsed, CND_IDX);
4001 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
4003 /* If this was an interrupt handler that called another function */
4004 /* function, then assume A, B, DPH, & DPL may be modified by it. */
4005 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
4007 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
4008 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
4009 regsUsed = bitVectSetBit (regsUsed, B_IDX);
4010 regsUsed = bitVectSetBit (regsUsed, A_IDX);
4011 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
4014 /* Remove the unneeded push/pops */
4015 regsUnneeded = newBitVect (mcs51_nRegs);
4018 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
4020 if (!strncmp(lnp->line, "push", 4))
4022 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
4023 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4025 connectLine (lnp->prev, lnp->next);
4026 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4029 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
4031 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
4032 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4034 connectLine (lnp->prev, lnp->next);
4035 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4042 for (idx = 0; idx < regsUnneeded->size; idx++)
4043 if (bitVectBitValue (regsUnneeded, idx))
4044 emitcode (";", "eliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
4046 freeBitVect (regsUnneeded);
4047 freeBitVect (regsUsed);
4048 freeBitVect (regsUsedPrologue);
4051 /*-----------------------------------------------------------------*/
4052 /* genRet - generate code for return statement */
4053 /*-----------------------------------------------------------------*/
4057 int size, offset = 0, pushed = 0;
4059 D (emitcode (";", "genRet"));
4061 /* if we have no return value then
4062 just generate the "ret" */
4066 /* we have something to return then
4067 move the return value into place */
4068 aopOp (IC_LEFT (ic), ic, FALSE);
4069 size = AOP_SIZE (IC_LEFT (ic));
4071 if (IS_BIT(_G.currentFunc->etype))
4073 if (!IS_OP_RUONLY (IC_LEFT (ic)))
4074 toCarry (IC_LEFT (ic));
4081 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
4084 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
4085 emitcode ("push", "%s", l);
4090 l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
4091 if (strcmp (fReturn[offset], l))
4092 emitcode ("mov", "%s,%s", fReturn[offset++], l);
4099 if (strcmp (fReturn[pushed], "a"))
4100 emitcode ("pop", fReturn[pushed]);
4102 emitcode ("pop", "acc");
4105 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
4108 /* generate a jump to the return label
4109 if the next is not the return statement */
4110 if (!(ic->next && ic->next->op == LABEL &&
4111 IC_LABEL (ic->next) == returnLabel))
4113 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
4117 /*-----------------------------------------------------------------*/
4118 /* genLabel - generates a label */
4119 /*-----------------------------------------------------------------*/
4121 genLabel (iCode * ic)
4123 /* special case never generate */
4124 if (IC_LABEL (ic) == entryLabel)
4127 emitLabel (IC_LABEL (ic));
4130 /*-----------------------------------------------------------------*/
4131 /* genGoto - generates a ljmp */
4132 /*-----------------------------------------------------------------*/
4134 genGoto (iCode * ic)
4136 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
4139 /*-----------------------------------------------------------------*/
4140 /* findLabelBackwards: walks back through the iCode chain looking */
4141 /* for the given label. Returns number of iCode instructions */
4142 /* between that label and given ic. */
4143 /* Returns zero if label not found. */
4144 /*-----------------------------------------------------------------*/
4146 findLabelBackwards (iCode * ic, int key)
4155 /* If we have any pushes or pops, we cannot predict the distance.
4156 I don't like this at all, this should be dealt with in the
4158 if (ic->op == IPUSH || ic->op == IPOP) {
4162 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4171 /*-----------------------------------------------------------------*/
4172 /* genPlusIncr :- does addition with increment if possible */
4173 /*-----------------------------------------------------------------*/
4175 genPlusIncr (iCode * ic)
4177 unsigned int icount;
4178 unsigned int size = getDataSize (IC_RESULT (ic));
4180 /* will try to generate an increment */
4181 /* if the right side is not a literal
4183 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4186 icount = (unsigned int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4188 D(emitcode (";","genPlusIncr"));
4190 /* if increment >=16 bits in register or direct space */
4191 if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG ||
4192 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4193 (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4194 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4195 !isOperandVolatile (IC_RESULT (ic), FALSE) &&
4203 /* If the next instruction is a goto and the goto target
4204 * is < 10 instructions previous to this, we can generate
4205 * jumps straight to that target.
4207 if (ic->next && ic->next->op == GOTO
4208 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4209 && labelRange <= 10)
4211 D (emitcode (";", "tail increment optimized (range %d)", labelRange));
4212 tlbl = IC_LABEL (ic->next);
4217 tlbl = newiTempLabel (NULL);
4220 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4221 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4222 IS_AOP_PREG (IC_RESULT (ic)))
4223 emitcode ("cjne", "%s,#0x00,%05d$",
4224 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4228 emitcode ("clr", "a");
4229 emitcode ("cjne", "a,%s,%05d$",
4230 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4234 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4237 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4238 IS_AOP_PREG (IC_RESULT (ic)))
4239 emitcode ("cjne", "%s,#0x00,%05d$",
4240 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4243 emitcode ("cjne", "a,%s,%05d$",
4244 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4247 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4251 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4252 IS_AOP_PREG (IC_RESULT (ic)))
4253 emitcode ("cjne", "%s,#0x00,%05d$",
4254 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4258 emitcode ("cjne", "a,%s,%05d$",
4259 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4262 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4272 /* if result is dptr */
4273 if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
4274 (AOP_SIZE (IC_RESULT (ic)) == 2) &&
4275 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
4276 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
4278 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4284 if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
4287 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0);
4288 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1);
4290 emitcode ("inc", "dptr");
4295 /* if the literal value of the right hand side
4296 is greater than 4 then it is not worth it */
4300 /* if the sizes are greater than 1 then we cannot */
4301 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4302 AOP_SIZE (IC_LEFT (ic)) > 1)
4305 /* we can if the aops of the left & result match or
4306 if they are in registers and the registers are the
4308 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4312 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4313 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4314 aopPut (IC_RESULT (ic), "a", 0);
4320 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4329 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4330 emitcode ("inc", "a");
4331 aopPut (IC_RESULT (ic), "a", 0);
4338 /*-----------------------------------------------------------------*/
4339 /* outBitAcc - output a bit in acc */
4340 /*-----------------------------------------------------------------*/
4342 outBitAcc (operand * result)
4344 symbol *tlbl = newiTempLabel (NULL);
4345 /* if the result is a bit */
4346 if (AOP_TYPE (result) == AOP_CRY)
4348 aopPut (result, "a", 0);
4352 emitcode ("jz", "%05d$", tlbl->key + 100);
4353 emitcode ("mov", "a,%s", one);
4359 /*-----------------------------------------------------------------*/
4360 /* genPlusBits - generates code for addition of two bits */
4361 /*-----------------------------------------------------------------*/
4363 genPlusBits (iCode * ic)
4365 D (emitcode (";", "genPlusBits"));
4367 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4368 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4370 symbol *lbl = newiTempLabel (NULL);
4371 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4372 emitcode ("cpl", "c");
4374 outBitC (IC_RESULT (ic));
4378 emitcode ("clr", "a");
4379 emitcode ("rlc", "a");
4380 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4381 emitcode ("addc", "a,%s", zero);
4382 outAcc (IC_RESULT (ic));
4387 /* This is the original version of this code.
4389 * This is being kept around for reference,
4390 * because I am not entirely sure I got it right...
4393 adjustArithmeticResult (iCode * ic)
4395 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4396 AOP_SIZE (IC_LEFT (ic)) == 3 &&
4397 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4398 aopPut (IC_RESULT (ic),
4399 aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4402 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4403 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4404 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4405 aopPut (IC_RESULT (ic),
4406 aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4409 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4410 AOP_SIZE (IC_LEFT (ic)) < 3 &&
4411 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4412 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4413 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4416 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4417 aopPut (IC_RESULT (ic), buffer, 2);
4421 /* This is the pure and virtuous version of this code.
4422 * I'm pretty certain it's right, but not enough to toss the old
4426 adjustArithmeticResult (iCode * ic)
4428 if (opIsGptr (IC_RESULT (ic)))
4432 if (opIsGptr (IC_LEFT (ic)))
4434 if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4436 aopPut (IC_RESULT (ic),
4437 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4443 if (opIsGptr (IC_RIGHT (ic)))
4445 if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4447 aopPut (IC_RESULT (ic),
4448 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4454 if (IC_LEFT (ic) && AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4455 IC_RIGHT (ic) && AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4456 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4457 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4459 SNPRINTF (buffer, sizeof(buffer),
4460 "#0x%02x", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4461 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4464 if (IC_LEFT (ic) && AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4465 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4467 SNPRINTF (buffer, sizeof(buffer),
4468 "#0x%02x", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4469 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4472 if (IC_RIGHT (ic) && AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4473 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4475 SNPRINTF (buffer, sizeof(buffer),
4476 "#0x%02x", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_RIGHT (ic)))), NULL, NULL));
4477 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4484 /*-----------------------------------------------------------------*/
4485 /* genPlus - generates code for addition */
4486 /*-----------------------------------------------------------------*/
4488 genPlus (iCode * ic)
4490 int size, offset = 0;
4493 bool swappedLR = FALSE;
4494 operand *leftOp, *rightOp;
4497 D (emitcode (";", "genPlus"));
4499 /* special cases :- */
4501 aopOp (IC_LEFT (ic), ic, FALSE);
4502 aopOp (IC_RIGHT (ic), ic, FALSE);
4503 aopOp (IC_RESULT (ic), ic, TRUE);
4505 /* if literal, literal on the right or
4506 if left requires ACC or right is already
4508 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4509 (AOP_NEEDSACC (IC_LEFT (ic))) ||
4510 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4512 operand *t = IC_RIGHT (ic);
4513 IC_RIGHT (ic) = IC_LEFT (ic);
4518 /* if both left & right are in bit
4520 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4521 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4527 /* if left in bit space & right literal */
4528 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4529 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4531 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4532 /* if result in bit space */
4533 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4535 if (ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4536 emitcode ("cpl", "c");
4537 outBitC (IC_RESULT (ic));
4541 size = getDataSize (IC_RESULT (ic));
4544 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4545 emitcode ("addc", "a,%s", zero);
4546 aopPut (IC_RESULT (ic), "a", offset++);
4552 /* if I can do an increment instead
4553 of add then GOOD for ME */
4554 if (genPlusIncr (ic) == TRUE)
4557 size = getDataSize (IC_RESULT (ic));
4558 leftOp = IC_LEFT(ic);
4559 rightOp = IC_RIGHT(ic);
4562 /* if this is an add for an array access
4563 at a 256 byte boundary */
4565 && AOP_TYPE (op) == AOP_IMMD
4567 && IS_SPEC (OP_SYM_ETYPE (op))
4568 && SPEC_ABSA (OP_SYM_ETYPE (op))
4569 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4572 D(emitcode (";", "genPlus aligned array"));
4573 aopPut (IC_RESULT (ic),
4574 aopGet (rightOp, 0, FALSE, FALSE),
4577 if( 1 == getDataSize (IC_RIGHT (ic)) )
4579 aopPut (IC_RESULT (ic),
4580 aopGet (leftOp, 1, FALSE, FALSE),
4585 MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4586 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4587 aopPut (IC_RESULT (ic), "a", 1);
4592 /* if the lower bytes of a literal are zero skip the addition */
4593 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4595 while ((0 == ((unsigned int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4596 (skip_bytes+1 < size))
4601 D(emitcode (";", "genPlus shortcut"));
4606 if( offset >= skip_bytes )
4608 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4611 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4613 emitcode("xch", "a,b");
4614 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4615 emitcode (add, "a,b");
4618 else if (aopGetUsesAcc (leftOp, offset))
4620 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4621 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4625 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4626 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4628 aopPut (IC_RESULT (ic), "a", offset);
4629 add = "addc"; /* further adds must propagate carry */
4633 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4634 isOperandVolatile (IC_RESULT (ic), FALSE))
4637 aopPut (IC_RESULT (ic),
4638 aopGet (leftOp, offset, FALSE, FALSE),
4645 adjustArithmeticResult (ic);
4648 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4651 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4652 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4656 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4657 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4661 /*-----------------------------------------------------------------*/
4662 /* genMinusDec :- does subtraction with decrement if possible */
4663 /*-----------------------------------------------------------------*/
4665 genMinusDec (iCode * ic)
4667 unsigned int icount;
4668 unsigned int size = getDataSize (IC_RESULT (ic));
4670 /* will try to generate an increment */
4671 /* if the right side is not a literal
4673 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4676 /* if the literal value of the right hand side
4677 is greater than 4 then it is not worth it */
4678 if ((icount = (unsigned int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4681 D (emitcode (";", "genMinusDec"));
4683 /* if decrement >=16 bits in register or direct space */
4684 if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG ||
4685 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4686 (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4687 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4695 /* If the next instruction is a goto and the goto target
4696 * is <= 10 instructions previous to this, we can generate
4697 * jumps straight to that target.
4699 if (ic->next && ic->next->op == GOTO
4700 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4701 && labelRange <= 10)
4703 D (emitcode (";", "tail decrement optimized (range %d)", labelRange));
4704 tlbl = IC_LABEL (ic->next);
4709 tlbl = newiTempLabel (NULL);
4713 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4714 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4715 IS_AOP_PREG (IC_RESULT (ic)))
4716 emitcode ("cjne", "%s,#0xff,%05d$"
4717 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4721 emitcode ("mov", "a,#0xff");
4722 emitcode ("cjne", "a,%s,%05d$"
4723 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4726 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4729 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4730 IS_AOP_PREG (IC_RESULT (ic)))
4731 emitcode ("cjne", "%s,#0xff,%05d$"
4732 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4736 emitcode ("cjne", "a,%s,%05d$"
4737 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4740 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4744 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4745 IS_AOP_PREG (IC_RESULT (ic)))
4746 emitcode ("cjne", "%s,#0xff,%05d$"
4747 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4751 emitcode ("cjne", "a,%s,%05d$"
4752 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4755 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4764 /* if the sizes are greater than 1 then we cannot */
4765 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4766 AOP_SIZE (IC_LEFT (ic)) > 1)
4769 /* we can if the aops of the left & result match or
4770 if they are in registers and the registers are the
4772 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4776 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4778 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4783 l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
4788 emitcode ("dec", "%s", l);
4791 if (AOP_NEEDSACC (IC_RESULT (ic)))
4792 aopPut (IC_RESULT (ic), "a", 0);
4799 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4800 emitcode ("dec", "a");
4801 aopPut (IC_RESULT (ic), "a", 0);
4808 /*-----------------------------------------------------------------*/
4809 /* addSign - complete with sign */
4810 /*-----------------------------------------------------------------*/
4812 addSign (operand * result, int offset, int sign)
4814 int size = (getDataSize (result) - offset);
4819 emitcode ("rlc", "a");
4820 emitcode ("subb", "a,acc");
4823 aopPut (result, "a", offset++);
4830 aopPut (result, zero, offset++);
4836 /*-----------------------------------------------------------------*/
4837 /* genMinusBits - generates code for subtraction of two bits */
4838 /*-----------------------------------------------------------------*/
4840 genMinusBits (iCode * ic)
4842 symbol *lbl = newiTempLabel (NULL);
4844 D (emitcode (";", "genMinusBits"));
4846 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4848 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4849 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4850 emitcode ("cpl", "c");
4852 outBitC (IC_RESULT (ic));
4856 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4857 emitcode ("subb", "a,acc");
4858 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4859 emitcode ("inc", "a");
4861 aopPut (IC_RESULT (ic), "a", 0);
4862 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4866 /*-----------------------------------------------------------------*/
4867 /* genMinus - generates code for subtraction */
4868 /*-----------------------------------------------------------------*/
4870 genMinus (iCode * ic)
4872 int size, offset = 0;
4874 D (emitcode (";", "genMinus"));
4876 aopOp (IC_LEFT (ic), ic, FALSE);
4877 aopOp (IC_RIGHT (ic), ic, FALSE);
4878 aopOp (IC_RESULT (ic), ic, TRUE);
4880 /* special cases :- */
4881 /* if both left & right are in bit space */
4882 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4883 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4889 /* if I can do an decrement instead
4890 of subtract then GOOD for ME */
4891 if (genMinusDec (ic) == TRUE)
4894 size = getDataSize (IC_RESULT (ic));
4896 /* if literal, add a,#-lit, else normal subb */
4897 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4899 unsigned long lit = 0L;
4900 bool useCarry = FALSE;
4902 lit = ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4907 if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4909 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4910 if (!offset && !size && lit== (unsigned long) -1)
4912 emitcode ("dec", "a");
4916 /* first add without previous c */
4917 emitcode ("add", "a,#0x%02x",
4918 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4923 emitcode ("addc", "a,#0x%02x",
4924 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4926 aopPut (IC_RESULT (ic), "a", offset++);
4930 /* no need to add zeroes */
4931 if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4933 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4942 operand *leftOp, *rightOp;
4944 leftOp = IC_LEFT(ic);
4945 rightOp = IC_RIGHT(ic);
4949 if (aopGetUsesAcc(rightOp, offset)) {
4950 if (aopGetUsesAcc(leftOp, offset)) {
4953 MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4955 emitcode ("mov", "b,a");
4958 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4959 emitcode ("subb", "a,b");
4962 /* reverse subtraction with 2's complement */
4964 emitcode( "setb", "c");
4966 emitcode( "cpl", "c");
4967 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4968 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4969 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4970 emitcode("cpl", "a");
4971 if (size) /* skip if last byte */
4972 emitcode( "cpl", "c");
4975 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4978 emitcode ("subb", "a,%s",
4979 aopGet(rightOp, offset, FALSE, TRUE));
4982 aopPut (IC_RESULT (ic), "a", offset++);
4986 adjustArithmeticResult (ic);
4989 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4990 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4991 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4995 /*-----------------------------------------------------------------*/
4996 /* genMultbits :- multiplication of bits */
4997 /*-----------------------------------------------------------------*/
4999 genMultbits (operand * left,
5003 D (emitcode (";", "genMultbits"));
5005 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5006 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5010 /*-----------------------------------------------------------------*/
5011 /* genMultOneByte : 8*8=8/16 bit multiplication */
5012 /*-----------------------------------------------------------------*/
5014 genMultOneByte (operand * left,
5019 int size = AOP_SIZE (result);
5020 bool runtimeSign, compiletimeSign;
5021 bool lUnsigned, rUnsigned, pushedB;
5023 D (emitcode (";", "genMultOneByte"));
5025 if (size < 1 || size > 2)
5027 /* this should never happen */
5028 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
5029 AOP_SIZE(result), __FILE__, lineno);
5033 /* (if two literals: the value is computed before) */
5034 /* if one literal, literal on the right */
5035 if (AOP_TYPE (left) == AOP_LIT)
5040 /* emitcode (";", "swapped left and right"); */
5042 /* if no literal, unsigned on the right: shorter code */
5043 if ( AOP_TYPE (right) != AOP_LIT
5044 && SPEC_USIGN (getSpec (operandType (left))))
5051 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5052 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5056 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
5057 no need to take care about the signedness! */
5058 || (lUnsigned && rUnsigned))
5060 /* just an unsigned 8 * 8 = 8 multiply
5062 /* emitcode (";","unsigned"); */
5063 /* TODO: check for accumulator clash between left & right aops? */
5065 if (AOP_TYPE (right) == AOP_LIT)
5067 /* moving to accumulator first helps peepholes */
5068 MOVA (aopGet (left, 0, FALSE, FALSE));
5069 MOVB (aopGet (right, 0, FALSE, FALSE));
5073 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5074 MOVA (aopGet (left, 0, FALSE, FALSE));
5077 emitcode ("mul", "ab");
5078 aopPut (result, "a", 0);
5080 aopPut (result, "b", 1);
5086 /* we have to do a signed multiply */
5087 /* emitcode (";", "signed"); */
5089 /* now sign adjust for both left & right */
5091 /* let's see what's needed: */
5092 /* apply negative sign during runtime */
5093 runtimeSign = FALSE;
5094 /* negative sign from literals */
5095 compiletimeSign = FALSE;
5099 if (AOP_TYPE(left) == AOP_LIT)
5101 /* signed literal */
5102 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5104 compiletimeSign = TRUE;
5107 /* signed but not literal */
5113 if (AOP_TYPE(right) == AOP_LIT)
5115 /* signed literal */
5116 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
5118 compiletimeSign ^= TRUE;
5121 /* signed but not literal */
5125 /* initialize F0, which stores the runtime sign */
5128 if (compiletimeSign)
5129 emitcode ("setb", "F0"); /* set sign flag */
5131 emitcode ("clr", "F0"); /* reset sign flag */
5134 /* save the signs of the operands */
5135 if (AOP_TYPE(right) == AOP_LIT)
5137 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
5139 if (!rUnsigned && val < 0)
5140 emitcode ("mov", "b,#0x%02x", -val);
5142 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5144 else /* ! literal */
5146 if (rUnsigned) /* emitcode (";", "signed"); */
5147 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5150 MOVA (aopGet (right, 0, FALSE, FALSE));
5151 lbl = newiTempLabel (NULL);
5152 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5153 emitcode ("cpl", "F0"); /* complement sign flag */
5154 emitcode ("cpl", "a"); /* 2's complement */
5155 emitcode ("inc", "a");
5157 emitcode ("mov", "b,a");
5161 if (AOP_TYPE(left) == AOP_LIT)
5163 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5165 if (!lUnsigned && val < 0)
5166 emitcode ("mov", "a,#0x%02x", -val);
5168 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5170 else /* ! literal */
5172 MOVA (aopGet (left, 0, FALSE, FALSE));
5176 lbl = newiTempLabel (NULL);
5177 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5178 emitcode ("cpl", "F0"); /* complement sign flag */
5179 emitcode ("cpl", "a"); /* 2's complement */
5180 emitcode ("inc", "a");
5185 /* now the multiplication */
5186 emitcode ("mul", "ab");
5187 if (runtimeSign || compiletimeSign)
5189 lbl = newiTempLabel (NULL);
5191 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5192 emitcode ("cpl", "a"); /* lsb 2's complement */
5194 emitcode ("inc", "a"); /* inc doesn't set carry flag */
5197 emitcode ("add", "a,#0x01"); /* this sets carry flag */
5198 emitcode ("xch", "a,b");
5199 emitcode ("cpl", "a"); /* msb 2's complement */
5200 emitcode ("addc", "a,#0x00");
5201 emitcode ("xch", "a,b");
5205 aopPut (result, "a", 0);
5207 aopPut (result, "b", 1);
5212 /*-----------------------------------------------------------------*/
5213 /* genMult - generates code for multiplication */
5214 /*-----------------------------------------------------------------*/
5216 genMult (iCode * ic)
5218 operand *left = IC_LEFT (ic);
5219 operand *right = IC_RIGHT (ic);
5220 operand *result = IC_RESULT (ic);
5222 D (emitcode (";", "genMult"));
5224 /* assign the asmops */
5225 aopOp (left, ic, FALSE);
5226 aopOp (right, ic, FALSE);
5227 aopOp (result, ic, TRUE);
5229 /* special cases first */
5231 if (AOP_TYPE (left) == AOP_CRY &&
5232 AOP_TYPE (right) == AOP_CRY)
5234 genMultbits (left, right, result);
5238 /* if both are of size == 1 */
5239 #if 0 // one of them can be a sloc shared with the result
5240 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
5242 if (getSize(operandType(left)) == 1 &&
5243 getSize(operandType(right)) == 1)
5246 genMultOneByte (left, right, result);
5250 /* should have been converted to function call */
5251 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
5252 getSize(OP_SYMBOL(right)->type));
5256 freeAsmop (result, NULL, ic, TRUE);
5257 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5258 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5261 /*-----------------------------------------------------------------*/
5262 /* genDivbits :- division of bits */
5263 /*-----------------------------------------------------------------*/
5265 genDivbits (operand * left,
5272 D(emitcode (";", "genDivbits"));
5276 /* the result must be bit */
5277 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5278 l = aopGet (left, 0, FALSE, FALSE);
5282 emitcode ("div", "ab");
5283 emitcode ("rrc", "a");
5287 aopPut (result, "c", 0);
5290 /*-----------------------------------------------------------------*/
5291 /* genDivOneByte : 8 bit division */
5292 /*-----------------------------------------------------------------*/
5294 genDivOneByte (operand * left,
5298 bool lUnsigned, rUnsigned, pushedB;
5299 bool runtimeSign, compiletimeSign;
5300 bool accuse = FALSE;
5301 bool pushedA = FALSE;
5305 D(emitcode (";", "genDivOneByte"));
5307 /* Why is it necessary that genDivOneByte() can return an int result?
5310 volatile unsigned char uc;
5311 volatile signed char sc1, sc2;
5324 In all cases a one byte result would overflow, the following cast to int
5325 would return the wrong result.
5327 Two possible solution:
5328 a) cast operands to int, if ((unsigned) / (signed)) or
5329 ((signed) / (signed))
5330 b) return an 16 bit signed int; this is what we're doing here!
5333 size = AOP_SIZE (result) - 1;
5335 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5336 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5340 /* signed or unsigned */
5341 if (lUnsigned && rUnsigned)
5343 /* unsigned is easy */
5344 MOVB (aopGet (right, 0, FALSE, FALSE));
5345 MOVA (aopGet (left, 0, FALSE, FALSE));
5346 emitcode ("div", "ab");
5347 aopPut (result, "a", 0);
5349 aopPut (result, zero, offset++);
5355 /* signed is a little bit more difficult */
5357 /* now sign adjust for both left & right */
5359 /* let's see what's needed: */
5360 /* apply negative sign during runtime */
5361 runtimeSign = FALSE;
5362 /* negative sign from literals */
5363 compiletimeSign = FALSE;
5367 if (AOP_TYPE(left) == AOP_LIT)
5369 /* signed literal */
5370 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5372 compiletimeSign = TRUE;
5375 /* signed but not literal */
5381 if (AOP_TYPE(right) == AOP_LIT)
5383 /* signed literal */
5384 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
5386 compiletimeSign ^= TRUE;
5389 /* signed but not literal */
5393 /* initialize F0, which stores the runtime sign */
5396 if (compiletimeSign)
5397 emitcode ("setb", "F0"); /* set sign flag */
5399 emitcode ("clr", "F0"); /* reset sign flag */
5402 /* save the signs of the operands */
5403 if (AOP_TYPE(right) == AOP_LIT)
5405 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
5407 if (!rUnsigned && val < 0)
5408 emitcode ("mov", "b,#0x%02x", -val);
5410 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5412 else /* ! literal */
5415 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5418 MOVA (aopGet (right, 0, FALSE, FALSE));
5419 lbl = newiTempLabel (NULL);
5420 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5421 emitcode ("cpl", "F0"); /* complement sign flag */
5422 emitcode ("cpl", "a"); /* 2's complement */
5423 emitcode ("inc", "a");
5425 emitcode ("mov", "b,a");
5429 if (AOP_TYPE(left) == AOP_LIT)
5431 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5433 if (!lUnsigned && val < 0)
5434 emitcode ("mov", "a,#0x%02x", -val);
5436 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5438 else /* ! literal */
5440 MOVA (aopGet (left, 0, FALSE, FALSE));
5444 lbl = newiTempLabel (NULL);
5445 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5446 emitcode ("cpl", "F0"); /* complement sign flag */
5447 emitcode ("cpl", "a"); /* 2's complement */
5448 emitcode ("inc", "a");
5453 /* now the division */
5454 emitcode ("div", "ab");
5456 if (runtimeSign || compiletimeSign)
5458 lbl = newiTempLabel (NULL);
5460 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5461 emitcode ("cpl", "a"); /* lsb 2's complement */
5462 emitcode ("inc", "a");
5465 accuse = aopPut (result, "a", 0);
5468 /* msb is 0x00 or 0xff depending on the sign */
5473 emitcode ("push", "acc");
5476 emitcode ("mov", "c,F0");
5477 emitcode ("subb", "a,acc");
5479 aopPut (result, "a", offset++);
5481 else /* compiletimeSign */
5483 if (aopPutUsesAcc (result, "#0xff", offset))
5485 emitcode ("push", "acc");
5489 aopPut (result, "#0xff", offset++);
5495 aopPut (result, "a", 0);
5497 aopPut (result, zero, offset++);
5501 emitcode ("pop", "acc");
5505 /*-----------------------------------------------------------------*/
5506 /* genDiv - generates code for division */
5507 /*-----------------------------------------------------------------*/
5511 operand *left = IC_LEFT (ic);
5512 operand *right = IC_RIGHT (ic);
5513 operand *result = IC_RESULT (ic);
5515 D (emitcode (";", "genDiv"));
5517 /* assign the asmops */
5518 aopOp (left, ic, FALSE);
5519 aopOp (right, ic, FALSE);
5520 aopOp (result, ic, TRUE);
5522 /* special cases first */
5524 if (AOP_TYPE (left) == AOP_CRY &&
5525 AOP_TYPE (right) == AOP_CRY)
5527 genDivbits (left, right, result);
5531 /* if both are of size == 1 */
5532 if (AOP_SIZE (left) == 1 &&
5533 AOP_SIZE (right) == 1)
5535 genDivOneByte (left, right, result);
5539 /* should have been converted to function call */
5542 freeAsmop (result, NULL, ic, TRUE);
5543 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5544 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5547 /*-----------------------------------------------------------------*/
5548 /* genModbits :- modulus of bits */
5549 /*-----------------------------------------------------------------*/
5551 genModbits (operand * left,
5558 D (emitcode (";", "genModbits"));
5562 /* the result must be bit */
5563 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5564 l = aopGet (left, 0, FALSE, FALSE);
5568 emitcode ("div", "ab");
5569 emitcode ("mov", "a,b");
5570 emitcode ("rrc", "a");
5574 aopPut (result, "c", 0);
5577 /*-----------------------------------------------------------------*/
5578 /* genModOneByte : 8 bit modulus */
5579 /*-----------------------------------------------------------------*/
5581 genModOneByte (operand * left,
5585 bool lUnsigned, rUnsigned, pushedB;
5586 bool runtimeSign, compiletimeSign;
5590 D (emitcode (";", "genModOneByte"));
5592 size = AOP_SIZE (result) - 1;
5594 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5595 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5597 /* if right is a literal, check it for 2^n */
5598 if (AOP_TYPE(right) == AOP_LIT)
5600 unsigned char val = abs((int) operandLitValue(right));
5601 symbol *lbl2 = NULL;
5605 case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5614 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5615 "modulus of unsigned char by 2^n literal shouldn't be processed here");
5616 /* because iCode should have been changed to genAnd */
5617 /* see file "SDCCopt.c", function "convertToFcall()" */
5619 MOVA (aopGet (left, 0, FALSE, FALSE));
5620 emitcode ("mov", "c,acc.7");
5621 emitcode ("anl", "a,#0x%02x", val - 1);
5622 lbl = newiTempLabel (NULL);
5623 emitcode ("jz", "%05d$", (lbl->key + 100));
5624 emitcode ("jnc", "%05d$", (lbl->key + 100));
5625 emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5631 aopPut (result, "a", 0);
5633 aopPut (result, "#0xff", offs2++);
5634 lbl2 = newiTempLabel (NULL);
5635 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5638 aopPut (result, "a", 0);
5640 aopPut (result, zero, offset++);
5654 /* signed or unsigned */
5655 if (lUnsigned && rUnsigned)
5657 /* unsigned is easy */
5658 MOVB (aopGet (right, 0, FALSE, FALSE));
5659 MOVA (aopGet (left, 0, FALSE, FALSE));
5660 emitcode ("div", "ab");
5661 aopPut (result, "b", 0);
5663 aopPut (result, zero, offset++);
5669 /* signed is a little bit more difficult */
5671 /* now sign adjust for both left & right */
5673 /* modulus: sign of the right operand has no influence on the result! */
5674 if (AOP_TYPE(right) == AOP_LIT)
5676 signed char val = (char) operandLitValue(right);
5678 if (!rUnsigned && val < 0)
5679 emitcode ("mov", "b,#0x%02x", -val);
5681 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5683 else /* not literal */
5686 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5689 MOVA (aopGet (right, 0, FALSE, FALSE));
5690 lbl = newiTempLabel (NULL);
5691 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5692 emitcode ("cpl", "a"); /* 2's complement */
5693 emitcode ("inc", "a");
5695 emitcode ("mov", "b,a");
5699 /* let's see what's needed: */
5700 /* apply negative sign during runtime */
5701 runtimeSign = FALSE;
5702 /* negative sign from literals */
5703 compiletimeSign = FALSE;
5705 /* sign adjust left side */
5706 if (AOP_TYPE(left) == AOP_LIT)
5708 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5710 if (!lUnsigned && val < 0)
5712 compiletimeSign = TRUE; /* set sign flag */
5713 emitcode ("mov", "a,#0x%02x", -val);
5716 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5718 else /* ! literal */
5720 MOVA (aopGet (left, 0, FALSE, FALSE));
5725 emitcode ("clr", "F0"); /* clear sign flag */
5727 lbl = newiTempLabel (NULL);
5728 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5729 emitcode ("setb", "F0"); /* set sign flag */
5730 emitcode ("cpl", "a"); /* 2's complement */
5731 emitcode ("inc", "a");
5736 /* now the modulus */
5737 emitcode ("div", "ab");
5739 if (runtimeSign || compiletimeSign)
5741 emitcode ("mov", "a,b");
5742 lbl = newiTempLabel (NULL);
5744 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5745 emitcode ("cpl", "a"); /* 2's complement */
5746 emitcode ("inc", "a");
5749 aopPut (result, "a", 0);
5752 /* msb is 0x00 or 0xff depending on the sign */
5755 emitcode ("mov", "c,F0");
5756 emitcode ("subb", "a,acc");
5758 aopPut (result, "a", offset++);
5760 else /* compiletimeSign */
5762 aopPut (result, "#0xff", offset++);
5767 aopPut (result, "b", 0);
5769 aopPut (result, zero, offset++);
5775 /*-----------------------------------------------------------------*/
5776 /* genMod - generates code for division */
5777 /*-----------------------------------------------------------------*/
5781 operand *left = IC_LEFT (ic);
5782 operand *right = IC_RIGHT (ic);
5783 operand *result = IC_RESULT (ic);
5785 D (emitcode (";", "genMod"));
5787 /* assign the asmops */
5788 aopOp (left, ic, FALSE);
5789 aopOp (right, ic, FALSE);
5790 aopOp (result, ic, TRUE);
5792 /* special cases first */
5794 if (AOP_TYPE (left) == AOP_CRY &&
5795 AOP_TYPE (right) == AOP_CRY)
5797 genModbits (left, right, result);
5801 /* if both are of size == 1 */
5802 if (AOP_SIZE (left) == 1 &&
5803 AOP_SIZE (right) == 1)
5805 genModOneByte (left, right, result);
5809 /* should have been converted to function call */
5813 freeAsmop (result, NULL, ic, TRUE);
5814 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5815 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5818 /*-----------------------------------------------------------------*/
5819 /* genIfxJump :- will create a jump depending on the ifx */
5820 /*-----------------------------------------------------------------*/
5822 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5825 symbol *tlbl = newiTempLabel (NULL);
5828 D (emitcode (";", "genIfxJump"));
5830 /* if true label then we jump if condition
5834 jlbl = IC_TRUE (ic);
5835 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5836 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5840 /* false label is present */
5841 jlbl = IC_FALSE (ic);
5842 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5843 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5845 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5846 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5848 emitcode (inst, "%05d$", tlbl->key + 100);
5849 freeForBranchAsmop (result);
5850 freeForBranchAsmop (right);
5851 freeForBranchAsmop (left);
5852 emitcode ("ljmp", "%05d$", jlbl->key + 100);
5855 /* mark the icode as generated */
5859 /*-----------------------------------------------------------------*/
5860 /* genCmp :- greater or less than comparison */
5861 /*-----------------------------------------------------------------*/
5863 genCmp (operand * left, operand * right,
5864 operand * result, iCode * ifx, int sign, iCode *ic)
5866 int size, offset = 0;
5867 unsigned long lit = 0L;
5870 D (emitcode (";", "genCmp"));
5872 /* if left & right are bit variables */
5873 if (AOP_TYPE (left) == AOP_CRY &&
5874 AOP_TYPE (right) == AOP_CRY)
5876 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5877 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5881 /* subtract right from left if at the
5882 end the carry flag is set then we know that
5883 left is greater than right */
5884 size = max (AOP_SIZE (left), AOP_SIZE (right));
5886 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5887 if ((size == 1) && !sign &&
5888 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5890 symbol *lbl = newiTempLabel (NULL);
5891 emitcode ("cjne", "%s,%s,%05d$",
5892 aopGet (left, offset, FALSE, FALSE),
5893 aopGet (right, offset, FALSE, FALSE),
5899 if (AOP_TYPE (right) == AOP_LIT)
5901 lit = ulFromVal (AOP (right)->aopu.aop_lit);
5902 /* optimize if(x < 0) or if(x >= 0) */
5911 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5912 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5914 genIfxJump (ifx, "acc.7", left, right, result);
5915 freeAsmop (right, NULL, ic, TRUE);
5916 freeAsmop (left, NULL, ic, TRUE);
5922 emitcode ("rlc", "a");
5929 int bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5930 while (size && (bytelit == 0))
5933 bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5939 MOVA (aopGet (left, offset, FALSE, FALSE));
5940 if (sign && size == 0)
5942 emitcode ("xrl", "a,#0x80");
5943 emitcode ("subb", "a,#0x%02x",
5944 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5948 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5958 bool pushedB = FALSE;
5959 rightInB = aopGetUsesAcc(right, offset);
5963 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5965 MOVA (aopGet (left, offset, FALSE, FALSE));
5966 if (sign && size == 0)
5968 emitcode ("xrl", "a,#0x80");
5973 MOVB (aopGet (right, offset, FALSE, FALSE));
5975 emitcode ("xrl", "b,#0x80");
5976 emitcode ("subb", "a,b");
5981 emitcode ("subb", "a,b");
5983 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5993 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5994 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5995 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6001 /* if the result is used in the next
6002 ifx conditional branch then generate
6003 code a little differently */
6006 genIfxJump (ifx, "c", NULL, NULL, result);
6012 /* leave the result in acc */
6016 /*-----------------------------------------------------------------*/
6017 /* genCmpGt :- greater than comparison */
6018 /*-----------------------------------------------------------------*/
6020 genCmpGt (iCode * ic, iCode * ifx)
6022 operand *left, *right, *result;
6023 sym_link *letype, *retype;
6026 D (emitcode (";", "genCmpGt"));
6028 left = IC_LEFT (ic);
6029 right = IC_RIGHT (ic);
6030 result = IC_RESULT (ic);
6032 letype = getSpec (operandType (left));
6033 retype = getSpec (operandType (right));
6034 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
6035 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
6036 /* assign the asmops */
6037 aopOp (result, ic, TRUE);
6038 aopOp (left, ic, FALSE);
6039 aopOp (right, ic, FALSE);
6041 genCmp (right, left, result, ifx, sign, ic);
6043 freeAsmop (result, NULL, ic, TRUE);
6046 /*-----------------------------------------------------------------*/
6047 /* genCmpLt - less than comparisons */
6048 /*-----------------------------------------------------------------*/
6050 genCmpLt (iCode * ic, iCode * ifx)
6052 operand *left, *right, *result;
6053 sym_link *letype, *retype;
6056 D (emitcode (";", "genCmpLt"));
6058 left = IC_LEFT (ic);
6059 right = IC_RIGHT (ic);
6060 result = IC_RESULT (ic);
6062 letype = getSpec (operandType (left));
6063 retype = getSpec (operandType (right));
6064 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
6065 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
6066 /* assign the asmops */
6067 aopOp (result, ic, TRUE);
6068 aopOp (left, ic, FALSE);
6069 aopOp (right, ic, FALSE);
6071 genCmp (left, right, result, ifx, sign, ic);
6073 freeAsmop (result, NULL, ic, TRUE);
6076 /*-----------------------------------------------------------------*/
6077 /* gencjneshort - compare and jump if not equal */
6078 /*-----------------------------------------------------------------*/
6080 gencjneshort (operand * left, operand * right, symbol * lbl)
6082 int size = max (AOP_SIZE (left), AOP_SIZE (right));
6084 unsigned long lit = 0L;
6086 D (emitcode (";", "gencjneshort"));
6088 /* if the left side is a literal or
6089 if the right is in a pointer register and left
6091 if ((AOP_TYPE (left) == AOP_LIT) ||
6092 (AOP_TYPE (left) == AOP_IMMD) ||
6093 (AOP_TYPE (left) == AOP_DIR) ||
6094 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6101 if (AOP_TYPE (right) == AOP_LIT)
6102 lit = ulFromVal (AOP (right)->aopu.aop_lit);
6104 /* if the right side is a literal then anything goes */
6105 if (AOP_TYPE (right) == AOP_LIT &&
6106 AOP_TYPE (left) != AOP_DIR &&
6107 AOP_TYPE (left) != AOP_IMMD)
6111 emitcode ("cjne", "%s,%s,%05d$",
6112 aopGet (left, offset, FALSE, FALSE),
6113 aopGet (right, offset, FALSE, FALSE),
6119 /* if the right side is in a register or in direct space or
6120 if the left is a pointer register & right is not */
6121 else if (AOP_TYPE (right) == AOP_REG ||
6122 AOP_TYPE (right) == AOP_DIR ||
6123 AOP_TYPE (right) == AOP_LIT ||
6124 AOP_TYPE (right) == AOP_IMMD ||
6125 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6126 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6130 MOVA (aopGet (left, offset, FALSE, FALSE));
6131 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6132 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6133 emitcode ("jnz", "%05d$", lbl->key + 100);
6135 emitcode ("cjne", "a,%s,%05d$",
6136 aopGet (right, offset, FALSE, TRUE),
6143 /* right is a pointer reg need both a & b */
6146 //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
6147 wassertl(!BINUSE, "B was in use");
6148 MOVB (aopGet (left, offset, FALSE, FALSE));
6149 MOVA (aopGet (right, offset, FALSE, FALSE));
6150 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
6156 /*-----------------------------------------------------------------*/
6157 /* gencjne - compare and jump if not equal */
6158 /*-----------------------------------------------------------------*/
6160 gencjne (operand * left, operand * right, symbol * lbl, bool useCarry)
6162 symbol *tlbl = newiTempLabel (NULL);
6164 D (emitcode (";", "gencjne"));
6166 gencjneshort (left, right, lbl);
6172 emitcode ("sjmp", "%05d$", tlbl->key + 100);
6181 /*-----------------------------------------------------------------*/
6182 /* genCmpEq - generates code for equal to */
6183 /*-----------------------------------------------------------------*/
6185 genCmpEq (iCode * ic, iCode * ifx)
6187 bool swappedLR = FALSE;
6188 operand *left, *right, *result;
6190 D (emitcode (";", "genCmpEq"));
6192 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6193 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6194 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6196 /* if literal, literal on the right or
6197 if the right is in a pointer register and left
6199 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6200 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6202 operand *t = IC_RIGHT (ic);
6203 IC_RIGHT (ic) = IC_LEFT (ic);
6208 if (ifx && !AOP_SIZE (result))
6211 /* if they are both bit variables */
6212 if (AOP_TYPE (left) == AOP_CRY &&
6213 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6215 if (AOP_TYPE (right) == AOP_LIT)
6217 unsigned long lit = ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6220 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6221 emitcode ("cpl", "c");
6225 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6229 emitcode ("clr", "c");
6231 /* AOP_TYPE(right) == AOP_CRY */
6235 symbol *lbl = newiTempLabel (NULL);
6236 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6237 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6238 emitcode ("cpl", "c");
6241 /* if true label then we jump if condition
6243 tlbl = newiTempLabel (NULL);
6246 emitcode ("jnc", "%05d$", tlbl->key + 100);
6247 freeForBranchAsmop (result);
6248 freeForBranchAsmop (right);
6249 freeForBranchAsmop (left);
6250 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6254 emitcode ("jc", "%05d$", tlbl->key + 100);
6255 freeForBranchAsmop (result);
6256 freeForBranchAsmop (right);
6257 freeForBranchAsmop (left);
6258 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6264 tlbl = newiTempLabel (NULL);
6265 gencjneshort (left, right, tlbl);
6268 freeForBranchAsmop (result);
6269 freeForBranchAsmop (right);
6270 freeForBranchAsmop (left);
6271 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6276 symbol *lbl = newiTempLabel (NULL);
6277 emitcode ("sjmp", "%05d$", lbl->key + 100);
6279 freeForBranchAsmop (result);
6280 freeForBranchAsmop (right);
6281 freeForBranchAsmop (left);
6282 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6286 /* mark the icode as generated */
6291 /* if they are both bit variables */
6292 if (AOP_TYPE (left) == AOP_CRY &&
6293 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6295 if (AOP_TYPE (right) == AOP_LIT)
6297 unsigned long lit = ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6300 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6301 emitcode ("cpl", "c");
6305 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6309 emitcode ("clr", "c");
6311 /* AOP_TYPE(right) == AOP_CRY */
6315 symbol *lbl = newiTempLabel (NULL);
6316 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6317 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6318 emitcode ("cpl", "c");
6322 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6329 genIfxJump (ifx, "c", left, right, result);
6332 /* if the result is used in an arithmetic operation
6333 then put the result in place */
6338 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6340 gencjne (left, right, newiTempLabel (NULL), TRUE);
6341 aopPut (result, "c", 0);
6344 gencjne (left, right, newiTempLabel (NULL), FALSE);
6347 genIfxJump (ifx, "a", left, right, result);
6350 /* if the result is used in an arithmetic operation
6351 then put the result in place */
6352 if (AOP_TYPE (result) != AOP_CRY)
6354 /* leave the result in acc */
6358 freeAsmop (result, NULL, ic, TRUE);
6361 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6362 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6366 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6367 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6371 /*-----------------------------------------------------------------*/
6372 /* ifxForOp - returns the icode containing the ifx for operand */
6373 /*-----------------------------------------------------------------*/
6375 ifxForOp (operand * op, iCode * ic)
6377 /* if true symbol then needs to be assigned */
6378 if (IS_TRUE_SYMOP (op))
6381 /* if this has register type condition and
6382 the next instruction is ifx with the same operand
6383 and live to of the operand is upto the ifx only then */
6385 ic->next->op == IFX &&
6386 IC_COND (ic->next)->key == op->key &&
6387 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6393 /*-----------------------------------------------------------------*/
6394 /* hasInc - operand is incremented before any other use */
6395 /*-----------------------------------------------------------------*/
6397 hasInc (operand *op, iCode *ic, int osize)
6399 sym_link *type = operandType(op);
6400 sym_link *retype = getSpec (type);
6401 iCode *lic = ic->next;
6404 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6405 if (!IS_SYMOP(op)) return NULL;
6407 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6408 if (IS_AGGREGATE(type->next)) return NULL;
6409 if (osize != (isize = getSize(type->next))) return NULL;
6412 /* if operand of the form op = op + <sizeof *op> */
6413 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6414 isOperandEqual(IC_RESULT(lic),op) &&
6415 isOperandLiteral(IC_RIGHT(lic)) &&
6416 operandLitValue(IC_RIGHT(lic)) == isize) {
6419 /* if the operand used or deffed */
6420 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6423 /* if GOTO or IFX */
6424 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6430 /*-----------------------------------------------------------------*/
6431 /* genAndOp - for && operation */
6432 /*-----------------------------------------------------------------*/
6434 genAndOp (iCode * ic)
6436 operand *left, *right, *result;
6439 D (emitcode (";", "genAndOp"));
6441 /* note here that && operations that are in an
6442 if statement are taken away by backPatchLabels
6443 only those used in arthmetic operations remain */
6444 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6445 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6446 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6448 /* if both are bit variables */
6449 if (AOP_TYPE (left) == AOP_CRY &&
6450 AOP_TYPE (right) == AOP_CRY)
6452 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6453 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6458 tlbl = newiTempLabel (NULL);
6460 emitcode ("jz", "%05d$", tlbl->key + 100);
6466 freeAsmop (result, NULL, ic, TRUE);
6467 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6468 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6472 /*-----------------------------------------------------------------*/
6473 /* genOrOp - for || operation */
6474 /*-----------------------------------------------------------------*/
6476 genOrOp (iCode * ic)
6478 operand *left, *right, *result;
6481 D (emitcode (";", "genOrOp"));
6483 /* note here that || operations that are in an
6484 if statement are taken away by backPatchLabels
6485 only those used in arthmetic operations remain */
6486 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6487 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6488 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6490 /* if both are bit variables */
6491 if (AOP_TYPE (left) == AOP_CRY &&
6492 AOP_TYPE (right) == AOP_CRY)
6494 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6495 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6500 tlbl = newiTempLabel (NULL);
6502 emitcode ("jnz", "%05d$", tlbl->key + 100);
6508 freeAsmop (result, NULL, ic, TRUE);
6509 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6510 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6513 /*-----------------------------------------------------------------*/
6514 /* isLiteralBit - test if lit == 2^n */
6515 /*-----------------------------------------------------------------*/
6517 isLiteralBit (unsigned long lit)
6519 unsigned long pw[32] =
6520 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6521 0x100L, 0x200L, 0x400L, 0x800L,
6522 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6523 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6524 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6525 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6526 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6529 for (idx = 0; idx < 32; idx++)
6535 /*-----------------------------------------------------------------*/
6536 /* continueIfTrue - */
6537 /*-----------------------------------------------------------------*/
6539 continueIfTrue (iCode * ic)
6542 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6546 /*-----------------------------------------------------------------*/
6548 /*-----------------------------------------------------------------*/
6550 jumpIfTrue (iCode * ic)
6553 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6557 /*-----------------------------------------------------------------*/
6558 /* jmpTrueOrFalse - */
6559 /*-----------------------------------------------------------------*/
6561 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6563 // ugly but optimized by peephole
6566 symbol *nlbl = newiTempLabel (NULL);
6567 emitcode ("sjmp", "%05d$", nlbl->key + 100);
6569 freeForBranchAsmop (result);
6570 freeForBranchAsmop (right);
6571 freeForBranchAsmop (left);
6572 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6577 freeForBranchAsmop (result);
6578 freeForBranchAsmop (right);
6579 freeForBranchAsmop (left);
6580 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6586 /*-----------------------------------------------------------------*/
6587 /* genAnd - code for and */
6588 /*-----------------------------------------------------------------*/
6590 genAnd (iCode * ic, iCode * ifx)
6592 operand *left, *right, *result;
6593 int size, offset = 0;
6594 unsigned long lit = 0L;
6598 D (emitcode (";", "genAnd"));
6600 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6601 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6602 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6605 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
6607 AOP_TYPE (left), AOP_TYPE (right));
6608 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
6610 AOP_SIZE (left), AOP_SIZE (right));
6613 /* if left is a literal & right is not then exchange them */
6614 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6615 AOP_NEEDSACC (left))
6617 operand *tmp = right;
6622 /* if result = right then exchange left and right */
6623 if (sameRegs (AOP (result), AOP (right)))
6625 operand *tmp = right;
6630 /* if right is bit then exchange them */
6631 if (AOP_TYPE (right) == AOP_CRY &&
6632 AOP_TYPE (left) != AOP_CRY)
6634 operand *tmp = right;
6638 if (AOP_TYPE (right) == AOP_LIT)
6639 lit = ulFromVal (AOP (right)->aopu.aop_lit);
6641 size = AOP_SIZE (result);
6644 // result = bit & yy;
6645 if (AOP_TYPE (left) == AOP_CRY)
6647 // c = bit & literal;
6648 if (AOP_TYPE (right) == AOP_LIT)
6652 if (size && sameRegs (AOP (result), AOP (left)))
6655 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6660 if (size && (AOP_TYPE (result) == AOP_CRY))
6662 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6665 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6670 emitcode ("clr", "c");
6675 if (AOP_TYPE (right) == AOP_CRY)
6678 if (IS_OP_ACCUSE (left))
6680 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6684 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6685 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6691 MOVA (aopGet (right, 0, FALSE, FALSE));
6693 emitcode ("rrc", "a");
6694 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6702 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6703 genIfxJump (ifx, "c", left, right, result);
6707 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6708 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6709 if ((AOP_TYPE (right) == AOP_LIT) &&
6710 (AOP_TYPE (result) == AOP_CRY) &&
6711 (AOP_TYPE (left) != AOP_CRY))
6713 int posbit = isLiteralBit (lit);
6718 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6722 switch (posbit & 0x07)
6724 case 0: emitcode ("rrc", "a");
6726 case 7: emitcode ("rlc", "a");
6728 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6737 SNPRINTF (buffer, sizeof(buffer),
6738 "acc.%d", posbit & 0x07);
6739 genIfxJump (ifx, buffer, left, right, result);
6742 {// what is this case? just found it in ds390/gen.c
6743 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6750 symbol *tlbl = newiTempLabel (NULL);
6751 int sizel = AOP_SIZE (left);
6753 emitcode ("setb", "c");
6756 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6758 MOVA (aopGet (left, offset, FALSE, FALSE));
6760 if ((posbit = isLiteralBit (bytelit)) != 0)
6761 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6764 if (bytelit != 0x0FFL)
6765 emitcode ("anl", "a,%s",
6766 aopGet (right, offset, FALSE, TRUE));
6767 emitcode ("jnz", "%05d$", tlbl->key + 100);
6772 // bit = left & literal
6775 emitcode ("clr", "c");
6778 // if(left & literal)
6782 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6792 /* if left is same as result */
6793 if (sameRegs (AOP (result), AOP (left)))
6795 for (; size--; offset++)
6797 if (AOP_TYPE (right) == AOP_LIT)
6799 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6800 if (bytelit == 0x0FF)
6802 /* dummy read of volatile operand */
6803 if (isOperandVolatile (left, FALSE))
6804 MOVA (aopGet (left, offset, FALSE, FALSE));
6808 else if (bytelit == 0)
6810 aopPut (result, zero, offset);
6812 else if (IS_AOP_PREG (result))
6814 MOVA (aopGet (left, offset, FALSE, TRUE));
6815 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6816 aopPut (result, "a", offset);
6819 emitcode ("anl", "%s,%s",
6820 aopGet (left, offset, FALSE, TRUE),
6821 aopGet (right, offset, FALSE, FALSE));
6825 if (AOP_TYPE (left) == AOP_ACC)
6828 emitcode("mov", "a,b");
6829 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6831 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6833 MOVB (aopGet (left, offset, FALSE, FALSE));
6834 MOVA (aopGet (right, offset, FALSE, FALSE));
6835 emitcode ("anl", "a,b");
6836 aopPut (result, "a", offset);
6838 else if (aopGetUsesAcc (left, offset))
6840 MOVA (aopGet (left, offset, FALSE, FALSE));
6841 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6842 aopPut (result, "a", offset);
6846 MOVA (aopGet (right, offset, FALSE, FALSE));
6847 if (IS_AOP_PREG (result))
6849 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6850 aopPut (result, "a", offset);
6853 emitcode ("anl", "%s,a", aopGet (left, offset, FALSE, TRUE));
6860 // left & result in different registers
6861 if (AOP_TYPE (result) == AOP_CRY)
6864 // if(size), result in bit
6865 // if(!size && ifx), conditional oper: if(left & right)
6866 symbol *tlbl = newiTempLabel (NULL);
6867 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6869 emitcode ("setb", "c");
6872 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6873 && AOP_TYPE(left)==AOP_ACC)
6876 emitcode("mov", "a,b");
6877 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6879 else if (AOP_TYPE(left)==AOP_ACC)
6883 bool pushedB = pushB ();
6884 emitcode("mov", "b,a");
6885 MOVA (aopGet (right, offset, FALSE, FALSE));
6886 emitcode("anl", "a,b");
6891 MOVA (aopGet (right, offset, FALSE, FALSE));
6892 emitcode("anl", "a,b");
6895 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6897 MOVB (aopGet (left, offset, FALSE, FALSE));
6898 MOVA (aopGet (right, offset, FALSE, FALSE));
6899 emitcode ("anl", "a,b");
6901 else if (aopGetUsesAcc (left, offset))
6903 MOVA (aopGet (left, offset, FALSE, FALSE));
6904 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6908 MOVA (aopGet (right, offset, FALSE, FALSE));
6909 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6912 emitcode ("jnz", "%05d$", tlbl->key + 100);
6922 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6928 for (; (size--); offset++)
6931 // result = left & right
6932 if (AOP_TYPE (right) == AOP_LIT)
6934 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6935 if (bytelit == 0x0FF)
6938 aopGet (left, offset, FALSE, FALSE),
6942 else if (bytelit == 0)
6944 /* dummy read of volatile operand */
6945 if (isOperandVolatile (left, FALSE))
6946 MOVA (aopGet (left, offset, FALSE, FALSE));
6947 aopPut (result, zero, offset);
6950 else if (AOP_TYPE (left) == AOP_ACC)
6954 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6955 aopPut (result, "a", offset);
6960 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6961 aopPut (result, "b", offset);
6966 // faster than result <- left, anl result,right
6967 // and better if result is SFR
6968 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6969 && AOP_TYPE(left)==AOP_ACC)
6972 emitcode("mov", "a,b");
6973 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6975 else if (AOP_TYPE(left)==AOP_ACC)
6979 bool pushedB = pushB ();
6980 emitcode("mov", "b,a");
6981 MOVA (aopGet (right, offset, FALSE, FALSE));
6982 emitcode("anl", "a,b");
6987 MOVA (aopGet (right, offset, FALSE, FALSE));
6988 emitcode("anl", "a,b");
6991 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6993 MOVB (aopGet (left, offset, FALSE, FALSE));
6994 MOVA (aopGet (right, offset, FALSE, FALSE));
6995 emitcode ("anl", "a,b");
6997 else if (aopGetUsesAcc (left, offset))
6999 MOVA (aopGet (left, offset, FALSE, FALSE));
7000 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7004 MOVA (aopGet (right, offset, FALSE, FALSE));
7005 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7007 aopPut (result, "a", offset);
7013 freeAsmop (result, NULL, ic, TRUE);
7014 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7015 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7018 /*-----------------------------------------------------------------*/
7019 /* genOr - code for or */
7020 /*-----------------------------------------------------------------*/
7022 genOr (iCode * ic, iCode * ifx)
7024 operand *left, *right, *result;
7025 int size, offset = 0;
7026 unsigned long lit = 0L;
7029 D (emitcode (";", "genOr"));
7031 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7032 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7033 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7036 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
7038 AOP_TYPE (left), AOP_TYPE (right));
7039 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
7041 AOP_SIZE (left), AOP_SIZE (right));
7044 /* if left is a literal & right is not then exchange them */
7045 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7046 AOP_NEEDSACC (left))
7048 operand *tmp = right;
7053 /* if result = right then exchange them */
7054 if (sameRegs (AOP (result), AOP (right)))
7056 operand *tmp = right;
7061 /* if right is bit then exchange them */
7062 if (AOP_TYPE (right) == AOP_CRY &&
7063 AOP_TYPE (left) != AOP_CRY)
7065 operand *tmp = right;
7069 if (AOP_TYPE (right) == AOP_LIT)
7070 lit = ulFromVal (AOP (right)->aopu.aop_lit);
7072 size = AOP_SIZE (result);
7076 if (AOP_TYPE (left) == AOP_CRY)
7078 if (AOP_TYPE (right) == AOP_LIT)
7080 // c = bit | literal;
7083 // lit != 0 => result = 1
7084 if (AOP_TYPE (result) == AOP_CRY)
7087 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7089 continueIfTrue (ifx);
7092 emitcode ("setb", "c");
7096 // lit == 0 => result = left
7097 if (size && sameRegs (AOP (result), AOP (left)))
7099 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7104 if (AOP_TYPE (right) == AOP_CRY)
7107 if (IS_OP_ACCUSE (left))
7109 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
7113 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7114 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7120 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7122 symbol *tlbl = newiTempLabel (NULL);
7123 emitcode ("jb", "%s,%05d$",
7124 AOP (left)->aopu.aop_dir, tlbl->key + 100);
7126 emitcode ("jnz", "%05d$", tlbl->key + 100);
7127 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7133 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7142 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7143 genIfxJump (ifx, "c", left, right, result);
7147 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7148 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7149 if ((AOP_TYPE (right) == AOP_LIT) &&
7150 (AOP_TYPE (result) == AOP_CRY) &&
7151 (AOP_TYPE (left) != AOP_CRY))
7157 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7159 continueIfTrue (ifx);
7164 // lit = 0, result = boolean(left)
7166 emitcode ("setb", "c");
7170 symbol *tlbl = newiTempLabel (NULL);
7171 emitcode ("jnz", "%05d$", tlbl->key + 100);
7177 genIfxJump (ifx, "a", left, right, result);
7185 /* if left is same as result */
7186 if (sameRegs (AOP (result), AOP (left)))
7188 for (; size--; offset++)
7190 if (AOP_TYPE (right) == AOP_LIT)
7192 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7195 /* dummy read of volatile operand */
7196 if (isOperandVolatile (left, FALSE))
7197 MOVA (aopGet (left, offset, FALSE, FALSE));
7201 else if (bytelit == 0x0FF)
7203 aopPut (result, "#0xff", offset);
7205 else if (IS_AOP_PREG (left))
7207 MOVA (aopGet (left, offset, FALSE, TRUE));
7208 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7209 aopPut (result, "a", offset);
7213 emitcode ("orl", "%s,%s",
7214 aopGet (left, offset, FALSE, TRUE),
7215 aopGet (right, offset, FALSE, FALSE));
7220 if (AOP_TYPE (left) == AOP_ACC)
7223 emitcode("mov", "a,b");
7224 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7226 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7228 MOVB (aopGet (left, offset, FALSE, FALSE));
7229 MOVA (aopGet (right, offset, FALSE, FALSE));
7230 emitcode ("orl", "a,b");
7231 aopPut (result, "a", offset);
7233 else if (aopGetUsesAcc (left, offset))
7235 MOVA (aopGet (left, offset, FALSE, FALSE));
7236 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7237 aopPut (result, "a", offset);
7241 MOVA (aopGet (right, offset, FALSE, FALSE));
7242 if (IS_AOP_PREG (left))
7244 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7245 aopPut (result, "a", offset);
7249 emitcode ("orl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7257 // left & result in different registers
7258 if (AOP_TYPE (result) == AOP_CRY)
7261 // if(size), result in bit
7262 // if(!size && ifx), conditional oper: if(left | right)
7263 symbol *tlbl = newiTempLabel (NULL);
7264 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7266 emitcode ("setb", "c");
7269 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7270 && AOP_TYPE(left)==AOP_ACC)
7273 emitcode("mov", "a,b");
7274 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7276 else if (AOP_TYPE(left)==AOP_ACC)
7280 bool pushedB = pushB ();
7281 emitcode("mov", "b,a");
7282 MOVA (aopGet (right, offset, FALSE, FALSE));
7283 emitcode("orl", "a,b");
7288 MOVA (aopGet (right, offset, FALSE, FALSE));
7289 emitcode("orl", "a,b");
7292 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7294 MOVB (aopGet (left, offset, FALSE, FALSE));
7295 MOVA (aopGet (right, offset, FALSE, FALSE));
7296 emitcode ("orl", "a,b");
7298 else if (aopGetUsesAcc (left, offset))
7300 MOVA (aopGet (left, offset, FALSE, FALSE));
7301 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7305 MOVA (aopGet (right, offset, FALSE, FALSE));
7306 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7309 emitcode ("jnz", "%05d$", tlbl->key + 100);
7319 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7325 for (; (size--); offset++)
7328 // result = left | right
7329 if (AOP_TYPE (right) == AOP_LIT)
7331 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7335 aopGet (left, offset, FALSE, FALSE),
7339 else if (bytelit == 0x0FF)
7341 /* dummy read of volatile operand */
7342 if (isOperandVolatile (left, FALSE))
7343 MOVA (aopGet (left, offset, FALSE, FALSE));
7344 aopPut (result, "#0xff", offset);
7348 // faster than result <- left, orl result,right
7349 // and better if result is SFR
7350 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7351 && AOP_TYPE(left)==AOP_ACC)
7354 emitcode("mov", "a,b");
7355 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7357 else if (AOP_TYPE(left)==AOP_ACC)
7361 bool pushedB = pushB ();
7362 emitcode("mov", "b,a");
7363 MOVA (aopGet (right, offset, FALSE, FALSE));
7364 emitcode("orl", "a,b");
7369 MOVA (aopGet (right, offset, FALSE, FALSE));
7370 emitcode("orl", "a,b");
7373 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7375 MOVB (aopGet (left, offset, FALSE, FALSE));
7376 MOVA (aopGet (right, offset, FALSE, FALSE));
7377 emitcode ("orl", "a,b");
7379 else if (aopGetUsesAcc (left, offset))
7381 MOVA (aopGet (left, offset, FALSE, FALSE));
7382 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7386 MOVA (aopGet (right, offset, FALSE, FALSE));
7387 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7389 aopPut (result, "a", offset);
7395 freeAsmop (result, NULL, ic, TRUE);
7396 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7397 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7400 /*-----------------------------------------------------------------*/
7401 /* genXor - code for xclusive or */
7402 /*-----------------------------------------------------------------*/
7404 genXor (iCode * ic, iCode * ifx)
7406 operand *left, *right, *result;
7407 int size, offset = 0;
7408 unsigned long lit = 0L;
7411 D (emitcode (";", "genXor"));
7413 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7414 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7415 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7418 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
7420 AOP_TYPE (left), AOP_TYPE (right));
7421 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
7423 AOP_SIZE (left), AOP_SIZE (right));
7426 /* if left is a literal & right is not ||
7427 if left needs acc & right does not */
7428 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7429 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7431 operand *tmp = right;
7436 /* if result = right then exchange them */
7437 if (sameRegs (AOP (result), AOP (right)))
7439 operand *tmp = right;
7444 /* if right is bit then exchange them */
7445 if (AOP_TYPE (right) == AOP_CRY &&
7446 AOP_TYPE (left) != AOP_CRY)
7448 operand *tmp = right;
7453 if (AOP_TYPE (right) == AOP_LIT)
7454 lit = ulFromVal (AOP (right)->aopu.aop_lit);
7456 size = AOP_SIZE (result);
7460 if (AOP_TYPE (left) == AOP_CRY)
7462 if (AOP_TYPE (right) == AOP_LIT)
7464 // c = bit & literal;
7467 // lit>>1 != 0 => result = 1
7468 if (AOP_TYPE (result) == AOP_CRY)
7471 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7473 continueIfTrue (ifx);
7476 emitcode ("setb", "c");
7483 // lit == 0, result = left
7484 if (size && sameRegs (AOP (result), AOP (left)))
7486 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7490 // lit == 1, result = not(left)
7491 if (size && sameRegs (AOP (result), AOP (left)))
7493 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7498 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7499 emitcode ("cpl", "c");
7507 symbol *tlbl = newiTempLabel (NULL);
7508 if (AOP_TYPE (right) == AOP_CRY)
7511 if (IS_OP_ACCUSE (left))
7512 {// left already is in the carry
7513 operand *tmp = right;
7527 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7528 emitcode ("cpl", "c");
7536 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7537 genIfxJump (ifx, "c", left, right, result);
7541 /* if left is same as result */
7542 if (sameRegs (AOP (result), AOP (left)))
7544 for (; size--; offset++)
7546 if (AOP_TYPE (right) == AOP_LIT)
7548 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7551 /* dummy read of volatile operand */
7552 if (isOperandVolatile (left, FALSE))
7553 MOVA (aopGet (left, offset, FALSE, FALSE));
7557 else if (IS_AOP_PREG (left))
7559 MOVA (aopGet (left, offset, FALSE, TRUE));
7560 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7561 aopPut (result, "a", offset);
7565 emitcode ("xrl", "%s,%s",
7566 aopGet (left, offset, FALSE, TRUE),
7567 aopGet (right, offset, FALSE, FALSE));
7572 if (AOP_TYPE (left) == AOP_ACC)
7575 emitcode("mov", "a,b");
7576 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7578 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7580 MOVB (aopGet (left, offset, FALSE, FALSE));
7581 MOVA (aopGet (right, offset, FALSE, FALSE));
7582 emitcode ("xrl", "a,b");
7583 aopPut (result, "a", offset);
7585 else if (aopGetUsesAcc (left, offset))
7587 MOVA (aopGet (left, offset, FALSE, FALSE));
7588 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7589 aopPut (result, "a", offset);
7593 MOVA (aopGet (right, offset, FALSE, FALSE));
7594 if (IS_AOP_PREG (left))
7596 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7597 aopPut (result, "a", offset);
7600 emitcode ("xrl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7607 // left & result in different registers
7608 if (AOP_TYPE (result) == AOP_CRY)
7611 // if(size), result in bit
7612 // if(!size && ifx), conditional oper: if(left ^ right)
7613 symbol *tlbl = newiTempLabel (NULL);
7614 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7617 emitcode ("setb", "c");
7620 if ((AOP_TYPE (right) == AOP_LIT) &&
7621 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7623 MOVA (aopGet (left, offset, FALSE, FALSE));
7625 else if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7626 && AOP_TYPE(left)==AOP_ACC)
7629 emitcode("mov", "a,b");
7630 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7632 else if (AOP_TYPE(left)==AOP_ACC)
7636 bool pushedB = pushB ();
7637 emitcode("mov", "b,a");
7638 MOVA (aopGet (right, offset, FALSE, FALSE));
7639 emitcode("xrl", "a,b");
7644 MOVA (aopGet (right, offset, FALSE, FALSE));
7645 emitcode("xrl", "a,b");
7648 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7650 MOVB (aopGet (left, offset, FALSE, FALSE));
7651 MOVA (aopGet (right, offset, FALSE, FALSE));
7652 emitcode ("xrl", "a,b");
7654 else if (aopGetUsesAcc (left, offset))
7656 MOVA (aopGet (left, offset, FALSE, FALSE));
7657 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7661 MOVA (aopGet (right, offset, FALSE, FALSE));
7662 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7665 emitcode ("jnz", "%05d$", tlbl->key + 100);
7675 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7679 for (; (size--); offset++)
7682 // result = left ^ right
7683 if (AOP_TYPE (right) == AOP_LIT)
7685 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7689 aopGet (left, offset, FALSE, FALSE),
7694 // faster than result <- left, xrl result,right
7695 // and better if result is SFR
7696 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7697 && AOP_TYPE(left)==AOP_ACC)
7700 emitcode("mov", "a,b");
7701 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7703 else if (AOP_TYPE(left)==AOP_ACC)
7707 bool pushedB = pushB ();
7708 emitcode("mov", "b,a");
7709 MOVA (aopGet (right, offset, FALSE, FALSE));
7710 emitcode("xrl", "a,b");
7715 MOVA (aopGet (right, offset, FALSE, FALSE));
7716 emitcode("xrl", "a,b");
7719 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7721 MOVB (aopGet (left, offset, FALSE, FALSE));
7722 MOVA (aopGet (right, offset, FALSE, FALSE));
7723 emitcode ("xrl", "a,b");
7725 else if (aopGetUsesAcc (left, offset))
7727 MOVA (aopGet (left, offset, FALSE, FALSE));
7728 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7732 MOVA (aopGet (right, offset, FALSE, FALSE));
7733 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7735 aopPut (result, "a", offset);
7741 freeAsmop (result, NULL, ic, TRUE);
7742 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7743 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7746 /*-----------------------------------------------------------------*/
7747 /* genInline - write the inline code out */
7748 /*-----------------------------------------------------------------*/
7750 genInline (iCode * ic)
7752 char *buffer, *bp, *bp1;
7753 bool inComment = FALSE;
7755 D (emitcode (";", "genInline"));
7757 _G.inLine += (!options.asmpeep);
7759 buffer = bp = bp1 = Safe_strdup (IC_INLINE (ic));
7761 /* emit each line as a code */
7779 /* Add \n for labels, not dirs such as c:\mydir */
7780 if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
7798 _G.inLine -= (!options.asmpeep);
7801 /*-----------------------------------------------------------------*/
7802 /* genRRC - rotate right with carry */
7803 /*-----------------------------------------------------------------*/
7807 operand *left, *result;
7811 D (emitcode (";", "genRRC"));
7813 /* rotate right with carry */
7814 left = IC_LEFT (ic);
7815 result = IC_RESULT (ic);
7816 aopOp (left, ic, FALSE);
7817 aopOp (result, ic, FALSE);
7819 /* move it to the result */
7820 size = AOP_SIZE (result);
7822 if (size == 1) { /* special case for 1 byte */
7823 l = aopGet (left, offset, FALSE, FALSE);
7825 emitcode ("rr", "a");
7828 /* no need to clear carry, bit7 will be written later */
7831 l = aopGet (left, offset, FALSE, FALSE);
7833 emitcode ("rrc", "a");
7834 if (AOP_SIZE (result) > 1)
7835 aopPut (result, "a", offset--);
7837 /* now we need to put the carry into the
7838 highest order byte of the result */
7839 if (AOP_SIZE (result) > 1)
7841 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7844 emitcode ("mov", "acc.7,c");
7846 aopPut (result, "a", AOP_SIZE (result) - 1);
7847 freeAsmop (result, NULL, ic, TRUE);
7848 freeAsmop (left, NULL, ic, TRUE);
7851 /*-----------------------------------------------------------------*/
7852 /* genRLC - generate code for rotate left with carry */
7853 /*-----------------------------------------------------------------*/
7857 operand *left, *result;
7861 D (emitcode (";", "genRLC"));
7863 /* rotate right with carry */
7864 left = IC_LEFT (ic);
7865 result = IC_RESULT (ic);
7866 aopOp (left, ic, FALSE);
7867 aopOp (result, ic, FALSE);
7869 /* move it to the result */
7870 size = AOP_SIZE (result);
7874 l = aopGet (left, offset, FALSE, FALSE);
7876 if (size == 0) { /* special case for 1 byte */
7880 emitcode("rlc","a"); /* bit0 will be written later */
7881 if (AOP_SIZE (result) > 1)
7883 aopPut (result, "a", offset++);
7888 l = aopGet (left, offset, FALSE, FALSE);
7890 emitcode ("rlc", "a");
7891 if (AOP_SIZE (result) > 1)
7892 aopPut (result, "a", offset++);
7895 /* now we need to put the carry into the
7896 highest order byte of the result */
7897 if (AOP_SIZE (result) > 1)
7899 l = aopGet (result, 0, FALSE, FALSE);
7902 emitcode ("mov", "acc.0,c");
7904 aopPut (result, "a", 0);
7905 freeAsmop (result, NULL, ic, TRUE);
7906 freeAsmop (left, NULL, ic, TRUE);
7909 /*-----------------------------------------------------------------*/
7910 /* genGetHbit - generates code get highest order bit */
7911 /*-----------------------------------------------------------------*/
7913 genGetHbit (iCode * ic)
7915 operand *left, *result;
7917 D (emitcode (";", "genGetHbit"));
7919 left = IC_LEFT (ic);
7920 result = IC_RESULT (ic);
7921 aopOp (left, ic, FALSE);
7922 aopOp (result, ic, FALSE);
7924 /* get the highest order byte into a */
7925 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7926 if (AOP_TYPE (result) == AOP_CRY)
7928 emitcode ("rlc", "a");
7933 emitcode ("rl", "a");
7934 emitcode ("anl", "a,#0x01");
7938 freeAsmop (result, NULL, ic, TRUE);
7939 freeAsmop (left, NULL, ic, TRUE);
7942 /*-----------------------------------------------------------------*/
7943 /* genGetAbit - generates code get a single bit */
7944 /*-----------------------------------------------------------------*/
7946 genGetAbit (iCode * ic)
7948 operand *left, *right, *result;
7951 D (emitcode (";", "genGetAbit"));
7953 left = IC_LEFT (ic);
7954 right = IC_RIGHT (ic);
7955 result = IC_RESULT (ic);
7956 aopOp (left, ic, FALSE);
7957 aopOp (right, ic, FALSE);
7958 aopOp (result, ic, FALSE);
7960 shCount = (int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7962 /* get the needed byte into a */
7963 MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7965 if (AOP_TYPE (result) == AOP_CRY)
7968 emitcode ("rlc", "a");
7969 else if ((shCount) == 0)
7970 emitcode ("rrc", "a");
7972 emitcode ("mov", "c,acc[%d]", shCount);
7980 emitcode ("rr", "a");
7983 emitcode ("rr", "a");
7986 emitcode ("anl", "a,#0x01");
7990 emitcode ("mov", "c,acc[%d]", shCount);
7991 emitcode ("clr", "a");
7992 emitcode ("rlc", "a");
7995 emitcode ("swap", "a");
7996 emitcode ("anl", "a,#0x01");
7999 emitcode ("rl", "a");
8002 emitcode ("rl", "a");
8003 emitcode ("anl", "a,#0x01");
8009 freeAsmop (result, NULL, ic, TRUE);
8010 freeAsmop (right, NULL, ic, TRUE);
8011 freeAsmop (left, NULL, ic, TRUE);
8014 /*-----------------------------------------------------------------*/
8015 /* genGetByte - generates code get a single byte */
8016 /*-----------------------------------------------------------------*/
8018 genGetByte (iCode * ic)
8020 operand *left, *right, *result;
8023 D (emitcode (";", "genGetByte"));
8025 left = IC_LEFT (ic);
8026 right = IC_RIGHT (ic);
8027 result = IC_RESULT (ic);
8028 aopOp (left, ic, FALSE);
8029 aopOp (right, ic, FALSE);
8030 aopOp (result, ic, FALSE);
8032 offset = (int) ulFromVal (AOP (right)->aopu.aop_lit) / 8;
8034 aopGet (left, offset, FALSE, FALSE),
8037 freeAsmop (result, NULL, ic, TRUE);
8038 freeAsmop (right, NULL, ic, TRUE);
8039 freeAsmop (left, NULL, ic, TRUE);
8042 /*-----------------------------------------------------------------*/
8043 /* genGetWord - generates code get two bytes */
8044 /*-----------------------------------------------------------------*/
8046 genGetWord (iCode * ic)
8048 operand *left, *right, *result;
8051 D (emitcode (";", "genGetWord"));
8053 left = IC_LEFT (ic);
8054 right = IC_RIGHT (ic);
8055 result = IC_RESULT (ic);
8056 aopOp (left, ic, FALSE);
8057 aopOp (right, ic, FALSE);
8058 aopOp (result, ic, FALSE);
8060 offset = (int) ulFromVal (AOP (right)->aopu.aop_lit) / 8;
8062 aopGet (left, offset, FALSE, FALSE),
8065 aopGet (left, offset+1, FALSE, FALSE),
8068 freeAsmop (result, NULL, ic, TRUE);
8069 freeAsmop (right, NULL, ic, TRUE);
8070 freeAsmop (left, NULL, ic, TRUE);
8073 /*-----------------------------------------------------------------*/
8074 /* genSwap - generates code to swap nibbles or bytes */
8075 /*-----------------------------------------------------------------*/
8077 genSwap (iCode * ic)
8079 operand *left, *result;
8081 D(emitcode (";", "genSwap"));
8083 left = IC_LEFT (ic);
8084 result = IC_RESULT (ic);
8085 aopOp (left, ic, FALSE);
8086 aopOp (result, ic, FALSE);
8088 switch (AOP_SIZE (left))
8090 case 1: /* swap nibbles in byte */
8091 MOVA (aopGet (left, 0, FALSE, FALSE));
8092 emitcode ("swap", "a");
8093 aopPut (result, "a", 0);
8095 case 2: /* swap bytes in word */
8096 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
8098 MOVA (aopGet (left, 0, FALSE, FALSE));
8099 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8100 aopPut (result, "a", 1);
8102 else if (operandsEqu (left, result))
8105 bool pushedB = FALSE, leftInB = FALSE;
8107 MOVA (aopGet (left, 0, FALSE, FALSE));
8108 if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
8111 emitcode ("mov", "b,a");
8115 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8116 aopPut (result, reg, 1);
8123 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8124 aopPut (result, aopGet (left, 0, FALSE, FALSE), 1);
8128 wassertl(FALSE, "unsupported SWAP operand size");
8131 freeAsmop (result, NULL, ic, TRUE);
8132 freeAsmop (left, NULL, ic, TRUE);
8135 /*-----------------------------------------------------------------*/
8136 /* AccRol - rotate left accumulator by known count */
8137 /*-----------------------------------------------------------------*/
8139 AccRol (int shCount)
8141 shCount &= 0x0007; // shCount : 0..7
8148 emitcode ("rl", "a");
8151 emitcode ("rl", "a");
8152 emitcode ("rl", "a");
8155 emitcode ("swap", "a");
8156 emitcode ("rr", "a");
8159 emitcode ("swap", "a");
8162 emitcode ("swap", "a");
8163 emitcode ("rl", "a");
8166 emitcode ("rr", "a");
8167 emitcode ("rr", "a");
8170 emitcode ("rr", "a");
8175 /*-----------------------------------------------------------------*/
8176 /* AccLsh - left shift accumulator by known count */
8177 /*-----------------------------------------------------------------*/
8179 AccLsh (int shCount)
8184 emitcode ("add", "a,acc");
8185 else if (shCount == 2)
8187 emitcode ("add", "a,acc");
8188 emitcode ("add", "a,acc");
8192 /* rotate left accumulator */
8194 /* and kill the lower order bits */
8195 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
8200 /*-----------------------------------------------------------------*/
8201 /* AccRsh - right shift accumulator by known count */
8202 /*-----------------------------------------------------------------*/
8204 AccRsh (int shCount)
8211 emitcode ("rrc", "a");
8215 /* rotate right accumulator */
8216 AccRol (8 - shCount);
8217 /* and kill the higher order bits */
8218 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8223 /*-----------------------------------------------------------------*/
8224 /* AccSRsh - signed right shift accumulator by known count */
8225 /*-----------------------------------------------------------------*/
8227 AccSRsh (int shCount)
8234 emitcode ("mov", "c,acc.7");
8235 emitcode ("rrc", "a");
8237 else if (shCount == 2)
8239 emitcode ("mov", "c,acc.7");
8240 emitcode ("rrc", "a");
8241 emitcode ("mov", "c,acc.7");
8242 emitcode ("rrc", "a");
8246 tlbl = newiTempLabel (NULL);
8247 /* rotate right accumulator */
8248 AccRol (8 - shCount);
8249 /* and kill the higher order bits */
8250 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8251 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8252 emitcode ("orl", "a,#0x%02x",
8253 (unsigned char) ~SRMask[shCount]);
8259 /*-----------------------------------------------------------------*/
8260 /* shiftR1Left2Result - shift right one byte from left to result */
8261 /*-----------------------------------------------------------------*/
8263 shiftR1Left2Result (operand * left, int offl,
8264 operand * result, int offr,
8265 int shCount, int sign)
8267 MOVA (aopGet (left, offl, FALSE, FALSE));
8268 /* shift right accumulator */
8273 aopPut (result, "a", offr);
8276 /*-----------------------------------------------------------------*/
8277 /* shiftL1Left2Result - shift left one byte from left to result */
8278 /*-----------------------------------------------------------------*/
8280 shiftL1Left2Result (operand * left, int offl,
8281 operand * result, int offr, int shCount)
8284 l = aopGet (left, offl, FALSE, FALSE);
8286 /* shift left accumulator */
8288 aopPut (result, "a", offr);
8291 /*-----------------------------------------------------------------*/
8292 /* movLeft2Result - move byte from left to result */
8293 /*-----------------------------------------------------------------*/
8295 movLeft2Result (operand * left, int offl,
8296 operand * result, int offr, int sign)
8299 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8301 l = aopGet (left, offl, FALSE, FALSE);
8303 if (*l == '@' && (IS_AOP_PREG (result)))
8305 emitcode ("mov", "a,%s", l);
8306 aopPut (result, "a", offr);
8312 aopPut (result, l, offr);
8316 /* MSB sign in acc.7 ! */
8317 if (getDataSize (left) == offl + 1)
8320 aopPut (result, "a", offr);
8327 /*-----------------------------------------------------------------*/
8328 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
8329 /*-----------------------------------------------------------------*/
8333 emitcode ("rrc", "a");
8334 emitcode ("xch", "a,%s", x);
8335 emitcode ("rrc", "a");
8336 emitcode ("xch", "a,%s", x);
8339 /*-----------------------------------------------------------------*/
8340 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
8341 /*-----------------------------------------------------------------*/
8345 emitcode ("xch", "a,%s", x);
8346 emitcode ("rlc", "a");
8347 emitcode ("xch", "a,%s", x);
8348 emitcode ("rlc", "a");
8351 /*-----------------------------------------------------------------*/
8352 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8353 /*-----------------------------------------------------------------*/
8357 emitcode ("xch", "a,%s", x);
8358 emitcode ("add", "a,acc");
8359 emitcode ("xch", "a,%s", x);
8360 emitcode ("rlc", "a");
8363 /*-----------------------------------------------------------------*/
8364 /* AccAXLsh - left shift a:x by known count (0..7) */
8365 /*-----------------------------------------------------------------*/
8367 AccAXLsh (char *x, int shCount)
8382 case 5: // AAAAABBB:CCCCCDDD
8384 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8386 emitcode ("anl", "a,#0x%02x",
8387 SLMask[shCount]); // BBB00000:CCCCCDDD
8389 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8391 AccRol (shCount); // DDDCCCCC:BBB00000
8393 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8395 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8397 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8399 emitcode ("anl", "a,#0x%02x",
8400 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8402 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8404 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8407 case 6: // AAAAAABB:CCCCCCDD
8408 emitcode ("anl", "a,#0x%02x",
8409 SRMask[shCount]); // 000000BB:CCCCCCDD
8410 emitcode ("mov", "c,acc.0"); // c = B
8411 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8413 AccAXRrl1 (x); // BCCCCCCD:D000000B
8414 AccAXRrl1 (x); // BBCCCCCC:DD000000
8416 emitcode("rrc","a");
8417 emitcode("xch","a,%s", x);
8418 emitcode("rrc","a");
8419 emitcode("mov","c,acc.0"); //<< get correct bit
8420 emitcode("xch","a,%s", x);
8422 emitcode("rrc","a");
8423 emitcode("xch","a,%s", x);
8424 emitcode("rrc","a");
8425 emitcode("xch","a,%s", x);
8428 case 7: // a:x <<= 7
8430 emitcode ("anl", "a,#0x%02x",
8431 SRMask[shCount]); // 0000000B:CCCCCCCD
8433 emitcode ("mov", "c,acc.0"); // c = B
8435 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
8437 AccAXRrl1 (x); // BCCCCCCC:D0000000
8445 /*-----------------------------------------------------------------*/
8446 /* AccAXRsh - right shift a:x known count (0..7) */
8447 /*-----------------------------------------------------------------*/
8449 AccAXRsh (char *x, int shCount)
8457 AccAXRrl1 (x); // 0->a:x
8462 AccAXRrl1 (x); // 0->a:x
8465 AccAXRrl1 (x); // 0->a:x
8470 case 5: // AAAAABBB:CCCCCDDD = a:x
8472 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8474 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8476 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8478 emitcode ("anl", "a,#0x%02x",
8479 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8481 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8483 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8485 emitcode ("anl", "a,#0x%02x",
8486 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8488 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8490 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8492 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8495 case 6: // AABBBBBB:CCDDDDDD
8497 emitcode ("mov", "c,acc.7");
8498 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8500 emitcode ("mov", "c,acc.7");
8501 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8503 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8505 emitcode ("anl", "a,#0x%02x",
8506 SRMask[shCount]); // 000000AA:BBBBBBCC
8509 case 7: // ABBBBBBB:CDDDDDDD
8511 emitcode ("mov", "c,acc.7"); // c = A
8513 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8515 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8517 emitcode ("anl", "a,#0x%02x",
8518 SRMask[shCount]); // 0000000A:BBBBBBBC
8526 /*-----------------------------------------------------------------*/
8527 /* AccAXRshS - right shift signed a:x known count (0..7) */
8528 /*-----------------------------------------------------------------*/
8530 AccAXRshS (char *x, int shCount)
8538 emitcode ("mov", "c,acc.7");
8539 AccAXRrl1 (x); // s->a:x
8543 emitcode ("mov", "c,acc.7");
8544 AccAXRrl1 (x); // s->a:x
8546 emitcode ("mov", "c,acc.7");
8547 AccAXRrl1 (x); // s->a:x
8552 case 5: // AAAAABBB:CCCCCDDD = a:x
8554 tlbl = newiTempLabel (NULL);
8555 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8557 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8559 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8561 emitcode ("anl", "a,#0x%02x",
8562 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8564 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8566 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8568 emitcode ("anl", "a,#0x%02x",
8569 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8571 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8573 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8575 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8577 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8578 emitcode ("orl", "a,#0x%02x",
8579 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8582 break; // SSSSAAAA:BBBCCCCC
8584 case 6: // AABBBBBB:CCDDDDDD
8586 tlbl = newiTempLabel (NULL);
8587 emitcode ("mov", "c,acc.7");
8588 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8590 emitcode ("mov", "c,acc.7");
8591 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8593 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8595 emitcode ("anl", "a,#0x%02x",
8596 SRMask[shCount]); // 000000AA:BBBBBBCC
8598 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8599 emitcode ("orl", "a,#0x%02x",
8600 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8604 case 7: // ABBBBBBB:CDDDDDDD
8606 tlbl = newiTempLabel (NULL);
8607 emitcode ("mov", "c,acc.7"); // c = A
8609 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8611 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8613 emitcode ("anl", "a,#0x%02x",
8614 SRMask[shCount]); // 0000000A:BBBBBBBC
8616 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8617 emitcode ("orl", "a,#0x%02x",
8618 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8627 /*-----------------------------------------------------------------*/
8628 /* shiftL2Left2Result - shift left two bytes from left to result */
8629 /*-----------------------------------------------------------------*/
8631 shiftL2Left2Result (operand * left, int offl,
8632 operand * result, int offr, int shCount)
8635 bool pushedB = FALSE;
8638 if (sameRegs (AOP (result), AOP (left)) &&
8639 ((offl + MSB16) == offr))
8641 /* don't crash result[offr] */
8642 MOVA (aopGet (left, offl, FALSE, FALSE));
8643 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8644 usedB = !strncmp(x, "b", 1);
8646 else if (aopGetUsesAcc (result, offr))
8648 movLeft2Result (left, offl, result, offr, 0);
8651 emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8652 MOVA (aopGet (result, offr, FALSE, FALSE));
8653 emitcode ("xch", "a,b");
8658 movLeft2Result (left, offl, result, offr, 0);
8659 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8660 x = aopGet (result, offr, FALSE, FALSE);
8662 /* ax << shCount (x = lsb(result)) */
8663 AccAXLsh (x, shCount);
8666 emitcode ("xch", "a,b");
8667 aopPut (result, "a", offr);
8668 aopPut (result, "b", offr + MSB16);
8673 aopPut (result, "a", offr + MSB16);
8678 /*-----------------------------------------------------------------*/
8679 /* shiftR2Left2Result - shift right two bytes from left to result */
8680 /*-----------------------------------------------------------------*/
8682 shiftR2Left2Result (operand * left, int offl,
8683 operand * result, int offr,
8684 int shCount, int sign)
8687 bool pushedB = FALSE;
8690 if (sameRegs (AOP (result), AOP (left)) &&
8691 ((offl + MSB16) == offr))
8693 /* don't crash result[offr] */
8694 MOVA (aopGet (left, offl, FALSE, FALSE));
8695 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8696 usedB = !strncmp(x, "b", 1);
8698 else if (aopGetUsesAcc (result, offr))
8700 movLeft2Result (left, offl, result, offr, 0);
8703 emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8704 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8709 movLeft2Result (left, offl, result, offr, 0);
8710 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8711 x = aopGet (result, offr, FALSE, FALSE);
8713 /* a:x >> shCount (x = lsb(result)) */
8715 AccAXRshS (x, shCount);
8717 AccAXRsh (x, shCount);
8720 emitcode ("xch", "a,b");
8721 aopPut (result, "a", offr);
8722 emitcode ("xch", "a,b");
8725 if (getDataSize (result) > 1)
8726 aopPut (result, "a", offr + MSB16);
8729 /*-----------------------------------------------------------------*/
8730 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8731 /*-----------------------------------------------------------------*/
8733 shiftLLeftOrResult (operand * left, int offl,
8734 operand * result, int offr, int shCount)
8736 MOVA (aopGet (left, offl, FALSE, FALSE));
8737 /* shift left accumulator */
8739 /* or with result */
8740 if (aopGetUsesAcc (result, offr))
8742 emitcode ("xch", "a,b");
8743 MOVA (aopGet (result, offr, FALSE, FALSE));
8744 emitcode ("orl", "a,b");
8748 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8750 /* back to result */
8751 aopPut (result, "a", offr);
8754 /*-----------------------------------------------------------------*/
8755 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8756 /*-----------------------------------------------------------------*/
8758 shiftRLeftOrResult (operand * left, int offl,
8759 operand * result, int offr, int shCount)
8761 MOVA (aopGet (left, offl, FALSE, FALSE));
8762 /* shift right accumulator */
8764 /* or with result */
8765 if (aopGetUsesAcc(result, offr))
8767 emitcode ("xch", "a,b");
8768 MOVA (aopGet (result, offr, FALSE, FALSE));
8769 emitcode ("orl", "a,b");
8773 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8775 /* back to result */
8776 aopPut (result, "a", offr);
8779 /*-----------------------------------------------------------------*/
8780 /* genlshOne - left shift a one byte quantity by known count */
8781 /*-----------------------------------------------------------------*/
8783 genlshOne (operand * result, operand * left, int shCount)
8785 D (emitcode (";", "genlshOne"));
8787 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8790 /*-----------------------------------------------------------------*/
8791 /* genlshTwo - left shift two bytes by known amount != 0 */
8792 /*-----------------------------------------------------------------*/
8794 genlshTwo (operand * result, operand * left, int shCount)
8798 D (emitcode (";", "genlshTwo"));
8800 size = getDataSize (result);
8802 /* if shCount >= 8 */
8810 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8812 movLeft2Result (left, LSB, result, MSB16, 0);
8814 aopPut (result, zero, LSB);
8817 /* 1 <= shCount <= 7 */
8821 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8823 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8827 /*-----------------------------------------------------------------*/
8828 /* shiftLLong - shift left one long from left to result */
8829 /* offl = LSB or MSB16 */
8830 /*-----------------------------------------------------------------*/
8832 shiftLLong (operand * left, operand * result, int offr)
8835 int size = AOP_SIZE (result);
8837 if (size >= LSB + offr)
8839 l = aopGet (left, LSB, FALSE, FALSE);
8841 emitcode ("add", "a,acc");
8842 if (sameRegs (AOP (left), AOP (result)) &&
8843 size >= MSB16 + offr && offr != LSB)
8844 xch_a_aopGet (left, LSB + offr, FALSE, FALSE);
8846 aopPut (result, "a", LSB + offr);
8849 if (size >= MSB16 + offr)
8851 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8853 l = aopGet (left, MSB16, FALSE, FALSE);
8856 emitcode ("rlc", "a");
8857 if (sameRegs (AOP (left), AOP (result)) &&
8858 size >= MSB24 + offr && offr != LSB)
8859 xch_a_aopGet (left, MSB16 + offr, FALSE, FALSE);
8861 aopPut (result, "a", MSB16 + offr);
8864 if (size >= MSB24 + offr)
8866 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8868 l = aopGet (left, MSB24, FALSE, FALSE);
8871 emitcode ("rlc", "a");
8872 if (sameRegs (AOP (left), AOP (result)) &&
8873 size >= MSB32 + offr && offr != LSB)
8874 xch_a_aopGet (left, MSB24 + offr, FALSE, FALSE);
8876 aopPut (result, "a", MSB24 + offr);
8879 if (size > MSB32 + offr)
8881 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8883 l = aopGet (left, MSB32, FALSE, FALSE);
8886 emitcode ("rlc", "a");
8887 aopPut (result, "a", MSB32 + offr);
8890 aopPut (result, zero, LSB);
8893 /*-----------------------------------------------------------------*/
8894 /* genlshFour - shift four byte by a known amount != 0 */
8895 /*-----------------------------------------------------------------*/
8897 genlshFour (operand * result, operand * left, int shCount)
8901 D (emitcode (";", "genlshFour"));
8903 size = AOP_SIZE (result);
8905 /* if shifting more that 3 bytes */
8910 /* lowest order of left goes to the highest
8911 order of the destination */
8912 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8914 movLeft2Result (left, LSB, result, MSB32, 0);
8915 aopPut (result, zero, LSB);
8916 aopPut (result, zero, MSB16);
8917 aopPut (result, zero, MSB24);
8921 /* more than two bytes */
8922 else if (shCount >= 16)
8924 /* lower order two bytes goes to higher order two bytes */
8926 /* if some more remaining */
8928 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8931 movLeft2Result (left, MSB16, result, MSB32, 0);
8932 movLeft2Result (left, LSB, result, MSB24, 0);
8934 aopPut (result, zero, MSB16);
8935 aopPut (result, zero, LSB);
8939 /* if more than 1 byte */
8940 else if (shCount >= 8)
8942 /* lower order three bytes goes to higher order three bytes */
8947 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8949 movLeft2Result (left, LSB, result, MSB16, 0);
8955 movLeft2Result (left, MSB24, result, MSB32, 0);
8956 movLeft2Result (left, MSB16, result, MSB24, 0);
8957 movLeft2Result (left, LSB, result, MSB16, 0);
8958 aopPut (result, zero, LSB);
8960 else if (shCount == 1)
8961 shiftLLong (left, result, MSB16);
8964 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8965 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8966 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8967 aopPut (result, zero, LSB);
8972 /* 1 <= shCount <= 7 */
8973 else if (shCount <= 2)
8975 shiftLLong (left, result, LSB);
8977 shiftLLong (result, result, LSB);
8979 /* 3 <= shCount <= 7, optimize */
8982 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8983 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8984 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8988 /*-----------------------------------------------------------------*/
8989 /* genLeftShiftLiteral - left shifting by known count */
8990 /*-----------------------------------------------------------------*/
8992 genLeftShiftLiteral (operand * left,
8997 int shCount = (int) ulFromVal (AOP (right)->aopu.aop_lit);
9000 D (emitcode (";", "genLeftShiftLiteral"));
9002 freeAsmop (right, NULL, ic, TRUE);
9004 aopOp (left, ic, FALSE);
9005 aopOp (result, ic, FALSE);
9007 size = getSize (operandType (result));
9010 emitcode ("; shift left ", "result %d, left %d", size,
9014 /* I suppose that the left size >= result size */
9019 movLeft2Result (left, size, result, size, 0);
9022 else if (shCount >= (size * 8))
9026 aopPut (result, zero, size);
9034 genlshOne (result, left, shCount);
9038 genlshTwo (result, left, shCount);
9042 genlshFour (result, left, shCount);
9045 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9046 "*** ack! mystery literal shift!\n");
9050 freeAsmop (result, NULL, ic, TRUE);
9051 freeAsmop (left, NULL, ic, TRUE);
9054 /*-----------------------------------------------------------------*/
9055 /* genLeftShift - generates code for left shifting */
9056 /*-----------------------------------------------------------------*/
9058 genLeftShift (iCode * ic)
9060 operand *left, *right, *result;
9063 symbol *tlbl, *tlbl1;
9066 D (emitcode (";", "genLeftShift"));
9068 right = IC_RIGHT (ic);
9069 left = IC_LEFT (ic);
9070 result = IC_RESULT (ic);
9072 aopOp (right, ic, FALSE);
9074 /* if the shift count is known then do it
9075 as efficiently as possible */
9076 if (AOP_TYPE (right) == AOP_LIT)
9078 genLeftShiftLiteral (left, right, result, ic);
9082 /* shift count is unknown then we have to form
9083 a loop get the loop count in B : Note: we take
9084 only the lower order byte since shifting
9085 more that 32 bits make no sense anyway, ( the
9086 largest size of an object can be only 32 bits ) */
9089 MOVB (aopGet (right, 0, FALSE, FALSE));
9090 emitcode ("inc", "b");
9091 freeAsmop (right, NULL, ic, TRUE);
9092 aopOp (left, ic, FALSE);
9093 aopOp (result, ic, FALSE);
9095 /* now move the left to the result if they are not the same */
9096 if (!sameRegs (AOP (left), AOP (result)) &&
9097 AOP_SIZE (result) > 1)
9100 size = AOP_SIZE (result);
9104 l = aopGet (left, offset, FALSE, TRUE);
9105 if (*l == '@' && (IS_AOP_PREG (result)))
9108 emitcode ("mov", "a,%s", l);
9109 aopPut (result, "a", offset);
9112 aopPut (result, l, offset);
9117 tlbl = newiTempLabel (NULL);
9118 size = AOP_SIZE (result);
9120 tlbl1 = newiTempLabel (NULL);
9122 /* if it is only one byte then */
9125 symbol *tlbl1 = newiTempLabel (NULL);
9127 l = aopGet (left, 0, FALSE, FALSE);
9129 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9131 emitcode ("add", "a,acc");
9133 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9135 aopPut (result, "a", 0);
9139 reAdjustPreg (AOP (result));
9141 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9143 l = aopGet (result, offset, FALSE, FALSE);
9145 emitcode ("add", "a,acc");
9146 aopPut (result, "a", offset++);
9149 l = aopGet (result, offset, FALSE, FALSE);
9151 emitcode ("rlc", "a");
9152 aopPut (result, "a", offset++);
9154 reAdjustPreg (AOP (result));
9157 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9160 freeAsmop (result, NULL, ic, TRUE);
9161 freeAsmop (left, NULL, ic, TRUE);
9164 /*-----------------------------------------------------------------*/
9165 /* genrshOne - right shift a one byte quantity by known count */
9166 /*-----------------------------------------------------------------*/
9168 genrshOne (operand * result, operand * left,
9169 int shCount, int sign)
9171 D (emitcode (";", "genrshOne"));
9173 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9176 /*-----------------------------------------------------------------*/
9177 /* genrshTwo - right shift two bytes by known amount != 0 */
9178 /*-----------------------------------------------------------------*/
9180 genrshTwo (operand * result, operand * left,
9181 int shCount, int sign)
9183 D (emitcode (";", "genrshTwo"));
9185 /* if shCount >= 8 */
9190 shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
9192 movLeft2Result (left, MSB16, result, LSB, sign);
9193 addSign (result, MSB16, sign);
9196 /* 1 <= shCount <= 7 */
9198 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9201 /*-----------------------------------------------------------------*/
9202 /* shiftRLong - shift right one long from left to result */
9203 /* offl = LSB or MSB16 */
9204 /*-----------------------------------------------------------------*/
9206 shiftRLong (operand * left, int offl,
9207 operand * result, int sign)
9209 bool overlapping = regsInCommon (left, result) || operandsEqu(left, result);
9211 if (overlapping && offl>1)
9213 // we are in big trouble, but this shouldn't happen
9214 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9217 MOVA (aopGet (left, MSB32, FALSE, FALSE));
9224 emitcode ("rlc", "a");
9225 emitcode ("subb", "a,acc");
9226 if (overlapping && sameByte (AOP (left), MSB32, AOP (result), MSB32))
9228 xch_a_aopGet (left, MSB32, FALSE, FALSE);
9232 aopPut (result, "a", MSB32);
9233 MOVA (aopGet (left, MSB32, FALSE, FALSE));
9238 if (aopPutUsesAcc (result, zero, MSB32))
9240 emitcode("xch", "a,b");
9241 aopPut (result, zero, MSB32);
9242 emitcode("xch", "a,b");
9246 aopPut (result, zero, MSB32);
9253 emitcode ("clr", "c");
9257 emitcode ("mov", "c,acc.7");
9260 emitcode ("rrc", "a");
9262 if (overlapping && offl==MSB16 &&
9263 sameByte (AOP (left), MSB24, AOP (result), MSB32-offl))
9265 xch_a_aopGet (left, MSB24, FALSE, FALSE);
9269 aopPut (result, "a", MSB32 - offl);
9270 MOVA (aopGet (left, MSB24, FALSE, FALSE));
9273 emitcode ("rrc", "a");
9274 if (overlapping && offl==MSB16 &&
9275 sameByte (AOP (left), MSB16, AOP (result), MSB24-offl))
9277 xch_a_aopGet (left, MSB16, FALSE, FALSE);
9281 aopPut (result, "a", MSB24 - offl);
9282 MOVA (aopGet (left, MSB16, FALSE, FALSE));
9285 emitcode ("rrc", "a");
9288 aopPut (result, "a", MSB16 - offl);
9293 sameByte (AOP (left), LSB, AOP (result), MSB16-offl))
9295 xch_a_aopGet (left, LSB, FALSE, FALSE);
9299 aopPut (result, "a", MSB16 - offl);
9300 MOVA (aopGet (left, LSB, FALSE, FALSE));
9302 emitcode ("rrc", "a");
9303 aopPut (result, "a", LSB);
9307 /*-----------------------------------------------------------------*/
9308 /* genrshFour - shift four byte by a known amount != 0 */
9309 /*-----------------------------------------------------------------*/
9311 genrshFour (operand * result, operand * left,
9312 int shCount, int sign)
9314 D (emitcode (";", "genrshFour"));
9316 /* if shifting more that 3 bytes */
9321 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9323 movLeft2Result (left, MSB32, result, LSB, sign);
9324 addSign (result, MSB16, sign);
9326 else if (shCount >= 16)
9330 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9333 movLeft2Result (left, MSB24, result, LSB, 0);
9334 movLeft2Result (left, MSB32, result, MSB16, sign);
9336 addSign (result, MSB24, sign);
9338 else if (shCount >= 8)
9343 shiftRLong (left, MSB16, result, sign);
9345 else if (shCount == 0)
9347 movLeft2Result (left, MSB16, result, LSB, 0);
9348 movLeft2Result (left, MSB24, result, MSB16, 0);
9349 movLeft2Result (left, MSB32, result, MSB24, sign);
9350 addSign (result, MSB32, sign);
9354 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9355 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9356 /* the last shift is signed */
9357 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9358 addSign (result, MSB32, sign);
9363 /* 1 <= shCount <= 7 */
9366 shiftRLong (left, LSB, result, sign);
9368 shiftRLong (result, LSB, result, sign);
9372 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9373 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9374 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9379 /*-----------------------------------------------------------------*/
9380 /* genRightShiftLiteral - right shifting by known count */
9381 /*-----------------------------------------------------------------*/
9383 genRightShiftLiteral (operand * left,
9389 int shCount = (int) ulFromVal (AOP (right)->aopu.aop_lit);
9392 D (emitcode (";", "genRightShiftLiteral"));
9394 freeAsmop (right, NULL, ic, TRUE);
9396 aopOp (left, ic, FALSE);
9397 aopOp (result, ic, FALSE);
9400 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9404 size = getDataSize (left);
9405 /* test the LEFT size !!! */
9407 /* I suppose that the left size >= result size */
9410 size = getDataSize (result);
9412 movLeft2Result (left, size, result, size, 0);
9415 else if (shCount >= (size * 8))
9419 /* get sign in acc.7 */
9420 MOVA (aopGet (left, size - 1, FALSE, FALSE));
9422 addSign (result, LSB, sign);
9429 genrshOne (result, left, shCount, sign);
9433 genrshTwo (result, left, shCount, sign);
9437 genrshFour (result, left, shCount, sign);
9443 freeAsmop (result, NULL, ic, TRUE);
9444 freeAsmop (left, NULL, ic, TRUE);
9447 /*-----------------------------------------------------------------*/
9448 /* genSignedRightShift - right shift of signed number */
9449 /*-----------------------------------------------------------------*/
9451 genSignedRightShift (iCode * ic)
9453 operand *right, *left, *result;
9456 symbol *tlbl, *tlbl1;
9459 D (emitcode (";", "genSignedRightShift"));
9461 /* we do it the hard way put the shift count in b
9462 and loop thru preserving the sign */
9464 right = IC_RIGHT (ic);
9465 left = IC_LEFT (ic);
9466 result = IC_RESULT (ic);
9468 aopOp (right, ic, FALSE);
9471 if (AOP_TYPE (right) == AOP_LIT)
9473 genRightShiftLiteral (left, right, result, ic, 1);
9476 /* shift count is unknown then we have to form
9477 a loop get the loop count in B : Note: we take
9478 only the lower order byte since shifting
9479 more that 32 bits make no sense anyway, ( the
9480 largest size of an object can be only 32 bits ) */
9483 MOVB (aopGet (right, 0, FALSE, FALSE));
9484 emitcode ("inc", "b");
9485 freeAsmop (right, NULL, ic, TRUE);
9486 aopOp (left, ic, FALSE);
9487 aopOp (result, ic, FALSE);
9489 /* now move the left to the result if they are not the
9491 if (!sameRegs (AOP (left), AOP (result)) &&
9492 AOP_SIZE (result) > 1)
9495 size = AOP_SIZE (result);
9499 l = aopGet (left, offset, FALSE, TRUE);
9500 if (*l == '@' && IS_AOP_PREG (result))
9503 emitcode ("mov", "a,%s", l);
9504 aopPut (result, "a", offset);
9507 aopPut (result, l, offset);
9512 /* mov the highest order bit to OVR */
9513 tlbl = newiTempLabel (NULL);
9514 tlbl1 = newiTempLabel (NULL);
9516 size = AOP_SIZE (result);
9518 MOVA (aopGet (left, offset, FALSE, FALSE));
9519 emitcode ("rlc", "a");
9520 emitcode ("mov", "ov,c");
9521 /* if it is only one byte then */
9524 l = aopGet (left, 0, FALSE, FALSE);
9526 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9528 emitcode ("mov", "c,ov");
9529 emitcode ("rrc", "a");
9531 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9533 aopPut (result, "a", 0);
9537 reAdjustPreg (AOP (result));
9538 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9540 emitcode ("mov", "c,ov");
9543 l = aopGet (result, offset, FALSE, FALSE);
9545 emitcode ("rrc", "a");
9546 aopPut (result, "a", offset--);
9548 reAdjustPreg (AOP (result));
9550 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9554 freeAsmop (result, NULL, ic, TRUE);
9555 freeAsmop (left, NULL, ic, TRUE);
9558 /*-----------------------------------------------------------------*/
9559 /* genRightShift - generate code for right shifting */
9560 /*-----------------------------------------------------------------*/
9562 genRightShift (iCode * ic)
9564 operand *right, *left, *result;
9568 symbol *tlbl, *tlbl1;
9571 D (emitcode (";", "genRightShift"));
9573 /* if signed then we do it the hard way preserve the
9574 sign bit moving it inwards */
9575 letype = getSpec (operandType (IC_LEFT (ic)));
9577 if (!SPEC_USIGN (letype))
9579 genSignedRightShift (ic);
9583 /* signed & unsigned types are treated the same : i.e. the
9584 signed is NOT propagated inwards : quoting from the
9585 ANSI - standard : "for E1 >> E2, is equivalent to division
9586 by 2**E2 if unsigned or if it has a non-negative value,
9587 otherwise the result is implementation defined ", MY definition
9588 is that the sign does not get propagated */
9590 right = IC_RIGHT (ic);
9591 left = IC_LEFT (ic);
9592 result = IC_RESULT (ic);
9594 aopOp (right, ic, FALSE);
9596 /* if the shift count is known then do it
9597 as efficiently as possible */
9598 if (AOP_TYPE (right) == AOP_LIT)
9600 genRightShiftLiteral (left, right, result, ic, 0);
9604 /* shift count is unknown then we have to form
9605 a loop get the loop count in B : Note: we take
9606 only the lower order byte since shifting
9607 more that 32 bits make no sense anyway, ( the
9608 largest size of an object can be only 32 bits ) */
9611 MOVB (aopGet (right, 0, FALSE, FALSE));
9612 emitcode ("inc", "b");
9613 freeAsmop (right, NULL, ic, TRUE);
9614 aopOp (left, ic, FALSE);
9615 aopOp (result, ic, FALSE);
9617 /* now move the left to the result if they are not the
9619 if (!sameRegs (AOP (left), AOP (result)) &&
9620 AOP_SIZE (result) > 1)
9622 size = AOP_SIZE (result);
9626 l = aopGet (left, offset, FALSE, TRUE);
9627 if (*l == '@' && IS_AOP_PREG (result))
9630 emitcode ("mov", "a,%s", l);
9631 aopPut (result, "a", offset);
9634 aopPut (result, l, offset);
9639 tlbl = newiTempLabel (NULL);
9640 tlbl1 = newiTempLabel (NULL);
9641 size = AOP_SIZE (result);
9644 /* if it is only one byte then */
9647 l = aopGet (left, 0, FALSE, FALSE);
9649 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9652 emitcode ("rrc", "a");
9654 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9656 aopPut (result, "a", 0);
9660 reAdjustPreg (AOP (result));
9661 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9666 l = aopGet (result, offset, FALSE, FALSE);
9668 emitcode ("rrc", "a");
9669 aopPut (result, "a", offset--);
9671 reAdjustPreg (AOP (result));
9674 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9678 freeAsmop (result, NULL, ic, TRUE);
9679 freeAsmop (left, NULL, ic, TRUE);
9682 /*-----------------------------------------------------------------*/
9683 /* emitPtrByteGet - emits code to get a byte into A through a */
9684 /* pointer register (R0, R1, or DPTR). The */
9685 /* original value of A can be preserved in B. */
9686 /*-----------------------------------------------------------------*/
9688 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9695 emitcode ("mov", "b,a");
9696 emitcode ("mov", "a,@%s", rname);
9701 emitcode ("mov", "b,a");
9702 emitcode ("movx", "a,@%s", rname);
9707 emitcode ("mov", "b,a");
9708 emitcode ("movx", "a,@dptr");
9713 emitcode ("mov", "b,a");
9714 emitcode ("clr", "a");
9715 emitcode ("movc", "a,@a+dptr");
9721 emitcode ("push", "b");
9722 emitcode ("push", "acc");
9724 emitcode ("lcall", "__gptrget");
9726 emitcode ("pop", "b");
9731 /*-----------------------------------------------------------------*/
9732 /* emitPtrByteSet - emits code to set a byte from src through a */
9733 /* pointer register (R0, R1, or DPTR). */
9734 /*-----------------------------------------------------------------*/
9736 emitPtrByteSet (char *rname, int p_type, char *src)
9745 emitcode ("mov", "@%s,a", rname);
9748 emitcode ("mov", "@%s,%s", rname, src);
9753 emitcode ("movx", "@%s,a", rname);
9758 emitcode ("movx", "@dptr,a");
9763 emitcode ("lcall", "__gptrput");
9768 /*-----------------------------------------------------------------*/
9769 /* genUnpackBits - generates code for unpacking bits */
9770 /*-----------------------------------------------------------------*/
9772 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9774 int offset = 0; /* result byte offset */
9775 int rsize; /* result size */
9776 int rlen = 0; /* remaining bitfield length */
9777 sym_link *etype; /* bitfield type information */
9778 int blen; /* bitfield length */
9779 int bstr; /* bitfield starting bit within byte */
9780 static char* const accBits[] = {"acc.0", "acc.1", "acc.2", "acc.3",
9781 "acc.4", "acc.5", "acc.6", "acc.7"};
9783 D(emitcode (";", "genUnpackBits"));
9785 etype = getSpec (operandType (result));
9786 rsize = getSize (operandType (result));
9787 blen = SPEC_BLEN (etype);
9788 bstr = SPEC_BSTR (etype);
9790 if (ifx && blen <= 8)
9792 emitPtrByteGet (rname, ptype, FALSE);
9795 return accBits[bstr];;
9800 emitcode ("anl", "a,#0x%02x",
9801 (((unsigned char) -1) >> (8 - blen)) << bstr);
9807 /* If the bitfield length is less than a byte */
9810 emitPtrByteGet (rname, ptype, FALSE);
9812 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9813 if (!SPEC_USIGN (etype))
9815 /* signed bitfield */
9816 symbol *tlbl = newiTempLabel (NULL);
9818 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9819 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9822 aopPut (result, "a", offset++);
9826 /* Bit field did not fit in a byte. Copy all
9827 but the partial byte at the end. */
9828 for (rlen=blen;rlen>=8;rlen-=8)
9830 emitPtrByteGet (rname, ptype, FALSE);
9831 aopPut (result, "a", offset++);
9833 emitcode ("inc", "%s", rname);
9836 /* Handle the partial byte at the end */
9839 emitPtrByteGet (rname, ptype, FALSE);
9840 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9841 if (!SPEC_USIGN (etype))
9843 /* signed bitfield */
9844 symbol *tlbl = newiTempLabel (NULL);
9846 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9847 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9850 aopPut (result, "a", offset++);
9858 if (SPEC_USIGN (etype))
9862 /* signed bitfield: sign extension with 0x00 or 0xff */
9863 emitcode ("rlc", "a");
9864 emitcode ("subb", "a,acc");
9870 aopPut (result, source, offset++);
9876 /*-----------------------------------------------------------------*/
9877 /* genDataPointerGet - generates code when ptr offset is known */
9878 /*-----------------------------------------------------------------*/
9880 genDataPointerGet (operand * left,
9886 int size, offset = 0;
9888 D (emitcode (";", "genDataPointerGet"));
9890 aopOp (result, ic, TRUE);
9892 /* get the string representation of the name */
9893 l = aopGet (left, 0, FALSE, TRUE);
9895 size = AOP_SIZE (result);
9900 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
9904 SNPRINTF (buffer, sizeof(buffer), "%s", l);
9906 aopPut (result, buffer, offset++);
9909 freeAsmop (result, NULL, ic, TRUE);
9910 freeAsmop (left, NULL, ic, TRUE);
9913 /*-----------------------------------------------------------------*/
9914 /* genNearPointerGet - emitcode for near pointer fetch */
9915 /*-----------------------------------------------------------------*/
9917 genNearPointerGet (operand * left,
9926 char *ifxCond = "a";
9927 sym_link *rtype, *retype;
9928 sym_link *ltype = operandType (left);
9930 D (emitcode (";", "genNearPointerGet"));
9932 rtype = operandType (result);
9933 retype = getSpec (rtype);
9935 aopOp (left, ic, FALSE);
9937 /* if left is rematerialisable and
9938 result is not bitfield variable type and
9939 the left is pointer to data space i.e
9940 lower 128 bytes of space */
9941 if (AOP_TYPE (left) == AOP_IMMD &&
9942 !IS_BITFIELD (retype) &&
9943 DCL_TYPE (ltype) == POINTER)
9945 genDataPointerGet (left, result, ic);
9949 //aopOp (result, ic, FALSE);
9950 aopOp (result, ic, result?TRUE:FALSE);
9952 /* if the value is already in a pointer register
9953 then don't need anything more */
9954 if (!AOP_INPREG (AOP (left)))
9956 if (IS_AOP_PREG (left))
9958 // Aha, it is a pointer, just in disguise.
9959 rname = aopGet (left, 0, FALSE, FALSE);
9962 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9963 __FILE__, __LINE__);
9968 emitcode ("mov", "a%s,%s", rname + 1, rname);
9969 rname++; // skip the '@'.
9974 /* otherwise get a free pointer register */
9976 preg = getFreePtr (ic, &aop, FALSE);
9977 emitcode ("mov", "%s,%s",
9979 aopGet (left, 0, FALSE, TRUE));
9984 rname = aopGet (left, 0, FALSE, FALSE);
9986 /* if bitfield then unpack the bits */
9987 if (IS_BITFIELD (retype))
9988 ifxCond = genUnpackBits (result, rname, POINTER, ifx);
9991 /* we have can just get the values */
9992 int size = AOP_SIZE (result);
9997 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
10000 emitcode ("mov", "a,@%s", rname);
10002 aopPut (result, "a", offset);
10008 SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
10009 aopPut (result, buffer, offset);
10013 emitcode ("inc", "%s", rname);
10017 /* now some housekeeping stuff */
10018 if (aop) /* we had to allocate for this iCode */
10020 if (pi) { /* post increment present */
10021 aopPut (left, rname, 0);
10023 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
10027 /* we did not allocate which means left
10028 already in a pointer register, then
10029 if size > 0 && this could be used again
10030 we have to point it back to where it
10032 if ((AOP_SIZE (result) > 1 &&
10033 !OP_SYMBOL (left)->remat &&
10034 (OP_SYMBOL (left)->liveTo > ic->seq ||
10038 int size = AOP_SIZE (result) - 1;
10040 emitcode ("dec", "%s", rname);
10044 if (ifx && !ifx->generated)
10046 genIfxJump (ifx, ifxCond, left, NULL, result);
10050 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
10051 freeAsmop (left, NULL, ic, TRUE);
10052 if (pi) pi->generated = 1;
10055 /*-----------------------------------------------------------------*/
10056 /* genPagedPointerGet - emitcode for paged pointer fetch */
10057 /*-----------------------------------------------------------------*/
10059 genPagedPointerGet (operand * left,
10068 char *ifxCond = "a";
10069 sym_link *rtype, *retype;
10071 D (emitcode (";", "genPagedPointerGet"));
10073 rtype = operandType (result);
10074 retype = getSpec (rtype);
10076 aopOp (left, ic, FALSE);
10078 aopOp (result, ic, FALSE);
10080 /* if the value is already in a pointer register
10081 then don't need anything more */
10082 if (!AOP_INPREG (AOP (left)))
10084 /* otherwise get a free pointer register */
10085 aop = newAsmop (0);
10086 preg = getFreePtr (ic, &aop, FALSE);
10087 emitcode ("mov", "%s,%s",
10089 aopGet (left, 0, FALSE, TRUE));
10090 rname = preg->name;
10093 rname = aopGet (left, 0, FALSE, FALSE);
10095 /* if bitfield then unpack the bits */
10096 if (IS_BITFIELD (retype))
10097 ifxCond = genUnpackBits (result, rname, PPOINTER, ifx);
10100 /* we have can just get the values */
10101 int size = AOP_SIZE (result);
10107 emitcode ("movx", "a,@%s", rname);
10109 aopPut (result, "a", offset);
10114 emitcode ("inc", "%s", rname);
10118 /* now some housekeeping stuff */
10119 if (aop) /* we had to allocate for this iCode */
10122 aopPut (left, rname, 0);
10123 freeAsmop (NULL, aop, ic, TRUE);
10127 /* we did not allocate which means left
10128 already in a pointer register, then
10129 if size > 0 && this could be used again
10130 we have to point it back to where it
10132 if ((AOP_SIZE (result) > 1 &&
10133 !OP_SYMBOL (left)->remat &&
10134 (OP_SYMBOL (left)->liveTo > ic->seq ||
10138 int size = AOP_SIZE (result) - 1;
10140 emitcode ("dec", "%s", rname);
10144 if (ifx && !ifx->generated)
10146 genIfxJump (ifx, ifxCond, left, NULL, result);
10150 freeAsmop (result, NULL, ic, TRUE);
10151 freeAsmop (left, NULL, ic, TRUE);
10152 if (pi) pi->generated = 1;
10155 /*--------------------------------------------------------------------*/
10156 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
10157 /*--------------------------------------------------------------------*/
10159 loadDptrFromOperand (operand *op, bool loadBToo)
10161 if (AOP_TYPE (op) != AOP_STR)
10163 /* if this is rematerializable */
10164 if (AOP_TYPE (op) == AOP_IMMD)
10166 emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
10169 if (AOP(op)->aopu.aop_immd.from_cast_remat)
10170 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
10173 wassertl(FALSE, "need pointerCode");
10174 emitcode (";", "mov b,???");
10175 /* genPointerGet and genPointerSet originally did different
10176 ** things for this case. Both seem wrong.
10177 ** from genPointerGet:
10178 ** emitcode ("mov", "b,#%d", pointerCode (retype));
10179 ** from genPointerSet:
10180 ** emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
10185 else if (AOP_TYPE (op) == AOP_DPTR)
10189 MOVA (aopGet (op, 0, FALSE, FALSE));
10190 emitcode ("push", "acc");
10191 MOVA (aopGet (op, 1, FALSE, FALSE));
10192 emitcode ("push", "acc");
10193 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10194 emitcode ("pop", "dph");
10195 emitcode ("pop", "dpl");
10199 MOVA (aopGet (op, 0, FALSE, FALSE));
10200 emitcode ("push", "acc");
10201 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10202 emitcode ("pop", "dpl");
10206 { /* we need to get it byte by byte */
10207 emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
10208 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10210 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10215 /*-----------------------------------------------------------------*/
10216 /* genFarPointerGet - get value from far space */
10217 /*-----------------------------------------------------------------*/
10219 genFarPointerGet (operand * left,
10220 operand * result, iCode * ic, iCode * pi, iCode * ifx)
10223 char *ifxCond = "a";
10224 sym_link *retype = getSpec (operandType (result));
10226 D (emitcode (";", "genFarPointerGet"));
10228 aopOp (left, ic, FALSE);
10229 loadDptrFromOperand (left, FALSE);
10231 /* so dptr now contains the address */
10232 aopOp (result, ic, FALSE);
10234 /* if bit then unpack */
10235 if (IS_BITFIELD (retype))
10236 ifxCond = genUnpackBits (result, "dptr", FPOINTER, ifx);
10239 size = AOP_SIZE (result);
10244 emitcode ("movx", "a,@dptr");
10246 aopPut (result, "a", offset++);
10248 emitcode ("inc", "dptr");
10252 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10254 aopPut (left, "dpl", 0);
10255 aopPut (left, "dph", 1);
10259 if (ifx && !ifx->generated)
10261 genIfxJump (ifx, ifxCond, left, NULL, result);
10264 freeAsmop (result, NULL, ic, TRUE);
10265 freeAsmop (left, NULL, ic, TRUE);
10268 /*-----------------------------------------------------------------*/
10269 /* genCodePointerGet - get value from code space */
10270 /*-----------------------------------------------------------------*/
10272 genCodePointerGet (operand * left,
10273 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10276 char *ifxCond = "a";
10277 sym_link *retype = getSpec (operandType (result));
10279 D (emitcode (";", "genCodePointerGet"));
10281 aopOp (left, ic, FALSE);
10282 loadDptrFromOperand (left, FALSE);
10284 /* so dptr now contains the address */
10285 aopOp (result, ic, FALSE);
10287 /* if bit then unpack */
10288 if (IS_BITFIELD (retype))
10289 ifxCond = genUnpackBits (result, "dptr", CPOINTER, ifx);
10292 size = AOP_SIZE (result);
10297 emitcode ("clr", "a");
10298 emitcode ("movc", "a,@a+dptr");
10300 aopPut (result, "a", offset++);
10302 emitcode ("inc", "dptr");
10306 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10308 aopPut (left, "dpl", 0);
10309 aopPut (left, "dph", 1);
10313 if (ifx && !ifx->generated)
10315 genIfxJump (ifx, ifxCond, left, NULL, result);
10318 freeAsmop (result, NULL, ic, TRUE);
10319 freeAsmop (left, NULL, ic, TRUE);
10322 /*-----------------------------------------------------------------*/
10323 /* genGenPointerGet - get value from generic pointer space */
10324 /*-----------------------------------------------------------------*/
10326 genGenPointerGet (operand * left,
10327 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10330 char *ifxCond = "a";
10331 sym_link *retype = getSpec (operandType (result));
10333 D (emitcode (";", "genGenPointerGet"));
10335 aopOp (left, ic, FALSE);
10336 loadDptrFromOperand (left, TRUE);
10338 /* so dptr now contains the address */
10339 aopOp (result, ic, FALSE);
10341 /* if bit then unpack */
10342 if (IS_BITFIELD (retype))
10344 ifxCond = genUnpackBits (result, "dptr", GPOINTER, ifx);
10348 size = AOP_SIZE (result);
10353 emitcode ("lcall", "__gptrget");
10355 aopPut (result, "a", offset++);
10357 emitcode ("inc", "dptr");
10361 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10363 aopPut (left, "dpl", 0);
10364 aopPut (left, "dph", 1);
10368 if (ifx && !ifx->generated)
10370 genIfxJump (ifx, ifxCond, left, NULL, result);
10373 freeAsmop (result, NULL, ic, TRUE);
10374 freeAsmop (left, NULL, ic, TRUE);
10377 /*-----------------------------------------------------------------*/
10378 /* genPointerGet - generate code for pointer get */
10379 /*-----------------------------------------------------------------*/
10381 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
10383 operand *left, *result;
10384 sym_link *type, *etype;
10387 D (emitcode (";", "genPointerGet"));
10389 left = IC_LEFT (ic);
10390 result = IC_RESULT (ic);
10392 if (getSize (operandType (result))>1)
10395 /* depending on the type of pointer we need to
10396 move it to the correct pointer register */
10397 type = operandType (left);
10398 etype = getSpec (type);
10399 /* if left is of type of pointer then it is simple */
10400 if (IS_PTR (type) && !IS_FUNC (type->next))
10402 p_type = DCL_TYPE (type);
10406 /* we have to go by the storage class */
10407 p_type = PTR_TYPE (SPEC_OCLS (etype));
10410 /* special case when cast remat */
10411 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10412 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10414 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10415 type = operandType (left);
10416 p_type = DCL_TYPE (type);
10418 /* now that we have the pointer type we assign
10419 the pointer values */
10425 genNearPointerGet (left, result, ic, pi, ifx);
10429 genPagedPointerGet (left, result, ic, pi, ifx);
10433 genFarPointerGet (left, result, ic, pi, ifx);
10437 genCodePointerGet (left, result, ic, pi, ifx);
10441 genGenPointerGet (left, result, ic, pi, ifx);
10447 /*-----------------------------------------------------------------*/
10448 /* genPackBits - generates code for packed bit storage */
10449 /*-----------------------------------------------------------------*/
10451 genPackBits (sym_link * etype,
10453 char *rname, int p_type)
10455 int offset = 0; /* source byte offset */
10456 int rlen = 0; /* remaining bitfield length */
10457 int blen; /* bitfield length */
10458 int bstr; /* bitfield starting bit within byte */
10459 int litval; /* source literal value (if AOP_LIT) */
10460 unsigned char mask; /* bitmask within current byte */
10462 D(emitcode (";", "genPackBits"));
10464 blen = SPEC_BLEN (etype);
10465 bstr = SPEC_BSTR (etype);
10467 /* If the bitfield length is less than a byte */
10470 mask = ((unsigned char) (0xFF << (blen + bstr)) |
10471 (unsigned char) (0xFF >> (8 - bstr)));
10473 if (AOP_TYPE (right) == AOP_LIT)
10475 /* Case with a bitfield length <8 and literal source
10477 litval = (int) ulFromVal (AOP (right)->aopu.aop_lit);
10479 litval &= (~mask) & 0xff;
10480 emitPtrByteGet (rname, p_type, FALSE);
10481 if ((mask|litval)!=0xff)
10482 emitcode ("anl","a,#0x%02x", mask);
10484 emitcode ("orl","a,#0x%02x", litval);
10488 if ((blen==1) && (p_type!=GPOINTER))
10490 /* Case with a bitfield length == 1 and no generic pointer
10492 if (AOP_TYPE (right) == AOP_CRY)
10493 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10496 MOVA (aopGet (right, 0, FALSE, FALSE));
10497 emitcode ("rrc","a");
10499 emitPtrByteGet (rname, p_type, FALSE);
10500 emitcode ("mov","acc.%d,c",bstr);
10505 /* Case with a bitfield length < 8 and arbitrary source
10507 MOVA (aopGet (right, 0, FALSE, FALSE));
10508 /* shift and mask source value */
10510 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10512 pushedB = pushB ();
10513 /* transfer A to B and get next byte */
10514 emitPtrByteGet (rname, p_type, TRUE);
10516 emitcode ("anl", "a,#0x%02x", mask);
10517 emitcode ("orl", "a,b");
10518 if (p_type == GPOINTER)
10519 emitcode ("pop", "b");
10525 emitPtrByteSet (rname, p_type, "a");
10529 /* Bit length is greater than 7 bits. In this case, copy */
10530 /* all except the partial byte at the end */
10531 for (rlen=blen;rlen>=8;rlen-=8)
10533 emitPtrByteSet (rname, p_type,
10534 aopGet (right, offset++, FALSE, TRUE) );
10536 emitcode ("inc", "%s", rname);
10539 /* If there was a partial byte at the end */
10542 mask = (((unsigned char) -1 << rlen) & 0xff);
10544 if (AOP_TYPE (right) == AOP_LIT)
10546 /* Case with partial byte and literal source
10548 litval = (int) ulFromVal (AOP (right)->aopu.aop_lit);
10549 litval >>= (blen-rlen);
10550 litval &= (~mask) & 0xff;
10551 emitPtrByteGet (rname, p_type, FALSE);
10552 if ((mask|litval)!=0xff)
10553 emitcode ("anl","a,#0x%02x", mask);
10555 emitcode ("orl","a,#0x%02x", litval);
10560 /* Case with partial byte and arbitrary source
10562 MOVA (aopGet (right, offset++, FALSE, FALSE));
10563 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10565 pushedB = pushB ();
10566 /* transfer A to B and get next byte */
10567 emitPtrByteGet (rname, p_type, TRUE);
10569 emitcode ("anl", "a,#0x%02x", mask);
10570 emitcode ("orl", "a,b");
10571 if (p_type == GPOINTER)
10572 emitcode ("pop", "b");
10576 emitPtrByteSet (rname, p_type, "a");
10581 /*-----------------------------------------------------------------*/
10582 /* genDataPointerSet - remat pointer to data space */
10583 /*-----------------------------------------------------------------*/
10585 genDataPointerSet (operand * right,
10589 int size, offset = 0;
10590 char *l, buffer[256];
10592 D (emitcode (";", "genDataPointerSet"));
10594 aopOp (right, ic, FALSE);
10596 l = aopGet (result, 0, FALSE, TRUE);
10598 size = max (AOP_SIZE (right), AOP_SIZE (result));
10602 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
10604 SNPRINTF (buffer, sizeof(buffer), "%s", l);
10605 emitcode ("mov", "%s,%s", buffer,
10606 aopGet (right, offset++, FALSE, FALSE));
10609 freeAsmop (right, NULL, ic, TRUE);
10610 freeAsmop (result, NULL, ic, TRUE);
10613 /*-----------------------------------------------------------------*/
10614 /* genNearPointerSet - emitcode for near pointer put */
10615 /*-----------------------------------------------------------------*/
10617 genNearPointerSet (operand * right,
10625 sym_link *retype, *letype;
10626 sym_link *ptype = operandType (result);
10628 D (emitcode (";", "genNearPointerSet"));
10630 retype = getSpec (operandType (right));
10631 letype = getSpec (ptype);
10633 aopOp (result, ic, FALSE);
10635 /* if the result is rematerializable &
10636 in data space & not a bit variable */
10637 if (AOP_TYPE (result) == AOP_IMMD &&
10638 DCL_TYPE (ptype) == POINTER &&
10639 !IS_BITVAR (retype) &&
10640 !IS_BITVAR (letype))
10642 genDataPointerSet (right, result, ic);
10646 /* if the value is already in a pointer register
10647 then don't need anything more */
10648 if (!AOP_INPREG (AOP (result)))
10650 if (IS_AOP_PREG (result))
10652 // Aha, it is a pointer, just in disguise.
10653 rname = aopGet (result, 0, FALSE, FALSE);
10656 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10657 __FILE__, __LINE__);
10662 emitcode ("mov", "a%s,%s", rname + 1, rname);
10663 rname++; // skip the '@'.
10668 /* otherwise get a free pointer register */
10669 aop = newAsmop (0);
10670 preg = getFreePtr (ic, &aop, FALSE);
10671 emitcode ("mov", "%s,%s",
10673 aopGet (result, 0, FALSE, TRUE));
10674 rname = preg->name;
10679 rname = aopGet (result, 0, FALSE, FALSE);
10682 aopOp (right, ic, FALSE);
10684 /* if bitfield then unpack the bits */
10685 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10686 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10689 /* we can just get the values */
10690 int size = AOP_SIZE (right);
10695 l = aopGet (right, offset, FALSE, TRUE);
10696 if ((*l == '@') || (strcmp (l, "acc") == 0))
10699 emitcode ("mov", "@%s,a", rname);
10702 emitcode ("mov", "@%s,%s", rname, l);
10704 emitcode ("inc", "%s", rname);
10709 /* now some housekeeping stuff */
10710 if (aop) /* we had to allocate for this iCode */
10713 aopPut (result, rname, 0);
10714 freeAsmop (NULL, aop, ic, TRUE);
10718 /* we did not allocate which means left
10719 already in a pointer register, then
10720 if size > 0 && this could be used again
10721 we have to point it back to where it
10723 if ((AOP_SIZE (right) > 1 &&
10724 !OP_SYMBOL (result)->remat &&
10725 (OP_SYMBOL (result)->liveTo > ic->seq ||
10729 int size = AOP_SIZE (right) - 1;
10731 emitcode ("dec", "%s", rname);
10738 freeAsmop (right, NULL, ic, TRUE);
10739 freeAsmop (result, NULL, ic, TRUE);
10742 /*-----------------------------------------------------------------*/
10743 /* genPagedPointerSet - emitcode for Paged pointer put */
10744 /*-----------------------------------------------------------------*/
10746 genPagedPointerSet (operand * right,
10754 sym_link *retype, *letype;
10756 D (emitcode (";", "genPagedPointerSet"));
10758 retype = getSpec (operandType (right));
10759 letype = getSpec (operandType (result));
10761 aopOp (result, ic, FALSE);
10763 /* if the value is already in a pointer register
10764 then don't need anything more */
10765 if (!AOP_INPREG (AOP (result)))
10767 if (IS_AOP_PREG (result))
10769 // Aha, it is a pointer, just in disguise.
10770 rname = aopGet (result, 0, FALSE, FALSE);
10773 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10774 __FILE__, __LINE__);
10779 emitcode ("mov", "a%s,%s", rname + 1, rname);
10780 rname++; // skip the '@'.
10785 /* otherwise get a free pointer register */
10786 aop = newAsmop (0);
10787 preg = getFreePtr (ic, &aop, FALSE);
10788 emitcode ("mov", "%s,%s",
10790 aopGet (result, 0, FALSE, TRUE));
10791 rname = preg->name;
10796 rname = aopGet (result, 0, FALSE, FALSE);
10799 aopOp (right, ic, FALSE);
10801 /* if bitfield then unpack the bits */
10802 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10803 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10806 /* we can just get the values */
10807 int size = AOP_SIZE (right);
10812 l = aopGet (right, offset, FALSE, TRUE);
10814 emitcode ("movx", "@%s,a", rname);
10816 emitcode ("inc", "%s", rname);
10821 /* now some housekeeping stuff */
10822 if (aop) /* we had to allocate for this iCode */
10825 aopPut (result, rname, 0);
10826 freeAsmop (NULL, aop, ic, TRUE);
10830 /* we did not allocate which means left
10831 already in a pointer register, then
10832 if size > 0 && this could be used again
10833 we have to point it back to where it
10835 if (AOP_SIZE (right) > 1 &&
10836 !OP_SYMBOL (result)->remat &&
10837 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth) &&
10840 int size = AOP_SIZE (right) - 1;
10842 emitcode ("dec", "%s", rname);
10849 freeAsmop (right, NULL, ic, TRUE);
10850 freeAsmop (result, NULL, ic, TRUE);
10853 /*-----------------------------------------------------------------*/
10854 /* genFarPointerSet - set value from far space */
10855 /*-----------------------------------------------------------------*/
10857 genFarPointerSet (operand * right,
10858 operand * result, iCode * ic, iCode * pi)
10861 sym_link *retype = getSpec (operandType (right));
10862 sym_link *letype = getSpec (operandType (result));
10864 D(emitcode (";", "genFarPointerSet"));
10866 aopOp (result, ic, FALSE);
10867 loadDptrFromOperand (result, FALSE);
10869 /* so dptr now contains the address */
10870 aopOp (right, ic, FALSE);
10872 /* if bit then unpack */
10873 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10874 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10877 size = AOP_SIZE (right);
10882 char *l = aopGet (right, offset++, FALSE, FALSE);
10884 emitcode ("movx", "@dptr,a");
10886 emitcode ("inc", "dptr");
10889 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10890 aopPut (result, "dpl", 0);
10891 aopPut (result, "dph", 1);
10894 freeAsmop (result, NULL, ic, TRUE);
10895 freeAsmop (right, NULL, ic, TRUE);
10898 /*-----------------------------------------------------------------*/
10899 /* genGenPointerSet - set value from generic pointer space */
10900 /*-----------------------------------------------------------------*/
10902 genGenPointerSet (operand * right,
10903 operand * result, iCode * ic, iCode * pi)
10906 sym_link *retype = getSpec (operandType (right));
10907 sym_link *letype = getSpec (operandType (result));
10909 D (emitcode (";", "genGenPointerSet"));
10911 aopOp (result, ic, FALSE);
10912 loadDptrFromOperand (result, TRUE);
10914 /* so dptr now contains the address */
10915 aopOp (right, ic, FALSE);
10917 /* if bit then unpack */
10918 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10920 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10924 size = AOP_SIZE (right);
10929 char *l = aopGet (right, offset++, FALSE, FALSE);
10931 emitcode ("lcall", "__gptrput");
10933 emitcode ("inc", "dptr");
10937 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10938 aopPut (result, "dpl", 0);
10939 aopPut (result, "dph", 1);
10942 freeAsmop (result, NULL, ic, TRUE);
10943 freeAsmop (right, NULL, ic, TRUE);
10946 /*-----------------------------------------------------------------*/
10947 /* genPointerSet - stores the value into a pointer location */
10948 /*-----------------------------------------------------------------*/
10950 genPointerSet (iCode * ic, iCode *pi)
10952 operand *right, *result;
10953 sym_link *type, *etype;
10956 D (emitcode (";", "genPointerSet"));
10958 right = IC_RIGHT (ic);
10959 result = IC_RESULT (ic);
10961 /* depending on the type of pointer we need to
10962 move it to the correct pointer register */
10963 type = operandType (result);
10964 etype = getSpec (type);
10965 /* if left is of type of pointer then it is simple */
10966 if (IS_PTR (type) && !IS_FUNC (type->next))
10968 p_type = DCL_TYPE (type);
10972 /* we have to go by the storage class */
10973 p_type = PTR_TYPE (SPEC_OCLS (etype));
10976 /* special case when cast remat */
10977 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10978 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10979 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10980 type = operandType (result);
10981 p_type = DCL_TYPE (type);
10984 /* now that we have the pointer type we assign
10985 the pointer values */
10991 genNearPointerSet (right, result, ic, pi);
10995 genPagedPointerSet (right, result, ic, pi);
10999 genFarPointerSet (right, result, ic, pi);
11003 genGenPointerSet (right, result, ic, pi);
11007 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11008 "genPointerSet: illegal pointer type");
11012 /*-----------------------------------------------------------------*/
11013 /* genIfx - generate code for Ifx statement */
11014 /*-----------------------------------------------------------------*/
11016 genIfx (iCode * ic, iCode * popIc)
11018 operand *cond = IC_COND (ic);
11022 D (emitcode (";", "genIfx"));
11024 aopOp (cond, ic, FALSE);
11026 /* get the value into acc */
11027 if (AOP_TYPE (cond) != AOP_CRY)
11034 if (AOP(cond)->aopu.aop_dir)
11035 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
11038 /* the result is now in the accumulator or a directly addressable bit */
11039 freeAsmop (cond, NULL, ic, TRUE);
11041 /* if there was something to be popped then do it */
11045 /* if the condition is a bit variable */
11047 genIfxJump(ic, dup, NULL, NULL, NULL);
11048 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
11049 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
11050 else if (isbit && !IS_ITEMP (cond))
11051 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
11053 genIfxJump (ic, "a", NULL, NULL, NULL);
11058 /*-----------------------------------------------------------------*/
11059 /* genAddrOf - generates code for address of */
11060 /*-----------------------------------------------------------------*/
11062 genAddrOf (iCode * ic)
11064 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
11067 D (emitcode (";", "genAddrOf"));
11069 aopOp (IC_RESULT (ic), ic, FALSE);
11071 /* if the operand is on the stack then we
11072 need to get the stack offset of this
11076 /* if it has an offset then we need to compute it */
11079 int stack_offset = ((sym->stack < 0) ?
11080 ((char) (sym->stack - _G.nRegsSaved)) :
11081 ((char) sym->stack)) & 0xff;
11082 if ((abs(stack_offset) == 1) &&
11083 !AOP_NEEDSACC(IC_RESULT (ic)) &&
11084 !isOperandVolatile (IC_RESULT (ic), FALSE))
11086 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
11087 if (stack_offset > 0)
11088 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
11090 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
11094 emitcode ("mov", "a,%s", SYM_BP (sym));
11095 emitcode ("add", "a,#0x%02x", stack_offset & 0xff);
11096 aopPut (IC_RESULT (ic), "a", 0);
11101 /* we can just move _bp */
11102 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
11104 /* fill the result with zero */
11105 size = AOP_SIZE (IC_RESULT (ic)) - 1;
11110 aopPut (IC_RESULT (ic), zero, offset++);
11115 /* object not on stack then we need the name */
11116 size = getDataSize (IC_RESULT (ic));
11121 char s[SDCC_NAME_MAX];
11123 sprintf (s, "#(%s >> %d)",
11127 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11128 aopPut (IC_RESULT (ic), s, offset++);
11130 if (opIsGptr (IC_RESULT (ic)))
11133 SNPRINTF (buffer, sizeof(buffer),
11134 "#0x%02x", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
11135 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
11139 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11143 /*-----------------------------------------------------------------*/
11144 /* genFarFarAssign - assignment when both are in far space */
11145 /*-----------------------------------------------------------------*/
11147 genFarFarAssign (operand * result, operand * right, iCode * ic)
11149 int size = AOP_SIZE (right);
11153 D (emitcode (";", "genFarFarAssign"));
11155 /* first push the right side on to the stack */
11158 l = aopGet (right, offset++, FALSE, FALSE);
11160 emitcode ("push", "acc");
11163 freeAsmop (right, NULL, ic, FALSE);
11164 /* now assign DPTR to result */
11165 aopOp (result, ic, FALSE);
11166 size = AOP_SIZE (result);
11169 emitcode ("pop", "acc");
11170 aopPut (result, "a", --offset);
11172 freeAsmop (result, NULL, ic, FALSE);
11175 /*-----------------------------------------------------------------*/
11176 /* genAssign - generate code for assignment */
11177 /*-----------------------------------------------------------------*/
11179 genAssign (iCode * ic)
11181 operand *result, *right;
11183 unsigned long lit = 0L;
11185 D (emitcode (";", "genAssign"));
11187 result = IC_RESULT (ic);
11188 right = IC_RIGHT (ic);
11190 /* if they are the same */
11191 if (operandsEqu (result, right) &&
11192 !isOperandVolatile (result, FALSE) &&
11193 !isOperandVolatile (right, FALSE))
11196 aopOp (right, ic, FALSE);
11198 /* special case both in far space */
11199 if (AOP_TYPE (right) == AOP_DPTR &&
11200 IS_TRUE_SYMOP (result) &&
11201 isOperandInFarSpace (result))
11203 genFarFarAssign (result, right, ic);
11207 aopOp (result, ic, TRUE);
11209 /* if they are the same registers */
11210 if (sameRegs (AOP (right), AOP (result)) &&
11211 !isOperandVolatile (result, FALSE) &&
11212 !isOperandVolatile (right, FALSE))
11215 /* if the result is a bit */
11216 if (AOP_TYPE (result) == AOP_CRY)
11218 assignBit (result, right);
11222 /* bit variables done */
11224 size = getDataSize (result);
11226 if (AOP_TYPE (right) == AOP_LIT)
11227 lit = ulFromVal (AOP (right)->aopu.aop_lit);
11230 (AOP_TYPE (result) != AOP_REG) &&
11231 (AOP_TYPE (right) == AOP_LIT) &&
11232 !IS_FLOAT (operandType (right)) &&
11235 while ((size) && (lit))
11238 aopGet (right, offset, FALSE, FALSE),
11244 /* And now fill the rest with zeros. */
11247 emitcode ("clr", "a");
11251 aopPut (result, "a", offset);
11260 aopGet (right, offset, FALSE, FALSE),
11265 adjustArithmeticResult (ic);
11268 freeAsmop (result, NULL, ic, TRUE);
11269 freeAsmop (right, NULL, ic, TRUE);
11272 /*-----------------------------------------------------------------*/
11273 /* genJumpTab - generates code for jump table */
11274 /*-----------------------------------------------------------------*/
11276 genJumpTab (iCode * ic)
11278 symbol *jtab,*jtablo,*jtabhi;
11280 unsigned int count;
11282 D (emitcode (";", "genJumpTab"));
11284 count = elementsInSet( IC_JTLABELS (ic) );
11288 /* this algorithm needs 9 cycles and 7 + 3*n bytes
11289 if the switch argument is in a register.
11290 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
11291 /* Peephole may not convert ljmp to sjmp or ret
11292 labelIsReturnOnly & labelInRange must check
11293 currPl->ic->op != JUMPTABLE */
11294 aopOp (IC_JTCOND (ic), ic, FALSE);
11295 /* get the condition into accumulator */
11296 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11298 /* multiply by three */
11299 if (aopGetUsesAcc (IC_JTCOND (ic), 0))
11301 emitcode ("mov", "b,#0x03");
11302 emitcode ("mul", "ab");
11306 emitcode ("add", "a,acc");
11307 emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
11309 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11311 jtab = newiTempLabel (NULL);
11312 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
11313 emitcode ("jmp", "@a+dptr");
11315 /* now generate the jump labels */
11316 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11317 jtab = setNextItem (IC_JTLABELS (ic)))
11318 emitcode ("ljmp", "%05d$", jtab->key + 100);
11322 /* this algorithm needs 14 cycles and 13 + 2*n bytes
11323 if the switch argument is in a register.
11324 For n>6 this algorithm may be more compact */
11325 jtablo = newiTempLabel (NULL);
11326 jtabhi = newiTempLabel (NULL);
11328 /* get the condition into accumulator.
11329 Using b as temporary storage, if register push/pop is needed */
11330 aopOp (IC_JTCOND (ic), ic, FALSE);
11331 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11332 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
11333 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
11335 // (MB) what if B is in use???
11336 wassertl(!BINUSE, "B was in use");
11337 emitcode ("mov", "b,%s", l);
11340 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11344 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
11345 emitcode ("movc", "a,@a+pc");
11346 emitcode ("push", "acc");
11349 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
11350 emitcode ("movc", "a,@a+pc");
11351 emitcode ("push", "acc");
11355 /* this scales up to n<=255, but needs two more bytes
11356 and changes dptr */
11357 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
11358 emitcode ("movc", "a,@a+dptr");
11359 emitcode ("push", "acc");
11362 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
11363 emitcode ("movc", "a,@a+dptr");
11364 emitcode ("push", "acc");
11367 emitcode ("ret", "");
11369 /* now generate jump table, LSB */
11370 emitLabel (jtablo);
11371 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11372 jtab = setNextItem (IC_JTLABELS (ic)))
11373 emitcode (".db", "%05d$", jtab->key + 100);
11375 /* now generate jump table, MSB */
11376 emitLabel (jtabhi);
11377 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11378 jtab = setNextItem (IC_JTLABELS (ic)))
11379 emitcode (".db", "%05d$>>8", jtab->key + 100);
11383 /*-----------------------------------------------------------------*/
11384 /* genCast - gen code for casting */
11385 /*-----------------------------------------------------------------*/
11387 genCast (iCode * ic)
11389 operand *result = IC_RESULT (ic);
11390 sym_link *ctype = operandType (IC_LEFT (ic));
11391 sym_link *rtype = operandType (IC_RIGHT (ic));
11392 operand *right = IC_RIGHT (ic);
11395 D (emitcode (";", "genCast"));
11397 /* if they are equivalent then do nothing */
11398 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11401 aopOp (right, ic, FALSE);
11402 aopOp (result, ic, FALSE);
11404 /* if the result is a bit (and not a bitfield) */
11405 if (IS_BIT (OP_SYMBOL (result)->type))
11407 assignBit (result, right);
11411 /* if they are the same size : or less */
11412 if (AOP_SIZE (result) <= AOP_SIZE (right))
11415 /* if they are in the same place */
11416 if (sameRegs (AOP (right), AOP (result)))
11419 /* if they in different places then copy */
11420 size = AOP_SIZE (result);
11425 aopGet (right, offset, FALSE, FALSE),
11432 /* if the result is of type pointer */
11433 if (IS_PTR (ctype))
11437 sym_link *type = operandType (right);
11438 sym_link *etype = getSpec (type);
11440 /* pointer to generic pointer */
11441 if (IS_GENPTR (ctype))
11445 p_type = DCL_TYPE (type);
11449 if (SPEC_SCLS(etype)==S_REGISTER) {
11450 // let's assume it is a generic pointer
11453 /* we have to go by the storage class */
11454 p_type = PTR_TYPE (SPEC_OCLS (etype));
11458 /* the first two bytes are known */
11459 size = GPTRSIZE - 1;
11464 aopGet (right, offset, FALSE, FALSE),
11468 /* the last byte depending on type */
11470 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11475 // pointerTypeToGPByte will have bitched.
11479 sprintf(gpValStr, "#0x%02x", gpVal);
11480 aopPut (result, gpValStr, GPTRSIZE - 1);
11485 /* just copy the pointers */
11486 size = AOP_SIZE (result);
11491 aopGet (right, offset, FALSE, FALSE),
11498 /* so we now know that the size of destination is greater
11499 than the size of the source */
11500 /* we move to result for the size of source */
11501 size = AOP_SIZE (right);
11506 aopGet (right, offset, FALSE, FALSE),
11511 /* now depending on the sign of the source && destination */
11512 size = AOP_SIZE (result) - AOP_SIZE (right);
11513 /* if unsigned or not an integral type */
11514 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11517 aopPut (result, zero, offset++);
11521 /* we need to extend the sign :{ */
11522 char *l = aopGet (right, AOP_SIZE (right) - 1,
11525 emitcode ("rlc", "a");
11526 emitcode ("subb", "a,acc");
11528 aopPut (result, "a", offset++);
11531 /* we are done hurray !!!! */
11534 freeAsmop (result, NULL, ic, TRUE);
11535 freeAsmop (right, NULL, ic, TRUE);
11538 /*-----------------------------------------------------------------*/
11539 /* genDjnz - generate decrement & jump if not zero instrucion */
11540 /*-----------------------------------------------------------------*/
11542 genDjnz (iCode * ic, iCode * ifx)
11544 symbol *lbl, *lbl1;
11548 /* if the if condition has a false label
11549 then we cannot save */
11550 if (IC_FALSE (ifx))
11553 /* if the minus is not of the form a = a - 1 */
11554 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11555 !IS_OP_LITERAL (IC_RIGHT (ic)))
11558 if (operandLitValue (IC_RIGHT (ic)) != 1)
11561 /* if the size of this greater than one then no
11563 if (getSize (operandType (IC_RESULT (ic))) > 1)
11566 /* otherwise we can save BIG */
11568 D (emitcode (";", "genDjnz"));
11570 lbl = newiTempLabel (NULL);
11571 lbl1 = newiTempLabel (NULL);
11573 aopOp (IC_RESULT (ic), ic, FALSE);
11575 if (AOP_NEEDSACC(IC_RESULT(ic)))
11577 /* If the result is accessed indirectly via
11578 * the accumulator, we must explicitly write
11579 * it back after the decrement.
11581 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11583 if (strcmp(rByte, "a"))
11585 /* Something is hopelessly wrong */
11586 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11587 __FILE__, __LINE__);
11588 /* We can just give up; the generated code will be inefficient,
11589 * but what the hey.
11591 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11594 emitcode ("dec", "%s", rByte);
11595 aopPut (IC_RESULT (ic), rByte, 0);
11596 emitcode ("jnz", "%05d$", lbl->key + 100);
11598 else if (IS_AOP_PREG (IC_RESULT (ic)))
11600 emitcode ("dec", "%s",
11601 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11602 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11603 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11604 ifx->generated = 1;
11605 emitcode ("jnz", "%05d$", lbl->key + 100);
11609 emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11612 emitcode ("sjmp", "%05d$", lbl1->key + 100);
11614 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11617 if (!ifx->generated)
11618 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11619 ifx->generated = 1;
11623 /*-----------------------------------------------------------------*/
11624 /* genReceive - generate code for a receive iCode */
11625 /*-----------------------------------------------------------------*/
11627 genReceive (iCode * ic)
11629 int size = getSize (operandType (IC_RESULT (ic)));
11632 D (emitcode (";", "genReceive"));
11634 if (ic->argreg == 1)
11635 { /* first parameter */
11636 if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11637 isOperandInPagedSpace (IC_RESULT (ic))) &&
11638 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11639 IS_TRUE_SYMOP (IC_RESULT (ic))))
11642 int receivingA = 0;
11645 for (offset = 0; offset<size; offset++)
11646 if (!strcmp (fReturn[offset], "a"))
11651 if (size==1 || getTempRegs(tempRegs, size-1, ic))
11653 for (offset = size-1; offset>0; offset--)
11654 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11655 emitcode("mov","a,%s", fReturn[0]);
11657 aopOp (IC_RESULT (ic), ic, FALSE);
11659 aopPut (IC_RESULT (ic), "a", offset);
11660 for (offset = 1; offset<size; offset++)
11661 aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset);
11667 if (getTempRegs(tempRegs, size, ic))
11669 for (offset = 0; offset<size; offset++)
11670 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11671 aopOp (IC_RESULT (ic), ic, FALSE);
11672 for (offset = 0; offset<size; offset++)
11673 aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset);
11678 offset = fReturnSizeMCS51 - size;
11681 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11682 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11685 aopOp (IC_RESULT (ic), ic, FALSE);
11686 size = AOP_SIZE (IC_RESULT (ic));
11690 emitcode ("pop", "acc");
11691 aopPut (IC_RESULT (ic), "a", offset++);
11697 aopOp (IC_RESULT (ic), ic, FALSE);
11699 assignResultValue (IC_RESULT (ic), NULL);
11702 else if (ic->argreg > 12)
11703 { /* bit parameters */
11704 regs *reg = OP_SYMBOL (IC_RESULT (ic))->regs[0];
11707 if (!reg || reg->rIdx != ic->argreg-5)
11709 aopOp (IC_RESULT (ic), ic, FALSE);
11710 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11711 outBitC(IC_RESULT (ic));
11715 { /* other parameters */
11717 aopOp (IC_RESULT (ic), ic, FALSE);
11718 rb1off = ic->argreg;
11721 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
11726 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11729 /*-----------------------------------------------------------------*/
11730 /* genDummyRead - generate code for dummy read of volatiles */
11731 /*-----------------------------------------------------------------*/
11733 genDummyRead (iCode * ic)
11738 D (emitcode(";", "genDummyRead"));
11740 op = IC_RIGHT (ic);
11741 if (op && IS_SYMOP (op))
11743 aopOp (op, ic, FALSE);
11745 /* if the result is a bit */
11746 if (AOP_TYPE (op) == AOP_CRY)
11747 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11750 /* bit variables done */
11752 size = AOP_SIZE (op);
11756 MOVA (aopGet (op, offset, FALSE, FALSE));
11761 freeAsmop (op, NULL, ic, TRUE);
11765 if (op && IS_SYMOP (op))
11767 aopOp (op, ic, FALSE);
11769 /* if the result is a bit */
11770 if (AOP_TYPE (op) == AOP_CRY)
11771 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11774 /* bit variables done */
11776 size = AOP_SIZE (op);
11780 MOVA (aopGet (op, offset, FALSE, FALSE));
11785 freeAsmop (op, NULL, ic, TRUE);
11789 /*-----------------------------------------------------------------*/
11790 /* genCritical - generate code for start of a critical sequence */
11791 /*-----------------------------------------------------------------*/
11793 genCritical (iCode *ic)
11795 symbol *tlbl = newiTempLabel (NULL);
11797 D (emitcode(";", "genCritical"));
11799 if (IC_RESULT (ic))
11801 aopOp (IC_RESULT (ic), ic, TRUE);
11802 aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
11803 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11804 aopPut (IC_RESULT (ic), zero, 0);
11806 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11810 emitcode ("setb", "c");
11811 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11812 emitcode ("clr", "c");
11814 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11818 /*-----------------------------------------------------------------*/
11819 /* genEndCritical - generate code for end of a critical sequence */
11820 /*-----------------------------------------------------------------*/
11822 genEndCritical (iCode *ic)
11824 D(emitcode(";", "genEndCritical"));
11828 aopOp (IC_RIGHT (ic), ic, FALSE);
11829 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11831 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11832 emitcode ("mov", "ea,c");
11836 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11837 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11838 emitcode ("rrc", "a");
11839 emitcode ("mov", "ea,c");
11841 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11845 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11846 emitcode ("mov", "ea,c");
11850 /*-----------------------------------------------------------------*/
11851 /* gen51Code - generate code for 8051 based controllers */
11852 /*-----------------------------------------------------------------*/
11854 gen51Code (iCode * lic)
11858 /* int cseq = 0; */
11860 _G.currentFunc = NULL;
11861 lineHead = lineCurr = NULL;
11863 /* print the allocation information */
11864 if (allocInfo && currFunc)
11865 printAllocInfo (currFunc, codeOutBuf);
11866 /* if debug information required */
11867 if (options.debug && currFunc)
11869 debugFile->writeFunction (currFunc, lic);
11871 /* stack pointer name */
11872 if (options.useXstack)
11878 for (ic = lic; ic; ic = ic->next)
11880 _G.current_iCode = ic;
11882 if (ic->lineno && cln != ic->lineno)
11886 debugFile->writeCLine (ic);
11888 if (!options.noCcodeInAsm) {
11889 emitcode (";", "%s:%d: %s", ic->filename, ic->lineno,
11890 printCLine(ic->filename, ic->lineno));
11895 if (ic->seqPoint && ic->seqPoint != cseq)
11897 emitcode (";", "sequence point %d", ic->seqPoint);
11898 cseq = ic->seqPoint;
11901 if (options.iCodeInAsm) {
11902 char regsInUse[80];
11907 for (i=0; i<8; i++) {
11908 sprintf (®sInUse[i],
11909 "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11912 strcpy (regsInUse, "--------");
11913 for (i=0; i < 8; i++) {
11914 if (bitVectBitValue (ic->rMask, i))
11916 int offset = regs8051[i].offset;
11917 regsInUse[offset] = offset + '0'; /* show rMask */
11921 iLine = printILine(ic);
11922 emitcode(";", "[%s] ic:%d: %s", regsInUse, ic->seq, iLine);
11925 /* if the result is marked as
11926 spilt and rematerializable or code for
11927 this has already been generated then
11929 if (resultRemat (ic) || ic->generated)
11932 /* depending on the operation */
11952 /* IPOP happens only when trying to restore a
11953 spilt live range, if there is an ifx statement
11954 following this pop then the if statement might
11955 be using some of the registers being popped which
11956 would destory the contents of the register so
11957 we need to check for this condition and handle it */
11959 ic->next->op == IFX &&
11960 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11961 genIfx (ic->next, ic);
11979 genEndFunction (ic);
11999 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
12016 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
12020 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
12027 /* note these two are xlated by algebraic equivalence
12028 in decorateType() in SDCCast.c */
12029 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12030 "got '>=' or '<=' shouldn't have come here");
12034 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
12046 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
12050 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
12054 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
12090 genRightShift (ic);
12093 case GET_VALUE_AT_ADDRESS:
12095 hasInc (IC_LEFT (ic), ic,
12096 getSize (operandType (IC_RESULT (ic)))),
12097 ifxForOp (IC_RESULT (ic), ic) );
12101 if (POINTER_SET (ic))
12103 hasInc (IC_RESULT (ic), ic,
12104 getSize (operandType (IC_RIGHT (ic)))));
12130 addSet (&_G.sendSet, ic);
12133 case DUMMY_READ_VOLATILE:
12142 genEndCritical (ic);
12154 _G.current_iCode = NULL;
12156 /* now we are ready to call the
12157 peep hole optimizer */
12158 if (!options.nopeep)
12159 peepHole (&lineHead);
12161 /* now do the actual printing */
12162 printLine (lineHead, codeOutBuf);