1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for 8051
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
27 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
28 Made everything static
29 -------------------------------------------------------------------------*/
31 #define D(x) do if (options.verboseAsm) {x;} while(0)
37 #include "SDCCglobl.h"
41 #include "SDCCpeeph.h"
45 #include "dbuf_string.h"
47 char *aopLiteral (value * val, int offset);
48 char *aopLiteralLong (value * val, int offset, int size);
51 /* this is the down and dirty file with all kinds of
52 kludgy & hacky stuff. This is what it is all about
53 CODE GENERATION for a specific MCU . some of the
54 routines may be reusable, will have to see */
56 static char *zero = "#0x00";
57 static char *one = "#0x01";
61 {"dpl", "dph", "b", "a"};
62 unsigned fReturnSizeMCS51 = 4; /* shared with ralloc.c */
63 char **fReturn = fReturn8051;
64 static char *accUse[] =
67 static unsigned short rbank = -1;
69 #define REG_WITH_INDEX mcs51_regWithIdx
71 #define AOP(op) op->aop
72 #define AOP_TYPE(op) AOP(op)->type
73 #define AOP_SIZE(op) AOP(op)->size
74 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
75 AOP_TYPE(x) == AOP_R0))
77 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
78 AOP_TYPE(x) == AOP_DPTR || \
81 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
82 (x->aopu.aop_reg[0] == REG_WITH_INDEX(R0_IDX) || \
83 x->aopu.aop_reg[0] == REG_WITH_INDEX(R1_IDX) )))
85 #define SYM_BP(sym) (SPEC_OCLS (sym->etype)->paged ? "_bpx" : "_bp")
87 #define R0INB _G.bu.bs.r0InB
88 #define R1INB _G.bu.bs.r1InB
89 #define OPINB _G.bu.bs.OpInB
90 #define BINUSE _G.bu.BInUse
100 short r0InB : 2;//2 so we can see it overflow
101 short r1InB : 2;//2 so we can see it overflow
102 short OpInB : 2;//2 so we can see it overflow
111 iCode *current_iCode;
116 static char *rb1regs[] = {
117 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7",
118 "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7"
121 extern struct dbuf_s *codeOutBuf;
123 #define RESULTONSTACK(x) \
124 (IC_RESULT(x) && IC_RESULT(x)->aop && \
125 IC_RESULT(x)->aop->type == AOP_STK )
127 #define MOVA(x) mova(x) /* use function to avoid multiple eval */
128 #define MOVB(x) movb(x)
130 #define CLRC emitcode("clr","c")
131 #define SETC emitcode("setb","c")
133 static lineNode *lineHead = NULL;
134 static lineNode *lineCurr = NULL;
136 static unsigned char SLMask[] =
137 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
138 0xE0, 0xC0, 0x80, 0x00};
139 static unsigned char SRMask[] =
140 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
141 0x07, 0x03, 0x01, 0x00};
148 /*-----------------------------------------------------------------*/
149 /* emitcode - writes the code into a file : for now it is simple */
150 /*-----------------------------------------------------------------*/
152 emitcode (const char *inst, const char *fmt,...)
156 const char *lbp, *lb;
158 dbuf_init (&dbuf, INITIAL_INLINEASM);
164 dbuf_append_str (&dbuf, inst);
168 dbuf_append_char (&dbuf, '\t');
169 dbuf_tvprintf (&dbuf, fmt, ap);
174 dbuf_tvprintf (&dbuf, fmt, ap);
177 lbp = lb = dbuf_c_str(&dbuf);
179 while (isspace ((unsigned char)*lbp))
188 lineCurr = (lineCurr ?
189 connectLine (lineCurr, newLineNode (lb)) :
190 (lineHead = newLineNode (lb)));
192 lineCurr->isInline = _G.inLine;
193 lineCurr->isDebug = _G.debugLine;
194 lineCurr->ic = _G.current_iCode;
195 lineCurr->isComment = (*lbp==';');
204 emitLabel (symbol *tlbl)
206 emitcode ("", "%05d$:", tlbl->key + 100);
207 lineCurr->isLabel = 1;
210 /*-----------------------------------------------------------------*/
211 /* mcs51_emitDebuggerSymbol - associate the current code location */
212 /* with a debugger symbol */
213 /*-----------------------------------------------------------------*/
215 mcs51_emitDebuggerSymbol (char * debugSym)
218 emitcode ("", "%s ==.", debugSym);
222 /*-----------------------------------------------------------------*/
223 /* mova - moves specified value into accumulator */
224 /*-----------------------------------------------------------------*/
228 /* do some early peephole optimization */
229 if (!strncmp(x, "a", 2) || !strncmp(x, "acc", 4))
232 /* if it is a literal mov try to get it cheaper */
237 emitcode("mov", "a,%s", x);
240 /*-----------------------------------------------------------------*/
241 /* movb - moves specified value into register b */
242 /*-----------------------------------------------------------------*/
246 /* do some early peephole optimization */
247 if (!strncmp(x, "b", 2))
250 /* if it is a literal mov try to get it cheaper */
253 emitcode("mov","b,%s", rtrackGetLit(x));
257 emitcode("mov","b,%s", x);
260 /*-----------------------------------------------------------------*/
261 /* pushB - saves register B if necessary */
262 /*-----------------------------------------------------------------*/
266 bool pushedB = FALSE;
270 emitcode ("push", "b");
271 // printf("B was in use !\n");
281 /*-----------------------------------------------------------------*/
282 /* popB - restores value of register B if necessary */
283 /*-----------------------------------------------------------------*/
289 emitcode ("pop", "b");
297 /*-----------------------------------------------------------------*/
298 /* pushReg - saves register */
299 /*-----------------------------------------------------------------*/
301 pushReg (int index, bool bits_pushed)
303 regs * reg = REG_WITH_INDEX (index);
304 if (reg->type == REG_BIT)
307 emitcode ("push", "%s", reg->base);
311 emitcode ("push", "%s", reg->dname);
315 /*-----------------------------------------------------------------*/
316 /* popReg - restores register */
317 /*-----------------------------------------------------------------*/
319 popReg (int index, bool bits_popped)
321 regs * reg = REG_WITH_INDEX (index);
322 if (reg->type == REG_BIT)
325 emitcode ("pop", "%s", reg->base);
329 emitcode ("pop", "%s", reg->dname);
333 /*-----------------------------------------------------------------*/
334 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
335 /*-----------------------------------------------------------------*/
337 getFreePtr (iCode * ic, asmop ** aopp, bool result)
342 /* the logic: if r0 & r1 used in the instruction
343 then we are in trouble otherwise */
345 /* first check if r0 & r1 are used by this
346 instruction, in which case we are in trouble */
347 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
348 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
353 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
354 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
356 /* if no usage of r0 then return it */
359 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
360 (*aopp)->type = AOP_R0;
362 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
365 /* if no usage of r1 then return it */
368 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
369 (*aopp)->type = AOP_R1;
371 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R1_IDX);
374 /* now we know they both have usage */
375 /* if r0 not used in this instruction */
378 /* push it if not already pushed */
381 MOVB (REG_WITH_INDEX (R0_IDX)->dname);
384 else if (!_G.r0Pushed)
386 emitcode ("push", "%s",
387 REG_WITH_INDEX (R0_IDX)->dname);
391 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
392 (*aopp)->type = AOP_R0;
394 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
397 /* if r1 not used then */
401 /* push it if not already pushed */
404 MOVB (REG_WITH_INDEX (R1_IDX)->dname);
407 else if (!_G.r1Pushed)
409 emitcode ("push", "%s",
410 REG_WITH_INDEX (R1_IDX)->dname);
414 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
415 (*aopp)->type = AOP_R1;
416 return REG_WITH_INDEX (R1_IDX);
420 /* I said end of world, but not quite end of world yet */
421 /* if this is a result then we can push it on the stack */
424 (*aopp)->type = AOP_STK;
427 /* in the case that result AND left AND right needs a pointer reg
428 we can safely use the result's */
429 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX))
431 (*aopp)->type = AOP_R0;
432 return REG_WITH_INDEX (R0_IDX);
434 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX))
436 (*aopp)->type = AOP_R1;
437 return REG_WITH_INDEX (R1_IDX);
440 /* now this is REALLY the end of the world */
441 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
442 "getFreePtr should never reach here");
447 /*-----------------------------------------------------------------*/
448 /* getTempRegs - initialize an array of pointers to GPR registers */
449 /* that are not in use. Returns 1 if the requested */
450 /* number of registers were available, 0 otherwise. */
451 /*-----------------------------------------------------------------*/
453 getTempRegs(regs **tempRegs, int size, iCode *ic)
460 ic = _G.current_iCode;
466 freeRegs = newBitVect(8);
467 bitVectSetBit (freeRegs, R2_IDX);
468 bitVectSetBit (freeRegs, R3_IDX);
469 bitVectSetBit (freeRegs, R4_IDX);
470 bitVectSetBit (freeRegs, R5_IDX);
471 bitVectSetBit (freeRegs, R6_IDX);
472 bitVectSetBit (freeRegs, R7_IDX);
474 if (IFFUNC_CALLEESAVES(_G.currentFunc->type))
476 bitVect * newfreeRegs;
477 newfreeRegs = bitVectIntersect (freeRegs, _G.currentFunc->regsUsed);
478 freeBitVect(freeRegs);
479 freeRegs = newfreeRegs;
481 freeRegs = bitVectCplAnd (freeRegs, ic->rMask);
484 for (i=0; i<freeRegs->size; i++)
486 if (bitVectBitValue(freeRegs,i))
487 tempRegs[offset++] = REG_WITH_INDEX(i);
490 freeBitVect(freeRegs);
495 freeBitVect(freeRegs);
500 /*-----------------------------------------------------------------*/
501 /* newAsmop - creates a new asmOp */
502 /*-----------------------------------------------------------------*/
504 newAsmop (short type)
508 aop = Safe_calloc (1, sizeof (asmop));
514 /*-----------------------------------------------------------------*/
515 /* pointerCode - returns the code for a pointer type */
516 /*-----------------------------------------------------------------*/
518 pointerCode (sym_link * etype)
521 return PTR_TYPE (SPEC_OCLS (etype));
525 /*-----------------------------------------------------------------*/
526 /* leftRightUseAcc - returns size of accumulator use by operands */
527 /*-----------------------------------------------------------------*/
529 leftRightUseAcc(iCode *ic)
538 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
539 "null iCode pointer");
546 if (IS_OP_ACCUSE (op))
549 size = getSize (OP_SYMBOL (op)->type);
554 else if (ic->op == JUMPTABLE)
557 if (IS_OP_ACCUSE (op))
560 size = getSize (OP_SYMBOL (op)->type);
568 if (IS_OP_ACCUSE (op))
571 size = getSize (OP_SYMBOL (op)->type);
576 if (IS_OP_ACCUSE (op))
579 size = getSize (OP_SYMBOL (op)->type);
591 /*-----------------------------------------------------------------*/
592 /* aopForSym - for a true symbol */
593 /*-----------------------------------------------------------------*/
595 aopForSym (iCode * ic, symbol * sym, bool result)
599 bool accuse = leftRightUseAcc (ic) || _G.accInUse;
601 wassertl (ic != NULL, "Got a null iCode");
602 wassertl (sym != NULL, "Got a null symbol");
604 space = SPEC_OCLS (sym->etype);
606 /* if already has one */
609 sym->aop->allocated++;
613 /* assign depending on the storage class */
614 /* if it is on the stack or indirectly addressable */
615 /* space we need to assign either r0 or r1 to it */
616 if (sym->onStack || sym->iaccess)
618 sym->aop = aop = newAsmop (0);
619 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
620 aop->size = getSize (sym->type);
622 /* now assign the address of the variable to
623 the pointer register */
624 if (aop->type != AOP_STK)
628 signed char offset = ((sym->stack < 0) ?
629 ((signed char) (sym->stack - _G.nRegsSaved)) :
630 ((signed char) sym->stack)) & 0xff;
632 if ((abs(offset) <= 3) ||
633 (accuse && (abs(offset) <= 7)))
635 emitcode ("mov", "%s,%s",
636 aop->aopu.aop_ptr->name, SYM_BP (sym));
639 emitcode ("dec", aop->aopu.aop_ptr->name);
644 emitcode ("inc", aop->aopu.aop_ptr->name);
651 emitcode ("push", "acc");
652 emitcode ("mov", "a,%s", SYM_BP (sym));
653 emitcode ("add", "a,#0x%02x", offset & 0xff);
654 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
656 emitcode ("pop", "acc");
661 emitcode ("mov", "%s,#%s",
662 aop->aopu.aop_ptr->name,
665 aop->paged = space->paged;
668 aop->aopu.aop_stk = sym->stack;
672 /* if in bit space */
673 if (IN_BITSPACE (space))
675 sym->aop = aop = newAsmop (AOP_CRY);
676 aop->aopu.aop_dir = sym->rname;
677 aop->size = getSize (sym->type);
680 /* if it is in direct space */
681 if (IN_DIRSPACE (space))
683 //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
684 //printTypeChainRaw(sym->type, NULL);
685 //printf("space = %s\n", space ? space->sname : "NULL");
686 sym->aop = aop = newAsmop (AOP_DIR);
687 aop->aopu.aop_dir = sym->rname;
688 aop->size = getSize (sym->type);
692 /* special case for a function */
693 if (IS_FUNC (sym->type))
695 sym->aop = aop = newAsmop (AOP_IMMD);
696 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
697 aop->size = getSize (sym->type);
701 /* only remaining is far space */
702 /* in which case DPTR gets the address */
703 sym->aop = aop = newAsmop (AOP_DPTR);
704 emitcode ("mov", "dptr,#%s", sym->rname);
705 aop->size = getSize (sym->type);
707 /* if it is in code space */
708 if (IN_CODESPACE (space))
714 /*-----------------------------------------------------------------*/
715 /* aopForRemat - rematerializes an object */
716 /*-----------------------------------------------------------------*/
718 aopForRemat (symbol * sym)
720 iCode *ic = sym->rematiCode;
721 asmop *aop = newAsmop (AOP_IMMD);
728 val += (int) operandLitValue (IC_RIGHT (ic));
729 else if (ic->op == '-')
730 val -= (int) operandLitValue (IC_RIGHT (ic));
731 else if (IS_CAST_ICODE(ic))
733 sym_link *from_type = operandType(IC_RIGHT(ic));
734 aop->aopu.aop_immd.from_cast_remat = 1;
735 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
736 ptr_type = pointerTypeToGPByte (DCL_TYPE(from_type), NULL, NULL);
741 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
746 SNPRINTF (buffer, sizeof(buffer),
748 OP_SYMBOL (IC_LEFT (ic))->rname,
749 val >= 0 ? '+' : '-',
754 strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
757 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
758 /* set immd2 field if required */
759 if (aop->aopu.aop_immd.from_cast_remat)
761 SNPRINTF (buffer, sizeof(buffer), "#0x%02x", ptr_type);
762 aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
768 /*-----------------------------------------------------------------*/
769 /* regsInCommon - two operands have some registers in common */
770 /*-----------------------------------------------------------------*/
772 regsInCommon (operand * op1, operand * op2)
777 /* if they have registers in common */
778 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
781 sym1 = OP_SYMBOL (op1);
782 sym2 = OP_SYMBOL (op2);
784 if (sym1->nRegs == 0 || sym2->nRegs == 0)
787 for (i = 0; i < sym1->nRegs; i++)
793 for (j = 0; j < sym2->nRegs; j++)
798 if (sym2->regs[j] == sym1->regs[i])
806 /*-----------------------------------------------------------------*/
807 /* operandsEqu - equivalent */
808 /*-----------------------------------------------------------------*/
810 operandsEqu (operand * op1, operand * op2)
814 /* if they're not symbols */
815 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
818 sym1 = OP_SYMBOL (op1);
819 sym2 = OP_SYMBOL (op2);
821 /* if both are itemps & one is spilt
822 and the other is not then false */
823 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
824 sym1->isspilt != sym2->isspilt)
827 /* if they are the same */
831 /* if they have the same rname */
832 if (sym1->rname[0] && sym2->rname[0] &&
833 strcmp (sym1->rname, sym2->rname) == 0 &&
834 !(IS_PARM (op2) && IS_ITEMP (op1)))
837 /* if left is a tmp & right is not */
838 if (IS_ITEMP (op1) &&
841 (sym1->usl.spillLoc == sym2))
844 if (IS_ITEMP (op2) &&
848 (sym2->usl.spillLoc == sym1))
854 /*-----------------------------------------------------------------*/
855 /* sameByte - two asmops have the same address at given offsets */
856 /*-----------------------------------------------------------------*/
858 sameByte (asmop * aop1, int off1, asmop * aop2, int off2)
860 if (aop1 == aop2 && off1 == off2)
863 if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
866 if (aop1->type != aop2->type)
869 if (aop1->aopu.aop_reg[off1] != aop2->aopu.aop_reg[off2])
875 /*-----------------------------------------------------------------*/
876 /* sameRegs - two asmops have the same registers */
877 /*-----------------------------------------------------------------*/
879 sameRegs (asmop * aop1, asmop * aop2)
886 if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
889 if (aop1->type != aop2->type)
892 if (aop1->size != aop2->size)
895 for (i = 0; i < aop1->size; i++)
896 if (aop1->aopu.aop_reg[i] != aop2->aopu.aop_reg[i])
902 /*-----------------------------------------------------------------*/
903 /* aopOp - allocates an asmop for an operand : */
904 /*-----------------------------------------------------------------*/
906 aopOp (operand * op, iCode * ic, bool result)
915 /* if this a literal */
916 if (IS_OP_LITERAL (op))
918 op->aop = aop = newAsmop (AOP_LIT);
919 aop->aopu.aop_lit = op->operand.valOperand;
920 aop->size = getSize (operandType (op));
924 /* if already has a asmop then continue */
927 op->aop->allocated++;
931 /* if the underlying symbol has a aop */
932 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
934 op->aop = OP_SYMBOL (op)->aop;
935 op->aop->allocated++;
939 /* if this is a true symbol */
940 if (IS_TRUE_SYMOP (op))
942 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
946 /* this is a temporary : this has
952 e) can be a return use only */
954 sym = OP_SYMBOL (op);
956 /* if the type is a conditional */
957 if (sym->regType == REG_CND)
959 sym->aop = op->aop = aop = newAsmop (AOP_CRY);
960 aop->size = sym->ruonly ? 1 : 0;
964 /* if it is spilt then two situations
966 b) has a spill location */
967 if (sym->isspilt || sym->nRegs == 0)
970 /* rematerialize it NOW */
973 sym->aop = op->aop = aop = aopForRemat (sym);
974 aop->size = operandSize (op);
981 sym->aop = op->aop = aop = newAsmop (AOP_ACC);
982 aop->size = getSize (sym->type);
983 for (i = 0; i < 2; i++)
984 aop->aopu.aop_str[i] = accUse[i];
992 sym->aop = op->aop = aop = newAsmop (AOP_STR);
993 aop->size = getSize (sym->type);
994 for (i = 0; i < fReturnSizeMCS51; i++)
995 aop->aopu.aop_str[i] = fReturn[i];
999 if (sym->usl.spillLoc)
1001 asmop *oldAsmOp = NULL;
1003 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1005 /* force a new aop if sizes differ */
1006 oldAsmOp = sym->usl.spillLoc->aop;
1007 sym->usl.spillLoc->aop = NULL;
1009 sym->aop = op->aop = aop = aopForSym (ic, sym->usl.spillLoc, result);
1010 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1012 /* Don't reuse the new aop, go with the last one */
1013 sym->usl.spillLoc->aop = oldAsmOp;
1015 aop->size = getSize (sym->type);
1019 /* else must be a dummy iTemp */
1020 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1021 aop->size = getSize (sym->type);
1025 /* if the type is a bit register */
1026 if (sym->regType == REG_BIT)
1028 sym->aop = op->aop = aop = newAsmop (AOP_CRY);
1029 aop->size = sym->nRegs;//1???
1030 aop->aopu.aop_reg[0] = sym->regs[0];
1031 aop->aopu.aop_dir = sym->regs[0]->name;
1035 /* must be in a register */
1036 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1037 aop->size = sym->nRegs;
1038 for (i = 0; i < sym->nRegs; i++)
1039 aop->aopu.aop_reg[i] = sym->regs[i];
1042 /*-----------------------------------------------------------------*/
1043 /* freeAsmop - free up the asmop given to an operand */
1044 /*-----------------------------------------------------------------*/
1046 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1063 /* depending on the asmop type only three cases need work
1064 AOP_R0, AOP_R1 & AOP_STK */
1070 emitcode ("mov", "r0,b");
1073 else if (_G.r0Pushed)
1077 emitcode ("pop", "ar0");
1081 bitVectUnSetBit (ic->rUsed, R0_IDX);
1087 emitcode ("mov", "r1,b");
1090 else if (_G.r1Pushed)
1094 emitcode ("pop", "ar1");
1098 bitVectUnSetBit (ic->rUsed, R1_IDX);
1104 int stk = aop->aopu.aop_stk + aop->size - 1;
1105 bitVectUnSetBit (ic->rUsed, R0_IDX);
1106 bitVectUnSetBit (ic->rUsed, R1_IDX);
1108 getFreePtr (ic, &aop, FALSE);
1112 emitcode ("mov", "a,_bp");
1113 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1114 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1118 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1123 emitcode ("pop", "acc");
1124 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1127 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1130 freeAsmop (op, NULL, ic, TRUE);
1133 emitcode ("pop", "ar1");
1138 emitcode ("pop", "ar0");
1146 /* all other cases just dealloc */
1152 OP_SYMBOL (op)->aop = NULL;
1153 /* if the symbol has a spill */
1155 SPIL_LOC (op)->aop = NULL;
1160 /*------------------------------------------------------------------*/
1161 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
1162 /* pop r0 or r1 off stack if pushed */
1163 /*------------------------------------------------------------------*/
1165 freeForBranchAsmop (operand * op)
1177 if (!aop->allocated)
1185 emitcode ("mov", "r0,b");
1187 else if (_G.r0Pushed)
1189 emitcode ("pop", "ar0");
1196 emitcode ("mov", "r1,b");
1198 else if (_G.r1Pushed)
1200 emitcode ("pop", "ar1");
1207 int stk = aop->aopu.aop_stk + aop->size - 1;
1209 emitcode ("mov", "b,r0");
1212 emitcode ("mov", "a,_bp");
1213 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1214 emitcode ("mov", "r0,a");
1218 emitcode ("mov", "r0,_bp");
1223 emitcode ("pop", "acc");
1224 emitcode ("mov", "@r0,a");
1227 emitcode ("dec", "r0");
1229 emitcode ("mov", "r0,b");
1235 /*-----------------------------------------------------------------*/
1236 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
1237 /* clobber the accumulator */
1238 /*-----------------------------------------------------------------*/
1240 aopGetUsesAcc (operand * oper, int offset)
1242 asmop * aop = AOP (oper);
1244 if (offset > (aop->size - 1))
1262 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1273 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1279 /* Error case --- will have been caught already */
1285 /*-------------------------------------------------------------------*/
1286 /* aopGet - for fetching value of the aop */
1287 /*-------------------------------------------------------------------*/
1289 aopGet (operand * oper, int offset, bool bit16, bool dname)
1291 asmop * aop = AOP (oper);
1293 /* offset is greater than
1295 if (offset > (aop->size - 1) &&
1296 aop->type != AOP_LIT)
1299 /* depending on type */
1307 /* if we need to increment it */
1308 while (offset > aop->coff)
1310 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1314 while (offset < aop->coff)
1316 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1323 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1324 return (dname ? "acc" : "a");
1326 SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1327 return Safe_strdup(buffer);
1330 if (aop->code && aop->coff==0 && offset>=1) {
1331 emitcode ("mov", "a,#0x%02x", offset);
1332 emitcode ("movc", "a,@a+dptr");
1333 return (dname ? "acc" : "a");
1336 while (offset > aop->coff)
1338 emitcode ("inc", "dptr");
1342 while (offset < aop->coff)
1344 emitcode ("lcall", "__decdptr");
1351 emitcode ("clr", "a");
1352 emitcode ("movc", "a,@a+dptr");
1356 emitcode ("movx", "a,@dptr");
1358 return (dname ? "acc" : "a");
1361 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1363 SNPRINTF(buffer, sizeof(buffer),
1364 "%s",aop->aopu.aop_immd.aop_immd2);
1368 SNPRINTF(buffer, sizeof(buffer),
1369 "#%s", aop->aopu.aop_immd.aop_immd1);
1373 SNPRINTF (buffer, sizeof(buffer),
1375 aop->aopu.aop_immd.aop_immd1,
1380 SNPRINTF (buffer, sizeof(buffer),
1382 aop->aopu.aop_immd.aop_immd1);
1384 return Safe_strdup(buffer);
1387 if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
1389 SNPRINTF (buffer, sizeof(buffer),
1391 aop->aopu.aop_dir, offset * 8);
1395 SNPRINTF (buffer, sizeof(buffer),
1402 SNPRINTF (buffer, sizeof(buffer),
1407 return Safe_strdup(buffer);
1411 return aop->aopu.aop_reg[offset]->dname;
1413 return aop->aopu.aop_reg[offset]->name;
1416 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1417 emitcode ("clr", "a");
1418 emitcode ("rlc", "a");
1419 return (dname ? "acc" : "a");
1422 if (!offset && dname)
1424 return aop->aopu.aop_str[offset];
1427 return aopLiteral (aop->aopu.aop_lit, offset);
1431 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1435 return aop->aopu.aop_str[offset];
1439 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1440 "aopget got unsupported aop->type");
1444 /*-----------------------------------------------------------------*/
1445 /* aopPutUsesAcc - indicates ahead of time whether aopPut() will */
1446 /* clobber the accumulator */
1447 /*-----------------------------------------------------------------*/
1449 aopPutUsesAcc (operand * oper, const char *s, int offset)
1451 asmop * aop = AOP (oper);
1453 if (offset > (aop->size - 1))
1463 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1469 return ((aop->paged) || (*s == '@'));
1473 return (!aop->aopu.aop_dir || strcmp(s, aop->aopu.aop_dir));
1481 /* Error case --- will have been caught already */
1487 /*-----------------------------------------------------------------*/
1488 /* aopPut - puts a string for a aop and indicates if acc is in use */
1489 /*-----------------------------------------------------------------*/
1491 aopPut (operand * result, const char *s, int offset)
1493 bool bvolatile = isOperandVolatile (result, FALSE);
1494 bool accuse = FALSE;
1495 asmop * aop = AOP (result);
1496 const char *d = NULL;
1498 if (aop->size && offset > (aop->size - 1))
1500 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1501 "aopPut got offset > aop->size");
1505 /* will assign value to value */
1506 /* depending on where it is ofcourse */
1510 MOVA (s); /* read s in case it was volatile */
1515 if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1517 SNPRINTF (buffer, sizeof(buffer),
1519 aop->aopu.aop_dir, offset * 8);
1523 SNPRINTF (buffer, sizeof(buffer),
1525 aop->aopu.aop_dir, offset);
1529 SNPRINTF (buffer, sizeof(buffer),
1534 if (strcmp (buffer, s) || bvolatile)
1536 emitcode ("mov", "%s,%s", buffer, s);
1538 if (!strcmp (buffer, "acc"))
1545 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1546 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1549 strcmp (s, "r0") == 0 ||
1550 strcmp (s, "r1") == 0 ||
1551 strcmp (s, "r2") == 0 ||
1552 strcmp (s, "r3") == 0 ||
1553 strcmp (s, "r4") == 0 ||
1554 strcmp (s, "r5") == 0 ||
1555 strcmp (s, "r6") == 0 ||
1556 strcmp (s, "r7") == 0)
1558 emitcode ("mov", "%s,%s",
1559 aop->aopu.aop_reg[offset]->dname, s);
1563 emitcode ("mov", "%s,%s",
1564 aop->aopu.aop_reg[offset]->name, s);
1572 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1573 "aopPut writing to code space");
1577 while (offset > aop->coff)
1580 emitcode ("inc", "dptr");
1583 while (offset < aop->coff)
1586 emitcode ("lcall", "__decdptr");
1591 /* if not in accumulator */
1594 emitcode ("movx", "@dptr,a");
1599 while (offset > aop->coff)
1602 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1604 while (offset < aop->coff)
1607 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1614 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1619 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1621 else if (strcmp (s, "r0") == 0 ||
1622 strcmp (s, "r1") == 0 ||
1623 strcmp (s, "r2") == 0 ||
1624 strcmp (s, "r3") == 0 ||
1625 strcmp (s, "r4") == 0 ||
1626 strcmp (s, "r5") == 0 ||
1627 strcmp (s, "r6") == 0 ||
1628 strcmp (s, "r7") == 0)
1631 SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1632 emitcode ("mov", "@%s,%s",
1633 aop->aopu.aop_ptr->name, buffer);
1637 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1642 if (strcmp (s, "a") == 0)
1644 emitcode ("push", "acc");
1649 emitcode ("push", "acc");
1651 else if (strcmp (s, "r0") == 0 ||
1652 strcmp (s, "r1") == 0 ||
1653 strcmp (s, "r2") == 0 ||
1654 strcmp (s, "r3") == 0 ||
1655 strcmp (s, "r4") == 0 ||
1656 strcmp (s, "r5") == 0 ||
1657 strcmp (s, "r6") == 0 ||
1658 strcmp (s, "r7") == 0)
1661 SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1662 emitcode ("push", buffer);
1666 emitcode ("push", s);
1672 // destination is carry for return-use-only
1673 d = (IS_OP_RUONLY (result)) ? "c" : aop->aopu.aop_dir;
1674 // source is no literal and not in carry
1675 if ((s != zero) && (s != one) && strcmp (s, "c"))
1678 /* set C, if a >= 1 */
1679 emitcode ("add", "a,#0xff");
1682 // now source is zero, one or carry
1684 /* if result no bit variable */
1687 if (!strcmp (s, "c"))
1689 /* inefficient: move carry into A and use jz/jnz */
1690 emitcode ("clr", "a");
1691 emitcode ("rlc", "a");
1701 emitcode ("clr", "%s", d);
1703 emitcode ("setb", "%s", d);
1704 else if (strcmp (s, d))
1705 emitcode ("mov", "%s,c", d);
1710 if (strcmp (aop->aopu.aop_str[offset], s) || bvolatile)
1711 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1717 if (!offset && (strcmp (s, "acc") == 0) && !bvolatile)
1720 if (strcmp (aop->aopu.aop_str[offset], s) && !bvolatile)
1721 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1725 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1726 "aopPut got unsupported aop->type");
1735 /*-----------------------------------------------------------------*/
1736 /* pointToEnd :- points to the last byte of the operand */
1737 /*-----------------------------------------------------------------*/
1739 pointToEnd (asmop * aop)
1745 aop->coff = count = (aop->size - 1);
1751 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1755 emitcode ("inc", "dptr");
1762 /*-----------------------------------------------------------------*/
1763 /* reAdjustPreg - points a register back to where it should */
1764 /*-----------------------------------------------------------------*/
1766 reAdjustPreg (asmop * aop)
1768 if ((aop->coff==0) || (aop->size <= 1))
1776 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1781 emitcode ("lcall", "__decdptr");
1788 /*-----------------------------------------------------------------*/
1789 /* opIsGptr: returns non-zero if the passed operand is */
1790 /* a generic pointer type. */
1791 /*-----------------------------------------------------------------*/
1793 opIsGptr (operand * op)
1795 if (op && IS_GENPTR (operandType (op)) && (AOP_SIZE (op) == GPTRSIZE))
1802 /*-----------------------------------------------------------------*/
1803 /* getDataSize - get the operand data size */
1804 /*-----------------------------------------------------------------*/
1806 getDataSize (operand * op)
1808 int size = AOP_SIZE (op);
1810 if (size == GPTRSIZE)
1812 sym_link *type = operandType (op);
1813 if (IS_GENPTR (type))
1815 /* generic pointer; arithmetic operations
1816 * should ignore the high byte (pointer type).
1824 /*-----------------------------------------------------------------*/
1825 /* outAcc - output Acc */
1826 /*-----------------------------------------------------------------*/
1828 outAcc (operand * result)
1831 size = getDataSize (result);
1834 aopPut (result, "a", 0);
1837 /* unsigned or positive */
1840 aopPut (result, zero, offset++);
1845 /*-----------------------------------------------------------------*/
1846 /* outBitC - output a bit C */
1847 /*-----------------------------------------------------------------*/
1849 outBitC (operand * result)
1851 /* if the result is bit */
1852 if (AOP_TYPE (result) == AOP_CRY)
1854 if (!IS_OP_RUONLY (result))
1855 aopPut (result, "c", 0);
1857 else if (AOP_TYPE (result) != AOP_DUMMY)
1859 emitcode ("clr", "a");
1860 emitcode ("rlc", "a");
1865 /*-----------------------------------------------------------------*/
1866 /* toBoolean - emit code for orl a,operator(sizeop) */
1867 /*-----------------------------------------------------------------*/
1869 toBoolean (operand * oper)
1871 int size = AOP_SIZE (oper) - 1;
1873 bool AccUsed = FALSE;
1876 while (!AccUsed && size--)
1878 AccUsed |= aopGetUsesAcc(oper, offset++);
1881 size = AOP_SIZE (oper) - 1;
1883 MOVA (aopGet (oper, 0, FALSE, FALSE));
1884 if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1887 emitcode("mov", "b,a");
1890 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1891 emitcode ("orl", "b,a");
1893 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1894 emitcode ("orl", "a,b");
1901 emitcode ("orl", "a,%s",
1902 aopGet (oper, offset++, FALSE, FALSE));
1907 /*-----------------------------------------------------------------*/
1908 /* toCarry - make boolean and move into carry */
1909 /*-----------------------------------------------------------------*/
1911 toCarry (operand * oper)
1913 /* if the operand is a literal then
1914 we know what the value is */
1915 if (AOP_TYPE (oper) == AOP_LIT)
1917 if ((int) operandLitValue (oper))
1922 else if (AOP_TYPE (oper) == AOP_CRY)
1924 emitcode ("mov", "c,%s", oper->aop->aopu.aop_dir);
1928 /* or the operand into a */
1930 /* set C, if a >= 1 */
1931 emitcode ("add", "a,#0xff");
1935 /*-----------------------------------------------------------------*/
1936 /* assignBit - assign operand to bit operand */
1937 /*-----------------------------------------------------------------*/
1939 assignBit (operand * result, operand * right)
1941 /* if the right side is a literal then
1942 we know what the value is */
1943 if (AOP_TYPE (right) == AOP_LIT)
1945 if ((int) operandLitValue (right))
1946 aopPut (result, one, 0);
1948 aopPut (result, zero, 0);
1953 aopPut (result, "c", 0);
1958 /*-------------------------------------------------------------------*/
1959 /* xch_a_aopGet - for exchanging acc with value of the aop */
1960 /*-------------------------------------------------------------------*/
1962 xch_a_aopGet (operand * oper, int offset, bool bit16, bool dname)
1966 if (aopGetUsesAcc (oper, offset))
1968 emitcode("mov", "b,a");
1969 MOVA (aopGet (oper, offset, bit16, dname));
1970 emitcode("xch", "a,b");
1971 aopPut (oper, "a", offset);
1972 emitcode("xch", "a,b");
1977 l = aopGet (oper, offset, bit16, dname);
1978 emitcode("xch", "a,%s", l);
1984 /*-----------------------------------------------------------------*/
1985 /* genNot - generate code for ! operation */
1986 /*-----------------------------------------------------------------*/
1992 D (emitcode (";", "genNot"));
1994 /* assign asmOps to operand & result */
1995 aopOp (IC_LEFT (ic), ic, FALSE);
1996 aopOp (IC_RESULT (ic), ic, TRUE);
1998 /* if in bit space then a special case */
1999 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2001 /* if left==result then cpl bit */
2002 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2004 emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2008 toCarry (IC_LEFT (ic));
2009 emitcode ("cpl", "c");
2010 outBitC (IC_RESULT (ic));
2015 toBoolean (IC_LEFT (ic));
2017 /* set C, if a == 0 */
2018 tlbl = newiTempLabel (NULL);
2019 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
2021 outBitC (IC_RESULT (ic));
2024 /* release the aops */
2025 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2026 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2030 /*-----------------------------------------------------------------*/
2031 /* genCpl - generate code for complement */
2032 /*-----------------------------------------------------------------*/
2039 sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
2041 D(emitcode (";", "genCpl"));
2043 /* assign asmOps to operand & result */
2044 aopOp (IC_LEFT (ic), ic, FALSE);
2045 aopOp (IC_RESULT (ic), ic, TRUE);
2047 /* special case if in bit space */
2048 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2052 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
2053 (SPEC_USIGN (letype) && IS_CHAR (letype)))
2055 /* promotion rules are responsible for this strange result:
2056 bit -> int -> ~int -> bit
2057 uchar -> int -> ~int -> bit
2059 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
2063 tlbl=newiTempLabel(NULL);
2064 l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
2065 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
2066 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
2067 IS_AOP_PREG (IC_LEFT (ic)))
2069 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
2074 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
2077 outBitC (IC_RESULT(ic));
2081 size = AOP_SIZE (IC_RESULT (ic));
2084 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2086 emitcode ("cpl", "a");
2087 aopPut (IC_RESULT (ic), "a", offset++);
2092 /* release the aops */
2093 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2094 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2097 /*-----------------------------------------------------------------*/
2098 /* genUminusFloat - unary minus for floating points */
2099 /*-----------------------------------------------------------------*/
2101 genUminusFloat (operand * op, operand * result)
2103 int size, offset = 0;
2106 D (emitcode (";", "genUminusFloat"));
2108 /* for this we just copy and then flip the bit */
2110 size = AOP_SIZE (op) - 1;
2115 aopGet (op, offset, FALSE, FALSE),
2120 l = aopGet (op, offset, FALSE, FALSE);
2123 emitcode ("cpl", "acc.7");
2124 aopPut (result, "a", offset);
2127 /*-----------------------------------------------------------------*/
2128 /* genUminus - unary minus code generation */
2129 /*-----------------------------------------------------------------*/
2131 genUminus (iCode * ic)
2136 D (emitcode (";", "genUminus"));
2139 aopOp (IC_LEFT (ic), ic, FALSE);
2140 aopOp (IC_RESULT (ic), ic, TRUE);
2142 /* if both in bit space then special
2144 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2145 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2148 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2149 emitcode ("cpl", "c");
2150 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2154 optype = operandType (IC_LEFT (ic));
2156 /* if float then do float stuff */
2157 if (IS_FLOAT (optype))
2159 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2163 /* otherwise subtract from zero */
2164 size = AOP_SIZE (IC_LEFT (ic));
2168 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2169 if (!strcmp (l, "a"))
2173 emitcode ("cpl", "a");
2174 emitcode ("addc", "a,#0x00");
2180 emitcode ("clr", "a");
2181 emitcode ("subb", "a,%s", l);
2183 aopPut (IC_RESULT (ic), "a", offset++);
2186 /* if any remaining bytes in the result */
2187 /* we just need to propagate the sign */
2188 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2190 emitcode ("rlc", "a");
2191 emitcode ("subb", "a,acc");
2193 aopPut (IC_RESULT (ic), "a", offset++);
2197 /* release the aops */
2198 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2199 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2202 /*-----------------------------------------------------------------*/
2203 /* saveRegisters - will look for a call and save the registers */
2204 /*-----------------------------------------------------------------*/
2206 saveRegisters (iCode * lic)
2213 for (ic = lic; ic; ic = ic->next)
2214 if (ic->op == CALL || ic->op == PCALL)
2219 fprintf (stderr, "found parameter push with no function call\n");
2223 /* if the registers have been saved already or don't need to be then
2227 if (IS_SYMOP(IC_LEFT(ic)) &&
2228 (IFFUNC_CALLEESAVES (OP_SYMBOL (IC_LEFT (ic))->type) ||
2229 IFFUNC_ISNAKED (OP_SYM_TYPE (IC_LEFT (ic)))))
2232 /* save the registers in use at this time but skip the
2233 ones for the result */
2234 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2235 mcs51_rUmaskForOp (IC_RESULT(ic)));
2238 if (options.useXstack)
2240 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2241 int nBits = bitVectnBitsOn (rsavebits);
2242 int count = bitVectnBitsOn (rsave);
2246 count = count - nBits + 1;
2247 /* remove all but the first bits as they are pushed all at once */
2248 rsave = bitVectCplAnd (rsave, rsavebits);
2249 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2251 freeBitVect (rsavebits);
2255 regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2256 if (reg->type == REG_BIT)
2258 emitcode ("mov", "a,%s", reg->base);
2262 emitcode ("mov", "a,%s", reg->name);
2264 emitcode ("mov", "r0,%s", spname);
2265 emitcode ("inc", "%s", spname);// allocate before use
2266 emitcode ("movx", "@r0,a");
2267 if (bitVectBitValue (rsave, R0_IDX))
2268 emitcode ("mov", "r0,a");
2270 else if (count != 0)
2272 if (bitVectBitValue (rsave, R0_IDX))
2274 emitcode ("push", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2276 emitcode ("mov", "r0,%s", spname);
2278 emitcode ("add", "a,#0x%02x", count);
2279 emitcode ("mov", "%s,a", spname);
2280 for (i = 0; i < mcs51_nRegs; i++)
2282 if (bitVectBitValue (rsave, i))
2284 regs * reg = REG_WITH_INDEX (i);
2287 emitcode ("pop", "acc");
2288 emitcode ("push", "acc");
2290 else if (reg->type == REG_BIT)
2292 emitcode ("mov", "a,%s", reg->base);
2296 emitcode ("mov", "a,%s", reg->name);
2298 emitcode ("movx", "@r0,a");
2301 emitcode ("inc", "r0");
2305 if (bitVectBitValue (rsave, R0_IDX))
2307 emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2313 bool bits_pushed = FALSE;
2314 for (i = 0; i < mcs51_nRegs; i++)
2316 if (bitVectBitValue (rsave, i))
2318 bits_pushed = pushReg (i, bits_pushed);
2322 freeBitVect (rsave);
2325 /*-----------------------------------------------------------------*/
2326 /* unsaveRegisters - pop the pushed registers */
2327 /*-----------------------------------------------------------------*/
2329 unsaveRegisters (iCode * ic)
2334 /* restore the registers in use at this time but skip the
2335 ones for the result */
2336 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2337 mcs51_rUmaskForOp (IC_RESULT(ic)));
2339 if (options.useXstack)
2341 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2342 int nBits = bitVectnBitsOn (rsavebits);
2343 int count = bitVectnBitsOn (rsave);
2347 count = count - nBits + 1;
2348 /* remove all but the first bits as they are popped all at once */
2349 rsave = bitVectCplAnd (rsave, rsavebits);
2350 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2352 freeBitVect (rsavebits);
2356 regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2357 emitcode ("mov", "r0,%s", spname);
2358 emitcode ("dec", "r0");
2359 emitcode ("movx", "a,@r0");
2360 if (reg->type == REG_BIT)
2362 emitcode ("mov", "%s,a", reg->base);
2366 emitcode ("mov", "%s,a", reg->name);
2368 emitcode ("dec", "%s", spname);
2370 else if (count != 0)
2372 emitcode ("mov", "r0,%s", spname);
2373 for (i = mcs51_nRegs; i >= 0; i--)
2375 if (bitVectBitValue (rsave, i))
2377 regs * reg = REG_WITH_INDEX (i);
2378 emitcode ("dec", "r0");
2379 emitcode ("movx", "a,@r0");
2382 emitcode ("push", "acc");
2384 else if (reg->type == REG_BIT)
2386 emitcode ("mov", "%s,a", reg->base);
2390 emitcode ("mov", "%s,a", reg->name);
2394 emitcode ("mov", "%s,r0", spname);
2395 if (bitVectBitValue (rsave, R0_IDX))
2397 emitcode ("pop", "ar0");
2403 bool bits_popped = FALSE;
2404 for (i = mcs51_nRegs; i >= 0; i--)
2406 if (bitVectBitValue (rsave, i))
2408 bits_popped = popReg (i, bits_popped);
2412 freeBitVect (rsave);
2416 /*-----------------------------------------------------------------*/
2418 /*-----------------------------------------------------------------*/
2420 pushSide (operand * oper, int size, iCode * ic)
2423 int nPushed = _G.r0Pushed + _G.r1Pushed;
2425 aopOp (oper, ic, FALSE);
2427 if (nPushed != _G.r0Pushed + _G.r1Pushed)
2429 while (offset < size)
2431 char *l = aopGet (oper, offset, FALSE, TRUE);
2432 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2434 freeAsmop (oper, NULL, ic, TRUE);
2436 while (offset < size)
2438 emitcode ("push", "%s", fReturn[offset++]);
2445 char *l = aopGet (oper, offset++, FALSE, TRUE);
2446 if (AOP_TYPE (oper) != AOP_REG &&
2447 AOP_TYPE (oper) != AOP_DIR &&
2451 emitcode ("push", "acc");
2455 emitcode ("push", "%s", l);
2459 freeAsmop (oper, NULL, ic, TRUE);
2462 /*-----------------------------------------------------------------*/
2463 /* assignResultValue - also indicates if acc is in use afterwards */
2464 /*-----------------------------------------------------------------*/
2466 assignResultValue (operand * oper, operand * func)
2469 int size = AOP_SIZE (oper);
2470 bool accuse = FALSE;
2471 bool pushedA = FALSE;
2473 if (func && IS_BIT (OP_SYM_ETYPE (func)))
2479 if ((size > 3) && aopPutUsesAcc (oper, fReturn[offset], offset))
2481 emitcode ("push", "acc");
2486 if ((offset == 3) && pushedA)
2487 emitcode ("pop", "acc");
2488 accuse |= aopPut (oper, fReturn[offset], offset);
2495 /*-----------------------------------------------------------------*/
2496 /* genXpush - pushes onto the external stack */
2497 /*-----------------------------------------------------------------*/
2499 genXpush (iCode * ic)
2501 asmop *aop = newAsmop (0);
2503 int size, offset = 0;
2505 D (emitcode (";", "genXpush"));
2507 aopOp (IC_LEFT (ic), ic, FALSE);
2508 r = getFreePtr (ic, &aop, FALSE);
2510 size = AOP_SIZE (IC_LEFT (ic));
2514 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2515 emitcode ("mov", "%s,%s", r->name, spname);
2516 emitcode ("inc", "%s", spname); // allocate space first
2517 emitcode ("movx", "@%s,a", r->name);
2521 // allocate space first
2522 emitcode ("mov", "%s,%s", r->name, spname);
2524 emitcode ("add", "a,#0x%02x", size);
2525 emitcode ("mov", "%s,a", spname);
2529 MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2530 emitcode ("movx", "@%s,a", r->name);
2531 emitcode ("inc", "%s", r->name);
2535 freeAsmop (NULL, aop, ic, TRUE);
2536 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2539 /*-----------------------------------------------------------------*/
2540 /* genIpush - generate code for pushing this gets a little complex */
2541 /*-----------------------------------------------------------------*/
2543 genIpush (iCode * ic)
2545 int size, offset = 0;
2549 D (emitcode (";", "genIpush"));
2551 /* if this is not a parm push : ie. it is spill push
2552 and spill push is always done on the local stack */
2556 /* and the item is spilt then do nothing */
2557 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2560 aopOp (IC_LEFT (ic), ic, FALSE);
2561 size = AOP_SIZE (IC_LEFT (ic));
2562 /* push it on the stack */
2565 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2571 emitcode ("push", "%s", l);
2576 /* this is a parameter push: in this case we call
2577 the routine to find the call and save those
2578 registers that need to be saved */
2581 /* if use external stack then call the external
2582 stack pushing routine */
2583 if (options.useXstack)
2589 /* then do the push */
2590 aopOp (IC_LEFT (ic), ic, FALSE);
2592 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2593 size = AOP_SIZE (IC_LEFT (ic));
2597 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2598 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2599 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR)
2601 if (strcmp (l, prev) || *l == '@')
2603 emitcode ("push", "acc");
2607 emitcode ("push", "%s", l);
2612 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2615 /*-----------------------------------------------------------------*/
2616 /* genIpop - recover the registers: can happen only for spilling */
2617 /*-----------------------------------------------------------------*/
2619 genIpop (iCode * ic)
2623 D (emitcode (";", "genIpop"));
2625 /* if the temp was not pushed then */
2626 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2629 aopOp (IC_LEFT (ic), ic, FALSE);
2630 size = AOP_SIZE (IC_LEFT (ic));
2631 offset = (size - 1);
2634 emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2638 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2641 /*-----------------------------------------------------------------*/
2642 /* saveRBank - saves an entire register bank on the stack */
2643 /*-----------------------------------------------------------------*/
2645 saveRBank (int bank, iCode * ic, bool pushPsw)
2648 int count = 8 + (pushPsw ? 1 : 0);
2652 if (options.useXstack)
2656 /* Assume r0 is available for use. */
2657 r = REG_WITH_INDEX (R0_IDX);
2662 r = getFreePtr (ic, &aop, FALSE);
2664 // allocate space first
2665 emitcode ("mov", "%s,%s", r->name, spname);
2667 emitcode ("add", "a,#0x%02x", count);
2668 emitcode ("mov", "%s,a", spname);
2671 for (i = 0; i < 8; i++)
2673 if (options.useXstack)
2675 emitcode ("mov", "a,(%s+%d)",
2676 regs8051[i].base, 8 * bank + regs8051[i].offset);
2677 emitcode ("movx", "@%s,a", r->name);
2679 emitcode ("inc", "%s", r->name);
2682 emitcode ("push", "(%s+%d)",
2683 regs8051[i].base, 8 * bank + regs8051[i].offset);
2688 if (options.useXstack)
2690 emitcode ("mov", "a,psw");
2691 emitcode ("movx", "@%s,a", r->name);
2695 emitcode ("push", "psw");
2698 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2703 freeAsmop (NULL, aop, ic, TRUE);
2712 /*-----------------------------------------------------------------*/
2713 /* unsaveRBank - restores the register bank from stack */
2714 /*-----------------------------------------------------------------*/
2716 unsaveRBank (int bank, iCode * ic, bool popPsw)
2722 if (options.useXstack)
2726 /* Assume r0 is available for use. */
2727 r = REG_WITH_INDEX (R0_IDX);;
2732 r = getFreePtr (ic, &aop, FALSE);
2734 emitcode ("mov", "%s,%s", r->name, spname);
2739 if (options.useXstack)
2741 emitcode ("dec", "%s", r->name);
2742 emitcode ("movx", "a,@%s", r->name);
2743 emitcode ("mov", "psw,a");
2747 emitcode ("pop", "psw");
2751 for (i = 7; i >= 0; i--)
2753 if (options.useXstack)
2755 emitcode ("dec", "%s", r->name);
2756 emitcode ("movx", "a,@%s", r->name);
2757 emitcode ("mov", "(%s+%d),a",
2758 regs8051[i].base, 8 * bank + regs8051[i].offset);
2762 emitcode ("pop", "(%s+%d)",
2763 regs8051[i].base, 8 * bank + regs8051[i].offset);
2767 if (options.useXstack)
2769 emitcode ("mov", "%s,%s", spname, r->name);
2774 freeAsmop (NULL, aop, ic, TRUE);
2778 /*-----------------------------------------------------------------*/
2779 /* genSend - gen code for SEND */
2780 /*-----------------------------------------------------------------*/
2781 static void genSend(set *sendSet)
2786 /* first we do all bit parameters */
2787 for (sic = setFirstItem (sendSet); sic;
2788 sic = setNextItem (sendSet))
2790 if (sic->argreg > 12)
2792 int bit = sic->argreg-13;
2794 aopOp (IC_LEFT (sic), sic, FALSE);
2796 /* if left is a literal then
2797 we know what the value is */
2798 if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2800 if (((int) operandLitValue (IC_LEFT (sic))))
2801 emitcode ("setb", "b[%d]", bit);
2803 emitcode ("clr", "b[%d]", bit);
2808 toCarry (IC_LEFT (sic));
2809 emitcode ("mov", "b[%d],c", bit);
2814 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2820 saveRegisters (setFirstItem (sendSet));
2821 emitcode ("mov", "bits,b");
2824 /* then we do all other parameters */
2825 for (sic = setFirstItem (sendSet); sic;
2826 sic = setNextItem (sendSet))
2828 if (sic->argreg <= 12)
2830 int size, offset = 0;
2831 aopOp (IC_LEFT (sic), sic, FALSE);
2832 size = AOP_SIZE (IC_LEFT (sic));
2834 if (sic->argreg == 1)
2838 char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2839 if (strcmp (l, fReturn[offset]))
2841 emitcode ("mov", "%s,%s", fReturn[offset], l);
2850 emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2851 aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2855 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2860 /*-----------------------------------------------------------------*/
2861 /* selectRegBank - emit code to select the register bank */
2862 /*-----------------------------------------------------------------*/
2864 selectRegBank (short bank, bool keepFlags)
2866 /* if f.e. result is in carry */
2869 emitcode ("anl", "psw,#0xE7");
2871 emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2875 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2879 /*-----------------------------------------------------------------*/
2880 /* genCall - generates a call statement */
2881 /*-----------------------------------------------------------------*/
2883 genCall (iCode * ic)
2887 // bool restoreBank = FALSE;
2888 bool swapBanks = FALSE;
2889 bool accuse = FALSE;
2890 bool accPushed = FALSE;
2891 bool resultInF0 = FALSE;
2892 bool assignResultGenerated = FALSE;
2894 D (emitcode (";", "genCall"));
2896 dtype = operandType (IC_LEFT (ic));
2897 etype = getSpec(dtype);
2898 /* if send set is not empty then assign */
2901 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2902 genSend(reverseSet(_G.sendSet));
2904 genSend(_G.sendSet);
2909 /* if we are calling a not _naked function that is not using
2910 the same register bank then we need to save the
2911 destination registers on the stack */
2912 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2913 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2914 !IFFUNC_ISISR (dtype))
2919 /* if caller saves & we have not saved then */
2925 emitcode ("mov", "psw,#0x%02x",
2926 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2930 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2932 if (IFFUNC_CALLEESAVES(dtype))
2934 werror (E_BANKED_WITH_CALLEESAVES);
2938 char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2939 OP_SYMBOL (IC_LEFT (ic))->rname :
2940 OP_SYMBOL (IC_LEFT (ic))->name);
2942 emitcode ("mov", "r0,#%s", l);
2943 emitcode ("mov", "r1,#(%s >> 8)", l);
2944 emitcode ("mov", "r2,#(%s >> 16)", l);
2945 emitcode ("lcall", "__sdcc_banked_call");
2950 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2951 OP_SYMBOL (IC_LEFT (ic))->rname :
2952 OP_SYMBOL (IC_LEFT (ic))->name));
2957 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2960 /* if we need assign a result value */
2961 if ((IS_ITEMP (IC_RESULT (ic)) &&
2962 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2963 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2964 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2965 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2966 IS_TRUE_SYMOP (IC_RESULT (ic)))
2970 aopOp (IC_RESULT (ic), ic, FALSE);
2973 accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2974 assignResultGenerated = TRUE;
2976 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2979 /* adjust the stack for parameters if required */
2983 if (ic->parmBytes > 3)
2987 emitcode ("push", "acc");
2990 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2991 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2992 !assignResultGenerated)
2994 emitcode ("mov", "F0,c");
2998 emitcode ("mov", "a,%s", spname);
2999 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3000 emitcode ("mov", "%s,a", spname);
3002 /* unsaveRegisters from xstack needs acc, but */
3003 /* unsaveRegisters from stack needs this popped */
3004 if (accPushed && !options.useXstack)
3006 emitcode ("pop", "acc");
3011 for (i = 0; i < ic->parmBytes; i++)
3012 emitcode ("dec", "%s", spname);
3015 /* if we had saved some registers then unsave them */
3016 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3018 if (accuse && !accPushed && options.useXstack)
3020 /* xstack needs acc, but doesn't touch normal stack */
3021 emitcode ("push", "acc");
3024 unsaveRegisters (ic);
3027 // /* if register bank was saved then pop them */
3029 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
3031 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
3034 emitcode ("mov", "c,F0");
3036 aopOp (IC_RESULT (ic), ic, FALSE);
3037 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3038 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3042 emitcode ("pop", "acc");
3045 /*-----------------------------------------------------------------*/
3046 /* genPcall - generates a call by pointer statement */
3047 /*-----------------------------------------------------------------*/
3049 genPcall (iCode * ic)
3053 symbol *rlbl = newiTempLabel (NULL);
3054 // bool restoreBank=FALSE;
3055 bool swapBanks = FALSE;
3056 bool resultInF0 = FALSE;
3058 D (emitcode (";", "genPcall"));
3060 dtype = operandType (IC_LEFT (ic))->next;
3061 etype = getSpec(dtype);
3062 /* if caller saves & we have not saved then */
3066 /* if we are calling a not _naked function that is not using
3067 the same register bank then we need to save the
3068 destination registers on the stack */
3069 if (currFunc && dtype && !IFFUNC_ISNAKED (dtype) &&
3070 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
3071 !IFFUNC_ISISR (dtype))
3073 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3074 // restoreBank=TRUE;
3076 // need caution message to user here
3079 if (IS_LITERAL (etype))
3081 /* if send set is not empty then assign */
3084 genSend(reverseSet(_G.sendSet));
3090 emitcode ("mov", "psw,#0x%02x",
3091 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3094 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT (getSpec(dtype)))
3096 if (IFFUNC_CALLEESAVES (dtype))
3098 werror (E_BANKED_WITH_CALLEESAVES);
3102 char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
3104 emitcode ("mov", "r0,#%s", l);
3105 emitcode ("mov", "r1,#(%s >> 8)", l);
3106 emitcode ("mov", "r2,#(%s >> 16)", l);
3107 emitcode ("lcall", "__sdcc_banked_call");
3112 emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
3117 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT (getSpec(dtype)))
3119 if (IFFUNC_CALLEESAVES (dtype))
3121 werror (E_BANKED_WITH_CALLEESAVES);
3125 aopOp (IC_LEFT (ic), ic, FALSE);
3129 /* what if aopGet needs r0 or r1 ??? */
3130 emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3131 emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3132 emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3136 int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
3137 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3138 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3139 emitcode ("mov", "0x%02x,%s", reg, aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3142 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3144 /* if send set is not empty then assign */
3147 genSend(reverseSet(_G.sendSet));
3153 emitcode ("mov", "psw,#0x%02x",
3154 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3158 emitcode ("lcall", "__sdcc_banked_call");
3161 else if (_G.sendSet)
3163 /* push the return address on to the stack */
3164 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
3165 emitcode ("push", "acc");
3166 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
3167 emitcode ("push", "acc");
3169 /* now push the function address */
3170 pushSide (IC_LEFT (ic), FPTRSIZE, ic);
3172 /* if send set is not empty then assign */
3175 genSend(reverseSet(_G.sendSet));
3181 emitcode ("mov", "psw,#0x%02x",
3182 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3186 emitcode ("ret", "");
3189 else /* the send set is empty */
3192 /* now get the calling address into dptr */
3193 aopOp (IC_LEFT (ic), ic, FALSE);
3195 l = aopGet (IC_LEFT (ic), 0, FALSE, FALSE);
3196 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3198 emitcode ("mov", "r0,%s", l);
3199 l = aopGet (IC_LEFT (ic), 1, FALSE, FALSE);
3200 emitcode ("mov", "dph,%s", l);
3201 emitcode ("mov", "dpl,r0");
3205 emitcode ("mov", "dpl,%s", l);
3206 l = aopGet (IC_LEFT (ic), 1, FALSE, FALSE);
3207 emitcode ("mov", "dph,%s", l);
3210 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3214 emitcode ("mov", "psw,#0x%02x",
3215 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3219 emitcode ("lcall", "__sdcc_call_dptr");
3224 selectRegBank (FUNC_REGBANK (currFunc->type), IS_BIT (etype));
3227 /* if we need assign a result value */
3228 if ((IS_ITEMP (IC_RESULT (ic)) &&
3229 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3230 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3231 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3232 IS_TRUE_SYMOP (IC_RESULT (ic)))
3236 aopOp (IC_RESULT (ic), ic, FALSE);
3239 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3241 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3244 /* adjust the stack for parameters if required */
3248 if (ic->parmBytes > 3)
3250 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3251 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3253 emitcode ("mov", "F0,c");
3257 emitcode ("mov", "a,%s", spname);
3258 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3259 emitcode ("mov", "%s,a", spname);
3262 for (i = 0; i < ic->parmBytes; i++)
3263 emitcode ("dec", "%s", spname);
3266 // /* if register bank was saved then unsave them */
3268 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3270 /* if we had saved some registers then unsave them */
3271 if (ic->regsSaved && !IFFUNC_CALLEESAVES (dtype))
3272 unsaveRegisters (ic);
3274 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3277 emitcode ("mov", "c,F0");
3279 aopOp (IC_RESULT (ic), ic, FALSE);
3280 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3281 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3285 /*-----------------------------------------------------------------*/
3286 /* resultRemat - result is rematerializable */
3287 /*-----------------------------------------------------------------*/
3289 resultRemat (iCode * ic)
3291 if (SKIP_IC (ic) || ic->op == IFX)
3294 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3296 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3297 if (sym->remat && !POINTER_SET (ic))
3304 /*-----------------------------------------------------------------*/
3305 /* inExcludeList - return 1 if the string is in exclude Reg list */
3306 /*-----------------------------------------------------------------*/
3308 regsCmp(void *p1, void *p2)
3310 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3314 inExcludeList (char *s)
3316 const char *p = setFirstItem(options.excludeRegsSet);
3318 if (p == NULL || STRCASECMP(p, "none") == 0)
3322 return isinSetWith(options.excludeRegsSet, s, regsCmp);
3325 /*-----------------------------------------------------------------*/
3326 /* genFunction - generated code for function entry */
3327 /*-----------------------------------------------------------------*/
3329 genFunction (iCode * ic)
3331 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3333 bool switchedPSW = FALSE;
3334 int calleesaves_saved_register = -1;
3335 int stackAdjust = sym->stack;
3336 int accIsFree = sym->recvSize < 4;
3337 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3338 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3341 /* create the function header */
3342 emitcode (";", "-----------------------------------------");
3343 emitcode (";", " function %s", sym->name);
3344 emitcode (";", "-----------------------------------------");
3346 emitcode ("", "%s:", sym->rname);
3347 lineCurr->isLabel = 1;
3348 ftype = operandType (IC_LEFT (ic));
3349 _G.currentFunc = sym;
3351 if (IFFUNC_ISNAKED(ftype))
3353 emitcode(";", "naked function: no prologue.");
3357 /* here we need to generate the equates for the
3358 register bank if required */
3359 if (FUNC_REGBANK (ftype) != rbank)
3363 rbank = FUNC_REGBANK (ftype);
3364 for (i = 0; i < mcs51_nRegs; i++)
3366 if (regs8051[i].type != REG_BIT)
3368 if (strcmp (regs8051[i].base, "0") == 0)
3369 emitcode ("", "%s = 0x%02x",
3371 8 * rbank + regs8051[i].offset);
3373 emitcode ("", "%s = %s + 0x%02x",
3376 8 * rbank + regs8051[i].offset);
3381 /* if this is an interrupt service routine then
3382 save acc, b, dpl, dph */
3383 if (IFFUNC_ISISR (sym->type))
3387 rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), sym->regsUsed);
3388 if (IFFUNC_HASFCALL(sym->type) || !bitVectIsZero (rsavebits))
3390 emitcode ("push", "bits");
3393 freeBitVect (rsavebits);
3395 if (!inExcludeList ("acc"))
3396 emitcode ("push", "acc");
3397 if (!inExcludeList ("b"))
3398 emitcode ("push", "b");
3399 if (!inExcludeList ("dpl"))
3400 emitcode ("push", "dpl");
3401 if (!inExcludeList ("dph"))
3402 emitcode ("push", "dph");
3403 /* if this isr has no bank i.e. is going to
3404 run with bank 0 , then we need to save more
3406 if (!FUNC_REGBANK (sym->type))
3410 /* if this function does not call any other
3411 function then we can be economical and
3412 save only those registers that are used */
3413 if (!IFFUNC_HASFCALL(sym->type))
3415 /* if any registers used */
3418 /* save the registers used */
3419 for (i = 0; i < sym->regsUsed->size; i++)
3421 if (bitVectBitValue (sym->regsUsed, i))
3428 /* this function has a function call. We cannot
3429 determine register usage so we will have to push the
3431 saveRBank (0, ic, FALSE);
3432 if (options.parms_in_bank1) {
3433 for (i=0; i < 8 ; i++ ) {
3434 emitcode ("push","%s",rb1regs[i]);
3441 /* This ISR uses a non-zero bank.
3443 * We assume that the bank is available for our
3446 * However, if this ISR calls a function which uses some
3447 * other bank, we must save that bank entirely.
3449 unsigned long banksToSave = 0;
3451 if (IFFUNC_HASFCALL(sym->type))
3454 #define MAX_REGISTER_BANKS 4
3459 for (i = ic; i; i = i->next)
3461 if (i->op == ENDFUNCTION)
3463 /* we got to the end OK. */
3471 dtype = operandType (IC_LEFT(i));
3473 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3475 /* Mark this bank for saving. */
3476 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3478 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3482 banksToSave |= (1 << FUNC_REGBANK(dtype));
3485 /* And note that we don't need to do it in
3493 /* This is a mess; we have no idea what
3494 * register bank the called function might
3497 * The only thing I can think of to do is
3498 * throw a warning and hope.
3500 werror(W_FUNCPTR_IN_USING_ISR);
3504 if (banksToSave && options.useXstack)
3506 /* Since we aren't passing it an ic,
3507 * saveRBank will assume r0 is available to abuse.
3509 * So switch to our (trashable) bank now, so
3510 * the caller's R0 isn't trashed.
3512 emitcode ("push", "psw");
3513 emitcode ("mov", "psw,#0x%02x",
3514 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3518 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3520 if (banksToSave & (1 << ix))
3522 saveRBank(ix, NULL, FALSE);
3526 // TODO: this needs a closer look
3527 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3530 /* Set the register bank to the desired value if nothing else */
3531 /* has done so yet. */
3534 emitcode ("push", "psw");
3535 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3540 /* This is a non-ISR function. The caller has already switched register */
3541 /* banks, if necessary, so just handle the callee-saves option. */
3543 /* if callee-save to be used for this function
3544 then save the registers being used in this function */
3545 if (IFFUNC_CALLEESAVES(sym->type))
3549 /* if any registers used */
3552 bool bits_pushed = FALSE;
3553 /* save the registers used */
3554 for (i = 0; i < sym->regsUsed->size; i++)
3556 if (bitVectBitValue (sym->regsUsed, i))
3558 /* remember one saved register for later usage */
3559 if (calleesaves_saved_register < 0)
3560 calleesaves_saved_register = i;
3561 bits_pushed = pushReg (i, bits_pushed);
3571 if (options.useXstack)
3573 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3575 emitcode ("mov", "r0,%s", spname);
3576 emitcode ("inc", "%s", spname);
3577 emitcode ("xch", "a,_bpx");
3578 emitcode ("movx", "@r0,a");
3579 emitcode ("inc", "r0");
3580 emitcode ("mov", "a,r0");
3581 emitcode ("xch", "a,_bpx");
3585 emitcode ("push", "_bp"); /* save the callers stack */
3586 emitcode ("mov", "_bp,sp");
3591 if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3593 /* set up the stack */
3594 emitcode ("push", "_bp"); /* save the callers stack */
3595 emitcode ("mov", "_bp,sp");
3600 /* For some cases it is worthwhile to perform a RECEIVE iCode */
3601 /* before setting up the stack frame completely. */
3602 if (ric && ric->argreg == 1 && IC_RESULT (ric))
3604 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3608 if (rsym && rsym->regType == REG_CND)
3610 if (rsym && (rsym->accuse || rsym->ruonly))
3612 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3613 rsym = rsym->usl.spillLoc;
3616 /* If the RECEIVE operand immediately spills to the first entry on the */
3617 /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3618 /* rather than the usual @r0/r1 machinations. */
3619 if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3623 _G.current_iCode = ric;
3624 D(emitcode (";", "genReceive"));
3625 for (ofs=0; ofs < sym->recvSize; ofs++)
3627 if (!strcmp (fReturn[ofs], "a"))
3628 emitcode ("push", "acc");
3630 emitcode ("push", fReturn[ofs]);
3632 stackAdjust -= sym->recvSize;
3635 assert (stackAdjust>=0);
3638 _G.current_iCode = ic;
3642 /* If the RECEIVE operand is 4 registers, we can do the moves now */
3643 /* to free up the accumulator. */
3644 else if (rsym && rsym->nRegs && sym->recvSize == 4)
3648 _G.current_iCode = ric;
3649 D(emitcode (";", "genReceive"));
3650 for (ofs=0; ofs < sym->recvSize; ofs++)
3652 emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3654 _G.current_iCode = ic;
3660 /* adjust the stack for the function */
3663 int i = stackAdjust;
3665 werror (W_STACK_OVERFLOW, sym->name);
3667 if (i > 3 && accIsFree)
3669 emitcode ("mov", "a,sp");
3670 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3671 emitcode ("mov", "sp,a");
3675 /* The accumulator is not free, so we will need another register */
3676 /* to clobber. No need to worry about a possible conflict with */
3677 /* the above early RECEIVE optimizations since they would have */
3678 /* freed the accumulator if they were generated. */
3680 if (IFFUNC_CALLEESAVES(sym->type))
3682 /* if it's a callee-saves function we need a saved register */
3683 if (calleesaves_saved_register >= 0)
3685 emitcode ("mov", "%s,a", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3686 emitcode ("mov", "a,sp");
3687 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3688 emitcode ("mov", "sp,a");
3689 emitcode ("mov", "a,%s", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3692 /* do it the hard way */
3694 emitcode ("inc", "sp");
3698 /* not callee-saves, we can clobber r0 */
3699 emitcode ("mov", "r0,a");
3700 emitcode ("mov", "a,sp");
3701 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3702 emitcode ("mov", "sp,a");
3703 emitcode ("mov", "a,r0");
3708 emitcode ("inc", "sp");
3713 char i = ((char) sym->xstack & 0xff);
3715 if (i > 3 && accIsFree)
3717 emitcode ("mov", "a,_spx");
3718 emitcode ("add", "a,#0x%02x", i & 0xff);
3719 emitcode ("mov", "_spx,a");
3723 emitcode ("push", "acc");
3724 emitcode ("mov", "a,_spx");
3725 emitcode ("add", "a,#0x%02x", i & 0xff);
3726 emitcode ("mov", "_spx,a");
3727 emitcode ("pop", "acc");
3732 emitcode ("inc", "_spx");
3736 /* if critical function then turn interrupts off */
3737 if (IFFUNC_ISCRITICAL (ftype))
3739 symbol *tlbl = newiTempLabel (NULL);
3740 emitcode ("setb", "c");
3741 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3742 emitcode ("clr", "c");
3744 emitcode ("push", "psw"); /* save old ea via c in psw */
3748 /*-----------------------------------------------------------------*/
3749 /* genEndFunction - generates epilogue for functions */
3750 /*-----------------------------------------------------------------*/
3752 genEndFunction (iCode * ic)
3754 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3755 lineNode *lnp = lineCurr;
3757 bitVect *regsUsedPrologue;
3758 bitVect *regsUnneeded;
3761 _G.currentFunc = NULL;
3762 if (IFFUNC_ISNAKED(sym->type))
3764 emitcode(";", "naked function: no epilogue.");
3765 if (options.debug && currFunc)
3766 debugFile->writeEndFunction (currFunc, ic, 0);
3770 if (IFFUNC_ISCRITICAL (sym->type))
3772 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3774 emitcode ("rlc", "a"); /* save c in a */
3775 emitcode ("pop", "psw"); /* restore ea via c in psw */
3776 emitcode ("mov", "ea,c");
3777 emitcode ("rrc", "a"); /* restore c from a */
3781 emitcode ("pop", "psw"); /* restore ea via c in psw */
3782 emitcode ("mov", "ea,c");
3786 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3788 if (options.useXstack)
3792 emitcode ("mov", "sp,_bp");
3793 emitcode ("pop", "_bp");
3795 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3797 emitcode ("xch", "a,_bpx");
3798 emitcode ("mov", "r0,a");
3799 emitcode ("dec", "r0");
3800 emitcode ("movx", "a,@r0");
3801 emitcode ("xch", "a,_bpx");
3802 emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3805 else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3808 emitcode ("mov", "sp,_bp");
3809 emitcode ("pop", "_bp");
3813 /* restore the register bank */
3814 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3816 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3817 || !options.useXstack)
3819 /* Special case of ISR using non-zero bank with useXstack
3822 emitcode ("pop", "psw");
3826 if (IFFUNC_ISISR (sym->type))
3830 /* now we need to restore the registers */
3831 /* if this isr has no bank i.e. is going to
3832 run with bank 0 , then we need to save more
3834 if (!FUNC_REGBANK (sym->type))
3837 /* if this function does not call any other
3838 function then we can be economical and
3839 save only those registers that are used */
3840 if (!IFFUNC_HASFCALL(sym->type))
3842 /* if any registers used */
3845 /* save the registers used */
3846 for (i = sym->regsUsed->size; i >= 0; i--)
3848 if (bitVectBitValue (sym->regsUsed, i))
3855 if (options.parms_in_bank1) {
3856 for (i = 7 ; i >= 0 ; i-- ) {
3857 emitcode ("pop","%s",rb1regs[i]);
3860 /* this function has a function call. We cannot
3861 determine register usage so we will have to pop the
3863 unsaveRBank (0, ic, FALSE);
3868 /* This ISR uses a non-zero bank.
3870 * Restore any register banks saved by genFunction
3873 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3876 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3878 if (savedBanks & (1 << ix))
3880 unsaveRBank(ix, NULL, FALSE);
3884 if (options.useXstack)
3886 /* Restore bank AFTER calling unsaveRBank,
3887 * since it can trash r0.
3889 emitcode ("pop", "psw");
3893 if (!inExcludeList ("dph"))
3894 emitcode ("pop", "dph");
3895 if (!inExcludeList ("dpl"))
3896 emitcode ("pop", "dpl");
3897 if (!inExcludeList ("b"))
3898 emitcode ("pop", "b");
3899 if (!inExcludeList ("acc"))
3900 emitcode ("pop", "acc");
3902 rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), sym->regsUsed);
3903 if (IFFUNC_HASFCALL(sym->type) || !bitVectIsZero (rsavebits))
3904 emitcode ("pop", "bits");
3905 freeBitVect (rsavebits);
3907 /* if debug then send end of function */
3908 if (options.debug && currFunc)
3910 debugFile->writeEndFunction (currFunc, ic, 1);
3913 emitcode ("reti", "");
3917 if (IFFUNC_CALLEESAVES(sym->type))
3921 /* if any registers used */
3924 /* save the registers used */
3925 for (i = sym->regsUsed->size; i >= 0; i--)
3927 if (bitVectBitValue (sym->regsUsed, i) ||
3928 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3929 emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
3932 else if (mcs51_ptrRegReq)
3934 emitcode ("pop", "%s", REG_WITH_INDEX (R1_IDX)->dname);
3935 emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
3940 /* if debug then send end of function */
3941 if (options.debug && currFunc)
3943 debugFile->writeEndFunction (currFunc, ic, 1);
3946 if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3948 emitcode ("ljmp", "__sdcc_banked_ret");
3952 emitcode ("ret", "");
3956 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3959 /* If this was an interrupt handler using bank 0 that called another */
3960 /* function, then all registers must be saved; nothing to optimized. */
3961 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3962 && !FUNC_REGBANK(sym->type))
3965 /* There are no push/pops to optimize if not callee-saves or ISR */
3966 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3969 /* If there were stack parameters, we cannot optimize without also */
3970 /* fixing all of the stack offsets; this is too dificult to consider. */
3971 if (FUNC_HASSTACKPARM(sym->type))
3974 /* Compute the registers actually used */
3975 regsUsed = newBitVect (mcs51_nRegs);
3976 regsUsedPrologue = newBitVect (mcs51_nRegs);
3979 if (lnp->ic && lnp->ic->op == FUNCTION)
3980 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3982 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3984 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3985 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3992 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3993 && !bitVectBitValue (regsUsed, CND_IDX))
3995 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3996 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3997 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3998 bitVectUnSetBit (regsUsed, CND_IDX);
4001 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
4003 /* If this was an interrupt handler that called another function */
4004 /* function, then assume A, B, DPH, & DPL may be modified by it. */
4005 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
4007 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
4008 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
4009 regsUsed = bitVectSetBit (regsUsed, B_IDX);
4010 regsUsed = bitVectSetBit (regsUsed, A_IDX);
4011 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
4014 /* Remove the unneeded push/pops */
4015 regsUnneeded = newBitVect (mcs51_nRegs);
4018 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
4020 if (!strncmp(lnp->line, "push", 4))
4022 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
4023 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4025 connectLine (lnp->prev, lnp->next);
4026 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4029 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
4031 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
4032 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4034 connectLine (lnp->prev, lnp->next);
4035 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4042 for (idx = 0; idx < regsUnneeded->size; idx++)
4043 if (bitVectBitValue (regsUnneeded, idx))
4044 emitcode (";", "eliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
4046 freeBitVect (regsUnneeded);
4047 freeBitVect (regsUsed);
4048 freeBitVect (regsUsedPrologue);
4051 /*-----------------------------------------------------------------*/
4052 /* genRet - generate code for return statement */
4053 /*-----------------------------------------------------------------*/
4057 int size, offset = 0, pushed = 0;
4059 D (emitcode (";", "genRet"));
4061 /* if we have no return value then
4062 just generate the "ret" */
4066 /* we have something to return then
4067 move the return value into place */
4068 aopOp (IC_LEFT (ic), ic, FALSE);
4069 size = AOP_SIZE (IC_LEFT (ic));
4071 if (IS_BIT(_G.currentFunc->etype))
4073 if (!IS_OP_RUONLY (IC_LEFT (ic)))
4074 toCarry (IC_LEFT (ic));
4081 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
4084 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
4085 emitcode ("push", "%s", l);
4090 l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
4091 if (strcmp (fReturn[offset], l))
4092 emitcode ("mov", "%s,%s", fReturn[offset++], l);
4099 if (strcmp (fReturn[pushed], "a"))
4100 emitcode ("pop", fReturn[pushed]);
4102 emitcode ("pop", "acc");
4105 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
4108 /* generate a jump to the return label
4109 if the next is not the return statement */
4110 if (!(ic->next && ic->next->op == LABEL &&
4111 IC_LABEL (ic->next) == returnLabel))
4113 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
4117 /*-----------------------------------------------------------------*/
4118 /* genLabel - generates a label */
4119 /*-----------------------------------------------------------------*/
4121 genLabel (iCode * ic)
4123 /* special case never generate */
4124 if (IC_LABEL (ic) == entryLabel)
4127 emitLabel (IC_LABEL (ic));
4130 /*-----------------------------------------------------------------*/
4131 /* genGoto - generates a ljmp */
4132 /*-----------------------------------------------------------------*/
4134 genGoto (iCode * ic)
4136 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
4139 /*-----------------------------------------------------------------*/
4140 /* findLabelBackwards: walks back through the iCode chain looking */
4141 /* for the given label. Returns number of iCode instructions */
4142 /* between that label and given ic. */
4143 /* Returns zero if label not found. */
4144 /*-----------------------------------------------------------------*/
4146 findLabelBackwards (iCode * ic, int key)
4155 /* If we have any pushes or pops, we cannot predict the distance.
4156 I don't like this at all, this should be dealt with in the
4158 if (ic->op == IPUSH || ic->op == IPOP) {
4162 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4171 /*-----------------------------------------------------------------*/
4172 /* genPlusIncr :- does addition with increment if possible */
4173 /*-----------------------------------------------------------------*/
4175 genPlusIncr (iCode * ic)
4177 unsigned int icount;
4178 unsigned int size = getDataSize (IC_RESULT (ic));
4180 /* will try to generate an increment */
4181 /* if the right side is not a literal
4183 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4186 icount = (unsigned int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4188 D(emitcode (";","genPlusIncr"));
4190 /* if increment >=16 bits in register or direct space */
4191 if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG ||
4192 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4193 (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4194 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4195 !isOperandVolatile (IC_RESULT (ic), FALSE) &&
4203 /* If the next instruction is a goto and the goto target
4204 * is < 10 instructions previous to this, we can generate
4205 * jumps straight to that target.
4207 if (ic->next && ic->next->op == GOTO
4208 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4209 && labelRange <= 10)
4211 D (emitcode (";", "tail increment optimized (range %d)", labelRange));
4212 tlbl = IC_LABEL (ic->next);
4217 tlbl = newiTempLabel (NULL);
4220 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4221 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4222 IS_AOP_PREG (IC_RESULT (ic)))
4223 emitcode ("cjne", "%s,#0x00,%05d$",
4224 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4228 emitcode ("clr", "a");
4229 emitcode ("cjne", "a,%s,%05d$",
4230 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4234 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4237 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4238 IS_AOP_PREG (IC_RESULT (ic)))
4239 emitcode ("cjne", "%s,#0x00,%05d$",
4240 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4243 emitcode ("cjne", "a,%s,%05d$",
4244 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4247 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4251 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4252 IS_AOP_PREG (IC_RESULT (ic)))
4253 emitcode ("cjne", "%s,#0x00,%05d$",
4254 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4258 emitcode ("cjne", "a,%s,%05d$",
4259 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4262 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4272 /* if result is dptr */
4273 if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
4274 (AOP_SIZE (IC_RESULT (ic)) == 2) &&
4275 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
4276 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
4278 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4284 if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
4287 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0);
4288 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1);
4290 emitcode ("inc", "dptr");
4295 /* if the literal value of the right hand side
4296 is greater than 4 then it is not worth it */
4300 /* if the sizes are greater than 1 then we cannot */
4301 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4302 AOP_SIZE (IC_LEFT (ic)) > 1)
4305 /* we can if the aops of the left & result match or
4306 if they are in registers and the registers are the
4308 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4312 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4313 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4314 aopPut (IC_RESULT (ic), "a", 0);
4320 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4329 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4330 emitcode ("inc", "a");
4331 aopPut (IC_RESULT (ic), "a", 0);
4338 /*-----------------------------------------------------------------*/
4339 /* outBitAcc - output a bit in acc */
4340 /*-----------------------------------------------------------------*/
4342 outBitAcc (operand * result)
4344 symbol *tlbl = newiTempLabel (NULL);
4345 /* if the result is a bit */
4346 if (AOP_TYPE (result) == AOP_CRY)
4348 aopPut (result, "a", 0);
4352 emitcode ("jz", "%05d$", tlbl->key + 100);
4353 emitcode ("mov", "a,%s", one);
4359 /*-----------------------------------------------------------------*/
4360 /* genPlusBits - generates code for addition of two bits */
4361 /*-----------------------------------------------------------------*/
4363 genPlusBits (iCode * ic)
4365 D (emitcode (";", "genPlusBits"));
4367 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4368 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4370 symbol *lbl = newiTempLabel (NULL);
4371 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4372 emitcode ("cpl", "c");
4374 outBitC (IC_RESULT (ic));
4378 emitcode ("clr", "a");
4379 emitcode ("rlc", "a");
4380 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4381 emitcode ("addc", "a,%s", zero);
4382 outAcc (IC_RESULT (ic));
4387 /* This is the original version of this code.
4389 * This is being kept around for reference,
4390 * because I am not entirely sure I got it right...
4393 adjustArithmeticResult (iCode * ic)
4395 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4396 AOP_SIZE (IC_LEFT (ic)) == 3 &&
4397 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4398 aopPut (IC_RESULT (ic),
4399 aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4402 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4403 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4404 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4405 aopPut (IC_RESULT (ic),
4406 aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4409 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4410 AOP_SIZE (IC_LEFT (ic)) < 3 &&
4411 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4412 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4413 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4416 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4417 aopPut (IC_RESULT (ic), buffer, 2);
4421 /* This is the pure and virtuous version of this code.
4422 * I'm pretty certain it's right, but not enough to toss the old
4426 adjustArithmeticResult (iCode * ic)
4428 if (opIsGptr (IC_RESULT (ic)) &&
4429 opIsGptr (IC_LEFT (ic)) &&
4430 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4432 aopPut (IC_RESULT (ic),
4433 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4437 if (opIsGptr (IC_RESULT (ic)) &&
4438 opIsGptr (IC_RIGHT (ic)) &&
4439 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4441 aopPut (IC_RESULT (ic),
4442 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4446 if (opIsGptr (IC_RESULT (ic)) &&
4447 IC_LEFT (ic) && AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4448 IC_RIGHT (ic) && AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4449 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4450 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4453 SNPRINTF (buffer, sizeof(buffer),
4454 "#0x%02x", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4455 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4460 /*-----------------------------------------------------------------*/
4461 /* genPlus - generates code for addition */
4462 /*-----------------------------------------------------------------*/
4464 genPlus (iCode * ic)
4466 int size, offset = 0;
4469 bool swappedLR = FALSE;
4470 operand *leftOp, *rightOp;
4473 D (emitcode (";", "genPlus"));
4475 /* special cases :- */
4477 aopOp (IC_LEFT (ic), ic, FALSE);
4478 aopOp (IC_RIGHT (ic), ic, FALSE);
4479 aopOp (IC_RESULT (ic), ic, TRUE);
4481 /* if literal, literal on the right or
4482 if left requires ACC or right is already
4484 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4485 (AOP_NEEDSACC (IC_LEFT (ic))) ||
4486 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4488 operand *t = IC_RIGHT (ic);
4489 IC_RIGHT (ic) = IC_LEFT (ic);
4494 /* if both left & right are in bit
4496 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4497 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4503 /* if left in bit space & right literal */
4504 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4505 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4507 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4508 /* if result in bit space */
4509 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4511 if (ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4512 emitcode ("cpl", "c");
4513 outBitC (IC_RESULT (ic));
4517 size = getDataSize (IC_RESULT (ic));
4520 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4521 emitcode ("addc", "a,%s", zero);
4522 aopPut (IC_RESULT (ic), "a", offset++);
4528 /* if I can do an increment instead
4529 of add then GOOD for ME */
4530 if (genPlusIncr (ic) == TRUE)
4533 size = getDataSize (IC_RESULT (ic));
4534 leftOp = IC_LEFT(ic);
4535 rightOp = IC_RIGHT(ic);
4538 /* if this is an add for an array access
4539 at a 256 byte boundary */
4541 && AOP_TYPE (op) == AOP_IMMD
4543 && IS_SPEC (OP_SYM_ETYPE (op))
4544 && SPEC_ABSA (OP_SYM_ETYPE (op))
4545 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4548 D(emitcode (";", "genPlus aligned array"));
4549 aopPut (IC_RESULT (ic),
4550 aopGet (rightOp, 0, FALSE, FALSE),
4553 if( 1 == getDataSize (IC_RIGHT (ic)) )
4555 aopPut (IC_RESULT (ic),
4556 aopGet (leftOp, 1, FALSE, FALSE),
4561 MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4562 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4563 aopPut (IC_RESULT (ic), "a", 1);
4568 /* if the lower bytes of a literal are zero skip the addition */
4569 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4571 while ((0 == ((unsigned int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4572 (skip_bytes+1 < size))
4577 D(emitcode (";", "genPlus shortcut"));
4582 if( offset >= skip_bytes )
4584 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4587 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4589 emitcode("xch", "a,b");
4590 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4591 emitcode (add, "a,b");
4594 else if (aopGetUsesAcc (leftOp, offset))
4596 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4597 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4601 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4602 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4604 aopPut (IC_RESULT (ic), "a", offset);
4605 add = "addc"; /* further adds must propagate carry */
4609 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4610 isOperandVolatile (IC_RESULT (ic), FALSE))
4613 aopPut (IC_RESULT (ic),
4614 aopGet (leftOp, offset, FALSE, FALSE),
4621 adjustArithmeticResult (ic);
4624 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4627 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4628 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4632 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4633 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4637 /*-----------------------------------------------------------------*/
4638 /* genMinusDec :- does subtraction with decrement if possible */
4639 /*-----------------------------------------------------------------*/
4641 genMinusDec (iCode * ic)
4643 unsigned int icount;
4644 unsigned int size = getDataSize (IC_RESULT (ic));
4646 /* will try to generate an increment */
4647 /* if the right side is not a literal
4649 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4652 /* if the literal value of the right hand side
4653 is greater than 4 then it is not worth it */
4654 if ((icount = (unsigned int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4657 D (emitcode (";", "genMinusDec"));
4659 /* if decrement >=16 bits in register or direct space */
4660 if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG ||
4661 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4662 (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4663 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4671 /* If the next instruction is a goto and the goto target
4672 * is <= 10 instructions previous to this, we can generate
4673 * jumps straight to that target.
4675 if (ic->next && ic->next->op == GOTO
4676 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4677 && labelRange <= 10)
4679 D (emitcode (";", "tail decrement optimized (range %d)", labelRange));
4680 tlbl = IC_LABEL (ic->next);
4685 tlbl = newiTempLabel (NULL);
4689 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, 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), LSB, FALSE, FALSE)
4697 emitcode ("mov", "a,#0xff");
4698 emitcode ("cjne", "a,%s,%05d$"
4699 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4702 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, 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), MSB16, FALSE, FALSE)
4712 emitcode ("cjne", "a,%s,%05d$"
4713 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4716 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4720 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4721 IS_AOP_PREG (IC_RESULT (ic)))
4722 emitcode ("cjne", "%s,#0xff,%05d$"
4723 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4727 emitcode ("cjne", "a,%s,%05d$"
4728 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4731 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4740 /* if the sizes are greater than 1 then we cannot */
4741 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4742 AOP_SIZE (IC_LEFT (ic)) > 1)
4745 /* we can if the aops of the left & result match or
4746 if they are in registers and the registers are the
4748 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4752 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4754 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4759 l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
4764 emitcode ("dec", "%s", l);
4767 if (AOP_NEEDSACC (IC_RESULT (ic)))
4768 aopPut (IC_RESULT (ic), "a", 0);
4775 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4776 emitcode ("dec", "a");
4777 aopPut (IC_RESULT (ic), "a", 0);
4784 /*-----------------------------------------------------------------*/
4785 /* addSign - complete with sign */
4786 /*-----------------------------------------------------------------*/
4788 addSign (operand * result, int offset, int sign)
4790 int size = (getDataSize (result) - offset);
4795 emitcode ("rlc", "a");
4796 emitcode ("subb", "a,acc");
4799 aopPut (result, "a", offset++);
4806 aopPut (result, zero, offset++);
4812 /*-----------------------------------------------------------------*/
4813 /* genMinusBits - generates code for subtraction of two bits */
4814 /*-----------------------------------------------------------------*/
4816 genMinusBits (iCode * ic)
4818 symbol *lbl = newiTempLabel (NULL);
4820 D (emitcode (";", "genMinusBits"));
4822 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4824 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4825 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4826 emitcode ("cpl", "c");
4828 outBitC (IC_RESULT (ic));
4832 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4833 emitcode ("subb", "a,acc");
4834 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4835 emitcode ("inc", "a");
4837 aopPut (IC_RESULT (ic), "a", 0);
4838 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4842 /*-----------------------------------------------------------------*/
4843 /* genMinus - generates code for subtraction */
4844 /*-----------------------------------------------------------------*/
4846 genMinus (iCode * ic)
4848 int size, offset = 0;
4850 D (emitcode (";", "genMinus"));
4852 aopOp (IC_LEFT (ic), ic, FALSE);
4853 aopOp (IC_RIGHT (ic), ic, FALSE);
4854 aopOp (IC_RESULT (ic), ic, TRUE);
4856 /* special cases :- */
4857 /* if both left & right are in bit space */
4858 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4859 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4865 /* if I can do an decrement instead
4866 of subtract then GOOD for ME */
4867 if (genMinusDec (ic) == TRUE)
4870 size = getDataSize (IC_RESULT (ic));
4872 /* if literal, add a,#-lit, else normal subb */
4873 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4875 unsigned long lit = 0L;
4876 bool useCarry = FALSE;
4878 lit = ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4883 if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4885 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4886 if (!offset && !size && lit== (unsigned long) -1)
4888 emitcode ("dec", "a");
4892 /* first add without previous c */
4893 emitcode ("add", "a,#0x%02x",
4894 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4899 emitcode ("addc", "a,#0x%02x",
4900 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4902 aopPut (IC_RESULT (ic), "a", offset++);
4906 /* no need to add zeroes */
4907 if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4909 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4918 operand *leftOp, *rightOp;
4920 leftOp = IC_LEFT(ic);
4921 rightOp = IC_RIGHT(ic);
4925 if (aopGetUsesAcc(rightOp, offset)) {
4926 if (aopGetUsesAcc(leftOp, offset)) {
4929 MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4931 emitcode ("mov", "b,a");
4934 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4935 emitcode ("subb", "a,b");
4938 /* reverse subtraction with 2's complement */
4940 emitcode( "setb", "c");
4942 emitcode( "cpl", "c");
4943 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4944 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4945 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4946 emitcode("cpl", "a");
4947 if (size) /* skip if last byte */
4948 emitcode( "cpl", "c");
4951 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4954 emitcode ("subb", "a,%s",
4955 aopGet(rightOp, offset, FALSE, TRUE));
4958 aopPut (IC_RESULT (ic), "a", offset++);
4962 adjustArithmeticResult (ic);
4965 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4966 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4967 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4971 /*-----------------------------------------------------------------*/
4972 /* genMultbits :- multiplication of bits */
4973 /*-----------------------------------------------------------------*/
4975 genMultbits (operand * left,
4979 D (emitcode (";", "genMultbits"));
4981 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4982 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4986 /*-----------------------------------------------------------------*/
4987 /* genMultOneByte : 8*8=8/16 bit multiplication */
4988 /*-----------------------------------------------------------------*/
4990 genMultOneByte (operand * left,
4995 int size = AOP_SIZE (result);
4996 bool runtimeSign, compiletimeSign;
4997 bool lUnsigned, rUnsigned, pushedB;
4999 D (emitcode (";", "genMultOneByte"));
5001 if (size < 1 || size > 2)
5003 /* this should never happen */
5004 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
5005 AOP_SIZE(result), __FILE__, lineno);
5009 /* (if two literals: the value is computed before) */
5010 /* if one literal, literal on the right */
5011 if (AOP_TYPE (left) == AOP_LIT)
5016 /* emitcode (";", "swapped left and right"); */
5018 /* if no literal, unsigned on the right: shorter code */
5019 if ( AOP_TYPE (right) != AOP_LIT
5020 && SPEC_USIGN (getSpec (operandType (left))))
5027 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5028 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5032 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
5033 no need to take care about the signedness! */
5034 || (lUnsigned && rUnsigned))
5036 /* just an unsigned 8 * 8 = 8 multiply
5038 /* emitcode (";","unsigned"); */
5039 /* TODO: check for accumulator clash between left & right aops? */
5041 if (AOP_TYPE (right) == AOP_LIT)
5043 /* moving to accumulator first helps peepholes */
5044 MOVA (aopGet (left, 0, FALSE, FALSE));
5045 MOVB (aopGet (right, 0, FALSE, FALSE));
5049 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5050 MOVA (aopGet (left, 0, FALSE, FALSE));
5053 emitcode ("mul", "ab");
5054 aopPut (result, "a", 0);
5056 aopPut (result, "b", 1);
5062 /* we have to do a signed multiply */
5063 /* emitcode (";", "signed"); */
5065 /* now sign adjust for both left & right */
5067 /* let's see what's needed: */
5068 /* apply negative sign during runtime */
5069 runtimeSign = FALSE;
5070 /* negative sign from literals */
5071 compiletimeSign = FALSE;
5075 if (AOP_TYPE(left) == AOP_LIT)
5077 /* signed literal */
5078 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5080 compiletimeSign = TRUE;
5083 /* signed but not literal */
5089 if (AOP_TYPE(right) == AOP_LIT)
5091 /* signed literal */
5092 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
5094 compiletimeSign ^= TRUE;
5097 /* signed but not literal */
5101 /* initialize F0, which stores the runtime sign */
5104 if (compiletimeSign)
5105 emitcode ("setb", "F0"); /* set sign flag */
5107 emitcode ("clr", "F0"); /* reset sign flag */
5110 /* save the signs of the operands */
5111 if (AOP_TYPE(right) == AOP_LIT)
5113 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
5115 if (!rUnsigned && val < 0)
5116 emitcode ("mov", "b,#0x%02x", -val);
5118 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5120 else /* ! literal */
5122 if (rUnsigned) /* emitcode (";", "signed"); */
5123 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5126 MOVA (aopGet (right, 0, FALSE, FALSE));
5127 lbl = newiTempLabel (NULL);
5128 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5129 emitcode ("cpl", "F0"); /* complement sign flag */
5130 emitcode ("cpl", "a"); /* 2's complement */
5131 emitcode ("inc", "a");
5133 emitcode ("mov", "b,a");
5137 if (AOP_TYPE(left) == AOP_LIT)
5139 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5141 if (!lUnsigned && val < 0)
5142 emitcode ("mov", "a,#0x%02x", -val);
5144 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5146 else /* ! literal */
5148 MOVA (aopGet (left, 0, FALSE, FALSE));
5152 lbl = newiTempLabel (NULL);
5153 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5154 emitcode ("cpl", "F0"); /* complement sign flag */
5155 emitcode ("cpl", "a"); /* 2's complement */
5156 emitcode ("inc", "a");
5161 /* now the multiplication */
5162 emitcode ("mul", "ab");
5163 if (runtimeSign || compiletimeSign)
5165 lbl = newiTempLabel (NULL);
5167 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5168 emitcode ("cpl", "a"); /* lsb 2's complement */
5170 emitcode ("inc", "a"); /* inc doesn't set carry flag */
5173 emitcode ("add", "a,#0x01"); /* this sets carry flag */
5174 emitcode ("xch", "a,b");
5175 emitcode ("cpl", "a"); /* msb 2's complement */
5176 emitcode ("addc", "a,#0x00");
5177 emitcode ("xch", "a,b");
5181 aopPut (result, "a", 0);
5183 aopPut (result, "b", 1);
5188 /*-----------------------------------------------------------------*/
5189 /* genMult - generates code for multiplication */
5190 /*-----------------------------------------------------------------*/
5192 genMult (iCode * ic)
5194 operand *left = IC_LEFT (ic);
5195 operand *right = IC_RIGHT (ic);
5196 operand *result = IC_RESULT (ic);
5198 D (emitcode (";", "genMult"));
5200 /* assign the asmops */
5201 aopOp (left, ic, FALSE);
5202 aopOp (right, ic, FALSE);
5203 aopOp (result, ic, TRUE);
5205 /* special cases first */
5207 if (AOP_TYPE (left) == AOP_CRY &&
5208 AOP_TYPE (right) == AOP_CRY)
5210 genMultbits (left, right, result);
5214 /* if both are of size == 1 */
5215 #if 0 // one of them can be a sloc shared with the result
5216 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
5218 if (getSize(operandType(left)) == 1 &&
5219 getSize(operandType(right)) == 1)
5222 genMultOneByte (left, right, result);
5226 /* should have been converted to function call */
5227 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
5228 getSize(OP_SYMBOL(right)->type));
5232 freeAsmop (result, NULL, ic, TRUE);
5233 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5234 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5237 /*-----------------------------------------------------------------*/
5238 /* genDivbits :- division of bits */
5239 /*-----------------------------------------------------------------*/
5241 genDivbits (operand * left,
5248 D(emitcode (";", "genDivbits"));
5252 /* the result must be bit */
5253 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5254 l = aopGet (left, 0, FALSE, FALSE);
5258 emitcode ("div", "ab");
5259 emitcode ("rrc", "a");
5263 aopPut (result, "c", 0);
5266 /*-----------------------------------------------------------------*/
5267 /* genDivOneByte : 8 bit division */
5268 /*-----------------------------------------------------------------*/
5270 genDivOneByte (operand * left,
5274 bool lUnsigned, rUnsigned, pushedB;
5275 bool runtimeSign, compiletimeSign;
5276 bool accuse = FALSE;
5277 bool pushedA = FALSE;
5281 D(emitcode (";", "genDivOneByte"));
5283 /* Why is it necessary that genDivOneByte() can return an int result?
5286 volatile unsigned char uc;
5287 volatile signed char sc1, sc2;
5300 In all cases a one byte result would overflow, the following cast to int
5301 would return the wrong result.
5303 Two possible solution:
5304 a) cast operands to int, if ((unsigned) / (signed)) or
5305 ((signed) / (signed))
5306 b) return an 16 bit signed int; this is what we're doing here!
5309 size = AOP_SIZE (result) - 1;
5311 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5312 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5316 /* signed or unsigned */
5317 if (lUnsigned && rUnsigned)
5319 /* unsigned is easy */
5320 MOVB (aopGet (right, 0, FALSE, FALSE));
5321 MOVA (aopGet (left, 0, FALSE, FALSE));
5322 emitcode ("div", "ab");
5323 aopPut (result, "a", 0);
5325 aopPut (result, zero, offset++);
5331 /* signed is a little bit more difficult */
5333 /* now sign adjust for both left & right */
5335 /* let's see what's needed: */
5336 /* apply negative sign during runtime */
5337 runtimeSign = FALSE;
5338 /* negative sign from literals */
5339 compiletimeSign = FALSE;
5343 if (AOP_TYPE(left) == AOP_LIT)
5345 /* signed literal */
5346 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5348 compiletimeSign = TRUE;
5351 /* signed but not literal */
5357 if (AOP_TYPE(right) == AOP_LIT)
5359 /* signed literal */
5360 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
5362 compiletimeSign ^= TRUE;
5365 /* signed but not literal */
5369 /* initialize F0, which stores the runtime sign */
5372 if (compiletimeSign)
5373 emitcode ("setb", "F0"); /* set sign flag */
5375 emitcode ("clr", "F0"); /* reset sign flag */
5378 /* save the signs of the operands */
5379 if (AOP_TYPE(right) == AOP_LIT)
5381 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
5383 if (!rUnsigned && val < 0)
5384 emitcode ("mov", "b,#0x%02x", -val);
5386 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5388 else /* ! literal */
5391 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5394 MOVA (aopGet (right, 0, FALSE, FALSE));
5395 lbl = newiTempLabel (NULL);
5396 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5397 emitcode ("cpl", "F0"); /* complement sign flag */
5398 emitcode ("cpl", "a"); /* 2's complement */
5399 emitcode ("inc", "a");
5401 emitcode ("mov", "b,a");
5405 if (AOP_TYPE(left) == AOP_LIT)
5407 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5409 if (!lUnsigned && val < 0)
5410 emitcode ("mov", "a,#0x%02x", -val);
5412 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5414 else /* ! literal */
5416 MOVA (aopGet (left, 0, FALSE, FALSE));
5420 lbl = newiTempLabel (NULL);
5421 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5422 emitcode ("cpl", "F0"); /* complement sign flag */
5423 emitcode ("cpl", "a"); /* 2's complement */
5424 emitcode ("inc", "a");
5429 /* now the division */
5430 emitcode ("div", "ab");
5432 if (runtimeSign || compiletimeSign)
5434 lbl = newiTempLabel (NULL);
5436 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5437 emitcode ("cpl", "a"); /* lsb 2's complement */
5438 emitcode ("inc", "a");
5441 accuse = aopPut (result, "a", 0);
5444 /* msb is 0x00 or 0xff depending on the sign */
5449 emitcode ("push", "acc");
5452 emitcode ("mov", "c,F0");
5453 emitcode ("subb", "a,acc");
5455 aopPut (result, "a", offset++);
5457 else /* compiletimeSign */
5459 if (aopPutUsesAcc (result, "#0xff", offset))
5461 emitcode ("push", "acc");
5465 aopPut (result, "#0xff", offset++);
5471 aopPut (result, "a", 0);
5473 aopPut (result, zero, offset++);
5477 emitcode ("pop", "acc");
5481 /*-----------------------------------------------------------------*/
5482 /* genDiv - generates code for division */
5483 /*-----------------------------------------------------------------*/
5487 operand *left = IC_LEFT (ic);
5488 operand *right = IC_RIGHT (ic);
5489 operand *result = IC_RESULT (ic);
5491 D (emitcode (";", "genDiv"));
5493 /* assign the asmops */
5494 aopOp (left, ic, FALSE);
5495 aopOp (right, ic, FALSE);
5496 aopOp (result, ic, TRUE);
5498 /* special cases first */
5500 if (AOP_TYPE (left) == AOP_CRY &&
5501 AOP_TYPE (right) == AOP_CRY)
5503 genDivbits (left, right, result);
5507 /* if both are of size == 1 */
5508 if (AOP_SIZE (left) == 1 &&
5509 AOP_SIZE (right) == 1)
5511 genDivOneByte (left, right, result);
5515 /* should have been converted to function call */
5518 freeAsmop (result, NULL, ic, TRUE);
5519 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5520 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5523 /*-----------------------------------------------------------------*/
5524 /* genModbits :- modulus of bits */
5525 /*-----------------------------------------------------------------*/
5527 genModbits (operand * left,
5534 D (emitcode (";", "genModbits"));
5538 /* the result must be bit */
5539 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5540 l = aopGet (left, 0, FALSE, FALSE);
5544 emitcode ("div", "ab");
5545 emitcode ("mov", "a,b");
5546 emitcode ("rrc", "a");
5550 aopPut (result, "c", 0);
5553 /*-----------------------------------------------------------------*/
5554 /* genModOneByte : 8 bit modulus */
5555 /*-----------------------------------------------------------------*/
5557 genModOneByte (operand * left,
5561 bool lUnsigned, rUnsigned, pushedB;
5562 bool runtimeSign, compiletimeSign;
5566 D (emitcode (";", "genModOneByte"));
5568 size = AOP_SIZE (result) - 1;
5570 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5571 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5573 /* if right is a literal, check it for 2^n */
5574 if (AOP_TYPE(right) == AOP_LIT)
5576 unsigned char val = abs((int) operandLitValue(right));
5577 symbol *lbl2 = NULL;
5581 case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5590 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5591 "modulus of unsigned char by 2^n literal shouldn't be processed here");
5592 /* because iCode should have been changed to genAnd */
5593 /* see file "SDCCopt.c", function "convertToFcall()" */
5595 MOVA (aopGet (left, 0, FALSE, FALSE));
5596 emitcode ("mov", "c,acc.7");
5597 emitcode ("anl", "a,#0x%02x", val - 1);
5598 lbl = newiTempLabel (NULL);
5599 emitcode ("jz", "%05d$", (lbl->key + 100));
5600 emitcode ("jnc", "%05d$", (lbl->key + 100));
5601 emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5607 aopPut (result, "a", 0);
5609 aopPut (result, "#0xff", offs2++);
5610 lbl2 = newiTempLabel (NULL);
5611 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5614 aopPut (result, "a", 0);
5616 aopPut (result, zero, offset++);
5630 /* signed or unsigned */
5631 if (lUnsigned && rUnsigned)
5633 /* unsigned is easy */
5634 MOVB (aopGet (right, 0, FALSE, FALSE));
5635 MOVA (aopGet (left, 0, FALSE, FALSE));
5636 emitcode ("div", "ab");
5637 aopPut (result, "b", 0);
5639 aopPut (result, zero, offset++);
5645 /* signed is a little bit more difficult */
5647 /* now sign adjust for both left & right */
5649 /* modulus: sign of the right operand has no influence on the result! */
5650 if (AOP_TYPE(right) == AOP_LIT)
5652 signed char val = (char) operandLitValue(right);
5654 if (!rUnsigned && val < 0)
5655 emitcode ("mov", "b,#0x%02x", -val);
5657 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5659 else /* not literal */
5662 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5665 MOVA (aopGet (right, 0, FALSE, FALSE));
5666 lbl = newiTempLabel (NULL);
5667 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5668 emitcode ("cpl", "a"); /* 2's complement */
5669 emitcode ("inc", "a");
5671 emitcode ("mov", "b,a");
5675 /* let's see what's needed: */
5676 /* apply negative sign during runtime */
5677 runtimeSign = FALSE;
5678 /* negative sign from literals */
5679 compiletimeSign = FALSE;
5681 /* sign adjust left side */
5682 if (AOP_TYPE(left) == AOP_LIT)
5684 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5686 if (!lUnsigned && val < 0)
5688 compiletimeSign = TRUE; /* set sign flag */
5689 emitcode ("mov", "a,#0x%02x", -val);
5692 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5694 else /* ! literal */
5696 MOVA (aopGet (left, 0, FALSE, FALSE));
5701 emitcode ("clr", "F0"); /* clear sign flag */
5703 lbl = newiTempLabel (NULL);
5704 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5705 emitcode ("setb", "F0"); /* set sign flag */
5706 emitcode ("cpl", "a"); /* 2's complement */
5707 emitcode ("inc", "a");
5712 /* now the modulus */
5713 emitcode ("div", "ab");
5715 if (runtimeSign || compiletimeSign)
5717 emitcode ("mov", "a,b");
5718 lbl = newiTempLabel (NULL);
5720 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5721 emitcode ("cpl", "a"); /* 2's complement */
5722 emitcode ("inc", "a");
5725 aopPut (result, "a", 0);
5728 /* msb is 0x00 or 0xff depending on the sign */
5731 emitcode ("mov", "c,F0");
5732 emitcode ("subb", "a,acc");
5734 aopPut (result, "a", offset++);
5736 else /* compiletimeSign */
5738 aopPut (result, "#0xff", offset++);
5743 aopPut (result, "b", 0);
5745 aopPut (result, zero, offset++);
5751 /*-----------------------------------------------------------------*/
5752 /* genMod - generates code for division */
5753 /*-----------------------------------------------------------------*/
5757 operand *left = IC_LEFT (ic);
5758 operand *right = IC_RIGHT (ic);
5759 operand *result = IC_RESULT (ic);
5761 D (emitcode (";", "genMod"));
5763 /* assign the asmops */
5764 aopOp (left, ic, FALSE);
5765 aopOp (right, ic, FALSE);
5766 aopOp (result, ic, TRUE);
5768 /* special cases first */
5770 if (AOP_TYPE (left) == AOP_CRY &&
5771 AOP_TYPE (right) == AOP_CRY)
5773 genModbits (left, right, result);
5777 /* if both are of size == 1 */
5778 if (AOP_SIZE (left) == 1 &&
5779 AOP_SIZE (right) == 1)
5781 genModOneByte (left, right, result);
5785 /* should have been converted to function call */
5789 freeAsmop (result, NULL, ic, TRUE);
5790 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5791 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5794 /*-----------------------------------------------------------------*/
5795 /* genIfxJump :- will create a jump depending on the ifx */
5796 /*-----------------------------------------------------------------*/
5798 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5801 symbol *tlbl = newiTempLabel (NULL);
5804 D (emitcode (";", "genIfxJump"));
5806 /* if true label then we jump if condition
5810 jlbl = IC_TRUE (ic);
5811 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5812 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5816 /* false label is present */
5817 jlbl = IC_FALSE (ic);
5818 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5819 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5821 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5822 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5824 emitcode (inst, "%05d$", tlbl->key + 100);
5825 freeForBranchAsmop (result);
5826 freeForBranchAsmop (right);
5827 freeForBranchAsmop (left);
5828 emitcode ("ljmp", "%05d$", jlbl->key + 100);
5831 /* mark the icode as generated */
5835 /*-----------------------------------------------------------------*/
5836 /* genCmp :- greater or less than comparison */
5837 /*-----------------------------------------------------------------*/
5839 genCmp (operand * left, operand * right,
5840 operand * result, iCode * ifx, int sign, iCode *ic)
5842 int size, offset = 0;
5843 unsigned long lit = 0L;
5846 D (emitcode (";", "genCmp"));
5848 /* if left & right are bit variables */
5849 if (AOP_TYPE (left) == AOP_CRY &&
5850 AOP_TYPE (right) == AOP_CRY)
5852 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5853 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5857 /* subtract right from left if at the
5858 end the carry flag is set then we know that
5859 left is greater than right */
5860 size = max (AOP_SIZE (left), AOP_SIZE (right));
5862 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5863 if ((size == 1) && !sign &&
5864 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5866 symbol *lbl = newiTempLabel (NULL);
5867 emitcode ("cjne", "%s,%s,%05d$",
5868 aopGet (left, offset, FALSE, FALSE),
5869 aopGet (right, offset, FALSE, FALSE),
5875 if (AOP_TYPE (right) == AOP_LIT)
5877 lit = ulFromVal (AOP (right)->aopu.aop_lit);
5878 /* optimize if(x < 0) or if(x >= 0) */
5887 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5888 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5890 genIfxJump (ifx, "acc.7", left, right, result);
5891 freeAsmop (right, NULL, ic, TRUE);
5892 freeAsmop (left, NULL, ic, TRUE);
5898 emitcode ("rlc", "a");
5905 int bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5906 while (size && (bytelit == 0))
5909 bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5915 MOVA (aopGet (left, offset, FALSE, FALSE));
5916 if (sign && size == 0)
5918 emitcode ("xrl", "a,#0x80");
5919 emitcode ("subb", "a,#0x%02x",
5920 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5924 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5934 bool pushedB = FALSE;
5935 rightInB = aopGetUsesAcc(right, offset);
5939 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5941 MOVA (aopGet (left, offset, FALSE, FALSE));
5942 if (sign && size == 0)
5944 emitcode ("xrl", "a,#0x80");
5949 MOVB (aopGet (right, offset, FALSE, FALSE));
5951 emitcode ("xrl", "b,#0x80");
5952 emitcode ("subb", "a,b");
5957 emitcode ("subb", "a,b");
5959 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5969 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5970 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5971 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5977 /* if the result is used in the next
5978 ifx conditional branch then generate
5979 code a little differently */
5982 genIfxJump (ifx, "c", NULL, NULL, result);
5988 /* leave the result in acc */
5992 /*-----------------------------------------------------------------*/
5993 /* genCmpGt :- greater than comparison */
5994 /*-----------------------------------------------------------------*/
5996 genCmpGt (iCode * ic, iCode * ifx)
5998 operand *left, *right, *result;
5999 sym_link *letype, *retype;
6002 D (emitcode (";", "genCmpGt"));
6004 left = IC_LEFT (ic);
6005 right = IC_RIGHT (ic);
6006 result = IC_RESULT (ic);
6008 letype = getSpec (operandType (left));
6009 retype = getSpec (operandType (right));
6010 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
6011 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
6012 /* assign the asmops */
6013 aopOp (result, ic, TRUE);
6014 aopOp (left, ic, FALSE);
6015 aopOp (right, ic, FALSE);
6017 genCmp (right, left, result, ifx, sign, ic);
6019 freeAsmop (result, NULL, ic, TRUE);
6022 /*-----------------------------------------------------------------*/
6023 /* genCmpLt - less than comparisons */
6024 /*-----------------------------------------------------------------*/
6026 genCmpLt (iCode * ic, iCode * ifx)
6028 operand *left, *right, *result;
6029 sym_link *letype, *retype;
6032 D (emitcode (";", "genCmpLt"));
6034 left = IC_LEFT (ic);
6035 right = IC_RIGHT (ic);
6036 result = IC_RESULT (ic);
6038 letype = getSpec (operandType (left));
6039 retype = getSpec (operandType (right));
6040 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
6041 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
6042 /* assign the asmops */
6043 aopOp (result, ic, TRUE);
6044 aopOp (left, ic, FALSE);
6045 aopOp (right, ic, FALSE);
6047 genCmp (left, right, result, ifx, sign, ic);
6049 freeAsmop (result, NULL, ic, TRUE);
6052 /*-----------------------------------------------------------------*/
6053 /* gencjneshort - compare and jump if not equal */
6054 /*-----------------------------------------------------------------*/
6056 gencjneshort (operand * left, operand * right, symbol * lbl)
6058 int size = max (AOP_SIZE (left), AOP_SIZE (right));
6060 unsigned long lit = 0L;
6062 D (emitcode (";", "gencjneshort"));
6064 /* if the left side is a literal or
6065 if the right is in a pointer register and left
6067 if ((AOP_TYPE (left) == AOP_LIT) ||
6068 (AOP_TYPE (left) == AOP_IMMD) ||
6069 (AOP_TYPE (left) == AOP_DIR) ||
6070 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6077 if (AOP_TYPE (right) == AOP_LIT)
6078 lit = ulFromVal (AOP (right)->aopu.aop_lit);
6080 /* if the right side is a literal then anything goes */
6081 if (AOP_TYPE (right) == AOP_LIT &&
6082 AOP_TYPE (left) != AOP_DIR &&
6083 AOP_TYPE (left) != AOP_IMMD)
6087 emitcode ("cjne", "%s,%s,%05d$",
6088 aopGet (left, offset, FALSE, FALSE),
6089 aopGet (right, offset, FALSE, FALSE),
6095 /* if the right side is in a register or in direct space or
6096 if the left is a pointer register & right is not */
6097 else if (AOP_TYPE (right) == AOP_REG ||
6098 AOP_TYPE (right) == AOP_DIR ||
6099 AOP_TYPE (right) == AOP_LIT ||
6100 AOP_TYPE (right) == AOP_IMMD ||
6101 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6102 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6106 MOVA (aopGet (left, offset, FALSE, FALSE));
6107 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6108 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6109 emitcode ("jnz", "%05d$", lbl->key + 100);
6111 emitcode ("cjne", "a,%s,%05d$",
6112 aopGet (right, offset, FALSE, TRUE),
6119 /* right is a pointer reg need both a & b */
6122 //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
6123 wassertl(!BINUSE, "B was in use");
6124 MOVB (aopGet (left, offset, FALSE, FALSE));
6125 MOVA (aopGet (right, offset, FALSE, FALSE));
6126 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
6132 /*-----------------------------------------------------------------*/
6133 /* gencjne - compare and jump if not equal */
6134 /*-----------------------------------------------------------------*/
6136 gencjne (operand * left, operand * right, symbol * lbl, bool useCarry)
6138 symbol *tlbl = newiTempLabel (NULL);
6140 D (emitcode (";", "gencjne"));
6142 gencjneshort (left, right, lbl);
6148 emitcode ("sjmp", "%05d$", tlbl->key + 100);
6157 /*-----------------------------------------------------------------*/
6158 /* genCmpEq - generates code for equal to */
6159 /*-----------------------------------------------------------------*/
6161 genCmpEq (iCode * ic, iCode * ifx)
6163 bool swappedLR = FALSE;
6164 operand *left, *right, *result;
6166 D (emitcode (";", "genCmpEq"));
6168 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6169 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6170 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6172 /* if literal, literal on the right or
6173 if the right is in a pointer register and left
6175 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6176 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6178 operand *t = IC_RIGHT (ic);
6179 IC_RIGHT (ic) = IC_LEFT (ic);
6184 if (ifx && !AOP_SIZE (result))
6187 /* if they are both bit variables */
6188 if (AOP_TYPE (left) == AOP_CRY &&
6189 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6191 if (AOP_TYPE (right) == AOP_LIT)
6193 unsigned long lit = ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6196 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6197 emitcode ("cpl", "c");
6201 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6205 emitcode ("clr", "c");
6207 /* AOP_TYPE(right) == AOP_CRY */
6211 symbol *lbl = newiTempLabel (NULL);
6212 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6213 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6214 emitcode ("cpl", "c");
6217 /* if true label then we jump if condition
6219 tlbl = newiTempLabel (NULL);
6222 emitcode ("jnc", "%05d$", tlbl->key + 100);
6223 freeForBranchAsmop (result);
6224 freeForBranchAsmop (right);
6225 freeForBranchAsmop (left);
6226 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6230 emitcode ("jc", "%05d$", tlbl->key + 100);
6231 freeForBranchAsmop (result);
6232 freeForBranchAsmop (right);
6233 freeForBranchAsmop (left);
6234 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6240 tlbl = newiTempLabel (NULL);
6241 gencjneshort (left, right, tlbl);
6244 freeForBranchAsmop (result);
6245 freeForBranchAsmop (right);
6246 freeForBranchAsmop (left);
6247 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6252 symbol *lbl = newiTempLabel (NULL);
6253 emitcode ("sjmp", "%05d$", lbl->key + 100);
6255 freeForBranchAsmop (result);
6256 freeForBranchAsmop (right);
6257 freeForBranchAsmop (left);
6258 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6262 /* mark the icode as generated */
6267 /* if they are both bit variables */
6268 if (AOP_TYPE (left) == AOP_CRY &&
6269 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6271 if (AOP_TYPE (right) == AOP_LIT)
6273 unsigned long lit = ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6276 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6277 emitcode ("cpl", "c");
6281 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6285 emitcode ("clr", "c");
6287 /* AOP_TYPE(right) == AOP_CRY */
6291 symbol *lbl = newiTempLabel (NULL);
6292 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6293 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6294 emitcode ("cpl", "c");
6298 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6305 genIfxJump (ifx, "c", left, right, result);
6308 /* if the result is used in an arithmetic operation
6309 then put the result in place */
6314 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6316 gencjne (left, right, newiTempLabel (NULL), TRUE);
6317 aopPut (result, "c", 0);
6320 gencjne (left, right, newiTempLabel (NULL), FALSE);
6323 genIfxJump (ifx, "a", left, right, result);
6326 /* if the result is used in an arithmetic operation
6327 then put the result in place */
6328 if (AOP_TYPE (result) != AOP_CRY)
6330 /* leave the result in acc */
6334 freeAsmop (result, NULL, ic, TRUE);
6337 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6338 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6342 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6343 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6347 /*-----------------------------------------------------------------*/
6348 /* ifxForOp - returns the icode containing the ifx for operand */
6349 /*-----------------------------------------------------------------*/
6351 ifxForOp (operand * op, iCode * ic)
6353 /* if true symbol then needs to be assigned */
6354 if (IS_TRUE_SYMOP (op))
6357 /* if this has register type condition and
6358 the next instruction is ifx with the same operand
6359 and live to of the operand is upto the ifx only then */
6361 ic->next->op == IFX &&
6362 IC_COND (ic->next)->key == op->key &&
6363 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6369 /*-----------------------------------------------------------------*/
6370 /* hasInc - operand is incremented before any other use */
6371 /*-----------------------------------------------------------------*/
6373 hasInc (operand *op, iCode *ic, int osize)
6375 sym_link *type = operandType(op);
6376 sym_link *retype = getSpec (type);
6377 iCode *lic = ic->next;
6380 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6381 if (!IS_SYMOP(op)) return NULL;
6383 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6384 if (IS_AGGREGATE(type->next)) return NULL;
6385 if (osize != (isize = getSize(type->next))) return NULL;
6388 /* if operand of the form op = op + <sizeof *op> */
6389 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6390 isOperandEqual(IC_RESULT(lic),op) &&
6391 isOperandLiteral(IC_RIGHT(lic)) &&
6392 operandLitValue(IC_RIGHT(lic)) == isize) {
6395 /* if the operand used or deffed */
6396 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6399 /* if GOTO or IFX */
6400 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6406 /*-----------------------------------------------------------------*/
6407 /* genAndOp - for && operation */
6408 /*-----------------------------------------------------------------*/
6410 genAndOp (iCode * ic)
6412 operand *left, *right, *result;
6415 D (emitcode (";", "genAndOp"));
6417 /* note here that && operations that are in an
6418 if statement are taken away by backPatchLabels
6419 only those used in arthmetic operations remain */
6420 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6421 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6422 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6424 /* if both are bit variables */
6425 if (AOP_TYPE (left) == AOP_CRY &&
6426 AOP_TYPE (right) == AOP_CRY)
6428 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6429 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6434 tlbl = newiTempLabel (NULL);
6436 emitcode ("jz", "%05d$", tlbl->key + 100);
6442 freeAsmop (result, NULL, ic, TRUE);
6443 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6444 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6448 /*-----------------------------------------------------------------*/
6449 /* genOrOp - for || operation */
6450 /*-----------------------------------------------------------------*/
6452 genOrOp (iCode * ic)
6454 operand *left, *right, *result;
6457 D (emitcode (";", "genOrOp"));
6459 /* note here that || operations that are in an
6460 if statement are taken away by backPatchLabels
6461 only those used in arthmetic operations remain */
6462 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6463 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6464 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6466 /* if both are bit variables */
6467 if (AOP_TYPE (left) == AOP_CRY &&
6468 AOP_TYPE (right) == AOP_CRY)
6470 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6471 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6476 tlbl = newiTempLabel (NULL);
6478 emitcode ("jnz", "%05d$", tlbl->key + 100);
6484 freeAsmop (result, NULL, ic, TRUE);
6485 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6486 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6489 /*-----------------------------------------------------------------*/
6490 /* isLiteralBit - test if lit == 2^n */
6491 /*-----------------------------------------------------------------*/
6493 isLiteralBit (unsigned long lit)
6495 unsigned long pw[32] =
6496 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6497 0x100L, 0x200L, 0x400L, 0x800L,
6498 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6499 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6500 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6501 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6502 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6505 for (idx = 0; idx < 32; idx++)
6511 /*-----------------------------------------------------------------*/
6512 /* continueIfTrue - */
6513 /*-----------------------------------------------------------------*/
6515 continueIfTrue (iCode * ic)
6518 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6522 /*-----------------------------------------------------------------*/
6524 /*-----------------------------------------------------------------*/
6526 jumpIfTrue (iCode * ic)
6529 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6533 /*-----------------------------------------------------------------*/
6534 /* jmpTrueOrFalse - */
6535 /*-----------------------------------------------------------------*/
6537 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6539 // ugly but optimized by peephole
6542 symbol *nlbl = newiTempLabel (NULL);
6543 emitcode ("sjmp", "%05d$", nlbl->key + 100);
6545 freeForBranchAsmop (result);
6546 freeForBranchAsmop (right);
6547 freeForBranchAsmop (left);
6548 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6553 freeForBranchAsmop (result);
6554 freeForBranchAsmop (right);
6555 freeForBranchAsmop (left);
6556 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6562 /*-----------------------------------------------------------------*/
6563 /* genAnd - code for and */
6564 /*-----------------------------------------------------------------*/
6566 genAnd (iCode * ic, iCode * ifx)
6568 operand *left, *right, *result;
6569 int size, offset = 0;
6570 unsigned long lit = 0L;
6574 D (emitcode (";", "genAnd"));
6576 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6577 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6578 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6581 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
6583 AOP_TYPE (left), AOP_TYPE (right));
6584 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
6586 AOP_SIZE (left), AOP_SIZE (right));
6589 /* if left is a literal & right is not then exchange them */
6590 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6591 AOP_NEEDSACC (left))
6593 operand *tmp = right;
6598 /* if result = right then exchange left and right */
6599 if (sameRegs (AOP (result), AOP (right)))
6601 operand *tmp = right;
6606 /* if right is bit then exchange them */
6607 if (AOP_TYPE (right) == AOP_CRY &&
6608 AOP_TYPE (left) != AOP_CRY)
6610 operand *tmp = right;
6614 if (AOP_TYPE (right) == AOP_LIT)
6615 lit = ulFromVal (AOP (right)->aopu.aop_lit);
6617 size = AOP_SIZE (result);
6620 // result = bit & yy;
6621 if (AOP_TYPE (left) == AOP_CRY)
6623 // c = bit & literal;
6624 if (AOP_TYPE (right) == AOP_LIT)
6628 if (size && sameRegs (AOP (result), AOP (left)))
6631 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6636 if (size && (AOP_TYPE (result) == AOP_CRY))
6638 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6641 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6646 emitcode ("clr", "c");
6651 if (AOP_TYPE (right) == AOP_CRY)
6654 if (IS_OP_ACCUSE (left))
6656 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6660 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6661 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6667 MOVA (aopGet (right, 0, FALSE, FALSE));
6669 emitcode ("rrc", "a");
6670 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6678 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6679 genIfxJump (ifx, "c", left, right, result);
6683 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6684 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6685 if ((AOP_TYPE (right) == AOP_LIT) &&
6686 (AOP_TYPE (result) == AOP_CRY) &&
6687 (AOP_TYPE (left) != AOP_CRY))
6689 int posbit = isLiteralBit (lit);
6694 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6698 switch (posbit & 0x07)
6700 case 0: emitcode ("rrc", "a");
6702 case 7: emitcode ("rlc", "a");
6704 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6713 SNPRINTF (buffer, sizeof(buffer),
6714 "acc.%d", posbit & 0x07);
6715 genIfxJump (ifx, buffer, left, right, result);
6718 {// what is this case? just found it in ds390/gen.c
6719 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6726 symbol *tlbl = newiTempLabel (NULL);
6727 int sizel = AOP_SIZE (left);
6729 emitcode ("setb", "c");
6732 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6734 MOVA (aopGet (left, offset, FALSE, FALSE));
6736 if ((posbit = isLiteralBit (bytelit)) != 0)
6737 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6740 if (bytelit != 0x0FFL)
6741 emitcode ("anl", "a,%s",
6742 aopGet (right, offset, FALSE, TRUE));
6743 emitcode ("jnz", "%05d$", tlbl->key + 100);
6748 // bit = left & literal
6751 emitcode ("clr", "c");
6754 // if(left & literal)
6758 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6768 /* if left is same as result */
6769 if (sameRegs (AOP (result), AOP (left)))
6771 for (; size--; offset++)
6773 if (AOP_TYPE (right) == AOP_LIT)
6775 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6776 if (bytelit == 0x0FF)
6778 /* dummy read of volatile operand */
6779 if (isOperandVolatile (left, FALSE))
6780 MOVA (aopGet (left, offset, FALSE, FALSE));
6784 else if (bytelit == 0)
6786 aopPut (result, zero, offset);
6788 else if (IS_AOP_PREG (result))
6790 MOVA (aopGet (left, offset, FALSE, TRUE));
6791 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6792 aopPut (result, "a", offset);
6795 emitcode ("anl", "%s,%s",
6796 aopGet (left, offset, FALSE, TRUE),
6797 aopGet (right, offset, FALSE, FALSE));
6801 if (AOP_TYPE (left) == AOP_ACC)
6804 emitcode("mov", "a,b");
6805 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6807 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6809 MOVB (aopGet (left, offset, FALSE, FALSE));
6810 MOVA (aopGet (right, offset, FALSE, FALSE));
6811 emitcode ("anl", "a,b");
6812 aopPut (result, "a", offset);
6814 else if (aopGetUsesAcc (left, offset))
6816 MOVA (aopGet (left, offset, FALSE, FALSE));
6817 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6818 aopPut (result, "a", offset);
6822 MOVA (aopGet (right, offset, FALSE, FALSE));
6823 if (IS_AOP_PREG (result))
6825 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6826 aopPut (result, "a", offset);
6829 emitcode ("anl", "%s,a", aopGet (left, offset, FALSE, TRUE));
6836 // left & result in different registers
6837 if (AOP_TYPE (result) == AOP_CRY)
6840 // if(size), result in bit
6841 // if(!size && ifx), conditional oper: if(left & right)
6842 symbol *tlbl = newiTempLabel (NULL);
6843 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6845 emitcode ("setb", "c");
6848 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6849 && AOP_TYPE(left)==AOP_ACC)
6852 emitcode("mov", "a,b");
6853 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6855 else if (AOP_TYPE(left)==AOP_ACC)
6859 bool pushedB = pushB ();
6860 emitcode("mov", "b,a");
6861 MOVA (aopGet (right, offset, FALSE, FALSE));
6862 emitcode("anl", "a,b");
6867 MOVA (aopGet (right, offset, FALSE, FALSE));
6868 emitcode("anl", "a,b");
6871 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6873 MOVB (aopGet (left, offset, FALSE, FALSE));
6874 MOVA (aopGet (right, offset, FALSE, FALSE));
6875 emitcode ("anl", "a,b");
6877 else if (aopGetUsesAcc (left, offset))
6879 MOVA (aopGet (left, offset, FALSE, FALSE));
6880 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6884 MOVA (aopGet (right, offset, FALSE, FALSE));
6885 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6888 emitcode ("jnz", "%05d$", tlbl->key + 100);
6898 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6904 for (; (size--); offset++)
6907 // result = left & right
6908 if (AOP_TYPE (right) == AOP_LIT)
6910 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6911 if (bytelit == 0x0FF)
6914 aopGet (left, offset, FALSE, FALSE),
6918 else if (bytelit == 0)
6920 /* dummy read of volatile operand */
6921 if (isOperandVolatile (left, FALSE))
6922 MOVA (aopGet (left, offset, FALSE, FALSE));
6923 aopPut (result, zero, offset);
6926 else if (AOP_TYPE (left) == AOP_ACC)
6930 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6931 aopPut (result, "a", offset);
6936 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6937 aopPut (result, "b", offset);
6942 // faster than result <- left, anl result,right
6943 // and better if result is SFR
6944 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6945 && AOP_TYPE(left)==AOP_ACC)
6948 emitcode("mov", "a,b");
6949 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6951 else if (AOP_TYPE(left)==AOP_ACC)
6955 bool pushedB = pushB ();
6956 emitcode("mov", "b,a");
6957 MOVA (aopGet (right, offset, FALSE, FALSE));
6958 emitcode("anl", "a,b");
6963 MOVA (aopGet (right, offset, FALSE, FALSE));
6964 emitcode("anl", "a,b");
6967 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6969 MOVB (aopGet (left, offset, FALSE, FALSE));
6970 MOVA (aopGet (right, offset, FALSE, FALSE));
6971 emitcode ("anl", "a,b");
6973 else if (aopGetUsesAcc (left, offset))
6975 MOVA (aopGet (left, offset, FALSE, FALSE));
6976 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6980 MOVA (aopGet (right, offset, FALSE, FALSE));
6981 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6983 aopPut (result, "a", offset);
6989 freeAsmop (result, NULL, ic, TRUE);
6990 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6991 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6994 /*-----------------------------------------------------------------*/
6995 /* genOr - code for or */
6996 /*-----------------------------------------------------------------*/
6998 genOr (iCode * ic, iCode * ifx)
7000 operand *left, *right, *result;
7001 int size, offset = 0;
7002 unsigned long lit = 0L;
7005 D (emitcode (";", "genOr"));
7007 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7008 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7009 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7012 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
7014 AOP_TYPE (left), AOP_TYPE (right));
7015 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
7017 AOP_SIZE (left), AOP_SIZE (right));
7020 /* if left is a literal & right is not then exchange them */
7021 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7022 AOP_NEEDSACC (left))
7024 operand *tmp = right;
7029 /* if result = right then exchange them */
7030 if (sameRegs (AOP (result), AOP (right)))
7032 operand *tmp = right;
7037 /* if right is bit then exchange them */
7038 if (AOP_TYPE (right) == AOP_CRY &&
7039 AOP_TYPE (left) != AOP_CRY)
7041 operand *tmp = right;
7045 if (AOP_TYPE (right) == AOP_LIT)
7046 lit = ulFromVal (AOP (right)->aopu.aop_lit);
7048 size = AOP_SIZE (result);
7052 if (AOP_TYPE (left) == AOP_CRY)
7054 if (AOP_TYPE (right) == AOP_LIT)
7056 // c = bit | literal;
7059 // lit != 0 => result = 1
7060 if (AOP_TYPE (result) == AOP_CRY)
7063 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7065 continueIfTrue (ifx);
7068 emitcode ("setb", "c");
7072 // lit == 0 => result = left
7073 if (size && sameRegs (AOP (result), AOP (left)))
7075 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7080 if (AOP_TYPE (right) == AOP_CRY)
7083 if (IS_OP_ACCUSE (left))
7085 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
7089 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7090 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7096 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7098 symbol *tlbl = newiTempLabel (NULL);
7099 emitcode ("jb", "%s,%05d$",
7100 AOP (left)->aopu.aop_dir, tlbl->key + 100);
7102 emitcode ("jnz", "%05d$", tlbl->key + 100);
7103 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7109 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7118 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7119 genIfxJump (ifx, "c", left, right, result);
7123 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7124 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7125 if ((AOP_TYPE (right) == AOP_LIT) &&
7126 (AOP_TYPE (result) == AOP_CRY) &&
7127 (AOP_TYPE (left) != AOP_CRY))
7133 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7135 continueIfTrue (ifx);
7140 // lit = 0, result = boolean(left)
7142 emitcode ("setb", "c");
7146 symbol *tlbl = newiTempLabel (NULL);
7147 emitcode ("jnz", "%05d$", tlbl->key + 100);
7153 genIfxJump (ifx, "a", left, right, result);
7161 /* if left is same as result */
7162 if (sameRegs (AOP (result), AOP (left)))
7164 for (; size--; offset++)
7166 if (AOP_TYPE (right) == AOP_LIT)
7168 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7171 /* dummy read of volatile operand */
7172 if (isOperandVolatile (left, FALSE))
7173 MOVA (aopGet (left, offset, FALSE, FALSE));
7177 else if (bytelit == 0x0FF)
7179 aopPut (result, "#0xff", offset);
7181 else if (IS_AOP_PREG (left))
7183 MOVA (aopGet (left, offset, FALSE, TRUE));
7184 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7185 aopPut (result, "a", offset);
7189 emitcode ("orl", "%s,%s",
7190 aopGet (left, offset, FALSE, TRUE),
7191 aopGet (right, offset, FALSE, FALSE));
7196 if (AOP_TYPE (left) == AOP_ACC)
7199 emitcode("mov", "a,b");
7200 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7202 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7204 MOVB (aopGet (left, offset, FALSE, FALSE));
7205 MOVA (aopGet (right, offset, FALSE, FALSE));
7206 emitcode ("orl", "a,b");
7207 aopPut (result, "a", offset);
7209 else if (aopGetUsesAcc (left, offset))
7211 MOVA (aopGet (left, offset, FALSE, FALSE));
7212 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7213 aopPut (result, "a", offset);
7217 MOVA (aopGet (right, offset, FALSE, FALSE));
7218 if (IS_AOP_PREG (left))
7220 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7221 aopPut (result, "a", offset);
7225 emitcode ("orl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7233 // left & result in different registers
7234 if (AOP_TYPE (result) == AOP_CRY)
7237 // if(size), result in bit
7238 // if(!size && ifx), conditional oper: if(left | right)
7239 symbol *tlbl = newiTempLabel (NULL);
7240 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7242 emitcode ("setb", "c");
7245 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7246 && AOP_TYPE(left)==AOP_ACC)
7249 emitcode("mov", "a,b");
7250 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7252 else if (AOP_TYPE(left)==AOP_ACC)
7256 bool pushedB = pushB ();
7257 emitcode("mov", "b,a");
7258 MOVA (aopGet (right, offset, FALSE, FALSE));
7259 emitcode("orl", "a,b");
7264 MOVA (aopGet (right, offset, FALSE, FALSE));
7265 emitcode("orl", "a,b");
7268 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7270 MOVB (aopGet (left, offset, FALSE, FALSE));
7271 MOVA (aopGet (right, offset, FALSE, FALSE));
7272 emitcode ("orl", "a,b");
7274 else if (aopGetUsesAcc (left, offset))
7276 MOVA (aopGet (left, offset, FALSE, FALSE));
7277 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7281 MOVA (aopGet (right, offset, FALSE, FALSE));
7282 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7285 emitcode ("jnz", "%05d$", tlbl->key + 100);
7295 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7301 for (; (size--); offset++)
7304 // result = left | right
7305 if (AOP_TYPE (right) == AOP_LIT)
7307 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7311 aopGet (left, offset, FALSE, FALSE),
7315 else if (bytelit == 0x0FF)
7317 /* dummy read of volatile operand */
7318 if (isOperandVolatile (left, FALSE))
7319 MOVA (aopGet (left, offset, FALSE, FALSE));
7320 aopPut (result, "#0xff", offset);
7324 // faster than result <- left, orl result,right
7325 // and better if result is SFR
7326 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7327 && AOP_TYPE(left)==AOP_ACC)
7330 emitcode("mov", "a,b");
7331 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7333 else if (AOP_TYPE(left)==AOP_ACC)
7337 bool pushedB = pushB ();
7338 emitcode("mov", "b,a");
7339 MOVA (aopGet (right, offset, FALSE, FALSE));
7340 emitcode("orl", "a,b");
7345 MOVA (aopGet (right, offset, FALSE, FALSE));
7346 emitcode("orl", "a,b");
7349 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7351 MOVB (aopGet (left, offset, FALSE, FALSE));
7352 MOVA (aopGet (right, offset, FALSE, FALSE));
7353 emitcode ("orl", "a,b");
7355 else if (aopGetUsesAcc (left, offset))
7357 MOVA (aopGet (left, offset, FALSE, FALSE));
7358 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7362 MOVA (aopGet (right, offset, FALSE, FALSE));
7363 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7365 aopPut (result, "a", offset);
7371 freeAsmop (result, NULL, ic, TRUE);
7372 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7373 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7376 /*-----------------------------------------------------------------*/
7377 /* genXor - code for xclusive or */
7378 /*-----------------------------------------------------------------*/
7380 genXor (iCode * ic, iCode * ifx)
7382 operand *left, *right, *result;
7383 int size, offset = 0;
7384 unsigned long lit = 0L;
7387 D (emitcode (";", "genXor"));
7389 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7390 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7391 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7394 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
7396 AOP_TYPE (left), AOP_TYPE (right));
7397 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
7399 AOP_SIZE (left), AOP_SIZE (right));
7402 /* if left is a literal & right is not ||
7403 if left needs acc & right does not */
7404 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7405 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7407 operand *tmp = right;
7412 /* if result = right then exchange them */
7413 if (sameRegs (AOP (result), AOP (right)))
7415 operand *tmp = right;
7420 /* if right is bit then exchange them */
7421 if (AOP_TYPE (right) == AOP_CRY &&
7422 AOP_TYPE (left) != AOP_CRY)
7424 operand *tmp = right;
7429 if (AOP_TYPE (right) == AOP_LIT)
7430 lit = ulFromVal (AOP (right)->aopu.aop_lit);
7432 size = AOP_SIZE (result);
7436 if (AOP_TYPE (left) == AOP_CRY)
7438 if (AOP_TYPE (right) == AOP_LIT)
7440 // c = bit & literal;
7443 // lit>>1 != 0 => result = 1
7444 if (AOP_TYPE (result) == AOP_CRY)
7447 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7449 continueIfTrue (ifx);
7452 emitcode ("setb", "c");
7459 // lit == 0, result = left
7460 if (size && sameRegs (AOP (result), AOP (left)))
7462 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7466 // lit == 1, result = not(left)
7467 if (size && sameRegs (AOP (result), AOP (left)))
7469 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7474 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7475 emitcode ("cpl", "c");
7483 symbol *tlbl = newiTempLabel (NULL);
7484 if (AOP_TYPE (right) == AOP_CRY)
7487 if (IS_OP_ACCUSE (left))
7488 {// left already is in the carry
7489 operand *tmp = right;
7503 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7504 emitcode ("cpl", "c");
7512 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7513 genIfxJump (ifx, "c", left, right, result);
7517 /* if left is same as result */
7518 if (sameRegs (AOP (result), AOP (left)))
7520 for (; size--; offset++)
7522 if (AOP_TYPE (right) == AOP_LIT)
7524 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7527 /* dummy read of volatile operand */
7528 if (isOperandVolatile (left, FALSE))
7529 MOVA (aopGet (left, offset, FALSE, FALSE));
7533 else if (IS_AOP_PREG (left))
7535 MOVA (aopGet (left, offset, FALSE, TRUE));
7536 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7537 aopPut (result, "a", offset);
7541 emitcode ("xrl", "%s,%s",
7542 aopGet (left, offset, FALSE, TRUE),
7543 aopGet (right, offset, FALSE, FALSE));
7548 if (AOP_TYPE (left) == AOP_ACC)
7551 emitcode("mov", "a,b");
7552 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7554 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7556 MOVB (aopGet (left, offset, FALSE, FALSE));
7557 MOVA (aopGet (right, offset, FALSE, FALSE));
7558 emitcode ("xrl", "a,b");
7559 aopPut (result, "a", offset);
7561 else if (aopGetUsesAcc (left, offset))
7563 MOVA (aopGet (left, offset, FALSE, FALSE));
7564 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7565 aopPut (result, "a", offset);
7569 MOVA (aopGet (right, offset, FALSE, FALSE));
7570 if (IS_AOP_PREG (left))
7572 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7573 aopPut (result, "a", offset);
7576 emitcode ("xrl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7583 // left & result in different registers
7584 if (AOP_TYPE (result) == AOP_CRY)
7587 // if(size), result in bit
7588 // if(!size && ifx), conditional oper: if(left ^ right)
7589 symbol *tlbl = newiTempLabel (NULL);
7590 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7593 emitcode ("setb", "c");
7596 if ((AOP_TYPE (right) == AOP_LIT) &&
7597 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7599 MOVA (aopGet (left, offset, FALSE, FALSE));
7601 else if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7602 && AOP_TYPE(left)==AOP_ACC)
7605 emitcode("mov", "a,b");
7606 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7608 else if (AOP_TYPE(left)==AOP_ACC)
7612 bool pushedB = pushB ();
7613 emitcode("mov", "b,a");
7614 MOVA (aopGet (right, offset, FALSE, FALSE));
7615 emitcode("xrl", "a,b");
7620 MOVA (aopGet (right, offset, FALSE, FALSE));
7621 emitcode("xrl", "a,b");
7624 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7626 MOVB (aopGet (left, offset, FALSE, FALSE));
7627 MOVA (aopGet (right, offset, FALSE, FALSE));
7628 emitcode ("xrl", "a,b");
7630 else if (aopGetUsesAcc (left, offset))
7632 MOVA (aopGet (left, offset, FALSE, FALSE));
7633 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7637 MOVA (aopGet (right, offset, FALSE, FALSE));
7638 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7641 emitcode ("jnz", "%05d$", tlbl->key + 100);
7651 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7655 for (; (size--); offset++)
7658 // result = left ^ right
7659 if (AOP_TYPE (right) == AOP_LIT)
7661 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7665 aopGet (left, offset, FALSE, FALSE),
7670 // faster than result <- left, xrl result,right
7671 // and better if result is SFR
7672 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7673 && AOP_TYPE(left)==AOP_ACC)
7676 emitcode("mov", "a,b");
7677 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7679 else if (AOP_TYPE(left)==AOP_ACC)
7683 bool pushedB = pushB ();
7684 emitcode("mov", "b,a");
7685 MOVA (aopGet (right, offset, FALSE, FALSE));
7686 emitcode("xrl", "a,b");
7691 MOVA (aopGet (right, offset, FALSE, FALSE));
7692 emitcode("xrl", "a,b");
7695 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7697 MOVB (aopGet (left, offset, FALSE, FALSE));
7698 MOVA (aopGet (right, offset, FALSE, FALSE));
7699 emitcode ("xrl", "a,b");
7701 else if (aopGetUsesAcc (left, offset))
7703 MOVA (aopGet (left, offset, FALSE, FALSE));
7704 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7708 MOVA (aopGet (right, offset, FALSE, FALSE));
7709 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7711 aopPut (result, "a", offset);
7717 freeAsmop (result, NULL, ic, TRUE);
7718 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7719 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7722 /*-----------------------------------------------------------------*/
7723 /* genInline - write the inline code out */
7724 /*-----------------------------------------------------------------*/
7726 genInline (iCode * ic)
7728 char *buffer, *bp, *bp1;
7729 bool inComment = FALSE;
7731 D (emitcode (";", "genInline"));
7733 _G.inLine += (!options.asmpeep);
7735 buffer = bp = bp1 = Safe_strdup (IC_INLINE (ic));
7737 /* emit each line as a code */
7755 /* Add \n for labels, not dirs such as c:\mydir */
7756 if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
7774 _G.inLine -= (!options.asmpeep);
7777 /*-----------------------------------------------------------------*/
7778 /* genRRC - rotate right with carry */
7779 /*-----------------------------------------------------------------*/
7783 operand *left, *result;
7787 D (emitcode (";", "genRRC"));
7789 /* rotate right with carry */
7790 left = IC_LEFT (ic);
7791 result = IC_RESULT (ic);
7792 aopOp (left, ic, FALSE);
7793 aopOp (result, ic, FALSE);
7795 /* move it to the result */
7796 size = AOP_SIZE (result);
7798 if (size == 1) { /* special case for 1 byte */
7799 l = aopGet (left, offset, FALSE, FALSE);
7801 emitcode ("rr", "a");
7804 /* no need to clear carry, bit7 will be written later */
7807 l = aopGet (left, offset, FALSE, FALSE);
7809 emitcode ("rrc", "a");
7810 if (AOP_SIZE (result) > 1)
7811 aopPut (result, "a", offset--);
7813 /* now we need to put the carry into the
7814 highest order byte of the result */
7815 if (AOP_SIZE (result) > 1)
7817 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7820 emitcode ("mov", "acc.7,c");
7822 aopPut (result, "a", AOP_SIZE (result) - 1);
7823 freeAsmop (result, NULL, ic, TRUE);
7824 freeAsmop (left, NULL, ic, TRUE);
7827 /*-----------------------------------------------------------------*/
7828 /* genRLC - generate code for rotate left with carry */
7829 /*-----------------------------------------------------------------*/
7833 operand *left, *result;
7837 D (emitcode (";", "genRLC"));
7839 /* rotate right with carry */
7840 left = IC_LEFT (ic);
7841 result = IC_RESULT (ic);
7842 aopOp (left, ic, FALSE);
7843 aopOp (result, ic, FALSE);
7845 /* move it to the result */
7846 size = AOP_SIZE (result);
7850 l = aopGet (left, offset, FALSE, FALSE);
7852 if (size == 0) { /* special case for 1 byte */
7856 emitcode("rlc","a"); /* bit0 will be written later */
7857 if (AOP_SIZE (result) > 1)
7859 aopPut (result, "a", offset++);
7864 l = aopGet (left, offset, FALSE, FALSE);
7866 emitcode ("rlc", "a");
7867 if (AOP_SIZE (result) > 1)
7868 aopPut (result, "a", offset++);
7871 /* now we need to put the carry into the
7872 highest order byte of the result */
7873 if (AOP_SIZE (result) > 1)
7875 l = aopGet (result, 0, FALSE, FALSE);
7878 emitcode ("mov", "acc.0,c");
7880 aopPut (result, "a", 0);
7881 freeAsmop (result, NULL, ic, TRUE);
7882 freeAsmop (left, NULL, ic, TRUE);
7885 /*-----------------------------------------------------------------*/
7886 /* genGetHbit - generates code get highest order bit */
7887 /*-----------------------------------------------------------------*/
7889 genGetHbit (iCode * ic)
7891 operand *left, *result;
7893 D (emitcode (";", "genGetHbit"));
7895 left = IC_LEFT (ic);
7896 result = IC_RESULT (ic);
7897 aopOp (left, ic, FALSE);
7898 aopOp (result, ic, FALSE);
7900 /* get the highest order byte into a */
7901 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7902 if (AOP_TYPE (result) == AOP_CRY)
7904 emitcode ("rlc", "a");
7909 emitcode ("rl", "a");
7910 emitcode ("anl", "a,#0x01");
7914 freeAsmop (result, NULL, ic, TRUE);
7915 freeAsmop (left, NULL, ic, TRUE);
7918 /*-----------------------------------------------------------------*/
7919 /* genGetAbit - generates code get a single bit */
7920 /*-----------------------------------------------------------------*/
7922 genGetAbit (iCode * ic)
7924 operand *left, *right, *result;
7927 D (emitcode (";", "genGetAbit"));
7929 left = IC_LEFT (ic);
7930 right = IC_RIGHT (ic);
7931 result = IC_RESULT (ic);
7932 aopOp (left, ic, FALSE);
7933 aopOp (right, ic, FALSE);
7934 aopOp (result, ic, FALSE);
7936 shCount = (int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7938 /* get the needed byte into a */
7939 MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7941 if (AOP_TYPE (result) == AOP_CRY)
7944 emitcode ("rlc", "a");
7945 else if ((shCount) == 0)
7946 emitcode ("rrc", "a");
7948 emitcode ("mov", "c,acc[%d]", shCount);
7956 emitcode ("rr", "a");
7959 emitcode ("rr", "a");
7962 emitcode ("anl", "a,#0x01");
7966 emitcode ("mov", "c,acc[%d]", shCount);
7967 emitcode ("clr", "a");
7968 emitcode ("rlc", "a");
7971 emitcode ("swap", "a");
7972 emitcode ("anl", "a,#0x01");
7975 emitcode ("rl", "a");
7978 emitcode ("rl", "a");
7979 emitcode ("anl", "a,#0x01");
7985 freeAsmop (result, NULL, ic, TRUE);
7986 freeAsmop (right, NULL, ic, TRUE);
7987 freeAsmop (left, NULL, ic, TRUE);
7990 /*-----------------------------------------------------------------*/
7991 /* genGetByte - generates code get a single byte */
7992 /*-----------------------------------------------------------------*/
7994 genGetByte (iCode * ic)
7996 operand *left, *right, *result;
7999 D (emitcode (";", "genGetByte"));
8001 left = IC_LEFT (ic);
8002 right = IC_RIGHT (ic);
8003 result = IC_RESULT (ic);
8004 aopOp (left, ic, FALSE);
8005 aopOp (right, ic, FALSE);
8006 aopOp (result, ic, FALSE);
8008 offset = (int) ulFromVal (AOP (right)->aopu.aop_lit) / 8;
8010 aopGet (left, offset, FALSE, FALSE),
8013 freeAsmop (result, NULL, ic, TRUE);
8014 freeAsmop (right, NULL, ic, TRUE);
8015 freeAsmop (left, NULL, ic, TRUE);
8018 /*-----------------------------------------------------------------*/
8019 /* genGetWord - generates code get two bytes */
8020 /*-----------------------------------------------------------------*/
8022 genGetWord (iCode * ic)
8024 operand *left, *right, *result;
8027 D (emitcode (";", "genGetWord"));
8029 left = IC_LEFT (ic);
8030 right = IC_RIGHT (ic);
8031 result = IC_RESULT (ic);
8032 aopOp (left, ic, FALSE);
8033 aopOp (right, ic, FALSE);
8034 aopOp (result, ic, FALSE);
8036 offset = (int) ulFromVal (AOP (right)->aopu.aop_lit) / 8;
8038 aopGet (left, offset, FALSE, FALSE),
8041 aopGet (left, offset+1, FALSE, FALSE),
8044 freeAsmop (result, NULL, ic, TRUE);
8045 freeAsmop (right, NULL, ic, TRUE);
8046 freeAsmop (left, NULL, ic, TRUE);
8049 /*-----------------------------------------------------------------*/
8050 /* genSwap - generates code to swap nibbles or bytes */
8051 /*-----------------------------------------------------------------*/
8053 genSwap (iCode * ic)
8055 operand *left, *result;
8057 D(emitcode (";", "genSwap"));
8059 left = IC_LEFT (ic);
8060 result = IC_RESULT (ic);
8061 aopOp (left, ic, FALSE);
8062 aopOp (result, ic, FALSE);
8064 switch (AOP_SIZE (left))
8066 case 1: /* swap nibbles in byte */
8067 MOVA (aopGet (left, 0, FALSE, FALSE));
8068 emitcode ("swap", "a");
8069 aopPut (result, "a", 0);
8071 case 2: /* swap bytes in word */
8072 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
8074 MOVA (aopGet (left, 0, FALSE, FALSE));
8075 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8076 aopPut (result, "a", 1);
8078 else if (operandsEqu (left, result))
8081 bool pushedB = FALSE, leftInB = FALSE;
8083 MOVA (aopGet (left, 0, FALSE, FALSE));
8084 if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
8087 emitcode ("mov", "b,a");
8091 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8092 aopPut (result, reg, 1);
8099 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8100 aopPut (result, aopGet (left, 0, FALSE, FALSE), 1);
8104 wassertl(FALSE, "unsupported SWAP operand size");
8107 freeAsmop (result, NULL, ic, TRUE);
8108 freeAsmop (left, NULL, ic, TRUE);
8111 /*-----------------------------------------------------------------*/
8112 /* AccRol - rotate left accumulator by known count */
8113 /*-----------------------------------------------------------------*/
8115 AccRol (int shCount)
8117 shCount &= 0x0007; // shCount : 0..7
8124 emitcode ("rl", "a");
8127 emitcode ("rl", "a");
8128 emitcode ("rl", "a");
8131 emitcode ("swap", "a");
8132 emitcode ("rr", "a");
8135 emitcode ("swap", "a");
8138 emitcode ("swap", "a");
8139 emitcode ("rl", "a");
8142 emitcode ("rr", "a");
8143 emitcode ("rr", "a");
8146 emitcode ("rr", "a");
8151 /*-----------------------------------------------------------------*/
8152 /* AccLsh - left shift accumulator by known count */
8153 /*-----------------------------------------------------------------*/
8155 AccLsh (int shCount)
8160 emitcode ("add", "a,acc");
8161 else if (shCount == 2)
8163 emitcode ("add", "a,acc");
8164 emitcode ("add", "a,acc");
8168 /* rotate left accumulator */
8170 /* and kill the lower order bits */
8171 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
8176 /*-----------------------------------------------------------------*/
8177 /* AccRsh - right shift accumulator by known count */
8178 /*-----------------------------------------------------------------*/
8180 AccRsh (int shCount)
8187 emitcode ("rrc", "a");
8191 /* rotate right accumulator */
8192 AccRol (8 - shCount);
8193 /* and kill the higher order bits */
8194 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8199 /*-----------------------------------------------------------------*/
8200 /* AccSRsh - signed right shift accumulator by known count */
8201 /*-----------------------------------------------------------------*/
8203 AccSRsh (int shCount)
8210 emitcode ("mov", "c,acc.7");
8211 emitcode ("rrc", "a");
8213 else if (shCount == 2)
8215 emitcode ("mov", "c,acc.7");
8216 emitcode ("rrc", "a");
8217 emitcode ("mov", "c,acc.7");
8218 emitcode ("rrc", "a");
8222 tlbl = newiTempLabel (NULL);
8223 /* rotate right accumulator */
8224 AccRol (8 - shCount);
8225 /* and kill the higher order bits */
8226 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8227 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8228 emitcode ("orl", "a,#0x%02x",
8229 (unsigned char) ~SRMask[shCount]);
8235 /*-----------------------------------------------------------------*/
8236 /* shiftR1Left2Result - shift right one byte from left to result */
8237 /*-----------------------------------------------------------------*/
8239 shiftR1Left2Result (operand * left, int offl,
8240 operand * result, int offr,
8241 int shCount, int sign)
8243 MOVA (aopGet (left, offl, FALSE, FALSE));
8244 /* shift right accumulator */
8249 aopPut (result, "a", offr);
8252 /*-----------------------------------------------------------------*/
8253 /* shiftL1Left2Result - shift left one byte from left to result */
8254 /*-----------------------------------------------------------------*/
8256 shiftL1Left2Result (operand * left, int offl,
8257 operand * result, int offr, int shCount)
8260 l = aopGet (left, offl, FALSE, FALSE);
8262 /* shift left accumulator */
8264 aopPut (result, "a", offr);
8267 /*-----------------------------------------------------------------*/
8268 /* movLeft2Result - move byte from left to result */
8269 /*-----------------------------------------------------------------*/
8271 movLeft2Result (operand * left, int offl,
8272 operand * result, int offr, int sign)
8275 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8277 l = aopGet (left, offl, FALSE, FALSE);
8279 if (*l == '@' && (IS_AOP_PREG (result)))
8281 emitcode ("mov", "a,%s", l);
8282 aopPut (result, "a", offr);
8288 aopPut (result, l, offr);
8292 /* MSB sign in acc.7 ! */
8293 if (getDataSize (left) == offl + 1)
8296 aopPut (result, "a", offr);
8303 /*-----------------------------------------------------------------*/
8304 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
8305 /*-----------------------------------------------------------------*/
8309 emitcode ("rrc", "a");
8310 emitcode ("xch", "a,%s", x);
8311 emitcode ("rrc", "a");
8312 emitcode ("xch", "a,%s", x);
8315 /*-----------------------------------------------------------------*/
8316 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
8317 /*-----------------------------------------------------------------*/
8321 emitcode ("xch", "a,%s", x);
8322 emitcode ("rlc", "a");
8323 emitcode ("xch", "a,%s", x);
8324 emitcode ("rlc", "a");
8327 /*-----------------------------------------------------------------*/
8328 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8329 /*-----------------------------------------------------------------*/
8333 emitcode ("xch", "a,%s", x);
8334 emitcode ("add", "a,acc");
8335 emitcode ("xch", "a,%s", x);
8336 emitcode ("rlc", "a");
8339 /*-----------------------------------------------------------------*/
8340 /* AccAXLsh - left shift a:x by known count (0..7) */
8341 /*-----------------------------------------------------------------*/
8343 AccAXLsh (char *x, int shCount)
8358 case 5: // AAAAABBB:CCCCCDDD
8360 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8362 emitcode ("anl", "a,#0x%02x",
8363 SLMask[shCount]); // BBB00000:CCCCCDDD
8365 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8367 AccRol (shCount); // DDDCCCCC:BBB00000
8369 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8371 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8373 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8375 emitcode ("anl", "a,#0x%02x",
8376 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8378 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8380 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8383 case 6: // AAAAAABB:CCCCCCDD
8384 emitcode ("anl", "a,#0x%02x",
8385 SRMask[shCount]); // 000000BB:CCCCCCDD
8386 emitcode ("mov", "c,acc.0"); // c = B
8387 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8389 AccAXRrl1 (x); // BCCCCCCD:D000000B
8390 AccAXRrl1 (x); // BBCCCCCC:DD000000
8392 emitcode("rrc","a");
8393 emitcode("xch","a,%s", x);
8394 emitcode("rrc","a");
8395 emitcode("mov","c,acc.0"); //<< get correct bit
8396 emitcode("xch","a,%s", x);
8398 emitcode("rrc","a");
8399 emitcode("xch","a,%s", x);
8400 emitcode("rrc","a");
8401 emitcode("xch","a,%s", x);
8404 case 7: // a:x <<= 7
8406 emitcode ("anl", "a,#0x%02x",
8407 SRMask[shCount]); // 0000000B:CCCCCCCD
8409 emitcode ("mov", "c,acc.0"); // c = B
8411 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
8413 AccAXRrl1 (x); // BCCCCCCC:D0000000
8421 /*-----------------------------------------------------------------*/
8422 /* AccAXRsh - right shift a:x known count (0..7) */
8423 /*-----------------------------------------------------------------*/
8425 AccAXRsh (char *x, int shCount)
8433 AccAXRrl1 (x); // 0->a:x
8438 AccAXRrl1 (x); // 0->a:x
8441 AccAXRrl1 (x); // 0->a:x
8446 case 5: // AAAAABBB:CCCCCDDD = a:x
8448 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8450 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8452 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8454 emitcode ("anl", "a,#0x%02x",
8455 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8457 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8459 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8461 emitcode ("anl", "a,#0x%02x",
8462 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8464 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8466 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8468 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8471 case 6: // AABBBBBB:CCDDDDDD
8473 emitcode ("mov", "c,acc.7");
8474 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8476 emitcode ("mov", "c,acc.7");
8477 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8479 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8481 emitcode ("anl", "a,#0x%02x",
8482 SRMask[shCount]); // 000000AA:BBBBBBCC
8485 case 7: // ABBBBBBB:CDDDDDDD
8487 emitcode ("mov", "c,acc.7"); // c = A
8489 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8491 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8493 emitcode ("anl", "a,#0x%02x",
8494 SRMask[shCount]); // 0000000A:BBBBBBBC
8502 /*-----------------------------------------------------------------*/
8503 /* AccAXRshS - right shift signed a:x known count (0..7) */
8504 /*-----------------------------------------------------------------*/
8506 AccAXRshS (char *x, int shCount)
8514 emitcode ("mov", "c,acc.7");
8515 AccAXRrl1 (x); // s->a:x
8519 emitcode ("mov", "c,acc.7");
8520 AccAXRrl1 (x); // s->a:x
8522 emitcode ("mov", "c,acc.7");
8523 AccAXRrl1 (x); // s->a:x
8528 case 5: // AAAAABBB:CCCCCDDD = a:x
8530 tlbl = newiTempLabel (NULL);
8531 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8533 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8535 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8537 emitcode ("anl", "a,#0x%02x",
8538 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8540 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8542 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8544 emitcode ("anl", "a,#0x%02x",
8545 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8547 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8549 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8551 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8553 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8554 emitcode ("orl", "a,#0x%02x",
8555 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8558 break; // SSSSAAAA:BBBCCCCC
8560 case 6: // AABBBBBB:CCDDDDDD
8562 tlbl = newiTempLabel (NULL);
8563 emitcode ("mov", "c,acc.7");
8564 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8566 emitcode ("mov", "c,acc.7");
8567 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8569 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8571 emitcode ("anl", "a,#0x%02x",
8572 SRMask[shCount]); // 000000AA:BBBBBBCC
8574 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8575 emitcode ("orl", "a,#0x%02x",
8576 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8580 case 7: // ABBBBBBB:CDDDDDDD
8582 tlbl = newiTempLabel (NULL);
8583 emitcode ("mov", "c,acc.7"); // c = A
8585 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8587 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8589 emitcode ("anl", "a,#0x%02x",
8590 SRMask[shCount]); // 0000000A:BBBBBBBC
8592 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8593 emitcode ("orl", "a,#0x%02x",
8594 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8603 /*-----------------------------------------------------------------*/
8604 /* shiftL2Left2Result - shift left two bytes from left to result */
8605 /*-----------------------------------------------------------------*/
8607 shiftL2Left2Result (operand * left, int offl,
8608 operand * result, int offr, int shCount)
8611 bool pushedB = FALSE;
8614 if (sameRegs (AOP (result), AOP (left)) &&
8615 ((offl + MSB16) == offr))
8617 /* don't crash result[offr] */
8618 MOVA (aopGet (left, offl, FALSE, FALSE));
8619 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8620 usedB = !strncmp(x, "b", 1);
8622 else if (aopGetUsesAcc (result, offr))
8624 movLeft2Result (left, offl, result, offr, 0);
8627 emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8628 MOVA (aopGet (result, offr, FALSE, FALSE));
8629 emitcode ("xch", "a,b");
8634 movLeft2Result (left, offl, result, offr, 0);
8635 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8636 x = aopGet (result, offr, FALSE, FALSE);
8638 /* ax << shCount (x = lsb(result)) */
8639 AccAXLsh (x, shCount);
8642 emitcode ("xch", "a,b");
8643 aopPut (result, "a", offr);
8644 aopPut (result, "b", offr + MSB16);
8649 aopPut (result, "a", offr + MSB16);
8654 /*-----------------------------------------------------------------*/
8655 /* shiftR2Left2Result - shift right two bytes from left to result */
8656 /*-----------------------------------------------------------------*/
8658 shiftR2Left2Result (operand * left, int offl,
8659 operand * result, int offr,
8660 int shCount, int sign)
8663 bool pushedB = FALSE;
8666 if (sameRegs (AOP (result), AOP (left)) &&
8667 ((offl + MSB16) == offr))
8669 /* don't crash result[offr] */
8670 MOVA (aopGet (left, offl, FALSE, FALSE));
8671 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8672 usedB = !strncmp(x, "b", 1);
8674 else if (aopGetUsesAcc (result, offr))
8676 movLeft2Result (left, offl, result, offr, 0);
8679 emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8680 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8685 movLeft2Result (left, offl, result, offr, 0);
8686 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8687 x = aopGet (result, offr, FALSE, FALSE);
8689 /* a:x >> shCount (x = lsb(result)) */
8691 AccAXRshS (x, shCount);
8693 AccAXRsh (x, shCount);
8696 emitcode ("xch", "a,b");
8697 aopPut (result, "a", offr);
8698 emitcode ("xch", "a,b");
8701 if (getDataSize (result) > 1)
8702 aopPut (result, "a", offr + MSB16);
8705 /*-----------------------------------------------------------------*/
8706 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8707 /*-----------------------------------------------------------------*/
8709 shiftLLeftOrResult (operand * left, int offl,
8710 operand * result, int offr, int shCount)
8712 MOVA (aopGet (left, offl, FALSE, FALSE));
8713 /* shift left accumulator */
8715 /* or with result */
8716 if (aopGetUsesAcc (result, offr))
8718 emitcode ("xch", "a,b");
8719 MOVA (aopGet (result, offr, FALSE, FALSE));
8720 emitcode ("orl", "a,b");
8724 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8726 /* back to result */
8727 aopPut (result, "a", offr);
8730 /*-----------------------------------------------------------------*/
8731 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8732 /*-----------------------------------------------------------------*/
8734 shiftRLeftOrResult (operand * left, int offl,
8735 operand * result, int offr, int shCount)
8737 MOVA (aopGet (left, offl, FALSE, FALSE));
8738 /* shift right accumulator */
8740 /* or with result */
8741 if (aopGetUsesAcc(result, offr))
8743 emitcode ("xch", "a,b");
8744 MOVA (aopGet (result, offr, FALSE, FALSE));
8745 emitcode ("orl", "a,b");
8749 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8751 /* back to result */
8752 aopPut (result, "a", offr);
8755 /*-----------------------------------------------------------------*/
8756 /* genlshOne - left shift a one byte quantity by known count */
8757 /*-----------------------------------------------------------------*/
8759 genlshOne (operand * result, operand * left, int shCount)
8761 D (emitcode (";", "genlshOne"));
8763 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8766 /*-----------------------------------------------------------------*/
8767 /* genlshTwo - left shift two bytes by known amount != 0 */
8768 /*-----------------------------------------------------------------*/
8770 genlshTwo (operand * result, operand * left, int shCount)
8774 D (emitcode (";", "genlshTwo"));
8776 size = getDataSize (result);
8778 /* if shCount >= 8 */
8786 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8788 movLeft2Result (left, LSB, result, MSB16, 0);
8790 aopPut (result, zero, LSB);
8793 /* 1 <= shCount <= 7 */
8797 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8799 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8803 /*-----------------------------------------------------------------*/
8804 /* shiftLLong - shift left one long from left to result */
8805 /* offl = LSB or MSB16 */
8806 /*-----------------------------------------------------------------*/
8808 shiftLLong (operand * left, operand * result, int offr)
8811 int size = AOP_SIZE (result);
8813 if (size >= LSB + offr)
8815 l = aopGet (left, LSB, FALSE, FALSE);
8817 emitcode ("add", "a,acc");
8818 if (sameRegs (AOP (left), AOP (result)) &&
8819 size >= MSB16 + offr && offr != LSB)
8820 xch_a_aopGet (left, LSB + offr, FALSE, FALSE);
8822 aopPut (result, "a", LSB + offr);
8825 if (size >= MSB16 + offr)
8827 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8829 l = aopGet (left, MSB16, FALSE, FALSE);
8832 emitcode ("rlc", "a");
8833 if (sameRegs (AOP (left), AOP (result)) &&
8834 size >= MSB24 + offr && offr != LSB)
8835 xch_a_aopGet (left, MSB16 + offr, FALSE, FALSE);
8837 aopPut (result, "a", MSB16 + offr);
8840 if (size >= MSB24 + offr)
8842 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8844 l = aopGet (left, MSB24, FALSE, FALSE);
8847 emitcode ("rlc", "a");
8848 if (sameRegs (AOP (left), AOP (result)) &&
8849 size >= MSB32 + offr && offr != LSB)
8850 xch_a_aopGet (left, MSB24 + offr, FALSE, FALSE);
8852 aopPut (result, "a", MSB24 + offr);
8855 if (size > MSB32 + offr)
8857 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8859 l = aopGet (left, MSB32, FALSE, FALSE);
8862 emitcode ("rlc", "a");
8863 aopPut (result, "a", MSB32 + offr);
8866 aopPut (result, zero, LSB);
8869 /*-----------------------------------------------------------------*/
8870 /* genlshFour - shift four byte by a known amount != 0 */
8871 /*-----------------------------------------------------------------*/
8873 genlshFour (operand * result, operand * left, int shCount)
8877 D (emitcode (";", "genlshFour"));
8879 size = AOP_SIZE (result);
8881 /* if shifting more that 3 bytes */
8886 /* lowest order of left goes to the highest
8887 order of the destination */
8888 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8890 movLeft2Result (left, LSB, result, MSB32, 0);
8891 aopPut (result, zero, LSB);
8892 aopPut (result, zero, MSB16);
8893 aopPut (result, zero, MSB24);
8897 /* more than two bytes */
8898 else if (shCount >= 16)
8900 /* lower order two bytes goes to higher order two bytes */
8902 /* if some more remaining */
8904 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8907 movLeft2Result (left, MSB16, result, MSB32, 0);
8908 movLeft2Result (left, LSB, result, MSB24, 0);
8910 aopPut (result, zero, MSB16);
8911 aopPut (result, zero, LSB);
8915 /* if more than 1 byte */
8916 else if (shCount >= 8)
8918 /* lower order three bytes goes to higher order three bytes */
8923 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8925 movLeft2Result (left, LSB, result, MSB16, 0);
8931 movLeft2Result (left, MSB24, result, MSB32, 0);
8932 movLeft2Result (left, MSB16, result, MSB24, 0);
8933 movLeft2Result (left, LSB, result, MSB16, 0);
8934 aopPut (result, zero, LSB);
8936 else if (shCount == 1)
8937 shiftLLong (left, result, MSB16);
8940 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8941 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8942 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8943 aopPut (result, zero, LSB);
8948 /* 1 <= shCount <= 7 */
8949 else if (shCount <= 2)
8951 shiftLLong (left, result, LSB);
8953 shiftLLong (result, result, LSB);
8955 /* 3 <= shCount <= 7, optimize */
8958 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8959 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8960 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8964 /*-----------------------------------------------------------------*/
8965 /* genLeftShiftLiteral - left shifting by known count */
8966 /*-----------------------------------------------------------------*/
8968 genLeftShiftLiteral (operand * left,
8973 int shCount = (int) ulFromVal (AOP (right)->aopu.aop_lit);
8976 D (emitcode (";", "genLeftShiftLiteral"));
8978 freeAsmop (right, NULL, ic, TRUE);
8980 aopOp (left, ic, FALSE);
8981 aopOp (result, ic, FALSE);
8983 size = getSize (operandType (result));
8986 emitcode ("; shift left ", "result %d, left %d", size,
8990 /* I suppose that the left size >= result size */
8995 movLeft2Result (left, size, result, size, 0);
8998 else if (shCount >= (size * 8))
9002 aopPut (result, zero, size);
9010 genlshOne (result, left, shCount);
9014 genlshTwo (result, left, shCount);
9018 genlshFour (result, left, shCount);
9021 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9022 "*** ack! mystery literal shift!\n");
9026 freeAsmop (result, NULL, ic, TRUE);
9027 freeAsmop (left, NULL, ic, TRUE);
9030 /*-----------------------------------------------------------------*/
9031 /* genLeftShift - generates code for left shifting */
9032 /*-----------------------------------------------------------------*/
9034 genLeftShift (iCode * ic)
9036 operand *left, *right, *result;
9039 symbol *tlbl, *tlbl1;
9042 D (emitcode (";", "genLeftShift"));
9044 right = IC_RIGHT (ic);
9045 left = IC_LEFT (ic);
9046 result = IC_RESULT (ic);
9048 aopOp (right, ic, FALSE);
9050 /* if the shift count is known then do it
9051 as efficiently as possible */
9052 if (AOP_TYPE (right) == AOP_LIT)
9054 genLeftShiftLiteral (left, right, result, ic);
9058 /* shift count is unknown then we have to form
9059 a loop get the loop count in B : Note: we take
9060 only the lower order byte since shifting
9061 more that 32 bits make no sense anyway, ( the
9062 largest size of an object can be only 32 bits ) */
9065 MOVB (aopGet (right, 0, FALSE, FALSE));
9066 emitcode ("inc", "b");
9067 freeAsmop (right, NULL, ic, TRUE);
9068 aopOp (left, ic, FALSE);
9069 aopOp (result, ic, FALSE);
9071 /* now move the left to the result if they are not the same */
9072 if (!sameRegs (AOP (left), AOP (result)) &&
9073 AOP_SIZE (result) > 1)
9076 size = AOP_SIZE (result);
9080 l = aopGet (left, offset, FALSE, TRUE);
9081 if (*l == '@' && (IS_AOP_PREG (result)))
9084 emitcode ("mov", "a,%s", l);
9085 aopPut (result, "a", offset);
9088 aopPut (result, l, offset);
9093 tlbl = newiTempLabel (NULL);
9094 size = AOP_SIZE (result);
9096 tlbl1 = newiTempLabel (NULL);
9098 /* if it is only one byte then */
9101 symbol *tlbl1 = newiTempLabel (NULL);
9103 l = aopGet (left, 0, FALSE, FALSE);
9105 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9107 emitcode ("add", "a,acc");
9109 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9111 aopPut (result, "a", 0);
9115 reAdjustPreg (AOP (result));
9117 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9119 l = aopGet (result, offset, FALSE, FALSE);
9121 emitcode ("add", "a,acc");
9122 aopPut (result, "a", offset++);
9125 l = aopGet (result, offset, FALSE, FALSE);
9127 emitcode ("rlc", "a");
9128 aopPut (result, "a", offset++);
9130 reAdjustPreg (AOP (result));
9133 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9136 freeAsmop (result, NULL, ic, TRUE);
9137 freeAsmop (left, NULL, ic, TRUE);
9140 /*-----------------------------------------------------------------*/
9141 /* genrshOne - right shift a one byte quantity by known count */
9142 /*-----------------------------------------------------------------*/
9144 genrshOne (operand * result, operand * left,
9145 int shCount, int sign)
9147 D (emitcode (";", "genrshOne"));
9149 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9152 /*-----------------------------------------------------------------*/
9153 /* genrshTwo - right shift two bytes by known amount != 0 */
9154 /*-----------------------------------------------------------------*/
9156 genrshTwo (operand * result, operand * left,
9157 int shCount, int sign)
9159 D (emitcode (";", "genrshTwo"));
9161 /* if shCount >= 8 */
9166 shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
9168 movLeft2Result (left, MSB16, result, LSB, sign);
9169 addSign (result, MSB16, sign);
9172 /* 1 <= shCount <= 7 */
9174 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9177 /*-----------------------------------------------------------------*/
9178 /* shiftRLong - shift right one long from left to result */
9179 /* offl = LSB or MSB16 */
9180 /*-----------------------------------------------------------------*/
9182 shiftRLong (operand * left, int offl,
9183 operand * result, int sign)
9185 bool overlapping = regsInCommon (left, result) || operandsEqu(left, result);
9187 if (overlapping && offl>1)
9189 // we are in big trouble, but this shouldn't happen
9190 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9193 MOVA (aopGet (left, MSB32, FALSE, FALSE));
9200 emitcode ("rlc", "a");
9201 emitcode ("subb", "a,acc");
9202 if (overlapping && sameByte (AOP (left), MSB32, AOP (result), MSB32))
9204 xch_a_aopGet (left, MSB32, FALSE, FALSE);
9208 aopPut (result, "a", MSB32);
9209 MOVA (aopGet (left, MSB32, FALSE, FALSE));
9214 if (aopPutUsesAcc (result, zero, MSB32))
9216 emitcode("xch", "a,b");
9217 aopPut (result, zero, MSB32);
9218 emitcode("xch", "a,b");
9222 aopPut (result, zero, MSB32);
9229 emitcode ("clr", "c");
9233 emitcode ("mov", "c,acc.7");
9236 emitcode ("rrc", "a");
9238 if (overlapping && offl==MSB16 &&
9239 sameByte (AOP (left), MSB24, AOP (result), MSB32-offl))
9241 xch_a_aopGet (left, MSB24, FALSE, FALSE);
9245 aopPut (result, "a", MSB32 - offl);
9246 MOVA (aopGet (left, MSB24, FALSE, FALSE));
9249 emitcode ("rrc", "a");
9250 if (overlapping && offl==MSB16 &&
9251 sameByte (AOP (left), MSB16, AOP (result), MSB24-offl))
9253 xch_a_aopGet (left, MSB16, FALSE, FALSE);
9257 aopPut (result, "a", MSB24 - offl);
9258 MOVA (aopGet (left, MSB16, FALSE, FALSE));
9261 emitcode ("rrc", "a");
9264 aopPut (result, "a", MSB16 - offl);
9269 sameByte (AOP (left), LSB, AOP (result), MSB16-offl))
9271 xch_a_aopGet (left, LSB, FALSE, FALSE);
9275 aopPut (result, "a", MSB16 - offl);
9276 MOVA (aopGet (left, LSB, FALSE, FALSE));
9278 emitcode ("rrc", "a");
9279 aopPut (result, "a", LSB);
9283 /*-----------------------------------------------------------------*/
9284 /* genrshFour - shift four byte by a known amount != 0 */
9285 /*-----------------------------------------------------------------*/
9287 genrshFour (operand * result, operand * left,
9288 int shCount, int sign)
9290 D (emitcode (";", "genrshFour"));
9292 /* if shifting more that 3 bytes */
9297 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9299 movLeft2Result (left, MSB32, result, LSB, sign);
9300 addSign (result, MSB16, sign);
9302 else if (shCount >= 16)
9306 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9309 movLeft2Result (left, MSB24, result, LSB, 0);
9310 movLeft2Result (left, MSB32, result, MSB16, sign);
9312 addSign (result, MSB24, sign);
9314 else if (shCount >= 8)
9319 shiftRLong (left, MSB16, result, sign);
9321 else if (shCount == 0)
9323 movLeft2Result (left, MSB16, result, LSB, 0);
9324 movLeft2Result (left, MSB24, result, MSB16, 0);
9325 movLeft2Result (left, MSB32, result, MSB24, sign);
9326 addSign (result, MSB32, sign);
9330 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9331 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9332 /* the last shift is signed */
9333 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9334 addSign (result, MSB32, sign);
9339 /* 1 <= shCount <= 7 */
9342 shiftRLong (left, LSB, result, sign);
9344 shiftRLong (result, LSB, result, sign);
9348 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9349 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9350 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9355 /*-----------------------------------------------------------------*/
9356 /* genRightShiftLiteral - right shifting by known count */
9357 /*-----------------------------------------------------------------*/
9359 genRightShiftLiteral (operand * left,
9365 int shCount = (int) ulFromVal (AOP (right)->aopu.aop_lit);
9368 D (emitcode (";", "genRightShiftLiteral"));
9370 freeAsmop (right, NULL, ic, TRUE);
9372 aopOp (left, ic, FALSE);
9373 aopOp (result, ic, FALSE);
9376 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9380 size = getDataSize (left);
9381 /* test the LEFT size !!! */
9383 /* I suppose that the left size >= result size */
9386 size = getDataSize (result);
9388 movLeft2Result (left, size, result, size, 0);
9391 else if (shCount >= (size * 8))
9395 /* get sign in acc.7 */
9396 MOVA (aopGet (left, size - 1, FALSE, FALSE));
9398 addSign (result, LSB, sign);
9405 genrshOne (result, left, shCount, sign);
9409 genrshTwo (result, left, shCount, sign);
9413 genrshFour (result, left, shCount, sign);
9419 freeAsmop (result, NULL, ic, TRUE);
9420 freeAsmop (left, NULL, ic, TRUE);
9423 /*-----------------------------------------------------------------*/
9424 /* genSignedRightShift - right shift of signed number */
9425 /*-----------------------------------------------------------------*/
9427 genSignedRightShift (iCode * ic)
9429 operand *right, *left, *result;
9432 symbol *tlbl, *tlbl1;
9435 D (emitcode (";", "genSignedRightShift"));
9437 /* we do it the hard way put the shift count in b
9438 and loop thru preserving the sign */
9440 right = IC_RIGHT (ic);
9441 left = IC_LEFT (ic);
9442 result = IC_RESULT (ic);
9444 aopOp (right, ic, FALSE);
9447 if (AOP_TYPE (right) == AOP_LIT)
9449 genRightShiftLiteral (left, right, result, ic, 1);
9452 /* shift count is unknown then we have to form
9453 a loop get the loop count in B : Note: we take
9454 only the lower order byte since shifting
9455 more that 32 bits make no sense anyway, ( the
9456 largest size of an object can be only 32 bits ) */
9459 MOVB (aopGet (right, 0, FALSE, FALSE));
9460 emitcode ("inc", "b");
9461 freeAsmop (right, NULL, ic, TRUE);
9462 aopOp (left, ic, FALSE);
9463 aopOp (result, ic, FALSE);
9465 /* now move the left to the result if they are not the
9467 if (!sameRegs (AOP (left), AOP (result)) &&
9468 AOP_SIZE (result) > 1)
9471 size = AOP_SIZE (result);
9475 l = aopGet (left, offset, FALSE, TRUE);
9476 if (*l == '@' && IS_AOP_PREG (result))
9479 emitcode ("mov", "a,%s", l);
9480 aopPut (result, "a", offset);
9483 aopPut (result, l, offset);
9488 /* mov the highest order bit to OVR */
9489 tlbl = newiTempLabel (NULL);
9490 tlbl1 = newiTempLabel (NULL);
9492 size = AOP_SIZE (result);
9494 MOVA (aopGet (left, offset, FALSE, FALSE));
9495 emitcode ("rlc", "a");
9496 emitcode ("mov", "ov,c");
9497 /* if it is only one byte then */
9500 l = aopGet (left, 0, FALSE, FALSE);
9502 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9504 emitcode ("mov", "c,ov");
9505 emitcode ("rrc", "a");
9507 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9509 aopPut (result, "a", 0);
9513 reAdjustPreg (AOP (result));
9514 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9516 emitcode ("mov", "c,ov");
9519 l = aopGet (result, offset, FALSE, FALSE);
9521 emitcode ("rrc", "a");
9522 aopPut (result, "a", offset--);
9524 reAdjustPreg (AOP (result));
9526 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9530 freeAsmop (result, NULL, ic, TRUE);
9531 freeAsmop (left, NULL, ic, TRUE);
9534 /*-----------------------------------------------------------------*/
9535 /* genRightShift - generate code for right shifting */
9536 /*-----------------------------------------------------------------*/
9538 genRightShift (iCode * ic)
9540 operand *right, *left, *result;
9544 symbol *tlbl, *tlbl1;
9547 D (emitcode (";", "genRightShift"));
9549 /* if signed then we do it the hard way preserve the
9550 sign bit moving it inwards */
9551 letype = getSpec (operandType (IC_LEFT (ic)));
9553 if (!SPEC_USIGN (letype))
9555 genSignedRightShift (ic);
9559 /* signed & unsigned types are treated the same : i.e. the
9560 signed is NOT propagated inwards : quoting from the
9561 ANSI - standard : "for E1 >> E2, is equivalent to division
9562 by 2**E2 if unsigned or if it has a non-negative value,
9563 otherwise the result is implementation defined ", MY definition
9564 is that the sign does not get propagated */
9566 right = IC_RIGHT (ic);
9567 left = IC_LEFT (ic);
9568 result = IC_RESULT (ic);
9570 aopOp (right, ic, FALSE);
9572 /* if the shift count is known then do it
9573 as efficiently as possible */
9574 if (AOP_TYPE (right) == AOP_LIT)
9576 genRightShiftLiteral (left, right, result, ic, 0);
9580 /* shift count is unknown then we have to form
9581 a loop get the loop count in B : Note: we take
9582 only the lower order byte since shifting
9583 more that 32 bits make no sense anyway, ( the
9584 largest size of an object can be only 32 bits ) */
9587 MOVB (aopGet (right, 0, FALSE, FALSE));
9588 emitcode ("inc", "b");
9589 freeAsmop (right, NULL, ic, TRUE);
9590 aopOp (left, ic, FALSE);
9591 aopOp (result, ic, FALSE);
9593 /* now move the left to the result if they are not the
9595 if (!sameRegs (AOP (left), AOP (result)) &&
9596 AOP_SIZE (result) > 1)
9598 size = AOP_SIZE (result);
9602 l = aopGet (left, offset, FALSE, TRUE);
9603 if (*l == '@' && IS_AOP_PREG (result))
9606 emitcode ("mov", "a,%s", l);
9607 aopPut (result, "a", offset);
9610 aopPut (result, l, offset);
9615 tlbl = newiTempLabel (NULL);
9616 tlbl1 = newiTempLabel (NULL);
9617 size = AOP_SIZE (result);
9620 /* if it is only one byte then */
9623 l = aopGet (left, 0, FALSE, FALSE);
9625 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9628 emitcode ("rrc", "a");
9630 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9632 aopPut (result, "a", 0);
9636 reAdjustPreg (AOP (result));
9637 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9642 l = aopGet (result, offset, FALSE, FALSE);
9644 emitcode ("rrc", "a");
9645 aopPut (result, "a", offset--);
9647 reAdjustPreg (AOP (result));
9650 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9654 freeAsmop (result, NULL, ic, TRUE);
9655 freeAsmop (left, NULL, ic, TRUE);
9658 /*-----------------------------------------------------------------*/
9659 /* emitPtrByteGet - emits code to get a byte into A through a */
9660 /* pointer register (R0, R1, or DPTR). The */
9661 /* original value of A can be preserved in B. */
9662 /*-----------------------------------------------------------------*/
9664 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9671 emitcode ("mov", "b,a");
9672 emitcode ("mov", "a,@%s", rname);
9677 emitcode ("mov", "b,a");
9678 emitcode ("movx", "a,@%s", rname);
9683 emitcode ("mov", "b,a");
9684 emitcode ("movx", "a,@dptr");
9689 emitcode ("mov", "b,a");
9690 emitcode ("clr", "a");
9691 emitcode ("movc", "a,@a+dptr");
9697 emitcode ("push", "b");
9698 emitcode ("push", "acc");
9700 emitcode ("lcall", "__gptrget");
9702 emitcode ("pop", "b");
9707 /*-----------------------------------------------------------------*/
9708 /* emitPtrByteSet - emits code to set a byte from src through a */
9709 /* pointer register (R0, R1, or DPTR). */
9710 /*-----------------------------------------------------------------*/
9712 emitPtrByteSet (char *rname, int p_type, char *src)
9721 emitcode ("mov", "@%s,a", rname);
9724 emitcode ("mov", "@%s,%s", rname, src);
9729 emitcode ("movx", "@%s,a", rname);
9734 emitcode ("movx", "@dptr,a");
9739 emitcode ("lcall", "__gptrput");
9744 /*-----------------------------------------------------------------*/
9745 /* genUnpackBits - generates code for unpacking bits */
9746 /*-----------------------------------------------------------------*/
9748 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9750 int offset = 0; /* result byte offset */
9751 int rsize; /* result size */
9752 int rlen = 0; /* remaining bitfield length */
9753 sym_link *etype; /* bitfield type information */
9754 int blen; /* bitfield length */
9755 int bstr; /* bitfield starting bit within byte */
9756 static char* const accBits[] = {"acc.0", "acc.1", "acc.2", "acc.3",
9757 "acc.4", "acc.5", "acc.6", "acc.7"};
9759 D(emitcode (";", "genUnpackBits"));
9761 etype = getSpec (operandType (result));
9762 rsize = getSize (operandType (result));
9763 blen = SPEC_BLEN (etype);
9764 bstr = SPEC_BSTR (etype);
9766 if (ifx && blen <= 8)
9768 emitPtrByteGet (rname, ptype, FALSE);
9771 return accBits[bstr];;
9776 emitcode ("anl", "a,#0x%02x",
9777 (((unsigned char) -1) >> (8 - blen)) << bstr);
9783 /* If the bitfield length is less than a byte */
9786 emitPtrByteGet (rname, ptype, FALSE);
9788 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9789 if (!SPEC_USIGN (etype))
9791 /* signed bitfield */
9792 symbol *tlbl = newiTempLabel (NULL);
9794 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9795 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9798 aopPut (result, "a", offset++);
9802 /* Bit field did not fit in a byte. Copy all
9803 but the partial byte at the end. */
9804 for (rlen=blen;rlen>=8;rlen-=8)
9806 emitPtrByteGet (rname, ptype, FALSE);
9807 aopPut (result, "a", offset++);
9809 emitcode ("inc", "%s", rname);
9812 /* Handle the partial byte at the end */
9815 emitPtrByteGet (rname, ptype, FALSE);
9816 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9817 if (!SPEC_USIGN (etype))
9819 /* signed bitfield */
9820 symbol *tlbl = newiTempLabel (NULL);
9822 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9823 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9826 aopPut (result, "a", offset++);
9834 if (SPEC_USIGN (etype))
9838 /* signed bitfield: sign extension with 0x00 or 0xff */
9839 emitcode ("rlc", "a");
9840 emitcode ("subb", "a,acc");
9846 aopPut (result, source, offset++);
9852 /*-----------------------------------------------------------------*/
9853 /* genDataPointerGet - generates code when ptr offset is known */
9854 /*-----------------------------------------------------------------*/
9856 genDataPointerGet (operand * left,
9862 int size, offset = 0;
9864 D (emitcode (";", "genDataPointerGet"));
9866 aopOp (result, ic, TRUE);
9868 /* get the string representation of the name */
9869 l = aopGet (left, 0, FALSE, TRUE);
9871 size = AOP_SIZE (result);
9876 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
9880 SNPRINTF (buffer, sizeof(buffer), "%s", l);
9882 aopPut (result, buffer, offset++);
9885 freeAsmop (result, NULL, ic, TRUE);
9886 freeAsmop (left, NULL, ic, TRUE);
9889 /*-----------------------------------------------------------------*/
9890 /* genNearPointerGet - emitcode for near pointer fetch */
9891 /*-----------------------------------------------------------------*/
9893 genNearPointerGet (operand * left,
9902 char *ifxCond = "a";
9903 sym_link *rtype, *retype;
9904 sym_link *ltype = operandType (left);
9906 D (emitcode (";", "genNearPointerGet"));
9908 rtype = operandType (result);
9909 retype = getSpec (rtype);
9911 aopOp (left, ic, FALSE);
9913 /* if left is rematerialisable and
9914 result is not bitfield variable type and
9915 the left is pointer to data space i.e
9916 lower 128 bytes of space */
9917 if (AOP_TYPE (left) == AOP_IMMD &&
9918 !IS_BITFIELD (retype) &&
9919 DCL_TYPE (ltype) == POINTER)
9921 genDataPointerGet (left, result, ic);
9925 //aopOp (result, ic, FALSE);
9926 aopOp (result, ic, result?TRUE:FALSE);
9928 /* if the value is already in a pointer register
9929 then don't need anything more */
9930 if (!AOP_INPREG (AOP (left)))
9932 if (IS_AOP_PREG (left))
9934 // Aha, it is a pointer, just in disguise.
9935 rname = aopGet (left, 0, FALSE, FALSE);
9938 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9939 __FILE__, __LINE__);
9944 emitcode ("mov", "a%s,%s", rname + 1, rname);
9945 rname++; // skip the '@'.
9950 /* otherwise get a free pointer register */
9952 preg = getFreePtr (ic, &aop, FALSE);
9953 emitcode ("mov", "%s,%s",
9955 aopGet (left, 0, FALSE, TRUE));
9960 rname = aopGet (left, 0, FALSE, FALSE);
9962 /* if bitfield then unpack the bits */
9963 if (IS_BITFIELD (retype))
9964 ifxCond = genUnpackBits (result, rname, POINTER, ifx);
9967 /* we have can just get the values */
9968 int size = AOP_SIZE (result);
9973 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9976 emitcode ("mov", "a,@%s", rname);
9978 aopPut (result, "a", offset);
9984 SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
9985 aopPut (result, buffer, offset);
9989 emitcode ("inc", "%s", rname);
9993 /* now some housekeeping stuff */
9994 if (aop) /* we had to allocate for this iCode */
9996 if (pi) { /* post increment present */
9997 aopPut (left, rname, 0);
9999 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
10003 /* we did not allocate which means left
10004 already in a pointer register, then
10005 if size > 0 && this could be used again
10006 we have to point it back to where it
10008 if ((AOP_SIZE (result) > 1 &&
10009 !OP_SYMBOL (left)->remat &&
10010 (OP_SYMBOL (left)->liveTo > ic->seq ||
10014 int size = AOP_SIZE (result) - 1;
10016 emitcode ("dec", "%s", rname);
10020 if (ifx && !ifx->generated)
10022 genIfxJump (ifx, ifxCond, left, NULL, result);
10026 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
10027 freeAsmop (left, NULL, ic, TRUE);
10028 if (pi) pi->generated = 1;
10031 /*-----------------------------------------------------------------*/
10032 /* genPagedPointerGet - emitcode for paged pointer fetch */
10033 /*-----------------------------------------------------------------*/
10035 genPagedPointerGet (operand * left,
10044 char *ifxCond = "a";
10045 sym_link *rtype, *retype;
10047 D (emitcode (";", "genPagedPointerGet"));
10049 rtype = operandType (result);
10050 retype = getSpec (rtype);
10052 aopOp (left, ic, FALSE);
10054 aopOp (result, ic, FALSE);
10056 /* if the value is already in a pointer register
10057 then don't need anything more */
10058 if (!AOP_INPREG (AOP (left)))
10060 /* otherwise get a free pointer register */
10061 aop = newAsmop (0);
10062 preg = getFreePtr (ic, &aop, FALSE);
10063 emitcode ("mov", "%s,%s",
10065 aopGet (left, 0, FALSE, TRUE));
10066 rname = preg->name;
10069 rname = aopGet (left, 0, FALSE, FALSE);
10071 /* if bitfield then unpack the bits */
10072 if (IS_BITFIELD (retype))
10073 ifxCond = genUnpackBits (result, rname, PPOINTER, ifx);
10076 /* we have can just get the values */
10077 int size = AOP_SIZE (result);
10083 emitcode ("movx", "a,@%s", rname);
10085 aopPut (result, "a", offset);
10090 emitcode ("inc", "%s", rname);
10094 /* now some housekeeping stuff */
10095 if (aop) /* we had to allocate for this iCode */
10098 aopPut (left, rname, 0);
10099 freeAsmop (NULL, aop, ic, TRUE);
10103 /* we did not allocate which means left
10104 already in a pointer register, then
10105 if size > 0 && this could be used again
10106 we have to point it back to where it
10108 if ((AOP_SIZE (result) > 1 &&
10109 !OP_SYMBOL (left)->remat &&
10110 (OP_SYMBOL (left)->liveTo > ic->seq ||
10114 int size = AOP_SIZE (result) - 1;
10116 emitcode ("dec", "%s", rname);
10120 if (ifx && !ifx->generated)
10122 genIfxJump (ifx, ifxCond, left, NULL, result);
10126 freeAsmop (result, NULL, ic, TRUE);
10127 freeAsmop (left, NULL, ic, TRUE);
10128 if (pi) pi->generated = 1;
10131 /*--------------------------------------------------------------------*/
10132 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
10133 /*--------------------------------------------------------------------*/
10135 loadDptrFromOperand (operand *op, bool loadBToo)
10137 if (AOP_TYPE (op) != AOP_STR)
10139 /* if this is rematerializable */
10140 if (AOP_TYPE (op) == AOP_IMMD)
10142 emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
10145 if (AOP(op)->aopu.aop_immd.from_cast_remat)
10146 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
10149 wassertl(FALSE, "need pointerCode");
10150 emitcode (";", "mov b,???");
10151 /* genPointerGet and genPointerSet originally did different
10152 ** things for this case. Both seem wrong.
10153 ** from genPointerGet:
10154 ** emitcode ("mov", "b,#%d", pointerCode (retype));
10155 ** from genPointerSet:
10156 ** emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
10161 else if (AOP_TYPE (op) == AOP_DPTR)
10165 MOVA (aopGet (op, 0, FALSE, FALSE));
10166 emitcode ("push", "acc");
10167 MOVA (aopGet (op, 1, FALSE, FALSE));
10168 emitcode ("push", "acc");
10169 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10170 emitcode ("pop", "dph");
10171 emitcode ("pop", "dpl");
10175 MOVA (aopGet (op, 0, FALSE, FALSE));
10176 emitcode ("push", "acc");
10177 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10178 emitcode ("pop", "dpl");
10182 { /* we need to get it byte by byte */
10183 emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
10184 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10186 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10191 /*-----------------------------------------------------------------*/
10192 /* genFarPointerGet - get value from far space */
10193 /*-----------------------------------------------------------------*/
10195 genFarPointerGet (operand * left,
10196 operand * result, iCode * ic, iCode * pi, iCode * ifx)
10199 char *ifxCond = "a";
10200 sym_link *retype = getSpec (operandType (result));
10202 D (emitcode (";", "genFarPointerGet"));
10204 aopOp (left, ic, FALSE);
10205 loadDptrFromOperand (left, FALSE);
10207 /* so dptr now contains the address */
10208 aopOp (result, ic, FALSE);
10210 /* if bit then unpack */
10211 if (IS_BITFIELD (retype))
10212 ifxCond = genUnpackBits (result, "dptr", FPOINTER, ifx);
10215 size = AOP_SIZE (result);
10220 emitcode ("movx", "a,@dptr");
10222 aopPut (result, "a", offset++);
10224 emitcode ("inc", "dptr");
10228 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10230 aopPut (left, "dpl", 0);
10231 aopPut (left, "dph", 1);
10235 if (ifx && !ifx->generated)
10237 genIfxJump (ifx, ifxCond, left, NULL, result);
10240 freeAsmop (result, NULL, ic, TRUE);
10241 freeAsmop (left, NULL, ic, TRUE);
10244 /*-----------------------------------------------------------------*/
10245 /* genCodePointerGet - get value from code space */
10246 /*-----------------------------------------------------------------*/
10248 genCodePointerGet (operand * left,
10249 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10252 char *ifxCond = "a";
10253 sym_link *retype = getSpec (operandType (result));
10255 D (emitcode (";", "genCodePointerGet"));
10257 aopOp (left, ic, FALSE);
10258 loadDptrFromOperand (left, FALSE);
10260 /* so dptr now contains the address */
10261 aopOp (result, ic, FALSE);
10263 /* if bit then unpack */
10264 if (IS_BITFIELD (retype))
10265 ifxCond = genUnpackBits (result, "dptr", CPOINTER, ifx);
10268 size = AOP_SIZE (result);
10273 emitcode ("clr", "a");
10274 emitcode ("movc", "a,@a+dptr");
10276 aopPut (result, "a", offset++);
10278 emitcode ("inc", "dptr");
10282 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10284 aopPut (left, "dpl", 0);
10285 aopPut (left, "dph", 1);
10289 if (ifx && !ifx->generated)
10291 genIfxJump (ifx, ifxCond, left, NULL, result);
10294 freeAsmop (result, NULL, ic, TRUE);
10295 freeAsmop (left, NULL, ic, TRUE);
10298 /*-----------------------------------------------------------------*/
10299 /* genGenPointerGet - get value from generic pointer space */
10300 /*-----------------------------------------------------------------*/
10302 genGenPointerGet (operand * left,
10303 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10306 char *ifxCond = "a";
10307 sym_link *retype = getSpec (operandType (result));
10309 D (emitcode (";", "genGenPointerGet"));
10311 aopOp (left, ic, FALSE);
10312 loadDptrFromOperand (left, TRUE);
10314 /* so dptr now contains the address */
10315 aopOp (result, ic, FALSE);
10317 /* if bit then unpack */
10318 if (IS_BITFIELD (retype))
10320 ifxCond = genUnpackBits (result, "dptr", GPOINTER, ifx);
10324 size = AOP_SIZE (result);
10329 emitcode ("lcall", "__gptrget");
10331 aopPut (result, "a", offset++);
10333 emitcode ("inc", "dptr");
10337 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10339 aopPut (left, "dpl", 0);
10340 aopPut (left, "dph", 1);
10344 if (ifx && !ifx->generated)
10346 genIfxJump (ifx, ifxCond, left, NULL, result);
10349 freeAsmop (result, NULL, ic, TRUE);
10350 freeAsmop (left, NULL, ic, TRUE);
10353 /*-----------------------------------------------------------------*/
10354 /* genPointerGet - generate code for pointer get */
10355 /*-----------------------------------------------------------------*/
10357 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
10359 operand *left, *result;
10360 sym_link *type, *etype;
10363 D (emitcode (";", "genPointerGet"));
10365 left = IC_LEFT (ic);
10366 result = IC_RESULT (ic);
10368 if (getSize (operandType (result))>1)
10371 /* depending on the type of pointer we need to
10372 move it to the correct pointer register */
10373 type = operandType (left);
10374 etype = getSpec (type);
10375 /* if left is of type of pointer then it is simple */
10376 if (IS_PTR (type) && !IS_FUNC (type->next))
10378 p_type = DCL_TYPE (type);
10382 /* we have to go by the storage class */
10383 p_type = PTR_TYPE (SPEC_OCLS (etype));
10386 /* special case when cast remat */
10387 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10388 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10390 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10391 type = operandType (left);
10392 p_type = DCL_TYPE (type);
10394 /* now that we have the pointer type we assign
10395 the pointer values */
10401 genNearPointerGet (left, result, ic, pi, ifx);
10405 genPagedPointerGet (left, result, ic, pi, ifx);
10409 genFarPointerGet (left, result, ic, pi, ifx);
10413 genCodePointerGet (left, result, ic, pi, ifx);
10417 genGenPointerGet (left, result, ic, pi, ifx);
10423 /*-----------------------------------------------------------------*/
10424 /* genPackBits - generates code for packed bit storage */
10425 /*-----------------------------------------------------------------*/
10427 genPackBits (sym_link * etype,
10429 char *rname, int p_type)
10431 int offset = 0; /* source byte offset */
10432 int rlen = 0; /* remaining bitfield length */
10433 int blen; /* bitfield length */
10434 int bstr; /* bitfield starting bit within byte */
10435 int litval; /* source literal value (if AOP_LIT) */
10436 unsigned char mask; /* bitmask within current byte */
10438 D(emitcode (";", "genPackBits"));
10440 blen = SPEC_BLEN (etype);
10441 bstr = SPEC_BSTR (etype);
10443 /* If the bitfield length is less than a byte */
10446 mask = ((unsigned char) (0xFF << (blen + bstr)) |
10447 (unsigned char) (0xFF >> (8 - bstr)));
10449 if (AOP_TYPE (right) == AOP_LIT)
10451 /* Case with a bitfield length <8 and literal source
10453 litval = (int) ulFromVal (AOP (right)->aopu.aop_lit);
10455 litval &= (~mask) & 0xff;
10456 emitPtrByteGet (rname, p_type, FALSE);
10457 if ((mask|litval)!=0xff)
10458 emitcode ("anl","a,#0x%02x", mask);
10460 emitcode ("orl","a,#0x%02x", litval);
10464 if ((blen==1) && (p_type!=GPOINTER))
10466 /* Case with a bitfield length == 1 and no generic pointer
10468 if (AOP_TYPE (right) == AOP_CRY)
10469 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10472 MOVA (aopGet (right, 0, FALSE, FALSE));
10473 emitcode ("rrc","a");
10475 emitPtrByteGet (rname, p_type, FALSE);
10476 emitcode ("mov","acc.%d,c",bstr);
10481 /* Case with a bitfield length < 8 and arbitrary source
10483 MOVA (aopGet (right, 0, FALSE, FALSE));
10484 /* shift and mask source value */
10486 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10488 pushedB = pushB ();
10489 /* transfer A to B and get next byte */
10490 emitPtrByteGet (rname, p_type, TRUE);
10492 emitcode ("anl", "a,#0x%02x", mask);
10493 emitcode ("orl", "a,b");
10494 if (p_type == GPOINTER)
10495 emitcode ("pop", "b");
10501 emitPtrByteSet (rname, p_type, "a");
10505 /* Bit length is greater than 7 bits. In this case, copy */
10506 /* all except the partial byte at the end */
10507 for (rlen=blen;rlen>=8;rlen-=8)
10509 emitPtrByteSet (rname, p_type,
10510 aopGet (right, offset++, FALSE, TRUE) );
10512 emitcode ("inc", "%s", rname);
10515 /* If there was a partial byte at the end */
10518 mask = (((unsigned char) -1 << rlen) & 0xff);
10520 if (AOP_TYPE (right) == AOP_LIT)
10522 /* Case with partial byte and literal source
10524 litval = (int) ulFromVal (AOP (right)->aopu.aop_lit);
10525 litval >>= (blen-rlen);
10526 litval &= (~mask) & 0xff;
10527 emitPtrByteGet (rname, p_type, FALSE);
10528 if ((mask|litval)!=0xff)
10529 emitcode ("anl","a,#0x%02x", mask);
10531 emitcode ("orl","a,#0x%02x", litval);
10536 /* Case with partial byte and arbitrary source
10538 MOVA (aopGet (right, offset++, FALSE, FALSE));
10539 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10541 pushedB = pushB ();
10542 /* transfer A to B and get next byte */
10543 emitPtrByteGet (rname, p_type, TRUE);
10545 emitcode ("anl", "a,#0x%02x", mask);
10546 emitcode ("orl", "a,b");
10547 if (p_type == GPOINTER)
10548 emitcode ("pop", "b");
10552 emitPtrByteSet (rname, p_type, "a");
10557 /*-----------------------------------------------------------------*/
10558 /* genDataPointerSet - remat pointer to data space */
10559 /*-----------------------------------------------------------------*/
10561 genDataPointerSet (operand * right,
10565 int size, offset = 0;
10566 char *l, buffer[256];
10568 D (emitcode (";", "genDataPointerSet"));
10570 aopOp (right, ic, FALSE);
10572 l = aopGet (result, 0, FALSE, TRUE);
10574 size = max (AOP_SIZE (right), AOP_SIZE (result));
10578 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
10580 SNPRINTF (buffer, sizeof(buffer), "%s", l);
10581 emitcode ("mov", "%s,%s", buffer,
10582 aopGet (right, offset++, FALSE, FALSE));
10585 freeAsmop (right, NULL, ic, TRUE);
10586 freeAsmop (result, NULL, ic, TRUE);
10589 /*-----------------------------------------------------------------*/
10590 /* genNearPointerSet - emitcode for near pointer put */
10591 /*-----------------------------------------------------------------*/
10593 genNearPointerSet (operand * right,
10601 sym_link *retype, *letype;
10602 sym_link *ptype = operandType (result);
10604 D (emitcode (";", "genNearPointerSet"));
10606 retype = getSpec (operandType (right));
10607 letype = getSpec (ptype);
10609 aopOp (result, ic, FALSE);
10611 /* if the result is rematerializable &
10612 in data space & not a bit variable */
10613 if (AOP_TYPE (result) == AOP_IMMD &&
10614 DCL_TYPE (ptype) == POINTER &&
10615 !IS_BITVAR (retype) &&
10616 !IS_BITVAR (letype))
10618 genDataPointerSet (right, result, ic);
10622 /* if the value is already in a pointer register
10623 then don't need anything more */
10624 if (!AOP_INPREG (AOP (result)))
10626 if (IS_AOP_PREG (result))
10628 // Aha, it is a pointer, just in disguise.
10629 rname = aopGet (result, 0, FALSE, FALSE);
10632 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10633 __FILE__, __LINE__);
10638 emitcode ("mov", "a%s,%s", rname + 1, rname);
10639 rname++; // skip the '@'.
10644 /* otherwise get a free pointer register */
10645 aop = newAsmop (0);
10646 preg = getFreePtr (ic, &aop, FALSE);
10647 emitcode ("mov", "%s,%s",
10649 aopGet (result, 0, FALSE, TRUE));
10650 rname = preg->name;
10655 rname = aopGet (result, 0, FALSE, FALSE);
10658 aopOp (right, ic, FALSE);
10660 /* if bitfield then unpack the bits */
10661 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10662 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10665 /* we can just get the values */
10666 int size = AOP_SIZE (right);
10671 l = aopGet (right, offset, FALSE, TRUE);
10672 if ((*l == '@') || (strcmp (l, "acc") == 0))
10675 emitcode ("mov", "@%s,a", rname);
10678 emitcode ("mov", "@%s,%s", rname, l);
10680 emitcode ("inc", "%s", rname);
10685 /* now some housekeeping stuff */
10686 if (aop) /* we had to allocate for this iCode */
10689 aopPut (result, rname, 0);
10690 freeAsmop (NULL, aop, ic, TRUE);
10694 /* we did not allocate which means left
10695 already in a pointer register, then
10696 if size > 0 && this could be used again
10697 we have to point it back to where it
10699 if ((AOP_SIZE (right) > 1 &&
10700 !OP_SYMBOL (result)->remat &&
10701 (OP_SYMBOL (result)->liveTo > ic->seq ||
10705 int size = AOP_SIZE (right) - 1;
10707 emitcode ("dec", "%s", rname);
10714 freeAsmop (right, NULL, ic, TRUE);
10715 freeAsmop (result, NULL, ic, TRUE);
10718 /*-----------------------------------------------------------------*/
10719 /* genPagedPointerSet - emitcode for Paged pointer put */
10720 /*-----------------------------------------------------------------*/
10722 genPagedPointerSet (operand * right,
10730 sym_link *retype, *letype;
10732 D (emitcode (";", "genPagedPointerSet"));
10734 retype = getSpec (operandType (right));
10735 letype = getSpec (operandType (result));
10737 aopOp (result, ic, FALSE);
10739 /* if the value is already in a pointer register
10740 then don't need anything more */
10741 if (!AOP_INPREG (AOP (result)))
10743 if (IS_AOP_PREG (result))
10745 // Aha, it is a pointer, just in disguise.
10746 rname = aopGet (result, 0, FALSE, FALSE);
10749 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10750 __FILE__, __LINE__);
10755 emitcode ("mov", "a%s,%s", rname + 1, rname);
10756 rname++; // skip the '@'.
10761 /* otherwise get a free pointer register */
10762 aop = newAsmop (0);
10763 preg = getFreePtr (ic, &aop, FALSE);
10764 emitcode ("mov", "%s,%s",
10766 aopGet (result, 0, FALSE, TRUE));
10767 rname = preg->name;
10772 rname = aopGet (result, 0, FALSE, FALSE);
10775 aopOp (right, ic, FALSE);
10777 /* if bitfield then unpack the bits */
10778 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10779 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10782 /* we can just get the values */
10783 int size = AOP_SIZE (right);
10788 l = aopGet (right, offset, FALSE, TRUE);
10790 emitcode ("movx", "@%s,a", rname);
10792 emitcode ("inc", "%s", rname);
10797 /* now some housekeeping stuff */
10798 if (aop) /* we had to allocate for this iCode */
10801 aopPut (result, rname, 0);
10802 freeAsmop (NULL, aop, ic, TRUE);
10806 /* we did not allocate which means left
10807 already in a pointer register, then
10808 if size > 0 && this could be used again
10809 we have to point it back to where it
10811 if (AOP_SIZE (right) > 1 &&
10812 !OP_SYMBOL (result)->remat &&
10813 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth) &&
10816 int size = AOP_SIZE (right) - 1;
10818 emitcode ("dec", "%s", rname);
10825 freeAsmop (right, NULL, ic, TRUE);
10826 freeAsmop (result, NULL, ic, TRUE);
10829 /*-----------------------------------------------------------------*/
10830 /* genFarPointerSet - set value from far space */
10831 /*-----------------------------------------------------------------*/
10833 genFarPointerSet (operand * right,
10834 operand * result, iCode * ic, iCode * pi)
10837 sym_link *retype = getSpec (operandType (right));
10838 sym_link *letype = getSpec (operandType (result));
10840 D(emitcode (";", "genFarPointerSet"));
10842 aopOp (result, ic, FALSE);
10843 loadDptrFromOperand (result, FALSE);
10845 /* so dptr now contains the address */
10846 aopOp (right, ic, FALSE);
10848 /* if bit then unpack */
10849 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10850 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10853 size = AOP_SIZE (right);
10858 char *l = aopGet (right, offset++, FALSE, FALSE);
10860 emitcode ("movx", "@dptr,a");
10862 emitcode ("inc", "dptr");
10865 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10866 aopPut (result, "dpl", 0);
10867 aopPut (result, "dph", 1);
10870 freeAsmop (result, NULL, ic, TRUE);
10871 freeAsmop (right, NULL, ic, TRUE);
10874 /*-----------------------------------------------------------------*/
10875 /* genGenPointerSet - set value from generic pointer space */
10876 /*-----------------------------------------------------------------*/
10878 genGenPointerSet (operand * right,
10879 operand * result, iCode * ic, iCode * pi)
10882 sym_link *retype = getSpec (operandType (right));
10883 sym_link *letype = getSpec (operandType (result));
10885 D (emitcode (";", "genGenPointerSet"));
10887 aopOp (result, ic, FALSE);
10888 loadDptrFromOperand (result, TRUE);
10890 /* so dptr now contains the address */
10891 aopOp (right, ic, FALSE);
10893 /* if bit then unpack */
10894 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10896 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10900 size = AOP_SIZE (right);
10905 char *l = aopGet (right, offset++, FALSE, FALSE);
10907 emitcode ("lcall", "__gptrput");
10909 emitcode ("inc", "dptr");
10913 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10914 aopPut (result, "dpl", 0);
10915 aopPut (result, "dph", 1);
10918 freeAsmop (result, NULL, ic, TRUE);
10919 freeAsmop (right, NULL, ic, TRUE);
10922 /*-----------------------------------------------------------------*/
10923 /* genPointerSet - stores the value into a pointer location */
10924 /*-----------------------------------------------------------------*/
10926 genPointerSet (iCode * ic, iCode *pi)
10928 operand *right, *result;
10929 sym_link *type, *etype;
10932 D (emitcode (";", "genPointerSet"));
10934 right = IC_RIGHT (ic);
10935 result = IC_RESULT (ic);
10937 /* depending on the type of pointer we need to
10938 move it to the correct pointer register */
10939 type = operandType (result);
10940 etype = getSpec (type);
10941 /* if left is of type of pointer then it is simple */
10942 if (IS_PTR (type) && !IS_FUNC (type->next))
10944 p_type = DCL_TYPE (type);
10948 /* we have to go by the storage class */
10949 p_type = PTR_TYPE (SPEC_OCLS (etype));
10952 /* special case when cast remat */
10953 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10954 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10955 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10956 type = operandType (result);
10957 p_type = DCL_TYPE (type);
10960 /* now that we have the pointer type we assign
10961 the pointer values */
10967 genNearPointerSet (right, result, ic, pi);
10971 genPagedPointerSet (right, result, ic, pi);
10975 genFarPointerSet (right, result, ic, pi);
10979 genGenPointerSet (right, result, ic, pi);
10983 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10984 "genPointerSet: illegal pointer type");
10988 /*-----------------------------------------------------------------*/
10989 /* genIfx - generate code for Ifx statement */
10990 /*-----------------------------------------------------------------*/
10992 genIfx (iCode * ic, iCode * popIc)
10994 operand *cond = IC_COND (ic);
10998 D (emitcode (";", "genIfx"));
11000 aopOp (cond, ic, FALSE);
11002 /* get the value into acc */
11003 if (AOP_TYPE (cond) != AOP_CRY)
11010 if (AOP(cond)->aopu.aop_dir)
11011 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
11014 /* the result is now in the accumulator or a directly addressable bit */
11015 freeAsmop (cond, NULL, ic, TRUE);
11017 /* if there was something to be popped then do it */
11021 /* if the condition is a bit variable */
11023 genIfxJump(ic, dup, NULL, NULL, NULL);
11024 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
11025 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
11026 else if (isbit && !IS_ITEMP (cond))
11027 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
11029 genIfxJump (ic, "a", NULL, NULL, NULL);
11034 /*-----------------------------------------------------------------*/
11035 /* genAddrOf - generates code for address of */
11036 /*-----------------------------------------------------------------*/
11038 genAddrOf (iCode * ic)
11040 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
11043 D (emitcode (";", "genAddrOf"));
11045 aopOp (IC_RESULT (ic), ic, FALSE);
11047 /* if the operand is on the stack then we
11048 need to get the stack offset of this
11052 /* if it has an offset then we need to compute it */
11055 int stack_offset = ((sym->stack < 0) ?
11056 ((char) (sym->stack - _G.nRegsSaved)) :
11057 ((char) sym->stack)) & 0xff;
11058 if ((abs(stack_offset) == 1) &&
11059 !AOP_NEEDSACC(IC_RESULT (ic)) &&
11060 !isOperandVolatile (IC_RESULT (ic), FALSE))
11062 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
11063 if (stack_offset > 0)
11064 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
11066 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
11070 emitcode ("mov", "a,%s", SYM_BP (sym));
11071 emitcode ("add", "a,#0x%02x", stack_offset & 0xff);
11072 aopPut (IC_RESULT (ic), "a", 0);
11077 /* we can just move _bp */
11078 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
11080 /* fill the result with zero */
11081 size = AOP_SIZE (IC_RESULT (ic)) - 1;
11086 aopPut (IC_RESULT (ic), zero, offset++);
11091 /* object not on stack then we need the name */
11092 size = getDataSize (IC_RESULT (ic));
11097 char s[SDCC_NAME_MAX];
11099 sprintf (s, "#(%s >> %d)",
11103 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11104 aopPut (IC_RESULT (ic), s, offset++);
11106 if (opIsGptr (IC_RESULT (ic)))
11109 SNPRINTF (buffer, sizeof(buffer),
11110 "#0x%02x", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
11111 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
11115 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11119 /*-----------------------------------------------------------------*/
11120 /* genFarFarAssign - assignment when both are in far space */
11121 /*-----------------------------------------------------------------*/
11123 genFarFarAssign (operand * result, operand * right, iCode * ic)
11125 int size = AOP_SIZE (right);
11129 D (emitcode (";", "genFarFarAssign"));
11131 /* first push the right side on to the stack */
11134 l = aopGet (right, offset++, FALSE, FALSE);
11136 emitcode ("push", "acc");
11139 freeAsmop (right, NULL, ic, FALSE);
11140 /* now assign DPTR to result */
11141 aopOp (result, ic, FALSE);
11142 size = AOP_SIZE (result);
11145 emitcode ("pop", "acc");
11146 aopPut (result, "a", --offset);
11148 freeAsmop (result, NULL, ic, FALSE);
11151 /*-----------------------------------------------------------------*/
11152 /* genAssign - generate code for assignment */
11153 /*-----------------------------------------------------------------*/
11155 genAssign (iCode * ic)
11157 operand *result, *right;
11159 unsigned long lit = 0L;
11161 D (emitcode (";", "genAssign"));
11163 result = IC_RESULT (ic);
11164 right = IC_RIGHT (ic);
11166 /* if they are the same */
11167 if (operandsEqu (result, right) &&
11168 !isOperandVolatile (result, FALSE) &&
11169 !isOperandVolatile (right, FALSE))
11172 aopOp (right, ic, FALSE);
11174 /* special case both in far space */
11175 if (AOP_TYPE (right) == AOP_DPTR &&
11176 IS_TRUE_SYMOP (result) &&
11177 isOperandInFarSpace (result))
11179 genFarFarAssign (result, right, ic);
11183 aopOp (result, ic, TRUE);
11185 /* if they are the same registers */
11186 if (sameRegs (AOP (right), AOP (result)) &&
11187 !isOperandVolatile (result, FALSE) &&
11188 !isOperandVolatile (right, FALSE))
11191 /* if the result is a bit */
11192 if (AOP_TYPE (result) == AOP_CRY)
11194 assignBit (result, right);
11198 /* bit variables done */
11200 size = getDataSize (result);
11202 if (AOP_TYPE (right) == AOP_LIT)
11203 lit = ulFromVal (AOP (right)->aopu.aop_lit);
11206 (AOP_TYPE (result) != AOP_REG) &&
11207 (AOP_TYPE (right) == AOP_LIT) &&
11208 !IS_FLOAT (operandType (right)) &&
11211 while ((size) && (lit))
11214 aopGet (right, offset, FALSE, FALSE),
11220 /* And now fill the rest with zeros. */
11223 emitcode ("clr", "a");
11227 aopPut (result, "a", offset);
11236 aopGet (right, offset, FALSE, FALSE),
11241 adjustArithmeticResult (ic);
11244 freeAsmop (result, NULL, ic, TRUE);
11245 freeAsmop (right, NULL, ic, TRUE);
11248 /*-----------------------------------------------------------------*/
11249 /* genJumpTab - generates code for jump table */
11250 /*-----------------------------------------------------------------*/
11252 genJumpTab (iCode * ic)
11254 symbol *jtab,*jtablo,*jtabhi;
11256 unsigned int count;
11258 D (emitcode (";", "genJumpTab"));
11260 count = elementsInSet( IC_JTLABELS (ic) );
11264 /* this algorithm needs 9 cycles and 7 + 3*n bytes
11265 if the switch argument is in a register.
11266 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
11267 /* Peephole may not convert ljmp to sjmp or ret
11268 labelIsReturnOnly & labelInRange must check
11269 currPl->ic->op != JUMPTABLE */
11270 aopOp (IC_JTCOND (ic), ic, FALSE);
11271 /* get the condition into accumulator */
11272 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11274 /* multiply by three */
11275 if (aopGetUsesAcc (IC_JTCOND (ic), 0))
11277 emitcode ("mov", "b,#0x03");
11278 emitcode ("mul", "ab");
11282 emitcode ("add", "a,acc");
11283 emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
11285 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11287 jtab = newiTempLabel (NULL);
11288 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
11289 emitcode ("jmp", "@a+dptr");
11291 /* now generate the jump labels */
11292 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11293 jtab = setNextItem (IC_JTLABELS (ic)))
11294 emitcode ("ljmp", "%05d$", jtab->key + 100);
11298 /* this algorithm needs 14 cycles and 13 + 2*n bytes
11299 if the switch argument is in a register.
11300 For n>6 this algorithm may be more compact */
11301 jtablo = newiTempLabel (NULL);
11302 jtabhi = newiTempLabel (NULL);
11304 /* get the condition into accumulator.
11305 Using b as temporary storage, if register push/pop is needed */
11306 aopOp (IC_JTCOND (ic), ic, FALSE);
11307 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11308 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
11309 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
11311 // (MB) what if B is in use???
11312 wassertl(!BINUSE, "B was in use");
11313 emitcode ("mov", "b,%s", l);
11316 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11320 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
11321 emitcode ("movc", "a,@a+pc");
11322 emitcode ("push", "acc");
11325 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
11326 emitcode ("movc", "a,@a+pc");
11327 emitcode ("push", "acc");
11331 /* this scales up to n<=255, but needs two more bytes
11332 and changes dptr */
11333 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
11334 emitcode ("movc", "a,@a+dptr");
11335 emitcode ("push", "acc");
11338 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
11339 emitcode ("movc", "a,@a+dptr");
11340 emitcode ("push", "acc");
11343 emitcode ("ret", "");
11345 /* now generate jump table, LSB */
11346 emitLabel (jtablo);
11347 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11348 jtab = setNextItem (IC_JTLABELS (ic)))
11349 emitcode (".db", "%05d$", jtab->key + 100);
11351 /* now generate jump table, MSB */
11352 emitLabel (jtabhi);
11353 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11354 jtab = setNextItem (IC_JTLABELS (ic)))
11355 emitcode (".db", "%05d$>>8", jtab->key + 100);
11359 /*-----------------------------------------------------------------*/
11360 /* genCast - gen code for casting */
11361 /*-----------------------------------------------------------------*/
11363 genCast (iCode * ic)
11365 operand *result = IC_RESULT (ic);
11366 sym_link *ctype = operandType (IC_LEFT (ic));
11367 sym_link *rtype = operandType (IC_RIGHT (ic));
11368 operand *right = IC_RIGHT (ic);
11371 D (emitcode (";", "genCast"));
11373 /* if they are equivalent then do nothing */
11374 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11377 aopOp (right, ic, FALSE);
11378 aopOp (result, ic, FALSE);
11380 /* if the result is a bit (and not a bitfield) */
11381 if (IS_BIT (OP_SYMBOL (result)->type))
11383 assignBit (result, right);
11387 /* if they are the same size : or less */
11388 if (AOP_SIZE (result) <= AOP_SIZE (right))
11391 /* if they are in the same place */
11392 if (sameRegs (AOP (right), AOP (result)))
11395 /* if they in different places then copy */
11396 size = AOP_SIZE (result);
11401 aopGet (right, offset, FALSE, FALSE),
11408 /* if the result is of type pointer */
11409 if (IS_PTR (ctype))
11413 sym_link *type = operandType (right);
11414 sym_link *etype = getSpec (type);
11416 /* pointer to generic pointer */
11417 if (IS_GENPTR (ctype))
11421 p_type = DCL_TYPE (type);
11425 if (SPEC_SCLS(etype)==S_REGISTER) {
11426 // let's assume it is a generic pointer
11429 /* we have to go by the storage class */
11430 p_type = PTR_TYPE (SPEC_OCLS (etype));
11434 /* the first two bytes are known */
11435 size = GPTRSIZE - 1;
11440 aopGet (right, offset, FALSE, FALSE),
11444 /* the last byte depending on type */
11446 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11451 // pointerTypeToGPByte will have bitched.
11455 sprintf(gpValStr, "#0x%02x", gpVal);
11456 aopPut (result, gpValStr, GPTRSIZE - 1);
11461 /* just copy the pointers */
11462 size = AOP_SIZE (result);
11467 aopGet (right, offset, FALSE, FALSE),
11474 /* so we now know that the size of destination is greater
11475 than the size of the source */
11476 /* we move to result for the size of source */
11477 size = AOP_SIZE (right);
11482 aopGet (right, offset, FALSE, FALSE),
11487 /* now depending on the sign of the source && destination */
11488 size = AOP_SIZE (result) - AOP_SIZE (right);
11489 /* if unsigned or not an integral type */
11490 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11493 aopPut (result, zero, offset++);
11497 /* we need to extend the sign :{ */
11498 char *l = aopGet (right, AOP_SIZE (right) - 1,
11501 emitcode ("rlc", "a");
11502 emitcode ("subb", "a,acc");
11504 aopPut (result, "a", offset++);
11507 /* we are done hurray !!!! */
11510 freeAsmop (result, NULL, ic, TRUE);
11511 freeAsmop (right, NULL, ic, TRUE);
11514 /*-----------------------------------------------------------------*/
11515 /* genDjnz - generate decrement & jump if not zero instrucion */
11516 /*-----------------------------------------------------------------*/
11518 genDjnz (iCode * ic, iCode * ifx)
11520 symbol *lbl, *lbl1;
11524 /* if the if condition has a false label
11525 then we cannot save */
11526 if (IC_FALSE (ifx))
11529 /* if the minus is not of the form a = a - 1 */
11530 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11531 !IS_OP_LITERAL (IC_RIGHT (ic)))
11534 if (operandLitValue (IC_RIGHT (ic)) != 1)
11537 /* if the size of this greater than one then no
11539 if (getSize (operandType (IC_RESULT (ic))) > 1)
11542 /* otherwise we can save BIG */
11544 D (emitcode (";", "genDjnz"));
11546 lbl = newiTempLabel (NULL);
11547 lbl1 = newiTempLabel (NULL);
11549 aopOp (IC_RESULT (ic), ic, FALSE);
11551 if (AOP_NEEDSACC(IC_RESULT(ic)))
11553 /* If the result is accessed indirectly via
11554 * the accumulator, we must explicitly write
11555 * it back after the decrement.
11557 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11559 if (strcmp(rByte, "a"))
11561 /* Something is hopelessly wrong */
11562 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11563 __FILE__, __LINE__);
11564 /* We can just give up; the generated code will be inefficient,
11565 * but what the hey.
11567 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11570 emitcode ("dec", "%s", rByte);
11571 aopPut (IC_RESULT (ic), rByte, 0);
11572 emitcode ("jnz", "%05d$", lbl->key + 100);
11574 else if (IS_AOP_PREG (IC_RESULT (ic)))
11576 emitcode ("dec", "%s",
11577 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11578 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11579 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11580 ifx->generated = 1;
11581 emitcode ("jnz", "%05d$", lbl->key + 100);
11585 emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11588 emitcode ("sjmp", "%05d$", lbl1->key + 100);
11590 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11593 if (!ifx->generated)
11594 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11595 ifx->generated = 1;
11599 /*-----------------------------------------------------------------*/
11600 /* genReceive - generate code for a receive iCode */
11601 /*-----------------------------------------------------------------*/
11603 genReceive (iCode * ic)
11605 int size = getSize (operandType (IC_RESULT (ic)));
11608 D (emitcode (";", "genReceive"));
11610 if (ic->argreg == 1)
11611 { /* first parameter */
11612 if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11613 isOperandInPagedSpace (IC_RESULT (ic))) &&
11614 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11615 IS_TRUE_SYMOP (IC_RESULT (ic))))
11618 int receivingA = 0;
11621 for (offset = 0; offset<size; offset++)
11622 if (!strcmp (fReturn[offset], "a"))
11627 if (size==1 || getTempRegs(tempRegs, size-1, ic))
11629 for (offset = size-1; offset>0; offset--)
11630 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11631 emitcode("mov","a,%s", fReturn[0]);
11633 aopOp (IC_RESULT (ic), ic, FALSE);
11635 aopPut (IC_RESULT (ic), "a", offset);
11636 for (offset = 1; offset<size; offset++)
11637 aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset);
11643 if (getTempRegs(tempRegs, size, ic))
11645 for (offset = 0; offset<size; offset++)
11646 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11647 aopOp (IC_RESULT (ic), ic, FALSE);
11648 for (offset = 0; offset<size; offset++)
11649 aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset);
11654 offset = fReturnSizeMCS51 - size;
11657 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11658 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11661 aopOp (IC_RESULT (ic), ic, FALSE);
11662 size = AOP_SIZE (IC_RESULT (ic));
11666 emitcode ("pop", "acc");
11667 aopPut (IC_RESULT (ic), "a", offset++);
11673 aopOp (IC_RESULT (ic), ic, FALSE);
11675 assignResultValue (IC_RESULT (ic), NULL);
11678 else if (ic->argreg > 12)
11679 { /* bit parameters */
11680 regs *reg = OP_SYMBOL (IC_RESULT (ic))->regs[0];
11683 if (!reg || reg->rIdx != ic->argreg-5)
11685 aopOp (IC_RESULT (ic), ic, FALSE);
11686 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11687 outBitC(IC_RESULT (ic));
11691 { /* other parameters */
11693 aopOp (IC_RESULT (ic), ic, FALSE);
11694 rb1off = ic->argreg;
11697 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
11702 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11705 /*-----------------------------------------------------------------*/
11706 /* genDummyRead - generate code for dummy read of volatiles */
11707 /*-----------------------------------------------------------------*/
11709 genDummyRead (iCode * ic)
11714 D (emitcode(";", "genDummyRead"));
11716 op = IC_RIGHT (ic);
11717 if (op && IS_SYMOP (op))
11719 aopOp (op, ic, FALSE);
11721 /* if the result is a bit */
11722 if (AOP_TYPE (op) == AOP_CRY)
11723 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11726 /* bit variables done */
11728 size = AOP_SIZE (op);
11732 MOVA (aopGet (op, offset, FALSE, FALSE));
11737 freeAsmop (op, NULL, ic, TRUE);
11741 if (op && IS_SYMOP (op))
11743 aopOp (op, ic, FALSE);
11745 /* if the result is a bit */
11746 if (AOP_TYPE (op) == AOP_CRY)
11747 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11750 /* bit variables done */
11752 size = AOP_SIZE (op);
11756 MOVA (aopGet (op, offset, FALSE, FALSE));
11761 freeAsmop (op, NULL, ic, TRUE);
11765 /*-----------------------------------------------------------------*/
11766 /* genCritical - generate code for start of a critical sequence */
11767 /*-----------------------------------------------------------------*/
11769 genCritical (iCode *ic)
11771 symbol *tlbl = newiTempLabel (NULL);
11773 D (emitcode(";", "genCritical"));
11775 if (IC_RESULT (ic))
11777 aopOp (IC_RESULT (ic), ic, TRUE);
11778 aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
11779 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11780 aopPut (IC_RESULT (ic), zero, 0);
11782 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11786 emitcode ("setb", "c");
11787 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11788 emitcode ("clr", "c");
11790 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11794 /*-----------------------------------------------------------------*/
11795 /* genEndCritical - generate code for end of a critical sequence */
11796 /*-----------------------------------------------------------------*/
11798 genEndCritical (iCode *ic)
11800 D(emitcode(";", "genEndCritical"));
11804 aopOp (IC_RIGHT (ic), ic, FALSE);
11805 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11807 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11808 emitcode ("mov", "ea,c");
11812 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11813 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11814 emitcode ("rrc", "a");
11815 emitcode ("mov", "ea,c");
11817 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11821 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11822 emitcode ("mov", "ea,c");
11826 /*-----------------------------------------------------------------*/
11827 /* gen51Code - generate code for 8051 based controllers */
11828 /*-----------------------------------------------------------------*/
11830 gen51Code (iCode * lic)
11834 /* int cseq = 0; */
11836 _G.currentFunc = NULL;
11837 lineHead = lineCurr = NULL;
11839 /* print the allocation information */
11840 if (allocInfo && currFunc)
11841 printAllocInfo (currFunc, codeOutBuf);
11842 /* if debug information required */
11843 if (options.debug && currFunc)
11845 debugFile->writeFunction (currFunc, lic);
11847 /* stack pointer name */
11848 if (options.useXstack)
11854 for (ic = lic; ic; ic = ic->next)
11856 _G.current_iCode = ic;
11858 if (ic->lineno && cln != ic->lineno)
11862 debugFile->writeCLine (ic);
11864 if (!options.noCcodeInAsm) {
11865 emitcode (";", "%s:%d: %s", ic->filename, ic->lineno,
11866 printCLine(ic->filename, ic->lineno));
11871 if (ic->seqPoint && ic->seqPoint != cseq)
11873 emitcode (";", "sequence point %d", ic->seqPoint);
11874 cseq = ic->seqPoint;
11877 if (options.iCodeInAsm) {
11878 char regsInUse[80];
11883 for (i=0; i<8; i++) {
11884 sprintf (®sInUse[i],
11885 "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11888 strcpy (regsInUse, "--------");
11889 for (i=0; i < 8; i++) {
11890 if (bitVectBitValue (ic->rMask, i))
11892 int offset = regs8051[i].offset;
11893 regsInUse[offset] = offset + '0'; /* show rMask */
11897 iLine = printILine(ic);
11898 emitcode(";", "[%s] ic:%d: %s", regsInUse, ic->seq, iLine);
11901 /* if the result is marked as
11902 spilt and rematerializable or code for
11903 this has already been generated then
11905 if (resultRemat (ic) || ic->generated)
11908 /* depending on the operation */
11928 /* IPOP happens only when trying to restore a
11929 spilt live range, if there is an ifx statement
11930 following this pop then the if statement might
11931 be using some of the registers being popped which
11932 would destory the contents of the register so
11933 we need to check for this condition and handle it */
11935 ic->next->op == IFX &&
11936 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11937 genIfx (ic->next, ic);
11955 genEndFunction (ic);
11975 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11992 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11996 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
12003 /* note these two are xlated by algebraic equivalence
12004 in decorateType() in SDCCast.c */
12005 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12006 "got '>=' or '<=' shouldn't have come here");
12010 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
12022 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
12026 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
12030 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
12066 genRightShift (ic);
12069 case GET_VALUE_AT_ADDRESS:
12071 hasInc (IC_LEFT (ic), ic,
12072 getSize (operandType (IC_RESULT (ic)))),
12073 ifxForOp (IC_RESULT (ic), ic) );
12077 if (POINTER_SET (ic))
12079 hasInc (IC_RESULT (ic), ic,
12080 getSize (operandType (IC_RIGHT (ic)))));
12106 addSet (&_G.sendSet, ic);
12109 case DUMMY_READ_VOLATILE:
12118 genEndCritical (ic);
12130 _G.current_iCode = NULL;
12132 /* now we are ready to call the
12133 peep hole optimizer */
12134 if (!options.nopeep)
12135 peepHole (&lineHead);
12137 /* now do the actual printing */
12138 printLine (lineHead, codeOutBuf);