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)
2428 char *l = aopGet (oper, offset++, FALSE, TRUE);
2429 if (AOP_TYPE (oper) != AOP_REG &&
2430 AOP_TYPE (oper) != AOP_DIR &&
2434 emitcode ("push", "acc");
2438 emitcode ("push", "%s", l);
2443 /*-----------------------------------------------------------------*/
2444 /* assignResultValue - also indicates if acc is in use afterwards */
2445 /*-----------------------------------------------------------------*/
2447 assignResultValue (operand * oper, operand * func)
2450 int size = AOP_SIZE (oper);
2451 bool accuse = FALSE;
2452 bool pushedA = FALSE;
2454 if (func && IS_BIT (OP_SYM_ETYPE (func)))
2460 if ((size > 3) && aopPutUsesAcc (oper, fReturn[offset], offset))
2462 emitcode ("push", "acc");
2467 if ((offset == 3) && pushedA)
2468 emitcode ("pop", "acc");
2469 accuse |= aopPut (oper, fReturn[offset], offset);
2476 /*-----------------------------------------------------------------*/
2477 /* genXpush - pushes onto the external stack */
2478 /*-----------------------------------------------------------------*/
2480 genXpush (iCode * ic)
2482 asmop *aop = newAsmop (0);
2484 int size, offset = 0;
2486 D (emitcode (";", "genXpush"));
2488 aopOp (IC_LEFT (ic), ic, FALSE);
2489 r = getFreePtr (ic, &aop, FALSE);
2491 size = AOP_SIZE (IC_LEFT (ic));
2495 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2496 emitcode ("mov", "%s,%s", r->name, spname);
2497 emitcode ("inc", "%s", spname); // allocate space first
2498 emitcode ("movx", "@%s,a", r->name);
2502 // allocate space first
2503 emitcode ("mov", "%s,%s", r->name, spname);
2505 emitcode ("add", "a,#%d", size);
2506 emitcode ("mov", "%s,a", spname);
2510 MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2511 emitcode ("movx", "@%s,a", r->name);
2512 emitcode ("inc", "%s", r->name);
2516 freeAsmop (NULL, aop, ic, TRUE);
2517 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2520 /*-----------------------------------------------------------------*/
2521 /* genIpush - generate code for pushing this gets a little complex */
2522 /*-----------------------------------------------------------------*/
2524 genIpush (iCode * ic)
2526 int size, offset = 0;
2530 D (emitcode (";", "genIpush"));
2532 /* if this is not a parm push : ie. it is spill push
2533 and spill push is always done on the local stack */
2537 /* and the item is spilt then do nothing */
2538 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2541 aopOp (IC_LEFT (ic), ic, FALSE);
2542 size = AOP_SIZE (IC_LEFT (ic));
2543 /* push it on the stack */
2546 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2552 emitcode ("push", "%s", l);
2557 /* this is a parameter push: in this case we call
2558 the routine to find the call and save those
2559 registers that need to be saved */
2562 /* if use external stack then call the external
2563 stack pushing routine */
2564 if (options.useXstack)
2570 /* then do the push */
2571 aopOp (IC_LEFT (ic), ic, FALSE);
2573 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2574 size = AOP_SIZE (IC_LEFT (ic));
2578 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2579 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2580 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR)
2582 if (strcmp (l, prev) || *l == '@')
2584 emitcode ("push", "acc");
2588 emitcode ("push", "%s", l);
2593 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2596 /*-----------------------------------------------------------------*/
2597 /* genIpop - recover the registers: can happen only for spilling */
2598 /*-----------------------------------------------------------------*/
2600 genIpop (iCode * ic)
2604 D (emitcode (";", "genIpop"));
2606 /* if the temp was not pushed then */
2607 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2610 aopOp (IC_LEFT (ic), ic, FALSE);
2611 size = AOP_SIZE (IC_LEFT (ic));
2612 offset = (size - 1);
2615 emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2619 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2622 /*-----------------------------------------------------------------*/
2623 /* saveRBank - saves an entire register bank on the stack */
2624 /*-----------------------------------------------------------------*/
2626 saveRBank (int bank, iCode * ic, bool pushPsw)
2629 int count = 8 + (pushPsw ? 1 : 0);
2633 if (options.useXstack)
2637 /* Assume r0 is available for use. */
2638 r = REG_WITH_INDEX (R0_IDX);
2643 r = getFreePtr (ic, &aop, FALSE);
2645 // allocate space first
2646 emitcode ("mov", "%s,%s", r->name, spname);
2648 emitcode ("add", "a,#%d", count);
2649 emitcode ("mov", "%s,a", spname);
2652 for (i = 0; i < 8; i++)
2654 if (options.useXstack)
2656 emitcode ("mov", "a,(%s+%d)",
2657 regs8051[i].base, 8 * bank + regs8051[i].offset);
2658 emitcode ("movx", "@%s,a", r->name);
2660 emitcode ("inc", "%s", r->name);
2663 emitcode ("push", "(%s+%d)",
2664 regs8051[i].base, 8 * bank + regs8051[i].offset);
2669 if (options.useXstack)
2671 emitcode ("mov", "a,psw");
2672 emitcode ("movx", "@%s,a", r->name);
2676 emitcode ("push", "psw");
2679 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2684 freeAsmop (NULL, aop, ic, TRUE);
2693 /*-----------------------------------------------------------------*/
2694 /* unsaveRBank - restores the register bank from stack */
2695 /*-----------------------------------------------------------------*/
2697 unsaveRBank (int bank, iCode * ic, bool popPsw)
2703 if (options.useXstack)
2707 /* Assume r0 is available for use. */
2708 r = REG_WITH_INDEX (R0_IDX);;
2713 r = getFreePtr (ic, &aop, FALSE);
2715 emitcode ("mov", "%s,%s", r->name, spname);
2720 if (options.useXstack)
2722 emitcode ("dec", "%s", r->name);
2723 emitcode ("movx", "a,@%s", r->name);
2724 emitcode ("mov", "psw,a");
2728 emitcode ("pop", "psw");
2732 for (i = 7; i >= 0; i--)
2734 if (options.useXstack)
2736 emitcode ("dec", "%s", r->name);
2737 emitcode ("movx", "a,@%s", r->name);
2738 emitcode ("mov", "(%s+%d),a",
2739 regs8051[i].base, 8 * bank + regs8051[i].offset);
2743 emitcode ("pop", "(%s+%d)",
2744 regs8051[i].base, 8 * bank + regs8051[i].offset);
2748 if (options.useXstack)
2750 emitcode ("mov", "%s,%s", spname, r->name);
2755 freeAsmop (NULL, aop, ic, TRUE);
2759 /*-----------------------------------------------------------------*/
2760 /* genSend - gen code for SEND */
2761 /*-----------------------------------------------------------------*/
2762 static void genSend(set *sendSet)
2767 /* first we do all bit parameters */
2768 for (sic = setFirstItem (sendSet); sic;
2769 sic = setNextItem (sendSet))
2771 if (sic->argreg > 12)
2773 int bit = sic->argreg-13;
2775 aopOp (IC_LEFT (sic), sic, FALSE);
2777 /* if left is a literal then
2778 we know what the value is */
2779 if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2781 if (((int) operandLitValue (IC_LEFT (sic))))
2782 emitcode ("setb", "b[%d]", bit);
2784 emitcode ("clr", "b[%d]", bit);
2789 toCarry (IC_LEFT (sic));
2790 emitcode ("mov", "b[%d],c", bit);
2795 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2801 saveRegisters (setFirstItem (sendSet));
2802 emitcode ("mov", "bits,b");
2805 /* then we do all other parameters */
2806 for (sic = setFirstItem (sendSet); sic;
2807 sic = setNextItem (sendSet))
2809 if (sic->argreg <= 12)
2811 int size, offset = 0;
2812 aopOp (IC_LEFT (sic), sic, FALSE);
2813 size = AOP_SIZE (IC_LEFT (sic));
2815 if (sic->argreg == 1)
2819 char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2820 if (strcmp (l, fReturn[offset]))
2822 emitcode ("mov", "%s,%s", fReturn[offset], l);
2831 emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2832 aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2836 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2841 /*-----------------------------------------------------------------*/
2842 /* selectRegBank - emit code to select the register bank */
2843 /*-----------------------------------------------------------------*/
2845 selectRegBank (short bank, bool keepFlags)
2847 /* if f.e. result is in carry */
2850 emitcode ("anl", "psw,#0xE7");
2852 emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2856 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2860 /*-----------------------------------------------------------------*/
2861 /* genCall - generates a call statement */
2862 /*-----------------------------------------------------------------*/
2864 genCall (iCode * ic)
2868 // bool restoreBank = FALSE;
2869 bool swapBanks = FALSE;
2870 bool accuse = FALSE;
2871 bool accPushed = FALSE;
2872 bool resultInF0 = FALSE;
2873 bool assignResultGenerated = FALSE;
2875 D (emitcode (";", "genCall"));
2877 dtype = operandType (IC_LEFT (ic));
2878 etype = getSpec(dtype);
2879 /* if send set is not empty then assign */
2882 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2883 genSend(reverseSet(_G.sendSet));
2885 genSend(_G.sendSet);
2890 /* if we are calling a not _naked function that is not using
2891 the same register bank then we need to save the
2892 destination registers on the stack */
2893 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2894 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2895 !IFFUNC_ISISR (dtype))
2900 /* if caller saves & we have not saved then */
2906 emitcode ("mov", "psw,#0x%02x",
2907 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2911 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2913 if (IFFUNC_CALLEESAVES(dtype))
2915 werror (E_BANKED_WITH_CALLEESAVES);
2919 char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2920 OP_SYMBOL (IC_LEFT (ic))->rname :
2921 OP_SYMBOL (IC_LEFT (ic))->name);
2923 emitcode ("mov", "r0,#%s", l);
2924 emitcode ("mov", "r1,#(%s >> 8)", l);
2925 emitcode ("mov", "r2,#(%s >> 16)", l);
2926 emitcode ("lcall", "__sdcc_banked_call");
2931 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2932 OP_SYMBOL (IC_LEFT (ic))->rname :
2933 OP_SYMBOL (IC_LEFT (ic))->name));
2938 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2941 /* if we need assign a result value */
2942 if ((IS_ITEMP (IC_RESULT (ic)) &&
2943 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2944 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2945 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2946 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2947 IS_TRUE_SYMOP (IC_RESULT (ic)))
2951 aopOp (IC_RESULT (ic), ic, FALSE);
2954 accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2955 assignResultGenerated = TRUE;
2957 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2960 /* adjust the stack for parameters if required */
2964 if (ic->parmBytes > 3)
2968 emitcode ("push", "acc");
2971 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2972 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2973 !assignResultGenerated)
2975 emitcode ("mov", "F0,c");
2979 emitcode ("mov", "a,%s", spname);
2980 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2981 emitcode ("mov", "%s,a", spname);
2983 /* unsaveRegisters from xstack needs acc, but */
2984 /* unsaveRegisters from stack needs this popped */
2985 if (accPushed && !options.useXstack)
2987 emitcode ("pop", "acc");
2992 for (i = 0; i < ic->parmBytes; i++)
2993 emitcode ("dec", "%s", spname);
2996 /* if we had saved some registers then unsave them */
2997 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2999 if (accuse && !accPushed && options.useXstack)
3001 /* xstack needs acc, but doesn't touch normal stack */
3002 emitcode ("push", "acc");
3005 unsaveRegisters (ic);
3008 // /* if register bank was saved then pop them */
3010 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
3012 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
3015 emitcode ("mov", "c,F0");
3017 aopOp (IC_RESULT (ic), ic, FALSE);
3018 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3019 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3023 emitcode ("pop", "acc");
3026 /*-----------------------------------------------------------------*/
3027 /* genPcall - generates a call by pointer statement */
3028 /*-----------------------------------------------------------------*/
3030 genPcall (iCode * ic)
3034 symbol *rlbl = newiTempLabel (NULL);
3035 // bool restoreBank=FALSE;
3036 bool swapBanks = FALSE;
3037 bool resultInF0 = FALSE;
3039 D (emitcode (";", "genPcall"));
3041 dtype = operandType (IC_LEFT (ic))->next;
3042 etype = getSpec(dtype);
3043 /* if caller saves & we have not saved then */
3047 /* if we are calling a not _naked function that is not using
3048 the same register bank then we need to save the
3049 destination registers on the stack */
3050 if (currFunc && dtype && !IFFUNC_ISNAKED (dtype) &&
3051 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
3052 !IFFUNC_ISISR (dtype))
3054 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3055 // restoreBank=TRUE;
3057 // need caution message to user here
3060 if (IS_LITERAL (etype))
3062 /* if send set is not empty then assign */
3065 genSend(reverseSet(_G.sendSet));
3071 emitcode ("mov", "psw,#0x%02x",
3072 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3075 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT (getSpec(dtype)))
3077 if (IFFUNC_CALLEESAVES (dtype))
3079 werror (E_BANKED_WITH_CALLEESAVES);
3083 char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
3085 emitcode ("mov", "r0,#%s", l);
3086 emitcode ("mov", "r1,#(%s >> 8)", l);
3087 emitcode ("mov", "r2,#(%s >> 16)", l);
3088 emitcode ("lcall", "__sdcc_banked_call");
3093 emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
3098 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT (getSpec(dtype)))
3100 if (IFFUNC_CALLEESAVES (dtype))
3102 werror (E_BANKED_WITH_CALLEESAVES);
3106 aopOp (IC_LEFT (ic), ic, FALSE);
3110 /* what if aopGet needs r0 or r1 ??? */
3111 emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3112 emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3113 emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3117 int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
3118 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3119 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3120 emitcode ("mov", "0x%02x,%s", reg, aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3123 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3125 /* if send set is not empty then assign */
3128 genSend(reverseSet(_G.sendSet));
3134 emitcode ("mov", "psw,#0x%02x",
3135 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3139 emitcode ("lcall", "__sdcc_banked_call");
3142 else if (_G.sendSet)
3144 /* push the return address on to the stack */
3145 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
3146 emitcode ("push", "acc");
3147 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
3148 emitcode ("push", "acc");
3150 /* now push the calling address */
3151 aopOp (IC_LEFT (ic), ic, FALSE);
3153 pushSide (IC_LEFT (ic), FPTRSIZE);
3155 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3157 /* if send set is not empty the assign */
3160 genSend(reverseSet(_G.sendSet));
3166 emitcode ("mov", "psw,#0x%02x",
3167 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3171 emitcode ("ret", "");
3174 else /* the send set is empty */
3177 /* now get the calling address into dptr */
3178 aopOp (IC_LEFT (ic), ic, FALSE);
3180 l = aopGet (IC_LEFT (ic), 0, FALSE, FALSE);
3181 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3183 emitcode ("mov", "r0,%s", l);
3184 l = aopGet (IC_LEFT (ic), 1, FALSE, FALSE);
3185 emitcode ("mov", "dph,%s", l);
3186 emitcode ("mov", "dpl,r0");
3190 emitcode ("mov", "dpl,%s", l);
3191 l = aopGet (IC_LEFT (ic), 1, FALSE, FALSE);
3192 emitcode ("mov", "dph,%s", l);
3195 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3199 emitcode ("mov", "psw,#0x%02x",
3200 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3204 emitcode ("lcall", "__sdcc_call_dptr");
3209 selectRegBank (FUNC_REGBANK (currFunc->type), IS_BIT (etype));
3212 /* if we need assign a result value */
3213 if ((IS_ITEMP (IC_RESULT (ic)) &&
3214 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3215 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3216 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3217 IS_TRUE_SYMOP (IC_RESULT (ic)))
3221 aopOp (IC_RESULT (ic), ic, FALSE);
3224 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3226 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3229 /* adjust the stack for parameters if required */
3233 if (ic->parmBytes > 3)
3235 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3236 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3238 emitcode ("mov", "F0,c");
3242 emitcode ("mov", "a,%s", spname);
3243 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3244 emitcode ("mov", "%s,a", spname);
3247 for (i = 0; i < ic->parmBytes; i++)
3248 emitcode ("dec", "%s", spname);
3251 // /* if register bank was saved then unsave them */
3253 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3255 /* if we had saved some registers then unsave them */
3256 if (ic->regsSaved && !IFFUNC_CALLEESAVES (dtype))
3257 unsaveRegisters (ic);
3259 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3262 emitcode ("mov", "c,F0");
3264 aopOp (IC_RESULT (ic), ic, FALSE);
3265 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3266 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3270 /*-----------------------------------------------------------------*/
3271 /* resultRemat - result is rematerializable */
3272 /*-----------------------------------------------------------------*/
3274 resultRemat (iCode * ic)
3276 if (SKIP_IC (ic) || ic->op == IFX)
3279 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3281 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3282 if (sym->remat && !POINTER_SET (ic))
3289 /*-----------------------------------------------------------------*/
3290 /* inExcludeList - return 1 if the string is in exclude Reg list */
3291 /*-----------------------------------------------------------------*/
3293 regsCmp(void *p1, void *p2)
3295 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3299 inExcludeList (char *s)
3301 const char *p = setFirstItem(options.excludeRegsSet);
3303 if (p == NULL || STRCASECMP(p, "none") == 0)
3307 return isinSetWith(options.excludeRegsSet, s, regsCmp);
3310 /*-----------------------------------------------------------------*/
3311 /* genFunction - generated code for function entry */
3312 /*-----------------------------------------------------------------*/
3314 genFunction (iCode * ic)
3316 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3318 bool switchedPSW = FALSE;
3319 int calleesaves_saved_register = -1;
3320 int stackAdjust = sym->stack;
3321 int accIsFree = sym->recvSize < 4;
3322 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3323 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3326 /* create the function header */
3327 emitcode (";", "-----------------------------------------");
3328 emitcode (";", " function %s", sym->name);
3329 emitcode (";", "-----------------------------------------");
3331 emitcode ("", "%s:", sym->rname);
3332 lineCurr->isLabel = 1;
3333 ftype = operandType (IC_LEFT (ic));
3334 _G.currentFunc = sym;
3336 if (IFFUNC_ISNAKED(ftype))
3338 emitcode(";", "naked function: no prologue.");
3342 /* here we need to generate the equates for the
3343 register bank if required */
3344 if (FUNC_REGBANK (ftype) != rbank)
3348 rbank = FUNC_REGBANK (ftype);
3349 for (i = 0; i < mcs51_nRegs; i++)
3351 if (regs8051[i].type != REG_BIT)
3353 if (strcmp (regs8051[i].base, "0") == 0)
3354 emitcode ("", "%s = 0x%02x",
3356 8 * rbank + regs8051[i].offset);
3358 emitcode ("", "%s = %s + 0x%02x",
3361 8 * rbank + regs8051[i].offset);
3366 /* if this is an interrupt service routine then
3367 save acc, b, dpl, dph */
3368 if (IFFUNC_ISISR (sym->type))
3372 rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), sym->regsUsed);
3373 if (IFFUNC_HASFCALL(sym->type) || !bitVectIsZero (rsavebits))
3375 emitcode ("push", "bits");
3378 freeBitVect (rsavebits);
3380 if (!inExcludeList ("acc"))
3381 emitcode ("push", "acc");
3382 if (!inExcludeList ("b"))
3383 emitcode ("push", "b");
3384 if (!inExcludeList ("dpl"))
3385 emitcode ("push", "dpl");
3386 if (!inExcludeList ("dph"))
3387 emitcode ("push", "dph");
3388 /* if this isr has no bank i.e. is going to
3389 run with bank 0 , then we need to save more
3391 if (!FUNC_REGBANK (sym->type))
3395 /* if this function does not call any other
3396 function then we can be economical and
3397 save only those registers that are used */
3398 if (!IFFUNC_HASFCALL(sym->type))
3400 /* if any registers used */
3403 /* save the registers used */
3404 for (i = 0; i < sym->regsUsed->size; i++)
3406 if (bitVectBitValue (sym->regsUsed, i))
3413 /* this function has a function call. We cannot
3414 determine register usage so we will have to push the
3416 saveRBank (0, ic, FALSE);
3417 if (options.parms_in_bank1) {
3418 for (i=0; i < 8 ; i++ ) {
3419 emitcode ("push","%s",rb1regs[i]);
3426 /* This ISR uses a non-zero bank.
3428 * We assume that the bank is available for our
3431 * However, if this ISR calls a function which uses some
3432 * other bank, we must save that bank entirely.
3434 unsigned long banksToSave = 0;
3436 if (IFFUNC_HASFCALL(sym->type))
3439 #define MAX_REGISTER_BANKS 4
3444 for (i = ic; i; i = i->next)
3446 if (i->op == ENDFUNCTION)
3448 /* we got to the end OK. */
3456 dtype = operandType (IC_LEFT(i));
3458 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3460 /* Mark this bank for saving. */
3461 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3463 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3467 banksToSave |= (1 << FUNC_REGBANK(dtype));
3470 /* And note that we don't need to do it in
3478 /* This is a mess; we have no idea what
3479 * register bank the called function might
3482 * The only thing I can think of to do is
3483 * throw a warning and hope.
3485 werror(W_FUNCPTR_IN_USING_ISR);
3489 if (banksToSave && options.useXstack)
3491 /* Since we aren't passing it an ic,
3492 * saveRBank will assume r0 is available to abuse.
3494 * So switch to our (trashable) bank now, so
3495 * the caller's R0 isn't trashed.
3497 emitcode ("push", "psw");
3498 emitcode ("mov", "psw,#0x%02x",
3499 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3503 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3505 if (banksToSave & (1 << ix))
3507 saveRBank(ix, NULL, FALSE);
3511 // TODO: this needs a closer look
3512 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3515 /* Set the register bank to the desired value if nothing else */
3516 /* has done so yet. */
3519 emitcode ("push", "psw");
3520 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3525 /* This is a non-ISR function. The caller has already switched register */
3526 /* banks, if necessary, so just handle the callee-saves option. */
3528 /* if callee-save to be used for this function
3529 then save the registers being used in this function */
3530 if (IFFUNC_CALLEESAVES(sym->type))
3534 /* if any registers used */
3537 bool bits_pushed = FALSE;
3538 /* save the registers used */
3539 for (i = 0; i < sym->regsUsed->size; i++)
3541 if (bitVectBitValue (sym->regsUsed, i))
3543 /* remember one saved register for later usage */
3544 if (calleesaves_saved_register < 0)
3545 calleesaves_saved_register = i;
3546 bits_pushed = pushReg (i, bits_pushed);
3556 if (options.useXstack)
3558 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3560 emitcode ("mov", "r0,%s", spname);
3561 emitcode ("inc", "%s", spname);
3562 emitcode ("xch", "a,_bpx");
3563 emitcode ("movx", "@r0,a");
3564 emitcode ("inc", "r0");
3565 emitcode ("mov", "a,r0");
3566 emitcode ("xch", "a,_bpx");
3570 emitcode ("push", "_bp"); /* save the callers stack */
3571 emitcode ("mov", "_bp,sp");
3576 if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3578 /* set up the stack */
3579 emitcode ("push", "_bp"); /* save the callers stack */
3580 emitcode ("mov", "_bp,sp");
3585 /* For some cases it is worthwhile to perform a RECEIVE iCode */
3586 /* before setting up the stack frame completely. */
3587 if (ric && ric->argreg == 1 && IC_RESULT (ric))
3589 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3593 if (rsym && rsym->regType == REG_CND)
3595 if (rsym && (rsym->accuse || rsym->ruonly))
3597 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3598 rsym = rsym->usl.spillLoc;
3601 /* If the RECEIVE operand immediately spills to the first entry on the */
3602 /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3603 /* rather than the usual @r0/r1 machinations. */
3604 if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3608 _G.current_iCode = ric;
3609 D(emitcode (";", "genReceive"));
3610 for (ofs=0; ofs < sym->recvSize; ofs++)
3612 if (!strcmp (fReturn[ofs], "a"))
3613 emitcode ("push", "acc");
3615 emitcode ("push", fReturn[ofs]);
3617 stackAdjust -= sym->recvSize;
3620 assert (stackAdjust>=0);
3623 _G.current_iCode = ic;
3627 /* If the RECEIVE operand is 4 registers, we can do the moves now */
3628 /* to free up the accumulator. */
3629 else if (rsym && rsym->nRegs && sym->recvSize == 4)
3633 _G.current_iCode = ric;
3634 D(emitcode (";", "genReceive"));
3635 for (ofs=0; ofs < sym->recvSize; ofs++)
3637 emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3639 _G.current_iCode = ic;
3645 /* adjust the stack for the function */
3648 int i = stackAdjust;
3650 werror (W_STACK_OVERFLOW, sym->name);
3652 if (i > 3 && accIsFree)
3654 emitcode ("mov", "a,sp");
3655 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3656 emitcode ("mov", "sp,a");
3660 /* The accumulator is not free, so we will need another register */
3661 /* to clobber. No need to worry about a possible conflict with */
3662 /* the above early RECEIVE optimizations since they would have */
3663 /* freed the accumulator if they were generated. */
3665 if (IFFUNC_CALLEESAVES(sym->type))
3667 /* if it's a callee-saves function we need a saved register */
3668 if (calleesaves_saved_register >= 0)
3670 emitcode ("mov", "%s,a", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3671 emitcode ("mov", "a,sp");
3672 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3673 emitcode ("mov", "sp,a");
3674 emitcode ("mov", "a,%s", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3677 /* do it the hard way */
3679 emitcode ("inc", "sp");
3683 /* not callee-saves, we can clobber r0 */
3684 emitcode ("mov", "r0,a");
3685 emitcode ("mov", "a,sp");
3686 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3687 emitcode ("mov", "sp,a");
3688 emitcode ("mov", "a,r0");
3693 emitcode ("inc", "sp");
3698 char i = ((char) sym->xstack & 0xff);
3700 if (i > 3 && accIsFree)
3702 emitcode ("mov", "a,_spx");
3703 emitcode ("add", "a,#0x%02x", i & 0xff);
3704 emitcode ("mov", "_spx,a");
3708 emitcode ("push", "acc");
3709 emitcode ("mov", "a,_spx");
3710 emitcode ("add", "a,#0x%02x", i & 0xff);
3711 emitcode ("mov", "_spx,a");
3712 emitcode ("pop", "acc");
3717 emitcode ("inc", "_spx");
3721 /* if critical function then turn interrupts off */
3722 if (IFFUNC_ISCRITICAL (ftype))
3724 symbol *tlbl = newiTempLabel (NULL);
3725 emitcode ("setb", "c");
3726 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3727 emitcode ("clr", "c");
3729 emitcode ("push", "psw"); /* save old ea via c in psw */
3733 /*-----------------------------------------------------------------*/
3734 /* genEndFunction - generates epilogue for functions */
3735 /*-----------------------------------------------------------------*/
3737 genEndFunction (iCode * ic)
3739 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3740 lineNode *lnp = lineCurr;
3742 bitVect *regsUsedPrologue;
3743 bitVect *regsUnneeded;
3746 _G.currentFunc = NULL;
3747 if (IFFUNC_ISNAKED(sym->type))
3749 emitcode(";", "naked function: no epilogue.");
3750 if (options.debug && currFunc)
3751 debugFile->writeEndFunction (currFunc, ic, 0);
3755 if (IFFUNC_ISCRITICAL (sym->type))
3757 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3759 emitcode ("rlc", "a"); /* save c in a */
3760 emitcode ("pop", "psw"); /* restore ea via c in psw */
3761 emitcode ("mov", "ea,c");
3762 emitcode ("rrc", "a"); /* restore c from a */
3766 emitcode ("pop", "psw"); /* restore ea via c in psw */
3767 emitcode ("mov", "ea,c");
3771 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3773 if (options.useXstack)
3777 emitcode ("mov", "sp,_bp");
3778 emitcode ("pop", "_bp");
3780 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3782 emitcode ("xch", "a,_bpx");
3783 emitcode ("mov", "r0,a");
3784 emitcode ("dec", "r0");
3785 emitcode ("movx", "a,@r0");
3786 emitcode ("xch", "a,_bpx");
3787 emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3790 else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3793 emitcode ("mov", "sp,_bp");
3794 emitcode ("pop", "_bp");
3798 /* restore the register bank */
3799 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3801 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3802 || !options.useXstack)
3804 /* Special case of ISR using non-zero bank with useXstack
3807 emitcode ("pop", "psw");
3811 if (IFFUNC_ISISR (sym->type))
3815 /* now we need to restore the registers */
3816 /* if this isr has no bank i.e. is going to
3817 run with bank 0 , then we need to save more
3819 if (!FUNC_REGBANK (sym->type))
3822 /* if this function does not call any other
3823 function then we can be economical and
3824 save only those registers that are used */
3825 if (!IFFUNC_HASFCALL(sym->type))
3827 /* if any registers used */
3830 /* save the registers used */
3831 for (i = sym->regsUsed->size; i >= 0; i--)
3833 if (bitVectBitValue (sym->regsUsed, i))
3840 if (options.parms_in_bank1) {
3841 for (i = 7 ; i >= 0 ; i-- ) {
3842 emitcode ("pop","%s",rb1regs[i]);
3845 /* this function has a function call. We cannot
3846 determine register usage so we will have to pop the
3848 unsaveRBank (0, ic, FALSE);
3853 /* This ISR uses a non-zero bank.
3855 * Restore any register banks saved by genFunction
3858 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3861 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3863 if (savedBanks & (1 << ix))
3865 unsaveRBank(ix, NULL, FALSE);
3869 if (options.useXstack)
3871 /* Restore bank AFTER calling unsaveRBank,
3872 * since it can trash r0.
3874 emitcode ("pop", "psw");
3878 if (!inExcludeList ("dph"))
3879 emitcode ("pop", "dph");
3880 if (!inExcludeList ("dpl"))
3881 emitcode ("pop", "dpl");
3882 if (!inExcludeList ("b"))
3883 emitcode ("pop", "b");
3884 if (!inExcludeList ("acc"))
3885 emitcode ("pop", "acc");
3887 rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), sym->regsUsed);
3888 if (IFFUNC_HASFCALL(sym->type) || !bitVectIsZero (rsavebits))
3889 emitcode ("pop", "bits");
3890 freeBitVect (rsavebits);
3892 /* if debug then send end of function */
3893 if (options.debug && currFunc)
3895 debugFile->writeEndFunction (currFunc, ic, 1);
3898 emitcode ("reti", "");
3902 if (IFFUNC_CALLEESAVES(sym->type))
3906 /* if any registers used */
3909 /* save the registers used */
3910 for (i = sym->regsUsed->size; i >= 0; i--)
3912 if (bitVectBitValue (sym->regsUsed, i) ||
3913 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3914 emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
3917 else if (mcs51_ptrRegReq)
3919 emitcode ("pop", "%s", REG_WITH_INDEX (R1_IDX)->dname);
3920 emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
3925 /* if debug then send end of function */
3926 if (options.debug && currFunc)
3928 debugFile->writeEndFunction (currFunc, ic, 1);
3931 if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3933 emitcode ("ljmp", "__sdcc_banked_ret");
3937 emitcode ("ret", "");
3941 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3944 /* If this was an interrupt handler using bank 0 that called another */
3945 /* function, then all registers must be saved; nothing to optimized. */
3946 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3947 && !FUNC_REGBANK(sym->type))
3950 /* There are no push/pops to optimize if not callee-saves or ISR */
3951 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3954 /* If there were stack parameters, we cannot optimize without also */
3955 /* fixing all of the stack offsets; this is too dificult to consider. */
3956 if (FUNC_HASSTACKPARM(sym->type))
3959 /* Compute the registers actually used */
3960 regsUsed = newBitVect (mcs51_nRegs);
3961 regsUsedPrologue = newBitVect (mcs51_nRegs);
3964 if (lnp->ic && lnp->ic->op == FUNCTION)
3965 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3967 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3969 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3970 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3977 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3978 && !bitVectBitValue (regsUsed, CND_IDX))
3980 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3981 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3982 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3983 bitVectUnSetBit (regsUsed, CND_IDX);
3986 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3988 /* If this was an interrupt handler that called another function */
3989 /* function, then assume A, B, DPH, & DPL may be modified by it. */
3990 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3992 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3993 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3994 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3995 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3996 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3999 /* Remove the unneeded push/pops */
4000 regsUnneeded = newBitVect (mcs51_nRegs);
4003 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
4005 if (!strncmp(lnp->line, "push", 4))
4007 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
4008 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4010 connectLine (lnp->prev, lnp->next);
4011 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4014 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
4016 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
4017 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4019 connectLine (lnp->prev, lnp->next);
4020 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4027 for (idx = 0; idx < regsUnneeded->size; idx++)
4028 if (bitVectBitValue (regsUnneeded, idx))
4029 emitcode (";", "eliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
4031 freeBitVect (regsUnneeded);
4032 freeBitVect (regsUsed);
4033 freeBitVect (regsUsedPrologue);
4036 /*-----------------------------------------------------------------*/
4037 /* genRet - generate code for return statement */
4038 /*-----------------------------------------------------------------*/
4042 int size, offset = 0, pushed = 0;
4044 D (emitcode (";", "genRet"));
4046 /* if we have no return value then
4047 just generate the "ret" */
4051 /* we have something to return then
4052 move the return value into place */
4053 aopOp (IC_LEFT (ic), ic, FALSE);
4054 size = AOP_SIZE (IC_LEFT (ic));
4056 if (IS_BIT(_G.currentFunc->etype))
4058 if (!IS_OP_RUONLY (IC_LEFT (ic)))
4059 toCarry (IC_LEFT (ic));
4066 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
4069 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
4070 emitcode ("push", "%s", l);
4075 l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
4076 if (strcmp (fReturn[offset], l))
4077 emitcode ("mov", "%s,%s", fReturn[offset++], l);
4084 if (strcmp (fReturn[pushed], "a"))
4085 emitcode ("pop", fReturn[pushed]);
4087 emitcode ("pop", "acc");
4090 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
4093 /* generate a jump to the return label
4094 if the next is not the return statement */
4095 if (!(ic->next && ic->next->op == LABEL &&
4096 IC_LABEL (ic->next) == returnLabel))
4098 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
4102 /*-----------------------------------------------------------------*/
4103 /* genLabel - generates a label */
4104 /*-----------------------------------------------------------------*/
4106 genLabel (iCode * ic)
4108 /* special case never generate */
4109 if (IC_LABEL (ic) == entryLabel)
4112 emitLabel (IC_LABEL (ic));
4115 /*-----------------------------------------------------------------*/
4116 /* genGoto - generates a ljmp */
4117 /*-----------------------------------------------------------------*/
4119 genGoto (iCode * ic)
4121 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
4124 /*-----------------------------------------------------------------*/
4125 /* findLabelBackwards: walks back through the iCode chain looking */
4126 /* for the given label. Returns number of iCode instructions */
4127 /* between that label and given ic. */
4128 /* Returns zero if label not found. */
4129 /*-----------------------------------------------------------------*/
4131 findLabelBackwards (iCode * ic, int key)
4140 /* If we have any pushes or pops, we cannot predict the distance.
4141 I don't like this at all, this should be dealt with in the
4143 if (ic->op == IPUSH || ic->op == IPOP) {
4147 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4156 /*-----------------------------------------------------------------*/
4157 /* genPlusIncr :- does addition with increment if possible */
4158 /*-----------------------------------------------------------------*/
4160 genPlusIncr (iCode * ic)
4162 unsigned int icount;
4163 unsigned int size = getDataSize (IC_RESULT (ic));
4165 /* will try to generate an increment */
4166 /* if the right side is not a literal
4168 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4171 icount = (unsigned int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4173 D(emitcode (";","genPlusIncr"));
4175 /* if increment >=16 bits in register or direct space */
4176 if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG ||
4177 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4178 (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4179 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4180 !isOperandVolatile (IC_RESULT (ic), FALSE) &&
4188 /* If the next instruction is a goto and the goto target
4189 * is < 10 instructions previous to this, we can generate
4190 * jumps straight to that target.
4192 if (ic->next && ic->next->op == GOTO
4193 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4194 && labelRange <= 10)
4196 D (emitcode (";", "tail increment optimized (range %d)", labelRange));
4197 tlbl = IC_LABEL (ic->next);
4202 tlbl = newiTempLabel (NULL);
4205 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4206 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4207 IS_AOP_PREG (IC_RESULT (ic)))
4208 emitcode ("cjne", "%s,#0x00,%05d$",
4209 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4213 emitcode ("clr", "a");
4214 emitcode ("cjne", "a,%s,%05d$",
4215 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4219 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4222 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4223 IS_AOP_PREG (IC_RESULT (ic)))
4224 emitcode ("cjne", "%s,#0x00,%05d$",
4225 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4228 emitcode ("cjne", "a,%s,%05d$",
4229 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4232 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4236 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4237 IS_AOP_PREG (IC_RESULT (ic)))
4238 emitcode ("cjne", "%s,#0x00,%05d$",
4239 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4243 emitcode ("cjne", "a,%s,%05d$",
4244 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4247 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4257 /* if result is dptr */
4258 if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
4259 (AOP_SIZE (IC_RESULT (ic)) == 2) &&
4260 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
4261 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
4263 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4269 if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
4272 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0);
4273 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1);
4275 emitcode ("inc", "dptr");
4280 /* if the literal value of the right hand side
4281 is greater than 4 then it is not worth it */
4285 /* if the sizes are greater than 1 then we cannot */
4286 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4287 AOP_SIZE (IC_LEFT (ic)) > 1)
4290 /* we can if the aops of the left & result match or
4291 if they are in registers and the registers are the
4293 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4297 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4298 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4299 aopPut (IC_RESULT (ic), "a", 0);
4305 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4314 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4315 emitcode ("inc", "a");
4316 aopPut (IC_RESULT (ic), "a", 0);
4323 /*-----------------------------------------------------------------*/
4324 /* outBitAcc - output a bit in acc */
4325 /*-----------------------------------------------------------------*/
4327 outBitAcc (operand * result)
4329 symbol *tlbl = newiTempLabel (NULL);
4330 /* if the result is a bit */
4331 if (AOP_TYPE (result) == AOP_CRY)
4333 aopPut (result, "a", 0);
4337 emitcode ("jz", "%05d$", tlbl->key + 100);
4338 emitcode ("mov", "a,%s", one);
4344 /*-----------------------------------------------------------------*/
4345 /* genPlusBits - generates code for addition of two bits */
4346 /*-----------------------------------------------------------------*/
4348 genPlusBits (iCode * ic)
4350 D (emitcode (";", "genPlusBits"));
4352 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4353 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4355 symbol *lbl = newiTempLabel (NULL);
4356 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4357 emitcode ("cpl", "c");
4359 outBitC (IC_RESULT (ic));
4363 emitcode ("clr", "a");
4364 emitcode ("rlc", "a");
4365 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4366 emitcode ("addc", "a,%s", zero);
4367 outAcc (IC_RESULT (ic));
4372 /* This is the original version of this code.
4374 * This is being kept around for reference,
4375 * because I am not entirely sure I got it right...
4378 adjustArithmeticResult (iCode * ic)
4380 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4381 AOP_SIZE (IC_LEFT (ic)) == 3 &&
4382 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4383 aopPut (IC_RESULT (ic),
4384 aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4387 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4388 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4389 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4390 aopPut (IC_RESULT (ic),
4391 aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4394 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4395 AOP_SIZE (IC_LEFT (ic)) < 3 &&
4396 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4397 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4398 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4401 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4402 aopPut (IC_RESULT (ic), buffer, 2);
4406 /* This is the pure and virtuous version of this code.
4407 * I'm pretty certain it's right, but not enough to toss the old
4411 adjustArithmeticResult (iCode * ic)
4413 if (opIsGptr (IC_RESULT (ic)) &&
4414 opIsGptr (IC_LEFT (ic)) &&
4415 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4417 aopPut (IC_RESULT (ic),
4418 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4422 if (opIsGptr (IC_RESULT (ic)) &&
4423 opIsGptr (IC_RIGHT (ic)) &&
4424 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4426 aopPut (IC_RESULT (ic),
4427 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4431 if (opIsGptr (IC_RESULT (ic)) &&
4432 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4433 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4434 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4435 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4438 SNPRINTF (buffer, sizeof(buffer),
4439 "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4440 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4445 /*-----------------------------------------------------------------*/
4446 /* genPlus - generates code for addition */
4447 /*-----------------------------------------------------------------*/
4449 genPlus (iCode * ic)
4451 int size, offset = 0;
4454 bool swappedLR = FALSE;
4455 operand *leftOp, *rightOp;
4458 D (emitcode (";", "genPlus"));
4460 /* special cases :- */
4462 aopOp (IC_LEFT (ic), ic, FALSE);
4463 aopOp (IC_RIGHT (ic), ic, FALSE);
4464 aopOp (IC_RESULT (ic), ic, TRUE);
4466 /* if literal, literal on the right or
4467 if left requires ACC or right is already
4469 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4470 (AOP_NEEDSACC (IC_LEFT (ic))) ||
4471 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4473 operand *t = IC_RIGHT (ic);
4474 IC_RIGHT (ic) = IC_LEFT (ic);
4479 /* if both left & right are in bit
4481 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4482 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4488 /* if left in bit space & right literal */
4489 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4490 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4492 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4493 /* if result in bit space */
4494 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4496 if (ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4497 emitcode ("cpl", "c");
4498 outBitC (IC_RESULT (ic));
4502 size = getDataSize (IC_RESULT (ic));
4505 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4506 emitcode ("addc", "a,%s", zero);
4507 aopPut (IC_RESULT (ic), "a", offset++);
4513 /* if I can do an increment instead
4514 of add then GOOD for ME */
4515 if (genPlusIncr (ic) == TRUE)
4518 size = getDataSize (IC_RESULT (ic));
4519 leftOp = IC_LEFT(ic);
4520 rightOp = IC_RIGHT(ic);
4523 /* if this is an add for an array access
4524 at a 256 byte boundary */
4526 && AOP_TYPE (op) == AOP_IMMD
4528 && IS_SPEC (OP_SYM_ETYPE (op))
4529 && SPEC_ABSA (OP_SYM_ETYPE (op))
4530 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4533 D(emitcode (";", "genPlus aligned array"));
4534 aopPut (IC_RESULT (ic),
4535 aopGet (rightOp, 0, FALSE, FALSE),
4538 if( 1 == getDataSize (IC_RIGHT (ic)) )
4540 aopPut (IC_RESULT (ic),
4541 aopGet (leftOp, 1, FALSE, FALSE),
4546 MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4547 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4548 aopPut (IC_RESULT (ic), "a", 1);
4553 /* if the lower bytes of a literal are zero skip the addition */
4554 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4556 while ((0 == ((unsigned int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4557 (skip_bytes+1 < size))
4562 D(emitcode (";", "genPlus shortcut"));
4567 if( offset >= skip_bytes )
4569 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4572 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4574 emitcode("xch", "a,b");
4575 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4576 emitcode (add, "a,b");
4579 else if (aopGetUsesAcc (leftOp, offset))
4581 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4582 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4586 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4587 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4589 aopPut (IC_RESULT (ic), "a", offset);
4590 add = "addc"; /* further adds must propagate carry */
4594 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4595 isOperandVolatile (IC_RESULT (ic), FALSE))
4598 aopPut (IC_RESULT (ic),
4599 aopGet (leftOp, offset, FALSE, FALSE),
4606 adjustArithmeticResult (ic);
4609 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4612 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4613 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4617 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4618 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4622 /*-----------------------------------------------------------------*/
4623 /* genMinusDec :- does subtraction with decrement if possible */
4624 /*-----------------------------------------------------------------*/
4626 genMinusDec (iCode * ic)
4628 unsigned int icount;
4629 unsigned int size = getDataSize (IC_RESULT (ic));
4631 /* will try to generate an increment */
4632 /* if the right side is not a literal
4634 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4637 /* if the literal value of the right hand side
4638 is greater than 4 then it is not worth it */
4639 if ((icount = (unsigned int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4642 D (emitcode (";", "genMinusDec"));
4644 /* if decrement >=16 bits in register or direct space */
4645 if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG ||
4646 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4647 (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4648 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4656 /* If the next instruction is a goto and the goto target
4657 * is <= 10 instructions previous to this, we can generate
4658 * jumps straight to that target.
4660 if (ic->next && ic->next->op == GOTO
4661 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4662 && labelRange <= 10)
4664 D (emitcode (";", "tail decrement optimized (range %d)", labelRange));
4665 tlbl = IC_LABEL (ic->next);
4670 tlbl = newiTempLabel (NULL);
4674 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4675 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4676 IS_AOP_PREG (IC_RESULT (ic)))
4677 emitcode ("cjne", "%s,#0xff,%05d$"
4678 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4682 emitcode ("mov", "a,#0xff");
4683 emitcode ("cjne", "a,%s,%05d$"
4684 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4687 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4690 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4691 IS_AOP_PREG (IC_RESULT (ic)))
4692 emitcode ("cjne", "%s,#0xff,%05d$"
4693 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4697 emitcode ("cjne", "a,%s,%05d$"
4698 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4701 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4705 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4706 IS_AOP_PREG (IC_RESULT (ic)))
4707 emitcode ("cjne", "%s,#0xff,%05d$"
4708 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4712 emitcode ("cjne", "a,%s,%05d$"
4713 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4716 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4725 /* if the sizes are greater than 1 then we cannot */
4726 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4727 AOP_SIZE (IC_LEFT (ic)) > 1)
4730 /* we can if the aops of the left & result match or
4731 if they are in registers and the registers are the
4733 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4737 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4739 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4744 l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
4749 emitcode ("dec", "%s", l);
4752 if (AOP_NEEDSACC (IC_RESULT (ic)))
4753 aopPut (IC_RESULT (ic), "a", 0);
4760 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4761 emitcode ("dec", "a");
4762 aopPut (IC_RESULT (ic), "a", 0);
4769 /*-----------------------------------------------------------------*/
4770 /* addSign - complete with sign */
4771 /*-----------------------------------------------------------------*/
4773 addSign (operand * result, int offset, int sign)
4775 int size = (getDataSize (result) - offset);
4780 emitcode ("rlc", "a");
4781 emitcode ("subb", "a,acc");
4784 aopPut (result, "a", offset++);
4791 aopPut (result, zero, offset++);
4797 /*-----------------------------------------------------------------*/
4798 /* genMinusBits - generates code for subtraction of two bits */
4799 /*-----------------------------------------------------------------*/
4801 genMinusBits (iCode * ic)
4803 symbol *lbl = newiTempLabel (NULL);
4805 D (emitcode (";", "genMinusBits"));
4807 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4809 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4810 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4811 emitcode ("cpl", "c");
4813 outBitC (IC_RESULT (ic));
4817 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4818 emitcode ("subb", "a,acc");
4819 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4820 emitcode ("inc", "a");
4822 aopPut (IC_RESULT (ic), "a", 0);
4823 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4827 /*-----------------------------------------------------------------*/
4828 /* genMinus - generates code for subtraction */
4829 /*-----------------------------------------------------------------*/
4831 genMinus (iCode * ic)
4833 int size, offset = 0;
4835 D (emitcode (";", "genMinus"));
4837 aopOp (IC_LEFT (ic), ic, FALSE);
4838 aopOp (IC_RIGHT (ic), ic, FALSE);
4839 aopOp (IC_RESULT (ic), ic, TRUE);
4841 /* special cases :- */
4842 /* if both left & right are in bit space */
4843 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4844 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4850 /* if I can do an decrement instead
4851 of subtract then GOOD for ME */
4852 if (genMinusDec (ic) == TRUE)
4855 size = getDataSize (IC_RESULT (ic));
4857 /* if literal, add a,#-lit, else normal subb */
4858 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4860 unsigned long lit = 0L;
4861 bool useCarry = FALSE;
4863 lit = ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4868 if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4870 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4871 if (!offset && !size && lit== (unsigned long) -1)
4873 emitcode ("dec", "a");
4877 /* first add without previous c */
4878 emitcode ("add", "a,#0x%02x",
4879 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4884 emitcode ("addc", "a,#0x%02x",
4885 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4887 aopPut (IC_RESULT (ic), "a", offset++);
4891 /* no need to add zeroes */
4892 if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4894 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4903 operand *leftOp, *rightOp;
4905 leftOp = IC_LEFT(ic);
4906 rightOp = IC_RIGHT(ic);
4910 if (aopGetUsesAcc(rightOp, offset)) {
4911 if (aopGetUsesAcc(leftOp, offset)) {
4914 MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4916 emitcode ("mov", "b,a");
4919 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4920 emitcode ("subb", "a,b");
4923 /* reverse subtraction with 2's complement */
4925 emitcode( "setb", "c");
4927 emitcode( "cpl", "c");
4928 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4929 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4930 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4931 emitcode("cpl", "a");
4932 if (size) /* skip if last byte */
4933 emitcode( "cpl", "c");
4936 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4939 emitcode ("subb", "a,%s",
4940 aopGet(rightOp, offset, FALSE, TRUE));
4943 aopPut (IC_RESULT (ic), "a", offset++);
4947 adjustArithmeticResult (ic);
4950 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4951 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4952 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4956 /*-----------------------------------------------------------------*/
4957 /* genMultbits :- multiplication of bits */
4958 /*-----------------------------------------------------------------*/
4960 genMultbits (operand * left,
4964 D (emitcode (";", "genMultbits"));
4966 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4967 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4971 /*-----------------------------------------------------------------*/
4972 /* genMultOneByte : 8*8=8/16 bit multiplication */
4973 /*-----------------------------------------------------------------*/
4975 genMultOneByte (operand * left,
4980 int size = AOP_SIZE (result);
4981 bool runtimeSign, compiletimeSign;
4982 bool lUnsigned, rUnsigned, pushedB;
4984 D (emitcode (";", "genMultOneByte"));
4986 if (size < 1 || size > 2)
4988 /* this should never happen */
4989 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4990 AOP_SIZE(result), __FILE__, lineno);
4994 /* (if two literals: the value is computed before) */
4995 /* if one literal, literal on the right */
4996 if (AOP_TYPE (left) == AOP_LIT)
5001 /* emitcode (";", "swapped left and right"); */
5003 /* if no literal, unsigned on the right: shorter code */
5004 if ( AOP_TYPE (right) != AOP_LIT
5005 && SPEC_USIGN (getSpec (operandType (left))))
5012 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5013 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5017 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
5018 no need to take care about the signedness! */
5019 || (lUnsigned && rUnsigned))
5021 /* just an unsigned 8 * 8 = 8 multiply
5023 /* emitcode (";","unsigned"); */
5024 /* TODO: check for accumulator clash between left & right aops? */
5026 if (AOP_TYPE (right) == AOP_LIT)
5028 /* moving to accumulator first helps peepholes */
5029 MOVA (aopGet (left, 0, FALSE, FALSE));
5030 MOVB (aopGet (right, 0, FALSE, FALSE));
5034 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5035 MOVA (aopGet (left, 0, FALSE, FALSE));
5038 emitcode ("mul", "ab");
5039 aopPut (result, "a", 0);
5041 aopPut (result, "b", 1);
5047 /* we have to do a signed multiply */
5048 /* emitcode (";", "signed"); */
5050 /* now sign adjust for both left & right */
5052 /* let's see what's needed: */
5053 /* apply negative sign during runtime */
5054 runtimeSign = FALSE;
5055 /* negative sign from literals */
5056 compiletimeSign = FALSE;
5060 if (AOP_TYPE(left) == AOP_LIT)
5062 /* signed literal */
5063 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5065 compiletimeSign = TRUE;
5068 /* signed but not literal */
5074 if (AOP_TYPE(right) == AOP_LIT)
5076 /* signed literal */
5077 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
5079 compiletimeSign ^= TRUE;
5082 /* signed but not literal */
5086 /* initialize F0, which stores the runtime sign */
5089 if (compiletimeSign)
5090 emitcode ("setb", "F0"); /* set sign flag */
5092 emitcode ("clr", "F0"); /* reset sign flag */
5095 /* save the signs of the operands */
5096 if (AOP_TYPE(right) == AOP_LIT)
5098 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
5100 if (!rUnsigned && val < 0)
5101 emitcode ("mov", "b,#0x%02x", -val);
5103 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5105 else /* ! literal */
5107 if (rUnsigned) /* emitcode (";", "signed"); */
5108 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5111 MOVA (aopGet (right, 0, FALSE, FALSE));
5112 lbl = newiTempLabel (NULL);
5113 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5114 emitcode ("cpl", "F0"); /* complement sign flag */
5115 emitcode ("cpl", "a"); /* 2's complement */
5116 emitcode ("inc", "a");
5118 emitcode ("mov", "b,a");
5122 if (AOP_TYPE(left) == AOP_LIT)
5124 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5126 if (!lUnsigned && val < 0)
5127 emitcode ("mov", "a,#0x%02x", -val);
5129 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5131 else /* ! literal */
5133 MOVA (aopGet (left, 0, FALSE, FALSE));
5137 lbl = newiTempLabel (NULL);
5138 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5139 emitcode ("cpl", "F0"); /* complement sign flag */
5140 emitcode ("cpl", "a"); /* 2's complement */
5141 emitcode ("inc", "a");
5146 /* now the multiplication */
5147 emitcode ("mul", "ab");
5148 if (runtimeSign || compiletimeSign)
5150 lbl = newiTempLabel (NULL);
5152 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5153 emitcode ("cpl", "a"); /* lsb 2's complement */
5155 emitcode ("inc", "a"); /* inc doesn't set carry flag */
5158 emitcode ("add", "a,#1"); /* this sets carry flag */
5159 emitcode ("xch", "a,b");
5160 emitcode ("cpl", "a"); /* msb 2's complement */
5161 emitcode ("addc", "a,#0");
5162 emitcode ("xch", "a,b");
5166 aopPut (result, "a", 0);
5168 aopPut (result, "b", 1);
5173 /*-----------------------------------------------------------------*/
5174 /* genMult - generates code for multiplication */
5175 /*-----------------------------------------------------------------*/
5177 genMult (iCode * ic)
5179 operand *left = IC_LEFT (ic);
5180 operand *right = IC_RIGHT (ic);
5181 operand *result = IC_RESULT (ic);
5183 D (emitcode (";", "genMult"));
5185 /* assign the asmops */
5186 aopOp (left, ic, FALSE);
5187 aopOp (right, ic, FALSE);
5188 aopOp (result, ic, TRUE);
5190 /* special cases first */
5192 if (AOP_TYPE (left) == AOP_CRY &&
5193 AOP_TYPE (right) == AOP_CRY)
5195 genMultbits (left, right, result);
5199 /* if both are of size == 1 */
5200 #if 0 // one of them can be a sloc shared with the result
5201 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
5203 if (getSize(operandType(left)) == 1 &&
5204 getSize(operandType(right)) == 1)
5207 genMultOneByte (left, right, result);
5211 /* should have been converted to function call */
5212 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
5213 getSize(OP_SYMBOL(right)->type));
5217 freeAsmop (result, NULL, ic, TRUE);
5218 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5219 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5222 /*-----------------------------------------------------------------*/
5223 /* genDivbits :- division of bits */
5224 /*-----------------------------------------------------------------*/
5226 genDivbits (operand * left,
5233 D(emitcode (";", "genDivbits"));
5237 /* the result must be bit */
5238 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5239 l = aopGet (left, 0, FALSE, FALSE);
5243 emitcode ("div", "ab");
5244 emitcode ("rrc", "a");
5248 aopPut (result, "c", 0);
5251 /*-----------------------------------------------------------------*/
5252 /* genDivOneByte : 8 bit division */
5253 /*-----------------------------------------------------------------*/
5255 genDivOneByte (operand * left,
5259 bool lUnsigned, rUnsigned, pushedB;
5260 bool runtimeSign, compiletimeSign;
5261 bool accuse = FALSE;
5262 bool pushedA = FALSE;
5266 D(emitcode (";", "genDivOneByte"));
5268 /* Why is it necessary that genDivOneByte() can return an int result?
5271 volatile unsigned char uc;
5272 volatile signed char sc1, sc2;
5285 In all cases a one byte result would overflow, the following cast to int
5286 would return the wrong result.
5288 Two possible solution:
5289 a) cast operands to int, if ((unsigned) / (signed)) or
5290 ((signed) / (signed))
5291 b) return an 16 bit signed int; this is what we're doing here!
5294 size = AOP_SIZE (result) - 1;
5296 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5297 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5301 /* signed or unsigned */
5302 if (lUnsigned && rUnsigned)
5304 /* unsigned is easy */
5305 MOVB (aopGet (right, 0, FALSE, FALSE));
5306 MOVA (aopGet (left, 0, FALSE, FALSE));
5307 emitcode ("div", "ab");
5308 aopPut (result, "a", 0);
5310 aopPut (result, zero, offset++);
5316 /* signed is a little bit more difficult */
5318 /* now sign adjust for both left & right */
5320 /* let's see what's needed: */
5321 /* apply negative sign during runtime */
5322 runtimeSign = FALSE;
5323 /* negative sign from literals */
5324 compiletimeSign = FALSE;
5328 if (AOP_TYPE(left) == AOP_LIT)
5330 /* signed literal */
5331 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5333 compiletimeSign = TRUE;
5336 /* signed but not literal */
5342 if (AOP_TYPE(right) == AOP_LIT)
5344 /* signed literal */
5345 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
5347 compiletimeSign ^= TRUE;
5350 /* signed but not literal */
5354 /* initialize F0, which stores the runtime sign */
5357 if (compiletimeSign)
5358 emitcode ("setb", "F0"); /* set sign flag */
5360 emitcode ("clr", "F0"); /* reset sign flag */
5363 /* save the signs of the operands */
5364 if (AOP_TYPE(right) == AOP_LIT)
5366 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
5368 if (!rUnsigned && val < 0)
5369 emitcode ("mov", "b,#0x%02x", -val);
5371 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5373 else /* ! literal */
5376 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5379 MOVA (aopGet (right, 0, FALSE, FALSE));
5380 lbl = newiTempLabel (NULL);
5381 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5382 emitcode ("cpl", "F0"); /* complement sign flag */
5383 emitcode ("cpl", "a"); /* 2's complement */
5384 emitcode ("inc", "a");
5386 emitcode ("mov", "b,a");
5390 if (AOP_TYPE(left) == AOP_LIT)
5392 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5394 if (!lUnsigned && val < 0)
5395 emitcode ("mov", "a,#0x%02x", -val);
5397 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5399 else /* ! literal */
5401 MOVA (aopGet (left, 0, FALSE, FALSE));
5405 lbl = newiTempLabel (NULL);
5406 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5407 emitcode ("cpl", "F0"); /* complement sign flag */
5408 emitcode ("cpl", "a"); /* 2's complement */
5409 emitcode ("inc", "a");
5414 /* now the division */
5415 emitcode ("div", "ab");
5417 if (runtimeSign || compiletimeSign)
5419 lbl = newiTempLabel (NULL);
5421 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5422 emitcode ("cpl", "a"); /* lsb 2's complement */
5423 emitcode ("inc", "a");
5426 accuse = aopPut (result, "a", 0);
5429 /* msb is 0x00 or 0xff depending on the sign */
5434 emitcode ("push", "acc");
5437 emitcode ("mov", "c,F0");
5438 emitcode ("subb", "a,acc");
5440 aopPut (result, "a", offset++);
5442 else /* compiletimeSign */
5444 if (aopPutUsesAcc (result, "#0xFF", offset))
5446 emitcode ("push", "acc");
5450 aopPut (result, "#0xff", offset++);
5456 aopPut (result, "a", 0);
5458 aopPut (result, zero, offset++);
5462 emitcode ("pop", "acc");
5466 /*-----------------------------------------------------------------*/
5467 /* genDiv - generates code for division */
5468 /*-----------------------------------------------------------------*/
5472 operand *left = IC_LEFT (ic);
5473 operand *right = IC_RIGHT (ic);
5474 operand *result = IC_RESULT (ic);
5476 D (emitcode (";", "genDiv"));
5478 /* assign the asmops */
5479 aopOp (left, ic, FALSE);
5480 aopOp (right, ic, FALSE);
5481 aopOp (result, ic, TRUE);
5483 /* special cases first */
5485 if (AOP_TYPE (left) == AOP_CRY &&
5486 AOP_TYPE (right) == AOP_CRY)
5488 genDivbits (left, right, result);
5492 /* if both are of size == 1 */
5493 if (AOP_SIZE (left) == 1 &&
5494 AOP_SIZE (right) == 1)
5496 genDivOneByte (left, right, result);
5500 /* should have been converted to function call */
5503 freeAsmop (result, NULL, ic, TRUE);
5504 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5505 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5508 /*-----------------------------------------------------------------*/
5509 /* genModbits :- modulus of bits */
5510 /*-----------------------------------------------------------------*/
5512 genModbits (operand * left,
5519 D (emitcode (";", "genModbits"));
5523 /* the result must be bit */
5524 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5525 l = aopGet (left, 0, FALSE, FALSE);
5529 emitcode ("div", "ab");
5530 emitcode ("mov", "a,b");
5531 emitcode ("rrc", "a");
5535 aopPut (result, "c", 0);
5538 /*-----------------------------------------------------------------*/
5539 /* genModOneByte : 8 bit modulus */
5540 /*-----------------------------------------------------------------*/
5542 genModOneByte (operand * left,
5546 bool lUnsigned, rUnsigned, pushedB;
5547 bool runtimeSign, compiletimeSign;
5551 D (emitcode (";", "genModOneByte"));
5553 size = AOP_SIZE (result) - 1;
5555 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5556 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5558 /* if right is a literal, check it for 2^n */
5559 if (AOP_TYPE(right) == AOP_LIT)
5561 unsigned char val = abs((int) operandLitValue(right));
5562 symbol *lbl2 = NULL;
5566 case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5575 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5576 "modulus of unsigned char by 2^n literal shouldn't be processed here");
5577 /* because iCode should have been changed to genAnd */
5578 /* see file "SDCCopt.c", function "convertToFcall()" */
5580 MOVA (aopGet (left, 0, FALSE, FALSE));
5581 emitcode ("mov", "c,acc.7");
5582 emitcode ("anl", "a,#0x%02x", val - 1);
5583 lbl = newiTempLabel (NULL);
5584 emitcode ("jz", "%05d$", (lbl->key + 100));
5585 emitcode ("jnc", "%05d$", (lbl->key + 100));
5586 emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5592 aopPut (result, "a", 0);
5594 aopPut (result, "#0xff", offs2++);
5595 lbl2 = newiTempLabel (NULL);
5596 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5599 aopPut (result, "a", 0);
5601 aopPut (result, zero, offset++);
5615 /* signed or unsigned */
5616 if (lUnsigned && rUnsigned)
5618 /* unsigned is easy */
5619 MOVB (aopGet (right, 0, FALSE, FALSE));
5620 MOVA (aopGet (left, 0, FALSE, FALSE));
5621 emitcode ("div", "ab");
5622 aopPut (result, "b", 0);
5624 aopPut (result, zero, offset++);
5630 /* signed is a little bit more difficult */
5632 /* now sign adjust for both left & right */
5634 /* modulus: sign of the right operand has no influence on the result! */
5635 if (AOP_TYPE(right) == AOP_LIT)
5637 signed char val = (char) operandLitValue(right);
5639 if (!rUnsigned && val < 0)
5640 emitcode ("mov", "b,#0x%02x", -val);
5642 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5644 else /* not literal */
5647 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5650 MOVA (aopGet (right, 0, FALSE, FALSE));
5651 lbl = newiTempLabel (NULL);
5652 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5653 emitcode ("cpl", "a"); /* 2's complement */
5654 emitcode ("inc", "a");
5656 emitcode ("mov", "b,a");
5660 /* let's see what's needed: */
5661 /* apply negative sign during runtime */
5662 runtimeSign = FALSE;
5663 /* negative sign from literals */
5664 compiletimeSign = FALSE;
5666 /* sign adjust left side */
5667 if (AOP_TYPE(left) == AOP_LIT)
5669 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5671 if (!lUnsigned && val < 0)
5673 compiletimeSign = TRUE; /* set sign flag */
5674 emitcode ("mov", "a,#0x%02x", -val);
5677 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5679 else /* ! literal */
5681 MOVA (aopGet (left, 0, FALSE, FALSE));
5686 emitcode ("clr", "F0"); /* clear sign flag */
5688 lbl = newiTempLabel (NULL);
5689 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5690 emitcode ("setb", "F0"); /* set sign flag */
5691 emitcode ("cpl", "a"); /* 2's complement */
5692 emitcode ("inc", "a");
5697 /* now the modulus */
5698 emitcode ("div", "ab");
5700 if (runtimeSign || compiletimeSign)
5702 emitcode ("mov", "a,b");
5703 lbl = newiTempLabel (NULL);
5705 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5706 emitcode ("cpl", "a"); /* 2's complement */
5707 emitcode ("inc", "a");
5710 aopPut (result, "a", 0);
5713 /* msb is 0x00 or 0xff depending on the sign */
5716 emitcode ("mov", "c,F0");
5717 emitcode ("subb", "a,acc");
5719 aopPut (result, "a", offset++);
5721 else /* compiletimeSign */
5723 aopPut (result, "#0xff", offset++);
5728 aopPut (result, "b", 0);
5730 aopPut (result, zero, offset++);
5736 /*-----------------------------------------------------------------*/
5737 /* genMod - generates code for division */
5738 /*-----------------------------------------------------------------*/
5742 operand *left = IC_LEFT (ic);
5743 operand *right = IC_RIGHT (ic);
5744 operand *result = IC_RESULT (ic);
5746 D (emitcode (";", "genMod"));
5748 /* assign the asmops */
5749 aopOp (left, ic, FALSE);
5750 aopOp (right, ic, FALSE);
5751 aopOp (result, ic, TRUE);
5753 /* special cases first */
5755 if (AOP_TYPE (left) == AOP_CRY &&
5756 AOP_TYPE (right) == AOP_CRY)
5758 genModbits (left, right, result);
5762 /* if both are of size == 1 */
5763 if (AOP_SIZE (left) == 1 &&
5764 AOP_SIZE (right) == 1)
5766 genModOneByte (left, right, result);
5770 /* should have been converted to function call */
5774 freeAsmop (result, NULL, ic, TRUE);
5775 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5776 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5779 /*-----------------------------------------------------------------*/
5780 /* genIfxJump :- will create a jump depending on the ifx */
5781 /*-----------------------------------------------------------------*/
5783 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5786 symbol *tlbl = newiTempLabel (NULL);
5789 D (emitcode (";", "genIfxJump"));
5791 /* if true label then we jump if condition
5795 jlbl = IC_TRUE (ic);
5796 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5797 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5801 /* false label is present */
5802 jlbl = IC_FALSE (ic);
5803 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5804 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5806 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5807 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5809 emitcode (inst, "%05d$", tlbl->key + 100);
5810 freeForBranchAsmop (result);
5811 freeForBranchAsmop (right);
5812 freeForBranchAsmop (left);
5813 emitcode ("ljmp", "%05d$", jlbl->key + 100);
5816 /* mark the icode as generated */
5820 /*-----------------------------------------------------------------*/
5821 /* genCmp :- greater or less than comparison */
5822 /*-----------------------------------------------------------------*/
5824 genCmp (operand * left, operand * right,
5825 operand * result, iCode * ifx, int sign, iCode *ic)
5827 int size, offset = 0;
5828 unsigned long lit = 0L;
5831 D (emitcode (";", "genCmp"));
5833 /* if left & right are bit variables */
5834 if (AOP_TYPE (left) == AOP_CRY &&
5835 AOP_TYPE (right) == AOP_CRY)
5837 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5838 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5842 /* subtract right from left if at the
5843 end the carry flag is set then we know that
5844 left is greater than right */
5845 size = max (AOP_SIZE (left), AOP_SIZE (right));
5847 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5848 if ((size == 1) && !sign &&
5849 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5851 symbol *lbl = newiTempLabel (NULL);
5852 emitcode ("cjne", "%s,%s,%05d$",
5853 aopGet (left, offset, FALSE, FALSE),
5854 aopGet (right, offset, FALSE, FALSE),
5860 if (AOP_TYPE (right) == AOP_LIT)
5862 lit = ulFromVal (AOP (right)->aopu.aop_lit);
5863 /* optimize if(x < 0) or if(x >= 0) */
5872 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5873 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5875 genIfxJump (ifx, "acc.7", left, right, result);
5876 freeAsmop (right, NULL, ic, TRUE);
5877 freeAsmop (left, NULL, ic, TRUE);
5883 emitcode ("rlc", "a");
5890 int bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5891 while (size && (bytelit == 0))
5894 bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5900 MOVA (aopGet (left, offset, FALSE, FALSE));
5901 if (sign && size == 0)
5903 emitcode ("xrl", "a,#0x80");
5904 emitcode ("subb", "a,#0x%02x",
5905 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5909 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5919 bool pushedB = FALSE;
5920 rightInB = aopGetUsesAcc(right, offset);
5924 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5926 MOVA (aopGet (left, offset, FALSE, FALSE));
5927 if (sign && size == 0)
5929 emitcode ("xrl", "a,#0x80");
5934 MOVB (aopGet (right, offset, FALSE, FALSE));
5936 emitcode ("xrl", "b,#0x80");
5937 emitcode ("subb", "a,b");
5942 emitcode ("subb", "a,b");
5944 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5954 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5955 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5956 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5962 /* if the result is used in the next
5963 ifx conditional branch then generate
5964 code a little differently */
5967 genIfxJump (ifx, "c", NULL, NULL, result);
5973 /* leave the result in acc */
5977 /*-----------------------------------------------------------------*/
5978 /* genCmpGt :- greater than comparison */
5979 /*-----------------------------------------------------------------*/
5981 genCmpGt (iCode * ic, iCode * ifx)
5983 operand *left, *right, *result;
5984 sym_link *letype, *retype;
5987 D (emitcode (";", "genCmpGt"));
5989 left = IC_LEFT (ic);
5990 right = IC_RIGHT (ic);
5991 result = IC_RESULT (ic);
5993 letype = getSpec (operandType (left));
5994 retype = getSpec (operandType (right));
5995 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5996 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5997 /* assign the asmops */
5998 aopOp (result, ic, TRUE);
5999 aopOp (left, ic, FALSE);
6000 aopOp (right, ic, FALSE);
6002 genCmp (right, left, result, ifx, sign, ic);
6004 freeAsmop (result, NULL, ic, TRUE);
6007 /*-----------------------------------------------------------------*/
6008 /* genCmpLt - less than comparisons */
6009 /*-----------------------------------------------------------------*/
6011 genCmpLt (iCode * ic, iCode * ifx)
6013 operand *left, *right, *result;
6014 sym_link *letype, *retype;
6017 D (emitcode (";", "genCmpLt"));
6019 left = IC_LEFT (ic);
6020 right = IC_RIGHT (ic);
6021 result = IC_RESULT (ic);
6023 letype = getSpec (operandType (left));
6024 retype = getSpec (operandType (right));
6025 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
6026 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
6027 /* assign the asmops */
6028 aopOp (result, ic, TRUE);
6029 aopOp (left, ic, FALSE);
6030 aopOp (right, ic, FALSE);
6032 genCmp (left, right, result, ifx, sign, ic);
6034 freeAsmop (result, NULL, ic, TRUE);
6037 /*-----------------------------------------------------------------*/
6038 /* gencjneshort - compare and jump if not equal */
6039 /*-----------------------------------------------------------------*/
6041 gencjneshort (operand * left, operand * right, symbol * lbl)
6043 int size = max (AOP_SIZE (left), AOP_SIZE (right));
6045 unsigned long lit = 0L;
6047 D (emitcode (";", "gencjneshort"));
6049 /* if the left side is a literal or
6050 if the right is in a pointer register and left
6052 if ((AOP_TYPE (left) == AOP_LIT) ||
6053 (AOP_TYPE (left) == AOP_IMMD) ||
6054 (AOP_TYPE (left) == AOP_DIR) ||
6055 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6062 if (AOP_TYPE (right) == AOP_LIT)
6063 lit = ulFromVal (AOP (right)->aopu.aop_lit);
6065 /* if the right side is a literal then anything goes */
6066 if (AOP_TYPE (right) == AOP_LIT &&
6067 AOP_TYPE (left) != AOP_DIR &&
6068 AOP_TYPE (left) != AOP_IMMD)
6072 emitcode ("cjne", "%s,%s,%05d$",
6073 aopGet (left, offset, FALSE, FALSE),
6074 aopGet (right, offset, FALSE, FALSE),
6080 /* if the right side is in a register or in direct space or
6081 if the left is a pointer register & right is not */
6082 else if (AOP_TYPE (right) == AOP_REG ||
6083 AOP_TYPE (right) == AOP_DIR ||
6084 AOP_TYPE (right) == AOP_LIT ||
6085 AOP_TYPE (right) == AOP_IMMD ||
6086 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6087 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6091 MOVA (aopGet (left, offset, FALSE, FALSE));
6092 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6093 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6094 emitcode ("jnz", "%05d$", lbl->key + 100);
6096 emitcode ("cjne", "a,%s,%05d$",
6097 aopGet (right, offset, FALSE, TRUE),
6104 /* right is a pointer reg need both a & b */
6107 //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
6108 wassertl(!BINUSE, "B was in use");
6109 MOVB (aopGet (left, offset, FALSE, FALSE));
6110 MOVA (aopGet (right, offset, FALSE, FALSE));
6111 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
6117 /*-----------------------------------------------------------------*/
6118 /* gencjne - compare and jump if not equal */
6119 /*-----------------------------------------------------------------*/
6121 gencjne (operand * left, operand * right, symbol * lbl, bool useCarry)
6123 symbol *tlbl = newiTempLabel (NULL);
6125 D (emitcode (";", "gencjne"));
6127 gencjneshort (left, right, lbl);
6133 emitcode ("sjmp", "%05d$", tlbl->key + 100);
6142 /*-----------------------------------------------------------------*/
6143 /* genCmpEq - generates code for equal to */
6144 /*-----------------------------------------------------------------*/
6146 genCmpEq (iCode * ic, iCode * ifx)
6148 bool swappedLR = FALSE;
6149 operand *left, *right, *result;
6151 D (emitcode (";", "genCmpEq"));
6153 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6154 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6155 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6157 /* if literal, literal on the right or
6158 if the right is in a pointer register and left
6160 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6161 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6163 operand *t = IC_RIGHT (ic);
6164 IC_RIGHT (ic) = IC_LEFT (ic);
6169 if (ifx && !AOP_SIZE (result))
6172 /* if they are both bit variables */
6173 if (AOP_TYPE (left) == AOP_CRY &&
6174 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6176 if (AOP_TYPE (right) == AOP_LIT)
6178 unsigned long lit = ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6181 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6182 emitcode ("cpl", "c");
6186 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6190 emitcode ("clr", "c");
6192 /* AOP_TYPE(right) == AOP_CRY */
6196 symbol *lbl = newiTempLabel (NULL);
6197 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6198 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6199 emitcode ("cpl", "c");
6202 /* if true label then we jump if condition
6204 tlbl = newiTempLabel (NULL);
6207 emitcode ("jnc", "%05d$", tlbl->key + 100);
6208 freeForBranchAsmop (result);
6209 freeForBranchAsmop (right);
6210 freeForBranchAsmop (left);
6211 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6215 emitcode ("jc", "%05d$", tlbl->key + 100);
6216 freeForBranchAsmop (result);
6217 freeForBranchAsmop (right);
6218 freeForBranchAsmop (left);
6219 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6225 tlbl = newiTempLabel (NULL);
6226 gencjneshort (left, right, tlbl);
6229 freeForBranchAsmop (result);
6230 freeForBranchAsmop (right);
6231 freeForBranchAsmop (left);
6232 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6237 symbol *lbl = newiTempLabel (NULL);
6238 emitcode ("sjmp", "%05d$", lbl->key + 100);
6240 freeForBranchAsmop (result);
6241 freeForBranchAsmop (right);
6242 freeForBranchAsmop (left);
6243 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6247 /* mark the icode as generated */
6252 /* if they are both bit variables */
6253 if (AOP_TYPE (left) == AOP_CRY &&
6254 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6256 if (AOP_TYPE (right) == AOP_LIT)
6258 unsigned long lit = ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6261 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6262 emitcode ("cpl", "c");
6266 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6270 emitcode ("clr", "c");
6272 /* AOP_TYPE(right) == AOP_CRY */
6276 symbol *lbl = newiTempLabel (NULL);
6277 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6278 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6279 emitcode ("cpl", "c");
6283 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6290 genIfxJump (ifx, "c", left, right, result);
6293 /* if the result is used in an arithmetic operation
6294 then put the result in place */
6299 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6301 gencjne (left, right, newiTempLabel (NULL), TRUE);
6302 aopPut (result, "c", 0);
6305 gencjne (left, right, newiTempLabel (NULL), FALSE);
6308 genIfxJump (ifx, "a", left, right, result);
6311 /* if the result is used in an arithmetic operation
6312 then put the result in place */
6313 if (AOP_TYPE (result) != AOP_CRY)
6315 /* leave the result in acc */
6319 freeAsmop (result, NULL, ic, TRUE);
6322 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6323 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6327 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6328 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6332 /*-----------------------------------------------------------------*/
6333 /* ifxForOp - returns the icode containing the ifx for operand */
6334 /*-----------------------------------------------------------------*/
6336 ifxForOp (operand * op, iCode * ic)
6338 /* if true symbol then needs to be assigned */
6339 if (IS_TRUE_SYMOP (op))
6342 /* if this has register type condition and
6343 the next instruction is ifx with the same operand
6344 and live to of the operand is upto the ifx only then */
6346 ic->next->op == IFX &&
6347 IC_COND (ic->next)->key == op->key &&
6348 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6354 /*-----------------------------------------------------------------*/
6355 /* hasInc - operand is incremented before any other use */
6356 /*-----------------------------------------------------------------*/
6358 hasInc (operand *op, iCode *ic, int osize)
6360 sym_link *type = operandType(op);
6361 sym_link *retype = getSpec (type);
6362 iCode *lic = ic->next;
6365 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6366 if (!IS_SYMOP(op)) return NULL;
6368 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6369 if (IS_AGGREGATE(type->next)) return NULL;
6370 if (osize != (isize = getSize(type->next))) return NULL;
6373 /* if operand of the form op = op + <sizeof *op> */
6374 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6375 isOperandEqual(IC_RESULT(lic),op) &&
6376 isOperandLiteral(IC_RIGHT(lic)) &&
6377 operandLitValue(IC_RIGHT(lic)) == isize) {
6380 /* if the operand used or deffed */
6381 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6384 /* if GOTO or IFX */
6385 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6391 /*-----------------------------------------------------------------*/
6392 /* genAndOp - for && operation */
6393 /*-----------------------------------------------------------------*/
6395 genAndOp (iCode * ic)
6397 operand *left, *right, *result;
6400 D (emitcode (";", "genAndOp"));
6402 /* note here that && operations that are in an
6403 if statement are taken away by backPatchLabels
6404 only those used in arthmetic operations remain */
6405 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6406 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6407 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6409 /* if both are bit variables */
6410 if (AOP_TYPE (left) == AOP_CRY &&
6411 AOP_TYPE (right) == AOP_CRY)
6413 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6414 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6419 tlbl = newiTempLabel (NULL);
6421 emitcode ("jz", "%05d$", tlbl->key + 100);
6427 freeAsmop (result, NULL, ic, TRUE);
6428 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6429 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6433 /*-----------------------------------------------------------------*/
6434 /* genOrOp - for || operation */
6435 /*-----------------------------------------------------------------*/
6437 genOrOp (iCode * ic)
6439 operand *left, *right, *result;
6442 D (emitcode (";", "genOrOp"));
6444 /* note here that || operations that are in an
6445 if statement are taken away by backPatchLabels
6446 only those used in arthmetic operations remain */
6447 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6448 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6449 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6451 /* if both are bit variables */
6452 if (AOP_TYPE (left) == AOP_CRY &&
6453 AOP_TYPE (right) == AOP_CRY)
6455 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6456 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6461 tlbl = newiTempLabel (NULL);
6463 emitcode ("jnz", "%05d$", tlbl->key + 100);
6469 freeAsmop (result, NULL, ic, TRUE);
6470 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6471 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6474 /*-----------------------------------------------------------------*/
6475 /* isLiteralBit - test if lit == 2^n */
6476 /*-----------------------------------------------------------------*/
6478 isLiteralBit (unsigned long lit)
6480 unsigned long pw[32] =
6481 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6482 0x100L, 0x200L, 0x400L, 0x800L,
6483 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6484 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6485 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6486 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6487 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6490 for (idx = 0; idx < 32; idx++)
6496 /*-----------------------------------------------------------------*/
6497 /* continueIfTrue - */
6498 /*-----------------------------------------------------------------*/
6500 continueIfTrue (iCode * ic)
6503 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6507 /*-----------------------------------------------------------------*/
6509 /*-----------------------------------------------------------------*/
6511 jumpIfTrue (iCode * ic)
6514 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6518 /*-----------------------------------------------------------------*/
6519 /* jmpTrueOrFalse - */
6520 /*-----------------------------------------------------------------*/
6522 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6524 // ugly but optimized by peephole
6527 symbol *nlbl = newiTempLabel (NULL);
6528 emitcode ("sjmp", "%05d$", nlbl->key + 100);
6530 freeForBranchAsmop (result);
6531 freeForBranchAsmop (right);
6532 freeForBranchAsmop (left);
6533 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6538 freeForBranchAsmop (result);
6539 freeForBranchAsmop (right);
6540 freeForBranchAsmop (left);
6541 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6547 /*-----------------------------------------------------------------*/
6548 /* genAnd - code for and */
6549 /*-----------------------------------------------------------------*/
6551 genAnd (iCode * ic, iCode * ifx)
6553 operand *left, *right, *result;
6554 int size, offset = 0;
6555 unsigned long lit = 0L;
6559 D (emitcode (";", "genAnd"));
6561 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6562 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6563 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6566 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
6568 AOP_TYPE (left), AOP_TYPE (right));
6569 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
6571 AOP_SIZE (left), AOP_SIZE (right));
6574 /* if left is a literal & right is not then exchange them */
6575 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6576 AOP_NEEDSACC (left))
6578 operand *tmp = right;
6583 /* if result = right then exchange left and right */
6584 if (sameRegs (AOP (result), AOP (right)))
6586 operand *tmp = right;
6591 /* if right is bit then exchange them */
6592 if (AOP_TYPE (right) == AOP_CRY &&
6593 AOP_TYPE (left) != AOP_CRY)
6595 operand *tmp = right;
6599 if (AOP_TYPE (right) == AOP_LIT)
6600 lit = ulFromVal (AOP (right)->aopu.aop_lit);
6602 size = AOP_SIZE (result);
6605 // result = bit & yy;
6606 if (AOP_TYPE (left) == AOP_CRY)
6608 // c = bit & literal;
6609 if (AOP_TYPE (right) == AOP_LIT)
6613 if (size && sameRegs (AOP (result), AOP (left)))
6616 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6621 if (size && (AOP_TYPE (result) == AOP_CRY))
6623 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6626 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6631 emitcode ("clr", "c");
6636 if (AOP_TYPE (right) == AOP_CRY)
6639 if (IS_OP_ACCUSE (left))
6641 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6645 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6646 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6652 MOVA (aopGet (right, 0, FALSE, FALSE));
6654 emitcode ("rrc", "a");
6655 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6663 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6664 genIfxJump (ifx, "c", left, right, result);
6668 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6669 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6670 if ((AOP_TYPE (right) == AOP_LIT) &&
6671 (AOP_TYPE (result) == AOP_CRY) &&
6672 (AOP_TYPE (left) != AOP_CRY))
6674 int posbit = isLiteralBit (lit);
6679 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6683 switch (posbit & 0x07)
6685 case 0: emitcode ("rrc", "a");
6687 case 7: emitcode ("rlc", "a");
6689 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6698 SNPRINTF (buffer, sizeof(buffer),
6699 "acc.%d", posbit & 0x07);
6700 genIfxJump (ifx, buffer, left, right, result);
6703 {// what is this case? just found it in ds390/gen.c
6704 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6711 symbol *tlbl = newiTempLabel (NULL);
6712 int sizel = AOP_SIZE (left);
6714 emitcode ("setb", "c");
6717 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6719 MOVA (aopGet (left, offset, FALSE, FALSE));
6721 if ((posbit = isLiteralBit (bytelit)) != 0)
6722 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6725 if (bytelit != 0x0FFL)
6726 emitcode ("anl", "a,%s",
6727 aopGet (right, offset, FALSE, TRUE));
6728 emitcode ("jnz", "%05d$", tlbl->key + 100);
6733 // bit = left & literal
6736 emitcode ("clr", "c");
6739 // if(left & literal)
6743 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6753 /* if left is same as result */
6754 if (sameRegs (AOP (result), AOP (left)))
6756 for (; size--; offset++)
6758 if (AOP_TYPE (right) == AOP_LIT)
6760 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6761 if (bytelit == 0x0FF)
6763 /* dummy read of volatile operand */
6764 if (isOperandVolatile (left, FALSE))
6765 MOVA (aopGet (left, offset, FALSE, FALSE));
6769 else if (bytelit == 0)
6771 aopPut (result, zero, offset);
6773 else if (IS_AOP_PREG (result))
6775 MOVA (aopGet (left, offset, FALSE, TRUE));
6776 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6777 aopPut (result, "a", offset);
6780 emitcode ("anl", "%s,%s",
6781 aopGet (left, offset, FALSE, TRUE),
6782 aopGet (right, offset, FALSE, FALSE));
6786 if (AOP_TYPE (left) == AOP_ACC)
6789 emitcode("mov", "a,b");
6790 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6792 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6794 MOVB (aopGet (left, offset, FALSE, FALSE));
6795 MOVA (aopGet (right, offset, FALSE, FALSE));
6796 emitcode ("anl", "a,b");
6797 aopPut (result, "a", offset);
6799 else if (aopGetUsesAcc (left, offset))
6801 MOVA (aopGet (left, offset, FALSE, FALSE));
6802 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6803 aopPut (result, "a", offset);
6807 MOVA (aopGet (right, offset, FALSE, FALSE));
6808 if (IS_AOP_PREG (result))
6810 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6811 aopPut (result, "a", offset);
6814 emitcode ("anl", "%s,a", aopGet (left, offset, FALSE, TRUE));
6821 // left & result in different registers
6822 if (AOP_TYPE (result) == AOP_CRY)
6825 // if(size), result in bit
6826 // if(!size && ifx), conditional oper: if(left & right)
6827 symbol *tlbl = newiTempLabel (NULL);
6828 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6830 emitcode ("setb", "c");
6833 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6834 && AOP_TYPE(left)==AOP_ACC)
6837 emitcode("mov", "a,b");
6838 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6840 else if (AOP_TYPE(left)==AOP_ACC)
6844 bool pushedB = pushB ();
6845 emitcode("mov", "b,a");
6846 MOVA (aopGet (right, offset, FALSE, FALSE));
6847 emitcode("anl", "a,b");
6852 MOVA (aopGet (right, offset, FALSE, FALSE));
6853 emitcode("anl", "a,b");
6856 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6858 MOVB (aopGet (left, offset, FALSE, FALSE));
6859 MOVA (aopGet (right, offset, FALSE, FALSE));
6860 emitcode ("anl", "a,b");
6862 else if (aopGetUsesAcc (left, offset))
6864 MOVA (aopGet (left, offset, FALSE, FALSE));
6865 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6869 MOVA (aopGet (right, offset, FALSE, FALSE));
6870 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6873 emitcode ("jnz", "%05d$", tlbl->key + 100);
6883 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6889 for (; (size--); offset++)
6892 // result = left & right
6893 if (AOP_TYPE (right) == AOP_LIT)
6895 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6896 if (bytelit == 0x0FF)
6899 aopGet (left, offset, FALSE, FALSE),
6903 else if (bytelit == 0)
6905 /* dummy read of volatile operand */
6906 if (isOperandVolatile (left, FALSE))
6907 MOVA (aopGet (left, offset, FALSE, FALSE));
6908 aopPut (result, zero, offset);
6911 else if (AOP_TYPE (left) == AOP_ACC)
6915 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6916 aopPut (result, "a", offset);
6921 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6922 aopPut (result, "b", offset);
6927 // faster than result <- left, anl result,right
6928 // and better if result is SFR
6929 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6930 && AOP_TYPE(left)==AOP_ACC)
6933 emitcode("mov", "a,b");
6934 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6936 else if (AOP_TYPE(left)==AOP_ACC)
6940 bool pushedB = pushB ();
6941 emitcode("mov", "b,a");
6942 MOVA (aopGet (right, offset, FALSE, FALSE));
6943 emitcode("anl", "a,b");
6948 MOVA (aopGet (right, offset, FALSE, FALSE));
6949 emitcode("anl", "a,b");
6952 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6954 MOVB (aopGet (left, offset, FALSE, FALSE));
6955 MOVA (aopGet (right, offset, FALSE, FALSE));
6956 emitcode ("anl", "a,b");
6958 else if (aopGetUsesAcc (left, offset))
6960 MOVA (aopGet (left, offset, FALSE, FALSE));
6961 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6965 MOVA (aopGet (right, offset, FALSE, FALSE));
6966 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6968 aopPut (result, "a", offset);
6974 freeAsmop (result, NULL, ic, TRUE);
6975 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6976 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6979 /*-----------------------------------------------------------------*/
6980 /* genOr - code for or */
6981 /*-----------------------------------------------------------------*/
6983 genOr (iCode * ic, iCode * ifx)
6985 operand *left, *right, *result;
6986 int size, offset = 0;
6987 unsigned long lit = 0L;
6990 D (emitcode (";", "genOr"));
6992 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6993 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6994 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6997 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
6999 AOP_TYPE (left), AOP_TYPE (right));
7000 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
7002 AOP_SIZE (left), AOP_SIZE (right));
7005 /* if left is a literal & right is not then exchange them */
7006 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7007 AOP_NEEDSACC (left))
7009 operand *tmp = right;
7014 /* if result = right then exchange them */
7015 if (sameRegs (AOP (result), AOP (right)))
7017 operand *tmp = right;
7022 /* if right is bit then exchange them */
7023 if (AOP_TYPE (right) == AOP_CRY &&
7024 AOP_TYPE (left) != AOP_CRY)
7026 operand *tmp = right;
7030 if (AOP_TYPE (right) == AOP_LIT)
7031 lit = ulFromVal (AOP (right)->aopu.aop_lit);
7033 size = AOP_SIZE (result);
7037 if (AOP_TYPE (left) == AOP_CRY)
7039 if (AOP_TYPE (right) == AOP_LIT)
7041 // c = bit | literal;
7044 // lit != 0 => result = 1
7045 if (AOP_TYPE (result) == AOP_CRY)
7048 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7050 continueIfTrue (ifx);
7053 emitcode ("setb", "c");
7057 // lit == 0 => result = left
7058 if (size && sameRegs (AOP (result), AOP (left)))
7060 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7065 if (AOP_TYPE (right) == AOP_CRY)
7068 if (IS_OP_ACCUSE (left))
7070 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
7074 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7075 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7081 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7083 symbol *tlbl = newiTempLabel (NULL);
7084 emitcode ("jb", "%s,%05d$",
7085 AOP (left)->aopu.aop_dir, tlbl->key + 100);
7087 emitcode ("jnz", "%05d$", tlbl->key + 100);
7088 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7094 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7103 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7104 genIfxJump (ifx, "c", left, right, result);
7108 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7109 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7110 if ((AOP_TYPE (right) == AOP_LIT) &&
7111 (AOP_TYPE (result) == AOP_CRY) &&
7112 (AOP_TYPE (left) != AOP_CRY))
7118 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7120 continueIfTrue (ifx);
7125 // lit = 0, result = boolean(left)
7127 emitcode ("setb", "c");
7131 symbol *tlbl = newiTempLabel (NULL);
7132 emitcode ("jnz", "%05d$", tlbl->key + 100);
7138 genIfxJump (ifx, "a", left, right, result);
7146 /* if left is same as result */
7147 if (sameRegs (AOP (result), AOP (left)))
7149 for (; size--; offset++)
7151 if (AOP_TYPE (right) == AOP_LIT)
7153 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7156 /* dummy read of volatile operand */
7157 if (isOperandVolatile (left, FALSE))
7158 MOVA (aopGet (left, offset, FALSE, FALSE));
7162 else if (bytelit == 0x0FF)
7164 aopPut (result, "#0xFF", offset);
7166 else if (IS_AOP_PREG (left))
7168 MOVA (aopGet (left, offset, FALSE, TRUE));
7169 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7170 aopPut (result, "a", offset);
7174 emitcode ("orl", "%s,%s",
7175 aopGet (left, offset, FALSE, TRUE),
7176 aopGet (right, offset, FALSE, FALSE));
7181 if (AOP_TYPE (left) == AOP_ACC)
7184 emitcode("mov", "a,b");
7185 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7187 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7189 MOVB (aopGet (left, offset, FALSE, FALSE));
7190 MOVA (aopGet (right, offset, FALSE, FALSE));
7191 emitcode ("orl", "a,b");
7192 aopPut (result, "a", offset);
7194 else if (aopGetUsesAcc (left, offset))
7196 MOVA (aopGet (left, offset, FALSE, FALSE));
7197 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7198 aopPut (result, "a", offset);
7202 MOVA (aopGet (right, offset, FALSE, FALSE));
7203 if (IS_AOP_PREG (left))
7205 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7206 aopPut (result, "a", offset);
7210 emitcode ("orl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7218 // left & result in different registers
7219 if (AOP_TYPE (result) == AOP_CRY)
7222 // if(size), result in bit
7223 // if(!size && ifx), conditional oper: if(left | right)
7224 symbol *tlbl = newiTempLabel (NULL);
7225 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7227 emitcode ("setb", "c");
7230 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7231 && AOP_TYPE(left)==AOP_ACC)
7234 emitcode("mov", "a,b");
7235 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7237 else if (AOP_TYPE(left)==AOP_ACC)
7241 bool pushedB = pushB ();
7242 emitcode("mov", "b,a");
7243 MOVA (aopGet (right, offset, FALSE, FALSE));
7244 emitcode("orl", "a,b");
7249 MOVA (aopGet (right, offset, FALSE, FALSE));
7250 emitcode("orl", "a,b");
7253 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7255 MOVB (aopGet (left, offset, FALSE, FALSE));
7256 MOVA (aopGet (right, offset, FALSE, FALSE));
7257 emitcode ("orl", "a,b");
7259 else if (aopGetUsesAcc (left, offset))
7261 MOVA (aopGet (left, offset, FALSE, FALSE));
7262 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7266 MOVA (aopGet (right, offset, FALSE, FALSE));
7267 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7270 emitcode ("jnz", "%05d$", tlbl->key + 100);
7280 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7286 for (; (size--); offset++)
7289 // result = left | right
7290 if (AOP_TYPE (right) == AOP_LIT)
7292 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7296 aopGet (left, offset, FALSE, FALSE),
7300 else if (bytelit == 0x0FF)
7302 /* dummy read of volatile operand */
7303 if (isOperandVolatile (left, FALSE))
7304 MOVA (aopGet (left, offset, FALSE, FALSE));
7305 aopPut (result, "#0xFF", offset);
7309 // faster than result <- left, orl result,right
7310 // and better if result is SFR
7311 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7312 && AOP_TYPE(left)==AOP_ACC)
7315 emitcode("mov", "a,b");
7316 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7318 else if (AOP_TYPE(left)==AOP_ACC)
7322 bool pushedB = pushB ();
7323 emitcode("mov", "b,a");
7324 MOVA (aopGet (right, offset, FALSE, FALSE));
7325 emitcode("orl", "a,b");
7330 MOVA (aopGet (right, offset, FALSE, FALSE));
7331 emitcode("orl", "a,b");
7334 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7336 MOVB (aopGet (left, offset, FALSE, FALSE));
7337 MOVA (aopGet (right, offset, FALSE, FALSE));
7338 emitcode ("orl", "a,b");
7340 else if (aopGetUsesAcc (left, offset))
7342 MOVA (aopGet (left, offset, FALSE, FALSE));
7343 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7347 MOVA (aopGet (right, offset, FALSE, FALSE));
7348 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7350 aopPut (result, "a", offset);
7356 freeAsmop (result, NULL, ic, TRUE);
7357 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7358 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7361 /*-----------------------------------------------------------------*/
7362 /* genXor - code for xclusive or */
7363 /*-----------------------------------------------------------------*/
7365 genXor (iCode * ic, iCode * ifx)
7367 operand *left, *right, *result;
7368 int size, offset = 0;
7369 unsigned long lit = 0L;
7372 D (emitcode (";", "genXor"));
7374 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7375 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7376 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7379 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
7381 AOP_TYPE (left), AOP_TYPE (right));
7382 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
7384 AOP_SIZE (left), AOP_SIZE (right));
7387 /* if left is a literal & right is not ||
7388 if left needs acc & right does not */
7389 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7390 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7392 operand *tmp = right;
7397 /* if result = right then exchange them */
7398 if (sameRegs (AOP (result), AOP (right)))
7400 operand *tmp = right;
7405 /* if right is bit then exchange them */
7406 if (AOP_TYPE (right) == AOP_CRY &&
7407 AOP_TYPE (left) != AOP_CRY)
7409 operand *tmp = right;
7414 if (AOP_TYPE (right) == AOP_LIT)
7415 lit = ulFromVal (AOP (right)->aopu.aop_lit);
7417 size = AOP_SIZE (result);
7421 if (AOP_TYPE (left) == AOP_CRY)
7423 if (AOP_TYPE (right) == AOP_LIT)
7425 // c = bit & literal;
7428 // lit>>1 != 0 => result = 1
7429 if (AOP_TYPE (result) == AOP_CRY)
7432 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7434 continueIfTrue (ifx);
7437 emitcode ("setb", "c");
7444 // lit == 0, result = left
7445 if (size && sameRegs (AOP (result), AOP (left)))
7447 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7451 // lit == 1, result = not(left)
7452 if (size && sameRegs (AOP (result), AOP (left)))
7454 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7459 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7460 emitcode ("cpl", "c");
7468 symbol *tlbl = newiTempLabel (NULL);
7469 if (AOP_TYPE (right) == AOP_CRY)
7472 if (IS_OP_ACCUSE (left))
7473 {// left already is in the carry
7474 operand *tmp = right;
7488 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7489 emitcode ("cpl", "c");
7497 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7498 genIfxJump (ifx, "c", left, right, result);
7502 /* if left is same as result */
7503 if (sameRegs (AOP (result), AOP (left)))
7505 for (; size--; offset++)
7507 if (AOP_TYPE (right) == AOP_LIT)
7509 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7512 /* dummy read of volatile operand */
7513 if (isOperandVolatile (left, FALSE))
7514 MOVA (aopGet (left, offset, FALSE, FALSE));
7518 else if (IS_AOP_PREG (left))
7520 MOVA (aopGet (left, offset, FALSE, TRUE));
7521 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7522 aopPut (result, "a", offset);
7526 emitcode ("xrl", "%s,%s",
7527 aopGet (left, offset, FALSE, TRUE),
7528 aopGet (right, offset, FALSE, FALSE));
7533 if (AOP_TYPE (left) == AOP_ACC)
7536 emitcode("mov", "a,b");
7537 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7539 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7541 MOVB (aopGet (left, offset, FALSE, FALSE));
7542 MOVA (aopGet (right, offset, FALSE, FALSE));
7543 emitcode ("xrl", "a,b");
7544 aopPut (result, "a", offset);
7546 else if (aopGetUsesAcc (left, offset))
7548 MOVA (aopGet (left, offset, FALSE, FALSE));
7549 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7550 aopPut (result, "a", offset);
7554 MOVA (aopGet (right, offset, FALSE, FALSE));
7555 if (IS_AOP_PREG (left))
7557 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7558 aopPut (result, "a", offset);
7561 emitcode ("xrl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7568 // left & result in different registers
7569 if (AOP_TYPE (result) == AOP_CRY)
7572 // if(size), result in bit
7573 // if(!size && ifx), conditional oper: if(left ^ right)
7574 symbol *tlbl = newiTempLabel (NULL);
7575 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7578 emitcode ("setb", "c");
7581 if ((AOP_TYPE (right) == AOP_LIT) &&
7582 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7584 MOVA (aopGet (left, offset, FALSE, FALSE));
7586 else if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7587 && AOP_TYPE(left)==AOP_ACC)
7590 emitcode("mov", "a,b");
7591 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7593 else if (AOP_TYPE(left)==AOP_ACC)
7597 bool pushedB = pushB ();
7598 emitcode("mov", "b,a");
7599 MOVA (aopGet (right, offset, FALSE, FALSE));
7600 emitcode("xrl", "a,b");
7605 MOVA (aopGet (right, offset, FALSE, FALSE));
7606 emitcode("xrl", "a,b");
7609 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7611 MOVB (aopGet (left, offset, FALSE, FALSE));
7612 MOVA (aopGet (right, offset, FALSE, FALSE));
7613 emitcode ("xrl", "a,b");
7615 else if (aopGetUsesAcc (left, offset))
7617 MOVA (aopGet (left, offset, FALSE, FALSE));
7618 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7622 MOVA (aopGet (right, offset, FALSE, FALSE));
7623 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7626 emitcode ("jnz", "%05d$", tlbl->key + 100);
7636 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7640 for (; (size--); offset++)
7643 // result = left ^ right
7644 if (AOP_TYPE (right) == AOP_LIT)
7646 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7650 aopGet (left, offset, FALSE, FALSE),
7655 // faster than result <- left, xrl result,right
7656 // and better if result is SFR
7657 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7658 && AOP_TYPE(left)==AOP_ACC)
7661 emitcode("mov", "a,b");
7662 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7664 else if (AOP_TYPE(left)==AOP_ACC)
7668 bool pushedB = pushB ();
7669 emitcode("mov", "b,a");
7670 MOVA (aopGet (right, offset, FALSE, FALSE));
7671 emitcode("xrl", "a,b");
7676 MOVA (aopGet (right, offset, FALSE, FALSE));
7677 emitcode("xrl", "a,b");
7680 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7682 MOVB (aopGet (left, offset, FALSE, FALSE));
7683 MOVA (aopGet (right, offset, FALSE, FALSE));
7684 emitcode ("xrl", "a,b");
7686 else if (aopGetUsesAcc (left, offset))
7688 MOVA (aopGet (left, offset, FALSE, FALSE));
7689 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7693 MOVA (aopGet (right, offset, FALSE, FALSE));
7694 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7696 aopPut (result, "a", offset);
7702 freeAsmop (result, NULL, ic, TRUE);
7703 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7704 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7707 /*-----------------------------------------------------------------*/
7708 /* genInline - write the inline code out */
7709 /*-----------------------------------------------------------------*/
7711 genInline (iCode * ic)
7713 char *buffer, *bp, *bp1;
7714 bool inComment = FALSE;
7716 D (emitcode (";", "genInline"));
7718 _G.inLine += (!options.asmpeep);
7720 buffer = bp = bp1 = Safe_strdup (IC_INLINE (ic));
7722 /* emit each line as a code */
7740 /* Add \n for labels, not dirs such as c:\mydir */
7741 if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
7759 _G.inLine -= (!options.asmpeep);
7762 /*-----------------------------------------------------------------*/
7763 /* genRRC - rotate right with carry */
7764 /*-----------------------------------------------------------------*/
7768 operand *left, *result;
7772 D (emitcode (";", "genRRC"));
7774 /* rotate right with carry */
7775 left = IC_LEFT (ic);
7776 result = IC_RESULT (ic);
7777 aopOp (left, ic, FALSE);
7778 aopOp (result, ic, FALSE);
7780 /* move it to the result */
7781 size = AOP_SIZE (result);
7783 if (size == 1) { /* special case for 1 byte */
7784 l = aopGet (left, offset, FALSE, FALSE);
7786 emitcode ("rr", "a");
7789 /* no need to clear carry, bit7 will be written later */
7792 l = aopGet (left, offset, FALSE, FALSE);
7794 emitcode ("rrc", "a");
7795 if (AOP_SIZE (result) > 1)
7796 aopPut (result, "a", offset--);
7798 /* now we need to put the carry into the
7799 highest order byte of the result */
7800 if (AOP_SIZE (result) > 1)
7802 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7805 emitcode ("mov", "acc.7,c");
7807 aopPut (result, "a", AOP_SIZE (result) - 1);
7808 freeAsmop (result, NULL, ic, TRUE);
7809 freeAsmop (left, NULL, ic, TRUE);
7812 /*-----------------------------------------------------------------*/
7813 /* genRLC - generate code for rotate left with carry */
7814 /*-----------------------------------------------------------------*/
7818 operand *left, *result;
7822 D (emitcode (";", "genRLC"));
7824 /* rotate right with carry */
7825 left = IC_LEFT (ic);
7826 result = IC_RESULT (ic);
7827 aopOp (left, ic, FALSE);
7828 aopOp (result, ic, FALSE);
7830 /* move it to the result */
7831 size = AOP_SIZE (result);
7835 l = aopGet (left, offset, FALSE, FALSE);
7837 if (size == 0) { /* special case for 1 byte */
7841 emitcode("rlc","a"); /* bit0 will be written later */
7842 if (AOP_SIZE (result) > 1)
7844 aopPut (result, "a", offset++);
7849 l = aopGet (left, offset, FALSE, FALSE);
7851 emitcode ("rlc", "a");
7852 if (AOP_SIZE (result) > 1)
7853 aopPut (result, "a", offset++);
7856 /* now we need to put the carry into the
7857 highest order byte of the result */
7858 if (AOP_SIZE (result) > 1)
7860 l = aopGet (result, 0, FALSE, FALSE);
7863 emitcode ("mov", "acc.0,c");
7865 aopPut (result, "a", 0);
7866 freeAsmop (result, NULL, ic, TRUE);
7867 freeAsmop (left, NULL, ic, TRUE);
7870 /*-----------------------------------------------------------------*/
7871 /* genGetHbit - generates code get highest order bit */
7872 /*-----------------------------------------------------------------*/
7874 genGetHbit (iCode * ic)
7876 operand *left, *result;
7878 D (emitcode (";", "genGetHbit"));
7880 left = IC_LEFT (ic);
7881 result = IC_RESULT (ic);
7882 aopOp (left, ic, FALSE);
7883 aopOp (result, ic, FALSE);
7885 /* get the highest order byte into a */
7886 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7887 if (AOP_TYPE (result) == AOP_CRY)
7889 emitcode ("rlc", "a");
7894 emitcode ("rl", "a");
7895 emitcode ("anl", "a,#0x01");
7899 freeAsmop (result, NULL, ic, TRUE);
7900 freeAsmop (left, NULL, ic, TRUE);
7903 /*-----------------------------------------------------------------*/
7904 /* genGetAbit - generates code get a single bit */
7905 /*-----------------------------------------------------------------*/
7907 genGetAbit (iCode * ic)
7909 operand *left, *right, *result;
7912 D (emitcode (";", "genGetAbit"));
7914 left = IC_LEFT (ic);
7915 right = IC_RIGHT (ic);
7916 result = IC_RESULT (ic);
7917 aopOp (left, ic, FALSE);
7918 aopOp (right, ic, FALSE);
7919 aopOp (result, ic, FALSE);
7921 shCount = (int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7923 /* get the needed byte into a */
7924 MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7926 if (AOP_TYPE (result) == AOP_CRY)
7929 emitcode ("rlc", "a");
7930 else if ((shCount) == 0)
7931 emitcode ("rrc", "a");
7933 emitcode ("mov", "c,acc[%d]", shCount);
7941 emitcode ("rr", "a");
7944 emitcode ("rr", "a");
7947 emitcode ("anl", "a,#0x01");
7951 emitcode ("mov", "c,acc[%d]", shCount);
7952 emitcode ("clr", "a");
7953 emitcode ("rlc", "a");
7956 emitcode ("swap", "a");
7957 emitcode ("anl", "a,#0x01");
7960 emitcode ("rl", "a");
7963 emitcode ("rl", "a");
7964 emitcode ("anl", "a,#0x01");
7970 freeAsmop (result, NULL, ic, TRUE);
7971 freeAsmop (right, NULL, ic, TRUE);
7972 freeAsmop (left, NULL, ic, TRUE);
7975 /*-----------------------------------------------------------------*/
7976 /* genGetByte - generates code get a single byte */
7977 /*-----------------------------------------------------------------*/
7979 genGetByte (iCode * ic)
7981 operand *left, *right, *result;
7984 D (emitcode (";", "genGetByte"));
7986 left = IC_LEFT (ic);
7987 right = IC_RIGHT (ic);
7988 result = IC_RESULT (ic);
7989 aopOp (left, ic, FALSE);
7990 aopOp (right, ic, FALSE);
7991 aopOp (result, ic, FALSE);
7993 offset = (int) ulFromVal (AOP (right)->aopu.aop_lit) / 8;
7995 aopGet (left, offset, FALSE, FALSE),
7998 freeAsmop (result, NULL, ic, TRUE);
7999 freeAsmop (right, NULL, ic, TRUE);
8000 freeAsmop (left, NULL, ic, TRUE);
8003 /*-----------------------------------------------------------------*/
8004 /* genGetWord - generates code get two bytes */
8005 /*-----------------------------------------------------------------*/
8007 genGetWord (iCode * ic)
8009 operand *left, *right, *result;
8012 D (emitcode (";", "genGetWord"));
8014 left = IC_LEFT (ic);
8015 right = IC_RIGHT (ic);
8016 result = IC_RESULT (ic);
8017 aopOp (left, ic, FALSE);
8018 aopOp (right, ic, FALSE);
8019 aopOp (result, ic, FALSE);
8021 offset = (int) ulFromVal (AOP (right)->aopu.aop_lit) / 8;
8023 aopGet (left, offset, FALSE, FALSE),
8026 aopGet (left, offset+1, FALSE, FALSE),
8029 freeAsmop (result, NULL, ic, TRUE);
8030 freeAsmop (right, NULL, ic, TRUE);
8031 freeAsmop (left, NULL, ic, TRUE);
8034 /*-----------------------------------------------------------------*/
8035 /* genSwap - generates code to swap nibbles or bytes */
8036 /*-----------------------------------------------------------------*/
8038 genSwap (iCode * ic)
8040 operand *left, *result;
8042 D(emitcode (";", "genSwap"));
8044 left = IC_LEFT (ic);
8045 result = IC_RESULT (ic);
8046 aopOp (left, ic, FALSE);
8047 aopOp (result, ic, FALSE);
8049 switch (AOP_SIZE (left))
8051 case 1: /* swap nibbles in byte */
8052 MOVA (aopGet (left, 0, FALSE, FALSE));
8053 emitcode ("swap", "a");
8054 aopPut (result, "a", 0);
8056 case 2: /* swap bytes in word */
8057 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
8059 MOVA (aopGet (left, 0, FALSE, FALSE));
8060 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8061 aopPut (result, "a", 1);
8063 else if (operandsEqu (left, result))
8066 bool pushedB = FALSE, leftInB = FALSE;
8068 MOVA (aopGet (left, 0, FALSE, FALSE));
8069 if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
8072 emitcode ("mov", "b,a");
8076 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8077 aopPut (result, reg, 1);
8084 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8085 aopPut (result, aopGet (left, 0, FALSE, FALSE), 1);
8089 wassertl(FALSE, "unsupported SWAP operand size");
8092 freeAsmop (result, NULL, ic, TRUE);
8093 freeAsmop (left, NULL, ic, TRUE);
8096 /*-----------------------------------------------------------------*/
8097 /* AccRol - rotate left accumulator by known count */
8098 /*-----------------------------------------------------------------*/
8100 AccRol (int shCount)
8102 shCount &= 0x0007; // shCount : 0..7
8109 emitcode ("rl", "a");
8112 emitcode ("rl", "a");
8113 emitcode ("rl", "a");
8116 emitcode ("swap", "a");
8117 emitcode ("rr", "a");
8120 emitcode ("swap", "a");
8123 emitcode ("swap", "a");
8124 emitcode ("rl", "a");
8127 emitcode ("rr", "a");
8128 emitcode ("rr", "a");
8131 emitcode ("rr", "a");
8136 /*-----------------------------------------------------------------*/
8137 /* AccLsh - left shift accumulator by known count */
8138 /*-----------------------------------------------------------------*/
8140 AccLsh (int shCount)
8145 emitcode ("add", "a,acc");
8146 else if (shCount == 2)
8148 emitcode ("add", "a,acc");
8149 emitcode ("add", "a,acc");
8153 /* rotate left accumulator */
8155 /* and kill the lower order bits */
8156 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
8161 /*-----------------------------------------------------------------*/
8162 /* AccRsh - right shift accumulator by known count */
8163 /*-----------------------------------------------------------------*/
8165 AccRsh (int shCount)
8172 emitcode ("rrc", "a");
8176 /* rotate right accumulator */
8177 AccRol (8 - shCount);
8178 /* and kill the higher order bits */
8179 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8184 /*-----------------------------------------------------------------*/
8185 /* AccSRsh - signed right shift accumulator by known count */
8186 /*-----------------------------------------------------------------*/
8188 AccSRsh (int shCount)
8195 emitcode ("mov", "c,acc.7");
8196 emitcode ("rrc", "a");
8198 else if (shCount == 2)
8200 emitcode ("mov", "c,acc.7");
8201 emitcode ("rrc", "a");
8202 emitcode ("mov", "c,acc.7");
8203 emitcode ("rrc", "a");
8207 tlbl = newiTempLabel (NULL);
8208 /* rotate right accumulator */
8209 AccRol (8 - shCount);
8210 /* and kill the higher order bits */
8211 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8212 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8213 emitcode ("orl", "a,#0x%02x",
8214 (unsigned char) ~SRMask[shCount]);
8220 /*-----------------------------------------------------------------*/
8221 /* shiftR1Left2Result - shift right one byte from left to result */
8222 /*-----------------------------------------------------------------*/
8224 shiftR1Left2Result (operand * left, int offl,
8225 operand * result, int offr,
8226 int shCount, int sign)
8228 MOVA (aopGet (left, offl, FALSE, FALSE));
8229 /* shift right accumulator */
8234 aopPut (result, "a", offr);
8237 /*-----------------------------------------------------------------*/
8238 /* shiftL1Left2Result - shift left one byte from left to result */
8239 /*-----------------------------------------------------------------*/
8241 shiftL1Left2Result (operand * left, int offl,
8242 operand * result, int offr, int shCount)
8245 l = aopGet (left, offl, FALSE, FALSE);
8247 /* shift left accumulator */
8249 aopPut (result, "a", offr);
8252 /*-----------------------------------------------------------------*/
8253 /* movLeft2Result - move byte from left to result */
8254 /*-----------------------------------------------------------------*/
8256 movLeft2Result (operand * left, int offl,
8257 operand * result, int offr, int sign)
8260 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8262 l = aopGet (left, offl, FALSE, FALSE);
8264 if (*l == '@' && (IS_AOP_PREG (result)))
8266 emitcode ("mov", "a,%s", l);
8267 aopPut (result, "a", offr);
8273 aopPut (result, l, offr);
8277 /* MSB sign in acc.7 ! */
8278 if (getDataSize (left) == offl + 1)
8281 aopPut (result, "a", offr);
8288 /*-----------------------------------------------------------------*/
8289 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
8290 /*-----------------------------------------------------------------*/
8294 emitcode ("rrc", "a");
8295 emitcode ("xch", "a,%s", x);
8296 emitcode ("rrc", "a");
8297 emitcode ("xch", "a,%s", x);
8300 /*-----------------------------------------------------------------*/
8301 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
8302 /*-----------------------------------------------------------------*/
8306 emitcode ("xch", "a,%s", x);
8307 emitcode ("rlc", "a");
8308 emitcode ("xch", "a,%s", x);
8309 emitcode ("rlc", "a");
8312 /*-----------------------------------------------------------------*/
8313 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8314 /*-----------------------------------------------------------------*/
8318 emitcode ("xch", "a,%s", x);
8319 emitcode ("add", "a,acc");
8320 emitcode ("xch", "a,%s", x);
8321 emitcode ("rlc", "a");
8324 /*-----------------------------------------------------------------*/
8325 /* AccAXLsh - left shift a:x by known count (0..7) */
8326 /*-----------------------------------------------------------------*/
8328 AccAXLsh (char *x, int shCount)
8343 case 5: // AAAAABBB:CCCCCDDD
8345 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8347 emitcode ("anl", "a,#0x%02x",
8348 SLMask[shCount]); // BBB00000:CCCCCDDD
8350 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8352 AccRol (shCount); // DDDCCCCC:BBB00000
8354 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8356 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8358 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8360 emitcode ("anl", "a,#0x%02x",
8361 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8363 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8365 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8368 case 6: // AAAAAABB:CCCCCCDD
8369 emitcode ("anl", "a,#0x%02x",
8370 SRMask[shCount]); // 000000BB:CCCCCCDD
8371 emitcode ("mov", "c,acc.0"); // c = B
8372 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8374 AccAXRrl1 (x); // BCCCCCCD:D000000B
8375 AccAXRrl1 (x); // BBCCCCCC:DD000000
8377 emitcode("rrc","a");
8378 emitcode("xch","a,%s", x);
8379 emitcode("rrc","a");
8380 emitcode("mov","c,acc.0"); //<< get correct bit
8381 emitcode("xch","a,%s", x);
8383 emitcode("rrc","a");
8384 emitcode("xch","a,%s", x);
8385 emitcode("rrc","a");
8386 emitcode("xch","a,%s", x);
8389 case 7: // a:x <<= 7
8391 emitcode ("anl", "a,#0x%02x",
8392 SRMask[shCount]); // 0000000B:CCCCCCCD
8394 emitcode ("mov", "c,acc.0"); // c = B
8396 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
8398 AccAXRrl1 (x); // BCCCCCCC:D0000000
8406 /*-----------------------------------------------------------------*/
8407 /* AccAXRsh - right shift a:x known count (0..7) */
8408 /*-----------------------------------------------------------------*/
8410 AccAXRsh (char *x, int shCount)
8418 AccAXRrl1 (x); // 0->a:x
8423 AccAXRrl1 (x); // 0->a:x
8426 AccAXRrl1 (x); // 0->a:x
8431 case 5: // AAAAABBB:CCCCCDDD = a:x
8433 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8435 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8437 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8439 emitcode ("anl", "a,#0x%02x",
8440 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8442 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8444 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8446 emitcode ("anl", "a,#0x%02x",
8447 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8449 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8451 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8453 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8456 case 6: // AABBBBBB:CCDDDDDD
8458 emitcode ("mov", "c,acc.7");
8459 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8461 emitcode ("mov", "c,acc.7");
8462 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8464 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8466 emitcode ("anl", "a,#0x%02x",
8467 SRMask[shCount]); // 000000AA:BBBBBBCC
8470 case 7: // ABBBBBBB:CDDDDDDD
8472 emitcode ("mov", "c,acc.7"); // c = A
8474 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8476 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8478 emitcode ("anl", "a,#0x%02x",
8479 SRMask[shCount]); // 0000000A:BBBBBBBC
8487 /*-----------------------------------------------------------------*/
8488 /* AccAXRshS - right shift signed a:x known count (0..7) */
8489 /*-----------------------------------------------------------------*/
8491 AccAXRshS (char *x, int shCount)
8499 emitcode ("mov", "c,acc.7");
8500 AccAXRrl1 (x); // s->a:x
8504 emitcode ("mov", "c,acc.7");
8505 AccAXRrl1 (x); // s->a:x
8507 emitcode ("mov", "c,acc.7");
8508 AccAXRrl1 (x); // s->a:x
8513 case 5: // AAAAABBB:CCCCCDDD = a:x
8515 tlbl = newiTempLabel (NULL);
8516 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8518 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8520 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8522 emitcode ("anl", "a,#0x%02x",
8523 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8525 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8527 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8529 emitcode ("anl", "a,#0x%02x",
8530 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8532 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8534 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8536 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8538 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8539 emitcode ("orl", "a,#0x%02x",
8540 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8543 break; // SSSSAAAA:BBBCCCCC
8545 case 6: // AABBBBBB:CCDDDDDD
8547 tlbl = newiTempLabel (NULL);
8548 emitcode ("mov", "c,acc.7");
8549 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8551 emitcode ("mov", "c,acc.7");
8552 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8554 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8556 emitcode ("anl", "a,#0x%02x",
8557 SRMask[shCount]); // 000000AA:BBBBBBCC
8559 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8560 emitcode ("orl", "a,#0x%02x",
8561 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8565 case 7: // ABBBBBBB:CDDDDDDD
8567 tlbl = newiTempLabel (NULL);
8568 emitcode ("mov", "c,acc.7"); // c = A
8570 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8572 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8574 emitcode ("anl", "a,#0x%02x",
8575 SRMask[shCount]); // 0000000A:BBBBBBBC
8577 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8578 emitcode ("orl", "a,#0x%02x",
8579 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8588 /*-----------------------------------------------------------------*/
8589 /* shiftL2Left2Result - shift left two bytes from left to result */
8590 /*-----------------------------------------------------------------*/
8592 shiftL2Left2Result (operand * left, int offl,
8593 operand * result, int offr, int shCount)
8596 bool pushedB = FALSE;
8599 if (sameRegs (AOP (result), AOP (left)) &&
8600 ((offl + MSB16) == offr))
8602 /* don't crash result[offr] */
8603 MOVA (aopGet (left, offl, FALSE, FALSE));
8604 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8605 usedB = !strncmp(x, "b", 1);
8607 else if (aopGetUsesAcc (result, offr))
8609 movLeft2Result (left, offl, result, offr, 0);
8612 emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8613 MOVA (aopGet (result, offr, FALSE, FALSE));
8614 emitcode ("xch", "a,b");
8619 movLeft2Result (left, offl, result, offr, 0);
8620 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8621 x = aopGet (result, offr, FALSE, FALSE);
8623 /* ax << shCount (x = lsb(result)) */
8624 AccAXLsh (x, shCount);
8627 emitcode ("xch", "a,b");
8628 aopPut (result, "a", offr);
8629 aopPut (result, "b", offr + MSB16);
8634 aopPut (result, "a", offr + MSB16);
8639 /*-----------------------------------------------------------------*/
8640 /* shiftR2Left2Result - shift right two bytes from left to result */
8641 /*-----------------------------------------------------------------*/
8643 shiftR2Left2Result (operand * left, int offl,
8644 operand * result, int offr,
8645 int shCount, int sign)
8648 bool pushedB = FALSE;
8651 if (sameRegs (AOP (result), AOP (left)) &&
8652 ((offl + MSB16) == offr))
8654 /* don't crash result[offr] */
8655 MOVA (aopGet (left, offl, FALSE, FALSE));
8656 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8657 usedB = !strncmp(x, "b", 1);
8659 else if (aopGetUsesAcc (result, offr))
8661 movLeft2Result (left, offl, result, offr, 0);
8664 emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8665 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8670 movLeft2Result (left, offl, result, offr, 0);
8671 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8672 x = aopGet (result, offr, FALSE, FALSE);
8674 /* a:x >> shCount (x = lsb(result)) */
8676 AccAXRshS (x, shCount);
8678 AccAXRsh (x, shCount);
8681 emitcode ("xch", "a,b");
8682 aopPut (result, "a", offr);
8683 emitcode ("xch", "a,b");
8686 if (getDataSize (result) > 1)
8687 aopPut (result, "a", offr + MSB16);
8690 /*-----------------------------------------------------------------*/
8691 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8692 /*-----------------------------------------------------------------*/
8694 shiftLLeftOrResult (operand * left, int offl,
8695 operand * result, int offr, int shCount)
8697 MOVA (aopGet (left, offl, FALSE, FALSE));
8698 /* shift left accumulator */
8700 /* or with result */
8701 if (aopGetUsesAcc (result, offr))
8703 emitcode ("xch", "a,b");
8704 MOVA (aopGet (result, offr, FALSE, FALSE));
8705 emitcode ("orl", "a,b");
8709 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8711 /* back to result */
8712 aopPut (result, "a", offr);
8715 /*-----------------------------------------------------------------*/
8716 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8717 /*-----------------------------------------------------------------*/
8719 shiftRLeftOrResult (operand * left, int offl,
8720 operand * result, int offr, int shCount)
8722 MOVA (aopGet (left, offl, FALSE, FALSE));
8723 /* shift right accumulator */
8725 /* or with result */
8726 if (aopGetUsesAcc(result, offr))
8728 emitcode ("xch", "a,b");
8729 MOVA (aopGet (result, offr, FALSE, FALSE));
8730 emitcode ("orl", "a,b");
8734 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8736 /* back to result */
8737 aopPut (result, "a", offr);
8740 /*-----------------------------------------------------------------*/
8741 /* genlshOne - left shift a one byte quantity by known count */
8742 /*-----------------------------------------------------------------*/
8744 genlshOne (operand * result, operand * left, int shCount)
8746 D (emitcode (";", "genlshOne"));
8748 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8751 /*-----------------------------------------------------------------*/
8752 /* genlshTwo - left shift two bytes by known amount != 0 */
8753 /*-----------------------------------------------------------------*/
8755 genlshTwo (operand * result, operand * left, int shCount)
8759 D (emitcode (";", "genlshTwo"));
8761 size = getDataSize (result);
8763 /* if shCount >= 8 */
8771 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8773 movLeft2Result (left, LSB, result, MSB16, 0);
8775 aopPut (result, zero, LSB);
8778 /* 1 <= shCount <= 7 */
8782 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8784 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8788 /*-----------------------------------------------------------------*/
8789 /* shiftLLong - shift left one long from left to result */
8790 /* offl = LSB or MSB16 */
8791 /*-----------------------------------------------------------------*/
8793 shiftLLong (operand * left, operand * result, int offr)
8796 int size = AOP_SIZE (result);
8798 if (size >= LSB + offr)
8800 l = aopGet (left, LSB, FALSE, FALSE);
8802 emitcode ("add", "a,acc");
8803 if (sameRegs (AOP (left), AOP (result)) &&
8804 size >= MSB16 + offr && offr != LSB)
8805 xch_a_aopGet (left, LSB + offr, FALSE, FALSE);
8807 aopPut (result, "a", LSB + offr);
8810 if (size >= MSB16 + offr)
8812 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8814 l = aopGet (left, MSB16, FALSE, FALSE);
8817 emitcode ("rlc", "a");
8818 if (sameRegs (AOP (left), AOP (result)) &&
8819 size >= MSB24 + offr && offr != LSB)
8820 xch_a_aopGet (left, MSB16 + offr, FALSE, FALSE);
8822 aopPut (result, "a", MSB16 + offr);
8825 if (size >= MSB24 + offr)
8827 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8829 l = aopGet (left, MSB24, FALSE, FALSE);
8832 emitcode ("rlc", "a");
8833 if (sameRegs (AOP (left), AOP (result)) &&
8834 size >= MSB32 + offr && offr != LSB)
8835 xch_a_aopGet (left, MSB24 + offr, FALSE, FALSE);
8837 aopPut (result, "a", MSB24 + offr);
8840 if (size > MSB32 + offr)
8842 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8844 l = aopGet (left, MSB32, FALSE, FALSE);
8847 emitcode ("rlc", "a");
8848 aopPut (result, "a", MSB32 + offr);
8851 aopPut (result, zero, LSB);
8854 /*-----------------------------------------------------------------*/
8855 /* genlshFour - shift four byte by a known amount != 0 */
8856 /*-----------------------------------------------------------------*/
8858 genlshFour (operand * result, operand * left, int shCount)
8862 D (emitcode (";", "genlshFour"));
8864 size = AOP_SIZE (result);
8866 /* if shifting more that 3 bytes */
8871 /* lowest order of left goes to the highest
8872 order of the destination */
8873 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8875 movLeft2Result (left, LSB, result, MSB32, 0);
8876 aopPut (result, zero, LSB);
8877 aopPut (result, zero, MSB16);
8878 aopPut (result, zero, MSB24);
8882 /* more than two bytes */
8883 else if (shCount >= 16)
8885 /* lower order two bytes goes to higher order two bytes */
8887 /* if some more remaining */
8889 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8892 movLeft2Result (left, MSB16, result, MSB32, 0);
8893 movLeft2Result (left, LSB, result, MSB24, 0);
8895 aopPut (result, zero, MSB16);
8896 aopPut (result, zero, LSB);
8900 /* if more than 1 byte */
8901 else if (shCount >= 8)
8903 /* lower order three bytes goes to higher order three bytes */
8908 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8910 movLeft2Result (left, LSB, result, MSB16, 0);
8916 movLeft2Result (left, MSB24, result, MSB32, 0);
8917 movLeft2Result (left, MSB16, result, MSB24, 0);
8918 movLeft2Result (left, LSB, result, MSB16, 0);
8919 aopPut (result, zero, LSB);
8921 else if (shCount == 1)
8922 shiftLLong (left, result, MSB16);
8925 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8926 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8927 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8928 aopPut (result, zero, LSB);
8933 /* 1 <= shCount <= 7 */
8934 else if (shCount <= 2)
8936 shiftLLong (left, result, LSB);
8938 shiftLLong (result, result, LSB);
8940 /* 3 <= shCount <= 7, optimize */
8943 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8944 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8945 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8949 /*-----------------------------------------------------------------*/
8950 /* genLeftShiftLiteral - left shifting by known count */
8951 /*-----------------------------------------------------------------*/
8953 genLeftShiftLiteral (operand * left,
8958 int shCount = (int) ulFromVal (AOP (right)->aopu.aop_lit);
8961 D (emitcode (";", "genLeftShiftLiteral"));
8963 freeAsmop (right, NULL, ic, TRUE);
8965 aopOp (left, ic, FALSE);
8966 aopOp (result, ic, FALSE);
8968 size = getSize (operandType (result));
8971 emitcode ("; shift left ", "result %d, left %d", size,
8975 /* I suppose that the left size >= result size */
8980 movLeft2Result (left, size, result, size, 0);
8983 else if (shCount >= (size * 8))
8987 aopPut (result, zero, size);
8995 genlshOne (result, left, shCount);
8999 genlshTwo (result, left, shCount);
9003 genlshFour (result, left, shCount);
9006 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9007 "*** ack! mystery literal shift!\n");
9011 freeAsmop (result, NULL, ic, TRUE);
9012 freeAsmop (left, NULL, ic, TRUE);
9015 /*-----------------------------------------------------------------*/
9016 /* genLeftShift - generates code for left shifting */
9017 /*-----------------------------------------------------------------*/
9019 genLeftShift (iCode * ic)
9021 operand *left, *right, *result;
9024 symbol *tlbl, *tlbl1;
9027 D (emitcode (";", "genLeftShift"));
9029 right = IC_RIGHT (ic);
9030 left = IC_LEFT (ic);
9031 result = IC_RESULT (ic);
9033 aopOp (right, ic, FALSE);
9035 /* if the shift count is known then do it
9036 as efficiently as possible */
9037 if (AOP_TYPE (right) == AOP_LIT)
9039 genLeftShiftLiteral (left, right, result, ic);
9043 /* shift count is unknown then we have to form
9044 a loop get the loop count in B : Note: we take
9045 only the lower order byte since shifting
9046 more that 32 bits make no sense anyway, ( the
9047 largest size of an object can be only 32 bits ) */
9050 MOVB (aopGet (right, 0, FALSE, FALSE));
9051 emitcode ("inc", "b");
9052 freeAsmop (right, NULL, ic, TRUE);
9053 aopOp (left, ic, FALSE);
9054 aopOp (result, ic, FALSE);
9056 /* now move the left to the result if they are not the same */
9057 if (!sameRegs (AOP (left), AOP (result)) &&
9058 AOP_SIZE (result) > 1)
9061 size = AOP_SIZE (result);
9065 l = aopGet (left, offset, FALSE, TRUE);
9066 if (*l == '@' && (IS_AOP_PREG (result)))
9069 emitcode ("mov", "a,%s", l);
9070 aopPut (result, "a", offset);
9073 aopPut (result, l, offset);
9078 tlbl = newiTempLabel (NULL);
9079 size = AOP_SIZE (result);
9081 tlbl1 = newiTempLabel (NULL);
9083 /* if it is only one byte then */
9086 symbol *tlbl1 = newiTempLabel (NULL);
9088 l = aopGet (left, 0, FALSE, FALSE);
9090 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9092 emitcode ("add", "a,acc");
9094 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9096 aopPut (result, "a", 0);
9100 reAdjustPreg (AOP (result));
9102 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9104 l = aopGet (result, offset, FALSE, FALSE);
9106 emitcode ("add", "a,acc");
9107 aopPut (result, "a", offset++);
9110 l = aopGet (result, offset, FALSE, FALSE);
9112 emitcode ("rlc", "a");
9113 aopPut (result, "a", offset++);
9115 reAdjustPreg (AOP (result));
9118 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9121 freeAsmop (result, NULL, ic, TRUE);
9122 freeAsmop (left, NULL, ic, TRUE);
9125 /*-----------------------------------------------------------------*/
9126 /* genrshOne - right shift a one byte quantity by known count */
9127 /*-----------------------------------------------------------------*/
9129 genrshOne (operand * result, operand * left,
9130 int shCount, int sign)
9132 D (emitcode (";", "genrshOne"));
9134 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9137 /*-----------------------------------------------------------------*/
9138 /* genrshTwo - right shift two bytes by known amount != 0 */
9139 /*-----------------------------------------------------------------*/
9141 genrshTwo (operand * result, operand * left,
9142 int shCount, int sign)
9144 D (emitcode (";", "genrshTwo"));
9146 /* if shCount >= 8 */
9151 shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
9153 movLeft2Result (left, MSB16, result, LSB, sign);
9154 addSign (result, MSB16, sign);
9157 /* 1 <= shCount <= 7 */
9159 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9162 /*-----------------------------------------------------------------*/
9163 /* shiftRLong - shift right one long from left to result */
9164 /* offl = LSB or MSB16 */
9165 /*-----------------------------------------------------------------*/
9167 shiftRLong (operand * left, int offl,
9168 operand * result, int sign)
9170 bool overlapping = regsInCommon (left, result) || operandsEqu(left, result);
9172 if (overlapping && offl>1)
9174 // we are in big trouble, but this shouldn't happen
9175 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9178 MOVA (aopGet (left, MSB32, FALSE, FALSE));
9185 emitcode ("rlc", "a");
9186 emitcode ("subb", "a,acc");
9187 if (overlapping && sameByte (AOP (left), MSB32, AOP (result), MSB32))
9189 xch_a_aopGet (left, MSB32, FALSE, FALSE);
9193 aopPut (result, "a", MSB32);
9194 MOVA (aopGet (left, MSB32, FALSE, FALSE));
9199 if (aopPutUsesAcc (result, zero, MSB32))
9201 emitcode("xch", "a,b");
9202 aopPut (result, zero, MSB32);
9203 emitcode("xch", "a,b");
9207 aopPut (result, zero, MSB32);
9214 emitcode ("clr", "c");
9218 emitcode ("mov", "c,acc.7");
9221 emitcode ("rrc", "a");
9223 if (overlapping && offl==MSB16 &&
9224 sameByte (AOP (left), MSB24, AOP (result), MSB32-offl))
9226 xch_a_aopGet (left, MSB24, FALSE, FALSE);
9230 aopPut (result, "a", MSB32 - offl);
9231 MOVA (aopGet (left, MSB24, FALSE, FALSE));
9234 emitcode ("rrc", "a");
9235 if (overlapping && offl==MSB16 &&
9236 sameByte (AOP (left), MSB16, AOP (result), MSB24-offl))
9238 xch_a_aopGet (left, MSB16, FALSE, FALSE);
9242 aopPut (result, "a", MSB24 - offl);
9243 MOVA (aopGet (left, MSB16, FALSE, FALSE));
9246 emitcode ("rrc", "a");
9249 aopPut (result, "a", MSB16 - offl);
9254 sameByte (AOP (left), LSB, AOP (result), MSB16-offl))
9256 xch_a_aopGet (left, LSB, FALSE, FALSE);
9260 aopPut (result, "a", MSB16 - offl);
9261 MOVA (aopGet (left, LSB, FALSE, FALSE));
9263 emitcode ("rrc", "a");
9264 aopPut (result, "a", LSB);
9268 /*-----------------------------------------------------------------*/
9269 /* genrshFour - shift four byte by a known amount != 0 */
9270 /*-----------------------------------------------------------------*/
9272 genrshFour (operand * result, operand * left,
9273 int shCount, int sign)
9275 D (emitcode (";", "genrshFour"));
9277 /* if shifting more that 3 bytes */
9282 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9284 movLeft2Result (left, MSB32, result, LSB, sign);
9285 addSign (result, MSB16, sign);
9287 else if (shCount >= 16)
9291 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9294 movLeft2Result (left, MSB24, result, LSB, 0);
9295 movLeft2Result (left, MSB32, result, MSB16, sign);
9297 addSign (result, MSB24, sign);
9299 else if (shCount >= 8)
9304 shiftRLong (left, MSB16, result, sign);
9306 else if (shCount == 0)
9308 movLeft2Result (left, MSB16, result, LSB, 0);
9309 movLeft2Result (left, MSB24, result, MSB16, 0);
9310 movLeft2Result (left, MSB32, result, MSB24, sign);
9311 addSign (result, MSB32, sign);
9315 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9316 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9317 /* the last shift is signed */
9318 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9319 addSign (result, MSB32, sign);
9324 /* 1 <= shCount <= 7 */
9327 shiftRLong (left, LSB, result, sign);
9329 shiftRLong (result, LSB, result, sign);
9333 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9334 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9335 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9340 /*-----------------------------------------------------------------*/
9341 /* genRightShiftLiteral - right shifting by known count */
9342 /*-----------------------------------------------------------------*/
9344 genRightShiftLiteral (operand * left,
9350 int shCount = (int) ulFromVal (AOP (right)->aopu.aop_lit);
9353 D (emitcode (";", "genRightShiftLiteral"));
9355 freeAsmop (right, NULL, ic, TRUE);
9357 aopOp (left, ic, FALSE);
9358 aopOp (result, ic, FALSE);
9361 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9365 size = getDataSize (left);
9366 /* test the LEFT size !!! */
9368 /* I suppose that the left size >= result size */
9371 size = getDataSize (result);
9373 movLeft2Result (left, size, result, size, 0);
9376 else if (shCount >= (size * 8))
9380 /* get sign in acc.7 */
9381 MOVA (aopGet (left, size - 1, FALSE, FALSE));
9383 addSign (result, LSB, sign);
9390 genrshOne (result, left, shCount, sign);
9394 genrshTwo (result, left, shCount, sign);
9398 genrshFour (result, left, shCount, sign);
9404 freeAsmop (result, NULL, ic, TRUE);
9405 freeAsmop (left, NULL, ic, TRUE);
9408 /*-----------------------------------------------------------------*/
9409 /* genSignedRightShift - right shift of signed number */
9410 /*-----------------------------------------------------------------*/
9412 genSignedRightShift (iCode * ic)
9414 operand *right, *left, *result;
9417 symbol *tlbl, *tlbl1;
9420 D (emitcode (";", "genSignedRightShift"));
9422 /* we do it the hard way put the shift count in b
9423 and loop thru preserving the sign */
9425 right = IC_RIGHT (ic);
9426 left = IC_LEFT (ic);
9427 result = IC_RESULT (ic);
9429 aopOp (right, ic, FALSE);
9432 if (AOP_TYPE (right) == AOP_LIT)
9434 genRightShiftLiteral (left, right, result, ic, 1);
9437 /* shift count is unknown then we have to form
9438 a loop get the loop count in B : Note: we take
9439 only the lower order byte since shifting
9440 more that 32 bits make no sense anyway, ( the
9441 largest size of an object can be only 32 bits ) */
9444 MOVB (aopGet (right, 0, FALSE, FALSE));
9445 emitcode ("inc", "b");
9446 freeAsmop (right, NULL, ic, TRUE);
9447 aopOp (left, ic, FALSE);
9448 aopOp (result, ic, FALSE);
9450 /* now move the left to the result if they are not the
9452 if (!sameRegs (AOP (left), AOP (result)) &&
9453 AOP_SIZE (result) > 1)
9456 size = AOP_SIZE (result);
9460 l = aopGet (left, offset, FALSE, TRUE);
9461 if (*l == '@' && IS_AOP_PREG (result))
9464 emitcode ("mov", "a,%s", l);
9465 aopPut (result, "a", offset);
9468 aopPut (result, l, offset);
9473 /* mov the highest order bit to OVR */
9474 tlbl = newiTempLabel (NULL);
9475 tlbl1 = newiTempLabel (NULL);
9477 size = AOP_SIZE (result);
9479 MOVA (aopGet (left, offset, FALSE, FALSE));
9480 emitcode ("rlc", "a");
9481 emitcode ("mov", "ov,c");
9482 /* if it is only one byte then */
9485 l = aopGet (left, 0, FALSE, FALSE);
9487 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9489 emitcode ("mov", "c,ov");
9490 emitcode ("rrc", "a");
9492 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9494 aopPut (result, "a", 0);
9498 reAdjustPreg (AOP (result));
9499 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9501 emitcode ("mov", "c,ov");
9504 l = aopGet (result, offset, FALSE, FALSE);
9506 emitcode ("rrc", "a");
9507 aopPut (result, "a", offset--);
9509 reAdjustPreg (AOP (result));
9511 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9515 freeAsmop (result, NULL, ic, TRUE);
9516 freeAsmop (left, NULL, ic, TRUE);
9519 /*-----------------------------------------------------------------*/
9520 /* genRightShift - generate code for right shifting */
9521 /*-----------------------------------------------------------------*/
9523 genRightShift (iCode * ic)
9525 operand *right, *left, *result;
9529 symbol *tlbl, *tlbl1;
9532 D (emitcode (";", "genRightShift"));
9534 /* if signed then we do it the hard way preserve the
9535 sign bit moving it inwards */
9536 letype = getSpec (operandType (IC_LEFT (ic)));
9538 if (!SPEC_USIGN (letype))
9540 genSignedRightShift (ic);
9544 /* signed & unsigned types are treated the same : i.e. the
9545 signed is NOT propagated inwards : quoting from the
9546 ANSI - standard : "for E1 >> E2, is equivalent to division
9547 by 2**E2 if unsigned or if it has a non-negative value,
9548 otherwise the result is implementation defined ", MY definition
9549 is that the sign does not get propagated */
9551 right = IC_RIGHT (ic);
9552 left = IC_LEFT (ic);
9553 result = IC_RESULT (ic);
9555 aopOp (right, ic, FALSE);
9557 /* if the shift count is known then do it
9558 as efficiently as possible */
9559 if (AOP_TYPE (right) == AOP_LIT)
9561 genRightShiftLiteral (left, right, result, ic, 0);
9565 /* shift count is unknown then we have to form
9566 a loop get the loop count in B : Note: we take
9567 only the lower order byte since shifting
9568 more that 32 bits make no sense anyway, ( the
9569 largest size of an object can be only 32 bits ) */
9572 MOVB (aopGet (right, 0, FALSE, FALSE));
9573 emitcode ("inc", "b");
9574 freeAsmop (right, NULL, ic, TRUE);
9575 aopOp (left, ic, FALSE);
9576 aopOp (result, ic, FALSE);
9578 /* now move the left to the result if they are not the
9580 if (!sameRegs (AOP (left), AOP (result)) &&
9581 AOP_SIZE (result) > 1)
9583 size = AOP_SIZE (result);
9587 l = aopGet (left, offset, FALSE, TRUE);
9588 if (*l == '@' && IS_AOP_PREG (result))
9591 emitcode ("mov", "a,%s", l);
9592 aopPut (result, "a", offset);
9595 aopPut (result, l, offset);
9600 tlbl = newiTempLabel (NULL);
9601 tlbl1 = newiTempLabel (NULL);
9602 size = AOP_SIZE (result);
9605 /* if it is only one byte then */
9608 l = aopGet (left, 0, FALSE, FALSE);
9610 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9613 emitcode ("rrc", "a");
9615 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9617 aopPut (result, "a", 0);
9621 reAdjustPreg (AOP (result));
9622 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9627 l = aopGet (result, offset, FALSE, FALSE);
9629 emitcode ("rrc", "a");
9630 aopPut (result, "a", offset--);
9632 reAdjustPreg (AOP (result));
9635 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9639 freeAsmop (result, NULL, ic, TRUE);
9640 freeAsmop (left, NULL, ic, TRUE);
9643 /*-----------------------------------------------------------------*/
9644 /* emitPtrByteGet - emits code to get a byte into A through a */
9645 /* pointer register (R0, R1, or DPTR). The */
9646 /* original value of A can be preserved in B. */
9647 /*-----------------------------------------------------------------*/
9649 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9656 emitcode ("mov", "b,a");
9657 emitcode ("mov", "a,@%s", rname);
9662 emitcode ("mov", "b,a");
9663 emitcode ("movx", "a,@%s", rname);
9668 emitcode ("mov", "b,a");
9669 emitcode ("movx", "a,@dptr");
9674 emitcode ("mov", "b,a");
9675 emitcode ("clr", "a");
9676 emitcode ("movc", "a,@a+dptr");
9682 emitcode ("push", "b");
9683 emitcode ("push", "acc");
9685 emitcode ("lcall", "__gptrget");
9687 emitcode ("pop", "b");
9692 /*-----------------------------------------------------------------*/
9693 /* emitPtrByteSet - emits code to set a byte from src through a */
9694 /* pointer register (R0, R1, or DPTR). */
9695 /*-----------------------------------------------------------------*/
9697 emitPtrByteSet (char *rname, int p_type, char *src)
9706 emitcode ("mov", "@%s,a", rname);
9709 emitcode ("mov", "@%s,%s", rname, src);
9714 emitcode ("movx", "@%s,a", rname);
9719 emitcode ("movx", "@dptr,a");
9724 emitcode ("lcall", "__gptrput");
9729 /*-----------------------------------------------------------------*/
9730 /* genUnpackBits - generates code for unpacking bits */
9731 /*-----------------------------------------------------------------*/
9733 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9735 int offset = 0; /* result byte offset */
9736 int rsize; /* result size */
9737 int rlen = 0; /* remaining bitfield length */
9738 sym_link *etype; /* bitfield type information */
9739 int blen; /* bitfield length */
9740 int bstr; /* bitfield starting bit within byte */
9743 D(emitcode (";", "genUnpackBits"));
9745 etype = getSpec (operandType (result));
9746 rsize = getSize (operandType (result));
9747 blen = SPEC_BLEN (etype);
9748 bstr = SPEC_BSTR (etype);
9750 if (ifx && blen <= 8)
9752 emitPtrByteGet (rname, ptype, FALSE);
9755 SNPRINTF (buffer, sizeof(buffer),
9757 genIfxJump (ifx, buffer, NULL, NULL, NULL);
9762 emitcode ("anl", "a,#0x%02x",
9763 (((unsigned char) -1) >> (8 - blen)) << bstr);
9764 genIfxJump (ifx, "a", NULL, NULL, NULL);
9770 /* If the bitfield length is less than a byte */
9773 emitPtrByteGet (rname, ptype, FALSE);
9775 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9776 if (!SPEC_USIGN (etype))
9778 /* signed bitfield */
9779 symbol *tlbl = newiTempLabel (NULL);
9781 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9782 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9785 aopPut (result, "a", offset++);
9789 /* Bit field did not fit in a byte. Copy all
9790 but the partial byte at the end. */
9791 for (rlen=blen;rlen>=8;rlen-=8)
9793 emitPtrByteGet (rname, ptype, FALSE);
9794 aopPut (result, "a", offset++);
9796 emitcode ("inc", "%s", rname);
9799 /* Handle the partial byte at the end */
9802 emitPtrByteGet (rname, ptype, FALSE);
9803 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9804 if (!SPEC_USIGN (etype))
9806 /* signed bitfield */
9807 symbol *tlbl = newiTempLabel (NULL);
9809 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9810 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9813 aopPut (result, "a", offset++);
9821 if (SPEC_USIGN (etype))
9825 /* signed bitfield: sign extension with 0x00 or 0xff */
9826 emitcode ("rlc", "a");
9827 emitcode ("subb", "a,acc");
9833 aopPut (result, source, offset++);
9838 /*-----------------------------------------------------------------*/
9839 /* genDataPointerGet - generates code when ptr offset is known */
9840 /*-----------------------------------------------------------------*/
9842 genDataPointerGet (operand * left,
9848 int size, offset = 0;
9850 D (emitcode (";", "genDataPointerGet"));
9852 aopOp (result, ic, TRUE);
9854 /* get the string representation of the name */
9855 l = aopGet (left, 0, FALSE, TRUE);
9857 size = AOP_SIZE (result);
9862 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
9866 SNPRINTF (buffer, sizeof(buffer), "%s", l);
9868 aopPut (result, buffer, offset++);
9871 freeAsmop (result, NULL, ic, TRUE);
9872 freeAsmop (left, NULL, ic, TRUE);
9875 /*-----------------------------------------------------------------*/
9876 /* genNearPointerGet - emitcode for near pointer fetch */
9877 /*-----------------------------------------------------------------*/
9879 genNearPointerGet (operand * left,
9888 sym_link *rtype, *retype;
9889 sym_link *ltype = operandType (left);
9892 D (emitcode (";", "genNearPointerGet"));
9894 rtype = operandType (result);
9895 retype = getSpec (rtype);
9897 aopOp (left, ic, FALSE);
9899 /* if left is rematerialisable and
9900 result is not bitfield variable type and
9901 the left is pointer to data space i.e
9902 lower 128 bytes of space */
9903 if (AOP_TYPE (left) == AOP_IMMD &&
9904 !IS_BITFIELD (retype) &&
9905 DCL_TYPE (ltype) == POINTER)
9907 genDataPointerGet (left, result, ic);
9911 /* if the value is already in a pointer register
9912 then don't need anything more */
9913 if (!AOP_INPREG (AOP (left)))
9915 if (IS_AOP_PREG (left))
9917 // Aha, it is a pointer, just in disguise.
9918 rname = aopGet (left, 0, FALSE, FALSE);
9921 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9922 __FILE__, __LINE__);
9927 emitcode ("mov", "a%s,%s", rname + 1, rname);
9928 rname++; // skip the '@'.
9933 /* otherwise get a free pointer register */
9935 preg = getFreePtr (ic, &aop, FALSE);
9936 emitcode ("mov", "%s,%s",
9938 aopGet (left, 0, FALSE, TRUE));
9943 rname = aopGet (left, 0, FALSE, FALSE);
9945 //aopOp (result, ic, FALSE);
9946 aopOp (result, ic, result?TRUE:FALSE);
9948 /* if bitfield then unpack the bits */
9949 if (IS_BITFIELD (retype))
9950 genUnpackBits (result, rname, POINTER, ifx);
9953 /* we have can just get the values */
9954 int size = AOP_SIZE (result);
9959 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9962 emitcode ("mov", "a,@%s", rname);
9964 aopPut (result, "a", offset);
9968 SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
9969 aopPut (result, buffer, offset);
9973 emitcode ("inc", "%s", rname);
9977 /* now some housekeeping stuff */
9978 if (aop) /* we had to allocate for this iCode */
9980 if (pi) { /* post increment present */
9981 aopPut (left, rname, 0);
9983 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9987 /* we did not allocate which means left
9988 already in a pointer register, then
9989 if size > 0 && this could be used again
9990 we have to point it back to where it
9992 if ((AOP_SIZE (result) > 1 &&
9993 !OP_SYMBOL (left)->remat &&
9994 (OP_SYMBOL (left)->liveTo > ic->seq ||
9998 int size = AOP_SIZE (result) - 1;
10000 emitcode ("dec", "%s", rname);
10004 if (ifx && !ifx->generated)
10006 genIfxJump (ifx, "a", left, NULL, result);
10010 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
10011 freeAsmop (left, NULL, ic, TRUE);
10012 if (pi) pi->generated = 1;
10015 /*-----------------------------------------------------------------*/
10016 /* genPagedPointerGet - emitcode for paged pointer fetch */
10017 /*-----------------------------------------------------------------*/
10019 genPagedPointerGet (operand * left,
10028 sym_link *rtype, *retype;
10030 D (emitcode (";", "genPagedPointerGet"));
10032 rtype = operandType (result);
10033 retype = getSpec (rtype);
10035 aopOp (left, ic, FALSE);
10037 /* if the value is already in a pointer register
10038 then don't need anything more */
10039 if (!AOP_INPREG (AOP (left)))
10041 /* otherwise get a free pointer register */
10042 aop = newAsmop (0);
10043 preg = getFreePtr (ic, &aop, FALSE);
10044 emitcode ("mov", "%s,%s",
10046 aopGet (left, 0, FALSE, TRUE));
10047 rname = preg->name;
10050 rname = aopGet (left, 0, FALSE, FALSE);
10052 aopOp (result, ic, FALSE);
10054 /* if bitfield then unpack the bits */
10055 if (IS_BITFIELD (retype))
10056 genUnpackBits (result, rname, PPOINTER, ifx);
10059 /* we have can just get the values */
10060 int size = AOP_SIZE (result);
10066 emitcode ("movx", "a,@%s", rname);
10068 aopPut (result, "a", offset);
10073 emitcode ("inc", "%s", rname);
10077 /* now some housekeeping stuff */
10078 if (aop) /* we had to allocate for this iCode */
10081 aopPut (left, rname, 0);
10082 freeAsmop (NULL, aop, ic, TRUE);
10086 /* we did not allocate which means left
10087 already in a pointer register, then
10088 if size > 0 && this could be used again
10089 we have to point it back to where it
10091 if ((AOP_SIZE (result) > 1 &&
10092 !OP_SYMBOL (left)->remat &&
10093 (OP_SYMBOL (left)->liveTo > ic->seq ||
10097 int size = AOP_SIZE (result) - 1;
10099 emitcode ("dec", "%s", rname);
10103 if (ifx && !ifx->generated)
10105 genIfxJump (ifx, "a", left, NULL, result);
10109 freeAsmop (result, NULL, ic, TRUE);
10110 freeAsmop (left, NULL, ic, TRUE);
10111 if (pi) pi->generated = 1;
10114 /*--------------------------------------------------------------------*/
10115 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
10116 /*--------------------------------------------------------------------*/
10118 loadDptrFromOperand (operand *op, bool loadBToo)
10120 if (AOP_TYPE (op) != AOP_STR)
10122 /* if this is rematerializable */
10123 if (AOP_TYPE (op) == AOP_IMMD)
10125 emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
10128 if (AOP(op)->aopu.aop_immd.from_cast_remat)
10129 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
10132 wassertl(FALSE, "need pointerCode");
10133 emitcode (";", "mov b,???");
10134 /* genPointerGet and genPointerSet originally did different
10135 ** things for this case. Both seem wrong.
10136 ** from genPointerGet:
10137 ** emitcode ("mov", "b,#%d", pointerCode (retype));
10138 ** from genPointerSet:
10139 ** emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
10144 else if (AOP_TYPE (op) == AOP_DPTR)
10148 MOVA (aopGet (op, 0, FALSE, FALSE));
10149 emitcode ("push", "acc");
10150 MOVA (aopGet (op, 1, FALSE, FALSE));
10151 emitcode ("push", "acc");
10152 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10153 emitcode ("pop", "dph");
10154 emitcode ("pop", "dpl");
10158 MOVA (aopGet (op, 0, FALSE, FALSE));
10159 emitcode ("push", "acc");
10160 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10161 emitcode ("pop", "dpl");
10165 { /* we need to get it byte by byte */
10166 emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
10167 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10169 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10174 /*-----------------------------------------------------------------*/
10175 /* genFarPointerGet - get value from far space */
10176 /*-----------------------------------------------------------------*/
10178 genFarPointerGet (operand * left,
10179 operand * result, iCode * ic, iCode * pi, iCode * ifx)
10182 sym_link *retype = getSpec (operandType (result));
10184 D (emitcode (";", "genFarPointerGet"));
10186 aopOp (left, ic, FALSE);
10187 loadDptrFromOperand (left, FALSE);
10189 /* so dptr now contains the address */
10190 aopOp (result, ic, FALSE);
10192 /* if bit then unpack */
10193 if (IS_BITFIELD (retype))
10194 genUnpackBits (result, "dptr", FPOINTER, ifx);
10197 size = AOP_SIZE (result);
10202 emitcode ("movx", "a,@dptr");
10204 aopPut (result, "a", offset++);
10206 emitcode ("inc", "dptr");
10210 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10212 aopPut (left, "dpl", 0);
10213 aopPut (left, "dph", 1);
10217 if (ifx && !ifx->generated)
10219 genIfxJump (ifx, "a", left, NULL, result);
10222 freeAsmop (result, NULL, ic, TRUE);
10223 freeAsmop (left, NULL, ic, TRUE);
10226 /*-----------------------------------------------------------------*/
10227 /* genCodePointerGet - get value from code space */
10228 /*-----------------------------------------------------------------*/
10230 genCodePointerGet (operand * left,
10231 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10234 sym_link *retype = getSpec (operandType (result));
10236 D (emitcode (";", "genCodePointerGet"));
10238 aopOp (left, ic, FALSE);
10239 loadDptrFromOperand (left, FALSE);
10241 /* so dptr now contains the address */
10242 aopOp (result, ic, FALSE);
10244 /* if bit then unpack */
10245 if (IS_BITFIELD (retype))
10246 genUnpackBits (result, "dptr", CPOINTER, ifx);
10249 size = AOP_SIZE (result);
10254 emitcode ("clr", "a");
10255 emitcode ("movc", "a,@a+dptr");
10257 aopPut (result, "a", offset++);
10259 emitcode ("inc", "dptr");
10263 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10265 aopPut (left, "dpl", 0);
10266 aopPut (left, "dph", 1);
10270 if (ifx && !ifx->generated)
10272 genIfxJump (ifx, "a", left, NULL, result);
10275 freeAsmop (result, NULL, ic, TRUE);
10276 freeAsmop (left, NULL, ic, TRUE);
10279 /*-----------------------------------------------------------------*/
10280 /* genGenPointerGet - get value from generic pointer space */
10281 /*-----------------------------------------------------------------*/
10283 genGenPointerGet (operand * left,
10284 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10287 sym_link *retype = getSpec (operandType (result));
10289 D (emitcode (";", "genGenPointerGet"));
10291 aopOp (left, ic, FALSE);
10292 loadDptrFromOperand (left, TRUE);
10294 /* so dptr now contains the address */
10295 aopOp (result, ic, FALSE);
10297 /* if bit then unpack */
10298 if (IS_BITFIELD (retype))
10300 genUnpackBits (result, "dptr", GPOINTER, ifx);
10304 size = AOP_SIZE (result);
10309 emitcode ("lcall", "__gptrget");
10311 aopPut (result, "a", offset++);
10313 emitcode ("inc", "dptr");
10317 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10319 aopPut (left, "dpl", 0);
10320 aopPut (left, "dph", 1);
10324 if (ifx && !ifx->generated)
10326 genIfxJump (ifx, "a", left, NULL, result);
10329 freeAsmop (result, NULL, ic, TRUE);
10330 freeAsmop (left, NULL, ic, TRUE);
10333 /*-----------------------------------------------------------------*/
10334 /* genPointerGet - generate code for pointer get */
10335 /*-----------------------------------------------------------------*/
10337 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
10339 operand *left, *result;
10340 sym_link *type, *etype;
10343 D (emitcode (";", "genPointerGet"));
10345 left = IC_LEFT (ic);
10346 result = IC_RESULT (ic);
10348 if (getSize (operandType (result))>1)
10351 /* depending on the type of pointer we need to
10352 move it to the correct pointer register */
10353 type = operandType (left);
10354 etype = getSpec (type);
10355 /* if left is of type of pointer then it is simple */
10356 if (IS_PTR (type) && !IS_FUNC (type->next))
10358 p_type = DCL_TYPE (type);
10362 /* we have to go by the storage class */
10363 p_type = PTR_TYPE (SPEC_OCLS (etype));
10366 /* special case when cast remat */
10367 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10368 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10370 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10371 type = operandType (left);
10372 p_type = DCL_TYPE (type);
10374 /* now that we have the pointer type we assign
10375 the pointer values */
10381 genNearPointerGet (left, result, ic, pi, ifx);
10385 genPagedPointerGet (left, result, ic, pi, ifx);
10389 genFarPointerGet (left, result, ic, pi, ifx);
10393 genCodePointerGet (left, result, ic, pi, ifx);
10397 genGenPointerGet (left, result, ic, pi, ifx);
10403 /*-----------------------------------------------------------------*/
10404 /* genPackBits - generates code for packed bit storage */
10405 /*-----------------------------------------------------------------*/
10407 genPackBits (sym_link * etype,
10409 char *rname, int p_type)
10411 int offset = 0; /* source byte offset */
10412 int rlen = 0; /* remaining bitfield length */
10413 int blen; /* bitfield length */
10414 int bstr; /* bitfield starting bit within byte */
10415 int litval; /* source literal value (if AOP_LIT) */
10416 unsigned char mask; /* bitmask within current byte */
10418 D(emitcode (";", "genPackBits"));
10420 blen = SPEC_BLEN (etype);
10421 bstr = SPEC_BSTR (etype);
10423 /* If the bitfield length is less than a byte */
10426 mask = ((unsigned char) (0xFF << (blen + bstr)) |
10427 (unsigned char) (0xFF >> (8 - bstr)));
10429 if (AOP_TYPE (right) == AOP_LIT)
10431 /* Case with a bitfield length <8 and literal source
10433 litval = (int) ulFromVal (AOP (right)->aopu.aop_lit);
10435 litval &= (~mask) & 0xff;
10436 emitPtrByteGet (rname, p_type, FALSE);
10437 if ((mask|litval)!=0xff)
10438 emitcode ("anl","a,#0x%02x", mask);
10440 emitcode ("orl","a,#0x%02x", litval);
10444 if ((blen==1) && (p_type!=GPOINTER))
10446 /* Case with a bitfield length == 1 and no generic pointer
10448 if (AOP_TYPE (right) == AOP_CRY)
10449 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10452 MOVA (aopGet (right, 0, FALSE, FALSE));
10453 emitcode ("rrc","a");
10455 emitPtrByteGet (rname, p_type, FALSE);
10456 emitcode ("mov","acc.%d,c",bstr);
10461 /* Case with a bitfield length < 8 and arbitrary source
10463 MOVA (aopGet (right, 0, FALSE, FALSE));
10464 /* shift and mask source value */
10466 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10468 pushedB = pushB ();
10469 /* transfer A to B and get next byte */
10470 emitPtrByteGet (rname, p_type, TRUE);
10472 emitcode ("anl", "a,#0x%02x", mask);
10473 emitcode ("orl", "a,b");
10474 if (p_type == GPOINTER)
10475 emitcode ("pop", "b");
10481 emitPtrByteSet (rname, p_type, "a");
10485 /* Bit length is greater than 7 bits. In this case, copy */
10486 /* all except the partial byte at the end */
10487 for (rlen=blen;rlen>=8;rlen-=8)
10489 emitPtrByteSet (rname, p_type,
10490 aopGet (right, offset++, FALSE, TRUE) );
10492 emitcode ("inc", "%s", rname);
10495 /* If there was a partial byte at the end */
10498 mask = (((unsigned char) -1 << rlen) & 0xff);
10500 if (AOP_TYPE (right) == AOP_LIT)
10502 /* Case with partial byte and literal source
10504 litval = (int) ulFromVal (AOP (right)->aopu.aop_lit);
10505 litval >>= (blen-rlen);
10506 litval &= (~mask) & 0xff;
10507 emitPtrByteGet (rname, p_type, FALSE);
10508 if ((mask|litval)!=0xff)
10509 emitcode ("anl","a,#0x%02x", mask);
10511 emitcode ("orl","a,#0x%02x", litval);
10516 /* Case with partial byte and arbitrary source
10518 MOVA (aopGet (right, offset++, FALSE, FALSE));
10519 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10521 pushedB = pushB ();
10522 /* transfer A to B and get next byte */
10523 emitPtrByteGet (rname, p_type, TRUE);
10525 emitcode ("anl", "a,#0x%02x", mask);
10526 emitcode ("orl", "a,b");
10527 if (p_type == GPOINTER)
10528 emitcode ("pop", "b");
10532 emitPtrByteSet (rname, p_type, "a");
10537 /*-----------------------------------------------------------------*/
10538 /* genDataPointerSet - remat pointer to data space */
10539 /*-----------------------------------------------------------------*/
10541 genDataPointerSet (operand * right,
10545 int size, offset = 0;
10546 char *l, buffer[256];
10548 D (emitcode (";", "genDataPointerSet"));
10550 aopOp (right, ic, FALSE);
10552 l = aopGet (result, 0, FALSE, TRUE);
10554 size = max (AOP_SIZE (right), AOP_SIZE (result));
10558 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
10560 SNPRINTF (buffer, sizeof(buffer), "%s", l);
10561 emitcode ("mov", "%s,%s", buffer,
10562 aopGet (right, offset++, FALSE, FALSE));
10565 freeAsmop (right, NULL, ic, TRUE);
10566 freeAsmop (result, NULL, ic, TRUE);
10569 /*-----------------------------------------------------------------*/
10570 /* genNearPointerSet - emitcode for near pointer put */
10571 /*-----------------------------------------------------------------*/
10573 genNearPointerSet (operand * right,
10581 sym_link *retype, *letype;
10582 sym_link *ptype = operandType (result);
10584 D (emitcode (";", "genNearPointerSet"));
10586 retype = getSpec (operandType (right));
10587 letype = getSpec (ptype);
10589 aopOp (result, ic, FALSE);
10591 /* if the result is rematerializable &
10592 in data space & not a bit variable */
10593 if (AOP_TYPE (result) == AOP_IMMD &&
10594 DCL_TYPE (ptype) == POINTER &&
10595 !IS_BITVAR (retype) &&
10596 !IS_BITVAR (letype))
10598 genDataPointerSet (right, result, ic);
10602 /* if the value is already in a pointer register
10603 then don't need anything more */
10604 if (!AOP_INPREG (AOP (result)))
10607 //AOP_TYPE (result) == AOP_STK
10608 IS_AOP_PREG(result)
10611 // Aha, it is a pointer, just in disguise.
10612 rname = aopGet (result, 0, FALSE, FALSE);
10615 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10616 __FILE__, __LINE__);
10621 emitcode ("mov", "a%s,%s", rname + 1, rname);
10622 rname++; // skip the '@'.
10627 /* otherwise get a free pointer register */
10628 aop = newAsmop (0);
10629 preg = getFreePtr (ic, &aop, FALSE);
10630 emitcode ("mov", "%s,%s",
10632 aopGet (result, 0, FALSE, TRUE));
10633 rname = preg->name;
10638 rname = aopGet (result, 0, FALSE, FALSE);
10641 aopOp (right, ic, FALSE);
10643 /* if bitfield then unpack the bits */
10644 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10645 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10648 /* we can just get the values */
10649 int size = AOP_SIZE (right);
10654 l = aopGet (right, offset, FALSE, TRUE);
10655 if ((*l == '@') || (strcmp (l, "acc") == 0))
10658 emitcode ("mov", "@%s,a", rname);
10661 emitcode ("mov", "@%s,%s", rname, l);
10663 emitcode ("inc", "%s", rname);
10668 /* now some housekeeping stuff */
10669 if (aop) /* we had to allocate for this iCode */
10672 aopPut (result, rname, 0);
10673 freeAsmop (NULL, aop, ic, TRUE);
10677 /* we did not allocate which means left
10678 already in a pointer register, then
10679 if size > 0 && this could be used again
10680 we have to point it back to where it
10682 if ((AOP_SIZE (right) > 1 &&
10683 !OP_SYMBOL (result)->remat &&
10684 (OP_SYMBOL (result)->liveTo > ic->seq ||
10688 int size = AOP_SIZE (right) - 1;
10690 emitcode ("dec", "%s", rname);
10697 freeAsmop (right, NULL, ic, TRUE);
10698 freeAsmop (result, NULL, ic, TRUE);
10701 /*-----------------------------------------------------------------*/
10702 /* genPagedPointerSet - emitcode for Paged pointer put */
10703 /*-----------------------------------------------------------------*/
10705 genPagedPointerSet (operand * right,
10713 sym_link *retype, *letype;
10715 D (emitcode (";", "genPagedPointerSet"));
10717 retype = getSpec (operandType (right));
10718 letype = getSpec (operandType (result));
10720 aopOp (result, ic, FALSE);
10722 /* if the value is already in a pointer register
10723 then don't need anything more */
10724 if (!AOP_INPREG (AOP (result)))
10726 /* otherwise get a free pointer register */
10727 aop = newAsmop (0);
10728 preg = getFreePtr (ic, &aop, FALSE);
10729 emitcode ("mov", "%s,%s",
10731 aopGet (result, 0, FALSE, TRUE));
10732 rname = preg->name;
10735 rname = aopGet (result, 0, FALSE, FALSE);
10737 aopOp (right, ic, FALSE);
10739 /* if bitfield then unpack the bits */
10740 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10741 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10744 /* we have can just get the values */
10745 int size = AOP_SIZE (right);
10750 l = aopGet (right, offset, FALSE, TRUE);
10752 emitcode ("movx", "@%s,a", rname);
10755 emitcode ("inc", "%s", rname);
10761 /* now some housekeeping stuff */
10762 if (aop) /* we had to allocate for this iCode */
10765 aopPut (result, rname, 0);
10766 freeAsmop (NULL, aop, ic, TRUE);
10770 /* we did not allocate which means left
10771 already in a pointer register, then
10772 if size > 0 && this could be used again
10773 we have to point it back to where it
10775 if (AOP_SIZE (right) > 1 &&
10776 !OP_SYMBOL (result)->remat &&
10777 (OP_SYMBOL (result)->liveTo > ic->seq ||
10780 int size = AOP_SIZE (right) - 1;
10782 emitcode ("dec", "%s", rname);
10787 if (pi) pi->generated = 1;
10788 freeAsmop (result, NULL, ic, TRUE);
10789 freeAsmop (right, NULL, ic, TRUE);
10792 /*-----------------------------------------------------------------*/
10793 /* genFarPointerSet - set value from far space */
10794 /*-----------------------------------------------------------------*/
10796 genFarPointerSet (operand * right,
10797 operand * result, iCode * ic, iCode * pi)
10800 sym_link *retype = getSpec (operandType (right));
10801 sym_link *letype = getSpec (operandType (result));
10803 D(emitcode (";", "genFarPointerSet"));
10805 aopOp (result, ic, FALSE);
10806 loadDptrFromOperand (result, FALSE);
10808 /* so dptr now contains the address */
10809 aopOp (right, ic, FALSE);
10811 /* if bit then unpack */
10812 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10813 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10816 size = AOP_SIZE (right);
10821 char *l = aopGet (right, offset++, FALSE, FALSE);
10823 emitcode ("movx", "@dptr,a");
10825 emitcode ("inc", "dptr");
10828 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10829 aopPut (result, "dpl", 0);
10830 aopPut (result, "dph", 1);
10833 freeAsmop (result, NULL, ic, TRUE);
10834 freeAsmop (right, NULL, ic, TRUE);
10837 /*-----------------------------------------------------------------*/
10838 /* genGenPointerSet - set value from generic pointer space */
10839 /*-----------------------------------------------------------------*/
10841 genGenPointerSet (operand * right,
10842 operand * result, iCode * ic, iCode * pi)
10845 sym_link *retype = getSpec (operandType (right));
10846 sym_link *letype = getSpec (operandType (result));
10848 D (emitcode (";", "genGenPointerSet"));
10850 aopOp (result, ic, FALSE);
10851 loadDptrFromOperand (result, TRUE);
10853 /* so dptr now contains the address */
10854 aopOp (right, ic, FALSE);
10856 /* if bit then unpack */
10857 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10859 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10863 size = AOP_SIZE (right);
10868 char *l = aopGet (right, offset++, FALSE, FALSE);
10870 emitcode ("lcall", "__gptrput");
10872 emitcode ("inc", "dptr");
10876 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10877 aopPut (result, "dpl", 0);
10878 aopPut (result, "dph", 1);
10881 freeAsmop (result, NULL, ic, TRUE);
10882 freeAsmop (right, NULL, ic, TRUE);
10885 /*-----------------------------------------------------------------*/
10886 /* genPointerSet - stores the value into a pointer location */
10887 /*-----------------------------------------------------------------*/
10889 genPointerSet (iCode * ic, iCode *pi)
10891 operand *right, *result;
10892 sym_link *type, *etype;
10895 D (emitcode (";", "genPointerSet"));
10897 right = IC_RIGHT (ic);
10898 result = IC_RESULT (ic);
10900 /* depending on the type of pointer we need to
10901 move it to the correct pointer register */
10902 type = operandType (result);
10903 etype = getSpec (type);
10904 /* if left is of type of pointer then it is simple */
10905 if (IS_PTR (type) && !IS_FUNC (type->next))
10907 p_type = DCL_TYPE (type);
10911 /* we have to go by the storage class */
10912 p_type = PTR_TYPE (SPEC_OCLS (etype));
10915 /* special case when cast remat */
10916 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10917 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10918 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10919 type = operandType (result);
10920 p_type = DCL_TYPE (type);
10923 /* now that we have the pointer type we assign
10924 the pointer values */
10930 genNearPointerSet (right, result, ic, pi);
10934 genPagedPointerSet (right, result, ic, pi);
10938 genFarPointerSet (right, result, ic, pi);
10942 genGenPointerSet (right, result, ic, pi);
10946 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10947 "genPointerSet: illegal pointer type");
10951 /*-----------------------------------------------------------------*/
10952 /* genIfx - generate code for Ifx statement */
10953 /*-----------------------------------------------------------------*/
10955 genIfx (iCode * ic, iCode * popIc)
10957 operand *cond = IC_COND (ic);
10961 D (emitcode (";", "genIfx"));
10963 aopOp (cond, ic, FALSE);
10965 /* get the value into acc */
10966 if (AOP_TYPE (cond) != AOP_CRY)
10973 if (AOP(cond)->aopu.aop_dir)
10974 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10977 /* the result is now in the accumulator or a directly addressable bit */
10978 freeAsmop (cond, NULL, ic, TRUE);
10980 /* if there was something to be popped then do it */
10984 /* if the condition is a bit variable */
10986 genIfxJump(ic, dup, NULL, NULL, NULL);
10987 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10988 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10989 else if (isbit && !IS_ITEMP (cond))
10990 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10992 genIfxJump (ic, "a", NULL, NULL, NULL);
10997 /*-----------------------------------------------------------------*/
10998 /* genAddrOf - generates code for address of */
10999 /*-----------------------------------------------------------------*/
11001 genAddrOf (iCode * ic)
11003 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
11006 D (emitcode (";", "genAddrOf"));
11008 aopOp (IC_RESULT (ic), ic, FALSE);
11010 /* if the operand is on the stack then we
11011 need to get the stack offset of this
11015 /* if it has an offset then we need to compute it */
11018 int stack_offset = ((sym->stack < 0) ?
11019 ((char) (sym->stack - _G.nRegsSaved)) :
11020 ((char) sym->stack)) & 0xff;
11021 if ((abs(stack_offset) == 1) &&
11022 !AOP_NEEDSACC(IC_RESULT (ic)) &&
11023 !isOperandVolatile (IC_RESULT (ic), FALSE))
11025 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
11026 if (stack_offset > 0)
11027 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
11029 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
11033 emitcode ("mov", "a,%s", SYM_BP (sym));
11034 emitcode ("add", "a,#0x%02x", stack_offset & 0xff);
11035 aopPut (IC_RESULT (ic), "a", 0);
11040 /* we can just move _bp */
11041 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
11043 /* fill the result with zero */
11044 size = AOP_SIZE (IC_RESULT (ic)) - 1;
11049 aopPut (IC_RESULT (ic), zero, offset++);
11054 /* object not on stack then we need the name */
11055 size = AOP_SIZE (IC_RESULT (ic));
11060 char s[SDCC_NAME_MAX];
11062 sprintf (s, "#(%s >> %d)",
11066 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11067 aopPut (IC_RESULT (ic), s, offset++);
11071 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11075 /*-----------------------------------------------------------------*/
11076 /* genFarFarAssign - assignment when both are in far space */
11077 /*-----------------------------------------------------------------*/
11079 genFarFarAssign (operand * result, operand * right, iCode * ic)
11081 int size = AOP_SIZE (right);
11085 D (emitcode (";", "genFarFarAssign"));
11087 /* first push the right side on to the stack */
11090 l = aopGet (right, offset++, FALSE, FALSE);
11092 emitcode ("push", "acc");
11095 freeAsmop (right, NULL, ic, FALSE);
11096 /* now assign DPTR to result */
11097 aopOp (result, ic, FALSE);
11098 size = AOP_SIZE (result);
11101 emitcode ("pop", "acc");
11102 aopPut (result, "a", --offset);
11104 freeAsmop (result, NULL, ic, FALSE);
11107 /*-----------------------------------------------------------------*/
11108 /* genAssign - generate code for assignment */
11109 /*-----------------------------------------------------------------*/
11111 genAssign (iCode * ic)
11113 operand *result, *right;
11115 unsigned long lit = 0L;
11117 D (emitcode (";", "genAssign"));
11119 result = IC_RESULT (ic);
11120 right = IC_RIGHT (ic);
11122 /* if they are the same */
11123 if (operandsEqu (result, right) &&
11124 !isOperandVolatile (result, FALSE) &&
11125 !isOperandVolatile (right, FALSE))
11128 aopOp (right, ic, FALSE);
11130 /* special case both in far space */
11131 if (AOP_TYPE (right) == AOP_DPTR &&
11132 IS_TRUE_SYMOP (result) &&
11133 isOperandInFarSpace (result))
11135 genFarFarAssign (result, right, ic);
11139 aopOp (result, ic, TRUE);
11141 /* if they are the same registers */
11142 if (sameRegs (AOP (right), AOP (result)) &&
11143 !isOperandVolatile (result, FALSE) &&
11144 !isOperandVolatile (right, FALSE))
11147 /* if the result is a bit */
11148 if (AOP_TYPE (result) == AOP_CRY)
11150 assignBit (result, right);
11154 /* bit variables done */
11156 size = AOP_SIZE (result);
11158 if (AOP_TYPE (right) == AOP_LIT)
11159 lit = ulFromVal (AOP (right)->aopu.aop_lit);
11162 (AOP_TYPE (result) != AOP_REG) &&
11163 (AOP_TYPE (right) == AOP_LIT) &&
11164 !IS_FLOAT (operandType (right)) &&
11167 while ((size) && (lit))
11170 aopGet (right, offset, FALSE, FALSE),
11176 /* And now fill the rest with zeros. */
11179 emitcode ("clr", "a");
11183 aopPut (result, "a", offset);
11192 aopGet (right, offset, FALSE, FALSE),
11199 freeAsmop (result, NULL, ic, TRUE);
11200 freeAsmop (right, NULL, ic, TRUE);
11203 /*-----------------------------------------------------------------*/
11204 /* genJumpTab - generates code for jump table */
11205 /*-----------------------------------------------------------------*/
11207 genJumpTab (iCode * ic)
11209 symbol *jtab,*jtablo,*jtabhi;
11211 unsigned int count;
11213 D (emitcode (";", "genJumpTab"));
11215 count = elementsInSet( IC_JTLABELS (ic) );
11219 /* this algorithm needs 9 cycles and 7 + 3*n bytes
11220 if the switch argument is in a register.
11221 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
11222 /* Peephole may not convert ljmp to sjmp or ret
11223 labelIsReturnOnly & labelInRange must check
11224 currPl->ic->op != JUMPTABLE */
11225 aopOp (IC_JTCOND (ic), ic, FALSE);
11226 /* get the condition into accumulator */
11227 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11229 /* multiply by three */
11230 if (aopGetUsesAcc (IC_JTCOND (ic), 0))
11232 emitcode ("mov", "b,#3");
11233 emitcode ("mul", "ab");
11237 emitcode ("add", "a,acc");
11238 emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
11240 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11242 jtab = newiTempLabel (NULL);
11243 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
11244 emitcode ("jmp", "@a+dptr");
11246 /* now generate the jump labels */
11247 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11248 jtab = setNextItem (IC_JTLABELS (ic)))
11249 emitcode ("ljmp", "%05d$", jtab->key + 100);
11253 /* this algorithm needs 14 cycles and 13 + 2*n bytes
11254 if the switch argument is in a register.
11255 For n>6 this algorithm may be more compact */
11256 jtablo = newiTempLabel (NULL);
11257 jtabhi = newiTempLabel (NULL);
11259 /* get the condition into accumulator.
11260 Using b as temporary storage, if register push/pop is needed */
11261 aopOp (IC_JTCOND (ic), ic, FALSE);
11262 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11263 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
11264 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
11266 // (MB) what if B is in use???
11267 wassertl(!BINUSE, "B was in use");
11268 emitcode ("mov", "b,%s", l);
11271 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11275 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
11276 emitcode ("movc", "a,@a+pc");
11277 emitcode ("push", "acc");
11280 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
11281 emitcode ("movc", "a,@a+pc");
11282 emitcode ("push", "acc");
11286 /* this scales up to n<=255, but needs two more bytes
11287 and changes dptr */
11288 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
11289 emitcode ("movc", "a,@a+dptr");
11290 emitcode ("push", "acc");
11293 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
11294 emitcode ("movc", "a,@a+dptr");
11295 emitcode ("push", "acc");
11298 emitcode ("ret", "");
11300 /* now generate jump table, LSB */
11301 emitLabel (jtablo);
11302 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11303 jtab = setNextItem (IC_JTLABELS (ic)))
11304 emitcode (".db", "%05d$", jtab->key + 100);
11306 /* now generate jump table, MSB */
11307 emitLabel (jtabhi);
11308 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11309 jtab = setNextItem (IC_JTLABELS (ic)))
11310 emitcode (".db", "%05d$>>8", jtab->key + 100);
11314 /*-----------------------------------------------------------------*/
11315 /* genCast - gen code for casting */
11316 /*-----------------------------------------------------------------*/
11318 genCast (iCode * ic)
11320 operand *result = IC_RESULT (ic);
11321 sym_link *ctype = operandType (IC_LEFT (ic));
11322 sym_link *rtype = operandType (IC_RIGHT (ic));
11323 operand *right = IC_RIGHT (ic);
11326 D (emitcode (";", "genCast"));
11328 /* if they are equivalent then do nothing */
11329 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11332 aopOp (right, ic, FALSE);
11333 aopOp (result, ic, FALSE);
11335 /* if the result is a bit (and not a bitfield) */
11336 if (IS_BIT (OP_SYMBOL (result)->type))
11338 assignBit (result, right);
11342 /* if they are the same size : or less */
11343 if (AOP_SIZE (result) <= AOP_SIZE (right))
11346 /* if they are in the same place */
11347 if (sameRegs (AOP (right), AOP (result)))
11350 /* if they in different places then copy */
11351 size = AOP_SIZE (result);
11356 aopGet (right, offset, FALSE, FALSE),
11363 /* if the result is of type pointer */
11364 if (IS_PTR (ctype))
11368 sym_link *type = operandType (right);
11369 sym_link *etype = getSpec (type);
11371 /* pointer to generic pointer */
11372 if (IS_GENPTR (ctype))
11376 p_type = DCL_TYPE (type);
11380 if (SPEC_SCLS(etype)==S_REGISTER) {
11381 // let's assume it is a generic pointer
11384 /* we have to go by the storage class */
11385 p_type = PTR_TYPE (SPEC_OCLS (etype));
11389 /* the first two bytes are known */
11390 size = GPTRSIZE - 1;
11395 aopGet (right, offset, FALSE, FALSE),
11399 /* the last byte depending on type */
11401 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11406 // pointerTypeToGPByte will have bitched.
11410 sprintf(gpValStr, "#0x%x", gpVal);
11411 aopPut (result, gpValStr, GPTRSIZE - 1);
11416 /* just copy the pointers */
11417 size = AOP_SIZE (result);
11422 aopGet (right, offset, FALSE, FALSE),
11429 /* so we now know that the size of destination is greater
11430 than the size of the source */
11431 /* we move to result for the size of source */
11432 size = AOP_SIZE (right);
11437 aopGet (right, offset, FALSE, FALSE),
11442 /* now depending on the sign of the source && destination */
11443 size = AOP_SIZE (result) - AOP_SIZE (right);
11444 /* if unsigned or not an integral type */
11445 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11448 aopPut (result, zero, offset++);
11452 /* we need to extend the sign :{ */
11453 char *l = aopGet (right, AOP_SIZE (right) - 1,
11456 emitcode ("rlc", "a");
11457 emitcode ("subb", "a,acc");
11459 aopPut (result, "a", offset++);
11462 /* we are done hurray !!!! */
11465 freeAsmop (result, NULL, ic, TRUE);
11466 freeAsmop (right, NULL, ic, TRUE);
11469 /*-----------------------------------------------------------------*/
11470 /* genDjnz - generate decrement & jump if not zero instrucion */
11471 /*-----------------------------------------------------------------*/
11473 genDjnz (iCode * ic, iCode * ifx)
11475 symbol *lbl, *lbl1;
11479 /* if the if condition has a false label
11480 then we cannot save */
11481 if (IC_FALSE (ifx))
11484 /* if the minus is not of the form a = a - 1 */
11485 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11486 !IS_OP_LITERAL (IC_RIGHT (ic)))
11489 if (operandLitValue (IC_RIGHT (ic)) != 1)
11492 /* if the size of this greater than one then no
11494 if (getSize (operandType (IC_RESULT (ic))) > 1)
11497 /* otherwise we can save BIG */
11499 D (emitcode (";", "genDjnz"));
11501 lbl = newiTempLabel (NULL);
11502 lbl1 = newiTempLabel (NULL);
11504 aopOp (IC_RESULT (ic), ic, FALSE);
11506 if (AOP_NEEDSACC(IC_RESULT(ic)))
11508 /* If the result is accessed indirectly via
11509 * the accumulator, we must explicitly write
11510 * it back after the decrement.
11512 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11514 if (strcmp(rByte, "a"))
11516 /* Something is hopelessly wrong */
11517 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11518 __FILE__, __LINE__);
11519 /* We can just give up; the generated code will be inefficient,
11520 * but what the hey.
11522 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11525 emitcode ("dec", "%s", rByte);
11526 aopPut (IC_RESULT (ic), rByte, 0);
11527 emitcode ("jnz", "%05d$", lbl->key + 100);
11529 else if (IS_AOP_PREG (IC_RESULT (ic)))
11531 emitcode ("dec", "%s",
11532 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11533 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11534 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11535 ifx->generated = 1;
11536 emitcode ("jnz", "%05d$", lbl->key + 100);
11540 emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11543 emitcode ("sjmp", "%05d$", lbl1->key + 100);
11545 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11548 if (!ifx->generated)
11549 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11550 ifx->generated = 1;
11554 /*-----------------------------------------------------------------*/
11555 /* genReceive - generate code for a receive iCode */
11556 /*-----------------------------------------------------------------*/
11558 genReceive (iCode * ic)
11560 int size = getSize (operandType (IC_RESULT (ic)));
11563 D (emitcode (";", "genReceive"));
11565 if (ic->argreg == 1)
11566 { /* first parameter */
11567 if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11568 isOperandInPagedSpace (IC_RESULT (ic))) &&
11569 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11570 IS_TRUE_SYMOP (IC_RESULT (ic))))
11573 int receivingA = 0;
11576 for (offset = 0; offset<size; offset++)
11577 if (!strcmp (fReturn[offset], "a"))
11582 if (size==1 || getTempRegs(tempRegs, size-1, ic))
11584 for (offset = size-1; offset>0; offset--)
11585 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11586 emitcode("mov","a,%s", fReturn[0]);
11588 aopOp (IC_RESULT (ic), ic, FALSE);
11590 aopPut (IC_RESULT (ic), "a", offset);
11591 for (offset = 1; offset<size; offset++)
11592 aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset);
11598 if (getTempRegs(tempRegs, size, ic))
11600 for (offset = 0; offset<size; offset++)
11601 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11602 aopOp (IC_RESULT (ic), ic, FALSE);
11603 for (offset = 0; offset<size; offset++)
11604 aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset);
11609 offset = fReturnSizeMCS51 - size;
11612 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11613 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11616 aopOp (IC_RESULT (ic), ic, FALSE);
11617 size = AOP_SIZE (IC_RESULT (ic));
11621 emitcode ("pop", "acc");
11622 aopPut (IC_RESULT (ic), "a", offset++);
11628 aopOp (IC_RESULT (ic), ic, FALSE);
11630 assignResultValue (IC_RESULT (ic), NULL);
11633 else if (ic->argreg > 12)
11634 { /* bit parameters */
11635 regs *reg = OP_SYMBOL (IC_RESULT (ic))->regs[0];
11638 if (!reg || reg->rIdx != ic->argreg-5)
11640 aopOp (IC_RESULT (ic), ic, FALSE);
11641 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11642 outBitC(IC_RESULT (ic));
11646 { /* other parameters */
11648 aopOp (IC_RESULT (ic), ic, FALSE);
11649 rb1off = ic->argreg;
11652 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
11657 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11660 /*-----------------------------------------------------------------*/
11661 /* genDummyRead - generate code for dummy read of volatiles */
11662 /*-----------------------------------------------------------------*/
11664 genDummyRead (iCode * ic)
11669 D (emitcode(";", "genDummyRead"));
11671 op = IC_RIGHT (ic);
11672 if (op && IS_SYMOP (op))
11674 aopOp (op, ic, FALSE);
11676 /* if the result is a bit */
11677 if (AOP_TYPE (op) == AOP_CRY)
11678 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11681 /* bit variables done */
11683 size = AOP_SIZE (op);
11687 MOVA (aopGet (op, offset, FALSE, FALSE));
11692 freeAsmop (op, NULL, ic, TRUE);
11696 if (op && IS_SYMOP (op))
11698 aopOp (op, ic, FALSE);
11700 /* if the result is a bit */
11701 if (AOP_TYPE (op) == AOP_CRY)
11702 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11705 /* bit variables done */
11707 size = AOP_SIZE (op);
11711 MOVA (aopGet (op, offset, FALSE, FALSE));
11716 freeAsmop (op, NULL, ic, TRUE);
11720 /*-----------------------------------------------------------------*/
11721 /* genCritical - generate code for start of a critical sequence */
11722 /*-----------------------------------------------------------------*/
11724 genCritical (iCode *ic)
11726 symbol *tlbl = newiTempLabel (NULL);
11728 D (emitcode(";", "genCritical"));
11730 if (IC_RESULT (ic))
11732 aopOp (IC_RESULT (ic), ic, TRUE);
11733 aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
11734 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11735 aopPut (IC_RESULT (ic), zero, 0);
11737 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11741 emitcode ("setb", "c");
11742 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11743 emitcode ("clr", "c");
11745 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11749 /*-----------------------------------------------------------------*/
11750 /* genEndCritical - generate code for end of a critical sequence */
11751 /*-----------------------------------------------------------------*/
11753 genEndCritical (iCode *ic)
11755 D(emitcode(";", "genEndCritical"));
11759 aopOp (IC_RIGHT (ic), ic, FALSE);
11760 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11762 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11763 emitcode ("mov", "ea,c");
11767 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11768 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11769 emitcode ("rrc", "a");
11770 emitcode ("mov", "ea,c");
11772 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11776 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11777 emitcode ("mov", "ea,c");
11781 /*-----------------------------------------------------------------*/
11782 /* gen51Code - generate code for 8051 based controllers */
11783 /*-----------------------------------------------------------------*/
11785 gen51Code (iCode * lic)
11789 /* int cseq = 0; */
11791 _G.currentFunc = NULL;
11792 lineHead = lineCurr = NULL;
11794 /* print the allocation information */
11795 if (allocInfo && currFunc)
11796 printAllocInfo (currFunc, codeOutBuf);
11797 /* if debug information required */
11798 if (options.debug && currFunc)
11800 debugFile->writeFunction (currFunc, lic);
11802 /* stack pointer name */
11803 if (options.useXstack)
11809 for (ic = lic; ic; ic = ic->next)
11811 _G.current_iCode = ic;
11813 if (ic->lineno && cln != ic->lineno)
11817 debugFile->writeCLine (ic);
11819 if (!options.noCcodeInAsm) {
11820 emitcode (";", "%s:%d: %s", ic->filename, ic->lineno,
11821 printCLine(ic->filename, ic->lineno));
11826 if (ic->seqPoint && ic->seqPoint != cseq)
11828 emitcode (";", "sequence point %d", ic->seqPoint);
11829 cseq = ic->seqPoint;
11832 if (options.iCodeInAsm) {
11833 char regsInUse[80];
11838 for (i=0; i<8; i++) {
11839 sprintf (®sInUse[i],
11840 "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11843 strcpy (regsInUse, "--------");
11844 for (i=0; i < 8; i++) {
11845 if (bitVectBitValue (ic->rMask, i))
11847 int offset = regs8051[i].offset;
11848 regsInUse[offset] = offset + '0'; /* show rMask */
11852 iLine = printILine(ic);
11853 emitcode(";", "[%s] ic:%d: %s", regsInUse, ic->seq, iLine);
11856 /* if the result is marked as
11857 spilt and rematerializable or code for
11858 this has already been generated then
11860 if (resultRemat (ic) || ic->generated)
11863 /* depending on the operation */
11883 /* IPOP happens only when trying to restore a
11884 spilt live range, if there is an ifx statement
11885 following this pop then the if statement might
11886 be using some of the registers being popped which
11887 would destory the contents of the register so
11888 we need to check for this condition and handle it */
11890 ic->next->op == IFX &&
11891 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11892 genIfx (ic->next, ic);
11910 genEndFunction (ic);
11930 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11947 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11951 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11958 /* note these two are xlated by algebraic equivalence
11959 in decorateType() in SDCCast.c */
11960 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11961 "got '>=' or '<=' shouldn't have come here");
11965 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11977 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11981 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11985 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
12021 genRightShift (ic);
12024 case GET_VALUE_AT_ADDRESS:
12026 hasInc (IC_LEFT (ic), ic,
12027 getSize (operandType (IC_RESULT (ic)))),
12028 ifxForOp (IC_RESULT (ic), ic) );
12032 if (POINTER_SET (ic))
12034 hasInc (IC_RESULT (ic), ic,
12035 getSize (operandType (IC_RIGHT (ic)))));
12061 addSet (&_G.sendSet, ic);
12064 case DUMMY_READ_VOLATILE:
12073 genEndCritical (ic);
12085 _G.current_iCode = NULL;
12087 /* now we are ready to call the
12088 peep hole optimizer */
12089 if (!options.nopeep)
12090 peepHole (&lineHead);
12092 /* now do the actual printing */
12093 printLine (lineHead, codeOutBuf);