1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for 8051
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
27 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
28 Made everything static
29 -------------------------------------------------------------------------*/
31 #define D(x) do if (options.verboseAsm) {x;} while(0)
37 #include "SDCCglobl.h"
41 #include "SDCCpeeph.h"
45 #include "dbuf_string.h"
47 char *aopLiteral (value * val, int offset);
48 char *aopLiteralLong (value * val, int offset, int size);
51 /* this is the down and dirty file with all kinds of
52 kludgy & hacky stuff. This is what it is all about
53 CODE GENERATION for a specific MCU . some of the
54 routines may be reusable, will have to see */
56 static char *zero = "#0x00";
57 static char *one = "#0x01";
61 {"dpl", "dph", "b", "a"};
62 unsigned fReturnSizeMCS51 = 4; /* shared with ralloc.c */
63 char **fReturn = fReturn8051;
64 static char *accUse[] =
67 static unsigned short rbank = -1;
69 #define REG_WITH_INDEX mcs51_regWithIdx
71 #define AOP(op) op->aop
72 #define AOP_TYPE(op) AOP(op)->type
73 #define AOP_SIZE(op) AOP(op)->size
74 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
75 AOP_TYPE(x) == AOP_R0))
77 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
78 AOP_TYPE(x) == AOP_DPTR || \
81 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
82 (x->aopu.aop_reg[0] == REG_WITH_INDEX(R0_IDX) || \
83 x->aopu.aop_reg[0] == REG_WITH_INDEX(R1_IDX) )))
85 #define SYM_BP(sym) (SPEC_OCLS (sym->etype)->paged ? "_bpx" : "_bp")
87 #define R0INB _G.bu.bs.r0InB
88 #define R1INB _G.bu.bs.r1InB
89 #define OPINB _G.bu.bs.OpInB
90 #define BINUSE _G.bu.BInUse
100 short r0InB : 2;//2 so we can see it overflow
101 short r1InB : 2;//2 so we can see it overflow
102 short OpInB : 2;//2 so we can see it overflow
111 iCode *current_iCode;
116 static char *rb1regs[] = {
117 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7",
118 "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7"
121 extern struct dbuf_s *codeOutBuf;
123 #define RESULTONSTACK(x) \
124 (IC_RESULT(x) && IC_RESULT(x)->aop && \
125 IC_RESULT(x)->aop->type == AOP_STK )
127 #define MOVA(x) mova(x) /* use function to avoid multiple eval */
128 #define MOVB(x) movb(x)
130 #define CLRC emitcode("clr","c")
131 #define SETC emitcode("setb","c")
133 static lineNode *lineHead = NULL;
134 static lineNode *lineCurr = NULL;
136 static unsigned char SLMask[] =
137 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
138 0xE0, 0xC0, 0x80, 0x00};
139 static unsigned char SRMask[] =
140 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
141 0x07, 0x03, 0x01, 0x00};
148 /*-----------------------------------------------------------------*/
149 /* emitcode - writes the code into a file : for now it is simple */
150 /*-----------------------------------------------------------------*/
152 emitcode (const char *inst, const char *fmt,...)
156 const char *lbp, *lb;
158 dbuf_init (&dbuf, INITIAL_INLINEASM);
164 dbuf_append_str (&dbuf, inst);
168 dbuf_append_char (&dbuf, '\t');
169 dbuf_tvprintf (&dbuf, fmt, ap);
174 dbuf_tvprintf (&dbuf, fmt, ap);
177 lbp = lb = dbuf_c_str(&dbuf);
179 while (isspace ((unsigned char)*lbp))
188 lineCurr = (lineCurr ?
189 connectLine (lineCurr, newLineNode (lb)) :
190 (lineHead = newLineNode (lb)));
192 lineCurr->isInline = _G.inLine;
193 lineCurr->isDebug = _G.debugLine;
194 lineCurr->ic = _G.current_iCode;
195 lineCurr->isComment = (*lbp==';');
204 emitLabel (symbol *tlbl)
206 emitcode ("", "%05d$:", tlbl->key + 100);
207 lineCurr->isLabel = 1;
210 /*-----------------------------------------------------------------*/
211 /* mcs51_emitDebuggerSymbol - associate the current code location */
212 /* with a debugger symbol */
213 /*-----------------------------------------------------------------*/
215 mcs51_emitDebuggerSymbol (char * debugSym)
218 emitcode ("", "%s ==.", debugSym);
222 /*-----------------------------------------------------------------*/
223 /* mova - moves specified value into accumulator */
224 /*-----------------------------------------------------------------*/
228 /* do some early peephole optimization */
229 if (!strncmp(x, "a", 2) || !strncmp(x, "acc", 4))
232 /* if it is a literal mov try to get it cheaper */
237 emitcode("mov", "a,%s", x);
240 /*-----------------------------------------------------------------*/
241 /* movb - moves specified value into register b */
242 /*-----------------------------------------------------------------*/
246 /* do some early peephole optimization */
247 if (!strncmp(x, "b", 2))
250 /* if it is a literal mov try to get it cheaper */
253 emitcode("mov","b,%s", rtrackGetLit(x));
257 emitcode("mov","b,%s", x);
260 /*-----------------------------------------------------------------*/
261 /* pushB - saves register B if necessary */
262 /*-----------------------------------------------------------------*/
266 bool pushedB = FALSE;
270 emitcode ("push", "b");
271 // printf("B was in use !\n");
281 /*-----------------------------------------------------------------*/
282 /* popB - restores value of register B if necessary */
283 /*-----------------------------------------------------------------*/
289 emitcode ("pop", "b");
297 /*-----------------------------------------------------------------*/
298 /* pushReg - saves register */
299 /*-----------------------------------------------------------------*/
301 pushReg (int index, bool bits_pushed)
303 regs * reg = REG_WITH_INDEX (index);
304 if (reg->type == REG_BIT)
307 emitcode ("push", "%s", reg->base);
311 emitcode ("push", "%s", reg->dname);
315 /*-----------------------------------------------------------------*/
316 /* popReg - restores register */
317 /*-----------------------------------------------------------------*/
319 popReg (int index, bool bits_popped)
321 regs * reg = REG_WITH_INDEX (index);
322 if (reg->type == REG_BIT)
325 emitcode ("pop", "%s", reg->base);
329 emitcode ("pop", "%s", reg->dname);
333 /*-----------------------------------------------------------------*/
334 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
335 /*-----------------------------------------------------------------*/
337 getFreePtr (iCode * ic, asmop ** aopp, bool result)
342 /* the logic: if r0 & r1 used in the instruction
343 then we are in trouble otherwise */
345 /* first check if r0 & r1 are used by this
346 instruction, in which case we are in trouble */
347 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
348 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
353 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
354 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
356 /* if no usage of r0 then return it */
359 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
360 (*aopp)->type = AOP_R0;
362 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
365 /* if no usage of r1 then return it */
368 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
369 (*aopp)->type = AOP_R1;
371 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R1_IDX);
374 /* now we know they both have usage */
375 /* if r0 not used in this instruction */
378 /* push it if not already pushed */
381 MOVB (REG_WITH_INDEX (R0_IDX)->dname);
384 else if (!_G.r0Pushed)
386 emitcode ("push", "%s",
387 REG_WITH_INDEX (R0_IDX)->dname);
391 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
392 (*aopp)->type = AOP_R0;
394 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
397 /* if r1 not used then */
401 /* push it if not already pushed */
404 MOVB (REG_WITH_INDEX (R1_IDX)->dname);
407 else if (!_G.r1Pushed)
409 emitcode ("push", "%s",
410 REG_WITH_INDEX (R1_IDX)->dname);
414 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
415 (*aopp)->type = AOP_R1;
416 return REG_WITH_INDEX (R1_IDX);
420 /* I said end of world, but not quite end of world yet */
421 /* if this is a result then we can push it on the stack */
424 (*aopp)->type = AOP_STK;
427 /* in the case that result AND left AND right needs a pointer reg
428 we can safely use the result's */
429 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX))
431 (*aopp)->type = AOP_R0;
432 return REG_WITH_INDEX (R0_IDX);
434 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX))
436 (*aopp)->type = AOP_R1;
437 return REG_WITH_INDEX (R1_IDX);
440 /* now this is REALLY the end of the world */
441 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
442 "getFreePtr should never reach here");
447 /*-----------------------------------------------------------------*/
448 /* getTempRegs - initialize an array of pointers to GPR registers */
449 /* that are not in use. Returns 1 if the requested */
450 /* number of registers were available, 0 otherwise. */
451 /*-----------------------------------------------------------------*/
453 getTempRegs(regs **tempRegs, int size, iCode *ic)
460 ic = _G.current_iCode;
466 freeRegs = newBitVect(8);
467 bitVectSetBit (freeRegs, R2_IDX);
468 bitVectSetBit (freeRegs, R3_IDX);
469 bitVectSetBit (freeRegs, R4_IDX);
470 bitVectSetBit (freeRegs, R5_IDX);
471 bitVectSetBit (freeRegs, R6_IDX);
472 bitVectSetBit (freeRegs, R7_IDX);
474 if (IFFUNC_CALLEESAVES(_G.currentFunc->type))
476 bitVect * newfreeRegs;
477 newfreeRegs = bitVectIntersect (freeRegs, _G.currentFunc->regsUsed);
478 freeBitVect(freeRegs);
479 freeRegs = newfreeRegs;
481 freeRegs = bitVectCplAnd (freeRegs, ic->rMask);
484 for (i=0; i<freeRegs->size; i++)
486 if (bitVectBitValue(freeRegs,i))
487 tempRegs[offset++] = REG_WITH_INDEX(i);
490 freeBitVect(freeRegs);
495 freeBitVect(freeRegs);
500 /*-----------------------------------------------------------------*/
501 /* newAsmop - creates a new asmOp */
502 /*-----------------------------------------------------------------*/
504 newAsmop (short type)
508 aop = Safe_calloc (1, sizeof (asmop));
514 /*-----------------------------------------------------------------*/
515 /* pointerCode - returns the code for a pointer type */
516 /*-----------------------------------------------------------------*/
518 pointerCode (sym_link * etype)
521 return PTR_TYPE (SPEC_OCLS (etype));
525 /*-----------------------------------------------------------------*/
526 /* leftRightUseAcc - returns size of accumulator use by operands */
527 /*-----------------------------------------------------------------*/
529 leftRightUseAcc(iCode *ic)
538 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
539 "null iCode pointer");
546 if (IS_OP_ACCUSE (op))
549 size = getSize (OP_SYMBOL (op)->type);
554 else if (ic->op == JUMPTABLE)
557 if (IS_OP_ACCUSE (op))
560 size = getSize (OP_SYMBOL (op)->type);
568 if (IS_OP_ACCUSE (op))
571 size = getSize (OP_SYMBOL (op)->type);
576 if (IS_OP_ACCUSE (op))
579 size = getSize (OP_SYMBOL (op)->type);
591 /*-----------------------------------------------------------------*/
592 /* aopForSym - for a true symbol */
593 /*-----------------------------------------------------------------*/
595 aopForSym (iCode * ic, symbol * sym, bool result)
599 bool accuse = leftRightUseAcc (ic) || _G.accInUse;
601 wassertl (ic != NULL, "Got a null iCode");
602 wassertl (sym != NULL, "Got a null symbol");
604 space = SPEC_OCLS (sym->etype);
606 /* if already has one */
609 sym->aop->allocated++;
613 /* assign depending on the storage class */
614 /* if it is on the stack or indirectly addressable */
615 /* space we need to assign either r0 or r1 to it */
616 if (sym->onStack || sym->iaccess)
618 sym->aop = aop = newAsmop (0);
619 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
620 aop->size = getSize (sym->type);
622 /* now assign the address of the variable to
623 the pointer register */
624 if (aop->type != AOP_STK)
628 signed char offset = ((sym->stack < 0) ?
629 ((signed char) (sym->stack - _G.nRegsSaved)) :
630 ((signed char) sym->stack)) & 0xff;
632 if ((abs(offset) <= 3) ||
633 (accuse && (abs(offset) <= 7)))
635 emitcode ("mov", "%s,%s",
636 aop->aopu.aop_ptr->name, SYM_BP (sym));
639 emitcode ("dec", aop->aopu.aop_ptr->name);
644 emitcode ("inc", aop->aopu.aop_ptr->name);
651 emitcode ("push", "acc");
652 emitcode ("mov", "a,%s", SYM_BP (sym));
653 emitcode ("add", "a,#0x%02x", offset & 0xff);
654 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
656 emitcode ("pop", "acc");
661 emitcode ("mov", "%s,#%s",
662 aop->aopu.aop_ptr->name,
665 aop->paged = space->paged;
668 aop->aopu.aop_stk = sym->stack;
672 /* if in bit space */
673 if (IN_BITSPACE (space))
675 sym->aop = aop = newAsmop (AOP_CRY);
676 aop->aopu.aop_dir = sym->rname;
677 aop->size = getSize (sym->type);
680 /* if it is in direct space */
681 if (IN_DIRSPACE (space))
683 //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
684 //printTypeChainRaw(sym->type, NULL);
685 //printf("space = %s\n", space ? space->sname : "NULL");
686 sym->aop = aop = newAsmop (AOP_DIR);
687 aop->aopu.aop_dir = sym->rname;
688 aop->size = getSize (sym->type);
692 /* special case for a function */
693 if (IS_FUNC (sym->type))
695 sym->aop = aop = newAsmop (AOP_IMMD);
696 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
697 aop->size = getSize (sym->type);
701 /* only remaining is far space */
702 /* in which case DPTR gets the address */
703 sym->aop = aop = newAsmop (AOP_DPTR);
704 emitcode ("mov", "dptr,#%s", sym->rname);
705 aop->size = getSize (sym->type);
707 /* if it is in code space */
708 if (IN_CODESPACE (space))
714 /*-----------------------------------------------------------------*/
715 /* aopForRemat - rematerializes an object */
716 /*-----------------------------------------------------------------*/
718 aopForRemat (symbol * sym)
720 iCode *ic = sym->rematiCode;
721 asmop *aop = newAsmop (AOP_IMMD);
728 val += (int) operandLitValue (IC_RIGHT (ic));
729 else if (ic->op == '-')
730 val -= (int) operandLitValue (IC_RIGHT (ic));
731 else if (IS_CAST_ICODE(ic))
733 sym_link *from_type = operandType(IC_RIGHT(ic));
734 aop->aopu.aop_immd.from_cast_remat = 1;
735 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
736 ptr_type = pointerTypeToGPByte (DCL_TYPE(from_type), NULL, NULL);
741 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
746 SNPRINTF (buffer, sizeof(buffer),
748 OP_SYMBOL (IC_LEFT (ic))->rname,
749 val >= 0 ? '+' : '-',
754 strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
757 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
758 /* set immd2 field if required */
759 if (aop->aopu.aop_immd.from_cast_remat)
761 SNPRINTF (buffer, sizeof(buffer), "#0x%02x", ptr_type);
762 aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
768 /*-----------------------------------------------------------------*/
769 /* regsInCommon - two operands have some registers in common */
770 /*-----------------------------------------------------------------*/
772 regsInCommon (operand * op1, operand * op2)
777 /* if they have registers in common */
778 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
781 sym1 = OP_SYMBOL (op1);
782 sym2 = OP_SYMBOL (op2);
784 if (sym1->nRegs == 0 || sym2->nRegs == 0)
787 for (i = 0; i < sym1->nRegs; i++)
793 for (j = 0; j < sym2->nRegs; j++)
798 if (sym2->regs[j] == sym1->regs[i])
806 /*-----------------------------------------------------------------*/
807 /* operandsEqu - equivalent */
808 /*-----------------------------------------------------------------*/
810 operandsEqu (operand * op1, operand * op2)
814 /* if they're not symbols */
815 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
818 sym1 = OP_SYMBOL (op1);
819 sym2 = OP_SYMBOL (op2);
821 /* if both are itemps & one is spilt
822 and the other is not then false */
823 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
824 sym1->isspilt != sym2->isspilt)
827 /* if they are the same */
831 /* if they have the same rname */
832 if (sym1->rname[0] && sym2->rname[0] &&
833 strcmp (sym1->rname, sym2->rname) == 0 &&
834 !(IS_PARM (op2) && IS_ITEMP (op1)))
837 /* if left is a tmp & right is not */
838 if (IS_ITEMP (op1) &&
841 (sym1->usl.spillLoc == sym2))
844 if (IS_ITEMP (op2) &&
848 (sym2->usl.spillLoc == sym1))
854 /*-----------------------------------------------------------------*/
855 /* sameByte - two asmops have the same address at given offsets */
856 /*-----------------------------------------------------------------*/
858 sameByte (asmop * aop1, int off1, asmop * aop2, int off2)
860 if (aop1 == aop2 && off1 == off2)
863 if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
866 if (aop1->type != aop2->type)
869 if (aop1->aopu.aop_reg[off1] != aop2->aopu.aop_reg[off2])
875 /*-----------------------------------------------------------------*/
876 /* sameRegs - two asmops have the same registers */
877 /*-----------------------------------------------------------------*/
879 sameRegs (asmop * aop1, asmop * aop2)
886 if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
889 if (aop1->type != aop2->type)
892 if (aop1->size != aop2->size)
895 for (i = 0; i < aop1->size; i++)
896 if (aop1->aopu.aop_reg[i] != aop2->aopu.aop_reg[i])
902 /*-----------------------------------------------------------------*/
903 /* aopOp - allocates an asmop for an operand : */
904 /*-----------------------------------------------------------------*/
906 aopOp (operand * op, iCode * ic, bool result)
915 /* if this a literal */
916 if (IS_OP_LITERAL (op))
918 op->aop = aop = newAsmop (AOP_LIT);
919 aop->aopu.aop_lit = op->operand.valOperand;
920 aop->size = getSize (operandType (op));
924 /* if already has a asmop then continue */
927 op->aop->allocated++;
931 /* if the underlying symbol has a aop */
932 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
934 op->aop = OP_SYMBOL (op)->aop;
935 op->aop->allocated++;
939 /* if this is a true symbol */
940 if (IS_TRUE_SYMOP (op))
942 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
946 /* this is a temporary : this has
952 e) can be a return use only */
954 sym = OP_SYMBOL (op);
956 /* if the type is a conditional */
957 if (sym->regType == REG_CND)
959 sym->aop = op->aop = aop = newAsmop (AOP_CRY);
960 aop->size = sym->ruonly ? 1 : 0;
964 /* if it is spilt then two situations
966 b) has a spill location */
967 if (sym->isspilt || sym->nRegs == 0)
970 /* rematerialize it NOW */
973 sym->aop = op->aop = aop = aopForRemat (sym);
974 aop->size = operandSize (op);
981 sym->aop = op->aop = aop = newAsmop (AOP_ACC);
982 aop->size = getSize (sym->type);
983 for (i = 0; i < 2; i++)
984 aop->aopu.aop_str[i] = accUse[i];
992 sym->aop = op->aop = aop = newAsmop (AOP_STR);
993 aop->size = getSize (sym->type);
994 for (i = 0; i < fReturnSizeMCS51; i++)
995 aop->aopu.aop_str[i] = fReturn[i];
999 if (sym->usl.spillLoc)
1001 asmop *oldAsmOp = NULL;
1003 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1005 /* force a new aop if sizes differ */
1006 oldAsmOp = sym->usl.spillLoc->aop;
1007 sym->usl.spillLoc->aop = NULL;
1009 sym->aop = op->aop = aop =
1010 aopForSym (ic, sym->usl.spillLoc, result);
1011 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1013 /* Don't reuse the new aop, go with the last one */
1014 sym->usl.spillLoc->aop = oldAsmOp;
1016 aop->size = getSize (sym->type);
1020 /* else must be a dummy iTemp */
1021 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1022 aop->size = getSize (sym->type);
1026 /* if the type is a bit register */
1027 if (sym->regType == REG_BIT)
1029 sym->aop = op->aop = aop = newAsmop (AOP_CRY);
1030 aop->size = sym->nRegs;//1???
1031 aop->aopu.aop_reg[0] = sym->regs[0];
1032 aop->aopu.aop_dir = sym->regs[0]->name;
1036 /* must be in a register */
1037 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1038 aop->size = sym->nRegs;
1039 for (i = 0; i < sym->nRegs; i++)
1040 aop->aopu.aop_reg[i] = sym->regs[i];
1043 /*-----------------------------------------------------------------*/
1044 /* freeAsmop - free up the asmop given to an operand */
1045 /*-----------------------------------------------------------------*/
1047 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1064 /* depending on the asmop type only three cases need work
1065 AOP_R0, AOP_R1 & AOP_STK */
1071 emitcode ("mov", "r0,b");
1074 else if (_G.r0Pushed)
1078 emitcode ("pop", "ar0");
1082 bitVectUnSetBit (ic->rUsed, R0_IDX);
1088 emitcode ("mov", "r1,b");
1091 else if (_G.r1Pushed)
1095 emitcode ("pop", "ar1");
1099 bitVectUnSetBit (ic->rUsed, R1_IDX);
1105 int stk = aop->aopu.aop_stk + aop->size - 1;
1106 bitVectUnSetBit (ic->rUsed, R0_IDX);
1107 bitVectUnSetBit (ic->rUsed, R1_IDX);
1109 getFreePtr (ic, &aop, FALSE);
1113 emitcode ("mov", "a,_bp");
1114 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1115 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1119 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1124 emitcode ("pop", "acc");
1125 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1128 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1131 freeAsmop (op, NULL, ic, TRUE);
1134 emitcode ("pop", "ar1");
1139 emitcode ("pop", "ar0");
1147 /* all other cases just dealloc */
1153 OP_SYMBOL (op)->aop = NULL;
1154 /* if the symbol has a spill */
1156 SPIL_LOC (op)->aop = NULL;
1161 /*------------------------------------------------------------------*/
1162 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
1163 /* pop r0 or r1 off stack if pushed */
1164 /*------------------------------------------------------------------*/
1166 freeForBranchAsmop (operand * op)
1178 if (!aop->allocated)
1186 emitcode ("mov", "r0,b");
1188 else if (_G.r0Pushed)
1190 emitcode ("pop", "ar0");
1197 emitcode ("mov", "r1,b");
1199 else if (_G.r1Pushed)
1201 emitcode ("pop", "ar1");
1208 int stk = aop->aopu.aop_stk + aop->size - 1;
1210 emitcode ("mov", "b,r0");
1213 emitcode ("mov", "a,_bp");
1214 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1215 emitcode ("mov", "r0,a");
1219 emitcode ("mov", "r0,_bp");
1224 emitcode ("pop", "acc");
1225 emitcode ("mov", "@r0,a");
1228 emitcode ("dec", "r0");
1230 emitcode ("mov", "r0,b");
1236 /*-----------------------------------------------------------------*/
1237 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
1238 /* clobber the accumulator */
1239 /*-----------------------------------------------------------------*/
1241 aopGetUsesAcc (operand * oper, int offset)
1243 asmop * aop = AOP (oper);
1245 if (offset > (aop->size - 1))
1263 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1274 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1280 /* Error case --- will have been caught already */
1286 /*-------------------------------------------------------------------*/
1287 /* aopGet - for fetching value of the aop */
1288 /*-------------------------------------------------------------------*/
1290 aopGet (operand * oper, int offset, bool bit16, bool dname)
1292 asmop * aop = AOP (oper);
1294 /* offset is greater than
1296 if (offset > (aop->size - 1) &&
1297 aop->type != AOP_LIT)
1300 /* depending on type */
1308 /* if we need to increment it */
1309 while (offset > aop->coff)
1311 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1315 while (offset < aop->coff)
1317 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1324 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1325 return (dname ? "acc" : "a");
1327 SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1328 return Safe_strdup(buffer);
1331 if (aop->code && aop->coff==0 && offset>=1) {
1332 emitcode ("mov", "a,#0x%02x", offset);
1333 emitcode ("movc", "a,@a+dptr");
1334 return (dname ? "acc" : "a");
1337 while (offset > aop->coff)
1339 emitcode ("inc", "dptr");
1343 while (offset < aop->coff)
1345 emitcode ("lcall", "__decdptr");
1352 emitcode ("clr", "a");
1353 emitcode ("movc", "a,@a+dptr");
1357 emitcode ("movx", "a,@dptr");
1359 return (dname ? "acc" : "a");
1362 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1364 SNPRINTF(buffer, sizeof(buffer),
1365 "%s",aop->aopu.aop_immd.aop_immd2);
1369 SNPRINTF(buffer, sizeof(buffer),
1370 "#%s", aop->aopu.aop_immd.aop_immd1);
1374 SNPRINTF (buffer, sizeof(buffer),
1376 aop->aopu.aop_immd.aop_immd1,
1381 SNPRINTF (buffer, sizeof(buffer),
1383 aop->aopu.aop_immd.aop_immd1);
1385 return Safe_strdup(buffer);
1388 if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
1390 SNPRINTF (buffer, sizeof(buffer),
1392 aop->aopu.aop_dir, offset * 8);
1396 SNPRINTF (buffer, sizeof(buffer),
1403 SNPRINTF (buffer, sizeof(buffer),
1408 return Safe_strdup(buffer);
1412 return aop->aopu.aop_reg[offset]->dname;
1414 return aop->aopu.aop_reg[offset]->name;
1417 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1418 emitcode ("clr", "a");
1419 emitcode ("rlc", "a");
1420 return (dname ? "acc" : "a");
1423 if (!offset && dname)
1425 return aop->aopu.aop_str[offset];
1428 return aopLiteral (aop->aopu.aop_lit, offset);
1432 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1436 return aop->aopu.aop_str[offset];
1440 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1441 "aopget got unsupported aop->type");
1445 /*-----------------------------------------------------------------*/
1446 /* aopPutUsesAcc - indicates ahead of time whether aopPut() will */
1447 /* clobber the accumulator */
1448 /*-----------------------------------------------------------------*/
1450 aopPutUsesAcc (operand * oper, const char *s, int offset)
1452 asmop * aop = AOP (oper);
1454 if (offset > (aop->size - 1))
1464 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1470 return ((aop->paged) || (*s == '@'));
1474 return (!aop->aopu.aop_dir || strcmp(s, aop->aopu.aop_dir));
1482 /* Error case --- will have been caught already */
1488 /*-----------------------------------------------------------------*/
1489 /* aopPut - puts a string for a aop and indicates if acc is in use */
1490 /*-----------------------------------------------------------------*/
1492 aopPut (operand * result, const char *s, int offset)
1494 bool bvolatile = isOperandVolatile (result, FALSE);
1495 bool accuse = FALSE;
1496 asmop * aop = AOP (result);
1497 const char *d = NULL;
1499 if (aop->size && offset > (aop->size - 1))
1501 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1502 "aopPut got offset > aop->size");
1506 /* will assign value to value */
1507 /* depending on where it is ofcourse */
1511 MOVA (s); /* read s in case it was volatile */
1516 if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1518 SNPRINTF (buffer, sizeof(buffer),
1520 aop->aopu.aop_dir, offset * 8);
1524 SNPRINTF (buffer, sizeof(buffer),
1526 aop->aopu.aop_dir, offset);
1530 SNPRINTF (buffer, sizeof(buffer),
1535 if (strcmp (buffer, s) || bvolatile)
1537 emitcode ("mov", "%s,%s", buffer, s);
1539 if (!strcmp (buffer, "acc"))
1546 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1547 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1550 strcmp (s, "r0") == 0 ||
1551 strcmp (s, "r1") == 0 ||
1552 strcmp (s, "r2") == 0 ||
1553 strcmp (s, "r3") == 0 ||
1554 strcmp (s, "r4") == 0 ||
1555 strcmp (s, "r5") == 0 ||
1556 strcmp (s, "r6") == 0 ||
1557 strcmp (s, "r7") == 0)
1559 emitcode ("mov", "%s,%s",
1560 aop->aopu.aop_reg[offset]->dname, s);
1564 emitcode ("mov", "%s,%s",
1565 aop->aopu.aop_reg[offset]->name, s);
1573 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1574 "aopPut writing to code space");
1578 while (offset > aop->coff)
1581 emitcode ("inc", "dptr");
1584 while (offset < aop->coff)
1587 emitcode ("lcall", "__decdptr");
1592 /* if not in accumulator */
1595 emitcode ("movx", "@dptr,a");
1600 while (offset > aop->coff)
1603 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1605 while (offset < aop->coff)
1608 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1615 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1620 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1622 else if (strcmp (s, "r0") == 0 ||
1623 strcmp (s, "r1") == 0 ||
1624 strcmp (s, "r2") == 0 ||
1625 strcmp (s, "r3") == 0 ||
1626 strcmp (s, "r4") == 0 ||
1627 strcmp (s, "r5") == 0 ||
1628 strcmp (s, "r6") == 0 ||
1629 strcmp (s, "r7") == 0)
1632 SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1633 emitcode ("mov", "@%s,%s",
1634 aop->aopu.aop_ptr->name, buffer);
1638 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1643 if (strcmp (s, "a") == 0)
1645 emitcode ("push", "acc");
1650 emitcode ("push", "acc");
1652 else if (strcmp (s, "r0") == 0 ||
1653 strcmp (s, "r1") == 0 ||
1654 strcmp (s, "r2") == 0 ||
1655 strcmp (s, "r3") == 0 ||
1656 strcmp (s, "r4") == 0 ||
1657 strcmp (s, "r5") == 0 ||
1658 strcmp (s, "r6") == 0 ||
1659 strcmp (s, "r7") == 0)
1662 SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1663 emitcode ("push", buffer);
1667 emitcode ("push", s);
1673 // destination is carry for return-use-only
1674 d = (IS_OP_RUONLY (result)) ? "c" : aop->aopu.aop_dir;
1675 // source is no literal and not in carry
1676 if ((s != zero) && (s != one) && strcmp (s, "c"))
1679 /* set C, if a >= 1 */
1680 emitcode ("add", "a,#0xff");
1683 // now source is zero, one or carry
1685 /* if result no bit variable */
1688 if (!strcmp (s, "c"))
1690 /* inefficient: move carry into A and use jz/jnz */
1691 emitcode ("clr", "a");
1692 emitcode ("rlc", "a");
1702 emitcode ("clr", "%s", d);
1704 emitcode ("setb", "%s", d);
1705 else if (strcmp (s, d))
1706 emitcode ("mov", "%s,c", d);
1711 if (strcmp (aop->aopu.aop_str[offset], s) || bvolatile)
1712 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1718 if (!offset && (strcmp (s, "acc") == 0) && !bvolatile)
1721 if (strcmp (aop->aopu.aop_str[offset], s) && !bvolatile)
1722 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1726 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1727 "aopPut got unsupported aop->type");
1736 /*-----------------------------------------------------------------*/
1737 /* pointToEnd :- points to the last byte of the operand */
1738 /*-----------------------------------------------------------------*/
1740 pointToEnd (asmop * aop)
1746 aop->coff = count = (aop->size - 1);
1752 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1756 emitcode ("inc", "dptr");
1763 /*-----------------------------------------------------------------*/
1764 /* reAdjustPreg - points a register back to where it should */
1765 /*-----------------------------------------------------------------*/
1767 reAdjustPreg (asmop * aop)
1769 if ((aop->coff==0) || (aop->size <= 1))
1777 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1782 emitcode ("lcall", "__decdptr");
1789 /*-----------------------------------------------------------------*/
1790 /* opIsGptr: returns non-zero if the passed operand is */
1791 /* a generic pointer type. */
1792 /*-----------------------------------------------------------------*/
1794 opIsGptr (operand * op)
1796 sym_link *type = operandType (op);
1798 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1805 /*-----------------------------------------------------------------*/
1806 /* getDataSize - get the operand data size */
1807 /*-----------------------------------------------------------------*/
1809 getDataSize (operand * op)
1812 size = AOP_SIZE (op);
1813 if (size == GPTRSIZE)
1815 sym_link *type = operandType (op);
1816 if (IS_GENPTR (type))
1818 /* generic pointer; arithmetic operations
1819 * should ignore the high byte (pointer type).
1827 /*-----------------------------------------------------------------*/
1828 /* outAcc - output Acc */
1829 /*-----------------------------------------------------------------*/
1831 outAcc (operand * result)
1834 size = getDataSize (result);
1837 aopPut (result, "a", 0);
1840 /* unsigned or positive */
1843 aopPut (result, zero, offset++);
1848 /*-----------------------------------------------------------------*/
1849 /* outBitC - output a bit C */
1850 /*-----------------------------------------------------------------*/
1852 outBitC (operand * result)
1854 /* if the result is bit */
1855 if (AOP_TYPE (result) == AOP_CRY)
1857 if (!IS_OP_RUONLY (result))
1858 aopPut (result, "c", 0);
1860 else if (AOP_TYPE (result) != AOP_DUMMY)
1862 emitcode ("clr", "a");
1863 emitcode ("rlc", "a");
1868 /*-----------------------------------------------------------------*/
1869 /* toBoolean - emit code for orl a,operator(sizeop) */
1870 /*-----------------------------------------------------------------*/
1872 toBoolean (operand * oper)
1874 int size = AOP_SIZE (oper) - 1;
1876 bool AccUsed = FALSE;
1879 while (!AccUsed && size--)
1881 AccUsed |= aopGetUsesAcc(oper, offset++);
1884 size = AOP_SIZE (oper) - 1;
1886 MOVA (aopGet (oper, 0, FALSE, FALSE));
1887 if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1890 emitcode("mov", "b,a");
1893 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1894 emitcode ("orl", "b,a");
1896 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1897 emitcode ("orl", "a,b");
1904 emitcode ("orl", "a,%s",
1905 aopGet (oper, offset++, FALSE, FALSE));
1910 /*-----------------------------------------------------------------*/
1911 /* toCarry - make boolean and move into carry */
1912 /*-----------------------------------------------------------------*/
1914 toCarry (operand * oper)
1916 /* if the operand is a literal then
1917 we know what the value is */
1918 if (AOP_TYPE (oper) == AOP_LIT)
1920 if ((int) operandLitValue (oper))
1925 else if (AOP_TYPE (oper) == AOP_CRY)
1927 emitcode ("mov", "c,%s", oper->aop->aopu.aop_dir);
1931 /* or the operand into a */
1933 /* set C, if a >= 1 */
1934 emitcode ("add", "a,#0xff");
1938 /*-----------------------------------------------------------------*/
1939 /* assignBit - assign operand to bit operand */
1940 /*-----------------------------------------------------------------*/
1942 assignBit (operand * result, operand * right)
1944 /* if the right side is a literal then
1945 we know what the value is */
1946 if (AOP_TYPE (right) == AOP_LIT)
1948 if ((int) operandLitValue (right))
1949 aopPut (result, one, 0);
1951 aopPut (result, zero, 0);
1956 aopPut (result, "c", 0);
1961 /*-------------------------------------------------------------------*/
1962 /* xch_a_aopGet - for exchanging acc with value of the aop */
1963 /*-------------------------------------------------------------------*/
1965 xch_a_aopGet (operand * oper, int offset, bool bit16, bool dname)
1969 if (aopGetUsesAcc (oper, offset))
1971 emitcode("mov", "b,a");
1972 MOVA (aopGet (oper, offset, bit16, dname));
1973 emitcode("xch", "a,b");
1974 aopPut (oper, "a", offset);
1975 emitcode("xch", "a,b");
1980 l = aopGet (oper, offset, bit16, dname);
1981 emitcode("xch", "a,%s", l);
1987 /*-----------------------------------------------------------------*/
1988 /* genNot - generate code for ! operation */
1989 /*-----------------------------------------------------------------*/
1995 D (emitcode (";", "genNot"));
1997 /* assign asmOps to operand & result */
1998 aopOp (IC_LEFT (ic), ic, FALSE);
1999 aopOp (IC_RESULT (ic), ic, TRUE);
2001 /* if in bit space then a special case */
2002 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2004 /* if left==result then cpl bit */
2005 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2007 emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2011 toCarry (IC_LEFT (ic));
2012 emitcode ("cpl", "c");
2013 outBitC (IC_RESULT (ic));
2018 toBoolean (IC_LEFT (ic));
2020 /* set C, if a == 0 */
2021 tlbl = newiTempLabel (NULL);
2022 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
2024 outBitC (IC_RESULT (ic));
2027 /* release the aops */
2028 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2029 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2033 /*-----------------------------------------------------------------*/
2034 /* genCpl - generate code for complement */
2035 /*-----------------------------------------------------------------*/
2042 sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
2044 D(emitcode (";", "genCpl"));
2046 /* assign asmOps to operand & result */
2047 aopOp (IC_LEFT (ic), ic, FALSE);
2048 aopOp (IC_RESULT (ic), ic, TRUE);
2050 /* special case if in bit space */
2051 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2055 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
2056 (SPEC_USIGN (letype) && IS_CHAR (letype)))
2058 /* promotion rules are responsible for this strange result:
2059 bit -> int -> ~int -> bit
2060 uchar -> int -> ~int -> bit
2062 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
2066 tlbl=newiTempLabel(NULL);
2067 l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
2068 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
2069 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
2070 IS_AOP_PREG (IC_LEFT (ic)))
2072 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
2077 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
2080 outBitC (IC_RESULT(ic));
2084 size = AOP_SIZE (IC_RESULT (ic));
2087 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2089 emitcode ("cpl", "a");
2090 aopPut (IC_RESULT (ic), "a", offset++);
2095 /* release the aops */
2096 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2097 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2100 /*-----------------------------------------------------------------*/
2101 /* genUminusFloat - unary minus for floating points */
2102 /*-----------------------------------------------------------------*/
2104 genUminusFloat (operand * op, operand * result)
2106 int size, offset = 0;
2109 D (emitcode (";", "genUminusFloat"));
2111 /* for this we just copy and then flip the bit */
2113 size = AOP_SIZE (op) - 1;
2118 aopGet (op, offset, FALSE, FALSE),
2123 l = aopGet (op, offset, FALSE, FALSE);
2126 emitcode ("cpl", "acc.7");
2127 aopPut (result, "a", offset);
2130 /*-----------------------------------------------------------------*/
2131 /* genUminus - unary minus code generation */
2132 /*-----------------------------------------------------------------*/
2134 genUminus (iCode * ic)
2139 D (emitcode (";", "genUminus"));
2142 aopOp (IC_LEFT (ic), ic, FALSE);
2143 aopOp (IC_RESULT (ic), ic, TRUE);
2145 /* if both in bit space then special
2147 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2148 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2151 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2152 emitcode ("cpl", "c");
2153 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2157 optype = operandType (IC_LEFT (ic));
2159 /* if float then do float stuff */
2160 if (IS_FLOAT (optype))
2162 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2166 /* otherwise subtract from zero */
2167 size = AOP_SIZE (IC_LEFT (ic));
2171 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2172 if (!strcmp (l, "a"))
2176 emitcode ("cpl", "a");
2177 emitcode ("addc", "a,#0");
2183 emitcode ("clr", "a");
2184 emitcode ("subb", "a,%s", l);
2186 aopPut (IC_RESULT (ic), "a", offset++);
2189 /* if any remaining bytes in the result */
2190 /* we just need to propagate the sign */
2191 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2193 emitcode ("rlc", "a");
2194 emitcode ("subb", "a,acc");
2196 aopPut (IC_RESULT (ic), "a", offset++);
2200 /* release the aops */
2201 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2202 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2205 /*-----------------------------------------------------------------*/
2206 /* saveRegisters - will look for a call and save the registers */
2207 /*-----------------------------------------------------------------*/
2209 saveRegisters (iCode * lic)
2216 for (ic = lic; ic; ic = ic->next)
2217 if (ic->op == CALL || ic->op == PCALL)
2222 fprintf (stderr, "found parameter push with no function call\n");
2226 /* if the registers have been saved already or don't need to be then
2230 if (IS_SYMOP(IC_LEFT(ic)) &&
2231 (IFFUNC_CALLEESAVES (OP_SYMBOL (IC_LEFT (ic))->type) ||
2232 IFFUNC_ISNAKED (OP_SYM_TYPE (IC_LEFT (ic)))))
2235 /* save the registers in use at this time but skip the
2236 ones for the result */
2237 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2238 mcs51_rUmaskForOp (IC_RESULT(ic)));
2241 if (options.useXstack)
2243 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2244 int nBits = bitVectnBitsOn (rsavebits);
2245 int count = bitVectnBitsOn (rsave);
2249 count = count - nBits + 1;
2250 /* remove all but the first bits as they are pushed all at once */
2251 rsave = bitVectCplAnd (rsave, rsavebits);
2252 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2254 freeBitVect (rsavebits);
2258 regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2259 if (reg->type == REG_BIT)
2261 emitcode ("mov", "a,%s", reg->base);
2265 emitcode ("mov", "a,%s", reg->name);
2267 emitcode ("mov", "r0,%s", spname);
2268 emitcode ("inc", "%s", spname);// allocate before use
2269 emitcode ("movx", "@r0,a");
2270 if (bitVectBitValue (rsave, R0_IDX))
2271 emitcode ("mov", "r0,a");
2273 else if (count != 0)
2275 if (bitVectBitValue (rsave, R0_IDX))
2277 emitcode ("push", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2279 emitcode ("mov", "r0,%s", spname);
2281 emitcode ("add", "a,#%d", count);
2282 emitcode ("mov", "%s,a", spname);
2283 for (i = 0; i < mcs51_nRegs; i++)
2285 if (bitVectBitValue (rsave, i))
2287 regs * reg = REG_WITH_INDEX (i);
2290 emitcode ("pop", "acc");
2291 emitcode ("push", "acc");
2293 else if (reg->type == REG_BIT)
2295 emitcode ("mov", "a,%s", reg->base);
2299 emitcode ("mov", "a,%s", reg->name);
2301 emitcode ("movx", "@r0,a");
2304 emitcode ("inc", "r0");
2308 if (bitVectBitValue (rsave, R0_IDX))
2310 emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2316 bool bits_pushed = FALSE;
2317 for (i = 0; i < mcs51_nRegs; i++)
2319 if (bitVectBitValue (rsave, i))
2321 bits_pushed = pushReg (i, bits_pushed);
2325 freeBitVect (rsave);
2328 /*-----------------------------------------------------------------*/
2329 /* unsaveRegisters - pop the pushed registers */
2330 /*-----------------------------------------------------------------*/
2332 unsaveRegisters (iCode * ic)
2337 /* restore the registers in use at this time but skip the
2338 ones for the result */
2339 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2340 mcs51_rUmaskForOp (IC_RESULT(ic)));
2342 if (options.useXstack)
2344 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2345 int nBits = bitVectnBitsOn (rsavebits);
2346 int count = bitVectnBitsOn (rsave);
2350 count = count - nBits + 1;
2351 /* remove all but the first bits as they are popped all at once */
2352 rsave = bitVectCplAnd (rsave, rsavebits);
2353 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2355 freeBitVect (rsavebits);
2359 regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2360 emitcode ("mov", "r0,%s", spname);
2361 emitcode ("dec", "r0");
2362 emitcode ("movx", "a,@r0");
2363 if (reg->type == REG_BIT)
2365 emitcode ("mov", "%s,a", reg->base);
2369 emitcode ("mov", "%s,a", reg->name);
2371 emitcode ("dec", "%s", spname);
2373 else if (count != 0)
2375 emitcode ("mov", "r0,%s", spname);
2376 for (i = mcs51_nRegs; i >= 0; i--)
2378 if (bitVectBitValue (rsave, i))
2380 regs * reg = REG_WITH_INDEX (i);
2381 emitcode ("dec", "r0");
2382 emitcode ("movx", "a,@r0");
2385 emitcode ("push", "acc");
2387 else if (reg->type == REG_BIT)
2389 emitcode ("mov", "%s,a", reg->base);
2393 emitcode ("mov", "%s,a", reg->name);
2397 emitcode ("mov", "%s,r0", spname);
2398 if (bitVectBitValue (rsave, R0_IDX))
2400 emitcode ("pop", "ar0");
2406 bool bits_popped = FALSE;
2407 for (i = mcs51_nRegs; i >= 0; i--)
2409 if (bitVectBitValue (rsave, i))
2411 bits_popped = popReg (i, bits_popped);
2415 freeBitVect (rsave);
2419 /*-----------------------------------------------------------------*/
2421 /*-----------------------------------------------------------------*/
2423 pushSide (operand * oper, int size, iCode * ic)
2426 int nPushed = _G.r0Pushed + _G.r1Pushed;
2428 aopOp (oper, ic, FALSE);
2430 if (nPushed != _G.r0Pushed + _G.r1Pushed)
2432 while (offset < size)
2434 char *l = aopGet (oper, offset, FALSE, TRUE);
2435 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2437 freeAsmop (oper, NULL, ic, TRUE);
2439 while (offset < size)
2441 emitcode ("push", "%s", fReturn[offset++]);
2448 char *l = aopGet (oper, offset++, FALSE, TRUE);
2449 if (AOP_TYPE (oper) != AOP_REG &&
2450 AOP_TYPE (oper) != AOP_DIR &&
2454 emitcode ("push", "acc");
2458 emitcode ("push", "%s", l);
2462 freeAsmop (oper, NULL, ic, TRUE);
2465 /*-----------------------------------------------------------------*/
2466 /* assignResultValue - also indicates if acc is in use afterwards */
2467 /*-----------------------------------------------------------------*/
2469 assignResultValue (operand * oper, operand * func)
2472 int size = AOP_SIZE (oper);
2473 bool accuse = FALSE;
2474 bool pushedA = FALSE;
2476 if (func && IS_BIT (OP_SYM_ETYPE (func)))
2482 if ((size > 3) && aopPutUsesAcc (oper, fReturn[offset], offset))
2484 emitcode ("push", "acc");
2489 if ((offset == 3) && pushedA)
2490 emitcode ("pop", "acc");
2491 accuse |= aopPut (oper, fReturn[offset], offset);
2498 /*-----------------------------------------------------------------*/
2499 /* genXpush - pushes onto the external stack */
2500 /*-----------------------------------------------------------------*/
2502 genXpush (iCode * ic)
2504 asmop *aop = newAsmop (0);
2506 int size, offset = 0;
2508 D (emitcode (";", "genXpush"));
2510 aopOp (IC_LEFT (ic), ic, FALSE);
2511 r = getFreePtr (ic, &aop, FALSE);
2513 size = AOP_SIZE (IC_LEFT (ic));
2517 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2518 emitcode ("mov", "%s,%s", r->name, spname);
2519 emitcode ("inc", "%s", spname); // allocate space first
2520 emitcode ("movx", "@%s,a", r->name);
2524 // allocate space first
2525 emitcode ("mov", "%s,%s", r->name, spname);
2527 emitcode ("add", "a,#%d", size);
2528 emitcode ("mov", "%s,a", spname);
2532 MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2533 emitcode ("movx", "@%s,a", r->name);
2534 emitcode ("inc", "%s", r->name);
2538 freeAsmop (NULL, aop, ic, TRUE);
2539 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2542 /*-----------------------------------------------------------------*/
2543 /* genIpush - generate code for pushing this gets a little complex */
2544 /*-----------------------------------------------------------------*/
2546 genIpush (iCode * ic)
2548 int size, offset = 0;
2552 D (emitcode (";", "genIpush"));
2554 /* if this is not a parm push : ie. it is spill push
2555 and spill push is always done on the local stack */
2559 /* and the item is spilt then do nothing */
2560 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2563 aopOp (IC_LEFT (ic), ic, FALSE);
2564 size = AOP_SIZE (IC_LEFT (ic));
2565 /* push it on the stack */
2568 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2574 emitcode ("push", "%s", l);
2579 /* this is a parameter push: in this case we call
2580 the routine to find the call and save those
2581 registers that need to be saved */
2584 /* if use external stack then call the external
2585 stack pushing routine */
2586 if (options.useXstack)
2592 /* then do the push */
2593 aopOp (IC_LEFT (ic), ic, FALSE);
2595 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2596 size = AOP_SIZE (IC_LEFT (ic));
2600 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2601 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2602 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR)
2604 if (strcmp (l, prev) || *l == '@')
2606 emitcode ("push", "acc");
2610 emitcode ("push", "%s", l);
2615 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2618 /*-----------------------------------------------------------------*/
2619 /* genIpop - recover the registers: can happen only for spilling */
2620 /*-----------------------------------------------------------------*/
2622 genIpop (iCode * ic)
2626 D (emitcode (";", "genIpop"));
2628 /* if the temp was not pushed then */
2629 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2632 aopOp (IC_LEFT (ic), ic, FALSE);
2633 size = AOP_SIZE (IC_LEFT (ic));
2634 offset = (size - 1);
2637 emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2641 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2644 /*-----------------------------------------------------------------*/
2645 /* saveRBank - saves an entire register bank on the stack */
2646 /*-----------------------------------------------------------------*/
2648 saveRBank (int bank, iCode * ic, bool pushPsw)
2651 int count = 8 + (pushPsw ? 1 : 0);
2655 if (options.useXstack)
2659 /* Assume r0 is available for use. */
2660 r = REG_WITH_INDEX (R0_IDX);
2665 r = getFreePtr (ic, &aop, FALSE);
2667 // allocate space first
2668 emitcode ("mov", "%s,%s", r->name, spname);
2670 emitcode ("add", "a,#%d", count);
2671 emitcode ("mov", "%s,a", spname);
2674 for (i = 0; i < 8; i++)
2676 if (options.useXstack)
2678 emitcode ("mov", "a,(%s+%d)",
2679 regs8051[i].base, 8 * bank + regs8051[i].offset);
2680 emitcode ("movx", "@%s,a", r->name);
2682 emitcode ("inc", "%s", r->name);
2685 emitcode ("push", "(%s+%d)",
2686 regs8051[i].base, 8 * bank + regs8051[i].offset);
2691 if (options.useXstack)
2693 emitcode ("mov", "a,psw");
2694 emitcode ("movx", "@%s,a", r->name);
2698 emitcode ("push", "psw");
2701 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2706 freeAsmop (NULL, aop, ic, TRUE);
2715 /*-----------------------------------------------------------------*/
2716 /* unsaveRBank - restores the register bank from stack */
2717 /*-----------------------------------------------------------------*/
2719 unsaveRBank (int bank, iCode * ic, bool popPsw)
2725 if (options.useXstack)
2729 /* Assume r0 is available for use. */
2730 r = REG_WITH_INDEX (R0_IDX);;
2735 r = getFreePtr (ic, &aop, FALSE);
2737 emitcode ("mov", "%s,%s", r->name, spname);
2742 if (options.useXstack)
2744 emitcode ("dec", "%s", r->name);
2745 emitcode ("movx", "a,@%s", r->name);
2746 emitcode ("mov", "psw,a");
2750 emitcode ("pop", "psw");
2754 for (i = 7; i >= 0; i--)
2756 if (options.useXstack)
2758 emitcode ("dec", "%s", r->name);
2759 emitcode ("movx", "a,@%s", r->name);
2760 emitcode ("mov", "(%s+%d),a",
2761 regs8051[i].base, 8 * bank + regs8051[i].offset);
2765 emitcode ("pop", "(%s+%d)",
2766 regs8051[i].base, 8 * bank + regs8051[i].offset);
2770 if (options.useXstack)
2772 emitcode ("mov", "%s,%s", spname, r->name);
2777 freeAsmop (NULL, aop, ic, TRUE);
2781 /*-----------------------------------------------------------------*/
2782 /* genSend - gen code for SEND */
2783 /*-----------------------------------------------------------------*/
2784 static void genSend(set *sendSet)
2789 /* first we do all bit parameters */
2790 for (sic = setFirstItem (sendSet); sic;
2791 sic = setNextItem (sendSet))
2793 if (sic->argreg > 12)
2795 int bit = sic->argreg-13;
2797 aopOp (IC_LEFT (sic), sic, FALSE);
2799 /* if left is a literal then
2800 we know what the value is */
2801 if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2803 if (((int) operandLitValue (IC_LEFT (sic))))
2804 emitcode ("setb", "b[%d]", bit);
2806 emitcode ("clr", "b[%d]", bit);
2811 toCarry (IC_LEFT (sic));
2812 emitcode ("mov", "b[%d],c", bit);
2817 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2823 saveRegisters (setFirstItem (sendSet));
2824 emitcode ("mov", "bits,b");
2827 /* then we do all other parameters */
2828 for (sic = setFirstItem (sendSet); sic;
2829 sic = setNextItem (sendSet))
2831 if (sic->argreg <= 12)
2833 int size, offset = 0;
2834 aopOp (IC_LEFT (sic), sic, FALSE);
2835 size = AOP_SIZE (IC_LEFT (sic));
2837 if (sic->argreg == 1)
2841 char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2842 if (strcmp (l, fReturn[offset]))
2844 emitcode ("mov", "%s,%s", fReturn[offset], l);
2853 emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2854 aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2858 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2863 /*-----------------------------------------------------------------*/
2864 /* selectRegBank - emit code to select the register bank */
2865 /*-----------------------------------------------------------------*/
2867 selectRegBank (short bank, bool keepFlags)
2869 /* if f.e. result is in carry */
2872 emitcode ("anl", "psw,#0xE7");
2874 emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2878 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2882 /*-----------------------------------------------------------------*/
2883 /* genCall - generates a call statement */
2884 /*-----------------------------------------------------------------*/
2886 genCall (iCode * ic)
2890 // bool restoreBank = FALSE;
2891 bool swapBanks = FALSE;
2892 bool accuse = FALSE;
2893 bool accPushed = FALSE;
2894 bool resultInF0 = FALSE;
2895 bool assignResultGenerated = FALSE;
2897 D (emitcode (";", "genCall"));
2899 dtype = operandType (IC_LEFT (ic));
2900 etype = getSpec(dtype);
2901 /* if send set is not empty then assign */
2904 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2905 genSend(reverseSet(_G.sendSet));
2907 genSend(_G.sendSet);
2912 /* if we are calling a not _naked function that is not using
2913 the same register bank then we need to save the
2914 destination registers on the stack */
2915 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2916 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2917 !IFFUNC_ISISR (dtype))
2922 /* if caller saves & we have not saved then */
2928 emitcode ("mov", "psw,#0x%02x",
2929 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2933 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2935 if (IFFUNC_CALLEESAVES(dtype))
2937 werror (E_BANKED_WITH_CALLEESAVES);
2941 char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2942 OP_SYMBOL (IC_LEFT (ic))->rname :
2943 OP_SYMBOL (IC_LEFT (ic))->name);
2945 emitcode ("mov", "r0,#%s", l);
2946 emitcode ("mov", "r1,#(%s >> 8)", l);
2947 emitcode ("mov", "r2,#(%s >> 16)", l);
2948 emitcode ("lcall", "__sdcc_banked_call");
2953 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2954 OP_SYMBOL (IC_LEFT (ic))->rname :
2955 OP_SYMBOL (IC_LEFT (ic))->name));
2960 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2963 /* if we need assign a result value */
2964 if ((IS_ITEMP (IC_RESULT (ic)) &&
2965 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2966 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2967 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2968 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2969 IS_TRUE_SYMOP (IC_RESULT (ic)))
2973 aopOp (IC_RESULT (ic), ic, FALSE);
2976 accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2977 assignResultGenerated = TRUE;
2979 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2982 /* adjust the stack for parameters if required */
2986 if (ic->parmBytes > 3)
2990 emitcode ("push", "acc");
2993 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2994 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2995 !assignResultGenerated)
2997 emitcode ("mov", "F0,c");
3001 emitcode ("mov", "a,%s", spname);
3002 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3003 emitcode ("mov", "%s,a", spname);
3005 /* unsaveRegisters from xstack needs acc, but */
3006 /* unsaveRegisters from stack needs this popped */
3007 if (accPushed && !options.useXstack)
3009 emitcode ("pop", "acc");
3014 for (i = 0; i < ic->parmBytes; i++)
3015 emitcode ("dec", "%s", spname);
3018 /* if we had saved some registers then unsave them */
3019 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3021 if (accuse && !accPushed && options.useXstack)
3023 /* xstack needs acc, but doesn't touch normal stack */
3024 emitcode ("push", "acc");
3027 unsaveRegisters (ic);
3030 // /* if register bank was saved then pop them */
3032 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
3034 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
3037 emitcode ("mov", "c,F0");
3039 aopOp (IC_RESULT (ic), ic, FALSE);
3040 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3041 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3045 emitcode ("pop", "acc");
3048 /*-----------------------------------------------------------------*/
3049 /* genPcall - generates a call by pointer statement */
3050 /*-----------------------------------------------------------------*/
3052 genPcall (iCode * ic)
3056 symbol *rlbl = newiTempLabel (NULL);
3057 // bool restoreBank=FALSE;
3058 bool swapBanks = FALSE;
3059 bool resultInF0 = FALSE;
3061 D (emitcode (";", "genPcall"));
3063 dtype = operandType (IC_LEFT (ic))->next;
3064 etype = getSpec(dtype);
3065 /* if caller saves & we have not saved then */
3069 /* if we are calling a not _naked function that is not using
3070 the same register bank then we need to save the
3071 destination registers on the stack */
3072 if (currFunc && dtype && !IFFUNC_ISNAKED (dtype) &&
3073 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
3074 !IFFUNC_ISISR (dtype))
3076 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3077 // restoreBank=TRUE;
3079 // need caution message to user here
3082 if (IS_LITERAL (etype))
3084 /* if send set is not empty then assign */
3087 genSend(reverseSet(_G.sendSet));
3093 emitcode ("mov", "psw,#0x%02x",
3094 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3097 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT (getSpec(dtype)))
3099 if (IFFUNC_CALLEESAVES (dtype))
3101 werror (E_BANKED_WITH_CALLEESAVES);
3105 char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
3107 emitcode ("mov", "r0,#%s", l);
3108 emitcode ("mov", "r1,#(%s >> 8)", l);
3109 emitcode ("mov", "r2,#(%s >> 16)", l);
3110 emitcode ("lcall", "__sdcc_banked_call");
3115 emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
3120 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT (getSpec(dtype)))
3122 if (IFFUNC_CALLEESAVES (dtype))
3124 werror (E_BANKED_WITH_CALLEESAVES);
3128 aopOp (IC_LEFT (ic), ic, FALSE);
3132 /* what if aopGet needs r0 or r1 ??? */
3133 emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3134 emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3135 emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3139 int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
3140 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3141 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3142 emitcode ("mov", "0x%02x,%s", reg, aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3145 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3147 /* if send set is not empty then assign */
3150 genSend(reverseSet(_G.sendSet));
3156 emitcode ("mov", "psw,#0x%02x",
3157 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3161 emitcode ("lcall", "__sdcc_banked_call");
3164 else if (_G.sendSet)
3166 /* push the return address on to the stack */
3167 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
3168 emitcode ("push", "acc");
3169 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
3170 emitcode ("push", "acc");
3172 /* now push the calling address */
3173 pushSide (IC_LEFT (ic), FPTRSIZE, ic);
3175 /* if send set is not empty then assign */
3178 genSend(reverseSet(_G.sendSet));
3184 emitcode ("mov", "psw,#0x%02x",
3185 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3189 emitcode ("ret", "");
3192 else /* the send set is empty */
3195 /* now get the calling address into dptr */
3196 aopOp (IC_LEFT (ic), ic, FALSE);
3198 l = aopGet (IC_LEFT (ic), 0, FALSE, FALSE);
3199 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3201 emitcode ("mov", "r0,%s", l);
3202 l = aopGet (IC_LEFT (ic), 1, FALSE, FALSE);
3203 emitcode ("mov", "dph,%s", l);
3204 emitcode ("mov", "dpl,r0");
3208 emitcode ("mov", "dpl,%s", l);
3209 l = aopGet (IC_LEFT (ic), 1, FALSE, FALSE);
3210 emitcode ("mov", "dph,%s", l);
3213 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3217 emitcode ("mov", "psw,#0x%02x",
3218 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3222 emitcode ("lcall", "__sdcc_call_dptr");
3227 selectRegBank (FUNC_REGBANK (currFunc->type), IS_BIT (etype));
3230 /* if we need assign a result value */
3231 if ((IS_ITEMP (IC_RESULT (ic)) &&
3232 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3233 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3234 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3235 IS_TRUE_SYMOP (IC_RESULT (ic)))
3239 aopOp (IC_RESULT (ic), ic, FALSE);
3242 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3244 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3247 /* adjust the stack for parameters if required */
3251 if (ic->parmBytes > 3)
3253 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3254 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3256 emitcode ("mov", "F0,c");
3260 emitcode ("mov", "a,%s", spname);
3261 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3262 emitcode ("mov", "%s,a", spname);
3265 for (i = 0; i < ic->parmBytes; i++)
3266 emitcode ("dec", "%s", spname);
3269 // /* if register bank was saved then unsave them */
3271 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3273 /* if we had saved some registers then unsave them */
3274 if (ic->regsSaved && !IFFUNC_CALLEESAVES (dtype))
3275 unsaveRegisters (ic);
3277 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3280 emitcode ("mov", "c,F0");
3282 aopOp (IC_RESULT (ic), ic, FALSE);
3283 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3284 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3288 /*-----------------------------------------------------------------*/
3289 /* resultRemat - result is rematerializable */
3290 /*-----------------------------------------------------------------*/
3292 resultRemat (iCode * ic)
3294 if (SKIP_IC (ic) || ic->op == IFX)
3297 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3299 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3300 if (sym->remat && !POINTER_SET (ic))
3307 /*-----------------------------------------------------------------*/
3308 /* inExcludeList - return 1 if the string is in exclude Reg list */
3309 /*-----------------------------------------------------------------*/
3311 regsCmp(void *p1, void *p2)
3313 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3317 inExcludeList (char *s)
3319 const char *p = setFirstItem(options.excludeRegsSet);
3321 if (p == NULL || STRCASECMP(p, "none") == 0)
3325 return isinSetWith(options.excludeRegsSet, s, regsCmp);
3328 /*-----------------------------------------------------------------*/
3329 /* genFunction - generated code for function entry */
3330 /*-----------------------------------------------------------------*/
3332 genFunction (iCode * ic)
3334 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3336 bool switchedPSW = FALSE;
3337 int calleesaves_saved_register = -1;
3338 int stackAdjust = sym->stack;
3339 int accIsFree = sym->recvSize < 4;
3340 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3341 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3344 /* create the function header */
3345 emitcode (";", "-----------------------------------------");
3346 emitcode (";", " function %s", sym->name);
3347 emitcode (";", "-----------------------------------------");
3349 emitcode ("", "%s:", sym->rname);
3350 lineCurr->isLabel = 1;
3351 ftype = operandType (IC_LEFT (ic));
3352 _G.currentFunc = sym;
3354 if (IFFUNC_ISNAKED(ftype))
3356 emitcode(";", "naked function: no prologue.");
3360 /* here we need to generate the equates for the
3361 register bank if required */
3362 if (FUNC_REGBANK (ftype) != rbank)
3366 rbank = FUNC_REGBANK (ftype);
3367 for (i = 0; i < mcs51_nRegs; i++)
3369 if (regs8051[i].type != REG_BIT)
3371 if (strcmp (regs8051[i].base, "0") == 0)
3372 emitcode ("", "%s = 0x%02x",
3374 8 * rbank + regs8051[i].offset);
3376 emitcode ("", "%s = %s + 0x%02x",
3379 8 * rbank + regs8051[i].offset);
3384 /* if this is an interrupt service routine then
3385 save acc, b, dpl, dph */
3386 if (IFFUNC_ISISR (sym->type))
3390 rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), sym->regsUsed);
3391 if (IFFUNC_HASFCALL(sym->type) || !bitVectIsZero (rsavebits))
3393 emitcode ("push", "bits");
3396 freeBitVect (rsavebits);
3398 if (!inExcludeList ("acc"))
3399 emitcode ("push", "acc");
3400 if (!inExcludeList ("b"))
3401 emitcode ("push", "b");
3402 if (!inExcludeList ("dpl"))
3403 emitcode ("push", "dpl");
3404 if (!inExcludeList ("dph"))
3405 emitcode ("push", "dph");
3406 /* if this isr has no bank i.e. is going to
3407 run with bank 0 , then we need to save more
3409 if (!FUNC_REGBANK (sym->type))
3413 /* if this function does not call any other
3414 function then we can be economical and
3415 save only those registers that are used */
3416 if (!IFFUNC_HASFCALL(sym->type))
3418 /* if any registers used */
3421 /* save the registers used */
3422 for (i = 0; i < sym->regsUsed->size; i++)
3424 if (bitVectBitValue (sym->regsUsed, i))
3431 /* this function has a function call. We cannot
3432 determine register usage so we will have to push the
3434 saveRBank (0, ic, FALSE);
3435 if (options.parms_in_bank1) {
3436 for (i=0; i < 8 ; i++ ) {
3437 emitcode ("push","%s",rb1regs[i]);
3444 /* This ISR uses a non-zero bank.
3446 * We assume that the bank is available for our
3449 * However, if this ISR calls a function which uses some
3450 * other bank, we must save that bank entirely.
3452 unsigned long banksToSave = 0;
3454 if (IFFUNC_HASFCALL(sym->type))
3457 #define MAX_REGISTER_BANKS 4
3462 for (i = ic; i; i = i->next)
3464 if (i->op == ENDFUNCTION)
3466 /* we got to the end OK. */
3474 dtype = operandType (IC_LEFT(i));
3476 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3478 /* Mark this bank for saving. */
3479 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3481 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3485 banksToSave |= (1 << FUNC_REGBANK(dtype));
3488 /* And note that we don't need to do it in
3496 /* This is a mess; we have no idea what
3497 * register bank the called function might
3500 * The only thing I can think of to do is
3501 * throw a warning and hope.
3503 werror(W_FUNCPTR_IN_USING_ISR);
3507 if (banksToSave && options.useXstack)
3509 /* Since we aren't passing it an ic,
3510 * saveRBank will assume r0 is available to abuse.
3512 * So switch to our (trashable) bank now, so
3513 * the caller's R0 isn't trashed.
3515 emitcode ("push", "psw");
3516 emitcode ("mov", "psw,#0x%02x",
3517 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3521 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3523 if (banksToSave & (1 << ix))
3525 saveRBank(ix, NULL, FALSE);
3529 // TODO: this needs a closer look
3530 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3533 /* Set the register bank to the desired value if nothing else */
3534 /* has done so yet. */
3537 emitcode ("push", "psw");
3538 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3543 /* This is a non-ISR function. The caller has already switched register */
3544 /* banks, if necessary, so just handle the callee-saves option. */
3546 /* if callee-save to be used for this function
3547 then save the registers being used in this function */
3548 if (IFFUNC_CALLEESAVES(sym->type))
3552 /* if any registers used */
3555 bool bits_pushed = FALSE;
3556 /* save the registers used */
3557 for (i = 0; i < sym->regsUsed->size; i++)
3559 if (bitVectBitValue (sym->regsUsed, i))
3561 /* remember one saved register for later usage */
3562 if (calleesaves_saved_register < 0)
3563 calleesaves_saved_register = i;
3564 bits_pushed = pushReg (i, bits_pushed);
3574 if (options.useXstack)
3576 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3578 emitcode ("mov", "r0,%s", spname);
3579 emitcode ("inc", "%s", spname);
3580 emitcode ("xch", "a,_bpx");
3581 emitcode ("movx", "@r0,a");
3582 emitcode ("inc", "r0");
3583 emitcode ("mov", "a,r0");
3584 emitcode ("xch", "a,_bpx");
3588 emitcode ("push", "_bp"); /* save the callers stack */
3589 emitcode ("mov", "_bp,sp");
3594 if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3596 /* set up the stack */
3597 emitcode ("push", "_bp"); /* save the callers stack */
3598 emitcode ("mov", "_bp,sp");
3603 /* For some cases it is worthwhile to perform a RECEIVE iCode */
3604 /* before setting up the stack frame completely. */
3605 if (ric && ric->argreg == 1 && IC_RESULT (ric))
3607 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3611 if (rsym && rsym->regType == REG_CND)
3613 if (rsym && (rsym->accuse || rsym->ruonly))
3615 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3616 rsym = rsym->usl.spillLoc;
3619 /* If the RECEIVE operand immediately spills to the first entry on the */
3620 /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3621 /* rather than the usual @r0/r1 machinations. */
3622 if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3626 _G.current_iCode = ric;
3627 D(emitcode (";", "genReceive"));
3628 for (ofs=0; ofs < sym->recvSize; ofs++)
3630 if (!strcmp (fReturn[ofs], "a"))
3631 emitcode ("push", "acc");
3633 emitcode ("push", fReturn[ofs]);
3635 stackAdjust -= sym->recvSize;
3638 assert (stackAdjust>=0);
3641 _G.current_iCode = ic;
3645 /* If the RECEIVE operand is 4 registers, we can do the moves now */
3646 /* to free up the accumulator. */
3647 else if (rsym && rsym->nRegs && sym->recvSize == 4)
3651 _G.current_iCode = ric;
3652 D(emitcode (";", "genReceive"));
3653 for (ofs=0; ofs < sym->recvSize; ofs++)
3655 emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3657 _G.current_iCode = ic;
3663 /* adjust the stack for the function */
3666 int i = stackAdjust;
3668 werror (W_STACK_OVERFLOW, sym->name);
3670 if (i > 3 && accIsFree)
3672 emitcode ("mov", "a,sp");
3673 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3674 emitcode ("mov", "sp,a");
3678 /* The accumulator is not free, so we will need another register */
3679 /* to clobber. No need to worry about a possible conflict with */
3680 /* the above early RECEIVE optimizations since they would have */
3681 /* freed the accumulator if they were generated. */
3683 if (IFFUNC_CALLEESAVES(sym->type))
3685 /* if it's a callee-saves function we need a saved register */
3686 if (calleesaves_saved_register >= 0)
3688 emitcode ("mov", "%s,a", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3689 emitcode ("mov", "a,sp");
3690 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3691 emitcode ("mov", "sp,a");
3692 emitcode ("mov", "a,%s", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3695 /* do it the hard way */
3697 emitcode ("inc", "sp");
3701 /* not callee-saves, we can clobber r0 */
3702 emitcode ("mov", "r0,a");
3703 emitcode ("mov", "a,sp");
3704 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3705 emitcode ("mov", "sp,a");
3706 emitcode ("mov", "a,r0");
3711 emitcode ("inc", "sp");
3716 char i = ((char) sym->xstack & 0xff);
3718 if (i > 3 && accIsFree)
3720 emitcode ("mov", "a,_spx");
3721 emitcode ("add", "a,#0x%02x", i & 0xff);
3722 emitcode ("mov", "_spx,a");
3726 emitcode ("push", "acc");
3727 emitcode ("mov", "a,_spx");
3728 emitcode ("add", "a,#0x%02x", i & 0xff);
3729 emitcode ("mov", "_spx,a");
3730 emitcode ("pop", "acc");
3735 emitcode ("inc", "_spx");
3739 /* if critical function then turn interrupts off */
3740 if (IFFUNC_ISCRITICAL (ftype))
3742 symbol *tlbl = newiTempLabel (NULL);
3743 emitcode ("setb", "c");
3744 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3745 emitcode ("clr", "c");
3747 emitcode ("push", "psw"); /* save old ea via c in psw */
3751 /*-----------------------------------------------------------------*/
3752 /* genEndFunction - generates epilogue for functions */
3753 /*-----------------------------------------------------------------*/
3755 genEndFunction (iCode * ic)
3757 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3758 lineNode *lnp = lineCurr;
3760 bitVect *regsUsedPrologue;
3761 bitVect *regsUnneeded;
3764 _G.currentFunc = NULL;
3765 if (IFFUNC_ISNAKED(sym->type))
3767 emitcode(";", "naked function: no epilogue.");
3768 if (options.debug && currFunc)
3769 debugFile->writeEndFunction (currFunc, ic, 0);
3773 if (IFFUNC_ISCRITICAL (sym->type))
3775 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3777 emitcode ("rlc", "a"); /* save c in a */
3778 emitcode ("pop", "psw"); /* restore ea via c in psw */
3779 emitcode ("mov", "ea,c");
3780 emitcode ("rrc", "a"); /* restore c from a */
3784 emitcode ("pop", "psw"); /* restore ea via c in psw */
3785 emitcode ("mov", "ea,c");
3789 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3791 if (options.useXstack)
3795 emitcode ("mov", "sp,_bp");
3796 emitcode ("pop", "_bp");
3798 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3800 emitcode ("xch", "a,_bpx");
3801 emitcode ("mov", "r0,a");
3802 emitcode ("dec", "r0");
3803 emitcode ("movx", "a,@r0");
3804 emitcode ("xch", "a,_bpx");
3805 emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3808 else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3811 emitcode ("mov", "sp,_bp");
3812 emitcode ("pop", "_bp");
3816 /* restore the register bank */
3817 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3819 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3820 || !options.useXstack)
3822 /* Special case of ISR using non-zero bank with useXstack
3825 emitcode ("pop", "psw");
3829 if (IFFUNC_ISISR (sym->type))
3833 /* now we need to restore the registers */
3834 /* if this isr has no bank i.e. is going to
3835 run with bank 0 , then we need to save more
3837 if (!FUNC_REGBANK (sym->type))
3840 /* if this function does not call any other
3841 function then we can be economical and
3842 save only those registers that are used */
3843 if (!IFFUNC_HASFCALL(sym->type))
3845 /* if any registers used */
3848 /* save the registers used */
3849 for (i = sym->regsUsed->size; i >= 0; i--)
3851 if (bitVectBitValue (sym->regsUsed, i))
3858 if (options.parms_in_bank1) {
3859 for (i = 7 ; i >= 0 ; i-- ) {
3860 emitcode ("pop","%s",rb1regs[i]);
3863 /* this function has a function call. We cannot
3864 determine register usage so we will have to pop the
3866 unsaveRBank (0, ic, FALSE);
3871 /* This ISR uses a non-zero bank.
3873 * Restore any register banks saved by genFunction
3876 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3879 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3881 if (savedBanks & (1 << ix))
3883 unsaveRBank(ix, NULL, FALSE);
3887 if (options.useXstack)
3889 /* Restore bank AFTER calling unsaveRBank,
3890 * since it can trash r0.
3892 emitcode ("pop", "psw");
3896 if (!inExcludeList ("dph"))
3897 emitcode ("pop", "dph");
3898 if (!inExcludeList ("dpl"))
3899 emitcode ("pop", "dpl");
3900 if (!inExcludeList ("b"))
3901 emitcode ("pop", "b");
3902 if (!inExcludeList ("acc"))
3903 emitcode ("pop", "acc");
3905 rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), sym->regsUsed);
3906 if (IFFUNC_HASFCALL(sym->type) || !bitVectIsZero (rsavebits))
3907 emitcode ("pop", "bits");
3908 freeBitVect (rsavebits);
3910 /* if debug then send end of function */
3911 if (options.debug && currFunc)
3913 debugFile->writeEndFunction (currFunc, ic, 1);
3916 emitcode ("reti", "");
3920 if (IFFUNC_CALLEESAVES(sym->type))
3924 /* if any registers used */
3927 /* save the registers used */
3928 for (i = sym->regsUsed->size; i >= 0; i--)
3930 if (bitVectBitValue (sym->regsUsed, i) ||
3931 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3932 emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
3935 else if (mcs51_ptrRegReq)
3937 emitcode ("pop", "%s", REG_WITH_INDEX (R1_IDX)->dname);
3938 emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
3943 /* if debug then send end of function */
3944 if (options.debug && currFunc)
3946 debugFile->writeEndFunction (currFunc, ic, 1);
3949 if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3951 emitcode ("ljmp", "__sdcc_banked_ret");
3955 emitcode ("ret", "");
3959 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3962 /* If this was an interrupt handler using bank 0 that called another */
3963 /* function, then all registers must be saved; nothing to optimized. */
3964 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3965 && !FUNC_REGBANK(sym->type))
3968 /* There are no push/pops to optimize if not callee-saves or ISR */
3969 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3972 /* If there were stack parameters, we cannot optimize without also */
3973 /* fixing all of the stack offsets; this is too dificult to consider. */
3974 if (FUNC_HASSTACKPARM(sym->type))
3977 /* Compute the registers actually used */
3978 regsUsed = newBitVect (mcs51_nRegs);
3979 regsUsedPrologue = newBitVect (mcs51_nRegs);
3982 if (lnp->ic && lnp->ic->op == FUNCTION)
3983 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3985 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3987 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3988 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3995 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3996 && !bitVectBitValue (regsUsed, CND_IDX))
3998 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3999 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
4000 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
4001 bitVectUnSetBit (regsUsed, CND_IDX);
4004 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
4006 /* If this was an interrupt handler that called another function */
4007 /* function, then assume A, B, DPH, & DPL may be modified by it. */
4008 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
4010 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
4011 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
4012 regsUsed = bitVectSetBit (regsUsed, B_IDX);
4013 regsUsed = bitVectSetBit (regsUsed, A_IDX);
4014 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
4017 /* Remove the unneeded push/pops */
4018 regsUnneeded = newBitVect (mcs51_nRegs);
4021 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
4023 if (!strncmp(lnp->line, "push", 4))
4025 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
4026 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4028 connectLine (lnp->prev, lnp->next);
4029 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4032 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
4034 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
4035 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4037 connectLine (lnp->prev, lnp->next);
4038 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4045 for (idx = 0; idx < regsUnneeded->size; idx++)
4046 if (bitVectBitValue (regsUnneeded, idx))
4047 emitcode (";", "eliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
4049 freeBitVect (regsUnneeded);
4050 freeBitVect (regsUsed);
4051 freeBitVect (regsUsedPrologue);
4054 /*-----------------------------------------------------------------*/
4055 /* genRet - generate code for return statement */
4056 /*-----------------------------------------------------------------*/
4060 int size, offset = 0, pushed = 0;
4062 D (emitcode (";", "genRet"));
4064 /* if we have no return value then
4065 just generate the "ret" */
4069 /* we have something to return then
4070 move the return value into place */
4071 aopOp (IC_LEFT (ic), ic, FALSE);
4072 size = AOP_SIZE (IC_LEFT (ic));
4074 if (IS_BIT(_G.currentFunc->etype))
4076 if (!IS_OP_RUONLY (IC_LEFT (ic)))
4077 toCarry (IC_LEFT (ic));
4084 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
4087 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
4088 emitcode ("push", "%s", l);
4093 l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
4094 if (strcmp (fReturn[offset], l))
4095 emitcode ("mov", "%s,%s", fReturn[offset++], l);
4102 if (strcmp (fReturn[pushed], "a"))
4103 emitcode ("pop", fReturn[pushed]);
4105 emitcode ("pop", "acc");
4108 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
4111 /* generate a jump to the return label
4112 if the next is not the return statement */
4113 if (!(ic->next && ic->next->op == LABEL &&
4114 IC_LABEL (ic->next) == returnLabel))
4116 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
4120 /*-----------------------------------------------------------------*/
4121 /* genLabel - generates a label */
4122 /*-----------------------------------------------------------------*/
4124 genLabel (iCode * ic)
4126 /* special case never generate */
4127 if (IC_LABEL (ic) == entryLabel)
4130 emitLabel (IC_LABEL (ic));
4133 /*-----------------------------------------------------------------*/
4134 /* genGoto - generates a ljmp */
4135 /*-----------------------------------------------------------------*/
4137 genGoto (iCode * ic)
4139 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
4142 /*-----------------------------------------------------------------*/
4143 /* findLabelBackwards: walks back through the iCode chain looking */
4144 /* for the given label. Returns number of iCode instructions */
4145 /* between that label and given ic. */
4146 /* Returns zero if label not found. */
4147 /*-----------------------------------------------------------------*/
4149 findLabelBackwards (iCode * ic, int key)
4158 /* If we have any pushes or pops, we cannot predict the distance.
4159 I don't like this at all, this should be dealt with in the
4161 if (ic->op == IPUSH || ic->op == IPOP) {
4165 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4174 /*-----------------------------------------------------------------*/
4175 /* genPlusIncr :- does addition with increment if possible */
4176 /*-----------------------------------------------------------------*/
4178 genPlusIncr (iCode * ic)
4180 unsigned int icount;
4181 unsigned int size = getDataSize (IC_RESULT (ic));
4183 /* will try to generate an increment */
4184 /* if the right side is not a literal
4186 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4189 icount = (unsigned int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4191 D(emitcode (";","genPlusIncr"));
4193 /* if increment >=16 bits in register or direct space */
4194 if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG ||
4195 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4196 (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4197 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4198 !isOperandVolatile (IC_RESULT (ic), FALSE) &&
4206 /* If the next instruction is a goto and the goto target
4207 * is < 10 instructions previous to this, we can generate
4208 * jumps straight to that target.
4210 if (ic->next && ic->next->op == GOTO
4211 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4212 && labelRange <= 10)
4214 D (emitcode (";", "tail increment optimized (range %d)", labelRange));
4215 tlbl = IC_LABEL (ic->next);
4220 tlbl = newiTempLabel (NULL);
4223 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4224 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4225 IS_AOP_PREG (IC_RESULT (ic)))
4226 emitcode ("cjne", "%s,#0x00,%05d$",
4227 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4231 emitcode ("clr", "a");
4232 emitcode ("cjne", "a,%s,%05d$",
4233 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4237 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4240 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4241 IS_AOP_PREG (IC_RESULT (ic)))
4242 emitcode ("cjne", "%s,#0x00,%05d$",
4243 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4246 emitcode ("cjne", "a,%s,%05d$",
4247 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4250 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4254 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4255 IS_AOP_PREG (IC_RESULT (ic)))
4256 emitcode ("cjne", "%s,#0x00,%05d$",
4257 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4261 emitcode ("cjne", "a,%s,%05d$",
4262 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4265 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4275 /* if result is dptr */
4276 if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
4277 (AOP_SIZE (IC_RESULT (ic)) == 2) &&
4278 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
4279 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
4281 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4287 if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
4290 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0);
4291 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1);
4293 emitcode ("inc", "dptr");
4298 /* if the literal value of the right hand side
4299 is greater than 4 then it is not worth it */
4303 /* if the sizes are greater than 1 then we cannot */
4304 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4305 AOP_SIZE (IC_LEFT (ic)) > 1)
4308 /* we can if the aops of the left & result match or
4309 if they are in registers and the registers are the
4311 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4315 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4316 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4317 aopPut (IC_RESULT (ic), "a", 0);
4323 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4332 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4333 emitcode ("inc", "a");
4334 aopPut (IC_RESULT (ic), "a", 0);
4341 /*-----------------------------------------------------------------*/
4342 /* outBitAcc - output a bit in acc */
4343 /*-----------------------------------------------------------------*/
4345 outBitAcc (operand * result)
4347 symbol *tlbl = newiTempLabel (NULL);
4348 /* if the result is a bit */
4349 if (AOP_TYPE (result) == AOP_CRY)
4351 aopPut (result, "a", 0);
4355 emitcode ("jz", "%05d$", tlbl->key + 100);
4356 emitcode ("mov", "a,%s", one);
4362 /*-----------------------------------------------------------------*/
4363 /* genPlusBits - generates code for addition of two bits */
4364 /*-----------------------------------------------------------------*/
4366 genPlusBits (iCode * ic)
4368 D (emitcode (";", "genPlusBits"));
4370 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4371 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4373 symbol *lbl = newiTempLabel (NULL);
4374 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4375 emitcode ("cpl", "c");
4377 outBitC (IC_RESULT (ic));
4381 emitcode ("clr", "a");
4382 emitcode ("rlc", "a");
4383 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4384 emitcode ("addc", "a,%s", zero);
4385 outAcc (IC_RESULT (ic));
4390 /* This is the original version of this code.
4392 * This is being kept around for reference,
4393 * because I am not entirely sure I got it right...
4396 adjustArithmeticResult (iCode * ic)
4398 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4399 AOP_SIZE (IC_LEFT (ic)) == 3 &&
4400 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4401 aopPut (IC_RESULT (ic),
4402 aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4405 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4406 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4407 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4408 aopPut (IC_RESULT (ic),
4409 aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4412 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4413 AOP_SIZE (IC_LEFT (ic)) < 3 &&
4414 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4415 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4416 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4419 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4420 aopPut (IC_RESULT (ic), buffer, 2);
4424 /* This is the pure and virtuous version of this code.
4425 * I'm pretty certain it's right, but not enough to toss the old
4429 adjustArithmeticResult (iCode * ic)
4431 if (opIsGptr (IC_RESULT (ic)) &&
4432 opIsGptr (IC_LEFT (ic)) &&
4433 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4435 aopPut (IC_RESULT (ic),
4436 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4440 if (opIsGptr (IC_RESULT (ic)) &&
4441 opIsGptr (IC_RIGHT (ic)) &&
4442 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4444 aopPut (IC_RESULT (ic),
4445 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4449 if (opIsGptr (IC_RESULT (ic)) &&
4450 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4451 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4452 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4453 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4456 SNPRINTF (buffer, sizeof(buffer),
4457 "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4458 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4463 /*-----------------------------------------------------------------*/
4464 /* genPlus - generates code for addition */
4465 /*-----------------------------------------------------------------*/
4467 genPlus (iCode * ic)
4469 int size, offset = 0;
4472 bool swappedLR = FALSE;
4473 operand *leftOp, *rightOp;
4476 D (emitcode (";", "genPlus"));
4478 /* special cases :- */
4480 aopOp (IC_LEFT (ic), ic, FALSE);
4481 aopOp (IC_RIGHT (ic), ic, FALSE);
4482 aopOp (IC_RESULT (ic), ic, TRUE);
4484 /* if literal, literal on the right or
4485 if left requires ACC or right is already
4487 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4488 (AOP_NEEDSACC (IC_LEFT (ic))) ||
4489 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4491 operand *t = IC_RIGHT (ic);
4492 IC_RIGHT (ic) = IC_LEFT (ic);
4497 /* if both left & right are in bit
4499 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4500 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4506 /* if left in bit space & right literal */
4507 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4508 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4510 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4511 /* if result in bit space */
4512 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4514 if (ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4515 emitcode ("cpl", "c");
4516 outBitC (IC_RESULT (ic));
4520 size = getDataSize (IC_RESULT (ic));
4523 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4524 emitcode ("addc", "a,%s", zero);
4525 aopPut (IC_RESULT (ic), "a", offset++);
4531 /* if I can do an increment instead
4532 of add then GOOD for ME */
4533 if (genPlusIncr (ic) == TRUE)
4536 size = getDataSize (IC_RESULT (ic));
4537 leftOp = IC_LEFT(ic);
4538 rightOp = IC_RIGHT(ic);
4541 /* if this is an add for an array access
4542 at a 256 byte boundary */
4544 && AOP_TYPE (op) == AOP_IMMD
4546 && IS_SPEC (OP_SYM_ETYPE (op))
4547 && SPEC_ABSA (OP_SYM_ETYPE (op))
4548 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4551 D(emitcode (";", "genPlus aligned array"));
4552 aopPut (IC_RESULT (ic),
4553 aopGet (rightOp, 0, FALSE, FALSE),
4556 if( 1 == getDataSize (IC_RIGHT (ic)) )
4558 aopPut (IC_RESULT (ic),
4559 aopGet (leftOp, 1, FALSE, FALSE),
4564 MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4565 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4566 aopPut (IC_RESULT (ic), "a", 1);
4571 /* if the lower bytes of a literal are zero skip the addition */
4572 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4574 while ((0 == ((unsigned int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4575 (skip_bytes+1 < size))
4580 D(emitcode (";", "genPlus shortcut"));
4585 if( offset >= skip_bytes )
4587 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4590 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4592 emitcode("xch", "a,b");
4593 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4594 emitcode (add, "a,b");
4597 else if (aopGetUsesAcc (leftOp, offset))
4599 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4600 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4604 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4605 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4607 aopPut (IC_RESULT (ic), "a", offset);
4608 add = "addc"; /* further adds must propagate carry */
4612 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4613 isOperandVolatile (IC_RESULT (ic), FALSE))
4616 aopPut (IC_RESULT (ic),
4617 aopGet (leftOp, offset, FALSE, FALSE),
4624 adjustArithmeticResult (ic);
4627 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4630 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4631 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4635 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4636 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4640 /*-----------------------------------------------------------------*/
4641 /* genMinusDec :- does subtraction with decrement if possible */
4642 /*-----------------------------------------------------------------*/
4644 genMinusDec (iCode * ic)
4646 unsigned int icount;
4647 unsigned int size = getDataSize (IC_RESULT (ic));
4649 /* will try to generate an increment */
4650 /* if the right side is not a literal
4652 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4655 /* if the literal value of the right hand side
4656 is greater than 4 then it is not worth it */
4657 if ((icount = (unsigned int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4660 D (emitcode (";", "genMinusDec"));
4662 /* if decrement >=16 bits in register or direct space */
4663 if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG ||
4664 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4665 (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4666 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4674 /* If the next instruction is a goto and the goto target
4675 * is <= 10 instructions previous to this, we can generate
4676 * jumps straight to that target.
4678 if (ic->next && ic->next->op == GOTO
4679 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4680 && labelRange <= 10)
4682 D (emitcode (";", "tail decrement optimized (range %d)", labelRange));
4683 tlbl = IC_LABEL (ic->next);
4688 tlbl = newiTempLabel (NULL);
4692 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4693 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4694 IS_AOP_PREG (IC_RESULT (ic)))
4695 emitcode ("cjne", "%s,#0xff,%05d$"
4696 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4700 emitcode ("mov", "a,#0xff");
4701 emitcode ("cjne", "a,%s,%05d$"
4702 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4705 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4708 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4709 IS_AOP_PREG (IC_RESULT (ic)))
4710 emitcode ("cjne", "%s,#0xff,%05d$"
4711 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4715 emitcode ("cjne", "a,%s,%05d$"
4716 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4719 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4723 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4724 IS_AOP_PREG (IC_RESULT (ic)))
4725 emitcode ("cjne", "%s,#0xff,%05d$"
4726 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4730 emitcode ("cjne", "a,%s,%05d$"
4731 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4734 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4743 /* if the sizes are greater than 1 then we cannot */
4744 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4745 AOP_SIZE (IC_LEFT (ic)) > 1)
4748 /* we can if the aops of the left & result match or
4749 if they are in registers and the registers are the
4751 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4755 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4757 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4762 l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
4767 emitcode ("dec", "%s", l);
4770 if (AOP_NEEDSACC (IC_RESULT (ic)))
4771 aopPut (IC_RESULT (ic), "a", 0);
4778 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4779 emitcode ("dec", "a");
4780 aopPut (IC_RESULT (ic), "a", 0);
4787 /*-----------------------------------------------------------------*/
4788 /* addSign - complete with sign */
4789 /*-----------------------------------------------------------------*/
4791 addSign (operand * result, int offset, int sign)
4793 int size = (getDataSize (result) - offset);
4798 emitcode ("rlc", "a");
4799 emitcode ("subb", "a,acc");
4802 aopPut (result, "a", offset++);
4809 aopPut (result, zero, offset++);
4815 /*-----------------------------------------------------------------*/
4816 /* genMinusBits - generates code for subtraction of two bits */
4817 /*-----------------------------------------------------------------*/
4819 genMinusBits (iCode * ic)
4821 symbol *lbl = newiTempLabel (NULL);
4823 D (emitcode (";", "genMinusBits"));
4825 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4827 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4828 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4829 emitcode ("cpl", "c");
4831 outBitC (IC_RESULT (ic));
4835 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4836 emitcode ("subb", "a,acc");
4837 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4838 emitcode ("inc", "a");
4840 aopPut (IC_RESULT (ic), "a", 0);
4841 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4845 /*-----------------------------------------------------------------*/
4846 /* genMinus - generates code for subtraction */
4847 /*-----------------------------------------------------------------*/
4849 genMinus (iCode * ic)
4851 int size, offset = 0;
4853 D (emitcode (";", "genMinus"));
4855 aopOp (IC_LEFT (ic), ic, FALSE);
4856 aopOp (IC_RIGHT (ic), ic, FALSE);
4857 aopOp (IC_RESULT (ic), ic, TRUE);
4859 /* special cases :- */
4860 /* if both left & right are in bit space */
4861 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4862 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4868 /* if I can do an decrement instead
4869 of subtract then GOOD for ME */
4870 if (genMinusDec (ic) == TRUE)
4873 size = getDataSize (IC_RESULT (ic));
4875 /* if literal, add a,#-lit, else normal subb */
4876 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4878 unsigned long lit = 0L;
4879 bool useCarry = FALSE;
4881 lit = ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4886 if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4888 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4889 if (!offset && !size && lit== (unsigned long) -1)
4891 emitcode ("dec", "a");
4895 /* first add without previous c */
4896 emitcode ("add", "a,#0x%02x",
4897 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4902 emitcode ("addc", "a,#0x%02x",
4903 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4905 aopPut (IC_RESULT (ic), "a", offset++);
4909 /* no need to add zeroes */
4910 if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4912 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4921 operand *leftOp, *rightOp;
4923 leftOp = IC_LEFT(ic);
4924 rightOp = IC_RIGHT(ic);
4928 if (aopGetUsesAcc(rightOp, offset)) {
4929 if (aopGetUsesAcc(leftOp, offset)) {
4932 MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4934 emitcode ("mov", "b,a");
4937 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4938 emitcode ("subb", "a,b");
4941 /* reverse subtraction with 2's complement */
4943 emitcode( "setb", "c");
4945 emitcode( "cpl", "c");
4946 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4947 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4948 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4949 emitcode("cpl", "a");
4950 if (size) /* skip if last byte */
4951 emitcode( "cpl", "c");
4954 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4957 emitcode ("subb", "a,%s",
4958 aopGet(rightOp, offset, FALSE, TRUE));
4961 aopPut (IC_RESULT (ic), "a", offset++);
4965 adjustArithmeticResult (ic);
4968 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4969 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4970 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4974 /*-----------------------------------------------------------------*/
4975 /* genMultbits :- multiplication of bits */
4976 /*-----------------------------------------------------------------*/
4978 genMultbits (operand * left,
4982 D (emitcode (";", "genMultbits"));
4984 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4985 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4989 /*-----------------------------------------------------------------*/
4990 /* genMultOneByte : 8*8=8/16 bit multiplication */
4991 /*-----------------------------------------------------------------*/
4993 genMultOneByte (operand * left,
4998 int size = AOP_SIZE (result);
4999 bool runtimeSign, compiletimeSign;
5000 bool lUnsigned, rUnsigned, pushedB;
5002 D (emitcode (";", "genMultOneByte"));
5004 if (size < 1 || size > 2)
5006 /* this should never happen */
5007 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
5008 AOP_SIZE(result), __FILE__, lineno);
5012 /* (if two literals: the value is computed before) */
5013 /* if one literal, literal on the right */
5014 if (AOP_TYPE (left) == AOP_LIT)
5019 /* emitcode (";", "swapped left and right"); */
5021 /* if no literal, unsigned on the right: shorter code */
5022 if ( AOP_TYPE (right) != AOP_LIT
5023 && SPEC_USIGN (getSpec (operandType (left))))
5030 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5031 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5035 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
5036 no need to take care about the signedness! */
5037 || (lUnsigned && rUnsigned))
5039 /* just an unsigned 8 * 8 = 8 multiply
5041 /* emitcode (";","unsigned"); */
5042 /* TODO: check for accumulator clash between left & right aops? */
5044 if (AOP_TYPE (right) == AOP_LIT)
5046 /* moving to accumulator first helps peepholes */
5047 MOVA (aopGet (left, 0, FALSE, FALSE));
5048 MOVB (aopGet (right, 0, FALSE, FALSE));
5052 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5053 MOVA (aopGet (left, 0, FALSE, FALSE));
5056 emitcode ("mul", "ab");
5057 aopPut (result, "a", 0);
5059 aopPut (result, "b", 1);
5065 /* we have to do a signed multiply */
5066 /* emitcode (";", "signed"); */
5068 /* now sign adjust for both left & right */
5070 /* let's see what's needed: */
5071 /* apply negative sign during runtime */
5072 runtimeSign = FALSE;
5073 /* negative sign from literals */
5074 compiletimeSign = FALSE;
5078 if (AOP_TYPE(left) == AOP_LIT)
5080 /* signed literal */
5081 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5083 compiletimeSign = TRUE;
5086 /* signed but not literal */
5092 if (AOP_TYPE(right) == AOP_LIT)
5094 /* signed literal */
5095 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
5097 compiletimeSign ^= TRUE;
5100 /* signed but not literal */
5104 /* initialize F0, which stores the runtime sign */
5107 if (compiletimeSign)
5108 emitcode ("setb", "F0"); /* set sign flag */
5110 emitcode ("clr", "F0"); /* reset sign flag */
5113 /* save the signs of the operands */
5114 if (AOP_TYPE(right) == AOP_LIT)
5116 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
5118 if (!rUnsigned && val < 0)
5119 emitcode ("mov", "b,#0x%02x", -val);
5121 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5123 else /* ! literal */
5125 if (rUnsigned) /* emitcode (";", "signed"); */
5126 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5129 MOVA (aopGet (right, 0, FALSE, FALSE));
5130 lbl = newiTempLabel (NULL);
5131 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5132 emitcode ("cpl", "F0"); /* complement sign flag */
5133 emitcode ("cpl", "a"); /* 2's complement */
5134 emitcode ("inc", "a");
5136 emitcode ("mov", "b,a");
5140 if (AOP_TYPE(left) == AOP_LIT)
5142 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5144 if (!lUnsigned && val < 0)
5145 emitcode ("mov", "a,#0x%02x", -val);
5147 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5149 else /* ! literal */
5151 MOVA (aopGet (left, 0, FALSE, FALSE));
5155 lbl = newiTempLabel (NULL);
5156 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5157 emitcode ("cpl", "F0"); /* complement sign flag */
5158 emitcode ("cpl", "a"); /* 2's complement */
5159 emitcode ("inc", "a");
5164 /* now the multiplication */
5165 emitcode ("mul", "ab");
5166 if (runtimeSign || compiletimeSign)
5168 lbl = newiTempLabel (NULL);
5170 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5171 emitcode ("cpl", "a"); /* lsb 2's complement */
5173 emitcode ("inc", "a"); /* inc doesn't set carry flag */
5176 emitcode ("add", "a,#1"); /* this sets carry flag */
5177 emitcode ("xch", "a,b");
5178 emitcode ("cpl", "a"); /* msb 2's complement */
5179 emitcode ("addc", "a,#0");
5180 emitcode ("xch", "a,b");
5184 aopPut (result, "a", 0);
5186 aopPut (result, "b", 1);
5191 /*-----------------------------------------------------------------*/
5192 /* genMult - generates code for multiplication */
5193 /*-----------------------------------------------------------------*/
5195 genMult (iCode * ic)
5197 operand *left = IC_LEFT (ic);
5198 operand *right = IC_RIGHT (ic);
5199 operand *result = IC_RESULT (ic);
5201 D (emitcode (";", "genMult"));
5203 /* assign the asmops */
5204 aopOp (left, ic, FALSE);
5205 aopOp (right, ic, FALSE);
5206 aopOp (result, ic, TRUE);
5208 /* special cases first */
5210 if (AOP_TYPE (left) == AOP_CRY &&
5211 AOP_TYPE (right) == AOP_CRY)
5213 genMultbits (left, right, result);
5217 /* if both are of size == 1 */
5218 #if 0 // one of them can be a sloc shared with the result
5219 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
5221 if (getSize(operandType(left)) == 1 &&
5222 getSize(operandType(right)) == 1)
5225 genMultOneByte (left, right, result);
5229 /* should have been converted to function call */
5230 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
5231 getSize(OP_SYMBOL(right)->type));
5235 freeAsmop (result, NULL, ic, TRUE);
5236 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5237 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5240 /*-----------------------------------------------------------------*/
5241 /* genDivbits :- division of bits */
5242 /*-----------------------------------------------------------------*/
5244 genDivbits (operand * left,
5251 D(emitcode (";", "genDivbits"));
5255 /* the result must be bit */
5256 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5257 l = aopGet (left, 0, FALSE, FALSE);
5261 emitcode ("div", "ab");
5262 emitcode ("rrc", "a");
5266 aopPut (result, "c", 0);
5269 /*-----------------------------------------------------------------*/
5270 /* genDivOneByte : 8 bit division */
5271 /*-----------------------------------------------------------------*/
5273 genDivOneByte (operand * left,
5277 bool lUnsigned, rUnsigned, pushedB;
5278 bool runtimeSign, compiletimeSign;
5279 bool accuse = FALSE;
5280 bool pushedA = FALSE;
5284 D(emitcode (";", "genDivOneByte"));
5286 /* Why is it necessary that genDivOneByte() can return an int result?
5289 volatile unsigned char uc;
5290 volatile signed char sc1, sc2;
5303 In all cases a one byte result would overflow, the following cast to int
5304 would return the wrong result.
5306 Two possible solution:
5307 a) cast operands to int, if ((unsigned) / (signed)) or
5308 ((signed) / (signed))
5309 b) return an 16 bit signed int; this is what we're doing here!
5312 size = AOP_SIZE (result) - 1;
5314 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5315 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5319 /* signed or unsigned */
5320 if (lUnsigned && rUnsigned)
5322 /* unsigned is easy */
5323 MOVB (aopGet (right, 0, FALSE, FALSE));
5324 MOVA (aopGet (left, 0, FALSE, FALSE));
5325 emitcode ("div", "ab");
5326 aopPut (result, "a", 0);
5328 aopPut (result, zero, offset++);
5334 /* signed is a little bit more difficult */
5336 /* now sign adjust for both left & right */
5338 /* let's see what's needed: */
5339 /* apply negative sign during runtime */
5340 runtimeSign = FALSE;
5341 /* negative sign from literals */
5342 compiletimeSign = FALSE;
5346 if (AOP_TYPE(left) == AOP_LIT)
5348 /* signed literal */
5349 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5351 compiletimeSign = TRUE;
5354 /* signed but not literal */
5360 if (AOP_TYPE(right) == AOP_LIT)
5362 /* signed literal */
5363 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
5365 compiletimeSign ^= TRUE;
5368 /* signed but not literal */
5372 /* initialize F0, which stores the runtime sign */
5375 if (compiletimeSign)
5376 emitcode ("setb", "F0"); /* set sign flag */
5378 emitcode ("clr", "F0"); /* reset sign flag */
5381 /* save the signs of the operands */
5382 if (AOP_TYPE(right) == AOP_LIT)
5384 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
5386 if (!rUnsigned && val < 0)
5387 emitcode ("mov", "b,#0x%02x", -val);
5389 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5391 else /* ! literal */
5394 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5397 MOVA (aopGet (right, 0, FALSE, FALSE));
5398 lbl = newiTempLabel (NULL);
5399 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5400 emitcode ("cpl", "F0"); /* complement sign flag */
5401 emitcode ("cpl", "a"); /* 2's complement */
5402 emitcode ("inc", "a");
5404 emitcode ("mov", "b,a");
5408 if (AOP_TYPE(left) == AOP_LIT)
5410 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5412 if (!lUnsigned && val < 0)
5413 emitcode ("mov", "a,#0x%02x", -val);
5415 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5417 else /* ! literal */
5419 MOVA (aopGet (left, 0, FALSE, FALSE));
5423 lbl = newiTempLabel (NULL);
5424 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5425 emitcode ("cpl", "F0"); /* complement sign flag */
5426 emitcode ("cpl", "a"); /* 2's complement */
5427 emitcode ("inc", "a");
5432 /* now the division */
5433 emitcode ("div", "ab");
5435 if (runtimeSign || compiletimeSign)
5437 lbl = newiTempLabel (NULL);
5439 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5440 emitcode ("cpl", "a"); /* lsb 2's complement */
5441 emitcode ("inc", "a");
5444 accuse = aopPut (result, "a", 0);
5447 /* msb is 0x00 or 0xff depending on the sign */
5452 emitcode ("push", "acc");
5455 emitcode ("mov", "c,F0");
5456 emitcode ("subb", "a,acc");
5458 aopPut (result, "a", offset++);
5460 else /* compiletimeSign */
5462 if (aopPutUsesAcc (result, "#0xFF", offset))
5464 emitcode ("push", "acc");
5468 aopPut (result, "#0xff", offset++);
5474 aopPut (result, "a", 0);
5476 aopPut (result, zero, offset++);
5480 emitcode ("pop", "acc");
5484 /*-----------------------------------------------------------------*/
5485 /* genDiv - generates code for division */
5486 /*-----------------------------------------------------------------*/
5490 operand *left = IC_LEFT (ic);
5491 operand *right = IC_RIGHT (ic);
5492 operand *result = IC_RESULT (ic);
5494 D (emitcode (";", "genDiv"));
5496 /* assign the asmops */
5497 aopOp (left, ic, FALSE);
5498 aopOp (right, ic, FALSE);
5499 aopOp (result, ic, TRUE);
5501 /* special cases first */
5503 if (AOP_TYPE (left) == AOP_CRY &&
5504 AOP_TYPE (right) == AOP_CRY)
5506 genDivbits (left, right, result);
5510 /* if both are of size == 1 */
5511 if (AOP_SIZE (left) == 1 &&
5512 AOP_SIZE (right) == 1)
5514 genDivOneByte (left, right, result);
5518 /* should have been converted to function call */
5521 freeAsmop (result, NULL, ic, TRUE);
5522 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5523 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5526 /*-----------------------------------------------------------------*/
5527 /* genModbits :- modulus of bits */
5528 /*-----------------------------------------------------------------*/
5530 genModbits (operand * left,
5537 D (emitcode (";", "genModbits"));
5541 /* the result must be bit */
5542 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5543 l = aopGet (left, 0, FALSE, FALSE);
5547 emitcode ("div", "ab");
5548 emitcode ("mov", "a,b");
5549 emitcode ("rrc", "a");
5553 aopPut (result, "c", 0);
5556 /*-----------------------------------------------------------------*/
5557 /* genModOneByte : 8 bit modulus */
5558 /*-----------------------------------------------------------------*/
5560 genModOneByte (operand * left,
5564 bool lUnsigned, rUnsigned, pushedB;
5565 bool runtimeSign, compiletimeSign;
5569 D (emitcode (";", "genModOneByte"));
5571 size = AOP_SIZE (result) - 1;
5573 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5574 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5576 /* if right is a literal, check it for 2^n */
5577 if (AOP_TYPE(right) == AOP_LIT)
5579 unsigned char val = abs((int) operandLitValue(right));
5580 symbol *lbl2 = NULL;
5584 case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5593 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5594 "modulus of unsigned char by 2^n literal shouldn't be processed here");
5595 /* because iCode should have been changed to genAnd */
5596 /* see file "SDCCopt.c", function "convertToFcall()" */
5598 MOVA (aopGet (left, 0, FALSE, FALSE));
5599 emitcode ("mov", "c,acc.7");
5600 emitcode ("anl", "a,#0x%02x", val - 1);
5601 lbl = newiTempLabel (NULL);
5602 emitcode ("jz", "%05d$", (lbl->key + 100));
5603 emitcode ("jnc", "%05d$", (lbl->key + 100));
5604 emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5610 aopPut (result, "a", 0);
5612 aopPut (result, "#0xff", offs2++);
5613 lbl2 = newiTempLabel (NULL);
5614 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5617 aopPut (result, "a", 0);
5619 aopPut (result, zero, offset++);
5633 /* signed or unsigned */
5634 if (lUnsigned && rUnsigned)
5636 /* unsigned is easy */
5637 MOVB (aopGet (right, 0, FALSE, FALSE));
5638 MOVA (aopGet (left, 0, FALSE, FALSE));
5639 emitcode ("div", "ab");
5640 aopPut (result, "b", 0);
5642 aopPut (result, zero, offset++);
5648 /* signed is a little bit more difficult */
5650 /* now sign adjust for both left & right */
5652 /* modulus: sign of the right operand has no influence on the result! */
5653 if (AOP_TYPE(right) == AOP_LIT)
5655 signed char val = (char) operandLitValue(right);
5657 if (!rUnsigned && val < 0)
5658 emitcode ("mov", "b,#0x%02x", -val);
5660 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5662 else /* not literal */
5665 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5668 MOVA (aopGet (right, 0, FALSE, FALSE));
5669 lbl = newiTempLabel (NULL);
5670 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5671 emitcode ("cpl", "a"); /* 2's complement */
5672 emitcode ("inc", "a");
5674 emitcode ("mov", "b,a");
5678 /* let's see what's needed: */
5679 /* apply negative sign during runtime */
5680 runtimeSign = FALSE;
5681 /* negative sign from literals */
5682 compiletimeSign = FALSE;
5684 /* sign adjust left side */
5685 if (AOP_TYPE(left) == AOP_LIT)
5687 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5689 if (!lUnsigned && val < 0)
5691 compiletimeSign = TRUE; /* set sign flag */
5692 emitcode ("mov", "a,#0x%02x", -val);
5695 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5697 else /* ! literal */
5699 MOVA (aopGet (left, 0, FALSE, FALSE));
5704 emitcode ("clr", "F0"); /* clear sign flag */
5706 lbl = newiTempLabel (NULL);
5707 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5708 emitcode ("setb", "F0"); /* set sign flag */
5709 emitcode ("cpl", "a"); /* 2's complement */
5710 emitcode ("inc", "a");
5715 /* now the modulus */
5716 emitcode ("div", "ab");
5718 if (runtimeSign || compiletimeSign)
5720 emitcode ("mov", "a,b");
5721 lbl = newiTempLabel (NULL);
5723 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5724 emitcode ("cpl", "a"); /* 2's complement */
5725 emitcode ("inc", "a");
5728 aopPut (result, "a", 0);
5731 /* msb is 0x00 or 0xff depending on the sign */
5734 emitcode ("mov", "c,F0");
5735 emitcode ("subb", "a,acc");
5737 aopPut (result, "a", offset++);
5739 else /* compiletimeSign */
5741 aopPut (result, "#0xff", offset++);
5746 aopPut (result, "b", 0);
5748 aopPut (result, zero, offset++);
5754 /*-----------------------------------------------------------------*/
5755 /* genMod - generates code for division */
5756 /*-----------------------------------------------------------------*/
5760 operand *left = IC_LEFT (ic);
5761 operand *right = IC_RIGHT (ic);
5762 operand *result = IC_RESULT (ic);
5764 D (emitcode (";", "genMod"));
5766 /* assign the asmops */
5767 aopOp (left, ic, FALSE);
5768 aopOp (right, ic, FALSE);
5769 aopOp (result, ic, TRUE);
5771 /* special cases first */
5773 if (AOP_TYPE (left) == AOP_CRY &&
5774 AOP_TYPE (right) == AOP_CRY)
5776 genModbits (left, right, result);
5780 /* if both are of size == 1 */
5781 if (AOP_SIZE (left) == 1 &&
5782 AOP_SIZE (right) == 1)
5784 genModOneByte (left, right, result);
5788 /* should have been converted to function call */
5792 freeAsmop (result, NULL, ic, TRUE);
5793 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5794 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5797 /*-----------------------------------------------------------------*/
5798 /* genIfxJump :- will create a jump depending on the ifx */
5799 /*-----------------------------------------------------------------*/
5801 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5804 symbol *tlbl = newiTempLabel (NULL);
5807 D (emitcode (";", "genIfxJump"));
5809 /* if true label then we jump if condition
5813 jlbl = IC_TRUE (ic);
5814 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5815 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5819 /* false label is present */
5820 jlbl = IC_FALSE (ic);
5821 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5822 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5824 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5825 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5827 emitcode (inst, "%05d$", tlbl->key + 100);
5828 freeForBranchAsmop (result);
5829 freeForBranchAsmop (right);
5830 freeForBranchAsmop (left);
5831 emitcode ("ljmp", "%05d$", jlbl->key + 100);
5834 /* mark the icode as generated */
5838 /*-----------------------------------------------------------------*/
5839 /* genCmp :- greater or less than comparison */
5840 /*-----------------------------------------------------------------*/
5842 genCmp (operand * left, operand * right,
5843 operand * result, iCode * ifx, int sign, iCode *ic)
5845 int size, offset = 0;
5846 unsigned long lit = 0L;
5849 D (emitcode (";", "genCmp"));
5851 /* if left & right are bit variables */
5852 if (AOP_TYPE (left) == AOP_CRY &&
5853 AOP_TYPE (right) == AOP_CRY)
5855 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5856 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5860 /* subtract right from left if at the
5861 end the carry flag is set then we know that
5862 left is greater than right */
5863 size = max (AOP_SIZE (left), AOP_SIZE (right));
5865 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5866 if ((size == 1) && !sign &&
5867 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5869 symbol *lbl = newiTempLabel (NULL);
5870 emitcode ("cjne", "%s,%s,%05d$",
5871 aopGet (left, offset, FALSE, FALSE),
5872 aopGet (right, offset, FALSE, FALSE),
5878 if (AOP_TYPE (right) == AOP_LIT)
5880 lit = ulFromVal (AOP (right)->aopu.aop_lit);
5881 /* optimize if(x < 0) or if(x >= 0) */
5890 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5891 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5893 genIfxJump (ifx, "acc.7", left, right, result);
5894 freeAsmop (right, NULL, ic, TRUE);
5895 freeAsmop (left, NULL, ic, TRUE);
5901 emitcode ("rlc", "a");
5908 int bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5909 while (size && (bytelit == 0))
5912 bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5918 MOVA (aopGet (left, offset, FALSE, FALSE));
5919 if (sign && size == 0)
5921 emitcode ("xrl", "a,#0x80");
5922 emitcode ("subb", "a,#0x%02x",
5923 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5927 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5937 bool pushedB = FALSE;
5938 rightInB = aopGetUsesAcc(right, offset);
5942 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5944 MOVA (aopGet (left, offset, FALSE, FALSE));
5945 if (sign && size == 0)
5947 emitcode ("xrl", "a,#0x80");
5952 MOVB (aopGet (right, offset, FALSE, FALSE));
5954 emitcode ("xrl", "b,#0x80");
5955 emitcode ("subb", "a,b");
5960 emitcode ("subb", "a,b");
5962 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5972 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5973 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5974 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5980 /* if the result is used in the next
5981 ifx conditional branch then generate
5982 code a little differently */
5985 genIfxJump (ifx, "c", NULL, NULL, result);
5991 /* leave the result in acc */
5995 /*-----------------------------------------------------------------*/
5996 /* genCmpGt :- greater than comparison */
5997 /*-----------------------------------------------------------------*/
5999 genCmpGt (iCode * ic, iCode * ifx)
6001 operand *left, *right, *result;
6002 sym_link *letype, *retype;
6005 D (emitcode (";", "genCmpGt"));
6007 left = IC_LEFT (ic);
6008 right = IC_RIGHT (ic);
6009 result = IC_RESULT (ic);
6011 letype = getSpec (operandType (left));
6012 retype = getSpec (operandType (right));
6013 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
6014 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
6015 /* assign the asmops */
6016 aopOp (result, ic, TRUE);
6017 aopOp (left, ic, FALSE);
6018 aopOp (right, ic, FALSE);
6020 genCmp (right, left, result, ifx, sign, ic);
6022 freeAsmop (result, NULL, ic, TRUE);
6025 /*-----------------------------------------------------------------*/
6026 /* genCmpLt - less than comparisons */
6027 /*-----------------------------------------------------------------*/
6029 genCmpLt (iCode * ic, iCode * ifx)
6031 operand *left, *right, *result;
6032 sym_link *letype, *retype;
6035 D (emitcode (";", "genCmpLt"));
6037 left = IC_LEFT (ic);
6038 right = IC_RIGHT (ic);
6039 result = IC_RESULT (ic);
6041 letype = getSpec (operandType (left));
6042 retype = getSpec (operandType (right));
6043 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
6044 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
6045 /* assign the asmops */
6046 aopOp (result, ic, TRUE);
6047 aopOp (left, ic, FALSE);
6048 aopOp (right, ic, FALSE);
6050 genCmp (left, right, result, ifx, sign, ic);
6052 freeAsmop (result, NULL, ic, TRUE);
6055 /*-----------------------------------------------------------------*/
6056 /* gencjneshort - compare and jump if not equal */
6057 /*-----------------------------------------------------------------*/
6059 gencjneshort (operand * left, operand * right, symbol * lbl)
6061 int size = max (AOP_SIZE (left), AOP_SIZE (right));
6063 unsigned long lit = 0L;
6065 D (emitcode (";", "gencjneshort"));
6067 /* if the left side is a literal or
6068 if the right is in a pointer register and left
6070 if ((AOP_TYPE (left) == AOP_LIT) ||
6071 (AOP_TYPE (left) == AOP_IMMD) ||
6072 (AOP_TYPE (left) == AOP_DIR) ||
6073 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6080 if (AOP_TYPE (right) == AOP_LIT)
6081 lit = ulFromVal (AOP (right)->aopu.aop_lit);
6083 /* if the right side is a literal then anything goes */
6084 if (AOP_TYPE (right) == AOP_LIT &&
6085 AOP_TYPE (left) != AOP_DIR &&
6086 AOP_TYPE (left) != AOP_IMMD)
6090 emitcode ("cjne", "%s,%s,%05d$",
6091 aopGet (left, offset, FALSE, FALSE),
6092 aopGet (right, offset, FALSE, FALSE),
6098 /* if the right side is in a register or in direct space or
6099 if the left is a pointer register & right is not */
6100 else if (AOP_TYPE (right) == AOP_REG ||
6101 AOP_TYPE (right) == AOP_DIR ||
6102 AOP_TYPE (right) == AOP_LIT ||
6103 AOP_TYPE (right) == AOP_IMMD ||
6104 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6105 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6109 MOVA (aopGet (left, offset, FALSE, FALSE));
6110 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6111 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6112 emitcode ("jnz", "%05d$", lbl->key + 100);
6114 emitcode ("cjne", "a,%s,%05d$",
6115 aopGet (right, offset, FALSE, TRUE),
6122 /* right is a pointer reg need both a & b */
6125 //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
6126 wassertl(!BINUSE, "B was in use");
6127 MOVB (aopGet (left, offset, FALSE, FALSE));
6128 MOVA (aopGet (right, offset, FALSE, FALSE));
6129 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
6135 /*-----------------------------------------------------------------*/
6136 /* gencjne - compare and jump if not equal */
6137 /*-----------------------------------------------------------------*/
6139 gencjne (operand * left, operand * right, symbol * lbl, bool useCarry)
6141 symbol *tlbl = newiTempLabel (NULL);
6143 D (emitcode (";", "gencjne"));
6145 gencjneshort (left, right, lbl);
6151 emitcode ("sjmp", "%05d$", tlbl->key + 100);
6160 /*-----------------------------------------------------------------*/
6161 /* genCmpEq - generates code for equal to */
6162 /*-----------------------------------------------------------------*/
6164 genCmpEq (iCode * ic, iCode * ifx)
6166 bool swappedLR = FALSE;
6167 operand *left, *right, *result;
6169 D (emitcode (";", "genCmpEq"));
6171 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6172 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6173 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6175 /* if literal, literal on the right or
6176 if the right is in a pointer register and left
6178 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6179 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6181 operand *t = IC_RIGHT (ic);
6182 IC_RIGHT (ic) = IC_LEFT (ic);
6187 if (ifx && !AOP_SIZE (result))
6190 /* if they are both bit variables */
6191 if (AOP_TYPE (left) == AOP_CRY &&
6192 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6194 if (AOP_TYPE (right) == AOP_LIT)
6196 unsigned long lit = ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6199 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6200 emitcode ("cpl", "c");
6204 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6208 emitcode ("clr", "c");
6210 /* AOP_TYPE(right) == AOP_CRY */
6214 symbol *lbl = newiTempLabel (NULL);
6215 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6216 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6217 emitcode ("cpl", "c");
6220 /* if true label then we jump if condition
6222 tlbl = newiTempLabel (NULL);
6225 emitcode ("jnc", "%05d$", tlbl->key + 100);
6226 freeForBranchAsmop (result);
6227 freeForBranchAsmop (right);
6228 freeForBranchAsmop (left);
6229 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6233 emitcode ("jc", "%05d$", tlbl->key + 100);
6234 freeForBranchAsmop (result);
6235 freeForBranchAsmop (right);
6236 freeForBranchAsmop (left);
6237 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6243 tlbl = newiTempLabel (NULL);
6244 gencjneshort (left, right, tlbl);
6247 freeForBranchAsmop (result);
6248 freeForBranchAsmop (right);
6249 freeForBranchAsmop (left);
6250 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6255 symbol *lbl = newiTempLabel (NULL);
6256 emitcode ("sjmp", "%05d$", lbl->key + 100);
6258 freeForBranchAsmop (result);
6259 freeForBranchAsmop (right);
6260 freeForBranchAsmop (left);
6261 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6265 /* mark the icode as generated */
6270 /* if they are both bit variables */
6271 if (AOP_TYPE (left) == AOP_CRY &&
6272 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6274 if (AOP_TYPE (right) == AOP_LIT)
6276 unsigned long lit = ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6279 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6280 emitcode ("cpl", "c");
6284 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6288 emitcode ("clr", "c");
6290 /* AOP_TYPE(right) == AOP_CRY */
6294 symbol *lbl = newiTempLabel (NULL);
6295 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6296 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6297 emitcode ("cpl", "c");
6301 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6308 genIfxJump (ifx, "c", left, right, result);
6311 /* if the result is used in an arithmetic operation
6312 then put the result in place */
6317 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6319 gencjne (left, right, newiTempLabel (NULL), TRUE);
6320 aopPut (result, "c", 0);
6323 gencjne (left, right, newiTempLabel (NULL), FALSE);
6326 genIfxJump (ifx, "a", left, right, result);
6329 /* if the result is used in an arithmetic operation
6330 then put the result in place */
6331 if (AOP_TYPE (result) != AOP_CRY)
6333 /* leave the result in acc */
6337 freeAsmop (result, NULL, ic, TRUE);
6340 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6341 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6345 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6346 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6350 /*-----------------------------------------------------------------*/
6351 /* ifxForOp - returns the icode containing the ifx for operand */
6352 /*-----------------------------------------------------------------*/
6354 ifxForOp (operand * op, iCode * ic)
6356 /* if true symbol then needs to be assigned */
6357 if (IS_TRUE_SYMOP (op))
6360 /* if this has register type condition and
6361 the next instruction is ifx with the same operand
6362 and live to of the operand is upto the ifx only then */
6364 ic->next->op == IFX &&
6365 IC_COND (ic->next)->key == op->key &&
6366 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6372 /*-----------------------------------------------------------------*/
6373 /* hasInc - operand is incremented before any other use */
6374 /*-----------------------------------------------------------------*/
6376 hasInc (operand *op, iCode *ic, int osize)
6378 sym_link *type = operandType(op);
6379 sym_link *retype = getSpec (type);
6380 iCode *lic = ic->next;
6383 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6384 if (!IS_SYMOP(op)) return NULL;
6386 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6387 if (IS_AGGREGATE(type->next)) return NULL;
6388 if (osize != (isize = getSize(type->next))) return NULL;
6391 /* if operand of the form op = op + <sizeof *op> */
6392 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6393 isOperandEqual(IC_RESULT(lic),op) &&
6394 isOperandLiteral(IC_RIGHT(lic)) &&
6395 operandLitValue(IC_RIGHT(lic)) == isize) {
6398 /* if the operand used or deffed */
6399 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6402 /* if GOTO or IFX */
6403 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6409 /*-----------------------------------------------------------------*/
6410 /* genAndOp - for && operation */
6411 /*-----------------------------------------------------------------*/
6413 genAndOp (iCode * ic)
6415 operand *left, *right, *result;
6418 D (emitcode (";", "genAndOp"));
6420 /* note here that && operations that are in an
6421 if statement are taken away by backPatchLabels
6422 only those used in arthmetic operations remain */
6423 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6424 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6425 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6427 /* if both are bit variables */
6428 if (AOP_TYPE (left) == AOP_CRY &&
6429 AOP_TYPE (right) == AOP_CRY)
6431 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6432 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6437 tlbl = newiTempLabel (NULL);
6439 emitcode ("jz", "%05d$", tlbl->key + 100);
6445 freeAsmop (result, NULL, ic, TRUE);
6446 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6447 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6451 /*-----------------------------------------------------------------*/
6452 /* genOrOp - for || operation */
6453 /*-----------------------------------------------------------------*/
6455 genOrOp (iCode * ic)
6457 operand *left, *right, *result;
6460 D (emitcode (";", "genOrOp"));
6462 /* note here that || operations that are in an
6463 if statement are taken away by backPatchLabels
6464 only those used in arthmetic operations remain */
6465 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6466 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6467 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6469 /* if both are bit variables */
6470 if (AOP_TYPE (left) == AOP_CRY &&
6471 AOP_TYPE (right) == AOP_CRY)
6473 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6474 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6479 tlbl = newiTempLabel (NULL);
6481 emitcode ("jnz", "%05d$", tlbl->key + 100);
6487 freeAsmop (result, NULL, ic, TRUE);
6488 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6489 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6492 /*-----------------------------------------------------------------*/
6493 /* isLiteralBit - test if lit == 2^n */
6494 /*-----------------------------------------------------------------*/
6496 isLiteralBit (unsigned long lit)
6498 unsigned long pw[32] =
6499 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6500 0x100L, 0x200L, 0x400L, 0x800L,
6501 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6502 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6503 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6504 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6505 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6508 for (idx = 0; idx < 32; idx++)
6514 /*-----------------------------------------------------------------*/
6515 /* continueIfTrue - */
6516 /*-----------------------------------------------------------------*/
6518 continueIfTrue (iCode * ic)
6521 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6525 /*-----------------------------------------------------------------*/
6527 /*-----------------------------------------------------------------*/
6529 jumpIfTrue (iCode * ic)
6532 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6536 /*-----------------------------------------------------------------*/
6537 /* jmpTrueOrFalse - */
6538 /*-----------------------------------------------------------------*/
6540 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6542 // ugly but optimized by peephole
6545 symbol *nlbl = newiTempLabel (NULL);
6546 emitcode ("sjmp", "%05d$", nlbl->key + 100);
6548 freeForBranchAsmop (result);
6549 freeForBranchAsmop (right);
6550 freeForBranchAsmop (left);
6551 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6556 freeForBranchAsmop (result);
6557 freeForBranchAsmop (right);
6558 freeForBranchAsmop (left);
6559 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6565 /*-----------------------------------------------------------------*/
6566 /* genAnd - code for and */
6567 /*-----------------------------------------------------------------*/
6569 genAnd (iCode * ic, iCode * ifx)
6571 operand *left, *right, *result;
6572 int size, offset = 0;
6573 unsigned long lit = 0L;
6577 D (emitcode (";", "genAnd"));
6579 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6580 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6581 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6584 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
6586 AOP_TYPE (left), AOP_TYPE (right));
6587 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
6589 AOP_SIZE (left), AOP_SIZE (right));
6592 /* if left is a literal & right is not then exchange them */
6593 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6594 AOP_NEEDSACC (left))
6596 operand *tmp = right;
6601 /* if result = right then exchange left and right */
6602 if (sameRegs (AOP (result), AOP (right)))
6604 operand *tmp = right;
6609 /* if right is bit then exchange them */
6610 if (AOP_TYPE (right) == AOP_CRY &&
6611 AOP_TYPE (left) != AOP_CRY)
6613 operand *tmp = right;
6617 if (AOP_TYPE (right) == AOP_LIT)
6618 lit = ulFromVal (AOP (right)->aopu.aop_lit);
6620 size = AOP_SIZE (result);
6623 // result = bit & yy;
6624 if (AOP_TYPE (left) == AOP_CRY)
6626 // c = bit & literal;
6627 if (AOP_TYPE (right) == AOP_LIT)
6631 if (size && sameRegs (AOP (result), AOP (left)))
6634 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6639 if (size && (AOP_TYPE (result) == AOP_CRY))
6641 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6644 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6649 emitcode ("clr", "c");
6654 if (AOP_TYPE (right) == AOP_CRY)
6657 if (IS_OP_ACCUSE (left))
6659 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6663 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6664 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6670 MOVA (aopGet (right, 0, FALSE, FALSE));
6672 emitcode ("rrc", "a");
6673 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6681 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6682 genIfxJump (ifx, "c", left, right, result);
6686 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6687 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6688 if ((AOP_TYPE (right) == AOP_LIT) &&
6689 (AOP_TYPE (result) == AOP_CRY) &&
6690 (AOP_TYPE (left) != AOP_CRY))
6692 int posbit = isLiteralBit (lit);
6697 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6701 switch (posbit & 0x07)
6703 case 0: emitcode ("rrc", "a");
6705 case 7: emitcode ("rlc", "a");
6707 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6716 SNPRINTF (buffer, sizeof(buffer),
6717 "acc.%d", posbit & 0x07);
6718 genIfxJump (ifx, buffer, left, right, result);
6721 {// what is this case? just found it in ds390/gen.c
6722 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6729 symbol *tlbl = newiTempLabel (NULL);
6730 int sizel = AOP_SIZE (left);
6732 emitcode ("setb", "c");
6735 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6737 MOVA (aopGet (left, offset, FALSE, FALSE));
6739 if ((posbit = isLiteralBit (bytelit)) != 0)
6740 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6743 if (bytelit != 0x0FFL)
6744 emitcode ("anl", "a,%s",
6745 aopGet (right, offset, FALSE, TRUE));
6746 emitcode ("jnz", "%05d$", tlbl->key + 100);
6751 // bit = left & literal
6754 emitcode ("clr", "c");
6757 // if(left & literal)
6761 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6771 /* if left is same as result */
6772 if (sameRegs (AOP (result), AOP (left)))
6774 for (; size--; offset++)
6776 if (AOP_TYPE (right) == AOP_LIT)
6778 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6779 if (bytelit == 0x0FF)
6781 /* dummy read of volatile operand */
6782 if (isOperandVolatile (left, FALSE))
6783 MOVA (aopGet (left, offset, FALSE, FALSE));
6787 else if (bytelit == 0)
6789 aopPut (result, zero, offset);
6791 else if (IS_AOP_PREG (result))
6793 MOVA (aopGet (left, offset, FALSE, TRUE));
6794 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6795 aopPut (result, "a", offset);
6798 emitcode ("anl", "%s,%s",
6799 aopGet (left, offset, FALSE, TRUE),
6800 aopGet (right, offset, FALSE, FALSE));
6804 if (AOP_TYPE (left) == AOP_ACC)
6807 emitcode("mov", "a,b");
6808 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6810 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6812 MOVB (aopGet (left, offset, FALSE, FALSE));
6813 MOVA (aopGet (right, offset, FALSE, FALSE));
6814 emitcode ("anl", "a,b");
6815 aopPut (result, "a", offset);
6817 else if (aopGetUsesAcc (left, offset))
6819 MOVA (aopGet (left, offset, FALSE, FALSE));
6820 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6821 aopPut (result, "a", offset);
6825 MOVA (aopGet (right, offset, FALSE, FALSE));
6826 if (IS_AOP_PREG (result))
6828 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6829 aopPut (result, "a", offset);
6832 emitcode ("anl", "%s,a", aopGet (left, offset, FALSE, TRUE));
6839 // left & result in different registers
6840 if (AOP_TYPE (result) == AOP_CRY)
6843 // if(size), result in bit
6844 // if(!size && ifx), conditional oper: if(left & right)
6845 symbol *tlbl = newiTempLabel (NULL);
6846 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6848 emitcode ("setb", "c");
6851 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6852 && AOP_TYPE(left)==AOP_ACC)
6855 emitcode("mov", "a,b");
6856 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6858 else if (AOP_TYPE(left)==AOP_ACC)
6862 bool pushedB = pushB ();
6863 emitcode("mov", "b,a");
6864 MOVA (aopGet (right, offset, FALSE, FALSE));
6865 emitcode("anl", "a,b");
6870 MOVA (aopGet (right, offset, FALSE, FALSE));
6871 emitcode("anl", "a,b");
6874 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6876 MOVB (aopGet (left, offset, FALSE, FALSE));
6877 MOVA (aopGet (right, offset, FALSE, FALSE));
6878 emitcode ("anl", "a,b");
6880 else if (aopGetUsesAcc (left, offset))
6882 MOVA (aopGet (left, offset, FALSE, FALSE));
6883 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6887 MOVA (aopGet (right, offset, FALSE, FALSE));
6888 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6891 emitcode ("jnz", "%05d$", tlbl->key + 100);
6901 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6907 for (; (size--); offset++)
6910 // result = left & right
6911 if (AOP_TYPE (right) == AOP_LIT)
6913 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6914 if (bytelit == 0x0FF)
6917 aopGet (left, offset, FALSE, FALSE),
6921 else if (bytelit == 0)
6923 /* dummy read of volatile operand */
6924 if (isOperandVolatile (left, FALSE))
6925 MOVA (aopGet (left, offset, FALSE, FALSE));
6926 aopPut (result, zero, offset);
6929 else if (AOP_TYPE (left) == AOP_ACC)
6933 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6934 aopPut (result, "a", offset);
6939 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6940 aopPut (result, "b", offset);
6945 // faster than result <- left, anl result,right
6946 // and better if result is SFR
6947 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6948 && AOP_TYPE(left)==AOP_ACC)
6951 emitcode("mov", "a,b");
6952 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6954 else if (AOP_TYPE(left)==AOP_ACC)
6958 bool pushedB = pushB ();
6959 emitcode("mov", "b,a");
6960 MOVA (aopGet (right, offset, FALSE, FALSE));
6961 emitcode("anl", "a,b");
6966 MOVA (aopGet (right, offset, FALSE, FALSE));
6967 emitcode("anl", "a,b");
6970 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6972 MOVB (aopGet (left, offset, FALSE, FALSE));
6973 MOVA (aopGet (right, offset, FALSE, FALSE));
6974 emitcode ("anl", "a,b");
6976 else if (aopGetUsesAcc (left, offset))
6978 MOVA (aopGet (left, offset, FALSE, FALSE));
6979 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6983 MOVA (aopGet (right, offset, FALSE, FALSE));
6984 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6986 aopPut (result, "a", offset);
6992 freeAsmop (result, NULL, ic, TRUE);
6993 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6994 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6997 /*-----------------------------------------------------------------*/
6998 /* genOr - code for or */
6999 /*-----------------------------------------------------------------*/
7001 genOr (iCode * ic, iCode * ifx)
7003 operand *left, *right, *result;
7004 int size, offset = 0;
7005 unsigned long lit = 0L;
7008 D (emitcode (";", "genOr"));
7010 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7011 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7012 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7015 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
7017 AOP_TYPE (left), AOP_TYPE (right));
7018 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
7020 AOP_SIZE (left), AOP_SIZE (right));
7023 /* if left is a literal & right is not then exchange them */
7024 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7025 AOP_NEEDSACC (left))
7027 operand *tmp = right;
7032 /* if result = right then exchange them */
7033 if (sameRegs (AOP (result), AOP (right)))
7035 operand *tmp = right;
7040 /* if right is bit then exchange them */
7041 if (AOP_TYPE (right) == AOP_CRY &&
7042 AOP_TYPE (left) != AOP_CRY)
7044 operand *tmp = right;
7048 if (AOP_TYPE (right) == AOP_LIT)
7049 lit = ulFromVal (AOP (right)->aopu.aop_lit);
7051 size = AOP_SIZE (result);
7055 if (AOP_TYPE (left) == AOP_CRY)
7057 if (AOP_TYPE (right) == AOP_LIT)
7059 // c = bit | literal;
7062 // lit != 0 => result = 1
7063 if (AOP_TYPE (result) == AOP_CRY)
7066 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7068 continueIfTrue (ifx);
7071 emitcode ("setb", "c");
7075 // lit == 0 => result = left
7076 if (size && sameRegs (AOP (result), AOP (left)))
7078 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7083 if (AOP_TYPE (right) == AOP_CRY)
7086 if (IS_OP_ACCUSE (left))
7088 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
7092 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7093 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7099 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7101 symbol *tlbl = newiTempLabel (NULL);
7102 emitcode ("jb", "%s,%05d$",
7103 AOP (left)->aopu.aop_dir, tlbl->key + 100);
7105 emitcode ("jnz", "%05d$", tlbl->key + 100);
7106 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7112 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7121 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7122 genIfxJump (ifx, "c", left, right, result);
7126 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7127 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7128 if ((AOP_TYPE (right) == AOP_LIT) &&
7129 (AOP_TYPE (result) == AOP_CRY) &&
7130 (AOP_TYPE (left) != AOP_CRY))
7136 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7138 continueIfTrue (ifx);
7143 // lit = 0, result = boolean(left)
7145 emitcode ("setb", "c");
7149 symbol *tlbl = newiTempLabel (NULL);
7150 emitcode ("jnz", "%05d$", tlbl->key + 100);
7156 genIfxJump (ifx, "a", left, right, result);
7164 /* if left is same as result */
7165 if (sameRegs (AOP (result), AOP (left)))
7167 for (; size--; offset++)
7169 if (AOP_TYPE (right) == AOP_LIT)
7171 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7174 /* dummy read of volatile operand */
7175 if (isOperandVolatile (left, FALSE))
7176 MOVA (aopGet (left, offset, FALSE, FALSE));
7180 else if (bytelit == 0x0FF)
7182 aopPut (result, "#0xFF", offset);
7184 else if (IS_AOP_PREG (left))
7186 MOVA (aopGet (left, offset, FALSE, TRUE));
7187 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7188 aopPut (result, "a", offset);
7192 emitcode ("orl", "%s,%s",
7193 aopGet (left, offset, FALSE, TRUE),
7194 aopGet (right, offset, FALSE, FALSE));
7199 if (AOP_TYPE (left) == AOP_ACC)
7202 emitcode("mov", "a,b");
7203 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7205 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7207 MOVB (aopGet (left, offset, FALSE, FALSE));
7208 MOVA (aopGet (right, offset, FALSE, FALSE));
7209 emitcode ("orl", "a,b");
7210 aopPut (result, "a", offset);
7212 else if (aopGetUsesAcc (left, offset))
7214 MOVA (aopGet (left, offset, FALSE, FALSE));
7215 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7216 aopPut (result, "a", offset);
7220 MOVA (aopGet (right, offset, FALSE, FALSE));
7221 if (IS_AOP_PREG (left))
7223 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7224 aopPut (result, "a", offset);
7228 emitcode ("orl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7236 // left & result in different registers
7237 if (AOP_TYPE (result) == AOP_CRY)
7240 // if(size), result in bit
7241 // if(!size && ifx), conditional oper: if(left | right)
7242 symbol *tlbl = newiTempLabel (NULL);
7243 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7245 emitcode ("setb", "c");
7248 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7249 && AOP_TYPE(left)==AOP_ACC)
7252 emitcode("mov", "a,b");
7253 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7255 else if (AOP_TYPE(left)==AOP_ACC)
7259 bool pushedB = pushB ();
7260 emitcode("mov", "b,a");
7261 MOVA (aopGet (right, offset, FALSE, FALSE));
7262 emitcode("orl", "a,b");
7267 MOVA (aopGet (right, offset, FALSE, FALSE));
7268 emitcode("orl", "a,b");
7271 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7273 MOVB (aopGet (left, offset, FALSE, FALSE));
7274 MOVA (aopGet (right, offset, FALSE, FALSE));
7275 emitcode ("orl", "a,b");
7277 else if (aopGetUsesAcc (left, offset))
7279 MOVA (aopGet (left, offset, FALSE, FALSE));
7280 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7284 MOVA (aopGet (right, offset, FALSE, FALSE));
7285 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7288 emitcode ("jnz", "%05d$", tlbl->key + 100);
7298 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7304 for (; (size--); offset++)
7307 // result = left | right
7308 if (AOP_TYPE (right) == AOP_LIT)
7310 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7314 aopGet (left, offset, FALSE, FALSE),
7318 else if (bytelit == 0x0FF)
7320 /* dummy read of volatile operand */
7321 if (isOperandVolatile (left, FALSE))
7322 MOVA (aopGet (left, offset, FALSE, FALSE));
7323 aopPut (result, "#0xFF", offset);
7327 // faster than result <- left, orl result,right
7328 // and better if result is SFR
7329 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7330 && AOP_TYPE(left)==AOP_ACC)
7333 emitcode("mov", "a,b");
7334 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7336 else if (AOP_TYPE(left)==AOP_ACC)
7340 bool pushedB = pushB ();
7341 emitcode("mov", "b,a");
7342 MOVA (aopGet (right, offset, FALSE, FALSE));
7343 emitcode("orl", "a,b");
7348 MOVA (aopGet (right, offset, FALSE, FALSE));
7349 emitcode("orl", "a,b");
7352 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7354 MOVB (aopGet (left, offset, FALSE, FALSE));
7355 MOVA (aopGet (right, offset, FALSE, FALSE));
7356 emitcode ("orl", "a,b");
7358 else if (aopGetUsesAcc (left, offset))
7360 MOVA (aopGet (left, offset, FALSE, FALSE));
7361 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7365 MOVA (aopGet (right, offset, FALSE, FALSE));
7366 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7368 aopPut (result, "a", offset);
7374 freeAsmop (result, NULL, ic, TRUE);
7375 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7376 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7379 /*-----------------------------------------------------------------*/
7380 /* genXor - code for xclusive or */
7381 /*-----------------------------------------------------------------*/
7383 genXor (iCode * ic, iCode * ifx)
7385 operand *left, *right, *result;
7386 int size, offset = 0;
7387 unsigned long lit = 0L;
7390 D (emitcode (";", "genXor"));
7392 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7393 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7394 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7397 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
7399 AOP_TYPE (left), AOP_TYPE (right));
7400 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
7402 AOP_SIZE (left), AOP_SIZE (right));
7405 /* if left is a literal & right is not ||
7406 if left needs acc & right does not */
7407 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7408 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7410 operand *tmp = right;
7415 /* if result = right then exchange them */
7416 if (sameRegs (AOP (result), AOP (right)))
7418 operand *tmp = right;
7423 /* if right is bit then exchange them */
7424 if (AOP_TYPE (right) == AOP_CRY &&
7425 AOP_TYPE (left) != AOP_CRY)
7427 operand *tmp = right;
7432 if (AOP_TYPE (right) == AOP_LIT)
7433 lit = ulFromVal (AOP (right)->aopu.aop_lit);
7435 size = AOP_SIZE (result);
7439 if (AOP_TYPE (left) == AOP_CRY)
7441 if (AOP_TYPE (right) == AOP_LIT)
7443 // c = bit & literal;
7446 // lit>>1 != 0 => result = 1
7447 if (AOP_TYPE (result) == AOP_CRY)
7450 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7452 continueIfTrue (ifx);
7455 emitcode ("setb", "c");
7462 // lit == 0, result = left
7463 if (size && sameRegs (AOP (result), AOP (left)))
7465 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7469 // lit == 1, result = not(left)
7470 if (size && sameRegs (AOP (result), AOP (left)))
7472 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7477 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7478 emitcode ("cpl", "c");
7486 symbol *tlbl = newiTempLabel (NULL);
7487 if (AOP_TYPE (right) == AOP_CRY)
7490 if (IS_OP_ACCUSE (left))
7491 {// left already is in the carry
7492 operand *tmp = right;
7506 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7507 emitcode ("cpl", "c");
7515 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7516 genIfxJump (ifx, "c", left, right, result);
7520 /* if left is same as result */
7521 if (sameRegs (AOP (result), AOP (left)))
7523 for (; size--; offset++)
7525 if (AOP_TYPE (right) == AOP_LIT)
7527 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7530 /* dummy read of volatile operand */
7531 if (isOperandVolatile (left, FALSE))
7532 MOVA (aopGet (left, offset, FALSE, FALSE));
7536 else if (IS_AOP_PREG (left))
7538 MOVA (aopGet (left, offset, FALSE, TRUE));
7539 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7540 aopPut (result, "a", offset);
7544 emitcode ("xrl", "%s,%s",
7545 aopGet (left, offset, FALSE, TRUE),
7546 aopGet (right, offset, FALSE, FALSE));
7551 if (AOP_TYPE (left) == AOP_ACC)
7554 emitcode("mov", "a,b");
7555 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7557 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7559 MOVB (aopGet (left, offset, FALSE, FALSE));
7560 MOVA (aopGet (right, offset, FALSE, FALSE));
7561 emitcode ("xrl", "a,b");
7562 aopPut (result, "a", offset);
7564 else if (aopGetUsesAcc (left, offset))
7566 MOVA (aopGet (left, offset, FALSE, FALSE));
7567 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7568 aopPut (result, "a", offset);
7572 MOVA (aopGet (right, offset, FALSE, FALSE));
7573 if (IS_AOP_PREG (left))
7575 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7576 aopPut (result, "a", offset);
7579 emitcode ("xrl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7586 // left & result in different registers
7587 if (AOP_TYPE (result) == AOP_CRY)
7590 // if(size), result in bit
7591 // if(!size && ifx), conditional oper: if(left ^ right)
7592 symbol *tlbl = newiTempLabel (NULL);
7593 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7596 emitcode ("setb", "c");
7599 if ((AOP_TYPE (right) == AOP_LIT) &&
7600 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7602 MOVA (aopGet (left, offset, FALSE, FALSE));
7604 else if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7605 && AOP_TYPE(left)==AOP_ACC)
7608 emitcode("mov", "a,b");
7609 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7611 else if (AOP_TYPE(left)==AOP_ACC)
7615 bool pushedB = pushB ();
7616 emitcode("mov", "b,a");
7617 MOVA (aopGet (right, offset, FALSE, FALSE));
7618 emitcode("xrl", "a,b");
7623 MOVA (aopGet (right, offset, FALSE, FALSE));
7624 emitcode("xrl", "a,b");
7627 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7629 MOVB (aopGet (left, offset, FALSE, FALSE));
7630 MOVA (aopGet (right, offset, FALSE, FALSE));
7631 emitcode ("xrl", "a,b");
7633 else if (aopGetUsesAcc (left, offset))
7635 MOVA (aopGet (left, offset, FALSE, FALSE));
7636 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7640 MOVA (aopGet (right, offset, FALSE, FALSE));
7641 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7644 emitcode ("jnz", "%05d$", tlbl->key + 100);
7654 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7658 for (; (size--); offset++)
7661 // result = left ^ right
7662 if (AOP_TYPE (right) == AOP_LIT)
7664 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7668 aopGet (left, offset, FALSE, FALSE),
7673 // faster than result <- left, xrl result,right
7674 // and better if result is SFR
7675 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7676 && AOP_TYPE(left)==AOP_ACC)
7679 emitcode("mov", "a,b");
7680 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7682 else if (AOP_TYPE(left)==AOP_ACC)
7686 bool pushedB = pushB ();
7687 emitcode("mov", "b,a");
7688 MOVA (aopGet (right, offset, FALSE, FALSE));
7689 emitcode("xrl", "a,b");
7694 MOVA (aopGet (right, offset, FALSE, FALSE));
7695 emitcode("xrl", "a,b");
7698 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7700 MOVB (aopGet (left, offset, FALSE, FALSE));
7701 MOVA (aopGet (right, offset, FALSE, FALSE));
7702 emitcode ("xrl", "a,b");
7704 else if (aopGetUsesAcc (left, offset))
7706 MOVA (aopGet (left, offset, FALSE, FALSE));
7707 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7711 MOVA (aopGet (right, offset, FALSE, FALSE));
7712 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7714 aopPut (result, "a", offset);
7720 freeAsmop (result, NULL, ic, TRUE);
7721 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7722 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7725 /*-----------------------------------------------------------------*/
7726 /* genInline - write the inline code out */
7727 /*-----------------------------------------------------------------*/
7729 genInline (iCode * ic)
7731 char *buffer, *bp, *bp1;
7732 bool inComment = FALSE;
7734 D (emitcode (";", "genInline"));
7736 _G.inLine += (!options.asmpeep);
7738 buffer = bp = bp1 = Safe_strdup (IC_INLINE (ic));
7740 /* emit each line as a code */
7758 /* Add \n for labels, not dirs such as c:\mydir */
7759 if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
7777 _G.inLine -= (!options.asmpeep);
7780 /*-----------------------------------------------------------------*/
7781 /* genRRC - rotate right with carry */
7782 /*-----------------------------------------------------------------*/
7786 operand *left, *result;
7790 D (emitcode (";", "genRRC"));
7792 /* rotate right with carry */
7793 left = IC_LEFT (ic);
7794 result = IC_RESULT (ic);
7795 aopOp (left, ic, FALSE);
7796 aopOp (result, ic, FALSE);
7798 /* move it to the result */
7799 size = AOP_SIZE (result);
7801 if (size == 1) { /* special case for 1 byte */
7802 l = aopGet (left, offset, FALSE, FALSE);
7804 emitcode ("rr", "a");
7807 /* no need to clear carry, bit7 will be written later */
7810 l = aopGet (left, offset, FALSE, FALSE);
7812 emitcode ("rrc", "a");
7813 if (AOP_SIZE (result) > 1)
7814 aopPut (result, "a", offset--);
7816 /* now we need to put the carry into the
7817 highest order byte of the result */
7818 if (AOP_SIZE (result) > 1)
7820 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7823 emitcode ("mov", "acc.7,c");
7825 aopPut (result, "a", AOP_SIZE (result) - 1);
7826 freeAsmop (result, NULL, ic, TRUE);
7827 freeAsmop (left, NULL, ic, TRUE);
7830 /*-----------------------------------------------------------------*/
7831 /* genRLC - generate code for rotate left with carry */
7832 /*-----------------------------------------------------------------*/
7836 operand *left, *result;
7840 D (emitcode (";", "genRLC"));
7842 /* rotate right with carry */
7843 left = IC_LEFT (ic);
7844 result = IC_RESULT (ic);
7845 aopOp (left, ic, FALSE);
7846 aopOp (result, ic, FALSE);
7848 /* move it to the result */
7849 size = AOP_SIZE (result);
7853 l = aopGet (left, offset, FALSE, FALSE);
7855 if (size == 0) { /* special case for 1 byte */
7859 emitcode("rlc","a"); /* bit0 will be written later */
7860 if (AOP_SIZE (result) > 1)
7862 aopPut (result, "a", offset++);
7867 l = aopGet (left, offset, FALSE, FALSE);
7869 emitcode ("rlc", "a");
7870 if (AOP_SIZE (result) > 1)
7871 aopPut (result, "a", offset++);
7874 /* now we need to put the carry into the
7875 highest order byte of the result */
7876 if (AOP_SIZE (result) > 1)
7878 l = aopGet (result, 0, FALSE, FALSE);
7881 emitcode ("mov", "acc.0,c");
7883 aopPut (result, "a", 0);
7884 freeAsmop (result, NULL, ic, TRUE);
7885 freeAsmop (left, NULL, ic, TRUE);
7888 /*-----------------------------------------------------------------*/
7889 /* genGetHbit - generates code get highest order bit */
7890 /*-----------------------------------------------------------------*/
7892 genGetHbit (iCode * ic)
7894 operand *left, *result;
7896 D (emitcode (";", "genGetHbit"));
7898 left = IC_LEFT (ic);
7899 result = IC_RESULT (ic);
7900 aopOp (left, ic, FALSE);
7901 aopOp (result, ic, FALSE);
7903 /* get the highest order byte into a */
7904 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7905 if (AOP_TYPE (result) == AOP_CRY)
7907 emitcode ("rlc", "a");
7912 emitcode ("rl", "a");
7913 emitcode ("anl", "a,#0x01");
7917 freeAsmop (result, NULL, ic, TRUE);
7918 freeAsmop (left, NULL, ic, TRUE);
7921 /*-----------------------------------------------------------------*/
7922 /* genGetAbit - generates code get a single bit */
7923 /*-----------------------------------------------------------------*/
7925 genGetAbit (iCode * ic)
7927 operand *left, *right, *result;
7930 D (emitcode (";", "genGetAbit"));
7932 left = IC_LEFT (ic);
7933 right = IC_RIGHT (ic);
7934 result = IC_RESULT (ic);
7935 aopOp (left, ic, FALSE);
7936 aopOp (right, ic, FALSE);
7937 aopOp (result, ic, FALSE);
7939 shCount = (int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7941 /* get the needed byte into a */
7942 MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7944 if (AOP_TYPE (result) == AOP_CRY)
7947 emitcode ("rlc", "a");
7948 else if ((shCount) == 0)
7949 emitcode ("rrc", "a");
7951 emitcode ("mov", "c,acc[%d]", shCount);
7959 emitcode ("rr", "a");
7962 emitcode ("rr", "a");
7965 emitcode ("anl", "a,#0x01");
7969 emitcode ("mov", "c,acc[%d]", shCount);
7970 emitcode ("clr", "a");
7971 emitcode ("rlc", "a");
7974 emitcode ("swap", "a");
7975 emitcode ("anl", "a,#0x01");
7978 emitcode ("rl", "a");
7981 emitcode ("rl", "a");
7982 emitcode ("anl", "a,#0x01");
7988 freeAsmop (result, NULL, ic, TRUE);
7989 freeAsmop (right, NULL, ic, TRUE);
7990 freeAsmop (left, NULL, ic, TRUE);
7993 /*-----------------------------------------------------------------*/
7994 /* genGetByte - generates code get a single byte */
7995 /*-----------------------------------------------------------------*/
7997 genGetByte (iCode * ic)
7999 operand *left, *right, *result;
8002 D (emitcode (";", "genGetByte"));
8004 left = IC_LEFT (ic);
8005 right = IC_RIGHT (ic);
8006 result = IC_RESULT (ic);
8007 aopOp (left, ic, FALSE);
8008 aopOp (right, ic, FALSE);
8009 aopOp (result, ic, FALSE);
8011 offset = (int) ulFromVal (AOP (right)->aopu.aop_lit) / 8;
8013 aopGet (left, offset, FALSE, FALSE),
8016 freeAsmop (result, NULL, ic, TRUE);
8017 freeAsmop (right, NULL, ic, TRUE);
8018 freeAsmop (left, NULL, ic, TRUE);
8021 /*-----------------------------------------------------------------*/
8022 /* genGetWord - generates code get two bytes */
8023 /*-----------------------------------------------------------------*/
8025 genGetWord (iCode * ic)
8027 operand *left, *right, *result;
8030 D (emitcode (";", "genGetWord"));
8032 left = IC_LEFT (ic);
8033 right = IC_RIGHT (ic);
8034 result = IC_RESULT (ic);
8035 aopOp (left, ic, FALSE);
8036 aopOp (right, ic, FALSE);
8037 aopOp (result, ic, FALSE);
8039 offset = (int) ulFromVal (AOP (right)->aopu.aop_lit) / 8;
8041 aopGet (left, offset, FALSE, FALSE),
8044 aopGet (left, offset+1, FALSE, FALSE),
8047 freeAsmop (result, NULL, ic, TRUE);
8048 freeAsmop (right, NULL, ic, TRUE);
8049 freeAsmop (left, NULL, ic, TRUE);
8052 /*-----------------------------------------------------------------*/
8053 /* genSwap - generates code to swap nibbles or bytes */
8054 /*-----------------------------------------------------------------*/
8056 genSwap (iCode * ic)
8058 operand *left, *result;
8060 D(emitcode (";", "genSwap"));
8062 left = IC_LEFT (ic);
8063 result = IC_RESULT (ic);
8064 aopOp (left, ic, FALSE);
8065 aopOp (result, ic, FALSE);
8067 switch (AOP_SIZE (left))
8069 case 1: /* swap nibbles in byte */
8070 MOVA (aopGet (left, 0, FALSE, FALSE));
8071 emitcode ("swap", "a");
8072 aopPut (result, "a", 0);
8074 case 2: /* swap bytes in word */
8075 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
8077 MOVA (aopGet (left, 0, FALSE, FALSE));
8078 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8079 aopPut (result, "a", 1);
8081 else if (operandsEqu (left, result))
8084 bool pushedB = FALSE, leftInB = FALSE;
8086 MOVA (aopGet (left, 0, FALSE, FALSE));
8087 if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
8090 emitcode ("mov", "b,a");
8094 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8095 aopPut (result, reg, 1);
8102 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8103 aopPut (result, aopGet (left, 0, FALSE, FALSE), 1);
8107 wassertl(FALSE, "unsupported SWAP operand size");
8110 freeAsmop (result, NULL, ic, TRUE);
8111 freeAsmop (left, NULL, ic, TRUE);
8114 /*-----------------------------------------------------------------*/
8115 /* AccRol - rotate left accumulator by known count */
8116 /*-----------------------------------------------------------------*/
8118 AccRol (int shCount)
8120 shCount &= 0x0007; // shCount : 0..7
8127 emitcode ("rl", "a");
8130 emitcode ("rl", "a");
8131 emitcode ("rl", "a");
8134 emitcode ("swap", "a");
8135 emitcode ("rr", "a");
8138 emitcode ("swap", "a");
8141 emitcode ("swap", "a");
8142 emitcode ("rl", "a");
8145 emitcode ("rr", "a");
8146 emitcode ("rr", "a");
8149 emitcode ("rr", "a");
8154 /*-----------------------------------------------------------------*/
8155 /* AccLsh - left shift accumulator by known count */
8156 /*-----------------------------------------------------------------*/
8158 AccLsh (int shCount)
8163 emitcode ("add", "a,acc");
8164 else if (shCount == 2)
8166 emitcode ("add", "a,acc");
8167 emitcode ("add", "a,acc");
8171 /* rotate left accumulator */
8173 /* and kill the lower order bits */
8174 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
8179 /*-----------------------------------------------------------------*/
8180 /* AccRsh - right shift accumulator by known count */
8181 /*-----------------------------------------------------------------*/
8183 AccRsh (int shCount)
8190 emitcode ("rrc", "a");
8194 /* rotate right accumulator */
8195 AccRol (8 - shCount);
8196 /* and kill the higher order bits */
8197 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8202 /*-----------------------------------------------------------------*/
8203 /* AccSRsh - signed right shift accumulator by known count */
8204 /*-----------------------------------------------------------------*/
8206 AccSRsh (int shCount)
8213 emitcode ("mov", "c,acc.7");
8214 emitcode ("rrc", "a");
8216 else if (shCount == 2)
8218 emitcode ("mov", "c,acc.7");
8219 emitcode ("rrc", "a");
8220 emitcode ("mov", "c,acc.7");
8221 emitcode ("rrc", "a");
8225 tlbl = newiTempLabel (NULL);
8226 /* rotate right accumulator */
8227 AccRol (8 - shCount);
8228 /* and kill the higher order bits */
8229 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8230 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8231 emitcode ("orl", "a,#0x%02x",
8232 (unsigned char) ~SRMask[shCount]);
8238 /*-----------------------------------------------------------------*/
8239 /* shiftR1Left2Result - shift right one byte from left to result */
8240 /*-----------------------------------------------------------------*/
8242 shiftR1Left2Result (operand * left, int offl,
8243 operand * result, int offr,
8244 int shCount, int sign)
8246 MOVA (aopGet (left, offl, FALSE, FALSE));
8247 /* shift right accumulator */
8252 aopPut (result, "a", offr);
8255 /*-----------------------------------------------------------------*/
8256 /* shiftL1Left2Result - shift left one byte from left to result */
8257 /*-----------------------------------------------------------------*/
8259 shiftL1Left2Result (operand * left, int offl,
8260 operand * result, int offr, int shCount)
8263 l = aopGet (left, offl, FALSE, FALSE);
8265 /* shift left accumulator */
8267 aopPut (result, "a", offr);
8270 /*-----------------------------------------------------------------*/
8271 /* movLeft2Result - move byte from left to result */
8272 /*-----------------------------------------------------------------*/
8274 movLeft2Result (operand * left, int offl,
8275 operand * result, int offr, int sign)
8278 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8280 l = aopGet (left, offl, FALSE, FALSE);
8282 if (*l == '@' && (IS_AOP_PREG (result)))
8284 emitcode ("mov", "a,%s", l);
8285 aopPut (result, "a", offr);
8291 aopPut (result, l, offr);
8295 /* MSB sign in acc.7 ! */
8296 if (getDataSize (left) == offl + 1)
8299 aopPut (result, "a", offr);
8306 /*-----------------------------------------------------------------*/
8307 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
8308 /*-----------------------------------------------------------------*/
8312 emitcode ("rrc", "a");
8313 emitcode ("xch", "a,%s", x);
8314 emitcode ("rrc", "a");
8315 emitcode ("xch", "a,%s", x);
8318 /*-----------------------------------------------------------------*/
8319 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
8320 /*-----------------------------------------------------------------*/
8324 emitcode ("xch", "a,%s", x);
8325 emitcode ("rlc", "a");
8326 emitcode ("xch", "a,%s", x);
8327 emitcode ("rlc", "a");
8330 /*-----------------------------------------------------------------*/
8331 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8332 /*-----------------------------------------------------------------*/
8336 emitcode ("xch", "a,%s", x);
8337 emitcode ("add", "a,acc");
8338 emitcode ("xch", "a,%s", x);
8339 emitcode ("rlc", "a");
8342 /*-----------------------------------------------------------------*/
8343 /* AccAXLsh - left shift a:x by known count (0..7) */
8344 /*-----------------------------------------------------------------*/
8346 AccAXLsh (char *x, int shCount)
8361 case 5: // AAAAABBB:CCCCCDDD
8363 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8365 emitcode ("anl", "a,#0x%02x",
8366 SLMask[shCount]); // BBB00000:CCCCCDDD
8368 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8370 AccRol (shCount); // DDDCCCCC:BBB00000
8372 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8374 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8376 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8378 emitcode ("anl", "a,#0x%02x",
8379 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8381 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8383 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8386 case 6: // AAAAAABB:CCCCCCDD
8387 emitcode ("anl", "a,#0x%02x",
8388 SRMask[shCount]); // 000000BB:CCCCCCDD
8389 emitcode ("mov", "c,acc.0"); // c = B
8390 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8392 AccAXRrl1 (x); // BCCCCCCD:D000000B
8393 AccAXRrl1 (x); // BBCCCCCC:DD000000
8395 emitcode("rrc","a");
8396 emitcode("xch","a,%s", x);
8397 emitcode("rrc","a");
8398 emitcode("mov","c,acc.0"); //<< get correct bit
8399 emitcode("xch","a,%s", x);
8401 emitcode("rrc","a");
8402 emitcode("xch","a,%s", x);
8403 emitcode("rrc","a");
8404 emitcode("xch","a,%s", x);
8407 case 7: // a:x <<= 7
8409 emitcode ("anl", "a,#0x%02x",
8410 SRMask[shCount]); // 0000000B:CCCCCCCD
8412 emitcode ("mov", "c,acc.0"); // c = B
8414 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
8416 AccAXRrl1 (x); // BCCCCCCC:D0000000
8424 /*-----------------------------------------------------------------*/
8425 /* AccAXRsh - right shift a:x known count (0..7) */
8426 /*-----------------------------------------------------------------*/
8428 AccAXRsh (char *x, int shCount)
8436 AccAXRrl1 (x); // 0->a:x
8441 AccAXRrl1 (x); // 0->a:x
8444 AccAXRrl1 (x); // 0->a:x
8449 case 5: // AAAAABBB:CCCCCDDD = a:x
8451 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8453 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8455 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8457 emitcode ("anl", "a,#0x%02x",
8458 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8460 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8462 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8464 emitcode ("anl", "a,#0x%02x",
8465 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8467 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8469 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8471 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8474 case 6: // AABBBBBB:CCDDDDDD
8476 emitcode ("mov", "c,acc.7");
8477 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8479 emitcode ("mov", "c,acc.7");
8480 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8482 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8484 emitcode ("anl", "a,#0x%02x",
8485 SRMask[shCount]); // 000000AA:BBBBBBCC
8488 case 7: // ABBBBBBB:CDDDDDDD
8490 emitcode ("mov", "c,acc.7"); // c = A
8492 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8494 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8496 emitcode ("anl", "a,#0x%02x",
8497 SRMask[shCount]); // 0000000A:BBBBBBBC
8505 /*-----------------------------------------------------------------*/
8506 /* AccAXRshS - right shift signed a:x known count (0..7) */
8507 /*-----------------------------------------------------------------*/
8509 AccAXRshS (char *x, int shCount)
8517 emitcode ("mov", "c,acc.7");
8518 AccAXRrl1 (x); // s->a:x
8522 emitcode ("mov", "c,acc.7");
8523 AccAXRrl1 (x); // s->a:x
8525 emitcode ("mov", "c,acc.7");
8526 AccAXRrl1 (x); // s->a:x
8531 case 5: // AAAAABBB:CCCCCDDD = a:x
8533 tlbl = newiTempLabel (NULL);
8534 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8536 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8538 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8540 emitcode ("anl", "a,#0x%02x",
8541 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8543 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8545 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8547 emitcode ("anl", "a,#0x%02x",
8548 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8550 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8552 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8554 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8556 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8557 emitcode ("orl", "a,#0x%02x",
8558 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8561 break; // SSSSAAAA:BBBCCCCC
8563 case 6: // AABBBBBB:CCDDDDDD
8565 tlbl = newiTempLabel (NULL);
8566 emitcode ("mov", "c,acc.7");
8567 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8569 emitcode ("mov", "c,acc.7");
8570 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8572 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8574 emitcode ("anl", "a,#0x%02x",
8575 SRMask[shCount]); // 000000AA:BBBBBBCC
8577 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8578 emitcode ("orl", "a,#0x%02x",
8579 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8583 case 7: // ABBBBBBB:CDDDDDDD
8585 tlbl = newiTempLabel (NULL);
8586 emitcode ("mov", "c,acc.7"); // c = A
8588 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8590 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8592 emitcode ("anl", "a,#0x%02x",
8593 SRMask[shCount]); // 0000000A:BBBBBBBC
8595 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8596 emitcode ("orl", "a,#0x%02x",
8597 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8606 /*-----------------------------------------------------------------*/
8607 /* shiftL2Left2Result - shift left two bytes from left to result */
8608 /*-----------------------------------------------------------------*/
8610 shiftL2Left2Result (operand * left, int offl,
8611 operand * result, int offr, int shCount)
8614 bool pushedB = FALSE;
8617 if (sameRegs (AOP (result), AOP (left)) &&
8618 ((offl + MSB16) == offr))
8620 /* don't crash result[offr] */
8621 MOVA (aopGet (left, offl, FALSE, FALSE));
8622 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8623 usedB = !strncmp(x, "b", 1);
8625 else if (aopGetUsesAcc (result, offr))
8627 movLeft2Result (left, offl, result, offr, 0);
8630 emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8631 MOVA (aopGet (result, offr, FALSE, FALSE));
8632 emitcode ("xch", "a,b");
8637 movLeft2Result (left, offl, result, offr, 0);
8638 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8639 x = aopGet (result, offr, FALSE, FALSE);
8641 /* ax << shCount (x = lsb(result)) */
8642 AccAXLsh (x, shCount);
8645 emitcode ("xch", "a,b");
8646 aopPut (result, "a", offr);
8647 aopPut (result, "b", offr + MSB16);
8652 aopPut (result, "a", offr + MSB16);
8657 /*-----------------------------------------------------------------*/
8658 /* shiftR2Left2Result - shift right two bytes from left to result */
8659 /*-----------------------------------------------------------------*/
8661 shiftR2Left2Result (operand * left, int offl,
8662 operand * result, int offr,
8663 int shCount, int sign)
8666 bool pushedB = FALSE;
8669 if (sameRegs (AOP (result), AOP (left)) &&
8670 ((offl + MSB16) == offr))
8672 /* don't crash result[offr] */
8673 MOVA (aopGet (left, offl, FALSE, FALSE));
8674 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8675 usedB = !strncmp(x, "b", 1);
8677 else if (aopGetUsesAcc (result, offr))
8679 movLeft2Result (left, offl, result, offr, 0);
8682 emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8683 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8688 movLeft2Result (left, offl, result, offr, 0);
8689 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8690 x = aopGet (result, offr, FALSE, FALSE);
8692 /* a:x >> shCount (x = lsb(result)) */
8694 AccAXRshS (x, shCount);
8696 AccAXRsh (x, shCount);
8699 emitcode ("xch", "a,b");
8700 aopPut (result, "a", offr);
8701 emitcode ("xch", "a,b");
8704 if (getDataSize (result) > 1)
8705 aopPut (result, "a", offr + MSB16);
8708 /*-----------------------------------------------------------------*/
8709 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8710 /*-----------------------------------------------------------------*/
8712 shiftLLeftOrResult (operand * left, int offl,
8713 operand * result, int offr, int shCount)
8715 MOVA (aopGet (left, offl, FALSE, FALSE));
8716 /* shift left accumulator */
8718 /* or with result */
8719 if (aopGetUsesAcc (result, offr))
8721 emitcode ("xch", "a,b");
8722 MOVA (aopGet (result, offr, FALSE, FALSE));
8723 emitcode ("orl", "a,b");
8727 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8729 /* back to result */
8730 aopPut (result, "a", offr);
8733 /*-----------------------------------------------------------------*/
8734 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8735 /*-----------------------------------------------------------------*/
8737 shiftRLeftOrResult (operand * left, int offl,
8738 operand * result, int offr, int shCount)
8740 MOVA (aopGet (left, offl, FALSE, FALSE));
8741 /* shift right accumulator */
8743 /* or with result */
8744 if (aopGetUsesAcc(result, offr))
8746 emitcode ("xch", "a,b");
8747 MOVA (aopGet (result, offr, FALSE, FALSE));
8748 emitcode ("orl", "a,b");
8752 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8754 /* back to result */
8755 aopPut (result, "a", offr);
8758 /*-----------------------------------------------------------------*/
8759 /* genlshOne - left shift a one byte quantity by known count */
8760 /*-----------------------------------------------------------------*/
8762 genlshOne (operand * result, operand * left, int shCount)
8764 D (emitcode (";", "genlshOne"));
8766 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8769 /*-----------------------------------------------------------------*/
8770 /* genlshTwo - left shift two bytes by known amount != 0 */
8771 /*-----------------------------------------------------------------*/
8773 genlshTwo (operand * result, operand * left, int shCount)
8777 D (emitcode (";", "genlshTwo"));
8779 size = getDataSize (result);
8781 /* if shCount >= 8 */
8789 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8791 movLeft2Result (left, LSB, result, MSB16, 0);
8793 aopPut (result, zero, LSB);
8796 /* 1 <= shCount <= 7 */
8800 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8802 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8806 /*-----------------------------------------------------------------*/
8807 /* shiftLLong - shift left one long from left to result */
8808 /* offl = LSB or MSB16 */
8809 /*-----------------------------------------------------------------*/
8811 shiftLLong (operand * left, operand * result, int offr)
8814 int size = AOP_SIZE (result);
8816 if (size >= LSB + offr)
8818 l = aopGet (left, LSB, FALSE, FALSE);
8820 emitcode ("add", "a,acc");
8821 if (sameRegs (AOP (left), AOP (result)) &&
8822 size >= MSB16 + offr && offr != LSB)
8823 xch_a_aopGet (left, LSB + offr, FALSE, FALSE);
8825 aopPut (result, "a", LSB + offr);
8828 if (size >= MSB16 + offr)
8830 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8832 l = aopGet (left, MSB16, FALSE, FALSE);
8835 emitcode ("rlc", "a");
8836 if (sameRegs (AOP (left), AOP (result)) &&
8837 size >= MSB24 + offr && offr != LSB)
8838 xch_a_aopGet (left, MSB16 + offr, FALSE, FALSE);
8840 aopPut (result, "a", MSB16 + offr);
8843 if (size >= MSB24 + offr)
8845 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8847 l = aopGet (left, MSB24, FALSE, FALSE);
8850 emitcode ("rlc", "a");
8851 if (sameRegs (AOP (left), AOP (result)) &&
8852 size >= MSB32 + offr && offr != LSB)
8853 xch_a_aopGet (left, MSB24 + offr, FALSE, FALSE);
8855 aopPut (result, "a", MSB24 + offr);
8858 if (size > MSB32 + offr)
8860 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8862 l = aopGet (left, MSB32, FALSE, FALSE);
8865 emitcode ("rlc", "a");
8866 aopPut (result, "a", MSB32 + offr);
8869 aopPut (result, zero, LSB);
8872 /*-----------------------------------------------------------------*/
8873 /* genlshFour - shift four byte by a known amount != 0 */
8874 /*-----------------------------------------------------------------*/
8876 genlshFour (operand * result, operand * left, int shCount)
8880 D (emitcode (";", "genlshFour"));
8882 size = AOP_SIZE (result);
8884 /* if shifting more that 3 bytes */
8889 /* lowest order of left goes to the highest
8890 order of the destination */
8891 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8893 movLeft2Result (left, LSB, result, MSB32, 0);
8894 aopPut (result, zero, LSB);
8895 aopPut (result, zero, MSB16);
8896 aopPut (result, zero, MSB24);
8900 /* more than two bytes */
8901 else if (shCount >= 16)
8903 /* lower order two bytes goes to higher order two bytes */
8905 /* if some more remaining */
8907 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8910 movLeft2Result (left, MSB16, result, MSB32, 0);
8911 movLeft2Result (left, LSB, result, MSB24, 0);
8913 aopPut (result, zero, MSB16);
8914 aopPut (result, zero, LSB);
8918 /* if more than 1 byte */
8919 else if (shCount >= 8)
8921 /* lower order three bytes goes to higher order three bytes */
8926 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8928 movLeft2Result (left, LSB, result, MSB16, 0);
8934 movLeft2Result (left, MSB24, result, MSB32, 0);
8935 movLeft2Result (left, MSB16, result, MSB24, 0);
8936 movLeft2Result (left, LSB, result, MSB16, 0);
8937 aopPut (result, zero, LSB);
8939 else if (shCount == 1)
8940 shiftLLong (left, result, MSB16);
8943 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8944 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8945 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8946 aopPut (result, zero, LSB);
8951 /* 1 <= shCount <= 7 */
8952 else if (shCount <= 2)
8954 shiftLLong (left, result, LSB);
8956 shiftLLong (result, result, LSB);
8958 /* 3 <= shCount <= 7, optimize */
8961 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8962 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8963 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8967 /*-----------------------------------------------------------------*/
8968 /* genLeftShiftLiteral - left shifting by known count */
8969 /*-----------------------------------------------------------------*/
8971 genLeftShiftLiteral (operand * left,
8976 int shCount = (int) ulFromVal (AOP (right)->aopu.aop_lit);
8979 D (emitcode (";", "genLeftShiftLiteral"));
8981 freeAsmop (right, NULL, ic, TRUE);
8983 aopOp (left, ic, FALSE);
8984 aopOp (result, ic, FALSE);
8986 size = getSize (operandType (result));
8989 emitcode ("; shift left ", "result %d, left %d", size,
8993 /* I suppose that the left size >= result size */
8998 movLeft2Result (left, size, result, size, 0);
9001 else if (shCount >= (size * 8))
9005 aopPut (result, zero, size);
9013 genlshOne (result, left, shCount);
9017 genlshTwo (result, left, shCount);
9021 genlshFour (result, left, shCount);
9024 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9025 "*** ack! mystery literal shift!\n");
9029 freeAsmop (result, NULL, ic, TRUE);
9030 freeAsmop (left, NULL, ic, TRUE);
9033 /*-----------------------------------------------------------------*/
9034 /* genLeftShift - generates code for left shifting */
9035 /*-----------------------------------------------------------------*/
9037 genLeftShift (iCode * ic)
9039 operand *left, *right, *result;
9042 symbol *tlbl, *tlbl1;
9045 D (emitcode (";", "genLeftShift"));
9047 right = IC_RIGHT (ic);
9048 left = IC_LEFT (ic);
9049 result = IC_RESULT (ic);
9051 aopOp (right, ic, FALSE);
9053 /* if the shift count is known then do it
9054 as efficiently as possible */
9055 if (AOP_TYPE (right) == AOP_LIT)
9057 genLeftShiftLiteral (left, right, result, ic);
9061 /* shift count is unknown then we have to form
9062 a loop get the loop count in B : Note: we take
9063 only the lower order byte since shifting
9064 more that 32 bits make no sense anyway, ( the
9065 largest size of an object can be only 32 bits ) */
9068 MOVB (aopGet (right, 0, FALSE, FALSE));
9069 emitcode ("inc", "b");
9070 freeAsmop (right, NULL, ic, TRUE);
9071 aopOp (left, ic, FALSE);
9072 aopOp (result, ic, FALSE);
9074 /* now move the left to the result if they are not the same */
9075 if (!sameRegs (AOP (left), AOP (result)) &&
9076 AOP_SIZE (result) > 1)
9079 size = AOP_SIZE (result);
9083 l = aopGet (left, offset, FALSE, TRUE);
9084 if (*l == '@' && (IS_AOP_PREG (result)))
9087 emitcode ("mov", "a,%s", l);
9088 aopPut (result, "a", offset);
9091 aopPut (result, l, offset);
9096 tlbl = newiTempLabel (NULL);
9097 size = AOP_SIZE (result);
9099 tlbl1 = newiTempLabel (NULL);
9101 /* if it is only one byte then */
9104 symbol *tlbl1 = newiTempLabel (NULL);
9106 l = aopGet (left, 0, FALSE, FALSE);
9108 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9110 emitcode ("add", "a,acc");
9112 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9114 aopPut (result, "a", 0);
9118 reAdjustPreg (AOP (result));
9120 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9122 l = aopGet (result, offset, FALSE, FALSE);
9124 emitcode ("add", "a,acc");
9125 aopPut (result, "a", offset++);
9128 l = aopGet (result, offset, FALSE, FALSE);
9130 emitcode ("rlc", "a");
9131 aopPut (result, "a", offset++);
9133 reAdjustPreg (AOP (result));
9136 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9139 freeAsmop (result, NULL, ic, TRUE);
9140 freeAsmop (left, NULL, ic, TRUE);
9143 /*-----------------------------------------------------------------*/
9144 /* genrshOne - right shift a one byte quantity by known count */
9145 /*-----------------------------------------------------------------*/
9147 genrshOne (operand * result, operand * left,
9148 int shCount, int sign)
9150 D (emitcode (";", "genrshOne"));
9152 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9155 /*-----------------------------------------------------------------*/
9156 /* genrshTwo - right shift two bytes by known amount != 0 */
9157 /*-----------------------------------------------------------------*/
9159 genrshTwo (operand * result, operand * left,
9160 int shCount, int sign)
9162 D (emitcode (";", "genrshTwo"));
9164 /* if shCount >= 8 */
9169 shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
9171 movLeft2Result (left, MSB16, result, LSB, sign);
9172 addSign (result, MSB16, sign);
9175 /* 1 <= shCount <= 7 */
9177 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9180 /*-----------------------------------------------------------------*/
9181 /* shiftRLong - shift right one long from left to result */
9182 /* offl = LSB or MSB16 */
9183 /*-----------------------------------------------------------------*/
9185 shiftRLong (operand * left, int offl,
9186 operand * result, int sign)
9188 bool overlapping = regsInCommon (left, result) || operandsEqu(left, result);
9190 if (overlapping && offl>1)
9192 // we are in big trouble, but this shouldn't happen
9193 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9196 MOVA (aopGet (left, MSB32, FALSE, FALSE));
9203 emitcode ("rlc", "a");
9204 emitcode ("subb", "a,acc");
9205 if (overlapping && sameByte (AOP (left), MSB32, AOP (result), MSB32))
9207 xch_a_aopGet (left, MSB32, FALSE, FALSE);
9211 aopPut (result, "a", MSB32);
9212 MOVA (aopGet (left, MSB32, FALSE, FALSE));
9217 if (aopPutUsesAcc (result, zero, MSB32))
9219 emitcode("xch", "a,b");
9220 aopPut (result, zero, MSB32);
9221 emitcode("xch", "a,b");
9225 aopPut (result, zero, MSB32);
9232 emitcode ("clr", "c");
9236 emitcode ("mov", "c,acc.7");
9239 emitcode ("rrc", "a");
9241 if (overlapping && offl==MSB16 &&
9242 sameByte (AOP (left), MSB24, AOP (result), MSB32-offl))
9244 xch_a_aopGet (left, MSB24, FALSE, FALSE);
9248 aopPut (result, "a", MSB32 - offl);
9249 MOVA (aopGet (left, MSB24, FALSE, FALSE));
9252 emitcode ("rrc", "a");
9253 if (overlapping && offl==MSB16 &&
9254 sameByte (AOP (left), MSB16, AOP (result), MSB24-offl))
9256 xch_a_aopGet (left, MSB16, FALSE, FALSE);
9260 aopPut (result, "a", MSB24 - offl);
9261 MOVA (aopGet (left, MSB16, FALSE, FALSE));
9264 emitcode ("rrc", "a");
9267 aopPut (result, "a", MSB16 - offl);
9272 sameByte (AOP (left), LSB, AOP (result), MSB16-offl))
9274 xch_a_aopGet (left, LSB, FALSE, FALSE);
9278 aopPut (result, "a", MSB16 - offl);
9279 MOVA (aopGet (left, LSB, FALSE, FALSE));
9281 emitcode ("rrc", "a");
9282 aopPut (result, "a", LSB);
9286 /*-----------------------------------------------------------------*/
9287 /* genrshFour - shift four byte by a known amount != 0 */
9288 /*-----------------------------------------------------------------*/
9290 genrshFour (operand * result, operand * left,
9291 int shCount, int sign)
9293 D (emitcode (";", "genrshFour"));
9295 /* if shifting more that 3 bytes */
9300 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9302 movLeft2Result (left, MSB32, result, LSB, sign);
9303 addSign (result, MSB16, sign);
9305 else if (shCount >= 16)
9309 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9312 movLeft2Result (left, MSB24, result, LSB, 0);
9313 movLeft2Result (left, MSB32, result, MSB16, sign);
9315 addSign (result, MSB24, sign);
9317 else if (shCount >= 8)
9322 shiftRLong (left, MSB16, result, sign);
9324 else if (shCount == 0)
9326 movLeft2Result (left, MSB16, result, LSB, 0);
9327 movLeft2Result (left, MSB24, result, MSB16, 0);
9328 movLeft2Result (left, MSB32, result, MSB24, sign);
9329 addSign (result, MSB32, sign);
9333 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9334 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9335 /* the last shift is signed */
9336 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9337 addSign (result, MSB32, sign);
9342 /* 1 <= shCount <= 7 */
9345 shiftRLong (left, LSB, result, sign);
9347 shiftRLong (result, LSB, result, sign);
9351 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9352 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9353 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9358 /*-----------------------------------------------------------------*/
9359 /* genRightShiftLiteral - right shifting by known count */
9360 /*-----------------------------------------------------------------*/
9362 genRightShiftLiteral (operand * left,
9368 int shCount = (int) ulFromVal (AOP (right)->aopu.aop_lit);
9371 D (emitcode (";", "genRightShiftLiteral"));
9373 freeAsmop (right, NULL, ic, TRUE);
9375 aopOp (left, ic, FALSE);
9376 aopOp (result, ic, FALSE);
9379 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9383 size = getDataSize (left);
9384 /* test the LEFT size !!! */
9386 /* I suppose that the left size >= result size */
9389 size = getDataSize (result);
9391 movLeft2Result (left, size, result, size, 0);
9394 else if (shCount >= (size * 8))
9398 /* get sign in acc.7 */
9399 MOVA (aopGet (left, size - 1, FALSE, FALSE));
9401 addSign (result, LSB, sign);
9408 genrshOne (result, left, shCount, sign);
9412 genrshTwo (result, left, shCount, sign);
9416 genrshFour (result, left, shCount, sign);
9422 freeAsmop (result, NULL, ic, TRUE);
9423 freeAsmop (left, NULL, ic, TRUE);
9426 /*-----------------------------------------------------------------*/
9427 /* genSignedRightShift - right shift of signed number */
9428 /*-----------------------------------------------------------------*/
9430 genSignedRightShift (iCode * ic)
9432 operand *right, *left, *result;
9435 symbol *tlbl, *tlbl1;
9438 D (emitcode (";", "genSignedRightShift"));
9440 /* we do it the hard way put the shift count in b
9441 and loop thru preserving the sign */
9443 right = IC_RIGHT (ic);
9444 left = IC_LEFT (ic);
9445 result = IC_RESULT (ic);
9447 aopOp (right, ic, FALSE);
9450 if (AOP_TYPE (right) == AOP_LIT)
9452 genRightShiftLiteral (left, right, result, ic, 1);
9455 /* shift count is unknown then we have to form
9456 a loop get the loop count in B : Note: we take
9457 only the lower order byte since shifting
9458 more that 32 bits make no sense anyway, ( the
9459 largest size of an object can be only 32 bits ) */
9462 MOVB (aopGet (right, 0, FALSE, FALSE));
9463 emitcode ("inc", "b");
9464 freeAsmop (right, NULL, ic, TRUE);
9465 aopOp (left, ic, FALSE);
9466 aopOp (result, ic, FALSE);
9468 /* now move the left to the result if they are not the
9470 if (!sameRegs (AOP (left), AOP (result)) &&
9471 AOP_SIZE (result) > 1)
9474 size = AOP_SIZE (result);
9478 l = aopGet (left, offset, FALSE, TRUE);
9479 if (*l == '@' && IS_AOP_PREG (result))
9482 emitcode ("mov", "a,%s", l);
9483 aopPut (result, "a", offset);
9486 aopPut (result, l, offset);
9491 /* mov the highest order bit to OVR */
9492 tlbl = newiTempLabel (NULL);
9493 tlbl1 = newiTempLabel (NULL);
9495 size = AOP_SIZE (result);
9497 MOVA (aopGet (left, offset, FALSE, FALSE));
9498 emitcode ("rlc", "a");
9499 emitcode ("mov", "ov,c");
9500 /* if it is only one byte then */
9503 l = aopGet (left, 0, FALSE, FALSE);
9505 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9507 emitcode ("mov", "c,ov");
9508 emitcode ("rrc", "a");
9510 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9512 aopPut (result, "a", 0);
9516 reAdjustPreg (AOP (result));
9517 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9519 emitcode ("mov", "c,ov");
9522 l = aopGet (result, offset, FALSE, FALSE);
9524 emitcode ("rrc", "a");
9525 aopPut (result, "a", offset--);
9527 reAdjustPreg (AOP (result));
9529 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9533 freeAsmop (result, NULL, ic, TRUE);
9534 freeAsmop (left, NULL, ic, TRUE);
9537 /*-----------------------------------------------------------------*/
9538 /* genRightShift - generate code for right shifting */
9539 /*-----------------------------------------------------------------*/
9541 genRightShift (iCode * ic)
9543 operand *right, *left, *result;
9547 symbol *tlbl, *tlbl1;
9550 D (emitcode (";", "genRightShift"));
9552 /* if signed then we do it the hard way preserve the
9553 sign bit moving it inwards */
9554 letype = getSpec (operandType (IC_LEFT (ic)));
9556 if (!SPEC_USIGN (letype))
9558 genSignedRightShift (ic);
9562 /* signed & unsigned types are treated the same : i.e. the
9563 signed is NOT propagated inwards : quoting from the
9564 ANSI - standard : "for E1 >> E2, is equivalent to division
9565 by 2**E2 if unsigned or if it has a non-negative value,
9566 otherwise the result is implementation defined ", MY definition
9567 is that the sign does not get propagated */
9569 right = IC_RIGHT (ic);
9570 left = IC_LEFT (ic);
9571 result = IC_RESULT (ic);
9573 aopOp (right, ic, FALSE);
9575 /* if the shift count is known then do it
9576 as efficiently as possible */
9577 if (AOP_TYPE (right) == AOP_LIT)
9579 genRightShiftLiteral (left, right, result, ic, 0);
9583 /* shift count is unknown then we have to form
9584 a loop get the loop count in B : Note: we take
9585 only the lower order byte since shifting
9586 more that 32 bits make no sense anyway, ( the
9587 largest size of an object can be only 32 bits ) */
9590 MOVB (aopGet (right, 0, FALSE, FALSE));
9591 emitcode ("inc", "b");
9592 freeAsmop (right, NULL, ic, TRUE);
9593 aopOp (left, ic, FALSE);
9594 aopOp (result, ic, FALSE);
9596 /* now move the left to the result if they are not the
9598 if (!sameRegs (AOP (left), AOP (result)) &&
9599 AOP_SIZE (result) > 1)
9601 size = AOP_SIZE (result);
9605 l = aopGet (left, offset, FALSE, TRUE);
9606 if (*l == '@' && IS_AOP_PREG (result))
9609 emitcode ("mov", "a,%s", l);
9610 aopPut (result, "a", offset);
9613 aopPut (result, l, offset);
9618 tlbl = newiTempLabel (NULL);
9619 tlbl1 = newiTempLabel (NULL);
9620 size = AOP_SIZE (result);
9623 /* if it is only one byte then */
9626 l = aopGet (left, 0, FALSE, FALSE);
9628 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9631 emitcode ("rrc", "a");
9633 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9635 aopPut (result, "a", 0);
9639 reAdjustPreg (AOP (result));
9640 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9645 l = aopGet (result, offset, FALSE, FALSE);
9647 emitcode ("rrc", "a");
9648 aopPut (result, "a", offset--);
9650 reAdjustPreg (AOP (result));
9653 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9657 freeAsmop (result, NULL, ic, TRUE);
9658 freeAsmop (left, NULL, ic, TRUE);
9661 /*-----------------------------------------------------------------*/
9662 /* emitPtrByteGet - emits code to get a byte into A through a */
9663 /* pointer register (R0, R1, or DPTR). The */
9664 /* original value of A can be preserved in B. */
9665 /*-----------------------------------------------------------------*/
9667 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9674 emitcode ("mov", "b,a");
9675 emitcode ("mov", "a,@%s", rname);
9680 emitcode ("mov", "b,a");
9681 emitcode ("movx", "a,@%s", rname);
9686 emitcode ("mov", "b,a");
9687 emitcode ("movx", "a,@dptr");
9692 emitcode ("mov", "b,a");
9693 emitcode ("clr", "a");
9694 emitcode ("movc", "a,@a+dptr");
9700 emitcode ("push", "b");
9701 emitcode ("push", "acc");
9703 emitcode ("lcall", "__gptrget");
9705 emitcode ("pop", "b");
9710 /*-----------------------------------------------------------------*/
9711 /* emitPtrByteSet - emits code to set a byte from src through a */
9712 /* pointer register (R0, R1, or DPTR). */
9713 /*-----------------------------------------------------------------*/
9715 emitPtrByteSet (char *rname, int p_type, char *src)
9724 emitcode ("mov", "@%s,a", rname);
9727 emitcode ("mov", "@%s,%s", rname, src);
9732 emitcode ("movx", "@%s,a", rname);
9737 emitcode ("movx", "@dptr,a");
9742 emitcode ("lcall", "__gptrput");
9747 /*-----------------------------------------------------------------*/
9748 /* genUnpackBits - generates code for unpacking bits */
9749 /*-----------------------------------------------------------------*/
9751 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9753 int offset = 0; /* result byte offset */
9754 int rsize; /* result size */
9755 int rlen = 0; /* remaining bitfield length */
9756 sym_link *etype; /* bitfield type information */
9757 int blen; /* bitfield length */
9758 int bstr; /* bitfield starting bit within byte */
9759 static char* const accBits[] = {"acc.0", "acc.1", "acc.2", "acc.3",
9760 "acc.4", "acc.5", "acc.6", "acc.7"};
9762 D(emitcode (";", "genUnpackBits"));
9764 etype = getSpec (operandType (result));
9765 rsize = getSize (operandType (result));
9766 blen = SPEC_BLEN (etype);
9767 bstr = SPEC_BSTR (etype);
9769 if (ifx && blen <= 8)
9771 emitPtrByteGet (rname, ptype, FALSE);
9774 return accBits[bstr];;
9779 emitcode ("anl", "a,#0x%02x",
9780 (((unsigned char) -1) >> (8 - blen)) << bstr);
9786 /* If the bitfield length is less than a byte */
9789 emitPtrByteGet (rname, ptype, FALSE);
9791 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9792 if (!SPEC_USIGN (etype))
9794 /* signed bitfield */
9795 symbol *tlbl = newiTempLabel (NULL);
9797 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9798 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9801 aopPut (result, "a", offset++);
9805 /* Bit field did not fit in a byte. Copy all
9806 but the partial byte at the end. */
9807 for (rlen=blen;rlen>=8;rlen-=8)
9809 emitPtrByteGet (rname, ptype, FALSE);
9810 aopPut (result, "a", offset++);
9812 emitcode ("inc", "%s", rname);
9815 /* Handle the partial byte at the end */
9818 emitPtrByteGet (rname, ptype, FALSE);
9819 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9820 if (!SPEC_USIGN (etype))
9822 /* signed bitfield */
9823 symbol *tlbl = newiTempLabel (NULL);
9825 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9826 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9829 aopPut (result, "a", offset++);
9837 if (SPEC_USIGN (etype))
9841 /* signed bitfield: sign extension with 0x00 or 0xff */
9842 emitcode ("rlc", "a");
9843 emitcode ("subb", "a,acc");
9849 aopPut (result, source, offset++);
9855 /*-----------------------------------------------------------------*/
9856 /* genDataPointerGet - generates code when ptr offset is known */
9857 /*-----------------------------------------------------------------*/
9859 genDataPointerGet (operand * left,
9865 int size, offset = 0;
9867 D (emitcode (";", "genDataPointerGet"));
9869 aopOp (result, ic, TRUE);
9871 /* get the string representation of the name */
9872 l = aopGet (left, 0, FALSE, TRUE);
9874 size = AOP_SIZE (result);
9879 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
9883 SNPRINTF (buffer, sizeof(buffer), "%s", l);
9885 aopPut (result, buffer, offset++);
9888 freeAsmop (result, NULL, ic, TRUE);
9889 freeAsmop (left, NULL, ic, TRUE);
9892 /*-----------------------------------------------------------------*/
9893 /* genNearPointerGet - emitcode for near pointer fetch */
9894 /*-----------------------------------------------------------------*/
9896 genNearPointerGet (operand * left,
9905 char *ifxCond = "a";
9906 sym_link *rtype, *retype;
9907 sym_link *ltype = operandType (left);
9909 D (emitcode (";", "genNearPointerGet"));
9911 rtype = operandType (result);
9912 retype = getSpec (rtype);
9914 aopOp (left, ic, FALSE);
9916 /* if left is rematerialisable and
9917 result is not bitfield variable type and
9918 the left is pointer to data space i.e
9919 lower 128 bytes of space */
9920 if (AOP_TYPE (left) == AOP_IMMD &&
9921 !IS_BITFIELD (retype) &&
9922 DCL_TYPE (ltype) == POINTER)
9924 genDataPointerGet (left, result, ic);
9928 //aopOp (result, ic, FALSE);
9929 aopOp (result, ic, result?TRUE:FALSE);
9931 /* if the value is already in a pointer register
9932 then don't need anything more */
9933 if (!AOP_INPREG (AOP (left)))
9935 if (IS_AOP_PREG (left))
9937 // Aha, it is a pointer, just in disguise.
9938 rname = aopGet (left, 0, FALSE, FALSE);
9941 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9942 __FILE__, __LINE__);
9947 emitcode ("mov", "a%s,%s", rname + 1, rname);
9948 rname++; // skip the '@'.
9953 /* otherwise get a free pointer register */
9955 preg = getFreePtr (ic, &aop, FALSE);
9956 emitcode ("mov", "%s,%s",
9958 aopGet (left, 0, FALSE, TRUE));
9963 rname = aopGet (left, 0, FALSE, FALSE);
9965 /* if bitfield then unpack the bits */
9966 if (IS_BITFIELD (retype))
9967 ifxCond = genUnpackBits (result, rname, POINTER, ifx);
9970 /* we have can just get the values */
9971 int size = AOP_SIZE (result);
9976 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9979 emitcode ("mov", "a,@%s", rname);
9981 aopPut (result, "a", offset);
9987 SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
9988 aopPut (result, buffer, offset);
9992 emitcode ("inc", "%s", rname);
9996 /* now some housekeeping stuff */
9997 if (aop) /* we had to allocate for this iCode */
9999 if (pi) { /* post increment present */
10000 aopPut (left, rname, 0);
10002 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
10006 /* we did not allocate which means left
10007 already in a pointer register, then
10008 if size > 0 && this could be used again
10009 we have to point it back to where it
10011 if ((AOP_SIZE (result) > 1 &&
10012 !OP_SYMBOL (left)->remat &&
10013 (OP_SYMBOL (left)->liveTo > ic->seq ||
10017 int size = AOP_SIZE (result) - 1;
10019 emitcode ("dec", "%s", rname);
10023 if (ifx && !ifx->generated)
10025 genIfxJump (ifx, ifxCond, left, NULL, result);
10029 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
10030 freeAsmop (left, NULL, ic, TRUE);
10031 if (pi) pi->generated = 1;
10034 /*-----------------------------------------------------------------*/
10035 /* genPagedPointerGet - emitcode for paged pointer fetch */
10036 /*-----------------------------------------------------------------*/
10038 genPagedPointerGet (operand * left,
10047 char *ifxCond = "a";
10048 sym_link *rtype, *retype;
10050 D (emitcode (";", "genPagedPointerGet"));
10052 rtype = operandType (result);
10053 retype = getSpec (rtype);
10055 aopOp (left, ic, FALSE);
10057 aopOp (result, ic, FALSE);
10059 /* if the value is already in a pointer register
10060 then don't need anything more */
10061 if (!AOP_INPREG (AOP (left)))
10063 /* otherwise get a free pointer register */
10064 aop = newAsmop (0);
10065 preg = getFreePtr (ic, &aop, FALSE);
10066 emitcode ("mov", "%s,%s",
10068 aopGet (left, 0, FALSE, TRUE));
10069 rname = preg->name;
10072 rname = aopGet (left, 0, FALSE, FALSE);
10074 /* if bitfield then unpack the bits */
10075 if (IS_BITFIELD (retype))
10076 ifxCond = genUnpackBits (result, rname, PPOINTER, ifx);
10079 /* we have can just get the values */
10080 int size = AOP_SIZE (result);
10086 emitcode ("movx", "a,@%s", rname);
10088 aopPut (result, "a", offset);
10093 emitcode ("inc", "%s", rname);
10097 /* now some housekeeping stuff */
10098 if (aop) /* we had to allocate for this iCode */
10101 aopPut (left, rname, 0);
10102 freeAsmop (NULL, aop, ic, TRUE);
10106 /* we did not allocate which means left
10107 already in a pointer register, then
10108 if size > 0 && this could be used again
10109 we have to point it back to where it
10111 if ((AOP_SIZE (result) > 1 &&
10112 !OP_SYMBOL (left)->remat &&
10113 (OP_SYMBOL (left)->liveTo > ic->seq ||
10117 int size = AOP_SIZE (result) - 1;
10119 emitcode ("dec", "%s", rname);
10123 if (ifx && !ifx->generated)
10125 genIfxJump (ifx, ifxCond, left, NULL, result);
10129 freeAsmop (result, NULL, ic, TRUE);
10130 freeAsmop (left, NULL, ic, TRUE);
10131 if (pi) pi->generated = 1;
10134 /*--------------------------------------------------------------------*/
10135 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
10136 /*--------------------------------------------------------------------*/
10138 loadDptrFromOperand (operand *op, bool loadBToo)
10140 if (AOP_TYPE (op) != AOP_STR)
10142 /* if this is rematerializable */
10143 if (AOP_TYPE (op) == AOP_IMMD)
10145 emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
10148 if (AOP(op)->aopu.aop_immd.from_cast_remat)
10149 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
10152 wassertl(FALSE, "need pointerCode");
10153 emitcode (";", "mov b,???");
10154 /* genPointerGet and genPointerSet originally did different
10155 ** things for this case. Both seem wrong.
10156 ** from genPointerGet:
10157 ** emitcode ("mov", "b,#%d", pointerCode (retype));
10158 ** from genPointerSet:
10159 ** emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
10164 else if (AOP_TYPE (op) == AOP_DPTR)
10168 MOVA (aopGet (op, 0, FALSE, FALSE));
10169 emitcode ("push", "acc");
10170 MOVA (aopGet (op, 1, FALSE, FALSE));
10171 emitcode ("push", "acc");
10172 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10173 emitcode ("pop", "dph");
10174 emitcode ("pop", "dpl");
10178 MOVA (aopGet (op, 0, FALSE, FALSE));
10179 emitcode ("push", "acc");
10180 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10181 emitcode ("pop", "dpl");
10185 { /* we need to get it byte by byte */
10186 emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
10187 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10189 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10194 /*-----------------------------------------------------------------*/
10195 /* genFarPointerGet - get value from far space */
10196 /*-----------------------------------------------------------------*/
10198 genFarPointerGet (operand * left,
10199 operand * result, iCode * ic, iCode * pi, iCode * ifx)
10202 char *ifxCond = "a";
10203 sym_link *retype = getSpec (operandType (result));
10205 D (emitcode (";", "genFarPointerGet"));
10207 aopOp (left, ic, FALSE);
10208 loadDptrFromOperand (left, FALSE);
10210 /* so dptr now contains the address */
10211 aopOp (result, ic, FALSE);
10213 /* if bit then unpack */
10214 if (IS_BITFIELD (retype))
10215 ifxCond = genUnpackBits (result, "dptr", FPOINTER, ifx);
10218 size = AOP_SIZE (result);
10223 emitcode ("movx", "a,@dptr");
10225 aopPut (result, "a", offset++);
10227 emitcode ("inc", "dptr");
10231 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10233 aopPut (left, "dpl", 0);
10234 aopPut (left, "dph", 1);
10238 if (ifx && !ifx->generated)
10240 genIfxJump (ifx, ifxCond, left, NULL, result);
10243 freeAsmop (result, NULL, ic, TRUE);
10244 freeAsmop (left, NULL, ic, TRUE);
10247 /*-----------------------------------------------------------------*/
10248 /* genCodePointerGet - get value from code space */
10249 /*-----------------------------------------------------------------*/
10251 genCodePointerGet (operand * left,
10252 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10255 char *ifxCond = "a";
10256 sym_link *retype = getSpec (operandType (result));
10258 D (emitcode (";", "genCodePointerGet"));
10260 aopOp (left, ic, FALSE);
10261 loadDptrFromOperand (left, FALSE);
10263 /* so dptr now contains the address */
10264 aopOp (result, ic, FALSE);
10266 /* if bit then unpack */
10267 if (IS_BITFIELD (retype))
10268 ifxCond = genUnpackBits (result, "dptr", CPOINTER, ifx);
10271 size = AOP_SIZE (result);
10276 emitcode ("clr", "a");
10277 emitcode ("movc", "a,@a+dptr");
10279 aopPut (result, "a", offset++);
10281 emitcode ("inc", "dptr");
10285 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10287 aopPut (left, "dpl", 0);
10288 aopPut (left, "dph", 1);
10292 if (ifx && !ifx->generated)
10294 genIfxJump (ifx, ifxCond, left, NULL, result);
10297 freeAsmop (result, NULL, ic, TRUE);
10298 freeAsmop (left, NULL, ic, TRUE);
10301 /*-----------------------------------------------------------------*/
10302 /* genGenPointerGet - get value from generic pointer space */
10303 /*-----------------------------------------------------------------*/
10305 genGenPointerGet (operand * left,
10306 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10309 char *ifxCond = "a";
10310 sym_link *retype = getSpec (operandType (result));
10312 D (emitcode (";", "genGenPointerGet"));
10314 aopOp (left, ic, FALSE);
10315 loadDptrFromOperand (left, TRUE);
10317 /* so dptr now contains the address */
10318 aopOp (result, ic, FALSE);
10320 /* if bit then unpack */
10321 if (IS_BITFIELD (retype))
10323 ifxCond = genUnpackBits (result, "dptr", GPOINTER, ifx);
10327 size = AOP_SIZE (result);
10332 emitcode ("lcall", "__gptrget");
10334 aopPut (result, "a", offset++);
10336 emitcode ("inc", "dptr");
10340 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10342 aopPut (left, "dpl", 0);
10343 aopPut (left, "dph", 1);
10347 if (ifx && !ifx->generated)
10349 genIfxJump (ifx, ifxCond, left, NULL, result);
10352 freeAsmop (result, NULL, ic, TRUE);
10353 freeAsmop (left, NULL, ic, TRUE);
10356 /*-----------------------------------------------------------------*/
10357 /* genPointerGet - generate code for pointer get */
10358 /*-----------------------------------------------------------------*/
10360 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
10362 operand *left, *result;
10363 sym_link *type, *etype;
10366 D (emitcode (";", "genPointerGet"));
10368 left = IC_LEFT (ic);
10369 result = IC_RESULT (ic);
10371 if (getSize (operandType (result))>1)
10374 /* depending on the type of pointer we need to
10375 move it to the correct pointer register */
10376 type = operandType (left);
10377 etype = getSpec (type);
10378 /* if left is of type of pointer then it is simple */
10379 if (IS_PTR (type) && !IS_FUNC (type->next))
10381 p_type = DCL_TYPE (type);
10385 /* we have to go by the storage class */
10386 p_type = PTR_TYPE (SPEC_OCLS (etype));
10389 /* special case when cast remat */
10390 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10391 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10393 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10394 type = operandType (left);
10395 p_type = DCL_TYPE (type);
10397 /* now that we have the pointer type we assign
10398 the pointer values */
10404 genNearPointerGet (left, result, ic, pi, ifx);
10408 genPagedPointerGet (left, result, ic, pi, ifx);
10412 genFarPointerGet (left, result, ic, pi, ifx);
10416 genCodePointerGet (left, result, ic, pi, ifx);
10420 genGenPointerGet (left, result, ic, pi, ifx);
10426 /*-----------------------------------------------------------------*/
10427 /* genPackBits - generates code for packed bit storage */
10428 /*-----------------------------------------------------------------*/
10430 genPackBits (sym_link * etype,
10432 char *rname, int p_type)
10434 int offset = 0; /* source byte offset */
10435 int rlen = 0; /* remaining bitfield length */
10436 int blen; /* bitfield length */
10437 int bstr; /* bitfield starting bit within byte */
10438 int litval; /* source literal value (if AOP_LIT) */
10439 unsigned char mask; /* bitmask within current byte */
10441 D(emitcode (";", "genPackBits"));
10443 blen = SPEC_BLEN (etype);
10444 bstr = SPEC_BSTR (etype);
10446 /* If the bitfield length is less than a byte */
10449 mask = ((unsigned char) (0xFF << (blen + bstr)) |
10450 (unsigned char) (0xFF >> (8 - bstr)));
10452 if (AOP_TYPE (right) == AOP_LIT)
10454 /* Case with a bitfield length <8 and literal source
10456 litval = (int) ulFromVal (AOP (right)->aopu.aop_lit);
10458 litval &= (~mask) & 0xff;
10459 emitPtrByteGet (rname, p_type, FALSE);
10460 if ((mask|litval)!=0xff)
10461 emitcode ("anl","a,#0x%02x", mask);
10463 emitcode ("orl","a,#0x%02x", litval);
10467 if ((blen==1) && (p_type!=GPOINTER))
10469 /* Case with a bitfield length == 1 and no generic pointer
10471 if (AOP_TYPE (right) == AOP_CRY)
10472 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10475 MOVA (aopGet (right, 0, FALSE, FALSE));
10476 emitcode ("rrc","a");
10478 emitPtrByteGet (rname, p_type, FALSE);
10479 emitcode ("mov","acc.%d,c",bstr);
10484 /* Case with a bitfield length < 8 and arbitrary source
10486 MOVA (aopGet (right, 0, FALSE, FALSE));
10487 /* shift and mask source value */
10489 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10491 pushedB = pushB ();
10492 /* transfer A to B and get next byte */
10493 emitPtrByteGet (rname, p_type, TRUE);
10495 emitcode ("anl", "a,#0x%02x", mask);
10496 emitcode ("orl", "a,b");
10497 if (p_type == GPOINTER)
10498 emitcode ("pop", "b");
10504 emitPtrByteSet (rname, p_type, "a");
10508 /* Bit length is greater than 7 bits. In this case, copy */
10509 /* all except the partial byte at the end */
10510 for (rlen=blen;rlen>=8;rlen-=8)
10512 emitPtrByteSet (rname, p_type,
10513 aopGet (right, offset++, FALSE, TRUE) );
10515 emitcode ("inc", "%s", rname);
10518 /* If there was a partial byte at the end */
10521 mask = (((unsigned char) -1 << rlen) & 0xff);
10523 if (AOP_TYPE (right) == AOP_LIT)
10525 /* Case with partial byte and literal source
10527 litval = (int) ulFromVal (AOP (right)->aopu.aop_lit);
10528 litval >>= (blen-rlen);
10529 litval &= (~mask) & 0xff;
10530 emitPtrByteGet (rname, p_type, FALSE);
10531 if ((mask|litval)!=0xff)
10532 emitcode ("anl","a,#0x%02x", mask);
10534 emitcode ("orl","a,#0x%02x", litval);
10539 /* Case with partial byte and arbitrary source
10541 MOVA (aopGet (right, offset++, FALSE, FALSE));
10542 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10544 pushedB = pushB ();
10545 /* transfer A to B and get next byte */
10546 emitPtrByteGet (rname, p_type, TRUE);
10548 emitcode ("anl", "a,#0x%02x", mask);
10549 emitcode ("orl", "a,b");
10550 if (p_type == GPOINTER)
10551 emitcode ("pop", "b");
10555 emitPtrByteSet (rname, p_type, "a");
10560 /*-----------------------------------------------------------------*/
10561 /* genDataPointerSet - remat pointer to data space */
10562 /*-----------------------------------------------------------------*/
10564 genDataPointerSet (operand * right,
10568 int size, offset = 0;
10569 char *l, buffer[256];
10571 D (emitcode (";", "genDataPointerSet"));
10573 aopOp (right, ic, FALSE);
10575 l = aopGet (result, 0, FALSE, TRUE);
10577 size = max (AOP_SIZE (right), AOP_SIZE (result));
10581 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
10583 SNPRINTF (buffer, sizeof(buffer), "%s", l);
10584 emitcode ("mov", "%s,%s", buffer,
10585 aopGet (right, offset++, FALSE, FALSE));
10588 freeAsmop (right, NULL, ic, TRUE);
10589 freeAsmop (result, NULL, ic, TRUE);
10592 /*-----------------------------------------------------------------*/
10593 /* genNearPointerSet - emitcode for near pointer put */
10594 /*-----------------------------------------------------------------*/
10596 genNearPointerSet (operand * right,
10604 sym_link *retype, *letype;
10605 sym_link *ptype = operandType (result);
10607 D (emitcode (";", "genNearPointerSet"));
10609 retype = getSpec (operandType (right));
10610 letype = getSpec (ptype);
10612 aopOp (result, ic, FALSE);
10614 /* if the result is rematerializable &
10615 in data space & not a bit variable */
10616 if (AOP_TYPE (result) == AOP_IMMD &&
10617 DCL_TYPE (ptype) == POINTER &&
10618 !IS_BITVAR (retype) &&
10619 !IS_BITVAR (letype))
10621 genDataPointerSet (right, result, ic);
10625 /* if the value is already in a pointer register
10626 then don't need anything more */
10627 if (!AOP_INPREG (AOP (result)))
10629 if (IS_AOP_PREG (result))
10631 // Aha, it is a pointer, just in disguise.
10632 rname = aopGet (result, 0, FALSE, FALSE);
10635 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10636 __FILE__, __LINE__);
10641 emitcode ("mov", "a%s,%s", rname + 1, rname);
10642 rname++; // skip the '@'.
10647 /* otherwise get a free pointer register */
10648 aop = newAsmop (0);
10649 preg = getFreePtr (ic, &aop, FALSE);
10650 emitcode ("mov", "%s,%s",
10652 aopGet (result, 0, FALSE, TRUE));
10653 rname = preg->name;
10658 rname = aopGet (result, 0, FALSE, FALSE);
10661 aopOp (right, ic, FALSE);
10663 /* if bitfield then unpack the bits */
10664 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10665 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10668 /* we can just get the values */
10669 int size = AOP_SIZE (right);
10674 l = aopGet (right, offset, FALSE, TRUE);
10675 if ((*l == '@') || (strcmp (l, "acc") == 0))
10678 emitcode ("mov", "@%s,a", rname);
10681 emitcode ("mov", "@%s,%s", rname, l);
10683 emitcode ("inc", "%s", rname);
10688 /* now some housekeeping stuff */
10689 if (aop) /* we had to allocate for this iCode */
10692 aopPut (result, rname, 0);
10693 freeAsmop (NULL, aop, ic, TRUE);
10697 /* we did not allocate which means left
10698 already in a pointer register, then
10699 if size > 0 && this could be used again
10700 we have to point it back to where it
10702 if ((AOP_SIZE (right) > 1 &&
10703 !OP_SYMBOL (result)->remat &&
10704 (OP_SYMBOL (result)->liveTo > ic->seq ||
10708 int size = AOP_SIZE (right) - 1;
10710 emitcode ("dec", "%s", rname);
10717 freeAsmop (right, NULL, ic, TRUE);
10718 freeAsmop (result, NULL, ic, TRUE);
10721 /*-----------------------------------------------------------------*/
10722 /* genPagedPointerSet - emitcode for Paged pointer put */
10723 /*-----------------------------------------------------------------*/
10725 genPagedPointerSet (operand * right,
10733 sym_link *retype, *letype;
10735 D (emitcode (";", "genPagedPointerSet"));
10737 retype = getSpec (operandType (right));
10738 letype = getSpec (operandType (result));
10740 aopOp (result, ic, FALSE);
10742 /* if the value is already in a pointer register
10743 then don't need anything more */
10744 if (!AOP_INPREG (AOP (result)))
10746 if (IS_AOP_PREG (result))
10748 // Aha, it is a pointer, just in disguise.
10749 rname = aopGet (result, 0, FALSE, FALSE);
10752 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10753 __FILE__, __LINE__);
10758 emitcode ("mov", "a%s,%s", rname + 1, rname);
10759 rname++; // skip the '@'.
10764 /* otherwise get a free pointer register */
10765 aop = newAsmop (0);
10766 preg = getFreePtr (ic, &aop, FALSE);
10767 emitcode ("mov", "%s,%s",
10769 aopGet (result, 0, FALSE, TRUE));
10770 rname = preg->name;
10775 rname = aopGet (result, 0, FALSE, FALSE);
10778 aopOp (right, ic, FALSE);
10780 /* if bitfield then unpack the bits */
10781 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10782 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10785 /* we can just get the values */
10786 int size = AOP_SIZE (right);
10791 l = aopGet (right, offset, FALSE, TRUE);
10793 emitcode ("movx", "@%s,a", rname);
10795 emitcode ("inc", "%s", rname);
10800 /* now some housekeeping stuff */
10801 if (aop) /* we had to allocate for this iCode */
10804 aopPut (result, rname, 0);
10805 freeAsmop (NULL, aop, ic, TRUE);
10809 /* we did not allocate which means left
10810 already in a pointer register, then
10811 if size > 0 && this could be used again
10812 we have to point it back to where it
10814 if (AOP_SIZE (right) > 1 &&
10815 !OP_SYMBOL (result)->remat &&
10816 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth) &&
10819 int size = AOP_SIZE (right) - 1;
10821 emitcode ("dec", "%s", rname);
10828 freeAsmop (right, NULL, ic, TRUE);
10829 freeAsmop (result, NULL, ic, TRUE);
10832 /*-----------------------------------------------------------------*/
10833 /* genFarPointerSet - set value from far space */
10834 /*-----------------------------------------------------------------*/
10836 genFarPointerSet (operand * right,
10837 operand * result, iCode * ic, iCode * pi)
10840 sym_link *retype = getSpec (operandType (right));
10841 sym_link *letype = getSpec (operandType (result));
10843 D(emitcode (";", "genFarPointerSet"));
10845 aopOp (result, ic, FALSE);
10846 loadDptrFromOperand (result, FALSE);
10848 /* so dptr now contains the address */
10849 aopOp (right, ic, FALSE);
10851 /* if bit then unpack */
10852 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10853 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10856 size = AOP_SIZE (right);
10861 char *l = aopGet (right, offset++, FALSE, FALSE);
10863 emitcode ("movx", "@dptr,a");
10865 emitcode ("inc", "dptr");
10868 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10869 aopPut (result, "dpl", 0);
10870 aopPut (result, "dph", 1);
10873 freeAsmop (result, NULL, ic, TRUE);
10874 freeAsmop (right, NULL, ic, TRUE);
10877 /*-----------------------------------------------------------------*/
10878 /* genGenPointerSet - set value from generic pointer space */
10879 /*-----------------------------------------------------------------*/
10881 genGenPointerSet (operand * right,
10882 operand * result, iCode * ic, iCode * pi)
10885 sym_link *retype = getSpec (operandType (right));
10886 sym_link *letype = getSpec (operandType (result));
10888 D (emitcode (";", "genGenPointerSet"));
10890 aopOp (result, ic, FALSE);
10891 loadDptrFromOperand (result, TRUE);
10893 /* so dptr now contains the address */
10894 aopOp (right, ic, FALSE);
10896 /* if bit then unpack */
10897 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10899 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10903 size = AOP_SIZE (right);
10908 char *l = aopGet (right, offset++, FALSE, FALSE);
10910 emitcode ("lcall", "__gptrput");
10912 emitcode ("inc", "dptr");
10916 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10917 aopPut (result, "dpl", 0);
10918 aopPut (result, "dph", 1);
10921 freeAsmop (result, NULL, ic, TRUE);
10922 freeAsmop (right, NULL, ic, TRUE);
10925 /*-----------------------------------------------------------------*/
10926 /* genPointerSet - stores the value into a pointer location */
10927 /*-----------------------------------------------------------------*/
10929 genPointerSet (iCode * ic, iCode *pi)
10931 operand *right, *result;
10932 sym_link *type, *etype;
10935 D (emitcode (";", "genPointerSet"));
10937 right = IC_RIGHT (ic);
10938 result = IC_RESULT (ic);
10940 /* depending on the type of pointer we need to
10941 move it to the correct pointer register */
10942 type = operandType (result);
10943 etype = getSpec (type);
10944 /* if left is of type of pointer then it is simple */
10945 if (IS_PTR (type) && !IS_FUNC (type->next))
10947 p_type = DCL_TYPE (type);
10951 /* we have to go by the storage class */
10952 p_type = PTR_TYPE (SPEC_OCLS (etype));
10955 /* special case when cast remat */
10956 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10957 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10958 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10959 type = operandType (result);
10960 p_type = DCL_TYPE (type);
10963 /* now that we have the pointer type we assign
10964 the pointer values */
10970 genNearPointerSet (right, result, ic, pi);
10974 genPagedPointerSet (right, result, ic, pi);
10978 genFarPointerSet (right, result, ic, pi);
10982 genGenPointerSet (right, result, ic, pi);
10986 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10987 "genPointerSet: illegal pointer type");
10991 /*-----------------------------------------------------------------*/
10992 /* genIfx - generate code for Ifx statement */
10993 /*-----------------------------------------------------------------*/
10995 genIfx (iCode * ic, iCode * popIc)
10997 operand *cond = IC_COND (ic);
11001 D (emitcode (";", "genIfx"));
11003 aopOp (cond, ic, FALSE);
11005 /* get the value into acc */
11006 if (AOP_TYPE (cond) != AOP_CRY)
11013 if (AOP(cond)->aopu.aop_dir)
11014 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
11017 /* the result is now in the accumulator or a directly addressable bit */
11018 freeAsmop (cond, NULL, ic, TRUE);
11020 /* if there was something to be popped then do it */
11024 /* if the condition is a bit variable */
11026 genIfxJump(ic, dup, NULL, NULL, NULL);
11027 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
11028 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
11029 else if (isbit && !IS_ITEMP (cond))
11030 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
11032 genIfxJump (ic, "a", NULL, NULL, NULL);
11037 /*-----------------------------------------------------------------*/
11038 /* genAddrOf - generates code for address of */
11039 /*-----------------------------------------------------------------*/
11041 genAddrOf (iCode * ic)
11043 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
11046 D (emitcode (";", "genAddrOf"));
11048 aopOp (IC_RESULT (ic), ic, FALSE);
11050 /* if the operand is on the stack then we
11051 need to get the stack offset of this
11055 /* if it has an offset then we need to compute it */
11058 int stack_offset = ((sym->stack < 0) ?
11059 ((char) (sym->stack - _G.nRegsSaved)) :
11060 ((char) sym->stack)) & 0xff;
11061 if ((abs(stack_offset) == 1) &&
11062 !AOP_NEEDSACC(IC_RESULT (ic)) &&
11063 !isOperandVolatile (IC_RESULT (ic), FALSE))
11065 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
11066 if (stack_offset > 0)
11067 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
11069 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
11073 emitcode ("mov", "a,%s", SYM_BP (sym));
11074 emitcode ("add", "a,#0x%02x", stack_offset & 0xff);
11075 aopPut (IC_RESULT (ic), "a", 0);
11080 /* we can just move _bp */
11081 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
11083 /* fill the result with zero */
11084 size = AOP_SIZE (IC_RESULT (ic)) - 1;
11089 aopPut (IC_RESULT (ic), zero, offset++);
11094 /* object not on stack then we need the name */
11095 size = AOP_SIZE (IC_RESULT (ic));
11100 char s[SDCC_NAME_MAX];
11102 sprintf (s, "#(%s >> %d)",
11106 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11107 aopPut (IC_RESULT (ic), s, offset++);
11111 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11115 /*-----------------------------------------------------------------*/
11116 /* genFarFarAssign - assignment when both are in far space */
11117 /*-----------------------------------------------------------------*/
11119 genFarFarAssign (operand * result, operand * right, iCode * ic)
11121 int size = AOP_SIZE (right);
11125 D (emitcode (";", "genFarFarAssign"));
11127 /* first push the right side on to the stack */
11130 l = aopGet (right, offset++, FALSE, FALSE);
11132 emitcode ("push", "acc");
11135 freeAsmop (right, NULL, ic, FALSE);
11136 /* now assign DPTR to result */
11137 aopOp (result, ic, FALSE);
11138 size = AOP_SIZE (result);
11141 emitcode ("pop", "acc");
11142 aopPut (result, "a", --offset);
11144 freeAsmop (result, NULL, ic, FALSE);
11147 /*-----------------------------------------------------------------*/
11148 /* genAssign - generate code for assignment */
11149 /*-----------------------------------------------------------------*/
11151 genAssign (iCode * ic)
11153 operand *result, *right;
11155 unsigned long lit = 0L;
11157 D (emitcode (";", "genAssign"));
11159 result = IC_RESULT (ic);
11160 right = IC_RIGHT (ic);
11162 /* if they are the same */
11163 if (operandsEqu (result, right) &&
11164 !isOperandVolatile (result, FALSE) &&
11165 !isOperandVolatile (right, FALSE))
11168 aopOp (right, ic, FALSE);
11170 /* special case both in far space */
11171 if (AOP_TYPE (right) == AOP_DPTR &&
11172 IS_TRUE_SYMOP (result) &&
11173 isOperandInFarSpace (result))
11175 genFarFarAssign (result, right, ic);
11179 aopOp (result, ic, TRUE);
11181 /* if they are the same registers */
11182 if (sameRegs (AOP (right), AOP (result)) &&
11183 !isOperandVolatile (result, FALSE) &&
11184 !isOperandVolatile (right, FALSE))
11187 /* if the result is a bit */
11188 if (AOP_TYPE (result) == AOP_CRY)
11190 assignBit (result, right);
11194 /* bit variables done */
11196 size = AOP_SIZE (result);
11198 if (AOP_TYPE (right) == AOP_LIT)
11199 lit = ulFromVal (AOP (right)->aopu.aop_lit);
11202 (AOP_TYPE (result) != AOP_REG) &&
11203 (AOP_TYPE (right) == AOP_LIT) &&
11204 !IS_FLOAT (operandType (right)) &&
11207 while ((size) && (lit))
11210 aopGet (right, offset, FALSE, FALSE),
11216 /* And now fill the rest with zeros. */
11219 emitcode ("clr", "a");
11223 aopPut (result, "a", offset);
11232 aopGet (right, offset, FALSE, FALSE),
11239 freeAsmop (result, NULL, ic, TRUE);
11240 freeAsmop (right, NULL, ic, TRUE);
11243 /*-----------------------------------------------------------------*/
11244 /* genJumpTab - generates code for jump table */
11245 /*-----------------------------------------------------------------*/
11247 genJumpTab (iCode * ic)
11249 symbol *jtab,*jtablo,*jtabhi;
11251 unsigned int count;
11253 D (emitcode (";", "genJumpTab"));
11255 count = elementsInSet( IC_JTLABELS (ic) );
11259 /* this algorithm needs 9 cycles and 7 + 3*n bytes
11260 if the switch argument is in a register.
11261 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
11262 /* Peephole may not convert ljmp to sjmp or ret
11263 labelIsReturnOnly & labelInRange must check
11264 currPl->ic->op != JUMPTABLE */
11265 aopOp (IC_JTCOND (ic), ic, FALSE);
11266 /* get the condition into accumulator */
11267 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11269 /* multiply by three */
11270 if (aopGetUsesAcc (IC_JTCOND (ic), 0))
11272 emitcode ("mov", "b,#3");
11273 emitcode ("mul", "ab");
11277 emitcode ("add", "a,acc");
11278 emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
11280 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11282 jtab = newiTempLabel (NULL);
11283 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
11284 emitcode ("jmp", "@a+dptr");
11286 /* now generate the jump labels */
11287 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11288 jtab = setNextItem (IC_JTLABELS (ic)))
11289 emitcode ("ljmp", "%05d$", jtab->key + 100);
11293 /* this algorithm needs 14 cycles and 13 + 2*n bytes
11294 if the switch argument is in a register.
11295 For n>6 this algorithm may be more compact */
11296 jtablo = newiTempLabel (NULL);
11297 jtabhi = newiTempLabel (NULL);
11299 /* get the condition into accumulator.
11300 Using b as temporary storage, if register push/pop is needed */
11301 aopOp (IC_JTCOND (ic), ic, FALSE);
11302 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11303 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
11304 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
11306 // (MB) what if B is in use???
11307 wassertl(!BINUSE, "B was in use");
11308 emitcode ("mov", "b,%s", l);
11311 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11315 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
11316 emitcode ("movc", "a,@a+pc");
11317 emitcode ("push", "acc");
11320 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
11321 emitcode ("movc", "a,@a+pc");
11322 emitcode ("push", "acc");
11326 /* this scales up to n<=255, but needs two more bytes
11327 and changes dptr */
11328 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
11329 emitcode ("movc", "a,@a+dptr");
11330 emitcode ("push", "acc");
11333 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
11334 emitcode ("movc", "a,@a+dptr");
11335 emitcode ("push", "acc");
11338 emitcode ("ret", "");
11340 /* now generate jump table, LSB */
11341 emitLabel (jtablo);
11342 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11343 jtab = setNextItem (IC_JTLABELS (ic)))
11344 emitcode (".db", "%05d$", jtab->key + 100);
11346 /* now generate jump table, MSB */
11347 emitLabel (jtabhi);
11348 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11349 jtab = setNextItem (IC_JTLABELS (ic)))
11350 emitcode (".db", "%05d$>>8", jtab->key + 100);
11354 /*-----------------------------------------------------------------*/
11355 /* genCast - gen code for casting */
11356 /*-----------------------------------------------------------------*/
11358 genCast (iCode * ic)
11360 operand *result = IC_RESULT (ic);
11361 sym_link *ctype = operandType (IC_LEFT (ic));
11362 sym_link *rtype = operandType (IC_RIGHT (ic));
11363 operand *right = IC_RIGHT (ic);
11366 D (emitcode (";", "genCast"));
11368 /* if they are equivalent then do nothing */
11369 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11372 aopOp (right, ic, FALSE);
11373 aopOp (result, ic, FALSE);
11375 /* if the result is a bit (and not a bitfield) */
11376 if (IS_BIT (OP_SYMBOL (result)->type))
11378 assignBit (result, right);
11382 /* if they are the same size : or less */
11383 if (AOP_SIZE (result) <= AOP_SIZE (right))
11386 /* if they are in the same place */
11387 if (sameRegs (AOP (right), AOP (result)))
11390 /* if they in different places then copy */
11391 size = AOP_SIZE (result);
11396 aopGet (right, offset, FALSE, FALSE),
11403 /* if the result is of type pointer */
11404 if (IS_PTR (ctype))
11408 sym_link *type = operandType (right);
11409 sym_link *etype = getSpec (type);
11411 /* pointer to generic pointer */
11412 if (IS_GENPTR (ctype))
11416 p_type = DCL_TYPE (type);
11420 if (SPEC_SCLS(etype)==S_REGISTER) {
11421 // let's assume it is a generic pointer
11424 /* we have to go by the storage class */
11425 p_type = PTR_TYPE (SPEC_OCLS (etype));
11429 /* the first two bytes are known */
11430 size = GPTRSIZE - 1;
11435 aopGet (right, offset, FALSE, FALSE),
11439 /* the last byte depending on type */
11441 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11446 // pointerTypeToGPByte will have bitched.
11450 sprintf(gpValStr, "#0x%x", gpVal);
11451 aopPut (result, gpValStr, GPTRSIZE - 1);
11456 /* just copy the pointers */
11457 size = AOP_SIZE (result);
11462 aopGet (right, offset, FALSE, FALSE),
11469 /* so we now know that the size of destination is greater
11470 than the size of the source */
11471 /* we move to result for the size of source */
11472 size = AOP_SIZE (right);
11477 aopGet (right, offset, FALSE, FALSE),
11482 /* now depending on the sign of the source && destination */
11483 size = AOP_SIZE (result) - AOP_SIZE (right);
11484 /* if unsigned or not an integral type */
11485 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11488 aopPut (result, zero, offset++);
11492 /* we need to extend the sign :{ */
11493 char *l = aopGet (right, AOP_SIZE (right) - 1,
11496 emitcode ("rlc", "a");
11497 emitcode ("subb", "a,acc");
11499 aopPut (result, "a", offset++);
11502 /* we are done hurray !!!! */
11505 freeAsmop (result, NULL, ic, TRUE);
11506 freeAsmop (right, NULL, ic, TRUE);
11509 /*-----------------------------------------------------------------*/
11510 /* genDjnz - generate decrement & jump if not zero instrucion */
11511 /*-----------------------------------------------------------------*/
11513 genDjnz (iCode * ic, iCode * ifx)
11515 symbol *lbl, *lbl1;
11519 /* if the if condition has a false label
11520 then we cannot save */
11521 if (IC_FALSE (ifx))
11524 /* if the minus is not of the form a = a - 1 */
11525 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11526 !IS_OP_LITERAL (IC_RIGHT (ic)))
11529 if (operandLitValue (IC_RIGHT (ic)) != 1)
11532 /* if the size of this greater than one then no
11534 if (getSize (operandType (IC_RESULT (ic))) > 1)
11537 /* otherwise we can save BIG */
11539 D (emitcode (";", "genDjnz"));
11541 lbl = newiTempLabel (NULL);
11542 lbl1 = newiTempLabel (NULL);
11544 aopOp (IC_RESULT (ic), ic, FALSE);
11546 if (AOP_NEEDSACC(IC_RESULT(ic)))
11548 /* If the result is accessed indirectly via
11549 * the accumulator, we must explicitly write
11550 * it back after the decrement.
11552 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11554 if (strcmp(rByte, "a"))
11556 /* Something is hopelessly wrong */
11557 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11558 __FILE__, __LINE__);
11559 /* We can just give up; the generated code will be inefficient,
11560 * but what the hey.
11562 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11565 emitcode ("dec", "%s", rByte);
11566 aopPut (IC_RESULT (ic), rByte, 0);
11567 emitcode ("jnz", "%05d$", lbl->key + 100);
11569 else if (IS_AOP_PREG (IC_RESULT (ic)))
11571 emitcode ("dec", "%s",
11572 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11573 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11574 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11575 ifx->generated = 1;
11576 emitcode ("jnz", "%05d$", lbl->key + 100);
11580 emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11583 emitcode ("sjmp", "%05d$", lbl1->key + 100);
11585 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11588 if (!ifx->generated)
11589 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11590 ifx->generated = 1;
11594 /*-----------------------------------------------------------------*/
11595 /* genReceive - generate code for a receive iCode */
11596 /*-----------------------------------------------------------------*/
11598 genReceive (iCode * ic)
11600 int size = getSize (operandType (IC_RESULT (ic)));
11603 D (emitcode (";", "genReceive"));
11605 if (ic->argreg == 1)
11606 { /* first parameter */
11607 if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11608 isOperandInPagedSpace (IC_RESULT (ic))) &&
11609 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11610 IS_TRUE_SYMOP (IC_RESULT (ic))))
11613 int receivingA = 0;
11616 for (offset = 0; offset<size; offset++)
11617 if (!strcmp (fReturn[offset], "a"))
11622 if (size==1 || getTempRegs(tempRegs, size-1, ic))
11624 for (offset = size-1; offset>0; offset--)
11625 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11626 emitcode("mov","a,%s", fReturn[0]);
11628 aopOp (IC_RESULT (ic), ic, FALSE);
11630 aopPut (IC_RESULT (ic), "a", offset);
11631 for (offset = 1; offset<size; offset++)
11632 aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset);
11638 if (getTempRegs(tempRegs, size, ic))
11640 for (offset = 0; offset<size; offset++)
11641 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11642 aopOp (IC_RESULT (ic), ic, FALSE);
11643 for (offset = 0; offset<size; offset++)
11644 aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset);
11649 offset = fReturnSizeMCS51 - size;
11652 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11653 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11656 aopOp (IC_RESULT (ic), ic, FALSE);
11657 size = AOP_SIZE (IC_RESULT (ic));
11661 emitcode ("pop", "acc");
11662 aopPut (IC_RESULT (ic), "a", offset++);
11668 aopOp (IC_RESULT (ic), ic, FALSE);
11670 assignResultValue (IC_RESULT (ic), NULL);
11673 else if (ic->argreg > 12)
11674 { /* bit parameters */
11675 regs *reg = OP_SYMBOL (IC_RESULT (ic))->regs[0];
11678 if (!reg || reg->rIdx != ic->argreg-5)
11680 aopOp (IC_RESULT (ic), ic, FALSE);
11681 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11682 outBitC(IC_RESULT (ic));
11686 { /* other parameters */
11688 aopOp (IC_RESULT (ic), ic, FALSE);
11689 rb1off = ic->argreg;
11692 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
11697 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11700 /*-----------------------------------------------------------------*/
11701 /* genDummyRead - generate code for dummy read of volatiles */
11702 /*-----------------------------------------------------------------*/
11704 genDummyRead (iCode * ic)
11709 D (emitcode(";", "genDummyRead"));
11711 op = IC_RIGHT (ic);
11712 if (op && IS_SYMOP (op))
11714 aopOp (op, ic, FALSE);
11716 /* if the result is a bit */
11717 if (AOP_TYPE (op) == AOP_CRY)
11718 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11721 /* bit variables done */
11723 size = AOP_SIZE (op);
11727 MOVA (aopGet (op, offset, FALSE, FALSE));
11732 freeAsmop (op, NULL, ic, TRUE);
11736 if (op && IS_SYMOP (op))
11738 aopOp (op, ic, FALSE);
11740 /* if the result is a bit */
11741 if (AOP_TYPE (op) == AOP_CRY)
11742 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11745 /* bit variables done */
11747 size = AOP_SIZE (op);
11751 MOVA (aopGet (op, offset, FALSE, FALSE));
11756 freeAsmop (op, NULL, ic, TRUE);
11760 /*-----------------------------------------------------------------*/
11761 /* genCritical - generate code for start of a critical sequence */
11762 /*-----------------------------------------------------------------*/
11764 genCritical (iCode *ic)
11766 symbol *tlbl = newiTempLabel (NULL);
11768 D (emitcode(";", "genCritical"));
11770 if (IC_RESULT (ic))
11772 aopOp (IC_RESULT (ic), ic, TRUE);
11773 aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
11774 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11775 aopPut (IC_RESULT (ic), zero, 0);
11777 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11781 emitcode ("setb", "c");
11782 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11783 emitcode ("clr", "c");
11785 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11789 /*-----------------------------------------------------------------*/
11790 /* genEndCritical - generate code for end of a critical sequence */
11791 /*-----------------------------------------------------------------*/
11793 genEndCritical (iCode *ic)
11795 D(emitcode(";", "genEndCritical"));
11799 aopOp (IC_RIGHT (ic), ic, FALSE);
11800 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11802 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11803 emitcode ("mov", "ea,c");
11807 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11808 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11809 emitcode ("rrc", "a");
11810 emitcode ("mov", "ea,c");
11812 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11816 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11817 emitcode ("mov", "ea,c");
11821 /*-----------------------------------------------------------------*/
11822 /* gen51Code - generate code for 8051 based controllers */
11823 /*-----------------------------------------------------------------*/
11825 gen51Code (iCode * lic)
11829 /* int cseq = 0; */
11831 _G.currentFunc = NULL;
11832 lineHead = lineCurr = NULL;
11834 /* print the allocation information */
11835 if (allocInfo && currFunc)
11836 printAllocInfo (currFunc, codeOutBuf);
11837 /* if debug information required */
11838 if (options.debug && currFunc)
11840 debugFile->writeFunction (currFunc, lic);
11842 /* stack pointer name */
11843 if (options.useXstack)
11849 for (ic = lic; ic; ic = ic->next)
11851 _G.current_iCode = ic;
11853 if (ic->lineno && cln != ic->lineno)
11857 debugFile->writeCLine (ic);
11859 if (!options.noCcodeInAsm) {
11860 emitcode (";", "%s:%d: %s", ic->filename, ic->lineno,
11861 printCLine(ic->filename, ic->lineno));
11866 if (ic->seqPoint && ic->seqPoint != cseq)
11868 emitcode (";", "sequence point %d", ic->seqPoint);
11869 cseq = ic->seqPoint;
11872 if (options.iCodeInAsm) {
11873 char regsInUse[80];
11878 for (i=0; i<8; i++) {
11879 sprintf (®sInUse[i],
11880 "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11883 strcpy (regsInUse, "--------");
11884 for (i=0; i < 8; i++) {
11885 if (bitVectBitValue (ic->rMask, i))
11887 int offset = regs8051[i].offset;
11888 regsInUse[offset] = offset + '0'; /* show rMask */
11892 iLine = printILine(ic);
11893 emitcode(";", "[%s] ic:%d: %s", regsInUse, ic->seq, iLine);
11896 /* if the result is marked as
11897 spilt and rematerializable or code for
11898 this has already been generated then
11900 if (resultRemat (ic) || ic->generated)
11903 /* depending on the operation */
11923 /* IPOP happens only when trying to restore a
11924 spilt live range, if there is an ifx statement
11925 following this pop then the if statement might
11926 be using some of the registers being popped which
11927 would destory the contents of the register so
11928 we need to check for this condition and handle it */
11930 ic->next->op == IFX &&
11931 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11932 genIfx (ic->next, ic);
11950 genEndFunction (ic);
11970 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11987 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11991 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11998 /* note these two are xlated by algebraic equivalence
11999 in decorateType() in SDCCast.c */
12000 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12001 "got '>=' or '<=' shouldn't have come here");
12005 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
12017 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
12021 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
12025 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
12061 genRightShift (ic);
12064 case GET_VALUE_AT_ADDRESS:
12066 hasInc (IC_LEFT (ic), ic,
12067 getSize (operandType (IC_RESULT (ic)))),
12068 ifxForOp (IC_RESULT (ic), ic) );
12072 if (POINTER_SET (ic))
12074 hasInc (IC_RESULT (ic), ic,
12075 getSize (operandType (IC_RIGHT (ic)))));
12101 addSet (&_G.sendSet, ic);
12104 case DUMMY_READ_VOLATILE:
12113 genEndCritical (ic);
12125 _G.current_iCode = NULL;
12127 /* now we are ready to call the
12128 peep hole optimizer */
12129 if (!options.nopeep)
12130 peepHole (&lineHead);
12132 /* now do the actual printing */
12133 printLine (lineHead, codeOutBuf);