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 sym_link *type = operandType (op);
1797 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1804 /*-----------------------------------------------------------------*/
1805 /* getDataSize - get the operand data size */
1806 /*-----------------------------------------------------------------*/
1808 getDataSize (operand * op)
1811 size = AOP_SIZE (op);
1812 if (size == GPTRSIZE)
1814 sym_link *type = operandType (op);
1815 if (IS_GENPTR (type))
1817 /* generic pointer; arithmetic operations
1818 * should ignore the high byte (pointer type).
1826 /*-----------------------------------------------------------------*/
1827 /* outAcc - output Acc */
1828 /*-----------------------------------------------------------------*/
1830 outAcc (operand * result)
1833 size = getDataSize (result);
1836 aopPut (result, "a", 0);
1839 /* unsigned or positive */
1842 aopPut (result, zero, offset++);
1847 /*-----------------------------------------------------------------*/
1848 /* outBitC - output a bit C */
1849 /*-----------------------------------------------------------------*/
1851 outBitC (operand * result)
1853 /* if the result is bit */
1854 if (AOP_TYPE (result) == AOP_CRY)
1856 if (!IS_OP_RUONLY (result))
1857 aopPut (result, "c", 0);
1859 else if (AOP_TYPE (result) != AOP_DUMMY)
1861 emitcode ("clr", "a");
1862 emitcode ("rlc", "a");
1867 /*-----------------------------------------------------------------*/
1868 /* toBoolean - emit code for orl a,operator(sizeop) */
1869 /*-----------------------------------------------------------------*/
1871 toBoolean (operand * oper)
1873 int size = AOP_SIZE (oper) - 1;
1875 bool AccUsed = FALSE;
1878 while (!AccUsed && size--)
1880 AccUsed |= aopGetUsesAcc(oper, offset++);
1883 size = AOP_SIZE (oper) - 1;
1885 MOVA (aopGet (oper, 0, FALSE, FALSE));
1886 if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1889 emitcode("mov", "b,a");
1892 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1893 emitcode ("orl", "b,a");
1895 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1896 emitcode ("orl", "a,b");
1903 emitcode ("orl", "a,%s",
1904 aopGet (oper, offset++, FALSE, FALSE));
1909 /*-----------------------------------------------------------------*/
1910 /* toCarry - make boolean and move into carry */
1911 /*-----------------------------------------------------------------*/
1913 toCarry (operand * oper)
1915 /* if the operand is a literal then
1916 we know what the value is */
1917 if (AOP_TYPE (oper) == AOP_LIT)
1919 if ((int) operandLitValue (oper))
1924 else if (AOP_TYPE (oper) == AOP_CRY)
1926 emitcode ("mov", "c,%s", oper->aop->aopu.aop_dir);
1930 /* or the operand into a */
1932 /* set C, if a >= 1 */
1933 emitcode ("add", "a,#0xff");
1937 /*-----------------------------------------------------------------*/
1938 /* assignBit - assign operand to bit operand */
1939 /*-----------------------------------------------------------------*/
1941 assignBit (operand * result, operand * right)
1943 /* if the right side is a literal then
1944 we know what the value is */
1945 if (AOP_TYPE (right) == AOP_LIT)
1947 if ((int) operandLitValue (right))
1948 aopPut (result, one, 0);
1950 aopPut (result, zero, 0);
1955 aopPut (result, "c", 0);
1960 /*-------------------------------------------------------------------*/
1961 /* xch_a_aopGet - for exchanging acc with value of the aop */
1962 /*-------------------------------------------------------------------*/
1964 xch_a_aopGet (operand * oper, int offset, bool bit16, bool dname)
1968 if (aopGetUsesAcc (oper, offset))
1970 emitcode("mov", "b,a");
1971 MOVA (aopGet (oper, offset, bit16, dname));
1972 emitcode("xch", "a,b");
1973 aopPut (oper, "a", offset);
1974 emitcode("xch", "a,b");
1979 l = aopGet (oper, offset, bit16, dname);
1980 emitcode("xch", "a,%s", l);
1986 /*-----------------------------------------------------------------*/
1987 /* genNot - generate code for ! operation */
1988 /*-----------------------------------------------------------------*/
1994 D (emitcode (";", "genNot"));
1996 /* assign asmOps to operand & result */
1997 aopOp (IC_LEFT (ic), ic, FALSE);
1998 aopOp (IC_RESULT (ic), ic, TRUE);
2000 /* if in bit space then a special case */
2001 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2003 /* if left==result then cpl bit */
2004 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2006 emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2010 toCarry (IC_LEFT (ic));
2011 emitcode ("cpl", "c");
2012 outBitC (IC_RESULT (ic));
2017 toBoolean (IC_LEFT (ic));
2019 /* set C, if a == 0 */
2020 tlbl = newiTempLabel (NULL);
2021 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
2023 outBitC (IC_RESULT (ic));
2026 /* release the aops */
2027 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2028 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2032 /*-----------------------------------------------------------------*/
2033 /* genCpl - generate code for complement */
2034 /*-----------------------------------------------------------------*/
2041 sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
2043 D(emitcode (";", "genCpl"));
2045 /* assign asmOps to operand & result */
2046 aopOp (IC_LEFT (ic), ic, FALSE);
2047 aopOp (IC_RESULT (ic), ic, TRUE);
2049 /* special case if in bit space */
2050 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2054 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
2055 (SPEC_USIGN (letype) && IS_CHAR (letype)))
2057 /* promotion rules are responsible for this strange result:
2058 bit -> int -> ~int -> bit
2059 uchar -> int -> ~int -> bit
2061 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
2065 tlbl=newiTempLabel(NULL);
2066 l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
2067 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
2068 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
2069 IS_AOP_PREG (IC_LEFT (ic)))
2071 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
2076 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
2079 outBitC (IC_RESULT(ic));
2083 size = AOP_SIZE (IC_RESULT (ic));
2086 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2088 emitcode ("cpl", "a");
2089 aopPut (IC_RESULT (ic), "a", offset++);
2094 /* release the aops */
2095 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2096 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2099 /*-----------------------------------------------------------------*/
2100 /* genUminusFloat - unary minus for floating points */
2101 /*-----------------------------------------------------------------*/
2103 genUminusFloat (operand * op, operand * result)
2105 int size, offset = 0;
2108 D (emitcode (";", "genUminusFloat"));
2110 /* for this we just copy and then flip the bit */
2112 size = AOP_SIZE (op) - 1;
2117 aopGet (op, offset, FALSE, FALSE),
2122 l = aopGet (op, offset, FALSE, FALSE);
2125 emitcode ("cpl", "acc.7");
2126 aopPut (result, "a", offset);
2129 /*-----------------------------------------------------------------*/
2130 /* genUminus - unary minus code generation */
2131 /*-----------------------------------------------------------------*/
2133 genUminus (iCode * ic)
2138 D (emitcode (";", "genUminus"));
2141 aopOp (IC_LEFT (ic), ic, FALSE);
2142 aopOp (IC_RESULT (ic), ic, TRUE);
2144 /* if both in bit space then special
2146 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2147 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2150 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2151 emitcode ("cpl", "c");
2152 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2156 optype = operandType (IC_LEFT (ic));
2158 /* if float then do float stuff */
2159 if (IS_FLOAT (optype))
2161 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2165 /* otherwise subtract from zero */
2166 size = AOP_SIZE (IC_LEFT (ic));
2170 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2171 if (!strcmp (l, "a"))
2175 emitcode ("cpl", "a");
2176 emitcode ("addc", "a,#0");
2182 emitcode ("clr", "a");
2183 emitcode ("subb", "a,%s", l);
2185 aopPut (IC_RESULT (ic), "a", offset++);
2188 /* if any remaining bytes in the result */
2189 /* we just need to propagate the sign */
2190 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2192 emitcode ("rlc", "a");
2193 emitcode ("subb", "a,acc");
2195 aopPut (IC_RESULT (ic), "a", offset++);
2199 /* release the aops */
2200 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2201 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2204 /*-----------------------------------------------------------------*/
2205 /* saveRegisters - will look for a call and save the registers */
2206 /*-----------------------------------------------------------------*/
2208 saveRegisters (iCode * lic)
2215 for (ic = lic; ic; ic = ic->next)
2216 if (ic->op == CALL || ic->op == PCALL)
2221 fprintf (stderr, "found parameter push with no function call\n");
2225 /* if the registers have been saved already or don't need to be then
2229 if (IS_SYMOP(IC_LEFT(ic)) &&
2230 (IFFUNC_CALLEESAVES (OP_SYMBOL (IC_LEFT (ic))->type) ||
2231 IFFUNC_ISNAKED (OP_SYM_TYPE (IC_LEFT (ic)))))
2234 /* save the registers in use at this time but skip the
2235 ones for the result */
2236 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2237 mcs51_rUmaskForOp (IC_RESULT(ic)));
2240 if (options.useXstack)
2242 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2243 int nBits = bitVectnBitsOn (rsavebits);
2244 int count = bitVectnBitsOn (rsave);
2248 count = count - nBits + 1;
2249 /* remove all but the first bits as they are pushed all at once */
2250 rsave = bitVectCplAnd (rsave, rsavebits);
2251 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2253 freeBitVect (rsavebits);
2257 regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2258 if (reg->type == REG_BIT)
2260 emitcode ("mov", "a,%s", reg->base);
2264 emitcode ("mov", "a,%s", reg->name);
2266 emitcode ("mov", "r0,%s", spname);
2267 emitcode ("inc", "%s", spname);// allocate before use
2268 emitcode ("movx", "@r0,a");
2269 if (bitVectBitValue (rsave, R0_IDX))
2270 emitcode ("mov", "r0,a");
2272 else if (count != 0)
2274 if (bitVectBitValue (rsave, R0_IDX))
2276 emitcode ("push", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2278 emitcode ("mov", "r0,%s", spname);
2280 emitcode ("add", "a,#%d", count);
2281 emitcode ("mov", "%s,a", spname);
2282 for (i = 0; i < mcs51_nRegs; i++)
2284 if (bitVectBitValue (rsave, i))
2286 regs * reg = REG_WITH_INDEX (i);
2289 emitcode ("pop", "acc");
2290 emitcode ("push", "acc");
2292 else if (reg->type == REG_BIT)
2294 emitcode ("mov", "a,%s", reg->base);
2298 emitcode ("mov", "a,%s", reg->name);
2300 emitcode ("movx", "@r0,a");
2303 emitcode ("inc", "r0");
2307 if (bitVectBitValue (rsave, R0_IDX))
2309 emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2315 bool bits_pushed = FALSE;
2316 for (i = 0; i < mcs51_nRegs; i++)
2318 if (bitVectBitValue (rsave, i))
2320 bits_pushed = pushReg (i, bits_pushed);
2324 freeBitVect (rsave);
2327 /*-----------------------------------------------------------------*/
2328 /* unsaveRegisters - pop the pushed registers */
2329 /*-----------------------------------------------------------------*/
2331 unsaveRegisters (iCode * ic)
2336 /* restore the registers in use at this time but skip the
2337 ones for the result */
2338 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2339 mcs51_rUmaskForOp (IC_RESULT(ic)));
2341 if (options.useXstack)
2343 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2344 int nBits = bitVectnBitsOn (rsavebits);
2345 int count = bitVectnBitsOn (rsave);
2349 count = count - nBits + 1;
2350 /* remove all but the first bits as they are popped all at once */
2351 rsave = bitVectCplAnd (rsave, rsavebits);
2352 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2354 freeBitVect (rsavebits);
2358 regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2359 emitcode ("mov", "r0,%s", spname);
2360 emitcode ("dec", "r0");
2361 emitcode ("movx", "a,@r0");
2362 if (reg->type == REG_BIT)
2364 emitcode ("mov", "%s,a", reg->base);
2368 emitcode ("mov", "%s,a", reg->name);
2370 emitcode ("dec", "%s", spname);
2372 else if (count != 0)
2374 emitcode ("mov", "r0,%s", spname);
2375 for (i = mcs51_nRegs; i >= 0; i--)
2377 if (bitVectBitValue (rsave, i))
2379 regs * reg = REG_WITH_INDEX (i);
2380 emitcode ("dec", "r0");
2381 emitcode ("movx", "a,@r0");
2384 emitcode ("push", "acc");
2386 else if (reg->type == REG_BIT)
2388 emitcode ("mov", "%s,a", reg->base);
2392 emitcode ("mov", "%s,a", reg->name);
2396 emitcode ("mov", "%s,r0", spname);
2397 if (bitVectBitValue (rsave, R0_IDX))
2399 emitcode ("pop", "ar0");
2405 bool bits_popped = FALSE;
2406 for (i = mcs51_nRegs; i >= 0; i--)
2408 if (bitVectBitValue (rsave, i))
2410 bits_popped = popReg (i, bits_popped);
2414 freeBitVect (rsave);
2418 /*-----------------------------------------------------------------*/
2420 /*-----------------------------------------------------------------*/
2422 pushSide (operand * oper, int size, iCode * ic)
2425 int nPushed = _G.r0Pushed + _G.r1Pushed;
2427 aopOp (oper, ic, FALSE);
2429 if (nPushed != _G.r0Pushed + _G.r1Pushed)
2431 while (offset < size)
2433 char *l = aopGet (oper, offset, FALSE, TRUE);
2434 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2436 freeAsmop (oper, NULL, ic, TRUE);
2438 while (offset < size)
2440 emitcode ("push", "%s", fReturn[offset++]);
2447 char *l = aopGet (oper, offset++, FALSE, TRUE);
2448 if (AOP_TYPE (oper) != AOP_REG &&
2449 AOP_TYPE (oper) != AOP_DIR &&
2453 emitcode ("push", "acc");
2457 emitcode ("push", "%s", l);
2461 freeAsmop (oper, NULL, ic, TRUE);
2464 /*-----------------------------------------------------------------*/
2465 /* assignResultValue - also indicates if acc is in use afterwards */
2466 /*-----------------------------------------------------------------*/
2468 assignResultValue (operand * oper, operand * func)
2471 int size = AOP_SIZE (oper);
2472 bool accuse = FALSE;
2473 bool pushedA = FALSE;
2475 if (func && IS_BIT (OP_SYM_ETYPE (func)))
2481 if ((size > 3) && aopPutUsesAcc (oper, fReturn[offset], offset))
2483 emitcode ("push", "acc");
2488 if ((offset == 3) && pushedA)
2489 emitcode ("pop", "acc");
2490 accuse |= aopPut (oper, fReturn[offset], offset);
2497 /*-----------------------------------------------------------------*/
2498 /* genXpush - pushes onto the external stack */
2499 /*-----------------------------------------------------------------*/
2501 genXpush (iCode * ic)
2503 asmop *aop = newAsmop (0);
2505 int size, offset = 0;
2507 D (emitcode (";", "genXpush"));
2509 aopOp (IC_LEFT (ic), ic, FALSE);
2510 r = getFreePtr (ic, &aop, FALSE);
2512 size = AOP_SIZE (IC_LEFT (ic));
2516 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2517 emitcode ("mov", "%s,%s", r->name, spname);
2518 emitcode ("inc", "%s", spname); // allocate space first
2519 emitcode ("movx", "@%s,a", r->name);
2523 // allocate space first
2524 emitcode ("mov", "%s,%s", r->name, spname);
2526 emitcode ("add", "a,#%d", size);
2527 emitcode ("mov", "%s,a", spname);
2531 MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2532 emitcode ("movx", "@%s,a", r->name);
2533 emitcode ("inc", "%s", r->name);
2537 freeAsmop (NULL, aop, ic, TRUE);
2538 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2541 /*-----------------------------------------------------------------*/
2542 /* genIpush - generate code for pushing this gets a little complex */
2543 /*-----------------------------------------------------------------*/
2545 genIpush (iCode * ic)
2547 int size, offset = 0;
2551 D (emitcode (";", "genIpush"));
2553 /* if this is not a parm push : ie. it is spill push
2554 and spill push is always done on the local stack */
2558 /* and the item is spilt then do nothing */
2559 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2562 aopOp (IC_LEFT (ic), ic, FALSE);
2563 size = AOP_SIZE (IC_LEFT (ic));
2564 /* push it on the stack */
2567 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2573 emitcode ("push", "%s", l);
2578 /* this is a parameter push: in this case we call
2579 the routine to find the call and save those
2580 registers that need to be saved */
2583 /* if use external stack then call the external
2584 stack pushing routine */
2585 if (options.useXstack)
2591 /* then do the push */
2592 aopOp (IC_LEFT (ic), ic, FALSE);
2594 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2595 size = AOP_SIZE (IC_LEFT (ic));
2599 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2600 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2601 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR)
2603 if (strcmp (l, prev) || *l == '@')
2605 emitcode ("push", "acc");
2609 emitcode ("push", "%s", l);
2614 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2617 /*-----------------------------------------------------------------*/
2618 /* genIpop - recover the registers: can happen only for spilling */
2619 /*-----------------------------------------------------------------*/
2621 genIpop (iCode * ic)
2625 D (emitcode (";", "genIpop"));
2627 /* if the temp was not pushed then */
2628 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2631 aopOp (IC_LEFT (ic), ic, FALSE);
2632 size = AOP_SIZE (IC_LEFT (ic));
2633 offset = (size - 1);
2636 emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2640 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2643 /*-----------------------------------------------------------------*/
2644 /* saveRBank - saves an entire register bank on the stack */
2645 /*-----------------------------------------------------------------*/
2647 saveRBank (int bank, iCode * ic, bool pushPsw)
2650 int count = 8 + (pushPsw ? 1 : 0);
2654 if (options.useXstack)
2658 /* Assume r0 is available for use. */
2659 r = REG_WITH_INDEX (R0_IDX);
2664 r = getFreePtr (ic, &aop, FALSE);
2666 // allocate space first
2667 emitcode ("mov", "%s,%s", r->name, spname);
2669 emitcode ("add", "a,#%d", count);
2670 emitcode ("mov", "%s,a", spname);
2673 for (i = 0; i < 8; i++)
2675 if (options.useXstack)
2677 emitcode ("mov", "a,(%s+%d)",
2678 regs8051[i].base, 8 * bank + regs8051[i].offset);
2679 emitcode ("movx", "@%s,a", r->name);
2681 emitcode ("inc", "%s", r->name);
2684 emitcode ("push", "(%s+%d)",
2685 regs8051[i].base, 8 * bank + regs8051[i].offset);
2690 if (options.useXstack)
2692 emitcode ("mov", "a,psw");
2693 emitcode ("movx", "@%s,a", r->name);
2697 emitcode ("push", "psw");
2700 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2705 freeAsmop (NULL, aop, ic, TRUE);
2714 /*-----------------------------------------------------------------*/
2715 /* unsaveRBank - restores the register bank from stack */
2716 /*-----------------------------------------------------------------*/
2718 unsaveRBank (int bank, iCode * ic, bool popPsw)
2724 if (options.useXstack)
2728 /* Assume r0 is available for use. */
2729 r = REG_WITH_INDEX (R0_IDX);;
2734 r = getFreePtr (ic, &aop, FALSE);
2736 emitcode ("mov", "%s,%s", r->name, spname);
2741 if (options.useXstack)
2743 emitcode ("dec", "%s", r->name);
2744 emitcode ("movx", "a,@%s", r->name);
2745 emitcode ("mov", "psw,a");
2749 emitcode ("pop", "psw");
2753 for (i = 7; i >= 0; i--)
2755 if (options.useXstack)
2757 emitcode ("dec", "%s", r->name);
2758 emitcode ("movx", "a,@%s", r->name);
2759 emitcode ("mov", "(%s+%d),a",
2760 regs8051[i].base, 8 * bank + regs8051[i].offset);
2764 emitcode ("pop", "(%s+%d)",
2765 regs8051[i].base, 8 * bank + regs8051[i].offset);
2769 if (options.useXstack)
2771 emitcode ("mov", "%s,%s", spname, r->name);
2776 freeAsmop (NULL, aop, ic, TRUE);
2780 /*-----------------------------------------------------------------*/
2781 /* genSend - gen code for SEND */
2782 /*-----------------------------------------------------------------*/
2783 static void genSend(set *sendSet)
2788 /* first we do all bit parameters */
2789 for (sic = setFirstItem (sendSet); sic;
2790 sic = setNextItem (sendSet))
2792 if (sic->argreg > 12)
2794 int bit = sic->argreg-13;
2796 aopOp (IC_LEFT (sic), sic, FALSE);
2798 /* if left is a literal then
2799 we know what the value is */
2800 if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2802 if (((int) operandLitValue (IC_LEFT (sic))))
2803 emitcode ("setb", "b[%d]", bit);
2805 emitcode ("clr", "b[%d]", bit);
2810 toCarry (IC_LEFT (sic));
2811 emitcode ("mov", "b[%d],c", bit);
2816 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2822 saveRegisters (setFirstItem (sendSet));
2823 emitcode ("mov", "bits,b");
2826 /* then we do all other parameters */
2827 for (sic = setFirstItem (sendSet); sic;
2828 sic = setNextItem (sendSet))
2830 if (sic->argreg <= 12)
2832 int size, offset = 0;
2833 aopOp (IC_LEFT (sic), sic, FALSE);
2834 size = AOP_SIZE (IC_LEFT (sic));
2836 if (sic->argreg == 1)
2840 char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2841 if (strcmp (l, fReturn[offset]))
2843 emitcode ("mov", "%s,%s", fReturn[offset], l);
2852 emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2853 aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2857 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2862 /*-----------------------------------------------------------------*/
2863 /* selectRegBank - emit code to select the register bank */
2864 /*-----------------------------------------------------------------*/
2866 selectRegBank (short bank, bool keepFlags)
2868 /* if f.e. result is in carry */
2871 emitcode ("anl", "psw,#0xE7");
2873 emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2877 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2881 /*-----------------------------------------------------------------*/
2882 /* genCall - generates a call statement */
2883 /*-----------------------------------------------------------------*/
2885 genCall (iCode * ic)
2889 // bool restoreBank = FALSE;
2890 bool swapBanks = FALSE;
2891 bool accuse = FALSE;
2892 bool accPushed = FALSE;
2893 bool resultInF0 = FALSE;
2894 bool assignResultGenerated = FALSE;
2896 D (emitcode (";", "genCall"));
2898 dtype = operandType (IC_LEFT (ic));
2899 etype = getSpec(dtype);
2900 /* if send set is not empty then assign */
2903 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2904 genSend(reverseSet(_G.sendSet));
2906 genSend(_G.sendSet);
2911 /* if we are calling a not _naked function that is not using
2912 the same register bank then we need to save the
2913 destination registers on the stack */
2914 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2915 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2916 !IFFUNC_ISISR (dtype))
2921 /* if caller saves & we have not saved then */
2927 emitcode ("mov", "psw,#0x%02x",
2928 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2932 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2934 if (IFFUNC_CALLEESAVES(dtype))
2936 werror (E_BANKED_WITH_CALLEESAVES);
2940 char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2941 OP_SYMBOL (IC_LEFT (ic))->rname :
2942 OP_SYMBOL (IC_LEFT (ic))->name);
2944 emitcode ("mov", "r0,#%s", l);
2945 emitcode ("mov", "r1,#(%s >> 8)", l);
2946 emitcode ("mov", "r2,#(%s >> 16)", l);
2947 emitcode ("lcall", "__sdcc_banked_call");
2952 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2953 OP_SYMBOL (IC_LEFT (ic))->rname :
2954 OP_SYMBOL (IC_LEFT (ic))->name));
2959 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2962 /* if we need assign a result value */
2963 if ((IS_ITEMP (IC_RESULT (ic)) &&
2964 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2965 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2966 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2967 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2968 IS_TRUE_SYMOP (IC_RESULT (ic)))
2972 aopOp (IC_RESULT (ic), ic, FALSE);
2975 accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2976 assignResultGenerated = TRUE;
2978 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2981 /* adjust the stack for parameters if required */
2985 if (ic->parmBytes > 3)
2989 emitcode ("push", "acc");
2992 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2993 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2994 !assignResultGenerated)
2996 emitcode ("mov", "F0,c");
3000 emitcode ("mov", "a,%s", spname);
3001 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3002 emitcode ("mov", "%s,a", spname);
3004 /* unsaveRegisters from xstack needs acc, but */
3005 /* unsaveRegisters from stack needs this popped */
3006 if (accPushed && !options.useXstack)
3008 emitcode ("pop", "acc");
3013 for (i = 0; i < ic->parmBytes; i++)
3014 emitcode ("dec", "%s", spname);
3017 /* if we had saved some registers then unsave them */
3018 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3020 if (accuse && !accPushed && options.useXstack)
3022 /* xstack needs acc, but doesn't touch normal stack */
3023 emitcode ("push", "acc");
3026 unsaveRegisters (ic);
3029 // /* if register bank was saved then pop them */
3031 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
3033 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
3036 emitcode ("mov", "c,F0");
3038 aopOp (IC_RESULT (ic), ic, FALSE);
3039 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3040 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3044 emitcode ("pop", "acc");
3047 /*-----------------------------------------------------------------*/
3048 /* genPcall - generates a call by pointer statement */
3049 /*-----------------------------------------------------------------*/
3051 genPcall (iCode * ic)
3055 symbol *rlbl = newiTempLabel (NULL);
3056 // bool restoreBank=FALSE;
3057 bool swapBanks = FALSE;
3058 bool resultInF0 = FALSE;
3060 D (emitcode (";", "genPcall"));
3062 dtype = operandType (IC_LEFT (ic))->next;
3063 etype = getSpec(dtype);
3064 /* if caller saves & we have not saved then */
3068 /* if we are calling a not _naked function that is not using
3069 the same register bank then we need to save the
3070 destination registers on the stack */
3071 if (currFunc && dtype && !IFFUNC_ISNAKED (dtype) &&
3072 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
3073 !IFFUNC_ISISR (dtype))
3075 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3076 // restoreBank=TRUE;
3078 // need caution message to user here
3081 if (IS_LITERAL (etype))
3083 /* if send set is not empty then assign */
3086 genSend(reverseSet(_G.sendSet));
3092 emitcode ("mov", "psw,#0x%02x",
3093 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3096 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT (getSpec(dtype)))
3098 if (IFFUNC_CALLEESAVES (dtype))
3100 werror (E_BANKED_WITH_CALLEESAVES);
3104 char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
3106 emitcode ("mov", "r0,#%s", l);
3107 emitcode ("mov", "r1,#(%s >> 8)", l);
3108 emitcode ("mov", "r2,#(%s >> 16)", l);
3109 emitcode ("lcall", "__sdcc_banked_call");
3114 emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
3119 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT (getSpec(dtype)))
3121 if (IFFUNC_CALLEESAVES (dtype))
3123 werror (E_BANKED_WITH_CALLEESAVES);
3127 aopOp (IC_LEFT (ic), ic, FALSE);
3131 /* what if aopGet needs r0 or r1 ??? */
3132 emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3133 emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3134 emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3138 int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
3139 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3140 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3141 emitcode ("mov", "0x%02x,%s", reg, aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3144 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3146 /* if send set is not empty then assign */
3149 genSend(reverseSet(_G.sendSet));
3155 emitcode ("mov", "psw,#0x%02x",
3156 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3160 emitcode ("lcall", "__sdcc_banked_call");
3163 else if (_G.sendSet)
3165 /* push the return address on to the stack */
3166 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
3167 emitcode ("push", "acc");
3168 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
3169 emitcode ("push", "acc");
3171 /* now push the function address */
3172 pushSide (IC_LEFT (ic), FPTRSIZE, ic);
3174 /* if send set is not empty then assign */
3177 genSend(reverseSet(_G.sendSet));
3183 emitcode ("mov", "psw,#0x%02x",
3184 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3188 emitcode ("ret", "");
3191 else /* the send set is empty */
3194 /* now get the calling address into dptr */
3195 aopOp (IC_LEFT (ic), ic, FALSE);
3197 l = aopGet (IC_LEFT (ic), 0, FALSE, FALSE);
3198 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3200 emitcode ("mov", "r0,%s", l);
3201 l = aopGet (IC_LEFT (ic), 1, FALSE, FALSE);
3202 emitcode ("mov", "dph,%s", l);
3203 emitcode ("mov", "dpl,r0");
3207 emitcode ("mov", "dpl,%s", l);
3208 l = aopGet (IC_LEFT (ic), 1, FALSE, FALSE);
3209 emitcode ("mov", "dph,%s", l);
3212 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3216 emitcode ("mov", "psw,#0x%02x",
3217 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3221 emitcode ("lcall", "__sdcc_call_dptr");
3226 selectRegBank (FUNC_REGBANK (currFunc->type), IS_BIT (etype));
3229 /* if we need assign a result value */
3230 if ((IS_ITEMP (IC_RESULT (ic)) &&
3231 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3232 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3233 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3234 IS_TRUE_SYMOP (IC_RESULT (ic)))
3238 aopOp (IC_RESULT (ic), ic, FALSE);
3241 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3243 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3246 /* adjust the stack for parameters if required */
3250 if (ic->parmBytes > 3)
3252 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3253 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3255 emitcode ("mov", "F0,c");
3259 emitcode ("mov", "a,%s", spname);
3260 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3261 emitcode ("mov", "%s,a", spname);
3264 for (i = 0; i < ic->parmBytes; i++)
3265 emitcode ("dec", "%s", spname);
3268 // /* if register bank was saved then unsave them */
3270 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3272 /* if we had saved some registers then unsave them */
3273 if (ic->regsSaved && !IFFUNC_CALLEESAVES (dtype))
3274 unsaveRegisters (ic);
3276 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3279 emitcode ("mov", "c,F0");
3281 aopOp (IC_RESULT (ic), ic, FALSE);
3282 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3283 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3287 /*-----------------------------------------------------------------*/
3288 /* resultRemat - result is rematerializable */
3289 /*-----------------------------------------------------------------*/
3291 resultRemat (iCode * ic)
3293 if (SKIP_IC (ic) || ic->op == IFX)
3296 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3298 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3299 if (sym->remat && !POINTER_SET (ic))
3306 /*-----------------------------------------------------------------*/
3307 /* inExcludeList - return 1 if the string is in exclude Reg list */
3308 /*-----------------------------------------------------------------*/
3310 regsCmp(void *p1, void *p2)
3312 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3316 inExcludeList (char *s)
3318 const char *p = setFirstItem(options.excludeRegsSet);
3320 if (p == NULL || STRCASECMP(p, "none") == 0)
3324 return isinSetWith(options.excludeRegsSet, s, regsCmp);
3327 /*-----------------------------------------------------------------*/
3328 /* genFunction - generated code for function entry */
3329 /*-----------------------------------------------------------------*/
3331 genFunction (iCode * ic)
3333 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3335 bool switchedPSW = FALSE;
3336 int calleesaves_saved_register = -1;
3337 int stackAdjust = sym->stack;
3338 int accIsFree = sym->recvSize < 4;
3339 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3340 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3343 /* create the function header */
3344 emitcode (";", "-----------------------------------------");
3345 emitcode (";", " function %s", sym->name);
3346 emitcode (";", "-----------------------------------------");
3348 emitcode ("", "%s:", sym->rname);
3349 lineCurr->isLabel = 1;
3350 ftype = operandType (IC_LEFT (ic));
3351 _G.currentFunc = sym;
3353 if (IFFUNC_ISNAKED(ftype))
3355 emitcode(";", "naked function: no prologue.");
3359 /* here we need to generate the equates for the
3360 register bank if required */
3361 if (FUNC_REGBANK (ftype) != rbank)
3365 rbank = FUNC_REGBANK (ftype);
3366 for (i = 0; i < mcs51_nRegs; i++)
3368 if (regs8051[i].type != REG_BIT)
3370 if (strcmp (regs8051[i].base, "0") == 0)
3371 emitcode ("", "%s = 0x%02x",
3373 8 * rbank + regs8051[i].offset);
3375 emitcode ("", "%s = %s + 0x%02x",
3378 8 * rbank + regs8051[i].offset);
3383 /* if this is an interrupt service routine then
3384 save acc, b, dpl, dph */
3385 if (IFFUNC_ISISR (sym->type))
3389 rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), sym->regsUsed);
3390 if (IFFUNC_HASFCALL(sym->type) || !bitVectIsZero (rsavebits))
3392 emitcode ("push", "bits");
3395 freeBitVect (rsavebits);
3397 if (!inExcludeList ("acc"))
3398 emitcode ("push", "acc");
3399 if (!inExcludeList ("b"))
3400 emitcode ("push", "b");
3401 if (!inExcludeList ("dpl"))
3402 emitcode ("push", "dpl");
3403 if (!inExcludeList ("dph"))
3404 emitcode ("push", "dph");
3405 /* if this isr has no bank i.e. is going to
3406 run with bank 0 , then we need to save more
3408 if (!FUNC_REGBANK (sym->type))
3412 /* if this function does not call any other
3413 function then we can be economical and
3414 save only those registers that are used */
3415 if (!IFFUNC_HASFCALL(sym->type))
3417 /* if any registers used */
3420 /* save the registers used */
3421 for (i = 0; i < sym->regsUsed->size; i++)
3423 if (bitVectBitValue (sym->regsUsed, i))
3430 /* this function has a function call. We cannot
3431 determine register usage so we will have to push the
3433 saveRBank (0, ic, FALSE);
3434 if (options.parms_in_bank1) {
3435 for (i=0; i < 8 ; i++ ) {
3436 emitcode ("push","%s",rb1regs[i]);
3443 /* This ISR uses a non-zero bank.
3445 * We assume that the bank is available for our
3448 * However, if this ISR calls a function which uses some
3449 * other bank, we must save that bank entirely.
3451 unsigned long banksToSave = 0;
3453 if (IFFUNC_HASFCALL(sym->type))
3456 #define MAX_REGISTER_BANKS 4
3461 for (i = ic; i; i = i->next)
3463 if (i->op == ENDFUNCTION)
3465 /* we got to the end OK. */
3473 dtype = operandType (IC_LEFT(i));
3475 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3477 /* Mark this bank for saving. */
3478 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3480 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3484 banksToSave |= (1 << FUNC_REGBANK(dtype));
3487 /* And note that we don't need to do it in
3495 /* This is a mess; we have no idea what
3496 * register bank the called function might
3499 * The only thing I can think of to do is
3500 * throw a warning and hope.
3502 werror(W_FUNCPTR_IN_USING_ISR);
3506 if (banksToSave && options.useXstack)
3508 /* Since we aren't passing it an ic,
3509 * saveRBank will assume r0 is available to abuse.
3511 * So switch to our (trashable) bank now, so
3512 * the caller's R0 isn't trashed.
3514 emitcode ("push", "psw");
3515 emitcode ("mov", "psw,#0x%02x",
3516 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3520 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3522 if (banksToSave & (1 << ix))
3524 saveRBank(ix, NULL, FALSE);
3528 // TODO: this needs a closer look
3529 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3532 /* Set the register bank to the desired value if nothing else */
3533 /* has done so yet. */
3536 emitcode ("push", "psw");
3537 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3542 /* This is a non-ISR function. The caller has already switched register */
3543 /* banks, if necessary, so just handle the callee-saves option. */
3545 /* if callee-save to be used for this function
3546 then save the registers being used in this function */
3547 if (IFFUNC_CALLEESAVES(sym->type))
3551 /* if any registers used */
3554 bool bits_pushed = FALSE;
3555 /* save the registers used */
3556 for (i = 0; i < sym->regsUsed->size; i++)
3558 if (bitVectBitValue (sym->regsUsed, i))
3560 /* remember one saved register for later usage */
3561 if (calleesaves_saved_register < 0)
3562 calleesaves_saved_register = i;
3563 bits_pushed = pushReg (i, bits_pushed);
3573 if (options.useXstack)
3575 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3577 emitcode ("mov", "r0,%s", spname);
3578 emitcode ("inc", "%s", spname);
3579 emitcode ("xch", "a,_bpx");
3580 emitcode ("movx", "@r0,a");
3581 emitcode ("inc", "r0");
3582 emitcode ("mov", "a,r0");
3583 emitcode ("xch", "a,_bpx");
3587 emitcode ("push", "_bp"); /* save the callers stack */
3588 emitcode ("mov", "_bp,sp");
3593 if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3595 /* set up the stack */
3596 emitcode ("push", "_bp"); /* save the callers stack */
3597 emitcode ("mov", "_bp,sp");
3602 /* For some cases it is worthwhile to perform a RECEIVE iCode */
3603 /* before setting up the stack frame completely. */
3604 if (ric && ric->argreg == 1 && IC_RESULT (ric))
3606 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3610 if (rsym && rsym->regType == REG_CND)
3612 if (rsym && (rsym->accuse || rsym->ruonly))
3614 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3615 rsym = rsym->usl.spillLoc;
3618 /* If the RECEIVE operand immediately spills to the first entry on the */
3619 /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3620 /* rather than the usual @r0/r1 machinations. */
3621 if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3625 _G.current_iCode = ric;
3626 D(emitcode (";", "genReceive"));
3627 for (ofs=0; ofs < sym->recvSize; ofs++)
3629 if (!strcmp (fReturn[ofs], "a"))
3630 emitcode ("push", "acc");
3632 emitcode ("push", fReturn[ofs]);
3634 stackAdjust -= sym->recvSize;
3637 assert (stackAdjust>=0);
3640 _G.current_iCode = ic;
3644 /* If the RECEIVE operand is 4 registers, we can do the moves now */
3645 /* to free up the accumulator. */
3646 else if (rsym && rsym->nRegs && sym->recvSize == 4)
3650 _G.current_iCode = ric;
3651 D(emitcode (";", "genReceive"));
3652 for (ofs=0; ofs < sym->recvSize; ofs++)
3654 emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3656 _G.current_iCode = ic;
3662 /* adjust the stack for the function */
3665 int i = stackAdjust;
3667 werror (W_STACK_OVERFLOW, sym->name);
3669 if (i > 3 && accIsFree)
3671 emitcode ("mov", "a,sp");
3672 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3673 emitcode ("mov", "sp,a");
3677 /* The accumulator is not free, so we will need another register */
3678 /* to clobber. No need to worry about a possible conflict with */
3679 /* the above early RECEIVE optimizations since they would have */
3680 /* freed the accumulator if they were generated. */
3682 if (IFFUNC_CALLEESAVES(sym->type))
3684 /* if it's a callee-saves function we need a saved register */
3685 if (calleesaves_saved_register >= 0)
3687 emitcode ("mov", "%s,a", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3688 emitcode ("mov", "a,sp");
3689 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3690 emitcode ("mov", "sp,a");
3691 emitcode ("mov", "a,%s", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3694 /* do it the hard way */
3696 emitcode ("inc", "sp");
3700 /* not callee-saves, we can clobber r0 */
3701 emitcode ("mov", "r0,a");
3702 emitcode ("mov", "a,sp");
3703 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3704 emitcode ("mov", "sp,a");
3705 emitcode ("mov", "a,r0");
3710 emitcode ("inc", "sp");
3715 char i = ((char) sym->xstack & 0xff);
3717 if (i > 3 && accIsFree)
3719 emitcode ("mov", "a,_spx");
3720 emitcode ("add", "a,#0x%02x", i & 0xff);
3721 emitcode ("mov", "_spx,a");
3725 emitcode ("push", "acc");
3726 emitcode ("mov", "a,_spx");
3727 emitcode ("add", "a,#0x%02x", i & 0xff);
3728 emitcode ("mov", "_spx,a");
3729 emitcode ("pop", "acc");
3734 emitcode ("inc", "_spx");
3738 /* if critical function then turn interrupts off */
3739 if (IFFUNC_ISCRITICAL (ftype))
3741 symbol *tlbl = newiTempLabel (NULL);
3742 emitcode ("setb", "c");
3743 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3744 emitcode ("clr", "c");
3746 emitcode ("push", "psw"); /* save old ea via c in psw */
3750 /*-----------------------------------------------------------------*/
3751 /* genEndFunction - generates epilogue for functions */
3752 /*-----------------------------------------------------------------*/
3754 genEndFunction (iCode * ic)
3756 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3757 lineNode *lnp = lineCurr;
3759 bitVect *regsUsedPrologue;
3760 bitVect *regsUnneeded;
3763 _G.currentFunc = NULL;
3764 if (IFFUNC_ISNAKED(sym->type))
3766 emitcode(";", "naked function: no epilogue.");
3767 if (options.debug && currFunc)
3768 debugFile->writeEndFunction (currFunc, ic, 0);
3772 if (IFFUNC_ISCRITICAL (sym->type))
3774 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3776 emitcode ("rlc", "a"); /* save c in a */
3777 emitcode ("pop", "psw"); /* restore ea via c in psw */
3778 emitcode ("mov", "ea,c");
3779 emitcode ("rrc", "a"); /* restore c from a */
3783 emitcode ("pop", "psw"); /* restore ea via c in psw */
3784 emitcode ("mov", "ea,c");
3788 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3790 if (options.useXstack)
3794 emitcode ("mov", "sp,_bp");
3795 emitcode ("pop", "_bp");
3797 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3799 emitcode ("xch", "a,_bpx");
3800 emitcode ("mov", "r0,a");
3801 emitcode ("dec", "r0");
3802 emitcode ("movx", "a,@r0");
3803 emitcode ("xch", "a,_bpx");
3804 emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3807 else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3810 emitcode ("mov", "sp,_bp");
3811 emitcode ("pop", "_bp");
3815 /* restore the register bank */
3816 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3818 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3819 || !options.useXstack)
3821 /* Special case of ISR using non-zero bank with useXstack
3824 emitcode ("pop", "psw");
3828 if (IFFUNC_ISISR (sym->type))
3832 /* now we need to restore the registers */
3833 /* if this isr has no bank i.e. is going to
3834 run with bank 0 , then we need to save more
3836 if (!FUNC_REGBANK (sym->type))
3839 /* if this function does not call any other
3840 function then we can be economical and
3841 save only those registers that are used */
3842 if (!IFFUNC_HASFCALL(sym->type))
3844 /* if any registers used */
3847 /* save the registers used */
3848 for (i = sym->regsUsed->size; i >= 0; i--)
3850 if (bitVectBitValue (sym->regsUsed, i))
3857 if (options.parms_in_bank1) {
3858 for (i = 7 ; i >= 0 ; i-- ) {
3859 emitcode ("pop","%s",rb1regs[i]);
3862 /* this function has a function call. We cannot
3863 determine register usage so we will have to pop the
3865 unsaveRBank (0, ic, FALSE);
3870 /* This ISR uses a non-zero bank.
3872 * Restore any register banks saved by genFunction
3875 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3878 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3880 if (savedBanks & (1 << ix))
3882 unsaveRBank(ix, NULL, FALSE);
3886 if (options.useXstack)
3888 /* Restore bank AFTER calling unsaveRBank,
3889 * since it can trash r0.
3891 emitcode ("pop", "psw");
3895 if (!inExcludeList ("dph"))
3896 emitcode ("pop", "dph");
3897 if (!inExcludeList ("dpl"))
3898 emitcode ("pop", "dpl");
3899 if (!inExcludeList ("b"))
3900 emitcode ("pop", "b");
3901 if (!inExcludeList ("acc"))
3902 emitcode ("pop", "acc");
3904 rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), sym->regsUsed);
3905 if (IFFUNC_HASFCALL(sym->type) || !bitVectIsZero (rsavebits))
3906 emitcode ("pop", "bits");
3907 freeBitVect (rsavebits);
3909 /* if debug then send end of function */
3910 if (options.debug && currFunc)
3912 debugFile->writeEndFunction (currFunc, ic, 1);
3915 emitcode ("reti", "");
3919 if (IFFUNC_CALLEESAVES(sym->type))
3923 /* if any registers used */
3926 /* save the registers used */
3927 for (i = sym->regsUsed->size; i >= 0; i--)
3929 if (bitVectBitValue (sym->regsUsed, i) ||
3930 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3931 emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
3934 else if (mcs51_ptrRegReq)
3936 emitcode ("pop", "%s", REG_WITH_INDEX (R1_IDX)->dname);
3937 emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
3942 /* if debug then send end of function */
3943 if (options.debug && currFunc)
3945 debugFile->writeEndFunction (currFunc, ic, 1);
3948 if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3950 emitcode ("ljmp", "__sdcc_banked_ret");
3954 emitcode ("ret", "");
3958 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3961 /* If this was an interrupt handler using bank 0 that called another */
3962 /* function, then all registers must be saved; nothing to optimized. */
3963 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3964 && !FUNC_REGBANK(sym->type))
3967 /* There are no push/pops to optimize if not callee-saves or ISR */
3968 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3971 /* If there were stack parameters, we cannot optimize without also */
3972 /* fixing all of the stack offsets; this is too dificult to consider. */
3973 if (FUNC_HASSTACKPARM(sym->type))
3976 /* Compute the registers actually used */
3977 regsUsed = newBitVect (mcs51_nRegs);
3978 regsUsedPrologue = newBitVect (mcs51_nRegs);
3981 if (lnp->ic && lnp->ic->op == FUNCTION)
3982 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3984 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3986 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3987 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3994 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3995 && !bitVectBitValue (regsUsed, CND_IDX))
3997 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3998 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3999 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
4000 bitVectUnSetBit (regsUsed, CND_IDX);
4003 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
4005 /* If this was an interrupt handler that called another function */
4006 /* function, then assume A, B, DPH, & DPL may be modified by it. */
4007 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
4009 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
4010 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
4011 regsUsed = bitVectSetBit (regsUsed, B_IDX);
4012 regsUsed = bitVectSetBit (regsUsed, A_IDX);
4013 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
4016 /* Remove the unneeded push/pops */
4017 regsUnneeded = newBitVect (mcs51_nRegs);
4020 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
4022 if (!strncmp(lnp->line, "push", 4))
4024 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
4025 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4027 connectLine (lnp->prev, lnp->next);
4028 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4031 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
4033 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
4034 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4036 connectLine (lnp->prev, lnp->next);
4037 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4044 for (idx = 0; idx < regsUnneeded->size; idx++)
4045 if (bitVectBitValue (regsUnneeded, idx))
4046 emitcode (";", "eliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
4048 freeBitVect (regsUnneeded);
4049 freeBitVect (regsUsed);
4050 freeBitVect (regsUsedPrologue);
4053 /*-----------------------------------------------------------------*/
4054 /* genRet - generate code for return statement */
4055 /*-----------------------------------------------------------------*/
4059 int size, offset = 0, pushed = 0;
4061 D (emitcode (";", "genRet"));
4063 /* if we have no return value then
4064 just generate the "ret" */
4068 /* we have something to return then
4069 move the return value into place */
4070 aopOp (IC_LEFT (ic), ic, FALSE);
4071 size = AOP_SIZE (IC_LEFT (ic));
4073 if (IS_BIT(_G.currentFunc->etype))
4075 if (!IS_OP_RUONLY (IC_LEFT (ic)))
4076 toCarry (IC_LEFT (ic));
4083 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
4086 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
4087 emitcode ("push", "%s", l);
4092 l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
4093 if (strcmp (fReturn[offset], l))
4094 emitcode ("mov", "%s,%s", fReturn[offset++], l);
4101 if (strcmp (fReturn[pushed], "a"))
4102 emitcode ("pop", fReturn[pushed]);
4104 emitcode ("pop", "acc");
4107 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
4110 /* generate a jump to the return label
4111 if the next is not the return statement */
4112 if (!(ic->next && ic->next->op == LABEL &&
4113 IC_LABEL (ic->next) == returnLabel))
4115 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
4119 /*-----------------------------------------------------------------*/
4120 /* genLabel - generates a label */
4121 /*-----------------------------------------------------------------*/
4123 genLabel (iCode * ic)
4125 /* special case never generate */
4126 if (IC_LABEL (ic) == entryLabel)
4129 emitLabel (IC_LABEL (ic));
4132 /*-----------------------------------------------------------------*/
4133 /* genGoto - generates a ljmp */
4134 /*-----------------------------------------------------------------*/
4136 genGoto (iCode * ic)
4138 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
4141 /*-----------------------------------------------------------------*/
4142 /* findLabelBackwards: walks back through the iCode chain looking */
4143 /* for the given label. Returns number of iCode instructions */
4144 /* between that label and given ic. */
4145 /* Returns zero if label not found. */
4146 /*-----------------------------------------------------------------*/
4148 findLabelBackwards (iCode * ic, int key)
4157 /* If we have any pushes or pops, we cannot predict the distance.
4158 I don't like this at all, this should be dealt with in the
4160 if (ic->op == IPUSH || ic->op == IPOP) {
4164 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4173 /*-----------------------------------------------------------------*/
4174 /* genPlusIncr :- does addition with increment if possible */
4175 /*-----------------------------------------------------------------*/
4177 genPlusIncr (iCode * ic)
4179 unsigned int icount;
4180 unsigned int size = getDataSize (IC_RESULT (ic));
4182 /* will try to generate an increment */
4183 /* if the right side is not a literal
4185 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4188 icount = (unsigned int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4190 D(emitcode (";","genPlusIncr"));
4192 /* if increment >=16 bits in register or direct space */
4193 if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG ||
4194 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4195 (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4196 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4197 !isOperandVolatile (IC_RESULT (ic), FALSE) &&
4205 /* If the next instruction is a goto and the goto target
4206 * is < 10 instructions previous to this, we can generate
4207 * jumps straight to that target.
4209 if (ic->next && ic->next->op == GOTO
4210 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4211 && labelRange <= 10)
4213 D (emitcode (";", "tail increment optimized (range %d)", labelRange));
4214 tlbl = IC_LABEL (ic->next);
4219 tlbl = newiTempLabel (NULL);
4222 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4223 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4224 IS_AOP_PREG (IC_RESULT (ic)))
4225 emitcode ("cjne", "%s,#0x00,%05d$",
4226 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4230 emitcode ("clr", "a");
4231 emitcode ("cjne", "a,%s,%05d$",
4232 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4236 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4239 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4240 IS_AOP_PREG (IC_RESULT (ic)))
4241 emitcode ("cjne", "%s,#0x00,%05d$",
4242 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4245 emitcode ("cjne", "a,%s,%05d$",
4246 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4249 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4253 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4254 IS_AOP_PREG (IC_RESULT (ic)))
4255 emitcode ("cjne", "%s,#0x00,%05d$",
4256 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4260 emitcode ("cjne", "a,%s,%05d$",
4261 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4264 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4274 /* if result is dptr */
4275 if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
4276 (AOP_SIZE (IC_RESULT (ic)) == 2) &&
4277 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
4278 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
4280 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4286 if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
4289 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0);
4290 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1);
4292 emitcode ("inc", "dptr");
4297 /* if the literal value of the right hand side
4298 is greater than 4 then it is not worth it */
4302 /* if the sizes are greater than 1 then we cannot */
4303 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4304 AOP_SIZE (IC_LEFT (ic)) > 1)
4307 /* we can if the aops of the left & result match or
4308 if they are in registers and the registers are the
4310 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4314 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4315 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4316 aopPut (IC_RESULT (ic), "a", 0);
4322 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4331 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4332 emitcode ("inc", "a");
4333 aopPut (IC_RESULT (ic), "a", 0);
4340 /*-----------------------------------------------------------------*/
4341 /* outBitAcc - output a bit in acc */
4342 /*-----------------------------------------------------------------*/
4344 outBitAcc (operand * result)
4346 symbol *tlbl = newiTempLabel (NULL);
4347 /* if the result is a bit */
4348 if (AOP_TYPE (result) == AOP_CRY)
4350 aopPut (result, "a", 0);
4354 emitcode ("jz", "%05d$", tlbl->key + 100);
4355 emitcode ("mov", "a,%s", one);
4361 /*-----------------------------------------------------------------*/
4362 /* genPlusBits - generates code for addition of two bits */
4363 /*-----------------------------------------------------------------*/
4365 genPlusBits (iCode * ic)
4367 D (emitcode (";", "genPlusBits"));
4369 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4370 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4372 symbol *lbl = newiTempLabel (NULL);
4373 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4374 emitcode ("cpl", "c");
4376 outBitC (IC_RESULT (ic));
4380 emitcode ("clr", "a");
4381 emitcode ("rlc", "a");
4382 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4383 emitcode ("addc", "a,%s", zero);
4384 outAcc (IC_RESULT (ic));
4389 /* This is the original version of this code.
4391 * This is being kept around for reference,
4392 * because I am not entirely sure I got it right...
4395 adjustArithmeticResult (iCode * ic)
4397 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4398 AOP_SIZE (IC_LEFT (ic)) == 3 &&
4399 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4400 aopPut (IC_RESULT (ic),
4401 aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4404 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4405 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4406 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4407 aopPut (IC_RESULT (ic),
4408 aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4411 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4412 AOP_SIZE (IC_LEFT (ic)) < 3 &&
4413 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4414 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4415 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4418 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4419 aopPut (IC_RESULT (ic), buffer, 2);
4423 /* This is the pure and virtuous version of this code.
4424 * I'm pretty certain it's right, but not enough to toss the old
4428 adjustArithmeticResult (iCode * ic)
4430 if (opIsGptr (IC_RESULT (ic)) &&
4431 opIsGptr (IC_LEFT (ic)) &&
4432 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4434 aopPut (IC_RESULT (ic),
4435 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4439 if (opIsGptr (IC_RESULT (ic)) &&
4440 opIsGptr (IC_RIGHT (ic)) &&
4441 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4443 aopPut (IC_RESULT (ic),
4444 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4448 if (opIsGptr (IC_RESULT (ic)) &&
4449 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4450 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4451 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4452 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4455 SNPRINTF (buffer, sizeof(buffer),
4456 "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4457 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4462 /*-----------------------------------------------------------------*/
4463 /* genPlus - generates code for addition */
4464 /*-----------------------------------------------------------------*/
4466 genPlus (iCode * ic)
4468 int size, offset = 0;
4471 bool swappedLR = FALSE;
4472 operand *leftOp, *rightOp;
4475 D (emitcode (";", "genPlus"));
4477 /* special cases :- */
4479 aopOp (IC_LEFT (ic), ic, FALSE);
4480 aopOp (IC_RIGHT (ic), ic, FALSE);
4481 aopOp (IC_RESULT (ic), ic, TRUE);
4483 /* if literal, literal on the right or
4484 if left requires ACC or right is already
4486 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4487 (AOP_NEEDSACC (IC_LEFT (ic))) ||
4488 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4490 operand *t = IC_RIGHT (ic);
4491 IC_RIGHT (ic) = IC_LEFT (ic);
4496 /* if both left & right are in bit
4498 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4499 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4505 /* if left in bit space & right literal */
4506 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4507 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4509 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4510 /* if result in bit space */
4511 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4513 if (ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4514 emitcode ("cpl", "c");
4515 outBitC (IC_RESULT (ic));
4519 size = getDataSize (IC_RESULT (ic));
4522 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4523 emitcode ("addc", "a,%s", zero);
4524 aopPut (IC_RESULT (ic), "a", offset++);
4530 /* if I can do an increment instead
4531 of add then GOOD for ME */
4532 if (genPlusIncr (ic) == TRUE)
4535 size = getDataSize (IC_RESULT (ic));
4536 leftOp = IC_LEFT(ic);
4537 rightOp = IC_RIGHT(ic);
4540 /* if this is an add for an array access
4541 at a 256 byte boundary */
4543 && AOP_TYPE (op) == AOP_IMMD
4545 && IS_SPEC (OP_SYM_ETYPE (op))
4546 && SPEC_ABSA (OP_SYM_ETYPE (op))
4547 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4550 D(emitcode (";", "genPlus aligned array"));
4551 aopPut (IC_RESULT (ic),
4552 aopGet (rightOp, 0, FALSE, FALSE),
4555 if( 1 == getDataSize (IC_RIGHT (ic)) )
4557 aopPut (IC_RESULT (ic),
4558 aopGet (leftOp, 1, FALSE, FALSE),
4563 MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4564 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4565 aopPut (IC_RESULT (ic), "a", 1);
4570 /* if the lower bytes of a literal are zero skip the addition */
4571 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4573 while ((0 == ((unsigned int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4574 (skip_bytes+1 < size))
4579 D(emitcode (";", "genPlus shortcut"));
4584 if( offset >= skip_bytes )
4586 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4589 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4591 emitcode("xch", "a,b");
4592 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4593 emitcode (add, "a,b");
4596 else if (aopGetUsesAcc (leftOp, offset))
4598 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4599 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4603 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4604 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4606 aopPut (IC_RESULT (ic), "a", offset);
4607 add = "addc"; /* further adds must propagate carry */
4611 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4612 isOperandVolatile (IC_RESULT (ic), FALSE))
4615 aopPut (IC_RESULT (ic),
4616 aopGet (leftOp, offset, FALSE, FALSE),
4623 adjustArithmeticResult (ic);
4626 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4629 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4630 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4634 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4635 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4639 /*-----------------------------------------------------------------*/
4640 /* genMinusDec :- does subtraction with decrement if possible */
4641 /*-----------------------------------------------------------------*/
4643 genMinusDec (iCode * ic)
4645 unsigned int icount;
4646 unsigned int size = getDataSize (IC_RESULT (ic));
4648 /* will try to generate an increment */
4649 /* if the right side is not a literal
4651 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4654 /* if the literal value of the right hand side
4655 is greater than 4 then it is not worth it */
4656 if ((icount = (unsigned int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4659 D (emitcode (";", "genMinusDec"));
4661 /* if decrement >=16 bits in register or direct space */
4662 if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG ||
4663 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4664 (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4665 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4673 /* If the next instruction is a goto and the goto target
4674 * is <= 10 instructions previous to this, we can generate
4675 * jumps straight to that target.
4677 if (ic->next && ic->next->op == GOTO
4678 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4679 && labelRange <= 10)
4681 D (emitcode (";", "tail decrement optimized (range %d)", labelRange));
4682 tlbl = IC_LABEL (ic->next);
4687 tlbl = newiTempLabel (NULL);
4691 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4692 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4693 IS_AOP_PREG (IC_RESULT (ic)))
4694 emitcode ("cjne", "%s,#0xff,%05d$"
4695 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4699 emitcode ("mov", "a,#0xff");
4700 emitcode ("cjne", "a,%s,%05d$"
4701 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4704 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4707 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4708 IS_AOP_PREG (IC_RESULT (ic)))
4709 emitcode ("cjne", "%s,#0xff,%05d$"
4710 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4714 emitcode ("cjne", "a,%s,%05d$"
4715 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4718 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4722 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4723 IS_AOP_PREG (IC_RESULT (ic)))
4724 emitcode ("cjne", "%s,#0xff,%05d$"
4725 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4729 emitcode ("cjne", "a,%s,%05d$"
4730 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4733 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4742 /* if the sizes are greater than 1 then we cannot */
4743 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4744 AOP_SIZE (IC_LEFT (ic)) > 1)
4747 /* we can if the aops of the left & result match or
4748 if they are in registers and the registers are the
4750 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4754 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4756 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4761 l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
4766 emitcode ("dec", "%s", l);
4769 if (AOP_NEEDSACC (IC_RESULT (ic)))
4770 aopPut (IC_RESULT (ic), "a", 0);
4777 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4778 emitcode ("dec", "a");
4779 aopPut (IC_RESULT (ic), "a", 0);
4786 /*-----------------------------------------------------------------*/
4787 /* addSign - complete with sign */
4788 /*-----------------------------------------------------------------*/
4790 addSign (operand * result, int offset, int sign)
4792 int size = (getDataSize (result) - offset);
4797 emitcode ("rlc", "a");
4798 emitcode ("subb", "a,acc");
4801 aopPut (result, "a", offset++);
4808 aopPut (result, zero, offset++);
4814 /*-----------------------------------------------------------------*/
4815 /* genMinusBits - generates code for subtraction of two bits */
4816 /*-----------------------------------------------------------------*/
4818 genMinusBits (iCode * ic)
4820 symbol *lbl = newiTempLabel (NULL);
4822 D (emitcode (";", "genMinusBits"));
4824 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4826 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4827 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4828 emitcode ("cpl", "c");
4830 outBitC (IC_RESULT (ic));
4834 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4835 emitcode ("subb", "a,acc");
4836 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4837 emitcode ("inc", "a");
4839 aopPut (IC_RESULT (ic), "a", 0);
4840 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4844 /*-----------------------------------------------------------------*/
4845 /* genMinus - generates code for subtraction */
4846 /*-----------------------------------------------------------------*/
4848 genMinus (iCode * ic)
4850 int size, offset = 0;
4852 D (emitcode (";", "genMinus"));
4854 aopOp (IC_LEFT (ic), ic, FALSE);
4855 aopOp (IC_RIGHT (ic), ic, FALSE);
4856 aopOp (IC_RESULT (ic), ic, TRUE);
4858 /* special cases :- */
4859 /* if both left & right are in bit space */
4860 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4861 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4867 /* if I can do an decrement instead
4868 of subtract then GOOD for ME */
4869 if (genMinusDec (ic) == TRUE)
4872 size = getDataSize (IC_RESULT (ic));
4874 /* if literal, add a,#-lit, else normal subb */
4875 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4877 unsigned long lit = 0L;
4878 bool useCarry = FALSE;
4880 lit = ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4885 if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4887 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4888 if (!offset && !size && lit== (unsigned long) -1)
4890 emitcode ("dec", "a");
4894 /* first add without previous c */
4895 emitcode ("add", "a,#0x%02x",
4896 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4901 emitcode ("addc", "a,#0x%02x",
4902 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4904 aopPut (IC_RESULT (ic), "a", offset++);
4908 /* no need to add zeroes */
4909 if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4911 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4920 operand *leftOp, *rightOp;
4922 leftOp = IC_LEFT(ic);
4923 rightOp = IC_RIGHT(ic);
4927 if (aopGetUsesAcc(rightOp, offset)) {
4928 if (aopGetUsesAcc(leftOp, offset)) {
4931 MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4933 emitcode ("mov", "b,a");
4936 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4937 emitcode ("subb", "a,b");
4940 /* reverse subtraction with 2's complement */
4942 emitcode( "setb", "c");
4944 emitcode( "cpl", "c");
4945 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4946 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4947 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4948 emitcode("cpl", "a");
4949 if (size) /* skip if last byte */
4950 emitcode( "cpl", "c");
4953 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4956 emitcode ("subb", "a,%s",
4957 aopGet(rightOp, offset, FALSE, TRUE));
4960 aopPut (IC_RESULT (ic), "a", offset++);
4964 adjustArithmeticResult (ic);
4967 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4968 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4969 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4973 /*-----------------------------------------------------------------*/
4974 /* genMultbits :- multiplication of bits */
4975 /*-----------------------------------------------------------------*/
4977 genMultbits (operand * left,
4981 D (emitcode (";", "genMultbits"));
4983 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4984 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4988 /*-----------------------------------------------------------------*/
4989 /* genMultOneByte : 8*8=8/16 bit multiplication */
4990 /*-----------------------------------------------------------------*/
4992 genMultOneByte (operand * left,
4997 int size = AOP_SIZE (result);
4998 bool runtimeSign, compiletimeSign;
4999 bool lUnsigned, rUnsigned, pushedB;
5001 D (emitcode (";", "genMultOneByte"));
5003 if (size < 1 || size > 2)
5005 /* this should never happen */
5006 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
5007 AOP_SIZE(result), __FILE__, lineno);
5011 /* (if two literals: the value is computed before) */
5012 /* if one literal, literal on the right */
5013 if (AOP_TYPE (left) == AOP_LIT)
5018 /* emitcode (";", "swapped left and right"); */
5020 /* if no literal, unsigned on the right: shorter code */
5021 if ( AOP_TYPE (right) != AOP_LIT
5022 && SPEC_USIGN (getSpec (operandType (left))))
5029 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5030 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5034 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
5035 no need to take care about the signedness! */
5036 || (lUnsigned && rUnsigned))
5038 /* just an unsigned 8 * 8 = 8 multiply
5040 /* emitcode (";","unsigned"); */
5041 /* TODO: check for accumulator clash between left & right aops? */
5043 if (AOP_TYPE (right) == AOP_LIT)
5045 /* moving to accumulator first helps peepholes */
5046 MOVA (aopGet (left, 0, FALSE, FALSE));
5047 MOVB (aopGet (right, 0, FALSE, FALSE));
5051 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5052 MOVA (aopGet (left, 0, FALSE, FALSE));
5055 emitcode ("mul", "ab");
5056 aopPut (result, "a", 0);
5058 aopPut (result, "b", 1);
5064 /* we have to do a signed multiply */
5065 /* emitcode (";", "signed"); */
5067 /* now sign adjust for both left & right */
5069 /* let's see what's needed: */
5070 /* apply negative sign during runtime */
5071 runtimeSign = FALSE;
5072 /* negative sign from literals */
5073 compiletimeSign = FALSE;
5077 if (AOP_TYPE(left) == AOP_LIT)
5079 /* signed literal */
5080 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5082 compiletimeSign = TRUE;
5085 /* signed but not literal */
5091 if (AOP_TYPE(right) == AOP_LIT)
5093 /* signed literal */
5094 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
5096 compiletimeSign ^= TRUE;
5099 /* signed but not literal */
5103 /* initialize F0, which stores the runtime sign */
5106 if (compiletimeSign)
5107 emitcode ("setb", "F0"); /* set sign flag */
5109 emitcode ("clr", "F0"); /* reset sign flag */
5112 /* save the signs of the operands */
5113 if (AOP_TYPE(right) == AOP_LIT)
5115 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
5117 if (!rUnsigned && val < 0)
5118 emitcode ("mov", "b,#0x%02x", -val);
5120 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5122 else /* ! literal */
5124 if (rUnsigned) /* emitcode (";", "signed"); */
5125 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5128 MOVA (aopGet (right, 0, FALSE, FALSE));
5129 lbl = newiTempLabel (NULL);
5130 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5131 emitcode ("cpl", "F0"); /* complement sign flag */
5132 emitcode ("cpl", "a"); /* 2's complement */
5133 emitcode ("inc", "a");
5135 emitcode ("mov", "b,a");
5139 if (AOP_TYPE(left) == AOP_LIT)
5141 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5143 if (!lUnsigned && val < 0)
5144 emitcode ("mov", "a,#0x%02x", -val);
5146 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5148 else /* ! literal */
5150 MOVA (aopGet (left, 0, FALSE, FALSE));
5154 lbl = newiTempLabel (NULL);
5155 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5156 emitcode ("cpl", "F0"); /* complement sign flag */
5157 emitcode ("cpl", "a"); /* 2's complement */
5158 emitcode ("inc", "a");
5163 /* now the multiplication */
5164 emitcode ("mul", "ab");
5165 if (runtimeSign || compiletimeSign)
5167 lbl = newiTempLabel (NULL);
5169 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5170 emitcode ("cpl", "a"); /* lsb 2's complement */
5172 emitcode ("inc", "a"); /* inc doesn't set carry flag */
5175 emitcode ("add", "a,#1"); /* this sets carry flag */
5176 emitcode ("xch", "a,b");
5177 emitcode ("cpl", "a"); /* msb 2's complement */
5178 emitcode ("addc", "a,#0");
5179 emitcode ("xch", "a,b");
5183 aopPut (result, "a", 0);
5185 aopPut (result, "b", 1);
5190 /*-----------------------------------------------------------------*/
5191 /* genMult - generates code for multiplication */
5192 /*-----------------------------------------------------------------*/
5194 genMult (iCode * ic)
5196 operand *left = IC_LEFT (ic);
5197 operand *right = IC_RIGHT (ic);
5198 operand *result = IC_RESULT (ic);
5200 D (emitcode (";", "genMult"));
5202 /* assign the asmops */
5203 aopOp (left, ic, FALSE);
5204 aopOp (right, ic, FALSE);
5205 aopOp (result, ic, TRUE);
5207 /* special cases first */
5209 if (AOP_TYPE (left) == AOP_CRY &&
5210 AOP_TYPE (right) == AOP_CRY)
5212 genMultbits (left, right, result);
5216 /* if both are of size == 1 */
5217 #if 0 // one of them can be a sloc shared with the result
5218 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
5220 if (getSize(operandType(left)) == 1 &&
5221 getSize(operandType(right)) == 1)
5224 genMultOneByte (left, right, result);
5228 /* should have been converted to function call */
5229 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
5230 getSize(OP_SYMBOL(right)->type));
5234 freeAsmop (result, NULL, ic, TRUE);
5235 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5236 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5239 /*-----------------------------------------------------------------*/
5240 /* genDivbits :- division of bits */
5241 /*-----------------------------------------------------------------*/
5243 genDivbits (operand * left,
5250 D(emitcode (";", "genDivbits"));
5254 /* the result must be bit */
5255 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5256 l = aopGet (left, 0, FALSE, FALSE);
5260 emitcode ("div", "ab");
5261 emitcode ("rrc", "a");
5265 aopPut (result, "c", 0);
5268 /*-----------------------------------------------------------------*/
5269 /* genDivOneByte : 8 bit division */
5270 /*-----------------------------------------------------------------*/
5272 genDivOneByte (operand * left,
5276 bool lUnsigned, rUnsigned, pushedB;
5277 bool runtimeSign, compiletimeSign;
5278 bool accuse = FALSE;
5279 bool pushedA = FALSE;
5283 D(emitcode (";", "genDivOneByte"));
5285 /* Why is it necessary that genDivOneByte() can return an int result?
5288 volatile unsigned char uc;
5289 volatile signed char sc1, sc2;
5302 In all cases a one byte result would overflow, the following cast to int
5303 would return the wrong result.
5305 Two possible solution:
5306 a) cast operands to int, if ((unsigned) / (signed)) or
5307 ((signed) / (signed))
5308 b) return an 16 bit signed int; this is what we're doing here!
5311 size = AOP_SIZE (result) - 1;
5313 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5314 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5318 /* signed or unsigned */
5319 if (lUnsigned && rUnsigned)
5321 /* unsigned is easy */
5322 MOVB (aopGet (right, 0, FALSE, FALSE));
5323 MOVA (aopGet (left, 0, FALSE, FALSE));
5324 emitcode ("div", "ab");
5325 aopPut (result, "a", 0);
5327 aopPut (result, zero, offset++);
5333 /* signed is a little bit more difficult */
5335 /* now sign adjust for both left & right */
5337 /* let's see what's needed: */
5338 /* apply negative sign during runtime */
5339 runtimeSign = FALSE;
5340 /* negative sign from literals */
5341 compiletimeSign = FALSE;
5345 if (AOP_TYPE(left) == AOP_LIT)
5347 /* signed literal */
5348 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5350 compiletimeSign = TRUE;
5353 /* signed but not literal */
5359 if (AOP_TYPE(right) == AOP_LIT)
5361 /* signed literal */
5362 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
5364 compiletimeSign ^= TRUE;
5367 /* signed but not literal */
5371 /* initialize F0, which stores the runtime sign */
5374 if (compiletimeSign)
5375 emitcode ("setb", "F0"); /* set sign flag */
5377 emitcode ("clr", "F0"); /* reset sign flag */
5380 /* save the signs of the operands */
5381 if (AOP_TYPE(right) == AOP_LIT)
5383 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
5385 if (!rUnsigned && val < 0)
5386 emitcode ("mov", "b,#0x%02x", -val);
5388 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5390 else /* ! literal */
5393 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5396 MOVA (aopGet (right, 0, FALSE, FALSE));
5397 lbl = newiTempLabel (NULL);
5398 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5399 emitcode ("cpl", "F0"); /* complement sign flag */
5400 emitcode ("cpl", "a"); /* 2's complement */
5401 emitcode ("inc", "a");
5403 emitcode ("mov", "b,a");
5407 if (AOP_TYPE(left) == AOP_LIT)
5409 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5411 if (!lUnsigned && val < 0)
5412 emitcode ("mov", "a,#0x%02x", -val);
5414 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5416 else /* ! literal */
5418 MOVA (aopGet (left, 0, FALSE, FALSE));
5422 lbl = newiTempLabel (NULL);
5423 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5424 emitcode ("cpl", "F0"); /* complement sign flag */
5425 emitcode ("cpl", "a"); /* 2's complement */
5426 emitcode ("inc", "a");
5431 /* now the division */
5432 emitcode ("div", "ab");
5434 if (runtimeSign || compiletimeSign)
5436 lbl = newiTempLabel (NULL);
5438 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5439 emitcode ("cpl", "a"); /* lsb 2's complement */
5440 emitcode ("inc", "a");
5443 accuse = aopPut (result, "a", 0);
5446 /* msb is 0x00 or 0xff depending on the sign */
5451 emitcode ("push", "acc");
5454 emitcode ("mov", "c,F0");
5455 emitcode ("subb", "a,acc");
5457 aopPut (result, "a", offset++);
5459 else /* compiletimeSign */
5461 if (aopPutUsesAcc (result, "#0xFF", offset))
5463 emitcode ("push", "acc");
5467 aopPut (result, "#0xff", offset++);
5473 aopPut (result, "a", 0);
5475 aopPut (result, zero, offset++);
5479 emitcode ("pop", "acc");
5483 /*-----------------------------------------------------------------*/
5484 /* genDiv - generates code for division */
5485 /*-----------------------------------------------------------------*/
5489 operand *left = IC_LEFT (ic);
5490 operand *right = IC_RIGHT (ic);
5491 operand *result = IC_RESULT (ic);
5493 D (emitcode (";", "genDiv"));
5495 /* assign the asmops */
5496 aopOp (left, ic, FALSE);
5497 aopOp (right, ic, FALSE);
5498 aopOp (result, ic, TRUE);
5500 /* special cases first */
5502 if (AOP_TYPE (left) == AOP_CRY &&
5503 AOP_TYPE (right) == AOP_CRY)
5505 genDivbits (left, right, result);
5509 /* if both are of size == 1 */
5510 if (AOP_SIZE (left) == 1 &&
5511 AOP_SIZE (right) == 1)
5513 genDivOneByte (left, right, result);
5517 /* should have been converted to function call */
5520 freeAsmop (result, NULL, ic, TRUE);
5521 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5522 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5525 /*-----------------------------------------------------------------*/
5526 /* genModbits :- modulus of bits */
5527 /*-----------------------------------------------------------------*/
5529 genModbits (operand * left,
5536 D (emitcode (";", "genModbits"));
5540 /* the result must be bit */
5541 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5542 l = aopGet (left, 0, FALSE, FALSE);
5546 emitcode ("div", "ab");
5547 emitcode ("mov", "a,b");
5548 emitcode ("rrc", "a");
5552 aopPut (result, "c", 0);
5555 /*-----------------------------------------------------------------*/
5556 /* genModOneByte : 8 bit modulus */
5557 /*-----------------------------------------------------------------*/
5559 genModOneByte (operand * left,
5563 bool lUnsigned, rUnsigned, pushedB;
5564 bool runtimeSign, compiletimeSign;
5568 D (emitcode (";", "genModOneByte"));
5570 size = AOP_SIZE (result) - 1;
5572 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5573 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5575 /* if right is a literal, check it for 2^n */
5576 if (AOP_TYPE(right) == AOP_LIT)
5578 unsigned char val = abs((int) operandLitValue(right));
5579 symbol *lbl2 = NULL;
5583 case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5592 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5593 "modulus of unsigned char by 2^n literal shouldn't be processed here");
5594 /* because iCode should have been changed to genAnd */
5595 /* see file "SDCCopt.c", function "convertToFcall()" */
5597 MOVA (aopGet (left, 0, FALSE, FALSE));
5598 emitcode ("mov", "c,acc.7");
5599 emitcode ("anl", "a,#0x%02x", val - 1);
5600 lbl = newiTempLabel (NULL);
5601 emitcode ("jz", "%05d$", (lbl->key + 100));
5602 emitcode ("jnc", "%05d$", (lbl->key + 100));
5603 emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5609 aopPut (result, "a", 0);
5611 aopPut (result, "#0xff", offs2++);
5612 lbl2 = newiTempLabel (NULL);
5613 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5616 aopPut (result, "a", 0);
5618 aopPut (result, zero, offset++);
5632 /* signed or unsigned */
5633 if (lUnsigned && rUnsigned)
5635 /* unsigned is easy */
5636 MOVB (aopGet (right, 0, FALSE, FALSE));
5637 MOVA (aopGet (left, 0, FALSE, FALSE));
5638 emitcode ("div", "ab");
5639 aopPut (result, "b", 0);
5641 aopPut (result, zero, offset++);
5647 /* signed is a little bit more difficult */
5649 /* now sign adjust for both left & right */
5651 /* modulus: sign of the right operand has no influence on the result! */
5652 if (AOP_TYPE(right) == AOP_LIT)
5654 signed char val = (char) operandLitValue(right);
5656 if (!rUnsigned && val < 0)
5657 emitcode ("mov", "b,#0x%02x", -val);
5659 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5661 else /* not literal */
5664 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5667 MOVA (aopGet (right, 0, FALSE, FALSE));
5668 lbl = newiTempLabel (NULL);
5669 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5670 emitcode ("cpl", "a"); /* 2's complement */
5671 emitcode ("inc", "a");
5673 emitcode ("mov", "b,a");
5677 /* let's see what's needed: */
5678 /* apply negative sign during runtime */
5679 runtimeSign = FALSE;
5680 /* negative sign from literals */
5681 compiletimeSign = FALSE;
5683 /* sign adjust left side */
5684 if (AOP_TYPE(left) == AOP_LIT)
5686 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5688 if (!lUnsigned && val < 0)
5690 compiletimeSign = TRUE; /* set sign flag */
5691 emitcode ("mov", "a,#0x%02x", -val);
5694 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5696 else /* ! literal */
5698 MOVA (aopGet (left, 0, FALSE, FALSE));
5703 emitcode ("clr", "F0"); /* clear sign flag */
5705 lbl = newiTempLabel (NULL);
5706 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5707 emitcode ("setb", "F0"); /* set sign flag */
5708 emitcode ("cpl", "a"); /* 2's complement */
5709 emitcode ("inc", "a");
5714 /* now the modulus */
5715 emitcode ("div", "ab");
5717 if (runtimeSign || compiletimeSign)
5719 emitcode ("mov", "a,b");
5720 lbl = newiTempLabel (NULL);
5722 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5723 emitcode ("cpl", "a"); /* 2's complement */
5724 emitcode ("inc", "a");
5727 aopPut (result, "a", 0);
5730 /* msb is 0x00 or 0xff depending on the sign */
5733 emitcode ("mov", "c,F0");
5734 emitcode ("subb", "a,acc");
5736 aopPut (result, "a", offset++);
5738 else /* compiletimeSign */
5740 aopPut (result, "#0xff", offset++);
5745 aopPut (result, "b", 0);
5747 aopPut (result, zero, offset++);
5753 /*-----------------------------------------------------------------*/
5754 /* genMod - generates code for division */
5755 /*-----------------------------------------------------------------*/
5759 operand *left = IC_LEFT (ic);
5760 operand *right = IC_RIGHT (ic);
5761 operand *result = IC_RESULT (ic);
5763 D (emitcode (";", "genMod"));
5765 /* assign the asmops */
5766 aopOp (left, ic, FALSE);
5767 aopOp (right, ic, FALSE);
5768 aopOp (result, ic, TRUE);
5770 /* special cases first */
5772 if (AOP_TYPE (left) == AOP_CRY &&
5773 AOP_TYPE (right) == AOP_CRY)
5775 genModbits (left, right, result);
5779 /* if both are of size == 1 */
5780 if (AOP_SIZE (left) == 1 &&
5781 AOP_SIZE (right) == 1)
5783 genModOneByte (left, right, result);
5787 /* should have been converted to function call */
5791 freeAsmop (result, NULL, ic, TRUE);
5792 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5793 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5796 /*-----------------------------------------------------------------*/
5797 /* genIfxJump :- will create a jump depending on the ifx */
5798 /*-----------------------------------------------------------------*/
5800 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5803 symbol *tlbl = newiTempLabel (NULL);
5806 D (emitcode (";", "genIfxJump"));
5808 /* if true label then we jump if condition
5812 jlbl = IC_TRUE (ic);
5813 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5814 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5818 /* false label is present */
5819 jlbl = IC_FALSE (ic);
5820 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5821 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5823 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5824 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5826 emitcode (inst, "%05d$", tlbl->key + 100);
5827 freeForBranchAsmop (result);
5828 freeForBranchAsmop (right);
5829 freeForBranchAsmop (left);
5830 emitcode ("ljmp", "%05d$", jlbl->key + 100);
5833 /* mark the icode as generated */
5837 /*-----------------------------------------------------------------*/
5838 /* genCmp :- greater or less than comparison */
5839 /*-----------------------------------------------------------------*/
5841 genCmp (operand * left, operand * right,
5842 operand * result, iCode * ifx, int sign, iCode *ic)
5844 int size, offset = 0;
5845 unsigned long lit = 0L;
5848 D (emitcode (";", "genCmp"));
5850 /* if left & right are bit variables */
5851 if (AOP_TYPE (left) == AOP_CRY &&
5852 AOP_TYPE (right) == AOP_CRY)
5854 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5855 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5859 /* subtract right from left if at the
5860 end the carry flag is set then we know that
5861 left is greater than right */
5862 size = max (AOP_SIZE (left), AOP_SIZE (right));
5864 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5865 if ((size == 1) && !sign &&
5866 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5868 symbol *lbl = newiTempLabel (NULL);
5869 emitcode ("cjne", "%s,%s,%05d$",
5870 aopGet (left, offset, FALSE, FALSE),
5871 aopGet (right, offset, FALSE, FALSE),
5877 if (AOP_TYPE (right) == AOP_LIT)
5879 lit = ulFromVal (AOP (right)->aopu.aop_lit);
5880 /* optimize if(x < 0) or if(x >= 0) */
5889 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5890 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5892 genIfxJump (ifx, "acc.7", left, right, result);
5893 freeAsmop (right, NULL, ic, TRUE);
5894 freeAsmop (left, NULL, ic, TRUE);
5900 emitcode ("rlc", "a");
5907 int bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5908 while (size && (bytelit == 0))
5911 bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5917 MOVA (aopGet (left, offset, FALSE, FALSE));
5918 if (sign && size == 0)
5920 emitcode ("xrl", "a,#0x80");
5921 emitcode ("subb", "a,#0x%02x",
5922 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5926 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5936 bool pushedB = FALSE;
5937 rightInB = aopGetUsesAcc(right, offset);
5941 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5943 MOVA (aopGet (left, offset, FALSE, FALSE));
5944 if (sign && size == 0)
5946 emitcode ("xrl", "a,#0x80");
5951 MOVB (aopGet (right, offset, FALSE, FALSE));
5953 emitcode ("xrl", "b,#0x80");
5954 emitcode ("subb", "a,b");
5959 emitcode ("subb", "a,b");
5961 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5971 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5972 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5973 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5979 /* if the result is used in the next
5980 ifx conditional branch then generate
5981 code a little differently */
5984 genIfxJump (ifx, "c", NULL, NULL, result);
5990 /* leave the result in acc */
5994 /*-----------------------------------------------------------------*/
5995 /* genCmpGt :- greater than comparison */
5996 /*-----------------------------------------------------------------*/
5998 genCmpGt (iCode * ic, iCode * ifx)
6000 operand *left, *right, *result;
6001 sym_link *letype, *retype;
6004 D (emitcode (";", "genCmpGt"));
6006 left = IC_LEFT (ic);
6007 right = IC_RIGHT (ic);
6008 result = IC_RESULT (ic);
6010 letype = getSpec (operandType (left));
6011 retype = getSpec (operandType (right));
6012 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
6013 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
6014 /* assign the asmops */
6015 aopOp (result, ic, TRUE);
6016 aopOp (left, ic, FALSE);
6017 aopOp (right, ic, FALSE);
6019 genCmp (right, left, result, ifx, sign, ic);
6021 freeAsmop (result, NULL, ic, TRUE);
6024 /*-----------------------------------------------------------------*/
6025 /* genCmpLt - less than comparisons */
6026 /*-----------------------------------------------------------------*/
6028 genCmpLt (iCode * ic, iCode * ifx)
6030 operand *left, *right, *result;
6031 sym_link *letype, *retype;
6034 D (emitcode (";", "genCmpLt"));
6036 left = IC_LEFT (ic);
6037 right = IC_RIGHT (ic);
6038 result = IC_RESULT (ic);
6040 letype = getSpec (operandType (left));
6041 retype = getSpec (operandType (right));
6042 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
6043 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
6044 /* assign the asmops */
6045 aopOp (result, ic, TRUE);
6046 aopOp (left, ic, FALSE);
6047 aopOp (right, ic, FALSE);
6049 genCmp (left, right, result, ifx, sign, ic);
6051 freeAsmop (result, NULL, ic, TRUE);
6054 /*-----------------------------------------------------------------*/
6055 /* gencjneshort - compare and jump if not equal */
6056 /*-----------------------------------------------------------------*/
6058 gencjneshort (operand * left, operand * right, symbol * lbl)
6060 int size = max (AOP_SIZE (left), AOP_SIZE (right));
6062 unsigned long lit = 0L;
6064 D (emitcode (";", "gencjneshort"));
6066 /* if the left side is a literal or
6067 if the right is in a pointer register and left
6069 if ((AOP_TYPE (left) == AOP_LIT) ||
6070 (AOP_TYPE (left) == AOP_IMMD) ||
6071 (AOP_TYPE (left) == AOP_DIR) ||
6072 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6079 if (AOP_TYPE (right) == AOP_LIT)
6080 lit = ulFromVal (AOP (right)->aopu.aop_lit);
6082 /* if the right side is a literal then anything goes */
6083 if (AOP_TYPE (right) == AOP_LIT &&
6084 AOP_TYPE (left) != AOP_DIR &&
6085 AOP_TYPE (left) != AOP_IMMD)
6089 emitcode ("cjne", "%s,%s,%05d$",
6090 aopGet (left, offset, FALSE, FALSE),
6091 aopGet (right, offset, FALSE, FALSE),
6097 /* if the right side is in a register or in direct space or
6098 if the left is a pointer register & right is not */
6099 else if (AOP_TYPE (right) == AOP_REG ||
6100 AOP_TYPE (right) == AOP_DIR ||
6101 AOP_TYPE (right) == AOP_LIT ||
6102 AOP_TYPE (right) == AOP_IMMD ||
6103 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6104 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6108 MOVA (aopGet (left, offset, FALSE, FALSE));
6109 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6110 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6111 emitcode ("jnz", "%05d$", lbl->key + 100);
6113 emitcode ("cjne", "a,%s,%05d$",
6114 aopGet (right, offset, FALSE, TRUE),
6121 /* right is a pointer reg need both a & b */
6124 //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
6125 wassertl(!BINUSE, "B was in use");
6126 MOVB (aopGet (left, offset, FALSE, FALSE));
6127 MOVA (aopGet (right, offset, FALSE, FALSE));
6128 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
6134 /*-----------------------------------------------------------------*/
6135 /* gencjne - compare and jump if not equal */
6136 /*-----------------------------------------------------------------*/
6138 gencjne (operand * left, operand * right, symbol * lbl, bool useCarry)
6140 symbol *tlbl = newiTempLabel (NULL);
6142 D (emitcode (";", "gencjne"));
6144 gencjneshort (left, right, lbl);
6150 emitcode ("sjmp", "%05d$", tlbl->key + 100);
6159 /*-----------------------------------------------------------------*/
6160 /* genCmpEq - generates code for equal to */
6161 /*-----------------------------------------------------------------*/
6163 genCmpEq (iCode * ic, iCode * ifx)
6165 bool swappedLR = FALSE;
6166 operand *left, *right, *result;
6168 D (emitcode (";", "genCmpEq"));
6170 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6171 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6172 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6174 /* if literal, literal on the right or
6175 if the right is in a pointer register and left
6177 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6178 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6180 operand *t = IC_RIGHT (ic);
6181 IC_RIGHT (ic) = IC_LEFT (ic);
6186 if (ifx && !AOP_SIZE (result))
6189 /* if they are both bit variables */
6190 if (AOP_TYPE (left) == AOP_CRY &&
6191 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6193 if (AOP_TYPE (right) == AOP_LIT)
6195 unsigned long lit = ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6198 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6199 emitcode ("cpl", "c");
6203 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6207 emitcode ("clr", "c");
6209 /* AOP_TYPE(right) == AOP_CRY */
6213 symbol *lbl = newiTempLabel (NULL);
6214 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6215 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6216 emitcode ("cpl", "c");
6219 /* if true label then we jump if condition
6221 tlbl = newiTempLabel (NULL);
6224 emitcode ("jnc", "%05d$", tlbl->key + 100);
6225 freeForBranchAsmop (result);
6226 freeForBranchAsmop (right);
6227 freeForBranchAsmop (left);
6228 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6232 emitcode ("jc", "%05d$", tlbl->key + 100);
6233 freeForBranchAsmop (result);
6234 freeForBranchAsmop (right);
6235 freeForBranchAsmop (left);
6236 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6242 tlbl = newiTempLabel (NULL);
6243 gencjneshort (left, right, tlbl);
6246 freeForBranchAsmop (result);
6247 freeForBranchAsmop (right);
6248 freeForBranchAsmop (left);
6249 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6254 symbol *lbl = newiTempLabel (NULL);
6255 emitcode ("sjmp", "%05d$", lbl->key + 100);
6257 freeForBranchAsmop (result);
6258 freeForBranchAsmop (right);
6259 freeForBranchAsmop (left);
6260 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6264 /* mark the icode as generated */
6269 /* if they are both bit variables */
6270 if (AOP_TYPE (left) == AOP_CRY &&
6271 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6273 if (AOP_TYPE (right) == AOP_LIT)
6275 unsigned long lit = ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6278 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6279 emitcode ("cpl", "c");
6283 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6287 emitcode ("clr", "c");
6289 /* AOP_TYPE(right) == AOP_CRY */
6293 symbol *lbl = newiTempLabel (NULL);
6294 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6295 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6296 emitcode ("cpl", "c");
6300 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6307 genIfxJump (ifx, "c", left, right, result);
6310 /* if the result is used in an arithmetic operation
6311 then put the result in place */
6316 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6318 gencjne (left, right, newiTempLabel (NULL), TRUE);
6319 aopPut (result, "c", 0);
6322 gencjne (left, right, newiTempLabel (NULL), FALSE);
6325 genIfxJump (ifx, "a", left, right, result);
6328 /* if the result is used in an arithmetic operation
6329 then put the result in place */
6330 if (AOP_TYPE (result) != AOP_CRY)
6332 /* leave the result in acc */
6336 freeAsmop (result, NULL, ic, TRUE);
6339 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6340 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6344 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6345 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6349 /*-----------------------------------------------------------------*/
6350 /* ifxForOp - returns the icode containing the ifx for operand */
6351 /*-----------------------------------------------------------------*/
6353 ifxForOp (operand * op, iCode * ic)
6355 /* if true symbol then needs to be assigned */
6356 if (IS_TRUE_SYMOP (op))
6359 /* if this has register type condition and
6360 the next instruction is ifx with the same operand
6361 and live to of the operand is upto the ifx only then */
6363 ic->next->op == IFX &&
6364 IC_COND (ic->next)->key == op->key &&
6365 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6371 /*-----------------------------------------------------------------*/
6372 /* hasInc - operand is incremented before any other use */
6373 /*-----------------------------------------------------------------*/
6375 hasInc (operand *op, iCode *ic, int osize)
6377 sym_link *type = operandType(op);
6378 sym_link *retype = getSpec (type);
6379 iCode *lic = ic->next;
6382 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6383 if (!IS_SYMOP(op)) return NULL;
6385 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6386 if (IS_AGGREGATE(type->next)) return NULL;
6387 if (osize != (isize = getSize(type->next))) return NULL;
6390 /* if operand of the form op = op + <sizeof *op> */
6391 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6392 isOperandEqual(IC_RESULT(lic),op) &&
6393 isOperandLiteral(IC_RIGHT(lic)) &&
6394 operandLitValue(IC_RIGHT(lic)) == isize) {
6397 /* if the operand used or deffed */
6398 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6401 /* if GOTO or IFX */
6402 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6408 /*-----------------------------------------------------------------*/
6409 /* genAndOp - for && operation */
6410 /*-----------------------------------------------------------------*/
6412 genAndOp (iCode * ic)
6414 operand *left, *right, *result;
6417 D (emitcode (";", "genAndOp"));
6419 /* note here that && operations that are in an
6420 if statement are taken away by backPatchLabels
6421 only those used in arthmetic operations remain */
6422 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6423 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6424 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6426 /* if both are bit variables */
6427 if (AOP_TYPE (left) == AOP_CRY &&
6428 AOP_TYPE (right) == AOP_CRY)
6430 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6431 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6436 tlbl = newiTempLabel (NULL);
6438 emitcode ("jz", "%05d$", tlbl->key + 100);
6444 freeAsmop (result, NULL, ic, TRUE);
6445 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6446 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6450 /*-----------------------------------------------------------------*/
6451 /* genOrOp - for || operation */
6452 /*-----------------------------------------------------------------*/
6454 genOrOp (iCode * ic)
6456 operand *left, *right, *result;
6459 D (emitcode (";", "genOrOp"));
6461 /* note here that || operations that are in an
6462 if statement are taken away by backPatchLabels
6463 only those used in arthmetic operations remain */
6464 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6465 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6466 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6468 /* if both are bit variables */
6469 if (AOP_TYPE (left) == AOP_CRY &&
6470 AOP_TYPE (right) == AOP_CRY)
6472 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6473 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6478 tlbl = newiTempLabel (NULL);
6480 emitcode ("jnz", "%05d$", tlbl->key + 100);
6486 freeAsmop (result, NULL, ic, TRUE);
6487 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6488 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6491 /*-----------------------------------------------------------------*/
6492 /* isLiteralBit - test if lit == 2^n */
6493 /*-----------------------------------------------------------------*/
6495 isLiteralBit (unsigned long lit)
6497 unsigned long pw[32] =
6498 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6499 0x100L, 0x200L, 0x400L, 0x800L,
6500 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6501 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6502 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6503 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6504 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6507 for (idx = 0; idx < 32; idx++)
6513 /*-----------------------------------------------------------------*/
6514 /* continueIfTrue - */
6515 /*-----------------------------------------------------------------*/
6517 continueIfTrue (iCode * ic)
6520 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6524 /*-----------------------------------------------------------------*/
6526 /*-----------------------------------------------------------------*/
6528 jumpIfTrue (iCode * ic)
6531 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6535 /*-----------------------------------------------------------------*/
6536 /* jmpTrueOrFalse - */
6537 /*-----------------------------------------------------------------*/
6539 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6541 // ugly but optimized by peephole
6544 symbol *nlbl = newiTempLabel (NULL);
6545 emitcode ("sjmp", "%05d$", nlbl->key + 100);
6547 freeForBranchAsmop (result);
6548 freeForBranchAsmop (right);
6549 freeForBranchAsmop (left);
6550 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6555 freeForBranchAsmop (result);
6556 freeForBranchAsmop (right);
6557 freeForBranchAsmop (left);
6558 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6564 /*-----------------------------------------------------------------*/
6565 /* genAnd - code for and */
6566 /*-----------------------------------------------------------------*/
6568 genAnd (iCode * ic, iCode * ifx)
6570 operand *left, *right, *result;
6571 int size, offset = 0;
6572 unsigned long lit = 0L;
6576 D (emitcode (";", "genAnd"));
6578 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6579 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6580 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6583 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
6585 AOP_TYPE (left), AOP_TYPE (right));
6586 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
6588 AOP_SIZE (left), AOP_SIZE (right));
6591 /* if left is a literal & right is not then exchange them */
6592 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6593 AOP_NEEDSACC (left))
6595 operand *tmp = right;
6600 /* if result = right then exchange left and right */
6601 if (sameRegs (AOP (result), AOP (right)))
6603 operand *tmp = right;
6608 /* if right is bit then exchange them */
6609 if (AOP_TYPE (right) == AOP_CRY &&
6610 AOP_TYPE (left) != AOP_CRY)
6612 operand *tmp = right;
6616 if (AOP_TYPE (right) == AOP_LIT)
6617 lit = ulFromVal (AOP (right)->aopu.aop_lit);
6619 size = AOP_SIZE (result);
6622 // result = bit & yy;
6623 if (AOP_TYPE (left) == AOP_CRY)
6625 // c = bit & literal;
6626 if (AOP_TYPE (right) == AOP_LIT)
6630 if (size && sameRegs (AOP (result), AOP (left)))
6633 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6638 if (size && (AOP_TYPE (result) == AOP_CRY))
6640 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6643 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6648 emitcode ("clr", "c");
6653 if (AOP_TYPE (right) == AOP_CRY)
6656 if (IS_OP_ACCUSE (left))
6658 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6662 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6663 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6669 MOVA (aopGet (right, 0, FALSE, FALSE));
6671 emitcode ("rrc", "a");
6672 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6680 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6681 genIfxJump (ifx, "c", left, right, result);
6685 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6686 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6687 if ((AOP_TYPE (right) == AOP_LIT) &&
6688 (AOP_TYPE (result) == AOP_CRY) &&
6689 (AOP_TYPE (left) != AOP_CRY))
6691 int posbit = isLiteralBit (lit);
6696 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6700 switch (posbit & 0x07)
6702 case 0: emitcode ("rrc", "a");
6704 case 7: emitcode ("rlc", "a");
6706 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6715 SNPRINTF (buffer, sizeof(buffer),
6716 "acc.%d", posbit & 0x07);
6717 genIfxJump (ifx, buffer, left, right, result);
6720 {// what is this case? just found it in ds390/gen.c
6721 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6728 symbol *tlbl = newiTempLabel (NULL);
6729 int sizel = AOP_SIZE (left);
6731 emitcode ("setb", "c");
6734 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6736 MOVA (aopGet (left, offset, FALSE, FALSE));
6738 if ((posbit = isLiteralBit (bytelit)) != 0)
6739 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6742 if (bytelit != 0x0FFL)
6743 emitcode ("anl", "a,%s",
6744 aopGet (right, offset, FALSE, TRUE));
6745 emitcode ("jnz", "%05d$", tlbl->key + 100);
6750 // bit = left & literal
6753 emitcode ("clr", "c");
6756 // if(left & literal)
6760 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6770 /* if left is same as result */
6771 if (sameRegs (AOP (result), AOP (left)))
6773 for (; size--; offset++)
6775 if (AOP_TYPE (right) == AOP_LIT)
6777 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6778 if (bytelit == 0x0FF)
6780 /* dummy read of volatile operand */
6781 if (isOperandVolatile (left, FALSE))
6782 MOVA (aopGet (left, offset, FALSE, FALSE));
6786 else if (bytelit == 0)
6788 aopPut (result, zero, offset);
6790 else if (IS_AOP_PREG (result))
6792 MOVA (aopGet (left, offset, FALSE, TRUE));
6793 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6794 aopPut (result, "a", offset);
6797 emitcode ("anl", "%s,%s",
6798 aopGet (left, offset, FALSE, TRUE),
6799 aopGet (right, offset, FALSE, FALSE));
6803 if (AOP_TYPE (left) == AOP_ACC)
6806 emitcode("mov", "a,b");
6807 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6809 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6811 MOVB (aopGet (left, offset, FALSE, FALSE));
6812 MOVA (aopGet (right, offset, FALSE, FALSE));
6813 emitcode ("anl", "a,b");
6814 aopPut (result, "a", offset);
6816 else if (aopGetUsesAcc (left, offset))
6818 MOVA (aopGet (left, offset, FALSE, FALSE));
6819 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6820 aopPut (result, "a", offset);
6824 MOVA (aopGet (right, offset, FALSE, FALSE));
6825 if (IS_AOP_PREG (result))
6827 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6828 aopPut (result, "a", offset);
6831 emitcode ("anl", "%s,a", aopGet (left, offset, FALSE, TRUE));
6838 // left & result in different registers
6839 if (AOP_TYPE (result) == AOP_CRY)
6842 // if(size), result in bit
6843 // if(!size && ifx), conditional oper: if(left & right)
6844 symbol *tlbl = newiTempLabel (NULL);
6845 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6847 emitcode ("setb", "c");
6850 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6851 && AOP_TYPE(left)==AOP_ACC)
6854 emitcode("mov", "a,b");
6855 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6857 else if (AOP_TYPE(left)==AOP_ACC)
6861 bool pushedB = pushB ();
6862 emitcode("mov", "b,a");
6863 MOVA (aopGet (right, offset, FALSE, FALSE));
6864 emitcode("anl", "a,b");
6869 MOVA (aopGet (right, offset, FALSE, FALSE));
6870 emitcode("anl", "a,b");
6873 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6875 MOVB (aopGet (left, offset, FALSE, FALSE));
6876 MOVA (aopGet (right, offset, FALSE, FALSE));
6877 emitcode ("anl", "a,b");
6879 else if (aopGetUsesAcc (left, offset))
6881 MOVA (aopGet (left, offset, FALSE, FALSE));
6882 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6886 MOVA (aopGet (right, offset, FALSE, FALSE));
6887 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6890 emitcode ("jnz", "%05d$", tlbl->key + 100);
6900 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6906 for (; (size--); offset++)
6909 // result = left & right
6910 if (AOP_TYPE (right) == AOP_LIT)
6912 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6913 if (bytelit == 0x0FF)
6916 aopGet (left, offset, FALSE, FALSE),
6920 else if (bytelit == 0)
6922 /* dummy read of volatile operand */
6923 if (isOperandVolatile (left, FALSE))
6924 MOVA (aopGet (left, offset, FALSE, FALSE));
6925 aopPut (result, zero, offset);
6928 else if (AOP_TYPE (left) == AOP_ACC)
6932 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6933 aopPut (result, "a", offset);
6938 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6939 aopPut (result, "b", offset);
6944 // faster than result <- left, anl result,right
6945 // and better if result is SFR
6946 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6947 && AOP_TYPE(left)==AOP_ACC)
6950 emitcode("mov", "a,b");
6951 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6953 else if (AOP_TYPE(left)==AOP_ACC)
6957 bool pushedB = pushB ();
6958 emitcode("mov", "b,a");
6959 MOVA (aopGet (right, offset, FALSE, FALSE));
6960 emitcode("anl", "a,b");
6965 MOVA (aopGet (right, offset, FALSE, FALSE));
6966 emitcode("anl", "a,b");
6969 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6971 MOVB (aopGet (left, offset, FALSE, FALSE));
6972 MOVA (aopGet (right, offset, FALSE, FALSE));
6973 emitcode ("anl", "a,b");
6975 else if (aopGetUsesAcc (left, offset))
6977 MOVA (aopGet (left, offset, FALSE, FALSE));
6978 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6982 MOVA (aopGet (right, offset, FALSE, FALSE));
6983 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6985 aopPut (result, "a", offset);
6991 freeAsmop (result, NULL, ic, TRUE);
6992 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6993 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6996 /*-----------------------------------------------------------------*/
6997 /* genOr - code for or */
6998 /*-----------------------------------------------------------------*/
7000 genOr (iCode * ic, iCode * ifx)
7002 operand *left, *right, *result;
7003 int size, offset = 0;
7004 unsigned long lit = 0L;
7007 D (emitcode (";", "genOr"));
7009 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7010 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7011 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7014 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
7016 AOP_TYPE (left), AOP_TYPE (right));
7017 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
7019 AOP_SIZE (left), AOP_SIZE (right));
7022 /* if left is a literal & right is not then exchange them */
7023 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7024 AOP_NEEDSACC (left))
7026 operand *tmp = right;
7031 /* if result = right then exchange them */
7032 if (sameRegs (AOP (result), AOP (right)))
7034 operand *tmp = right;
7039 /* if right is bit then exchange them */
7040 if (AOP_TYPE (right) == AOP_CRY &&
7041 AOP_TYPE (left) != AOP_CRY)
7043 operand *tmp = right;
7047 if (AOP_TYPE (right) == AOP_LIT)
7048 lit = ulFromVal (AOP (right)->aopu.aop_lit);
7050 size = AOP_SIZE (result);
7054 if (AOP_TYPE (left) == AOP_CRY)
7056 if (AOP_TYPE (right) == AOP_LIT)
7058 // c = bit | literal;
7061 // lit != 0 => result = 1
7062 if (AOP_TYPE (result) == AOP_CRY)
7065 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7067 continueIfTrue (ifx);
7070 emitcode ("setb", "c");
7074 // lit == 0 => result = left
7075 if (size && sameRegs (AOP (result), AOP (left)))
7077 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7082 if (AOP_TYPE (right) == AOP_CRY)
7085 if (IS_OP_ACCUSE (left))
7087 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
7091 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7092 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7098 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7100 symbol *tlbl = newiTempLabel (NULL);
7101 emitcode ("jb", "%s,%05d$",
7102 AOP (left)->aopu.aop_dir, tlbl->key + 100);
7104 emitcode ("jnz", "%05d$", tlbl->key + 100);
7105 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7111 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7120 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7121 genIfxJump (ifx, "c", left, right, result);
7125 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7126 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7127 if ((AOP_TYPE (right) == AOP_LIT) &&
7128 (AOP_TYPE (result) == AOP_CRY) &&
7129 (AOP_TYPE (left) != AOP_CRY))
7135 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7137 continueIfTrue (ifx);
7142 // lit = 0, result = boolean(left)
7144 emitcode ("setb", "c");
7148 symbol *tlbl = newiTempLabel (NULL);
7149 emitcode ("jnz", "%05d$", tlbl->key + 100);
7155 genIfxJump (ifx, "a", left, right, result);
7163 /* if left is same as result */
7164 if (sameRegs (AOP (result), AOP (left)))
7166 for (; size--; offset++)
7168 if (AOP_TYPE (right) == AOP_LIT)
7170 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7173 /* dummy read of volatile operand */
7174 if (isOperandVolatile (left, FALSE))
7175 MOVA (aopGet (left, offset, FALSE, FALSE));
7179 else if (bytelit == 0x0FF)
7181 aopPut (result, "#0xFF", offset);
7183 else if (IS_AOP_PREG (left))
7185 MOVA (aopGet (left, offset, FALSE, TRUE));
7186 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7187 aopPut (result, "a", offset);
7191 emitcode ("orl", "%s,%s",
7192 aopGet (left, offset, FALSE, TRUE),
7193 aopGet (right, offset, FALSE, FALSE));
7198 if (AOP_TYPE (left) == AOP_ACC)
7201 emitcode("mov", "a,b");
7202 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7204 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7206 MOVB (aopGet (left, offset, FALSE, FALSE));
7207 MOVA (aopGet (right, offset, FALSE, FALSE));
7208 emitcode ("orl", "a,b");
7209 aopPut (result, "a", offset);
7211 else if (aopGetUsesAcc (left, offset))
7213 MOVA (aopGet (left, offset, FALSE, FALSE));
7214 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7215 aopPut (result, "a", offset);
7219 MOVA (aopGet (right, offset, FALSE, FALSE));
7220 if (IS_AOP_PREG (left))
7222 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7223 aopPut (result, "a", offset);
7227 emitcode ("orl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7235 // left & result in different registers
7236 if (AOP_TYPE (result) == AOP_CRY)
7239 // if(size), result in bit
7240 // if(!size && ifx), conditional oper: if(left | right)
7241 symbol *tlbl = newiTempLabel (NULL);
7242 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7244 emitcode ("setb", "c");
7247 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7248 && AOP_TYPE(left)==AOP_ACC)
7251 emitcode("mov", "a,b");
7252 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7254 else if (AOP_TYPE(left)==AOP_ACC)
7258 bool pushedB = pushB ();
7259 emitcode("mov", "b,a");
7260 MOVA (aopGet (right, offset, FALSE, FALSE));
7261 emitcode("orl", "a,b");
7266 MOVA (aopGet (right, offset, FALSE, FALSE));
7267 emitcode("orl", "a,b");
7270 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7272 MOVB (aopGet (left, offset, FALSE, FALSE));
7273 MOVA (aopGet (right, offset, FALSE, FALSE));
7274 emitcode ("orl", "a,b");
7276 else if (aopGetUsesAcc (left, offset))
7278 MOVA (aopGet (left, offset, FALSE, FALSE));
7279 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7283 MOVA (aopGet (right, offset, FALSE, FALSE));
7284 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7287 emitcode ("jnz", "%05d$", tlbl->key + 100);
7297 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7303 for (; (size--); offset++)
7306 // result = left | right
7307 if (AOP_TYPE (right) == AOP_LIT)
7309 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7313 aopGet (left, offset, FALSE, FALSE),
7317 else if (bytelit == 0x0FF)
7319 /* dummy read of volatile operand */
7320 if (isOperandVolatile (left, FALSE))
7321 MOVA (aopGet (left, offset, FALSE, FALSE));
7322 aopPut (result, "#0xFF", offset);
7326 // faster than result <- left, orl result,right
7327 // and better if result is SFR
7328 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7329 && AOP_TYPE(left)==AOP_ACC)
7332 emitcode("mov", "a,b");
7333 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7335 else if (AOP_TYPE(left)==AOP_ACC)
7339 bool pushedB = pushB ();
7340 emitcode("mov", "b,a");
7341 MOVA (aopGet (right, offset, FALSE, FALSE));
7342 emitcode("orl", "a,b");
7347 MOVA (aopGet (right, offset, FALSE, FALSE));
7348 emitcode("orl", "a,b");
7351 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7353 MOVB (aopGet (left, offset, FALSE, FALSE));
7354 MOVA (aopGet (right, offset, FALSE, FALSE));
7355 emitcode ("orl", "a,b");
7357 else if (aopGetUsesAcc (left, offset))
7359 MOVA (aopGet (left, offset, FALSE, FALSE));
7360 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7364 MOVA (aopGet (right, offset, FALSE, FALSE));
7365 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7367 aopPut (result, "a", offset);
7373 freeAsmop (result, NULL, ic, TRUE);
7374 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7375 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7378 /*-----------------------------------------------------------------*/
7379 /* genXor - code for xclusive or */
7380 /*-----------------------------------------------------------------*/
7382 genXor (iCode * ic, iCode * ifx)
7384 operand *left, *right, *result;
7385 int size, offset = 0;
7386 unsigned long lit = 0L;
7389 D (emitcode (";", "genXor"));
7391 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7392 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7393 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7396 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
7398 AOP_TYPE (left), AOP_TYPE (right));
7399 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
7401 AOP_SIZE (left), AOP_SIZE (right));
7404 /* if left is a literal & right is not ||
7405 if left needs acc & right does not */
7406 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7407 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7409 operand *tmp = right;
7414 /* if result = right then exchange them */
7415 if (sameRegs (AOP (result), AOP (right)))
7417 operand *tmp = right;
7422 /* if right is bit then exchange them */
7423 if (AOP_TYPE (right) == AOP_CRY &&
7424 AOP_TYPE (left) != AOP_CRY)
7426 operand *tmp = right;
7431 if (AOP_TYPE (right) == AOP_LIT)
7432 lit = ulFromVal (AOP (right)->aopu.aop_lit);
7434 size = AOP_SIZE (result);
7438 if (AOP_TYPE (left) == AOP_CRY)
7440 if (AOP_TYPE (right) == AOP_LIT)
7442 // c = bit & literal;
7445 // lit>>1 != 0 => result = 1
7446 if (AOP_TYPE (result) == AOP_CRY)
7449 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7451 continueIfTrue (ifx);
7454 emitcode ("setb", "c");
7461 // lit == 0, result = left
7462 if (size && sameRegs (AOP (result), AOP (left)))
7464 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7468 // lit == 1, result = not(left)
7469 if (size && sameRegs (AOP (result), AOP (left)))
7471 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7476 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7477 emitcode ("cpl", "c");
7485 symbol *tlbl = newiTempLabel (NULL);
7486 if (AOP_TYPE (right) == AOP_CRY)
7489 if (IS_OP_ACCUSE (left))
7490 {// left already is in the carry
7491 operand *tmp = right;
7505 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7506 emitcode ("cpl", "c");
7514 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7515 genIfxJump (ifx, "c", left, right, result);
7519 /* if left is same as result */
7520 if (sameRegs (AOP (result), AOP (left)))
7522 for (; size--; offset++)
7524 if (AOP_TYPE (right) == AOP_LIT)
7526 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7529 /* dummy read of volatile operand */
7530 if (isOperandVolatile (left, FALSE))
7531 MOVA (aopGet (left, offset, FALSE, FALSE));
7535 else if (IS_AOP_PREG (left))
7537 MOVA (aopGet (left, offset, FALSE, TRUE));
7538 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7539 aopPut (result, "a", offset);
7543 emitcode ("xrl", "%s,%s",
7544 aopGet (left, offset, FALSE, TRUE),
7545 aopGet (right, offset, FALSE, FALSE));
7550 if (AOP_TYPE (left) == AOP_ACC)
7553 emitcode("mov", "a,b");
7554 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7556 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7558 MOVB (aopGet (left, offset, FALSE, FALSE));
7559 MOVA (aopGet (right, offset, FALSE, FALSE));
7560 emitcode ("xrl", "a,b");
7561 aopPut (result, "a", offset);
7563 else if (aopGetUsesAcc (left, offset))
7565 MOVA (aopGet (left, offset, FALSE, FALSE));
7566 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7567 aopPut (result, "a", offset);
7571 MOVA (aopGet (right, offset, FALSE, FALSE));
7572 if (IS_AOP_PREG (left))
7574 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7575 aopPut (result, "a", offset);
7578 emitcode ("xrl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7585 // left & result in different registers
7586 if (AOP_TYPE (result) == AOP_CRY)
7589 // if(size), result in bit
7590 // if(!size && ifx), conditional oper: if(left ^ right)
7591 symbol *tlbl = newiTempLabel (NULL);
7592 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7595 emitcode ("setb", "c");
7598 if ((AOP_TYPE (right) == AOP_LIT) &&
7599 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7601 MOVA (aopGet (left, offset, FALSE, FALSE));
7603 else if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7604 && AOP_TYPE(left)==AOP_ACC)
7607 emitcode("mov", "a,b");
7608 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7610 else if (AOP_TYPE(left)==AOP_ACC)
7614 bool pushedB = pushB ();
7615 emitcode("mov", "b,a");
7616 MOVA (aopGet (right, offset, FALSE, FALSE));
7617 emitcode("xrl", "a,b");
7622 MOVA (aopGet (right, offset, FALSE, FALSE));
7623 emitcode("xrl", "a,b");
7626 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7628 MOVB (aopGet (left, offset, FALSE, FALSE));
7629 MOVA (aopGet (right, offset, FALSE, FALSE));
7630 emitcode ("xrl", "a,b");
7632 else if (aopGetUsesAcc (left, offset))
7634 MOVA (aopGet (left, offset, FALSE, FALSE));
7635 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7639 MOVA (aopGet (right, offset, FALSE, FALSE));
7640 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7643 emitcode ("jnz", "%05d$", tlbl->key + 100);
7653 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7657 for (; (size--); offset++)
7660 // result = left ^ right
7661 if (AOP_TYPE (right) == AOP_LIT)
7663 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7667 aopGet (left, offset, FALSE, FALSE),
7672 // faster than result <- left, xrl result,right
7673 // and better if result is SFR
7674 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7675 && AOP_TYPE(left)==AOP_ACC)
7678 emitcode("mov", "a,b");
7679 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7681 else if (AOP_TYPE(left)==AOP_ACC)
7685 bool pushedB = pushB ();
7686 emitcode("mov", "b,a");
7687 MOVA (aopGet (right, offset, FALSE, FALSE));
7688 emitcode("xrl", "a,b");
7693 MOVA (aopGet (right, offset, FALSE, FALSE));
7694 emitcode("xrl", "a,b");
7697 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7699 MOVB (aopGet (left, offset, FALSE, FALSE));
7700 MOVA (aopGet (right, offset, FALSE, FALSE));
7701 emitcode ("xrl", "a,b");
7703 else if (aopGetUsesAcc (left, offset))
7705 MOVA (aopGet (left, offset, FALSE, FALSE));
7706 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7710 MOVA (aopGet (right, offset, FALSE, FALSE));
7711 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7713 aopPut (result, "a", offset);
7719 freeAsmop (result, NULL, ic, TRUE);
7720 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7721 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7724 /*-----------------------------------------------------------------*/
7725 /* genInline - write the inline code out */
7726 /*-----------------------------------------------------------------*/
7728 genInline (iCode * ic)
7730 char *buffer, *bp, *bp1;
7731 bool inComment = FALSE;
7733 D (emitcode (";", "genInline"));
7735 _G.inLine += (!options.asmpeep);
7737 buffer = bp = bp1 = Safe_strdup (IC_INLINE (ic));
7739 /* emit each line as a code */
7757 /* Add \n for labels, not dirs such as c:\mydir */
7758 if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
7776 _G.inLine -= (!options.asmpeep);
7779 /*-----------------------------------------------------------------*/
7780 /* genRRC - rotate right with carry */
7781 /*-----------------------------------------------------------------*/
7785 operand *left, *result;
7789 D (emitcode (";", "genRRC"));
7791 /* rotate right with carry */
7792 left = IC_LEFT (ic);
7793 result = IC_RESULT (ic);
7794 aopOp (left, ic, FALSE);
7795 aopOp (result, ic, FALSE);
7797 /* move it to the result */
7798 size = AOP_SIZE (result);
7800 if (size == 1) { /* special case for 1 byte */
7801 l = aopGet (left, offset, FALSE, FALSE);
7803 emitcode ("rr", "a");
7806 /* no need to clear carry, bit7 will be written later */
7809 l = aopGet (left, offset, FALSE, FALSE);
7811 emitcode ("rrc", "a");
7812 if (AOP_SIZE (result) > 1)
7813 aopPut (result, "a", offset--);
7815 /* now we need to put the carry into the
7816 highest order byte of the result */
7817 if (AOP_SIZE (result) > 1)
7819 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7822 emitcode ("mov", "acc.7,c");
7824 aopPut (result, "a", AOP_SIZE (result) - 1);
7825 freeAsmop (result, NULL, ic, TRUE);
7826 freeAsmop (left, NULL, ic, TRUE);
7829 /*-----------------------------------------------------------------*/
7830 /* genRLC - generate code for rotate left with carry */
7831 /*-----------------------------------------------------------------*/
7835 operand *left, *result;
7839 D (emitcode (";", "genRLC"));
7841 /* rotate right with carry */
7842 left = IC_LEFT (ic);
7843 result = IC_RESULT (ic);
7844 aopOp (left, ic, FALSE);
7845 aopOp (result, ic, FALSE);
7847 /* move it to the result */
7848 size = AOP_SIZE (result);
7852 l = aopGet (left, offset, FALSE, FALSE);
7854 if (size == 0) { /* special case for 1 byte */
7858 emitcode("rlc","a"); /* bit0 will be written later */
7859 if (AOP_SIZE (result) > 1)
7861 aopPut (result, "a", offset++);
7866 l = aopGet (left, offset, FALSE, FALSE);
7868 emitcode ("rlc", "a");
7869 if (AOP_SIZE (result) > 1)
7870 aopPut (result, "a", offset++);
7873 /* now we need to put the carry into the
7874 highest order byte of the result */
7875 if (AOP_SIZE (result) > 1)
7877 l = aopGet (result, 0, FALSE, FALSE);
7880 emitcode ("mov", "acc.0,c");
7882 aopPut (result, "a", 0);
7883 freeAsmop (result, NULL, ic, TRUE);
7884 freeAsmop (left, NULL, ic, TRUE);
7887 /*-----------------------------------------------------------------*/
7888 /* genGetHbit - generates code get highest order bit */
7889 /*-----------------------------------------------------------------*/
7891 genGetHbit (iCode * ic)
7893 operand *left, *result;
7895 D (emitcode (";", "genGetHbit"));
7897 left = IC_LEFT (ic);
7898 result = IC_RESULT (ic);
7899 aopOp (left, ic, FALSE);
7900 aopOp (result, ic, FALSE);
7902 /* get the highest order byte into a */
7903 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7904 if (AOP_TYPE (result) == AOP_CRY)
7906 emitcode ("rlc", "a");
7911 emitcode ("rl", "a");
7912 emitcode ("anl", "a,#0x01");
7916 freeAsmop (result, NULL, ic, TRUE);
7917 freeAsmop (left, NULL, ic, TRUE);
7920 /*-----------------------------------------------------------------*/
7921 /* genGetAbit - generates code get a single bit */
7922 /*-----------------------------------------------------------------*/
7924 genGetAbit (iCode * ic)
7926 operand *left, *right, *result;
7929 D (emitcode (";", "genGetAbit"));
7931 left = IC_LEFT (ic);
7932 right = IC_RIGHT (ic);
7933 result = IC_RESULT (ic);
7934 aopOp (left, ic, FALSE);
7935 aopOp (right, ic, FALSE);
7936 aopOp (result, ic, FALSE);
7938 shCount = (int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7940 /* get the needed byte into a */
7941 MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7943 if (AOP_TYPE (result) == AOP_CRY)
7946 emitcode ("rlc", "a");
7947 else if ((shCount) == 0)
7948 emitcode ("rrc", "a");
7950 emitcode ("mov", "c,acc[%d]", shCount);
7958 emitcode ("rr", "a");
7961 emitcode ("rr", "a");
7964 emitcode ("anl", "a,#0x01");
7968 emitcode ("mov", "c,acc[%d]", shCount);
7969 emitcode ("clr", "a");
7970 emitcode ("rlc", "a");
7973 emitcode ("swap", "a");
7974 emitcode ("anl", "a,#0x01");
7977 emitcode ("rl", "a");
7980 emitcode ("rl", "a");
7981 emitcode ("anl", "a,#0x01");
7987 freeAsmop (result, NULL, ic, TRUE);
7988 freeAsmop (right, NULL, ic, TRUE);
7989 freeAsmop (left, NULL, ic, TRUE);
7992 /*-----------------------------------------------------------------*/
7993 /* genGetByte - generates code get a single byte */
7994 /*-----------------------------------------------------------------*/
7996 genGetByte (iCode * ic)
7998 operand *left, *right, *result;
8001 D (emitcode (";", "genGetByte"));
8003 left = IC_LEFT (ic);
8004 right = IC_RIGHT (ic);
8005 result = IC_RESULT (ic);
8006 aopOp (left, ic, FALSE);
8007 aopOp (right, ic, FALSE);
8008 aopOp (result, ic, FALSE);
8010 offset = (int) ulFromVal (AOP (right)->aopu.aop_lit) / 8;
8012 aopGet (left, offset, FALSE, FALSE),
8015 freeAsmop (result, NULL, ic, TRUE);
8016 freeAsmop (right, NULL, ic, TRUE);
8017 freeAsmop (left, NULL, ic, TRUE);
8020 /*-----------------------------------------------------------------*/
8021 /* genGetWord - generates code get two bytes */
8022 /*-----------------------------------------------------------------*/
8024 genGetWord (iCode * ic)
8026 operand *left, *right, *result;
8029 D (emitcode (";", "genGetWord"));
8031 left = IC_LEFT (ic);
8032 right = IC_RIGHT (ic);
8033 result = IC_RESULT (ic);
8034 aopOp (left, ic, FALSE);
8035 aopOp (right, ic, FALSE);
8036 aopOp (result, ic, FALSE);
8038 offset = (int) ulFromVal (AOP (right)->aopu.aop_lit) / 8;
8040 aopGet (left, offset, FALSE, FALSE),
8043 aopGet (left, offset+1, FALSE, FALSE),
8046 freeAsmop (result, NULL, ic, TRUE);
8047 freeAsmop (right, NULL, ic, TRUE);
8048 freeAsmop (left, NULL, ic, TRUE);
8051 /*-----------------------------------------------------------------*/
8052 /* genSwap - generates code to swap nibbles or bytes */
8053 /*-----------------------------------------------------------------*/
8055 genSwap (iCode * ic)
8057 operand *left, *result;
8059 D(emitcode (";", "genSwap"));
8061 left = IC_LEFT (ic);
8062 result = IC_RESULT (ic);
8063 aopOp (left, ic, FALSE);
8064 aopOp (result, ic, FALSE);
8066 switch (AOP_SIZE (left))
8068 case 1: /* swap nibbles in byte */
8069 MOVA (aopGet (left, 0, FALSE, FALSE));
8070 emitcode ("swap", "a");
8071 aopPut (result, "a", 0);
8073 case 2: /* swap bytes in word */
8074 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
8076 MOVA (aopGet (left, 0, FALSE, FALSE));
8077 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8078 aopPut (result, "a", 1);
8080 else if (operandsEqu (left, result))
8083 bool pushedB = FALSE, leftInB = FALSE;
8085 MOVA (aopGet (left, 0, FALSE, FALSE));
8086 if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
8089 emitcode ("mov", "b,a");
8093 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8094 aopPut (result, reg, 1);
8101 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8102 aopPut (result, aopGet (left, 0, FALSE, FALSE), 1);
8106 wassertl(FALSE, "unsupported SWAP operand size");
8109 freeAsmop (result, NULL, ic, TRUE);
8110 freeAsmop (left, NULL, ic, TRUE);
8113 /*-----------------------------------------------------------------*/
8114 /* AccRol - rotate left accumulator by known count */
8115 /*-----------------------------------------------------------------*/
8117 AccRol (int shCount)
8119 shCount &= 0x0007; // shCount : 0..7
8126 emitcode ("rl", "a");
8129 emitcode ("rl", "a");
8130 emitcode ("rl", "a");
8133 emitcode ("swap", "a");
8134 emitcode ("rr", "a");
8137 emitcode ("swap", "a");
8140 emitcode ("swap", "a");
8141 emitcode ("rl", "a");
8144 emitcode ("rr", "a");
8145 emitcode ("rr", "a");
8148 emitcode ("rr", "a");
8153 /*-----------------------------------------------------------------*/
8154 /* AccLsh - left shift accumulator by known count */
8155 /*-----------------------------------------------------------------*/
8157 AccLsh (int shCount)
8162 emitcode ("add", "a,acc");
8163 else if (shCount == 2)
8165 emitcode ("add", "a,acc");
8166 emitcode ("add", "a,acc");
8170 /* rotate left accumulator */
8172 /* and kill the lower order bits */
8173 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
8178 /*-----------------------------------------------------------------*/
8179 /* AccRsh - right shift accumulator by known count */
8180 /*-----------------------------------------------------------------*/
8182 AccRsh (int shCount)
8189 emitcode ("rrc", "a");
8193 /* rotate right accumulator */
8194 AccRol (8 - shCount);
8195 /* and kill the higher order bits */
8196 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8201 /*-----------------------------------------------------------------*/
8202 /* AccSRsh - signed right shift accumulator by known count */
8203 /*-----------------------------------------------------------------*/
8205 AccSRsh (int shCount)
8212 emitcode ("mov", "c,acc.7");
8213 emitcode ("rrc", "a");
8215 else if (shCount == 2)
8217 emitcode ("mov", "c,acc.7");
8218 emitcode ("rrc", "a");
8219 emitcode ("mov", "c,acc.7");
8220 emitcode ("rrc", "a");
8224 tlbl = newiTempLabel (NULL);
8225 /* rotate right accumulator */
8226 AccRol (8 - shCount);
8227 /* and kill the higher order bits */
8228 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8229 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8230 emitcode ("orl", "a,#0x%02x",
8231 (unsigned char) ~SRMask[shCount]);
8237 /*-----------------------------------------------------------------*/
8238 /* shiftR1Left2Result - shift right one byte from left to result */
8239 /*-----------------------------------------------------------------*/
8241 shiftR1Left2Result (operand * left, int offl,
8242 operand * result, int offr,
8243 int shCount, int sign)
8245 MOVA (aopGet (left, offl, FALSE, FALSE));
8246 /* shift right accumulator */
8251 aopPut (result, "a", offr);
8254 /*-----------------------------------------------------------------*/
8255 /* shiftL1Left2Result - shift left one byte from left to result */
8256 /*-----------------------------------------------------------------*/
8258 shiftL1Left2Result (operand * left, int offl,
8259 operand * result, int offr, int shCount)
8262 l = aopGet (left, offl, FALSE, FALSE);
8264 /* shift left accumulator */
8266 aopPut (result, "a", offr);
8269 /*-----------------------------------------------------------------*/
8270 /* movLeft2Result - move byte from left to result */
8271 /*-----------------------------------------------------------------*/
8273 movLeft2Result (operand * left, int offl,
8274 operand * result, int offr, int sign)
8277 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8279 l = aopGet (left, offl, FALSE, FALSE);
8281 if (*l == '@' && (IS_AOP_PREG (result)))
8283 emitcode ("mov", "a,%s", l);
8284 aopPut (result, "a", offr);
8290 aopPut (result, l, offr);
8294 /* MSB sign in acc.7 ! */
8295 if (getDataSize (left) == offl + 1)
8298 aopPut (result, "a", offr);
8305 /*-----------------------------------------------------------------*/
8306 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
8307 /*-----------------------------------------------------------------*/
8311 emitcode ("rrc", "a");
8312 emitcode ("xch", "a,%s", x);
8313 emitcode ("rrc", "a");
8314 emitcode ("xch", "a,%s", x);
8317 /*-----------------------------------------------------------------*/
8318 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
8319 /*-----------------------------------------------------------------*/
8323 emitcode ("xch", "a,%s", x);
8324 emitcode ("rlc", "a");
8325 emitcode ("xch", "a,%s", x);
8326 emitcode ("rlc", "a");
8329 /*-----------------------------------------------------------------*/
8330 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8331 /*-----------------------------------------------------------------*/
8335 emitcode ("xch", "a,%s", x);
8336 emitcode ("add", "a,acc");
8337 emitcode ("xch", "a,%s", x);
8338 emitcode ("rlc", "a");
8341 /*-----------------------------------------------------------------*/
8342 /* AccAXLsh - left shift a:x by known count (0..7) */
8343 /*-----------------------------------------------------------------*/
8345 AccAXLsh (char *x, int shCount)
8360 case 5: // AAAAABBB:CCCCCDDD
8362 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8364 emitcode ("anl", "a,#0x%02x",
8365 SLMask[shCount]); // BBB00000:CCCCCDDD
8367 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8369 AccRol (shCount); // DDDCCCCC:BBB00000
8371 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8373 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8375 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8377 emitcode ("anl", "a,#0x%02x",
8378 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8380 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8382 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8385 case 6: // AAAAAABB:CCCCCCDD
8386 emitcode ("anl", "a,#0x%02x",
8387 SRMask[shCount]); // 000000BB:CCCCCCDD
8388 emitcode ("mov", "c,acc.0"); // c = B
8389 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8391 AccAXRrl1 (x); // BCCCCCCD:D000000B
8392 AccAXRrl1 (x); // BBCCCCCC:DD000000
8394 emitcode("rrc","a");
8395 emitcode("xch","a,%s", x);
8396 emitcode("rrc","a");
8397 emitcode("mov","c,acc.0"); //<< get correct bit
8398 emitcode("xch","a,%s", x);
8400 emitcode("rrc","a");
8401 emitcode("xch","a,%s", x);
8402 emitcode("rrc","a");
8403 emitcode("xch","a,%s", x);
8406 case 7: // a:x <<= 7
8408 emitcode ("anl", "a,#0x%02x",
8409 SRMask[shCount]); // 0000000B:CCCCCCCD
8411 emitcode ("mov", "c,acc.0"); // c = B
8413 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
8415 AccAXRrl1 (x); // BCCCCCCC:D0000000
8423 /*-----------------------------------------------------------------*/
8424 /* AccAXRsh - right shift a:x known count (0..7) */
8425 /*-----------------------------------------------------------------*/
8427 AccAXRsh (char *x, int shCount)
8435 AccAXRrl1 (x); // 0->a:x
8440 AccAXRrl1 (x); // 0->a:x
8443 AccAXRrl1 (x); // 0->a:x
8448 case 5: // AAAAABBB:CCCCCDDD = a:x
8450 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8452 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8454 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8456 emitcode ("anl", "a,#0x%02x",
8457 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8459 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8461 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8463 emitcode ("anl", "a,#0x%02x",
8464 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8466 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8468 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8470 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8473 case 6: // AABBBBBB:CCDDDDDD
8475 emitcode ("mov", "c,acc.7");
8476 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8478 emitcode ("mov", "c,acc.7");
8479 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8481 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8483 emitcode ("anl", "a,#0x%02x",
8484 SRMask[shCount]); // 000000AA:BBBBBBCC
8487 case 7: // ABBBBBBB:CDDDDDDD
8489 emitcode ("mov", "c,acc.7"); // c = A
8491 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8493 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8495 emitcode ("anl", "a,#0x%02x",
8496 SRMask[shCount]); // 0000000A:BBBBBBBC
8504 /*-----------------------------------------------------------------*/
8505 /* AccAXRshS - right shift signed a:x known count (0..7) */
8506 /*-----------------------------------------------------------------*/
8508 AccAXRshS (char *x, int shCount)
8516 emitcode ("mov", "c,acc.7");
8517 AccAXRrl1 (x); // s->a:x
8521 emitcode ("mov", "c,acc.7");
8522 AccAXRrl1 (x); // s->a:x
8524 emitcode ("mov", "c,acc.7");
8525 AccAXRrl1 (x); // s->a:x
8530 case 5: // AAAAABBB:CCCCCDDD = a:x
8532 tlbl = newiTempLabel (NULL);
8533 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8535 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8537 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8539 emitcode ("anl", "a,#0x%02x",
8540 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8542 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8544 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8546 emitcode ("anl", "a,#0x%02x",
8547 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8549 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8551 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8553 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8555 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8556 emitcode ("orl", "a,#0x%02x",
8557 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8560 break; // SSSSAAAA:BBBCCCCC
8562 case 6: // AABBBBBB:CCDDDDDD
8564 tlbl = newiTempLabel (NULL);
8565 emitcode ("mov", "c,acc.7");
8566 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8568 emitcode ("mov", "c,acc.7");
8569 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8571 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8573 emitcode ("anl", "a,#0x%02x",
8574 SRMask[shCount]); // 000000AA:BBBBBBCC
8576 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8577 emitcode ("orl", "a,#0x%02x",
8578 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8582 case 7: // ABBBBBBB:CDDDDDDD
8584 tlbl = newiTempLabel (NULL);
8585 emitcode ("mov", "c,acc.7"); // c = A
8587 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8589 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8591 emitcode ("anl", "a,#0x%02x",
8592 SRMask[shCount]); // 0000000A:BBBBBBBC
8594 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8595 emitcode ("orl", "a,#0x%02x",
8596 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8605 /*-----------------------------------------------------------------*/
8606 /* shiftL2Left2Result - shift left two bytes from left to result */
8607 /*-----------------------------------------------------------------*/
8609 shiftL2Left2Result (operand * left, int offl,
8610 operand * result, int offr, int shCount)
8613 bool pushedB = FALSE;
8616 if (sameRegs (AOP (result), AOP (left)) &&
8617 ((offl + MSB16) == offr))
8619 /* don't crash result[offr] */
8620 MOVA (aopGet (left, offl, FALSE, FALSE));
8621 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8622 usedB = !strncmp(x, "b", 1);
8624 else if (aopGetUsesAcc (result, offr))
8626 movLeft2Result (left, offl, result, offr, 0);
8629 emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8630 MOVA (aopGet (result, offr, FALSE, FALSE));
8631 emitcode ("xch", "a,b");
8636 movLeft2Result (left, offl, result, offr, 0);
8637 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8638 x = aopGet (result, offr, FALSE, FALSE);
8640 /* ax << shCount (x = lsb(result)) */
8641 AccAXLsh (x, shCount);
8644 emitcode ("xch", "a,b");
8645 aopPut (result, "a", offr);
8646 aopPut (result, "b", offr + MSB16);
8651 aopPut (result, "a", offr + MSB16);
8656 /*-----------------------------------------------------------------*/
8657 /* shiftR2Left2Result - shift right two bytes from left to result */
8658 /*-----------------------------------------------------------------*/
8660 shiftR2Left2Result (operand * left, int offl,
8661 operand * result, int offr,
8662 int shCount, int sign)
8665 bool pushedB = FALSE;
8668 if (sameRegs (AOP (result), AOP (left)) &&
8669 ((offl + MSB16) == offr))
8671 /* don't crash result[offr] */
8672 MOVA (aopGet (left, offl, FALSE, FALSE));
8673 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8674 usedB = !strncmp(x, "b", 1);
8676 else if (aopGetUsesAcc (result, offr))
8678 movLeft2Result (left, offl, result, offr, 0);
8681 emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8682 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8687 movLeft2Result (left, offl, result, offr, 0);
8688 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8689 x = aopGet (result, offr, FALSE, FALSE);
8691 /* a:x >> shCount (x = lsb(result)) */
8693 AccAXRshS (x, shCount);
8695 AccAXRsh (x, shCount);
8698 emitcode ("xch", "a,b");
8699 aopPut (result, "a", offr);
8700 emitcode ("xch", "a,b");
8703 if (getDataSize (result) > 1)
8704 aopPut (result, "a", offr + MSB16);
8707 /*-----------------------------------------------------------------*/
8708 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8709 /*-----------------------------------------------------------------*/
8711 shiftLLeftOrResult (operand * left, int offl,
8712 operand * result, int offr, int shCount)
8714 MOVA (aopGet (left, offl, FALSE, FALSE));
8715 /* shift left accumulator */
8717 /* or with result */
8718 if (aopGetUsesAcc (result, offr))
8720 emitcode ("xch", "a,b");
8721 MOVA (aopGet (result, offr, FALSE, FALSE));
8722 emitcode ("orl", "a,b");
8726 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8728 /* back to result */
8729 aopPut (result, "a", offr);
8732 /*-----------------------------------------------------------------*/
8733 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8734 /*-----------------------------------------------------------------*/
8736 shiftRLeftOrResult (operand * left, int offl,
8737 operand * result, int offr, int shCount)
8739 MOVA (aopGet (left, offl, FALSE, FALSE));
8740 /* shift right accumulator */
8742 /* or with result */
8743 if (aopGetUsesAcc(result, offr))
8745 emitcode ("xch", "a,b");
8746 MOVA (aopGet (result, offr, FALSE, FALSE));
8747 emitcode ("orl", "a,b");
8751 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8753 /* back to result */
8754 aopPut (result, "a", offr);
8757 /*-----------------------------------------------------------------*/
8758 /* genlshOne - left shift a one byte quantity by known count */
8759 /*-----------------------------------------------------------------*/
8761 genlshOne (operand * result, operand * left, int shCount)
8763 D (emitcode (";", "genlshOne"));
8765 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8768 /*-----------------------------------------------------------------*/
8769 /* genlshTwo - left shift two bytes by known amount != 0 */
8770 /*-----------------------------------------------------------------*/
8772 genlshTwo (operand * result, operand * left, int shCount)
8776 D (emitcode (";", "genlshTwo"));
8778 size = getDataSize (result);
8780 /* if shCount >= 8 */
8788 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8790 movLeft2Result (left, LSB, result, MSB16, 0);
8792 aopPut (result, zero, LSB);
8795 /* 1 <= shCount <= 7 */
8799 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8801 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8805 /*-----------------------------------------------------------------*/
8806 /* shiftLLong - shift left one long from left to result */
8807 /* offl = LSB or MSB16 */
8808 /*-----------------------------------------------------------------*/
8810 shiftLLong (operand * left, operand * result, int offr)
8813 int size = AOP_SIZE (result);
8815 if (size >= LSB + offr)
8817 l = aopGet (left, LSB, FALSE, FALSE);
8819 emitcode ("add", "a,acc");
8820 if (sameRegs (AOP (left), AOP (result)) &&
8821 size >= MSB16 + offr && offr != LSB)
8822 xch_a_aopGet (left, LSB + offr, FALSE, FALSE);
8824 aopPut (result, "a", LSB + offr);
8827 if (size >= MSB16 + offr)
8829 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8831 l = aopGet (left, MSB16, FALSE, FALSE);
8834 emitcode ("rlc", "a");
8835 if (sameRegs (AOP (left), AOP (result)) &&
8836 size >= MSB24 + offr && offr != LSB)
8837 xch_a_aopGet (left, MSB16 + offr, FALSE, FALSE);
8839 aopPut (result, "a", MSB16 + offr);
8842 if (size >= MSB24 + offr)
8844 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8846 l = aopGet (left, MSB24, FALSE, FALSE);
8849 emitcode ("rlc", "a");
8850 if (sameRegs (AOP (left), AOP (result)) &&
8851 size >= MSB32 + offr && offr != LSB)
8852 xch_a_aopGet (left, MSB24 + offr, FALSE, FALSE);
8854 aopPut (result, "a", MSB24 + offr);
8857 if (size > MSB32 + offr)
8859 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8861 l = aopGet (left, MSB32, FALSE, FALSE);
8864 emitcode ("rlc", "a");
8865 aopPut (result, "a", MSB32 + offr);
8868 aopPut (result, zero, LSB);
8871 /*-----------------------------------------------------------------*/
8872 /* genlshFour - shift four byte by a known amount != 0 */
8873 /*-----------------------------------------------------------------*/
8875 genlshFour (operand * result, operand * left, int shCount)
8879 D (emitcode (";", "genlshFour"));
8881 size = AOP_SIZE (result);
8883 /* if shifting more that 3 bytes */
8888 /* lowest order of left goes to the highest
8889 order of the destination */
8890 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8892 movLeft2Result (left, LSB, result, MSB32, 0);
8893 aopPut (result, zero, LSB);
8894 aopPut (result, zero, MSB16);
8895 aopPut (result, zero, MSB24);
8899 /* more than two bytes */
8900 else if (shCount >= 16)
8902 /* lower order two bytes goes to higher order two bytes */
8904 /* if some more remaining */
8906 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8909 movLeft2Result (left, MSB16, result, MSB32, 0);
8910 movLeft2Result (left, LSB, result, MSB24, 0);
8912 aopPut (result, zero, MSB16);
8913 aopPut (result, zero, LSB);
8917 /* if more than 1 byte */
8918 else if (shCount >= 8)
8920 /* lower order three bytes goes to higher order three bytes */
8925 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8927 movLeft2Result (left, LSB, result, MSB16, 0);
8933 movLeft2Result (left, MSB24, result, MSB32, 0);
8934 movLeft2Result (left, MSB16, result, MSB24, 0);
8935 movLeft2Result (left, LSB, result, MSB16, 0);
8936 aopPut (result, zero, LSB);
8938 else if (shCount == 1)
8939 shiftLLong (left, result, MSB16);
8942 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8943 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8944 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8945 aopPut (result, zero, LSB);
8950 /* 1 <= shCount <= 7 */
8951 else if (shCount <= 2)
8953 shiftLLong (left, result, LSB);
8955 shiftLLong (result, result, LSB);
8957 /* 3 <= shCount <= 7, optimize */
8960 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8961 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8962 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8966 /*-----------------------------------------------------------------*/
8967 /* genLeftShiftLiteral - left shifting by known count */
8968 /*-----------------------------------------------------------------*/
8970 genLeftShiftLiteral (operand * left,
8975 int shCount = (int) ulFromVal (AOP (right)->aopu.aop_lit);
8978 D (emitcode (";", "genLeftShiftLiteral"));
8980 freeAsmop (right, NULL, ic, TRUE);
8982 aopOp (left, ic, FALSE);
8983 aopOp (result, ic, FALSE);
8985 size = getSize (operandType (result));
8988 emitcode ("; shift left ", "result %d, left %d", size,
8992 /* I suppose that the left size >= result size */
8997 movLeft2Result (left, size, result, size, 0);
9000 else if (shCount >= (size * 8))
9004 aopPut (result, zero, size);
9012 genlshOne (result, left, shCount);
9016 genlshTwo (result, left, shCount);
9020 genlshFour (result, left, shCount);
9023 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9024 "*** ack! mystery literal shift!\n");
9028 freeAsmop (result, NULL, ic, TRUE);
9029 freeAsmop (left, NULL, ic, TRUE);
9032 /*-----------------------------------------------------------------*/
9033 /* genLeftShift - generates code for left shifting */
9034 /*-----------------------------------------------------------------*/
9036 genLeftShift (iCode * ic)
9038 operand *left, *right, *result;
9041 symbol *tlbl, *tlbl1;
9044 D (emitcode (";", "genLeftShift"));
9046 right = IC_RIGHT (ic);
9047 left = IC_LEFT (ic);
9048 result = IC_RESULT (ic);
9050 aopOp (right, ic, FALSE);
9052 /* if the shift count is known then do it
9053 as efficiently as possible */
9054 if (AOP_TYPE (right) == AOP_LIT)
9056 genLeftShiftLiteral (left, right, result, ic);
9060 /* shift count is unknown then we have to form
9061 a loop get the loop count in B : Note: we take
9062 only the lower order byte since shifting
9063 more that 32 bits make no sense anyway, ( the
9064 largest size of an object can be only 32 bits ) */
9067 MOVB (aopGet (right, 0, FALSE, FALSE));
9068 emitcode ("inc", "b");
9069 freeAsmop (right, NULL, ic, TRUE);
9070 aopOp (left, ic, FALSE);
9071 aopOp (result, ic, FALSE);
9073 /* now move the left to the result if they are not the same */
9074 if (!sameRegs (AOP (left), AOP (result)) &&
9075 AOP_SIZE (result) > 1)
9078 size = AOP_SIZE (result);
9082 l = aopGet (left, offset, FALSE, TRUE);
9083 if (*l == '@' && (IS_AOP_PREG (result)))
9086 emitcode ("mov", "a,%s", l);
9087 aopPut (result, "a", offset);
9090 aopPut (result, l, offset);
9095 tlbl = newiTempLabel (NULL);
9096 size = AOP_SIZE (result);
9098 tlbl1 = newiTempLabel (NULL);
9100 /* if it is only one byte then */
9103 symbol *tlbl1 = newiTempLabel (NULL);
9105 l = aopGet (left, 0, FALSE, FALSE);
9107 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9109 emitcode ("add", "a,acc");
9111 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9113 aopPut (result, "a", 0);
9117 reAdjustPreg (AOP (result));
9119 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9121 l = aopGet (result, offset, FALSE, FALSE);
9123 emitcode ("add", "a,acc");
9124 aopPut (result, "a", offset++);
9127 l = aopGet (result, offset, FALSE, FALSE);
9129 emitcode ("rlc", "a");
9130 aopPut (result, "a", offset++);
9132 reAdjustPreg (AOP (result));
9135 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9138 freeAsmop (result, NULL, ic, TRUE);
9139 freeAsmop (left, NULL, ic, TRUE);
9142 /*-----------------------------------------------------------------*/
9143 /* genrshOne - right shift a one byte quantity by known count */
9144 /*-----------------------------------------------------------------*/
9146 genrshOne (operand * result, operand * left,
9147 int shCount, int sign)
9149 D (emitcode (";", "genrshOne"));
9151 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9154 /*-----------------------------------------------------------------*/
9155 /* genrshTwo - right shift two bytes by known amount != 0 */
9156 /*-----------------------------------------------------------------*/
9158 genrshTwo (operand * result, operand * left,
9159 int shCount, int sign)
9161 D (emitcode (";", "genrshTwo"));
9163 /* if shCount >= 8 */
9168 shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
9170 movLeft2Result (left, MSB16, result, LSB, sign);
9171 addSign (result, MSB16, sign);
9174 /* 1 <= shCount <= 7 */
9176 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9179 /*-----------------------------------------------------------------*/
9180 /* shiftRLong - shift right one long from left to result */
9181 /* offl = LSB or MSB16 */
9182 /*-----------------------------------------------------------------*/
9184 shiftRLong (operand * left, int offl,
9185 operand * result, int sign)
9187 bool overlapping = regsInCommon (left, result) || operandsEqu(left, result);
9189 if (overlapping && offl>1)
9191 // we are in big trouble, but this shouldn't happen
9192 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9195 MOVA (aopGet (left, MSB32, FALSE, FALSE));
9202 emitcode ("rlc", "a");
9203 emitcode ("subb", "a,acc");
9204 if (overlapping && sameByte (AOP (left), MSB32, AOP (result), MSB32))
9206 xch_a_aopGet (left, MSB32, FALSE, FALSE);
9210 aopPut (result, "a", MSB32);
9211 MOVA (aopGet (left, MSB32, FALSE, FALSE));
9216 if (aopPutUsesAcc (result, zero, MSB32))
9218 emitcode("xch", "a,b");
9219 aopPut (result, zero, MSB32);
9220 emitcode("xch", "a,b");
9224 aopPut (result, zero, MSB32);
9231 emitcode ("clr", "c");
9235 emitcode ("mov", "c,acc.7");
9238 emitcode ("rrc", "a");
9240 if (overlapping && offl==MSB16 &&
9241 sameByte (AOP (left), MSB24, AOP (result), MSB32-offl))
9243 xch_a_aopGet (left, MSB24, FALSE, FALSE);
9247 aopPut (result, "a", MSB32 - offl);
9248 MOVA (aopGet (left, MSB24, FALSE, FALSE));
9251 emitcode ("rrc", "a");
9252 if (overlapping && offl==MSB16 &&
9253 sameByte (AOP (left), MSB16, AOP (result), MSB24-offl))
9255 xch_a_aopGet (left, MSB16, FALSE, FALSE);
9259 aopPut (result, "a", MSB24 - offl);
9260 MOVA (aopGet (left, MSB16, FALSE, FALSE));
9263 emitcode ("rrc", "a");
9266 aopPut (result, "a", MSB16 - offl);
9271 sameByte (AOP (left), LSB, AOP (result), MSB16-offl))
9273 xch_a_aopGet (left, LSB, FALSE, FALSE);
9277 aopPut (result, "a", MSB16 - offl);
9278 MOVA (aopGet (left, LSB, FALSE, FALSE));
9280 emitcode ("rrc", "a");
9281 aopPut (result, "a", LSB);
9285 /*-----------------------------------------------------------------*/
9286 /* genrshFour - shift four byte by a known amount != 0 */
9287 /*-----------------------------------------------------------------*/
9289 genrshFour (operand * result, operand * left,
9290 int shCount, int sign)
9292 D (emitcode (";", "genrshFour"));
9294 /* if shifting more that 3 bytes */
9299 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9301 movLeft2Result (left, MSB32, result, LSB, sign);
9302 addSign (result, MSB16, sign);
9304 else if (shCount >= 16)
9308 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9311 movLeft2Result (left, MSB24, result, LSB, 0);
9312 movLeft2Result (left, MSB32, result, MSB16, sign);
9314 addSign (result, MSB24, sign);
9316 else if (shCount >= 8)
9321 shiftRLong (left, MSB16, result, sign);
9323 else if (shCount == 0)
9325 movLeft2Result (left, MSB16, result, LSB, 0);
9326 movLeft2Result (left, MSB24, result, MSB16, 0);
9327 movLeft2Result (left, MSB32, result, MSB24, sign);
9328 addSign (result, MSB32, sign);
9332 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9333 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9334 /* the last shift is signed */
9335 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9336 addSign (result, MSB32, sign);
9341 /* 1 <= shCount <= 7 */
9344 shiftRLong (left, LSB, result, sign);
9346 shiftRLong (result, LSB, result, sign);
9350 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9351 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9352 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9357 /*-----------------------------------------------------------------*/
9358 /* genRightShiftLiteral - right shifting by known count */
9359 /*-----------------------------------------------------------------*/
9361 genRightShiftLiteral (operand * left,
9367 int shCount = (int) ulFromVal (AOP (right)->aopu.aop_lit);
9370 D (emitcode (";", "genRightShiftLiteral"));
9372 freeAsmop (right, NULL, ic, TRUE);
9374 aopOp (left, ic, FALSE);
9375 aopOp (result, ic, FALSE);
9378 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9382 size = getDataSize (left);
9383 /* test the LEFT size !!! */
9385 /* I suppose that the left size >= result size */
9388 size = getDataSize (result);
9390 movLeft2Result (left, size, result, size, 0);
9393 else if (shCount >= (size * 8))
9397 /* get sign in acc.7 */
9398 MOVA (aopGet (left, size - 1, FALSE, FALSE));
9400 addSign (result, LSB, sign);
9407 genrshOne (result, left, shCount, sign);
9411 genrshTwo (result, left, shCount, sign);
9415 genrshFour (result, left, shCount, sign);
9421 freeAsmop (result, NULL, ic, TRUE);
9422 freeAsmop (left, NULL, ic, TRUE);
9425 /*-----------------------------------------------------------------*/
9426 /* genSignedRightShift - right shift of signed number */
9427 /*-----------------------------------------------------------------*/
9429 genSignedRightShift (iCode * ic)
9431 operand *right, *left, *result;
9434 symbol *tlbl, *tlbl1;
9437 D (emitcode (";", "genSignedRightShift"));
9439 /* we do it the hard way put the shift count in b
9440 and loop thru preserving the sign */
9442 right = IC_RIGHT (ic);
9443 left = IC_LEFT (ic);
9444 result = IC_RESULT (ic);
9446 aopOp (right, ic, FALSE);
9449 if (AOP_TYPE (right) == AOP_LIT)
9451 genRightShiftLiteral (left, right, result, ic, 1);
9454 /* shift count is unknown then we have to form
9455 a loop get the loop count in B : Note: we take
9456 only the lower order byte since shifting
9457 more that 32 bits make no sense anyway, ( the
9458 largest size of an object can be only 32 bits ) */
9461 MOVB (aopGet (right, 0, FALSE, FALSE));
9462 emitcode ("inc", "b");
9463 freeAsmop (right, NULL, ic, TRUE);
9464 aopOp (left, ic, FALSE);
9465 aopOp (result, ic, FALSE);
9467 /* now move the left to the result if they are not the
9469 if (!sameRegs (AOP (left), AOP (result)) &&
9470 AOP_SIZE (result) > 1)
9473 size = AOP_SIZE (result);
9477 l = aopGet (left, offset, FALSE, TRUE);
9478 if (*l == '@' && IS_AOP_PREG (result))
9481 emitcode ("mov", "a,%s", l);
9482 aopPut (result, "a", offset);
9485 aopPut (result, l, offset);
9490 /* mov the highest order bit to OVR */
9491 tlbl = newiTempLabel (NULL);
9492 tlbl1 = newiTempLabel (NULL);
9494 size = AOP_SIZE (result);
9496 MOVA (aopGet (left, offset, FALSE, FALSE));
9497 emitcode ("rlc", "a");
9498 emitcode ("mov", "ov,c");
9499 /* if it is only one byte then */
9502 l = aopGet (left, 0, FALSE, FALSE);
9504 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9506 emitcode ("mov", "c,ov");
9507 emitcode ("rrc", "a");
9509 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9511 aopPut (result, "a", 0);
9515 reAdjustPreg (AOP (result));
9516 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9518 emitcode ("mov", "c,ov");
9521 l = aopGet (result, offset, FALSE, FALSE);
9523 emitcode ("rrc", "a");
9524 aopPut (result, "a", offset--);
9526 reAdjustPreg (AOP (result));
9528 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9532 freeAsmop (result, NULL, ic, TRUE);
9533 freeAsmop (left, NULL, ic, TRUE);
9536 /*-----------------------------------------------------------------*/
9537 /* genRightShift - generate code for right shifting */
9538 /*-----------------------------------------------------------------*/
9540 genRightShift (iCode * ic)
9542 operand *right, *left, *result;
9546 symbol *tlbl, *tlbl1;
9549 D (emitcode (";", "genRightShift"));
9551 /* if signed then we do it the hard way preserve the
9552 sign bit moving it inwards */
9553 letype = getSpec (operandType (IC_LEFT (ic)));
9555 if (!SPEC_USIGN (letype))
9557 genSignedRightShift (ic);
9561 /* signed & unsigned types are treated the same : i.e. the
9562 signed is NOT propagated inwards : quoting from the
9563 ANSI - standard : "for E1 >> E2, is equivalent to division
9564 by 2**E2 if unsigned or if it has a non-negative value,
9565 otherwise the result is implementation defined ", MY definition
9566 is that the sign does not get propagated */
9568 right = IC_RIGHT (ic);
9569 left = IC_LEFT (ic);
9570 result = IC_RESULT (ic);
9572 aopOp (right, ic, FALSE);
9574 /* if the shift count is known then do it
9575 as efficiently as possible */
9576 if (AOP_TYPE (right) == AOP_LIT)
9578 genRightShiftLiteral (left, right, result, ic, 0);
9582 /* shift count is unknown then we have to form
9583 a loop get the loop count in B : Note: we take
9584 only the lower order byte since shifting
9585 more that 32 bits make no sense anyway, ( the
9586 largest size of an object can be only 32 bits ) */
9589 MOVB (aopGet (right, 0, FALSE, FALSE));
9590 emitcode ("inc", "b");
9591 freeAsmop (right, NULL, ic, TRUE);
9592 aopOp (left, ic, FALSE);
9593 aopOp (result, ic, FALSE);
9595 /* now move the left to the result if they are not the
9597 if (!sameRegs (AOP (left), AOP (result)) &&
9598 AOP_SIZE (result) > 1)
9600 size = AOP_SIZE (result);
9604 l = aopGet (left, offset, FALSE, TRUE);
9605 if (*l == '@' && IS_AOP_PREG (result))
9608 emitcode ("mov", "a,%s", l);
9609 aopPut (result, "a", offset);
9612 aopPut (result, l, offset);
9617 tlbl = newiTempLabel (NULL);
9618 tlbl1 = newiTempLabel (NULL);
9619 size = AOP_SIZE (result);
9622 /* if it is only one byte then */
9625 l = aopGet (left, 0, FALSE, FALSE);
9627 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9630 emitcode ("rrc", "a");
9632 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9634 aopPut (result, "a", 0);
9638 reAdjustPreg (AOP (result));
9639 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9644 l = aopGet (result, offset, FALSE, FALSE);
9646 emitcode ("rrc", "a");
9647 aopPut (result, "a", offset--);
9649 reAdjustPreg (AOP (result));
9652 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9656 freeAsmop (result, NULL, ic, TRUE);
9657 freeAsmop (left, NULL, ic, TRUE);
9660 /*-----------------------------------------------------------------*/
9661 /* emitPtrByteGet - emits code to get a byte into A through a */
9662 /* pointer register (R0, R1, or DPTR). The */
9663 /* original value of A can be preserved in B. */
9664 /*-----------------------------------------------------------------*/
9666 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9673 emitcode ("mov", "b,a");
9674 emitcode ("mov", "a,@%s", rname);
9679 emitcode ("mov", "b,a");
9680 emitcode ("movx", "a,@%s", rname);
9685 emitcode ("mov", "b,a");
9686 emitcode ("movx", "a,@dptr");
9691 emitcode ("mov", "b,a");
9692 emitcode ("clr", "a");
9693 emitcode ("movc", "a,@a+dptr");
9699 emitcode ("push", "b");
9700 emitcode ("push", "acc");
9702 emitcode ("lcall", "__gptrget");
9704 emitcode ("pop", "b");
9709 /*-----------------------------------------------------------------*/
9710 /* emitPtrByteSet - emits code to set a byte from src through a */
9711 /* pointer register (R0, R1, or DPTR). */
9712 /*-----------------------------------------------------------------*/
9714 emitPtrByteSet (char *rname, int p_type, char *src)
9723 emitcode ("mov", "@%s,a", rname);
9726 emitcode ("mov", "@%s,%s", rname, src);
9731 emitcode ("movx", "@%s,a", rname);
9736 emitcode ("movx", "@dptr,a");
9741 emitcode ("lcall", "__gptrput");
9746 /*-----------------------------------------------------------------*/
9747 /* genUnpackBits - generates code for unpacking bits */
9748 /*-----------------------------------------------------------------*/
9750 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9752 int offset = 0; /* result byte offset */
9753 int rsize; /* result size */
9754 int rlen = 0; /* remaining bitfield length */
9755 sym_link *etype; /* bitfield type information */
9756 int blen; /* bitfield length */
9757 int bstr; /* bitfield starting bit within byte */
9758 static char* const accBits[] = {"acc.0", "acc.1", "acc.2", "acc.3",
9759 "acc.4", "acc.5", "acc.6", "acc.7"};
9761 D(emitcode (";", "genUnpackBits"));
9763 etype = getSpec (operandType (result));
9764 rsize = getSize (operandType (result));
9765 blen = SPEC_BLEN (etype);
9766 bstr = SPEC_BSTR (etype);
9768 if (ifx && blen <= 8)
9770 emitPtrByteGet (rname, ptype, FALSE);
9773 return accBits[bstr];;
9778 emitcode ("anl", "a,#0x%02x",
9779 (((unsigned char) -1) >> (8 - blen)) << bstr);
9785 /* If the bitfield length is less than a byte */
9788 emitPtrByteGet (rname, ptype, FALSE);
9790 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9791 if (!SPEC_USIGN (etype))
9793 /* signed bitfield */
9794 symbol *tlbl = newiTempLabel (NULL);
9796 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9797 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9800 aopPut (result, "a", offset++);
9804 /* Bit field did not fit in a byte. Copy all
9805 but the partial byte at the end. */
9806 for (rlen=blen;rlen>=8;rlen-=8)
9808 emitPtrByteGet (rname, ptype, FALSE);
9809 aopPut (result, "a", offset++);
9811 emitcode ("inc", "%s", rname);
9814 /* Handle the partial byte at the end */
9817 emitPtrByteGet (rname, ptype, FALSE);
9818 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9819 if (!SPEC_USIGN (etype))
9821 /* signed bitfield */
9822 symbol *tlbl = newiTempLabel (NULL);
9824 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9825 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9828 aopPut (result, "a", offset++);
9836 if (SPEC_USIGN (etype))
9840 /* signed bitfield: sign extension with 0x00 or 0xff */
9841 emitcode ("rlc", "a");
9842 emitcode ("subb", "a,acc");
9848 aopPut (result, source, offset++);
9854 /*-----------------------------------------------------------------*/
9855 /* genDataPointerGet - generates code when ptr offset is known */
9856 /*-----------------------------------------------------------------*/
9858 genDataPointerGet (operand * left,
9864 int size, offset = 0;
9866 D (emitcode (";", "genDataPointerGet"));
9868 aopOp (result, ic, TRUE);
9870 /* get the string representation of the name */
9871 l = aopGet (left, 0, FALSE, TRUE);
9873 size = AOP_SIZE (result);
9878 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
9882 SNPRINTF (buffer, sizeof(buffer), "%s", l);
9884 aopPut (result, buffer, offset++);
9887 freeAsmop (result, NULL, ic, TRUE);
9888 freeAsmop (left, NULL, ic, TRUE);
9891 /*-----------------------------------------------------------------*/
9892 /* genNearPointerGet - emitcode for near pointer fetch */
9893 /*-----------------------------------------------------------------*/
9895 genNearPointerGet (operand * left,
9904 char *ifxCond = "a";
9905 sym_link *rtype, *retype;
9906 sym_link *ltype = operandType (left);
9908 D (emitcode (";", "genNearPointerGet"));
9910 rtype = operandType (result);
9911 retype = getSpec (rtype);
9913 aopOp (left, ic, FALSE);
9915 /* if left is rematerialisable and
9916 result is not bitfield variable type and
9917 the left is pointer to data space i.e
9918 lower 128 bytes of space */
9919 if (AOP_TYPE (left) == AOP_IMMD &&
9920 !IS_BITFIELD (retype) &&
9921 DCL_TYPE (ltype) == POINTER)
9923 genDataPointerGet (left, result, ic);
9927 //aopOp (result, ic, FALSE);
9928 aopOp (result, ic, result?TRUE:FALSE);
9930 /* if the value is already in a pointer register
9931 then don't need anything more */
9932 if (!AOP_INPREG (AOP (left)))
9934 if (IS_AOP_PREG (left))
9936 // Aha, it is a pointer, just in disguise.
9937 rname = aopGet (left, 0, FALSE, FALSE);
9940 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9941 __FILE__, __LINE__);
9946 emitcode ("mov", "a%s,%s", rname + 1, rname);
9947 rname++; // skip the '@'.
9952 /* otherwise get a free pointer register */
9954 preg = getFreePtr (ic, &aop, FALSE);
9955 emitcode ("mov", "%s,%s",
9957 aopGet (left, 0, FALSE, TRUE));
9962 rname = aopGet (left, 0, FALSE, FALSE);
9964 /* if bitfield then unpack the bits */
9965 if (IS_BITFIELD (retype))
9966 ifxCond = genUnpackBits (result, rname, POINTER, ifx);
9969 /* we have can just get the values */
9970 int size = AOP_SIZE (result);
9975 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9978 emitcode ("mov", "a,@%s", rname);
9980 aopPut (result, "a", offset);
9986 SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
9987 aopPut (result, buffer, offset);
9991 emitcode ("inc", "%s", rname);
9995 /* now some housekeeping stuff */
9996 if (aop) /* we had to allocate for this iCode */
9998 if (pi) { /* post increment present */
9999 aopPut (left, rname, 0);
10001 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
10005 /* we did not allocate which means left
10006 already in a pointer register, then
10007 if size > 0 && this could be used again
10008 we have to point it back to where it
10010 if ((AOP_SIZE (result) > 1 &&
10011 !OP_SYMBOL (left)->remat &&
10012 (OP_SYMBOL (left)->liveTo > ic->seq ||
10016 int size = AOP_SIZE (result) - 1;
10018 emitcode ("dec", "%s", rname);
10022 if (ifx && !ifx->generated)
10024 genIfxJump (ifx, ifxCond, left, NULL, result);
10028 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
10029 freeAsmop (left, NULL, ic, TRUE);
10030 if (pi) pi->generated = 1;
10033 /*-----------------------------------------------------------------*/
10034 /* genPagedPointerGet - emitcode for paged pointer fetch */
10035 /*-----------------------------------------------------------------*/
10037 genPagedPointerGet (operand * left,
10046 char *ifxCond = "a";
10047 sym_link *rtype, *retype;
10049 D (emitcode (";", "genPagedPointerGet"));
10051 rtype = operandType (result);
10052 retype = getSpec (rtype);
10054 aopOp (left, ic, FALSE);
10056 aopOp (result, ic, FALSE);
10058 /* if the value is already in a pointer register
10059 then don't need anything more */
10060 if (!AOP_INPREG (AOP (left)))
10062 /* otherwise get a free pointer register */
10063 aop = newAsmop (0);
10064 preg = getFreePtr (ic, &aop, FALSE);
10065 emitcode ("mov", "%s,%s",
10067 aopGet (left, 0, FALSE, TRUE));
10068 rname = preg->name;
10071 rname = aopGet (left, 0, FALSE, FALSE);
10073 /* if bitfield then unpack the bits */
10074 if (IS_BITFIELD (retype))
10075 ifxCond = genUnpackBits (result, rname, PPOINTER, ifx);
10078 /* we have can just get the values */
10079 int size = AOP_SIZE (result);
10085 emitcode ("movx", "a,@%s", rname);
10087 aopPut (result, "a", offset);
10092 emitcode ("inc", "%s", rname);
10096 /* now some housekeeping stuff */
10097 if (aop) /* we had to allocate for this iCode */
10100 aopPut (left, rname, 0);
10101 freeAsmop (NULL, aop, ic, TRUE);
10105 /* we did not allocate which means left
10106 already in a pointer register, then
10107 if size > 0 && this could be used again
10108 we have to point it back to where it
10110 if ((AOP_SIZE (result) > 1 &&
10111 !OP_SYMBOL (left)->remat &&
10112 (OP_SYMBOL (left)->liveTo > ic->seq ||
10116 int size = AOP_SIZE (result) - 1;
10118 emitcode ("dec", "%s", rname);
10122 if (ifx && !ifx->generated)
10124 genIfxJump (ifx, ifxCond, left, NULL, result);
10128 freeAsmop (result, NULL, ic, TRUE);
10129 freeAsmop (left, NULL, ic, TRUE);
10130 if (pi) pi->generated = 1;
10133 /*--------------------------------------------------------------------*/
10134 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
10135 /*--------------------------------------------------------------------*/
10137 loadDptrFromOperand (operand *op, bool loadBToo)
10139 if (AOP_TYPE (op) != AOP_STR)
10141 /* if this is rematerializable */
10142 if (AOP_TYPE (op) == AOP_IMMD)
10144 emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
10147 if (AOP(op)->aopu.aop_immd.from_cast_remat)
10148 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
10151 wassertl(FALSE, "need pointerCode");
10152 emitcode (";", "mov b,???");
10153 /* genPointerGet and genPointerSet originally did different
10154 ** things for this case. Both seem wrong.
10155 ** from genPointerGet:
10156 ** emitcode ("mov", "b,#%d", pointerCode (retype));
10157 ** from genPointerSet:
10158 ** emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
10163 else if (AOP_TYPE (op) == AOP_DPTR)
10167 MOVA (aopGet (op, 0, FALSE, FALSE));
10168 emitcode ("push", "acc");
10169 MOVA (aopGet (op, 1, FALSE, FALSE));
10170 emitcode ("push", "acc");
10171 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10172 emitcode ("pop", "dph");
10173 emitcode ("pop", "dpl");
10177 MOVA (aopGet (op, 0, FALSE, FALSE));
10178 emitcode ("push", "acc");
10179 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10180 emitcode ("pop", "dpl");
10184 { /* we need to get it byte by byte */
10185 emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
10186 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10188 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10193 /*-----------------------------------------------------------------*/
10194 /* genFarPointerGet - get value from far space */
10195 /*-----------------------------------------------------------------*/
10197 genFarPointerGet (operand * left,
10198 operand * result, iCode * ic, iCode * pi, iCode * ifx)
10201 char *ifxCond = "a";
10202 sym_link *retype = getSpec (operandType (result));
10204 D (emitcode (";", "genFarPointerGet"));
10206 aopOp (left, ic, FALSE);
10207 loadDptrFromOperand (left, FALSE);
10209 /* so dptr now contains the address */
10210 aopOp (result, ic, FALSE);
10212 /* if bit then unpack */
10213 if (IS_BITFIELD (retype))
10214 ifxCond = genUnpackBits (result, "dptr", FPOINTER, ifx);
10217 size = AOP_SIZE (result);
10222 emitcode ("movx", "a,@dptr");
10224 aopPut (result, "a", offset++);
10226 emitcode ("inc", "dptr");
10230 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10232 aopPut (left, "dpl", 0);
10233 aopPut (left, "dph", 1);
10237 if (ifx && !ifx->generated)
10239 genIfxJump (ifx, ifxCond, left, NULL, result);
10242 freeAsmop (result, NULL, ic, TRUE);
10243 freeAsmop (left, NULL, ic, TRUE);
10246 /*-----------------------------------------------------------------*/
10247 /* genCodePointerGet - get value from code space */
10248 /*-----------------------------------------------------------------*/
10250 genCodePointerGet (operand * left,
10251 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10254 char *ifxCond = "a";
10255 sym_link *retype = getSpec (operandType (result));
10257 D (emitcode (";", "genCodePointerGet"));
10259 aopOp (left, ic, FALSE);
10260 loadDptrFromOperand (left, FALSE);
10262 /* so dptr now contains the address */
10263 aopOp (result, ic, FALSE);
10265 /* if bit then unpack */
10266 if (IS_BITFIELD (retype))
10267 ifxCond = genUnpackBits (result, "dptr", CPOINTER, ifx);
10270 size = AOP_SIZE (result);
10275 emitcode ("clr", "a");
10276 emitcode ("movc", "a,@a+dptr");
10278 aopPut (result, "a", offset++);
10280 emitcode ("inc", "dptr");
10284 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10286 aopPut (left, "dpl", 0);
10287 aopPut (left, "dph", 1);
10291 if (ifx && !ifx->generated)
10293 genIfxJump (ifx, ifxCond, left, NULL, result);
10296 freeAsmop (result, NULL, ic, TRUE);
10297 freeAsmop (left, NULL, ic, TRUE);
10300 /*-----------------------------------------------------------------*/
10301 /* genGenPointerGet - get value from generic pointer space */
10302 /*-----------------------------------------------------------------*/
10304 genGenPointerGet (operand * left,
10305 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10308 char *ifxCond = "a";
10309 sym_link *retype = getSpec (operandType (result));
10311 D (emitcode (";", "genGenPointerGet"));
10313 aopOp (left, ic, FALSE);
10314 loadDptrFromOperand (left, TRUE);
10316 /* so dptr now contains the address */
10317 aopOp (result, ic, FALSE);
10319 /* if bit then unpack */
10320 if (IS_BITFIELD (retype))
10322 ifxCond = genUnpackBits (result, "dptr", GPOINTER, ifx);
10326 size = AOP_SIZE (result);
10331 emitcode ("lcall", "__gptrget");
10333 aopPut (result, "a", offset++);
10335 emitcode ("inc", "dptr");
10339 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10341 aopPut (left, "dpl", 0);
10342 aopPut (left, "dph", 1);
10346 if (ifx && !ifx->generated)
10348 genIfxJump (ifx, ifxCond, left, NULL, result);
10351 freeAsmop (result, NULL, ic, TRUE);
10352 freeAsmop (left, NULL, ic, TRUE);
10355 /*-----------------------------------------------------------------*/
10356 /* genPointerGet - generate code for pointer get */
10357 /*-----------------------------------------------------------------*/
10359 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
10361 operand *left, *result;
10362 sym_link *type, *etype;
10365 D (emitcode (";", "genPointerGet"));
10367 left = IC_LEFT (ic);
10368 result = IC_RESULT (ic);
10370 if (getSize (operandType (result))>1)
10373 /* depending on the type of pointer we need to
10374 move it to the correct pointer register */
10375 type = operandType (left);
10376 etype = getSpec (type);
10377 /* if left is of type of pointer then it is simple */
10378 if (IS_PTR (type) && !IS_FUNC (type->next))
10380 p_type = DCL_TYPE (type);
10384 /* we have to go by the storage class */
10385 p_type = PTR_TYPE (SPEC_OCLS (etype));
10388 /* special case when cast remat */
10389 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10390 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10392 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10393 type = operandType (left);
10394 p_type = DCL_TYPE (type);
10396 /* now that we have the pointer type we assign
10397 the pointer values */
10403 genNearPointerGet (left, result, ic, pi, ifx);
10407 genPagedPointerGet (left, result, ic, pi, ifx);
10411 genFarPointerGet (left, result, ic, pi, ifx);
10415 genCodePointerGet (left, result, ic, pi, ifx);
10419 genGenPointerGet (left, result, ic, pi, ifx);
10425 /*-----------------------------------------------------------------*/
10426 /* genPackBits - generates code for packed bit storage */
10427 /*-----------------------------------------------------------------*/
10429 genPackBits (sym_link * etype,
10431 char *rname, int p_type)
10433 int offset = 0; /* source byte offset */
10434 int rlen = 0; /* remaining bitfield length */
10435 int blen; /* bitfield length */
10436 int bstr; /* bitfield starting bit within byte */
10437 int litval; /* source literal value (if AOP_LIT) */
10438 unsigned char mask; /* bitmask within current byte */
10440 D(emitcode (";", "genPackBits"));
10442 blen = SPEC_BLEN (etype);
10443 bstr = SPEC_BSTR (etype);
10445 /* If the bitfield length is less than a byte */
10448 mask = ((unsigned char) (0xFF << (blen + bstr)) |
10449 (unsigned char) (0xFF >> (8 - bstr)));
10451 if (AOP_TYPE (right) == AOP_LIT)
10453 /* Case with a bitfield length <8 and literal source
10455 litval = (int) ulFromVal (AOP (right)->aopu.aop_lit);
10457 litval &= (~mask) & 0xff;
10458 emitPtrByteGet (rname, p_type, FALSE);
10459 if ((mask|litval)!=0xff)
10460 emitcode ("anl","a,#0x%02x", mask);
10462 emitcode ("orl","a,#0x%02x", litval);
10466 if ((blen==1) && (p_type!=GPOINTER))
10468 /* Case with a bitfield length == 1 and no generic pointer
10470 if (AOP_TYPE (right) == AOP_CRY)
10471 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10474 MOVA (aopGet (right, 0, FALSE, FALSE));
10475 emitcode ("rrc","a");
10477 emitPtrByteGet (rname, p_type, FALSE);
10478 emitcode ("mov","acc.%d,c",bstr);
10483 /* Case with a bitfield length < 8 and arbitrary source
10485 MOVA (aopGet (right, 0, FALSE, FALSE));
10486 /* shift and mask source value */
10488 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10490 pushedB = pushB ();
10491 /* transfer A to B and get next byte */
10492 emitPtrByteGet (rname, p_type, TRUE);
10494 emitcode ("anl", "a,#0x%02x", mask);
10495 emitcode ("orl", "a,b");
10496 if (p_type == GPOINTER)
10497 emitcode ("pop", "b");
10503 emitPtrByteSet (rname, p_type, "a");
10507 /* Bit length is greater than 7 bits. In this case, copy */
10508 /* all except the partial byte at the end */
10509 for (rlen=blen;rlen>=8;rlen-=8)
10511 emitPtrByteSet (rname, p_type,
10512 aopGet (right, offset++, FALSE, TRUE) );
10514 emitcode ("inc", "%s", rname);
10517 /* If there was a partial byte at the end */
10520 mask = (((unsigned char) -1 << rlen) & 0xff);
10522 if (AOP_TYPE (right) == AOP_LIT)
10524 /* Case with partial byte and literal source
10526 litval = (int) ulFromVal (AOP (right)->aopu.aop_lit);
10527 litval >>= (blen-rlen);
10528 litval &= (~mask) & 0xff;
10529 emitPtrByteGet (rname, p_type, FALSE);
10530 if ((mask|litval)!=0xff)
10531 emitcode ("anl","a,#0x%02x", mask);
10533 emitcode ("orl","a,#0x%02x", litval);
10538 /* Case with partial byte and arbitrary source
10540 MOVA (aopGet (right, offset++, FALSE, FALSE));
10541 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10543 pushedB = pushB ();
10544 /* transfer A to B and get next byte */
10545 emitPtrByteGet (rname, p_type, TRUE);
10547 emitcode ("anl", "a,#0x%02x", mask);
10548 emitcode ("orl", "a,b");
10549 if (p_type == GPOINTER)
10550 emitcode ("pop", "b");
10554 emitPtrByteSet (rname, p_type, "a");
10559 /*-----------------------------------------------------------------*/
10560 /* genDataPointerSet - remat pointer to data space */
10561 /*-----------------------------------------------------------------*/
10563 genDataPointerSet (operand * right,
10567 int size, offset = 0;
10568 char *l, buffer[256];
10570 D (emitcode (";", "genDataPointerSet"));
10572 aopOp (right, ic, FALSE);
10574 l = aopGet (result, 0, FALSE, TRUE);
10576 size = max (AOP_SIZE (right), AOP_SIZE (result));
10580 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
10582 SNPRINTF (buffer, sizeof(buffer), "%s", l);
10583 emitcode ("mov", "%s,%s", buffer,
10584 aopGet (right, offset++, FALSE, FALSE));
10587 freeAsmop (right, NULL, ic, TRUE);
10588 freeAsmop (result, NULL, ic, TRUE);
10591 /*-----------------------------------------------------------------*/
10592 /* genNearPointerSet - emitcode for near pointer put */
10593 /*-----------------------------------------------------------------*/
10595 genNearPointerSet (operand * right,
10603 sym_link *retype, *letype;
10604 sym_link *ptype = operandType (result);
10606 D (emitcode (";", "genNearPointerSet"));
10608 retype = getSpec (operandType (right));
10609 letype = getSpec (ptype);
10611 aopOp (result, ic, FALSE);
10613 /* if the result is rematerializable &
10614 in data space & not a bit variable */
10615 if (AOP_TYPE (result) == AOP_IMMD &&
10616 DCL_TYPE (ptype) == POINTER &&
10617 !IS_BITVAR (retype) &&
10618 !IS_BITVAR (letype))
10620 genDataPointerSet (right, result, ic);
10624 /* if the value is already in a pointer register
10625 then don't need anything more */
10626 if (!AOP_INPREG (AOP (result)))
10628 if (IS_AOP_PREG (result))
10630 // Aha, it is a pointer, just in disguise.
10631 rname = aopGet (result, 0, FALSE, FALSE);
10634 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10635 __FILE__, __LINE__);
10640 emitcode ("mov", "a%s,%s", rname + 1, rname);
10641 rname++; // skip the '@'.
10646 /* otherwise get a free pointer register */
10647 aop = newAsmop (0);
10648 preg = getFreePtr (ic, &aop, FALSE);
10649 emitcode ("mov", "%s,%s",
10651 aopGet (result, 0, FALSE, TRUE));
10652 rname = preg->name;
10657 rname = aopGet (result, 0, FALSE, FALSE);
10660 aopOp (right, ic, FALSE);
10662 /* if bitfield then unpack the bits */
10663 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10664 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10667 /* we can just get the values */
10668 int size = AOP_SIZE (right);
10673 l = aopGet (right, offset, FALSE, TRUE);
10674 if ((*l == '@') || (strcmp (l, "acc") == 0))
10677 emitcode ("mov", "@%s,a", rname);
10680 emitcode ("mov", "@%s,%s", rname, l);
10682 emitcode ("inc", "%s", rname);
10687 /* now some housekeeping stuff */
10688 if (aop) /* we had to allocate for this iCode */
10691 aopPut (result, rname, 0);
10692 freeAsmop (NULL, aop, ic, TRUE);
10696 /* we did not allocate which means left
10697 already in a pointer register, then
10698 if size > 0 && this could be used again
10699 we have to point it back to where it
10701 if ((AOP_SIZE (right) > 1 &&
10702 !OP_SYMBOL (result)->remat &&
10703 (OP_SYMBOL (result)->liveTo > ic->seq ||
10707 int size = AOP_SIZE (right) - 1;
10709 emitcode ("dec", "%s", rname);
10716 freeAsmop (right, NULL, ic, TRUE);
10717 freeAsmop (result, NULL, ic, TRUE);
10720 /*-----------------------------------------------------------------*/
10721 /* genPagedPointerSet - emitcode for Paged pointer put */
10722 /*-----------------------------------------------------------------*/
10724 genPagedPointerSet (operand * right,
10732 sym_link *retype, *letype;
10734 D (emitcode (";", "genPagedPointerSet"));
10736 retype = getSpec (operandType (right));
10737 letype = getSpec (operandType (result));
10739 aopOp (result, ic, FALSE);
10741 /* if the value is already in a pointer register
10742 then don't need anything more */
10743 if (!AOP_INPREG (AOP (result)))
10745 if (IS_AOP_PREG (result))
10747 // Aha, it is a pointer, just in disguise.
10748 rname = aopGet (result, 0, FALSE, FALSE);
10751 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10752 __FILE__, __LINE__);
10757 emitcode ("mov", "a%s,%s", rname + 1, rname);
10758 rname++; // skip the '@'.
10763 /* otherwise get a free pointer register */
10764 aop = newAsmop (0);
10765 preg = getFreePtr (ic, &aop, FALSE);
10766 emitcode ("mov", "%s,%s",
10768 aopGet (result, 0, FALSE, TRUE));
10769 rname = preg->name;
10774 rname = aopGet (result, 0, FALSE, FALSE);
10777 aopOp (right, ic, FALSE);
10779 /* if bitfield then unpack the bits */
10780 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10781 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10784 /* we can just get the values */
10785 int size = AOP_SIZE (right);
10790 l = aopGet (right, offset, FALSE, TRUE);
10792 emitcode ("movx", "@%s,a", rname);
10794 emitcode ("inc", "%s", rname);
10799 /* now some housekeeping stuff */
10800 if (aop) /* we had to allocate for this iCode */
10803 aopPut (result, rname, 0);
10804 freeAsmop (NULL, aop, ic, TRUE);
10808 /* we did not allocate which means left
10809 already in a pointer register, then
10810 if size > 0 && this could be used again
10811 we have to point it back to where it
10813 if (AOP_SIZE (right) > 1 &&
10814 !OP_SYMBOL (result)->remat &&
10815 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth) &&
10818 int size = AOP_SIZE (right) - 1;
10820 emitcode ("dec", "%s", rname);
10827 freeAsmop (right, NULL, ic, TRUE);
10828 freeAsmop (result, NULL, ic, TRUE);
10831 /*-----------------------------------------------------------------*/
10832 /* genFarPointerSet - set value from far space */
10833 /*-----------------------------------------------------------------*/
10835 genFarPointerSet (operand * right,
10836 operand * result, iCode * ic, iCode * pi)
10839 sym_link *retype = getSpec (operandType (right));
10840 sym_link *letype = getSpec (operandType (result));
10842 D(emitcode (";", "genFarPointerSet"));
10844 aopOp (result, ic, FALSE);
10845 loadDptrFromOperand (result, FALSE);
10847 /* so dptr now contains the address */
10848 aopOp (right, ic, FALSE);
10850 /* if bit then unpack */
10851 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10852 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10855 size = AOP_SIZE (right);
10860 char *l = aopGet (right, offset++, FALSE, FALSE);
10862 emitcode ("movx", "@dptr,a");
10864 emitcode ("inc", "dptr");
10867 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10868 aopPut (result, "dpl", 0);
10869 aopPut (result, "dph", 1);
10872 freeAsmop (result, NULL, ic, TRUE);
10873 freeAsmop (right, NULL, ic, TRUE);
10876 /*-----------------------------------------------------------------*/
10877 /* genGenPointerSet - set value from generic pointer space */
10878 /*-----------------------------------------------------------------*/
10880 genGenPointerSet (operand * right,
10881 operand * result, iCode * ic, iCode * pi)
10884 sym_link *retype = getSpec (operandType (right));
10885 sym_link *letype = getSpec (operandType (result));
10887 D (emitcode (";", "genGenPointerSet"));
10889 aopOp (result, ic, FALSE);
10890 loadDptrFromOperand (result, TRUE);
10892 /* so dptr now contains the address */
10893 aopOp (right, ic, FALSE);
10895 /* if bit then unpack */
10896 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10898 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10902 size = AOP_SIZE (right);
10907 char *l = aopGet (right, offset++, FALSE, FALSE);
10909 emitcode ("lcall", "__gptrput");
10911 emitcode ("inc", "dptr");
10915 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10916 aopPut (result, "dpl", 0);
10917 aopPut (result, "dph", 1);
10920 freeAsmop (result, NULL, ic, TRUE);
10921 freeAsmop (right, NULL, ic, TRUE);
10924 /*-----------------------------------------------------------------*/
10925 /* genPointerSet - stores the value into a pointer location */
10926 /*-----------------------------------------------------------------*/
10928 genPointerSet (iCode * ic, iCode *pi)
10930 operand *right, *result;
10931 sym_link *type, *etype;
10934 D (emitcode (";", "genPointerSet"));
10936 right = IC_RIGHT (ic);
10937 result = IC_RESULT (ic);
10939 /* depending on the type of pointer we need to
10940 move it to the correct pointer register */
10941 type = operandType (result);
10942 etype = getSpec (type);
10943 /* if left is of type of pointer then it is simple */
10944 if (IS_PTR (type) && !IS_FUNC (type->next))
10946 p_type = DCL_TYPE (type);
10950 /* we have to go by the storage class */
10951 p_type = PTR_TYPE (SPEC_OCLS (etype));
10954 /* special case when cast remat */
10955 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10956 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10957 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10958 type = operandType (result);
10959 p_type = DCL_TYPE (type);
10962 /* now that we have the pointer type we assign
10963 the pointer values */
10969 genNearPointerSet (right, result, ic, pi);
10973 genPagedPointerSet (right, result, ic, pi);
10977 genFarPointerSet (right, result, ic, pi);
10981 genGenPointerSet (right, result, ic, pi);
10985 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10986 "genPointerSet: illegal pointer type");
10990 /*-----------------------------------------------------------------*/
10991 /* genIfx - generate code for Ifx statement */
10992 /*-----------------------------------------------------------------*/
10994 genIfx (iCode * ic, iCode * popIc)
10996 operand *cond = IC_COND (ic);
11000 D (emitcode (";", "genIfx"));
11002 aopOp (cond, ic, FALSE);
11004 /* get the value into acc */
11005 if (AOP_TYPE (cond) != AOP_CRY)
11012 if (AOP(cond)->aopu.aop_dir)
11013 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
11016 /* the result is now in the accumulator or a directly addressable bit */
11017 freeAsmop (cond, NULL, ic, TRUE);
11019 /* if there was something to be popped then do it */
11023 /* if the condition is a bit variable */
11025 genIfxJump(ic, dup, NULL, NULL, NULL);
11026 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
11027 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
11028 else if (isbit && !IS_ITEMP (cond))
11029 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
11031 genIfxJump (ic, "a", NULL, NULL, NULL);
11036 /*-----------------------------------------------------------------*/
11037 /* genAddrOf - generates code for address of */
11038 /*-----------------------------------------------------------------*/
11040 genAddrOf (iCode * ic)
11042 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
11045 D (emitcode (";", "genAddrOf"));
11047 aopOp (IC_RESULT (ic), ic, FALSE);
11049 /* if the operand is on the stack then we
11050 need to get the stack offset of this
11054 /* if it has an offset then we need to compute it */
11057 int stack_offset = ((sym->stack < 0) ?
11058 ((char) (sym->stack - _G.nRegsSaved)) :
11059 ((char) sym->stack)) & 0xff;
11060 if ((abs(stack_offset) == 1) &&
11061 !AOP_NEEDSACC(IC_RESULT (ic)) &&
11062 !isOperandVolatile (IC_RESULT (ic), FALSE))
11064 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
11065 if (stack_offset > 0)
11066 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
11068 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
11072 emitcode ("mov", "a,%s", SYM_BP (sym));
11073 emitcode ("add", "a,#0x%02x", stack_offset & 0xff);
11074 aopPut (IC_RESULT (ic), "a", 0);
11079 /* we can just move _bp */
11080 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
11082 /* fill the result with zero */
11083 size = AOP_SIZE (IC_RESULT (ic)) - 1;
11088 aopPut (IC_RESULT (ic), zero, offset++);
11093 /* object not on stack then we need the name */
11094 size = AOP_SIZE (IC_RESULT (ic));
11099 char s[SDCC_NAME_MAX];
11101 sprintf (s, "#(%s >> %d)",
11105 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11106 aopPut (IC_RESULT (ic), s, offset++);
11110 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11114 /*-----------------------------------------------------------------*/
11115 /* genFarFarAssign - assignment when both are in far space */
11116 /*-----------------------------------------------------------------*/
11118 genFarFarAssign (operand * result, operand * right, iCode * ic)
11120 int size = AOP_SIZE (right);
11124 D (emitcode (";", "genFarFarAssign"));
11126 /* first push the right side on to the stack */
11129 l = aopGet (right, offset++, FALSE, FALSE);
11131 emitcode ("push", "acc");
11134 freeAsmop (right, NULL, ic, FALSE);
11135 /* now assign DPTR to result */
11136 aopOp (result, ic, FALSE);
11137 size = AOP_SIZE (result);
11140 emitcode ("pop", "acc");
11141 aopPut (result, "a", --offset);
11143 freeAsmop (result, NULL, ic, FALSE);
11146 /*-----------------------------------------------------------------*/
11147 /* genAssign - generate code for assignment */
11148 /*-----------------------------------------------------------------*/
11150 genAssign (iCode * ic)
11152 operand *result, *right;
11154 unsigned long lit = 0L;
11156 D (emitcode (";", "genAssign"));
11158 result = IC_RESULT (ic);
11159 right = IC_RIGHT (ic);
11161 /* if they are the same */
11162 if (operandsEqu (result, right) &&
11163 !isOperandVolatile (result, FALSE) &&
11164 !isOperandVolatile (right, FALSE))
11167 aopOp (right, ic, FALSE);
11169 /* special case both in far space */
11170 if (AOP_TYPE (right) == AOP_DPTR &&
11171 IS_TRUE_SYMOP (result) &&
11172 isOperandInFarSpace (result))
11174 genFarFarAssign (result, right, ic);
11178 aopOp (result, ic, TRUE);
11180 /* if they are the same registers */
11181 if (sameRegs (AOP (right), AOP (result)) &&
11182 !isOperandVolatile (result, FALSE) &&
11183 !isOperandVolatile (right, FALSE))
11186 /* if the result is a bit */
11187 if (AOP_TYPE (result) == AOP_CRY)
11189 assignBit (result, right);
11193 /* bit variables done */
11195 size = AOP_SIZE (result);
11197 if (AOP_TYPE (right) == AOP_LIT)
11198 lit = ulFromVal (AOP (right)->aopu.aop_lit);
11201 (AOP_TYPE (result) != AOP_REG) &&
11202 (AOP_TYPE (right) == AOP_LIT) &&
11203 !IS_FLOAT (operandType (right)) &&
11206 while ((size) && (lit))
11209 aopGet (right, offset, FALSE, FALSE),
11215 /* And now fill the rest with zeros. */
11218 emitcode ("clr", "a");
11222 aopPut (result, "a", offset);
11231 aopGet (right, offset, FALSE, FALSE),
11238 freeAsmop (result, NULL, ic, TRUE);
11239 freeAsmop (right, NULL, ic, TRUE);
11242 /*-----------------------------------------------------------------*/
11243 /* genJumpTab - generates code for jump table */
11244 /*-----------------------------------------------------------------*/
11246 genJumpTab (iCode * ic)
11248 symbol *jtab,*jtablo,*jtabhi;
11250 unsigned int count;
11252 D (emitcode (";", "genJumpTab"));
11254 count = elementsInSet( IC_JTLABELS (ic) );
11258 /* this algorithm needs 9 cycles and 7 + 3*n bytes
11259 if the switch argument is in a register.
11260 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
11261 /* Peephole may not convert ljmp to sjmp or ret
11262 labelIsReturnOnly & labelInRange must check
11263 currPl->ic->op != JUMPTABLE */
11264 aopOp (IC_JTCOND (ic), ic, FALSE);
11265 /* get the condition into accumulator */
11266 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11268 /* multiply by three */
11269 if (aopGetUsesAcc (IC_JTCOND (ic), 0))
11271 emitcode ("mov", "b,#3");
11272 emitcode ("mul", "ab");
11276 emitcode ("add", "a,acc");
11277 emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
11279 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11281 jtab = newiTempLabel (NULL);
11282 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
11283 emitcode ("jmp", "@a+dptr");
11285 /* now generate the jump labels */
11286 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11287 jtab = setNextItem (IC_JTLABELS (ic)))
11288 emitcode ("ljmp", "%05d$", jtab->key + 100);
11292 /* this algorithm needs 14 cycles and 13 + 2*n bytes
11293 if the switch argument is in a register.
11294 For n>6 this algorithm may be more compact */
11295 jtablo = newiTempLabel (NULL);
11296 jtabhi = newiTempLabel (NULL);
11298 /* get the condition into accumulator.
11299 Using b as temporary storage, if register push/pop is needed */
11300 aopOp (IC_JTCOND (ic), ic, FALSE);
11301 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11302 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
11303 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
11305 // (MB) what if B is in use???
11306 wassertl(!BINUSE, "B was in use");
11307 emitcode ("mov", "b,%s", l);
11310 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11314 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
11315 emitcode ("movc", "a,@a+pc");
11316 emitcode ("push", "acc");
11319 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
11320 emitcode ("movc", "a,@a+pc");
11321 emitcode ("push", "acc");
11325 /* this scales up to n<=255, but needs two more bytes
11326 and changes dptr */
11327 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
11328 emitcode ("movc", "a,@a+dptr");
11329 emitcode ("push", "acc");
11332 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
11333 emitcode ("movc", "a,@a+dptr");
11334 emitcode ("push", "acc");
11337 emitcode ("ret", "");
11339 /* now generate jump table, LSB */
11340 emitLabel (jtablo);
11341 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11342 jtab = setNextItem (IC_JTLABELS (ic)))
11343 emitcode (".db", "%05d$", jtab->key + 100);
11345 /* now generate jump table, MSB */
11346 emitLabel (jtabhi);
11347 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11348 jtab = setNextItem (IC_JTLABELS (ic)))
11349 emitcode (".db", "%05d$>>8", jtab->key + 100);
11353 /*-----------------------------------------------------------------*/
11354 /* genCast - gen code for casting */
11355 /*-----------------------------------------------------------------*/
11357 genCast (iCode * ic)
11359 operand *result = IC_RESULT (ic);
11360 sym_link *ctype = operandType (IC_LEFT (ic));
11361 sym_link *rtype = operandType (IC_RIGHT (ic));
11362 operand *right = IC_RIGHT (ic);
11365 D (emitcode (";", "genCast"));
11367 /* if they are equivalent then do nothing */
11368 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11371 aopOp (right, ic, FALSE);
11372 aopOp (result, ic, FALSE);
11374 /* if the result is a bit (and not a bitfield) */
11375 if (IS_BIT (OP_SYMBOL (result)->type))
11377 assignBit (result, right);
11381 /* if they are the same size : or less */
11382 if (AOP_SIZE (result) <= AOP_SIZE (right))
11385 /* if they are in the same place */
11386 if (sameRegs (AOP (right), AOP (result)))
11389 /* if they in different places then copy */
11390 size = AOP_SIZE (result);
11395 aopGet (right, offset, FALSE, FALSE),
11402 /* if the result is of type pointer */
11403 if (IS_PTR (ctype))
11407 sym_link *type = operandType (right);
11408 sym_link *etype = getSpec (type);
11410 /* pointer to generic pointer */
11411 if (IS_GENPTR (ctype))
11415 p_type = DCL_TYPE (type);
11419 if (SPEC_SCLS(etype)==S_REGISTER) {
11420 // let's assume it is a generic pointer
11423 /* we have to go by the storage class */
11424 p_type = PTR_TYPE (SPEC_OCLS (etype));
11428 /* the first two bytes are known */
11429 size = GPTRSIZE - 1;
11434 aopGet (right, offset, FALSE, FALSE),
11438 /* the last byte depending on type */
11440 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11445 // pointerTypeToGPByte will have bitched.
11449 sprintf(gpValStr, "#0x%x", gpVal);
11450 aopPut (result, gpValStr, GPTRSIZE - 1);
11455 /* just copy the pointers */
11456 size = AOP_SIZE (result);
11461 aopGet (right, offset, FALSE, FALSE),
11468 /* so we now know that the size of destination is greater
11469 than the size of the source */
11470 /* we move to result for the size of source */
11471 size = AOP_SIZE (right);
11476 aopGet (right, offset, FALSE, FALSE),
11481 /* now depending on the sign of the source && destination */
11482 size = AOP_SIZE (result) - AOP_SIZE (right);
11483 /* if unsigned or not an integral type */
11484 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11487 aopPut (result, zero, offset++);
11491 /* we need to extend the sign :{ */
11492 char *l = aopGet (right, AOP_SIZE (right) - 1,
11495 emitcode ("rlc", "a");
11496 emitcode ("subb", "a,acc");
11498 aopPut (result, "a", offset++);
11501 /* we are done hurray !!!! */
11504 freeAsmop (result, NULL, ic, TRUE);
11505 freeAsmop (right, NULL, ic, TRUE);
11508 /*-----------------------------------------------------------------*/
11509 /* genDjnz - generate decrement & jump if not zero instrucion */
11510 /*-----------------------------------------------------------------*/
11512 genDjnz (iCode * ic, iCode * ifx)
11514 symbol *lbl, *lbl1;
11518 /* if the if condition has a false label
11519 then we cannot save */
11520 if (IC_FALSE (ifx))
11523 /* if the minus is not of the form a = a - 1 */
11524 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11525 !IS_OP_LITERAL (IC_RIGHT (ic)))
11528 if (operandLitValue (IC_RIGHT (ic)) != 1)
11531 /* if the size of this greater than one then no
11533 if (getSize (operandType (IC_RESULT (ic))) > 1)
11536 /* otherwise we can save BIG */
11538 D (emitcode (";", "genDjnz"));
11540 lbl = newiTempLabel (NULL);
11541 lbl1 = newiTempLabel (NULL);
11543 aopOp (IC_RESULT (ic), ic, FALSE);
11545 if (AOP_NEEDSACC(IC_RESULT(ic)))
11547 /* If the result is accessed indirectly via
11548 * the accumulator, we must explicitly write
11549 * it back after the decrement.
11551 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11553 if (strcmp(rByte, "a"))
11555 /* Something is hopelessly wrong */
11556 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11557 __FILE__, __LINE__);
11558 /* We can just give up; the generated code will be inefficient,
11559 * but what the hey.
11561 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11564 emitcode ("dec", "%s", rByte);
11565 aopPut (IC_RESULT (ic), rByte, 0);
11566 emitcode ("jnz", "%05d$", lbl->key + 100);
11568 else if (IS_AOP_PREG (IC_RESULT (ic)))
11570 emitcode ("dec", "%s",
11571 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11572 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11573 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11574 ifx->generated = 1;
11575 emitcode ("jnz", "%05d$", lbl->key + 100);
11579 emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11582 emitcode ("sjmp", "%05d$", lbl1->key + 100);
11584 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11587 if (!ifx->generated)
11588 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11589 ifx->generated = 1;
11593 /*-----------------------------------------------------------------*/
11594 /* genReceive - generate code for a receive iCode */
11595 /*-----------------------------------------------------------------*/
11597 genReceive (iCode * ic)
11599 int size = getSize (operandType (IC_RESULT (ic)));
11602 D (emitcode (";", "genReceive"));
11604 if (ic->argreg == 1)
11605 { /* first parameter */
11606 if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11607 isOperandInPagedSpace (IC_RESULT (ic))) &&
11608 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11609 IS_TRUE_SYMOP (IC_RESULT (ic))))
11612 int receivingA = 0;
11615 for (offset = 0; offset<size; offset++)
11616 if (!strcmp (fReturn[offset], "a"))
11621 if (size==1 || getTempRegs(tempRegs, size-1, ic))
11623 for (offset = size-1; offset>0; offset--)
11624 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11625 emitcode("mov","a,%s", fReturn[0]);
11627 aopOp (IC_RESULT (ic), ic, FALSE);
11629 aopPut (IC_RESULT (ic), "a", offset);
11630 for (offset = 1; offset<size; offset++)
11631 aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset);
11637 if (getTempRegs(tempRegs, size, ic))
11639 for (offset = 0; offset<size; offset++)
11640 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11641 aopOp (IC_RESULT (ic), ic, FALSE);
11642 for (offset = 0; offset<size; offset++)
11643 aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset);
11648 offset = fReturnSizeMCS51 - size;
11651 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11652 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11655 aopOp (IC_RESULT (ic), ic, FALSE);
11656 size = AOP_SIZE (IC_RESULT (ic));
11660 emitcode ("pop", "acc");
11661 aopPut (IC_RESULT (ic), "a", offset++);
11667 aopOp (IC_RESULT (ic), ic, FALSE);
11669 assignResultValue (IC_RESULT (ic), NULL);
11672 else if (ic->argreg > 12)
11673 { /* bit parameters */
11674 regs *reg = OP_SYMBOL (IC_RESULT (ic))->regs[0];
11677 if (!reg || reg->rIdx != ic->argreg-5)
11679 aopOp (IC_RESULT (ic), ic, FALSE);
11680 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11681 outBitC(IC_RESULT (ic));
11685 { /* other parameters */
11687 aopOp (IC_RESULT (ic), ic, FALSE);
11688 rb1off = ic->argreg;
11691 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
11696 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11699 /*-----------------------------------------------------------------*/
11700 /* genDummyRead - generate code for dummy read of volatiles */
11701 /*-----------------------------------------------------------------*/
11703 genDummyRead (iCode * ic)
11708 D (emitcode(";", "genDummyRead"));
11710 op = IC_RIGHT (ic);
11711 if (op && IS_SYMOP (op))
11713 aopOp (op, ic, FALSE);
11715 /* if the result is a bit */
11716 if (AOP_TYPE (op) == AOP_CRY)
11717 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11720 /* bit variables done */
11722 size = AOP_SIZE (op);
11726 MOVA (aopGet (op, offset, FALSE, FALSE));
11731 freeAsmop (op, NULL, ic, TRUE);
11735 if (op && IS_SYMOP (op))
11737 aopOp (op, ic, FALSE);
11739 /* if the result is a bit */
11740 if (AOP_TYPE (op) == AOP_CRY)
11741 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11744 /* bit variables done */
11746 size = AOP_SIZE (op);
11750 MOVA (aopGet (op, offset, FALSE, FALSE));
11755 freeAsmop (op, NULL, ic, TRUE);
11759 /*-----------------------------------------------------------------*/
11760 /* genCritical - generate code for start of a critical sequence */
11761 /*-----------------------------------------------------------------*/
11763 genCritical (iCode *ic)
11765 symbol *tlbl = newiTempLabel (NULL);
11767 D (emitcode(";", "genCritical"));
11769 if (IC_RESULT (ic))
11771 aopOp (IC_RESULT (ic), ic, TRUE);
11772 aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
11773 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11774 aopPut (IC_RESULT (ic), zero, 0);
11776 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11780 emitcode ("setb", "c");
11781 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11782 emitcode ("clr", "c");
11784 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11788 /*-----------------------------------------------------------------*/
11789 /* genEndCritical - generate code for end of a critical sequence */
11790 /*-----------------------------------------------------------------*/
11792 genEndCritical (iCode *ic)
11794 D(emitcode(";", "genEndCritical"));
11798 aopOp (IC_RIGHT (ic), ic, FALSE);
11799 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11801 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11802 emitcode ("mov", "ea,c");
11806 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11807 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11808 emitcode ("rrc", "a");
11809 emitcode ("mov", "ea,c");
11811 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11815 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11816 emitcode ("mov", "ea,c");
11820 /*-----------------------------------------------------------------*/
11821 /* gen51Code - generate code for 8051 based controllers */
11822 /*-----------------------------------------------------------------*/
11824 gen51Code (iCode * lic)
11828 /* int cseq = 0; */
11830 _G.currentFunc = NULL;
11831 lineHead = lineCurr = NULL;
11833 /* print the allocation information */
11834 if (allocInfo && currFunc)
11835 printAllocInfo (currFunc, codeOutBuf);
11836 /* if debug information required */
11837 if (options.debug && currFunc)
11839 debugFile->writeFunction (currFunc, lic);
11841 /* stack pointer name */
11842 if (options.useXstack)
11848 for (ic = lic; ic; ic = ic->next)
11850 _G.current_iCode = ic;
11852 if (ic->lineno && cln != ic->lineno)
11856 debugFile->writeCLine (ic);
11858 if (!options.noCcodeInAsm) {
11859 emitcode (";", "%s:%d: %s", ic->filename, ic->lineno,
11860 printCLine(ic->filename, ic->lineno));
11865 if (ic->seqPoint && ic->seqPoint != cseq)
11867 emitcode (";", "sequence point %d", ic->seqPoint);
11868 cseq = ic->seqPoint;
11871 if (options.iCodeInAsm) {
11872 char regsInUse[80];
11877 for (i=0; i<8; i++) {
11878 sprintf (®sInUse[i],
11879 "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11882 strcpy (regsInUse, "--------");
11883 for (i=0; i < 8; i++) {
11884 if (bitVectBitValue (ic->rMask, i))
11886 int offset = regs8051[i].offset;
11887 regsInUse[offset] = offset + '0'; /* show rMask */
11891 iLine = printILine(ic);
11892 emitcode(";", "[%s] ic:%d: %s", regsInUse, ic->seq, iLine);
11895 /* if the result is marked as
11896 spilt and rematerializable or code for
11897 this has already been generated then
11899 if (resultRemat (ic) || ic->generated)
11902 /* depending on the operation */
11922 /* IPOP happens only when trying to restore a
11923 spilt live range, if there is an ifx statement
11924 following this pop then the if statement might
11925 be using some of the registers being popped which
11926 would destory the contents of the register so
11927 we need to check for this condition and handle it */
11929 ic->next->op == IFX &&
11930 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11931 genIfx (ic->next, ic);
11949 genEndFunction (ic);
11969 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11986 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11990 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11997 /* note these two are xlated by algebraic equivalence
11998 in decorateType() in SDCCast.c */
11999 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12000 "got '>=' or '<=' shouldn't have come here");
12004 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
12016 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
12020 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
12024 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
12060 genRightShift (ic);
12063 case GET_VALUE_AT_ADDRESS:
12065 hasInc (IC_LEFT (ic), ic,
12066 getSize (operandType (IC_RESULT (ic)))),
12067 ifxForOp (IC_RESULT (ic), ic) );
12071 if (POINTER_SET (ic))
12073 hasInc (IC_RESULT (ic), ic,
12074 getSize (operandType (IC_RIGHT (ic)))));
12100 addSet (&_G.sendSet, ic);
12103 case DUMMY_READ_VOLATILE:
12112 genEndCritical (ic);
12124 _G.current_iCode = NULL;
12126 /* now we are ready to call the
12127 peep hole optimizer */
12128 if (!options.nopeep)
12129 peepHole (&lineHead);
12131 /* now do the actual printing */
12132 printLine (lineHead, codeOutBuf);