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.noGenComments) {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)));
193 lineCurr->isInline = _G.inLine;
194 lineCurr->isDebug = _G.debugLine;
195 lineCurr->ic = _G.current_iCode;
196 lineCurr->isComment = (*lbp==';');
203 emitLabel (symbol *tlbl)
205 emitcode ("", "%05d$:", tlbl->key + 100);
206 lineCurr->isLabel = 1;
209 /*-----------------------------------------------------------------*/
210 /* mcs51_emitDebuggerSymbol - associate the current code location */
211 /* with a debugger symbol */
212 /*-----------------------------------------------------------------*/
214 mcs51_emitDebuggerSymbol (char * debugSym)
217 emitcode ("", "%s ==.", debugSym);
221 /*-----------------------------------------------------------------*/
222 /* mova - moves specified value into accumulator */
223 /*-----------------------------------------------------------------*/
227 /* do some early peephole optimization */
228 if (!strncmp(x, "a", 2) || !strncmp(x, "acc", 4))
231 /* if it is a literal mov try to get it cheaper */
236 emitcode("mov", "a,%s", x);
239 /*-----------------------------------------------------------------*/
240 /* movb - moves specified value into register b */
241 /*-----------------------------------------------------------------*/
245 /* do some early peephole optimization */
246 if (!strncmp(x, "b", 2))
249 /* if it is a literal mov try to get it cheaper */
252 emitcode("mov","b,%s", rtrackGetLit(x));
256 emitcode("mov","b,%s", x);
259 /*-----------------------------------------------------------------*/
260 /* pushB - saves register B if necessary */
261 /*-----------------------------------------------------------------*/
265 bool pushedB = FALSE;
269 emitcode ("push", "b");
270 // printf("B was in use !\n");
280 /*-----------------------------------------------------------------*/
281 /* popB - restores value of register B if necessary */
282 /*-----------------------------------------------------------------*/
288 emitcode ("pop", "b");
296 /*-----------------------------------------------------------------*/
297 /* pushReg - saves register */
298 /*-----------------------------------------------------------------*/
300 pushReg (int index, bool bits_pushed)
302 regs * reg = REG_WITH_INDEX (index);
303 if (reg->type == REG_BIT)
306 emitcode ("push", "%s", reg->base);
310 emitcode ("push", "%s", reg->dname);
314 /*-----------------------------------------------------------------*/
315 /* popReg - restores register */
316 /*-----------------------------------------------------------------*/
318 popReg (int index, bool bits_popped)
320 regs * reg = REG_WITH_INDEX (index);
321 if (reg->type == REG_BIT)
324 emitcode ("pop", "%s", reg->base);
328 emitcode ("pop", "%s", reg->dname);
332 /*-----------------------------------------------------------------*/
333 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
334 /*-----------------------------------------------------------------*/
336 getFreePtr (iCode * ic, asmop ** aopp, bool result)
341 /* the logic: if r0 & r1 used in the instruction
342 then we are in trouble otherwise */
344 /* first check if r0 & r1 are used by this
345 instruction, in which case we are in trouble */
346 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
347 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
352 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
353 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
355 /* if no usage of r0 then return it */
358 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
359 (*aopp)->type = AOP_R0;
361 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
364 /* if no usage of r1 then return it */
367 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
368 (*aopp)->type = AOP_R1;
370 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R1_IDX);
373 /* now we know they both have usage */
374 /* if r0 not used in this instruction */
377 /* push it if not already pushed */
380 MOVB (REG_WITH_INDEX (R0_IDX)->dname);
383 else if (!_G.r0Pushed)
385 emitcode ("push", "%s",
386 REG_WITH_INDEX (R0_IDX)->dname);
390 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
391 (*aopp)->type = AOP_R0;
393 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
396 /* if r1 not used then */
400 /* push it if not already pushed */
403 MOVB (REG_WITH_INDEX (R1_IDX)->dname);
406 else if (!_G.r1Pushed)
408 emitcode ("push", "%s",
409 REG_WITH_INDEX (R1_IDX)->dname);
413 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
414 (*aopp)->type = AOP_R1;
415 return REG_WITH_INDEX (R1_IDX);
419 /* I said end of world, but not quite end of world yet */
420 /* if this is a result then we can push it on the stack */
423 (*aopp)->type = AOP_STK;
426 /* in the case that result AND left AND right needs a pointer reg
427 we can safely use the result's */
428 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX))
430 (*aopp)->type = AOP_R0;
431 return REG_WITH_INDEX (R0_IDX);
433 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX))
435 (*aopp)->type = AOP_R1;
436 return REG_WITH_INDEX (R1_IDX);
439 /* now this is REALLY the end of the world */
440 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
441 "getFreePtr should never reach here");
446 /*-----------------------------------------------------------------*/
447 /* getTempRegs - initialize an array of pointers to GPR registers */
448 /* that are not in use. Returns 1 if the requested */
449 /* number of registers were available, 0 otherwise. */
450 /*-----------------------------------------------------------------*/
452 getTempRegs(regs **tempRegs, int size, iCode *ic)
459 ic = _G.current_iCode;
465 freeRegs = newBitVect(8);
466 bitVectSetBit (freeRegs, R2_IDX);
467 bitVectSetBit (freeRegs, R3_IDX);
468 bitVectSetBit (freeRegs, R4_IDX);
469 bitVectSetBit (freeRegs, R5_IDX);
470 bitVectSetBit (freeRegs, R6_IDX);
471 bitVectSetBit (freeRegs, R7_IDX);
473 if (IFFUNC_CALLEESAVES(_G.currentFunc->type))
475 bitVect * newfreeRegs;
476 newfreeRegs = bitVectIntersect (freeRegs, _G.currentFunc->regsUsed);
477 freeBitVect(freeRegs);
478 freeRegs = newfreeRegs;
480 freeRegs = bitVectCplAnd (freeRegs, ic->rMask);
483 for (i=0; i<freeRegs->size; i++)
485 if (bitVectBitValue(freeRegs,i))
486 tempRegs[offset++] = REG_WITH_INDEX(i);
489 freeBitVect(freeRegs);
494 freeBitVect(freeRegs);
499 /*-----------------------------------------------------------------*/
500 /* newAsmop - creates a new asmOp */
501 /*-----------------------------------------------------------------*/
503 newAsmop (short type)
507 aop = Safe_calloc (1, sizeof (asmop));
513 /*-----------------------------------------------------------------*/
514 /* pointerCode - returns the code for a pointer type */
515 /*-----------------------------------------------------------------*/
517 pointerCode (sym_link * etype)
520 return PTR_TYPE (SPEC_OCLS (etype));
524 /*-----------------------------------------------------------------*/
525 /* leftRightUseAcc - returns size of accumulator use by operands */
526 /*-----------------------------------------------------------------*/
528 leftRightUseAcc(iCode *ic)
537 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
538 "null iCode pointer");
545 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
548 size = getSize (OP_SYMBOL (op)->type);
553 else if (ic->op == JUMPTABLE)
556 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
559 size = getSize (OP_SYMBOL (op)->type);
567 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
570 size = getSize (OP_SYMBOL (op)->type);
575 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
578 size = getSize (OP_SYMBOL (op)->type);
590 /*-----------------------------------------------------------------*/
591 /* aopForSym - for a true symbol */
592 /*-----------------------------------------------------------------*/
594 aopForSym (iCode * ic, symbol * sym, bool result)
598 bool accuse = leftRightUseAcc (ic) || _G.accInUse;
600 wassertl (ic != NULL, "Got a null iCode");
601 wassertl (sym != NULL, "Got a null symbol");
603 space = SPEC_OCLS (sym->etype);
605 /* if already has one */
608 sym->aop->allocated++;
612 /* assign depending on the storage class */
613 /* if it is on the stack or indirectly addressable */
614 /* space we need to assign either r0 or r1 to it */
615 if (sym->onStack || sym->iaccess)
617 sym->aop = aop = newAsmop (0);
618 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
619 aop->size = getSize (sym->type);
621 /* now assign the address of the variable to
622 the pointer register */
623 if (aop->type != AOP_STK)
627 signed char offset = ((sym->stack < 0) ?
628 ((signed char) (sym->stack - _G.nRegsSaved)) :
629 ((signed char) sym->stack)) & 0xff;
631 if ((abs(offset) <= 3) ||
632 (accuse && (abs(offset) <= 7)))
634 emitcode ("mov", "%s,%s",
635 aop->aopu.aop_ptr->name, SYM_BP (sym));
638 emitcode ("dec", aop->aopu.aop_ptr->name);
643 emitcode ("inc", aop->aopu.aop_ptr->name);
650 emitcode ("push", "acc");
651 emitcode ("mov", "a,%s", SYM_BP (sym));
652 emitcode ("add", "a,#0x%02x", offset & 0xff);
653 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
655 emitcode ("pop", "acc");
660 emitcode ("mov", "%s,#%s",
661 aop->aopu.aop_ptr->name,
664 aop->paged = space->paged;
667 aop->aopu.aop_stk = sym->stack;
671 /* if in bit space */
672 if (IN_BITSPACE (space))
674 sym->aop = aop = newAsmop (AOP_CRY);
675 aop->aopu.aop_dir = sym->rname;
676 aop->size = getSize (sym->type);
679 /* if it is in direct space */
680 if (IN_DIRSPACE (space))
682 //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
683 //printTypeChainRaw(sym->type, NULL);
684 //printf("space = %s\n", space ? space->sname : "NULL");
685 sym->aop = aop = newAsmop (AOP_DIR);
686 aop->aopu.aop_dir = sym->rname;
687 aop->size = getSize (sym->type);
691 /* special case for a function */
692 if (IS_FUNC (sym->type))
694 sym->aop = aop = newAsmop (AOP_IMMD);
695 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
696 aop->size = getSize (sym->type);
700 /* only remaining is far space */
701 /* in which case DPTR gets the address */
702 sym->aop = aop = newAsmop (AOP_DPTR);
703 emitcode ("mov", "dptr,#%s", sym->rname);
704 aop->size = getSize (sym->type);
706 /* if it is in code space */
707 if (IN_CODESPACE (space))
713 /*-----------------------------------------------------------------*/
714 /* aopForRemat - rematerialzes an object */
715 /*-----------------------------------------------------------------*/
717 aopForRemat (symbol * sym)
719 iCode *ic = sym->rematiCode;
720 asmop *aop = newAsmop (AOP_IMMD);
727 val += (int) operandLitValue (IC_RIGHT (ic));
728 else if (ic->op == '-')
729 val -= (int) operandLitValue (IC_RIGHT (ic));
730 else if (IS_CAST_ICODE(ic)) {
731 sym_link *from_type = operandType(IC_RIGHT(ic));
732 aop->aopu.aop_immd.from_cast_remat = 1;
733 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
734 ptr_type = pointerTypeToGPByte (DCL_TYPE(from_type), NULL, NULL);
738 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
743 SNPRINTF (buffer, sizeof(buffer),
745 OP_SYMBOL (IC_LEFT (ic))->rname,
746 val >= 0 ? '+' : '-',
751 strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
754 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
755 /* set immd2 field if required */
756 if (aop->aopu.aop_immd.from_cast_remat)
758 SNPRINTF (buffer, sizeof(buffer), "#0x%02x", ptr_type);
759 aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
765 /*-----------------------------------------------------------------*/
766 /* regsInCommon - two operands have some registers in common */
767 /*-----------------------------------------------------------------*/
769 regsInCommon (operand * op1, operand * op2)
774 /* if they have registers in common */
775 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
778 sym1 = OP_SYMBOL (op1);
779 sym2 = OP_SYMBOL (op2);
781 if (sym1->nRegs == 0 || sym2->nRegs == 0)
784 for (i = 0; i < sym1->nRegs; i++)
790 for (j = 0; j < sym2->nRegs; j++)
795 if (sym2->regs[j] == sym1->regs[i])
803 /*-----------------------------------------------------------------*/
804 /* operandsEqu - equivalent */
805 /*-----------------------------------------------------------------*/
807 operandsEqu (operand * op1, operand * op2)
811 /* if they're not symbols */
812 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
815 sym1 = OP_SYMBOL (op1);
816 sym2 = OP_SYMBOL (op2);
818 /* if both are itemps & one is spilt
819 and the other is not then false */
820 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
821 sym1->isspilt != sym2->isspilt)
824 /* if they are the same */
828 /* if they have the same rname */
829 if (sym1->rname[0] && sym2->rname[0] &&
830 strcmp (sym1->rname, sym2->rname) == 0 &&
831 !(IS_PARM (op2) && IS_ITEMP (op1)))
834 /* if left is a tmp & right is not */
835 if (IS_ITEMP (op1) &&
838 (sym1->usl.spillLoc == sym2))
841 if (IS_ITEMP (op2) &&
845 (sym2->usl.spillLoc == sym1))
851 /*-----------------------------------------------------------------*/
852 /* sameByte - two asmops have the same address at given offsets */
853 /*-----------------------------------------------------------------*/
855 sameByte (asmop * aop1, int off1, asmop * aop2, int off2)
857 if (aop1 == aop2 && off1 == off2)
860 if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
863 if (aop1->type != aop2->type)
866 if (aop1->aopu.aop_reg[off1] != aop2->aopu.aop_reg[off2])
872 /*-----------------------------------------------------------------*/
873 /* sameRegs - two asmops have the same registers */
874 /*-----------------------------------------------------------------*/
876 sameRegs (asmop * aop1, asmop * aop2)
883 if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
886 if (aop1->type != aop2->type)
889 if (aop1->size != aop2->size)
892 for (i = 0; i < aop1->size; i++)
893 if (aop1->aopu.aop_reg[i] != aop2->aopu.aop_reg[i])
899 /*-----------------------------------------------------------------*/
900 /* aopOp - allocates an asmop for an operand : */
901 /*-----------------------------------------------------------------*/
903 aopOp (operand * op, iCode * ic, bool result)
912 /* if this a literal */
913 if (IS_OP_LITERAL (op))
915 op->aop = aop = newAsmop (AOP_LIT);
916 aop->aopu.aop_lit = op->operand.valOperand;
917 aop->size = getSize (operandType (op));
921 /* if already has a asmop then continue */
924 op->aop->allocated++;
928 /* if the underlying symbol has a aop */
929 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
931 op->aop = OP_SYMBOL (op)->aop;
932 op->aop->allocated++;
936 /* if this is a true symbol */
937 if (IS_TRUE_SYMOP (op))
939 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
943 /* this is a temporary : this has
949 e) can be a return use only */
951 sym = OP_SYMBOL (op);
953 /* if the type is a conditional */
954 if (sym->regType == REG_CND)
956 sym->aop = op->aop = aop = newAsmop (AOP_CRY);
961 /* if it is spilt then two situations
963 b) has a spill location */
964 if (sym->isspilt || sym->nRegs == 0)
967 /* rematerialize it NOW */
970 sym->aop = op->aop = aop = aopForRemat (sym);
971 aop->size = getSize (sym->type);
978 sym->aop = op->aop = aop = newAsmop (AOP_ACC);
979 aop->size = getSize (sym->type);
980 for (i = 0; i < 2; i++)
981 aop->aopu.aop_str[i] = accUse[i];
989 sym->aop = op->aop = aop = newAsmop (AOP_STR);
990 aop->size = getSize (sym->type);
991 for (i = 0; i < fReturnSizeMCS51; i++)
992 aop->aopu.aop_str[i] = fReturn[i];
996 if (sym->usl.spillLoc)
998 asmop *oldAsmOp = NULL;
1000 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1002 /* force a new aop if sizes differ */
1003 oldAsmOp = sym->usl.spillLoc->aop;
1004 sym->usl.spillLoc->aop = NULL;
1006 sym->aop = op->aop = aop =
1007 aopForSym (ic, sym->usl.spillLoc, result);
1008 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1010 /* Don't reuse the new aop, go with the last one */
1011 sym->usl.spillLoc->aop = oldAsmOp;
1013 aop->size = getSize (sym->type);
1017 /* else must be a dummy iTemp */
1018 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1019 aop->size = getSize (sym->type);
1023 /* if the type is a bit register */
1024 if (sym->regType == REG_BIT)
1026 sym->aop = op->aop = aop = newAsmop (AOP_CRY);
1027 aop->size = sym->nRegs;//1???
1028 aop->aopu.aop_reg[0] = sym->regs[0];
1029 aop->aopu.aop_dir = sym->regs[0]->name;
1033 /* must be in a register */
1034 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1035 aop->size = sym->nRegs;
1036 for (i = 0; i < sym->nRegs; i++)
1037 aop->aopu.aop_reg[i] = sym->regs[i];
1040 /*-----------------------------------------------------------------*/
1041 /* freeAsmop - free up the asmop given to an operand */
1042 /*----------------------------------------------------------------*/
1044 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1061 /* depending on the asmop type only three cases need work
1062 AOP_R0, AOP_R1 & AOP_STK */
1068 emitcode ("mov", "r0,b");
1071 else if (_G.r0Pushed)
1075 emitcode ("pop", "ar0");
1079 bitVectUnSetBit (ic->rUsed, R0_IDX);
1085 emitcode ("mov", "r1,b");
1088 else if (_G.r1Pushed)
1092 emitcode ("pop", "ar1");
1096 bitVectUnSetBit (ic->rUsed, R1_IDX);
1102 int stk = aop->aopu.aop_stk + aop->size - 1;
1103 bitVectUnSetBit (ic->rUsed, R0_IDX);
1104 bitVectUnSetBit (ic->rUsed, R1_IDX);
1106 getFreePtr (ic, &aop, FALSE);
1110 emitcode ("mov", "a,_bp");
1111 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1112 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1116 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1121 emitcode ("pop", "acc");
1122 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1125 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1128 freeAsmop (op, NULL, ic, TRUE);
1131 emitcode ("pop", "ar1");
1136 emitcode ("pop", "ar0");
1144 /* all other cases just dealloc */
1150 OP_SYMBOL (op)->aop = NULL;
1151 /* if the symbol has a spill */
1153 SPIL_LOC (op)->aop = NULL;
1158 /*------------------------------------------------------------------*/
1159 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
1160 /* pop r0 or r1 off stack if pushed */
1161 /*------------------------------------------------------------------*/
1163 freeForBranchAsmop (operand * op)
1175 if (!aop->allocated)
1183 emitcode ("mov", "r0,b");
1185 else if (_G.r0Pushed)
1187 emitcode ("pop", "ar0");
1194 emitcode ("mov", "r1,b");
1196 else if (_G.r1Pushed)
1198 emitcode ("pop", "ar1");
1205 int stk = aop->aopu.aop_stk + aop->size - 1;
1207 emitcode ("mov", "b,r0");
1210 emitcode ("mov", "a,_bp");
1211 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1212 emitcode ("mov", "r0,a");
1216 emitcode ("mov", "r0,_bp");
1221 emitcode ("pop", "acc");
1222 emitcode ("mov", "@r0,a");
1225 emitcode ("dec", "r0");
1227 emitcode ("mov", "r0,b");
1233 /*-----------------------------------------------------------------*/
1234 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
1235 /* clobber the accumulator */
1236 /*-----------------------------------------------------------------*/
1238 aopGetUsesAcc (operand * oper, int offset)
1240 asmop * aop = AOP (oper);
1242 if (offset > (aop->size - 1))
1260 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1271 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1277 /* Error case --- will have been caught already */
1283 /*-------------------------------------------------------------------*/
1284 /* aopGet - for fetching value of the aop */
1285 /*-------------------------------------------------------------------*/
1287 aopGet (operand * oper, int offset, bool bit16, bool dname)
1289 asmop * aop = AOP (oper);
1291 /* offset is greater than
1293 if (offset > (aop->size - 1) &&
1294 aop->type != AOP_LIT)
1297 /* depending on type */
1305 /* if we need to increment it */
1306 while (offset > aop->coff)
1308 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1312 while (offset < aop->coff)
1314 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1321 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1322 return (dname ? "acc" : "a");
1324 SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1325 return Safe_strdup(buffer);
1328 if (aop->code && aop->coff==0 && offset>=1) {
1329 emitcode ("mov", "a,#0x%02x", offset);
1330 emitcode ("movc", "a,@a+dptr");
1331 return (dname ? "acc" : "a");
1334 while (offset > aop->coff)
1336 emitcode ("inc", "dptr");
1340 while (offset < aop->coff)
1342 emitcode ("lcall", "__decdptr");
1349 emitcode ("clr", "a");
1350 emitcode ("movc", "a,@a+dptr");
1354 emitcode ("movx", "a,@dptr");
1356 return (dname ? "acc" : "a");
1359 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1361 SNPRINTF(buffer, sizeof(buffer),
1362 "%s",aop->aopu.aop_immd.aop_immd2);
1366 SNPRINTF(buffer, sizeof(buffer),
1367 "#%s", aop->aopu.aop_immd.aop_immd1);
1371 SNPRINTF (buffer, sizeof(buffer),
1373 aop->aopu.aop_immd.aop_immd1,
1378 SNPRINTF (buffer, sizeof(buffer),
1380 aop->aopu.aop_immd.aop_immd1);
1382 return Safe_strdup(buffer);
1385 if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
1387 SNPRINTF (buffer, sizeof(buffer),
1389 aop->aopu.aop_dir, offset * 8);
1393 SNPRINTF (buffer, sizeof(buffer),
1400 SNPRINTF (buffer, sizeof(buffer),
1405 return Safe_strdup(buffer);
1409 return aop->aopu.aop_reg[offset]->dname;
1411 return aop->aopu.aop_reg[offset]->name;
1414 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1415 emitcode ("clr", "a");
1416 emitcode ("rlc", "a");
1417 return (dname ? "acc" : "a");
1420 if (!offset && dname)
1422 return aop->aopu.aop_str[offset];
1425 return aopLiteral (aop->aopu.aop_lit, offset);
1429 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1433 return aop->aopu.aop_str[offset];
1437 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1438 "aopget got unsupported aop->type");
1442 /*-----------------------------------------------------------------*/
1443 /* aopPutUsesAcc - indicates ahead of time whether aopPut() will */
1444 /* clobber the accumulator */
1445 /*-----------------------------------------------------------------*/
1447 aopPutUsesAcc (operand * oper, const char *s, int offset)
1449 asmop * aop = AOP (oper);
1451 if (offset > (aop->size - 1))
1461 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1467 return ((aop->paged) || (*s == '@'));
1471 return (!aop->aopu.aop_dir || strcmp(s, aop->aopu.aop_dir));
1479 /* Error case --- will have been caught already */
1485 /*-----------------------------------------------------------------*/
1486 /* aopPut - puts a string for a aop and indicates if acc is in use */
1487 /*-----------------------------------------------------------------*/
1489 aopPut (operand * result, const char *s, int offset)
1491 bool bvolatile = isOperandVolatile (result, FALSE);
1492 bool accuse = FALSE;
1493 asmop * aop = AOP (result);
1495 if (aop->size && offset > (aop->size - 1))
1497 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1498 "aopPut got offset > aop->size");
1502 /* will assign value to value */
1503 /* depending on where it is ofcourse */
1507 MOVA (s); /* read s in case it was volatile */
1512 if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1514 SNPRINTF (buffer, sizeof(buffer),
1516 aop->aopu.aop_dir, offset * 8);
1520 SNPRINTF (buffer, sizeof(buffer),
1522 aop->aopu.aop_dir, offset);
1526 SNPRINTF (buffer, sizeof(buffer),
1531 if (strcmp (buffer, s) || bvolatile)
1533 emitcode ("mov", "%s,%s", buffer, s);
1535 if (!strcmp (buffer, "acc"))
1542 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1543 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1546 strcmp (s, "r0") == 0 ||
1547 strcmp (s, "r1") == 0 ||
1548 strcmp (s, "r2") == 0 ||
1549 strcmp (s, "r3") == 0 ||
1550 strcmp (s, "r4") == 0 ||
1551 strcmp (s, "r5") == 0 ||
1552 strcmp (s, "r6") == 0 ||
1553 strcmp (s, "r7") == 0)
1555 emitcode ("mov", "%s,%s",
1556 aop->aopu.aop_reg[offset]->dname, s);
1560 emitcode ("mov", "%s,%s",
1561 aop->aopu.aop_reg[offset]->name, s);
1569 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1570 "aopPut writing to code space");
1574 while (offset > aop->coff)
1577 emitcode ("inc", "dptr");
1580 while (offset < aop->coff)
1583 emitcode ("lcall", "__decdptr");
1588 /* if not in accumulator */
1591 emitcode ("movx", "@dptr,a");
1596 while (offset > aop->coff)
1599 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1601 while (offset < aop->coff)
1604 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1611 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1616 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1618 else if (strcmp (s, "r0") == 0 ||
1619 strcmp (s, "r1") == 0 ||
1620 strcmp (s, "r2") == 0 ||
1621 strcmp (s, "r3") == 0 ||
1622 strcmp (s, "r4") == 0 ||
1623 strcmp (s, "r5") == 0 ||
1624 strcmp (s, "r6") == 0 ||
1625 strcmp (s, "r7") == 0)
1628 SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1629 emitcode ("mov", "@%s,%s",
1630 aop->aopu.aop_ptr->name, buffer);
1634 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1639 if (strcmp (s, "a") == 0)
1641 emitcode ("push", "acc");
1646 emitcode ("push", "acc");
1648 else if (strcmp (s, "r0") == 0 ||
1649 strcmp (s, "r1") == 0 ||
1650 strcmp (s, "r2") == 0 ||
1651 strcmp (s, "r3") == 0 ||
1652 strcmp (s, "r4") == 0 ||
1653 strcmp (s, "r5") == 0 ||
1654 strcmp (s, "r6") == 0 ||
1655 strcmp (s, "r7") == 0)
1658 SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1659 emitcode ("push", buffer);
1663 emitcode ("push", s);
1669 /* if result no bit variable */
1670 if (!aop->aopu.aop_dir)
1672 assert (!strcmp (s, "c"));
1673 /* inefficient: move carry into A and use jz/jnz */
1674 emitcode ("clr", "a");
1675 emitcode ("rlc", "a");
1679 emitcode ("clr", "%s", aop->aopu.aop_dir);
1681 emitcode ("setb", "%s", aop->aopu.aop_dir);
1682 else if (!strcmp (s, "c"))
1683 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1684 else if (strcmp (s, aop->aopu.aop_dir))
1687 /* set C, if a >= 1 */
1688 emitcode ("add", "a,#0xff");
1689 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1695 if (strcmp (aop->aopu.aop_str[offset], s) || bvolatile)
1696 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1702 if (!offset && (strcmp (s, "acc") == 0) && !bvolatile)
1705 if (strcmp (aop->aopu.aop_str[offset], s) && !bvolatile)
1706 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1710 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1711 "aopPut got unsupported aop->type");
1720 /*-----------------------------------------------------------------*/
1721 /* pointToEnd :- points to the last byte of the operand */
1722 /*-----------------------------------------------------------------*/
1724 pointToEnd (asmop * aop)
1730 aop->coff = count = (aop->size - 1);
1736 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1740 emitcode ("inc", "dptr");
1747 /*-----------------------------------------------------------------*/
1748 /* reAdjustPreg - points a register back to where it should */
1749 /*-----------------------------------------------------------------*/
1751 reAdjustPreg (asmop * aop)
1753 if ((aop->coff==0) || (aop->size <= 1))
1761 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1766 emitcode ("lcall", "__decdptr");
1773 /*-----------------------------------------------------------------*/
1774 /* opIsGptr: returns non-zero if the passed operand is */
1775 /* a generic pointer type. */
1776 /*-----------------------------------------------------------------*/
1778 opIsGptr (operand * op)
1780 sym_link *type = operandType (op);
1782 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1789 /*-----------------------------------------------------------------*/
1790 /* getDataSize - get the operand data size */
1791 /*-----------------------------------------------------------------*/
1793 getDataSize (operand * op)
1796 size = AOP_SIZE (op);
1797 if (size == GPTRSIZE)
1799 sym_link *type = operandType (op);
1800 if (IS_GENPTR (type))
1802 /* generic pointer; arithmetic operations
1803 * should ignore the high byte (pointer type).
1811 /*-----------------------------------------------------------------*/
1812 /* outAcc - output Acc */
1813 /*-----------------------------------------------------------------*/
1815 outAcc (operand * result)
1818 size = getDataSize (result);
1821 aopPut (result, "a", 0);
1824 /* unsigned or positive */
1827 aopPut (result, zero, offset++);
1832 /*-----------------------------------------------------------------*/
1833 /* outBitC - output a bit C */
1834 /*-----------------------------------------------------------------*/
1836 outBitC (operand * result)
1838 /* if the result is bit */
1839 if (AOP_TYPE (result) == AOP_CRY)
1841 if (!OP_SYMBOL (result)->ruonly)
1842 aopPut (result, "c", 0);
1846 emitcode ("clr", "a");
1847 emitcode ("rlc", "a");
1852 /*-----------------------------------------------------------------*/
1853 /* toBoolean - emit code for orl a,operator(sizeop) */
1854 /*-----------------------------------------------------------------*/
1856 toBoolean (operand * oper)
1858 int size = AOP_SIZE (oper) - 1;
1860 bool AccUsed = FALSE;
1863 while (!AccUsed && size--)
1865 AccUsed |= aopGetUsesAcc(oper, offset++);
1868 size = AOP_SIZE (oper) - 1;
1870 MOVA (aopGet (oper, 0, FALSE, FALSE));
1871 if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1874 emitcode("mov", "b,a");
1877 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1878 emitcode ("orl", "b,a");
1880 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1881 emitcode ("orl", "a,b");
1888 emitcode ("orl", "a,%s",
1889 aopGet (oper, offset++, FALSE, FALSE));
1894 /*-----------------------------------------------------------------*/
1895 /* toCarry - make boolean and move into carry */
1896 /*-----------------------------------------------------------------*/
1898 toCarry (operand * oper)
1900 /* if the operand is a literal then
1901 we know what the value is */
1902 if (AOP_TYPE (oper) == AOP_LIT)
1904 if ((int) operandLitValue (oper))
1909 else if (AOP_TYPE (oper) == AOP_CRY)
1911 emitcode ("mov", "c,%s", oper->aop->aopu.aop_dir);
1915 /* or the operand into a */
1917 /* set C, if a >= 1 */
1918 emitcode ("add", "a,#0xff");
1922 /*-----------------------------------------------------------------*/
1923 /* assignBit - assign operand to bit operand */
1924 /*-----------------------------------------------------------------*/
1926 assignBit (operand * result, operand * right)
1928 /* if the right side is a literal then
1929 we know what the value is */
1930 if (AOP_TYPE (right) == AOP_LIT)
1932 if ((int) operandLitValue (right))
1933 aopPut (result, one, 0);
1935 aopPut (result, zero, 0);
1940 aopPut (result, "c", 0);
1945 /*-------------------------------------------------------------------*/
1946 /* xch_a_aopGet - for exchanging acc with value of the aop */
1947 /*-------------------------------------------------------------------*/
1949 xch_a_aopGet (operand * oper, int offset, bool bit16, bool dname)
1953 if (aopGetUsesAcc (oper, offset))
1955 emitcode("mov", "b,a");
1956 MOVA (aopGet (oper, offset, bit16, dname));
1957 emitcode("xch", "a,b");
1958 aopPut (oper, "a", offset);
1959 emitcode("xch", "a,b");
1964 l = aopGet (oper, offset, bit16, dname);
1965 emitcode("xch", "a,%s", l);
1971 /*-----------------------------------------------------------------*/
1972 /* genNot - generate code for ! operation */
1973 /*-----------------------------------------------------------------*/
1979 D (emitcode (";", "genNot"));
1981 /* assign asmOps to operand & result */
1982 aopOp (IC_LEFT (ic), ic, FALSE);
1983 aopOp (IC_RESULT (ic), ic, TRUE);
1985 /* if in bit space then a special case */
1986 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1988 /* if left==result then cpl bit */
1989 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1991 emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1995 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1996 emitcode ("cpl", "c");
1997 outBitC (IC_RESULT (ic));
2002 toBoolean (IC_LEFT (ic));
2004 /* set C, if a == 0 */
2005 tlbl = newiTempLabel (NULL);
2006 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
2008 outBitC (IC_RESULT (ic));
2011 /* release the aops */
2012 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2013 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2017 /*-----------------------------------------------------------------*/
2018 /* genCpl - generate code for complement */
2019 /*-----------------------------------------------------------------*/
2026 sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
2028 D(emitcode (";", "genCpl"));
2030 /* assign asmOps to operand & result */
2031 aopOp (IC_LEFT (ic), ic, FALSE);
2032 aopOp (IC_RESULT (ic), ic, TRUE);
2034 /* special case if in bit space */
2035 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2039 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
2040 (SPEC_USIGN (letype) && IS_CHAR (letype)))
2042 /* promotion rules are responsible for this strange result:
2043 bit -> int -> ~int -> bit
2044 uchar -> int -> ~int -> bit
2046 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
2050 tlbl=newiTempLabel(NULL);
2051 l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
2052 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
2053 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
2054 IS_AOP_PREG (IC_LEFT (ic)))
2056 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
2061 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
2064 outBitC (IC_RESULT(ic));
2068 size = AOP_SIZE (IC_RESULT (ic));
2071 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2073 emitcode ("cpl", "a");
2074 aopPut (IC_RESULT (ic), "a", offset++);
2079 /* release the aops */
2080 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2081 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2084 /*-----------------------------------------------------------------*/
2085 /* genUminusFloat - unary minus for floating points */
2086 /*-----------------------------------------------------------------*/
2088 genUminusFloat (operand * op, operand * result)
2090 int size, offset = 0;
2093 D (emitcode (";", "genUminusFloat"));
2095 /* for this we just copy and then flip the bit */
2097 size = AOP_SIZE (op) - 1;
2102 aopGet (op, offset, FALSE, FALSE),
2107 l = aopGet (op, offset, FALSE, FALSE);
2110 emitcode ("cpl", "acc.7");
2111 aopPut (result, "a", offset);
2114 /*-----------------------------------------------------------------*/
2115 /* genUminus - unary minus code generation */
2116 /*-----------------------------------------------------------------*/
2118 genUminus (iCode * ic)
2123 D (emitcode (";", "genUminus"));
2126 aopOp (IC_LEFT (ic), ic, FALSE);
2127 aopOp (IC_RESULT (ic), ic, TRUE);
2129 /* if both in bit space then special
2131 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2132 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2135 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2136 emitcode ("cpl", "c");
2137 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2141 optype = operandType (IC_LEFT (ic));
2143 /* if float then do float stuff */
2144 if (IS_FLOAT (optype))
2146 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2150 /* otherwise subtract from zero */
2151 size = AOP_SIZE (IC_LEFT (ic));
2155 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2156 if (!strcmp (l, "a"))
2160 emitcode ("cpl", "a");
2161 emitcode ("addc", "a,#0");
2167 emitcode ("clr", "a");
2168 emitcode ("subb", "a,%s", l);
2170 aopPut (IC_RESULT (ic), "a", offset++);
2173 /* if any remaining bytes in the result */
2174 /* we just need to propagate the sign */
2175 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2177 emitcode ("rlc", "a");
2178 emitcode ("subb", "a,acc");
2180 aopPut (IC_RESULT (ic), "a", offset++);
2184 /* release the aops */
2185 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2186 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2189 /*-----------------------------------------------------------------*/
2190 /* saveRegisters - will look for a call and save the registers */
2191 /*-----------------------------------------------------------------*/
2193 saveRegisters (iCode * lic)
2200 for (ic = lic; ic; ic = ic->next)
2201 if (ic->op == CALL || ic->op == PCALL)
2206 fprintf (stderr, "found parameter push with no function call\n");
2210 /* if the registers have been saved already or don't need to be then
2214 if (IS_SYMOP(IC_LEFT(ic)) &&
2215 (IFFUNC_CALLEESAVES (OP_SYMBOL (IC_LEFT (ic))->type) ||
2216 IFFUNC_ISNAKED (OP_SYM_TYPE (IC_LEFT (ic)))))
2219 /* save the registers in use at this time but skip the
2220 ones for the result */
2221 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2222 mcs51_rUmaskForOp (IC_RESULT(ic)));
2225 if (options.useXstack)
2227 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2228 int nBits = bitVectnBitsOn (rsavebits);
2229 int count = bitVectnBitsOn (rsave);
2233 count = count - nBits + 1;
2234 /* remove all but the first bits as they are pushed all at once */
2235 rsave = bitVectCplAnd (rsave, rsavebits);
2236 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2238 freeBitVect (rsavebits);
2242 regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2243 if (reg->type == REG_BIT)
2245 emitcode ("mov", "a,%s", reg->base);
2249 emitcode ("mov", "a,%s", reg->name);
2251 emitcode ("mov", "r0,%s", spname);
2252 emitcode ("inc", "%s", spname);// allocate before use
2253 emitcode ("movx", "@r0,a");
2254 if (bitVectBitValue (rsave, R0_IDX))
2255 emitcode ("mov", "r0,a");
2257 else if (count != 0)
2259 if (bitVectBitValue (rsave, R0_IDX))
2261 emitcode ("push", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2263 emitcode ("mov", "r0,%s", spname);
2265 emitcode ("add", "a,#%d", count);
2266 emitcode ("mov", "%s,a", spname);
2267 for (i = 0; i < mcs51_nRegs; i++)
2269 if (bitVectBitValue (rsave, i))
2271 regs * reg = REG_WITH_INDEX (i);
2274 emitcode ("pop", "acc");
2275 emitcode ("push", "acc");
2277 else if (reg->type == REG_BIT)
2279 emitcode ("mov", "a,%s", reg->base);
2283 emitcode ("mov", "a,%s", reg->name);
2285 emitcode ("movx", "@r0,a");
2288 emitcode ("inc", "r0");
2292 if (bitVectBitValue (rsave, R0_IDX))
2294 emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2300 bool bits_pushed = FALSE;
2301 for (i = 0; i < mcs51_nRegs; i++)
2303 if (bitVectBitValue (rsave, i))
2305 bits_pushed = pushReg (i, bits_pushed);
2309 freeBitVect (rsave);
2312 /*-----------------------------------------------------------------*/
2313 /* unsaveRegisters - pop the pushed registers */
2314 /*-----------------------------------------------------------------*/
2316 unsaveRegisters (iCode * ic)
2321 /* restore the registers in use at this time but skip the
2322 ones for the result */
2323 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2324 mcs51_rUmaskForOp (IC_RESULT(ic)));
2326 if (options.useXstack)
2328 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2329 int nBits = bitVectnBitsOn (rsavebits);
2330 int count = bitVectnBitsOn (rsave);
2334 count = count - nBits + 1;
2335 /* remove all but the first bits as they are popped all at once */
2336 rsave = bitVectCplAnd (rsave, rsavebits);
2337 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2339 freeBitVect (rsavebits);
2343 regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2344 emitcode ("mov", "r0,%s", spname);
2345 emitcode ("dec", "r0");
2346 emitcode ("movx", "a,@r0");
2347 if (reg->type == REG_BIT)
2349 emitcode ("mov", "%s,a", reg->base);
2353 emitcode ("mov", "%s,a", reg->name);
2355 emitcode ("dec", "%s", spname);
2357 else if (count != 0)
2359 emitcode ("mov", "r0,%s", spname);
2360 for (i = mcs51_nRegs; i >= 0; i--)
2362 if (bitVectBitValue (rsave, i))
2364 regs * reg = REG_WITH_INDEX (i);
2365 emitcode ("dec", "r0");
2366 emitcode ("movx", "a,@r0");
2369 emitcode ("push", "acc");
2371 else if (reg->type == REG_BIT)
2373 emitcode ("mov", "%s,a", reg->base);
2377 emitcode ("mov", "%s,a", reg->name);
2381 emitcode ("mov", "%s,r0", spname);
2382 if (bitVectBitValue (rsave, R0_IDX))
2384 emitcode ("pop", "ar0");
2390 bool bits_popped = FALSE;
2391 for (i = mcs51_nRegs; i >= 0; i--)
2393 if (bitVectBitValue (rsave, i))
2395 bits_popped = popReg (i, bits_popped);
2399 freeBitVect (rsave);
2403 /*-----------------------------------------------------------------*/
2405 /*-----------------------------------------------------------------*/
2407 pushSide (operand * oper, int size)
2412 char *l = aopGet (oper, offset++, FALSE, TRUE);
2413 if (AOP_TYPE (oper) != AOP_REG &&
2414 AOP_TYPE (oper) != AOP_DIR &&
2418 emitcode ("push", "acc");
2422 emitcode ("push", "%s", l);
2427 /*-----------------------------------------------------------------*/
2428 /* assignResultValue - also indicates if acc is in use afterwards */
2429 /*-----------------------------------------------------------------*/
2431 assignResultValue (operand * oper, operand * func)
2434 int size = AOP_SIZE (oper);
2435 bool accuse = FALSE;
2436 bool pushedA = FALSE;
2438 if (func && IS_BIT (OP_SYM_ETYPE (func)))
2444 if ((size > 3) && aopPutUsesAcc (oper, fReturn[offset], offset))
2446 emitcode ("push", "acc");
2451 if ((offset == 3) && pushedA)
2452 emitcode ("pop", "acc");
2453 accuse |= aopPut (oper, fReturn[offset], offset);
2460 /*-----------------------------------------------------------------*/
2461 /* genXpush - pushes onto the external stack */
2462 /*-----------------------------------------------------------------*/
2464 genXpush (iCode * ic)
2466 asmop *aop = newAsmop (0);
2468 int size, offset = 0;
2470 D (emitcode (";", "genXpush"));
2472 aopOp (IC_LEFT (ic), ic, FALSE);
2473 r = getFreePtr (ic, &aop, FALSE);
2475 size = AOP_SIZE (IC_LEFT (ic));
2479 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2480 emitcode ("mov", "%s,%s", r->name, spname);
2481 emitcode ("inc", "%s", spname); // allocate space first
2482 emitcode ("movx", "@%s,a", r->name);
2486 // allocate space first
2487 emitcode ("mov", "%s,%s", r->name, spname);
2489 emitcode ("add", "a,#%d", size);
2490 emitcode ("mov", "%s,a", spname);
2494 MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2495 emitcode ("movx", "@%s,a", r->name);
2496 emitcode ("inc", "%s", r->name);
2500 freeAsmop (NULL, aop, ic, TRUE);
2501 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2504 /*-----------------------------------------------------------------*/
2505 /* genIpush - generate code for pushing this gets a little complex */
2506 /*-----------------------------------------------------------------*/
2508 genIpush (iCode * ic)
2510 int size, offset = 0;
2514 D (emitcode (";", "genIpush"));
2516 /* if this is not a parm push : ie. it is spill push
2517 and spill push is always done on the local stack */
2521 /* and the item is spilt then do nothing */
2522 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2525 aopOp (IC_LEFT (ic), ic, FALSE);
2526 size = AOP_SIZE (IC_LEFT (ic));
2527 /* push it on the stack */
2530 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2536 emitcode ("push", "%s", l);
2541 /* this is a parameter push: in this case we call
2542 the routine to find the call and save those
2543 registers that need to be saved */
2546 /* if use external stack then call the external
2547 stack pushing routine */
2548 if (options.useXstack)
2554 /* then do the push */
2555 aopOp (IC_LEFT (ic), ic, FALSE);
2557 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2558 size = AOP_SIZE (IC_LEFT (ic));
2562 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2563 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2564 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR)
2566 if (strcmp (l, prev) || *l == '@')
2568 emitcode ("push", "acc");
2572 emitcode ("push", "%s", l);
2577 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2580 /*-----------------------------------------------------------------*/
2581 /* genIpop - recover the registers: can happen only for spilling */
2582 /*-----------------------------------------------------------------*/
2584 genIpop (iCode * ic)
2588 D (emitcode (";", "genIpop"));
2590 /* if the temp was not pushed then */
2591 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2594 aopOp (IC_LEFT (ic), ic, FALSE);
2595 size = AOP_SIZE (IC_LEFT (ic));
2596 offset = (size - 1);
2599 emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2603 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2606 /*-----------------------------------------------------------------*/
2607 /* saveRBank - saves an entire register bank on the stack */
2608 /*-----------------------------------------------------------------*/
2610 saveRBank (int bank, iCode * ic, bool pushPsw)
2613 int count = 8 + (pushPsw ? 1 : 0);
2617 if (options.useXstack)
2621 /* Assume r0 is available for use. */
2622 r = REG_WITH_INDEX (R0_IDX);
2627 r = getFreePtr (ic, &aop, FALSE);
2629 // allocate space first
2630 emitcode ("mov", "%s,%s", r->name, spname);
2632 emitcode ("add", "a,#%d", count);
2633 emitcode ("mov", "%s,a", spname);
2636 for (i = 0; i < 8; i++)
2638 if (options.useXstack)
2640 emitcode ("mov", "a,(%s+%d)",
2641 regs8051[i].base, 8 * bank + regs8051[i].offset);
2642 emitcode ("movx", "@%s,a", r->name);
2644 emitcode ("inc", "%s", r->name);
2647 emitcode ("push", "(%s+%d)",
2648 regs8051[i].base, 8 * bank + regs8051[i].offset);
2653 if (options.useXstack)
2655 emitcode ("mov", "a,psw");
2656 emitcode ("movx", "@%s,a", r->name);
2660 emitcode ("push", "psw");
2663 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2668 freeAsmop (NULL, aop, ic, TRUE);
2677 /*-----------------------------------------------------------------*/
2678 /* unsaveRBank - restores the register bank from stack */
2679 /*-----------------------------------------------------------------*/
2681 unsaveRBank (int bank, iCode * ic, bool popPsw)
2687 if (options.useXstack)
2691 /* Assume r0 is available for use. */
2692 r = REG_WITH_INDEX (R0_IDX);;
2697 r = getFreePtr (ic, &aop, FALSE);
2699 emitcode ("mov", "%s,%s", r->name, spname);
2704 if (options.useXstack)
2706 emitcode ("dec", "%s", r->name);
2707 emitcode ("movx", "a,@%s", r->name);
2708 emitcode ("mov", "psw,a");
2712 emitcode ("pop", "psw");
2716 for (i = 7; i >= 0; i--)
2718 if (options.useXstack)
2720 emitcode ("dec", "%s", r->name);
2721 emitcode ("movx", "a,@%s", r->name);
2722 emitcode ("mov", "(%s+%d),a",
2723 regs8051[i].base, 8 * bank + regs8051[i].offset);
2727 emitcode ("pop", "(%s+%d)",
2728 regs8051[i].base, 8 * bank + regs8051[i].offset);
2732 if (options.useXstack)
2734 emitcode ("mov", "%s,%s", spname, r->name);
2739 freeAsmop (NULL, aop, ic, TRUE);
2743 /*-----------------------------------------------------------------*/
2744 /* genSend - gen code for SEND */
2745 /*-----------------------------------------------------------------*/
2746 static void genSend(set *sendSet)
2751 /* first we do all bit parameters */
2752 for (sic = setFirstItem (sendSet); sic;
2753 sic = setNextItem (sendSet))
2755 if (sic->argreg > 12)
2757 int bit = sic->argreg-13;
2759 aopOp (IC_LEFT (sic), sic, FALSE);
2761 /* if left is a literal then
2762 we know what the value is */
2763 if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2765 if (((int) operandLitValue (IC_LEFT (sic))))
2766 emitcode ("setb", "b[%d]", bit);
2768 emitcode ("clr", "b[%d]", bit);
2773 toCarry (IC_LEFT (sic));
2774 emitcode ("mov", "b[%d],c", bit);
2779 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2785 saveRegisters (setFirstItem (sendSet));
2786 emitcode ("mov", "bits,b");
2789 /* then we do all other parameters */
2790 for (sic = setFirstItem (sendSet); sic;
2791 sic = setNextItem (sendSet))
2793 if (sic->argreg <= 12)
2795 int size, offset = 0;
2796 aopOp (IC_LEFT (sic), sic, FALSE);
2797 size = AOP_SIZE (IC_LEFT (sic));
2799 if (sic->argreg == 1)
2803 char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2804 if (strcmp (l, fReturn[offset]))
2806 emitcode ("mov", "%s,%s", fReturn[offset], l);
2815 emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2816 aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2820 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2825 /*-----------------------------------------------------------------*/
2826 /* selectRegBank - emit code to select the register bank */
2827 /*-----------------------------------------------------------------*/
2829 selectRegBank (short bank, bool keepFlags)
2831 /* if f.e. result is in carry */
2834 emitcode ("anl", "psw,#0xE7");
2836 emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2840 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2844 /*-----------------------------------------------------------------*/
2845 /* genCall - generates a call statement */
2846 /*-----------------------------------------------------------------*/
2848 genCall (iCode * ic)
2852 // bool restoreBank = FALSE;
2853 bool swapBanks = FALSE;
2854 bool accuse = FALSE;
2855 bool accPushed = FALSE;
2856 bool resultInF0 = FALSE;
2857 bool assignResultGenerated = FALSE;
2859 D (emitcode (";", "genCall"));
2861 dtype = operandType (IC_LEFT (ic));
2862 etype = getSpec(dtype);
2863 /* if send set is not empty then assign */
2866 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2867 genSend(reverseSet(_G.sendSet));
2869 genSend(_G.sendSet);
2874 /* if we are calling a not _naked function that is not using
2875 the same register bank then we need to save the
2876 destination registers on the stack */
2877 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2878 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2879 !IFFUNC_ISISR (dtype))
2884 /* if caller saves & we have not saved then */
2890 emitcode ("mov", "psw,#0x%02x",
2891 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2895 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2897 if (IFFUNC_CALLEESAVES(dtype))
2899 werror (E_BANKED_WITH_CALLEESAVES);
2903 char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2904 OP_SYMBOL (IC_LEFT (ic))->rname :
2905 OP_SYMBOL (IC_LEFT (ic))->name);
2907 emitcode ("mov", "r0,#%s", l);
2908 emitcode ("mov", "r1,#(%s >> 8)", l);
2909 emitcode ("mov", "r2,#(%s >> 16)", l);
2910 emitcode ("lcall", "__sdcc_banked_call");
2915 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2916 OP_SYMBOL (IC_LEFT (ic))->rname :
2917 OP_SYMBOL (IC_LEFT (ic))->name));
2922 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2925 /* if we need assign a result value */
2926 if ((IS_ITEMP (IC_RESULT (ic)) &&
2927 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2928 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2929 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2930 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2931 IS_TRUE_SYMOP (IC_RESULT (ic)))
2935 aopOp (IC_RESULT (ic), ic, FALSE);
2938 accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2939 assignResultGenerated = TRUE;
2941 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2944 /* adjust the stack for parameters if required */
2948 if (ic->parmBytes > 3)
2952 emitcode ("push", "acc");
2955 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2956 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2957 !assignResultGenerated)
2959 emitcode ("mov", "F0,c");
2963 emitcode ("mov", "a,%s", spname);
2964 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2965 emitcode ("mov", "%s,a", spname);
2967 /* unsaveRegisters from xstack needs acc, but */
2968 /* unsaveRegisters from stack needs this popped */
2969 if (accPushed && !options.useXstack)
2971 emitcode ("pop", "acc");
2976 for (i = 0; i < ic->parmBytes; i++)
2977 emitcode ("dec", "%s", spname);
2980 /* if we had saved some registers then unsave them */
2981 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2983 if (accuse && !accPushed && options.useXstack)
2985 /* xstack needs acc, but doesn't touch normal stack */
2986 emitcode ("push", "acc");
2989 unsaveRegisters (ic);
2992 // /* if register bank was saved then pop them */
2994 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2996 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
2999 emitcode ("mov", "c,F0");
3001 aopOp (IC_RESULT (ic), ic, FALSE);
3002 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3003 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3007 emitcode ("pop", "acc");
3010 /*-----------------------------------------------------------------*/
3011 /* genPcall - generates a call by pointer statement */
3012 /*-----------------------------------------------------------------*/
3014 genPcall (iCode * ic)
3018 symbol *rlbl = newiTempLabel (NULL);
3019 // bool restoreBank=FALSE;
3020 bool swapBanks = FALSE;
3021 bool resultInF0 = FALSE;
3023 D (emitcode (";", "genPcall"));
3025 dtype = operandType (IC_LEFT (ic))->next;
3026 etype = getSpec(dtype);
3027 /* if caller saves & we have not saved then */
3031 /* if we are calling a not _naked function that is not using
3032 the same register bank then we need to save the
3033 destination registers on the stack */
3034 if (currFunc && dtype && !IFFUNC_ISNAKED (dtype) &&
3035 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
3036 !IFFUNC_ISISR (dtype))
3038 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3039 // restoreBank=TRUE;
3041 // need caution message to user here
3044 if (IS_LITERAL (etype))
3046 /* if send set is not empty then assign */
3049 genSend(reverseSet(_G.sendSet));
3055 emitcode ("mov", "psw,#0x%02x",
3056 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3059 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT (getSpec(dtype)))
3061 if (IFFUNC_CALLEESAVES (dtype))
3063 werror (E_BANKED_WITH_CALLEESAVES);
3067 char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
3069 emitcode ("mov", "r0,#%s", l);
3070 emitcode ("mov", "r1,#(%s >> 8)", l);
3071 emitcode ("mov", "r2,#(%s >> 16)", l);
3072 emitcode ("lcall", "__sdcc_banked_call");
3077 emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
3082 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT (getSpec(dtype)))
3084 if (IFFUNC_CALLEESAVES (dtype))
3086 werror (E_BANKED_WITH_CALLEESAVES);
3090 aopOp (IC_LEFT (ic), ic, FALSE);
3094 /* what if aopGet needs r0 or r1 ??? */
3095 emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3096 emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3097 emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3101 int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
3102 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3103 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3104 emitcode ("mov", "0x%02x,%s", reg, aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3107 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3109 /* if send set is not empty then assign */
3112 genSend(reverseSet(_G.sendSet));
3118 emitcode ("mov", "psw,#0x%02x",
3119 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3123 emitcode ("lcall", "__sdcc_banked_call");
3126 else if (_G.sendSet)
3128 /* push the return address on to the stack */
3129 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
3130 emitcode ("push", "acc");
3131 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
3132 emitcode ("push", "acc");
3134 /* now push the calling address */
3135 aopOp (IC_LEFT (ic), ic, FALSE);
3137 pushSide (IC_LEFT (ic), FPTRSIZE);
3139 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3141 /* if send set is not empty the assign */
3144 genSend(reverseSet(_G.sendSet));
3150 emitcode ("mov", "psw,#0x%02x",
3151 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3155 emitcode ("ret", "");
3158 else /* the send set is empty */
3161 /* now get the calling address into dptr */
3162 aopOp (IC_LEFT (ic), ic, FALSE);
3164 l = aopGet (IC_LEFT (ic), 0, FALSE, FALSE);
3165 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3167 emitcode ("mov", "r0,%s", l);
3168 l = aopGet (IC_LEFT (ic), 1, FALSE, FALSE);
3169 emitcode ("mov", "dph,%s", l);
3170 emitcode ("mov", "dpl,r0");
3174 emitcode ("mov", "dpl,%s", l);
3175 l = aopGet (IC_LEFT (ic), 1, FALSE, FALSE);
3176 emitcode ("mov", "dph,%s", l);
3179 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3183 emitcode ("mov", "psw,#0x%02x",
3184 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3188 emitcode ("lcall", "__sdcc_call_dptr");
3193 selectRegBank (FUNC_REGBANK (currFunc->type), IS_BIT (etype));
3196 /* if we need assign a result value */
3197 if ((IS_ITEMP (IC_RESULT (ic)) &&
3198 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3199 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3200 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3201 IS_TRUE_SYMOP (IC_RESULT (ic)))
3205 aopOp (IC_RESULT (ic), ic, FALSE);
3208 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3210 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3213 /* adjust the stack for parameters if required */
3217 if (ic->parmBytes > 3)
3219 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3220 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3222 emitcode ("mov", "F0,c");
3226 emitcode ("mov", "a,%s", spname);
3227 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3228 emitcode ("mov", "%s,a", spname);
3231 for (i = 0; i < ic->parmBytes; i++)
3232 emitcode ("dec", "%s", spname);
3235 // /* if register bank was saved then unsave them */
3237 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3239 /* if we had saved some registers then unsave them */
3240 if (ic->regsSaved && !IFFUNC_CALLEESAVES (dtype))
3241 unsaveRegisters (ic);
3243 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3246 emitcode ("mov", "c,F0");
3248 aopOp (IC_RESULT (ic), ic, FALSE);
3249 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3250 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3254 /*-----------------------------------------------------------------*/
3255 /* resultRemat - result is rematerializable */
3256 /*-----------------------------------------------------------------*/
3258 resultRemat (iCode * ic)
3260 if (SKIP_IC (ic) || ic->op == IFX)
3263 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3265 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3266 if (sym->remat && !POINTER_SET (ic))
3273 /*-----------------------------------------------------------------*/
3274 /* inExcludeList - return 1 if the string is in exclude Reg list */
3275 /*-----------------------------------------------------------------*/
3277 regsCmp(void *p1, void *p2)
3279 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3283 inExcludeList (char *s)
3285 const char *p = setFirstItem(options.excludeRegsSet);
3287 if (p == NULL || STRCASECMP(p, "none") == 0)
3291 return isinSetWith(options.excludeRegsSet, s, regsCmp);
3294 /*-----------------------------------------------------------------*/
3295 /* genFunction - generated code for function entry */
3296 /*-----------------------------------------------------------------*/
3298 genFunction (iCode * ic)
3300 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3302 bool switchedPSW = FALSE;
3303 int calleesaves_saved_register = -1;
3304 int stackAdjust = sym->stack;
3305 int accIsFree = sym->recvSize < 4;
3306 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3307 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3310 /* create the function header */
3311 emitcode (";", "-----------------------------------------");
3312 emitcode (";", " function %s", sym->name);
3313 emitcode (";", "-----------------------------------------");
3315 emitcode ("", "%s:", sym->rname);
3316 lineCurr->isLabel = 1;
3317 ftype = operandType (IC_LEFT (ic));
3318 _G.currentFunc = sym;
3320 if (IFFUNC_ISNAKED(ftype))
3322 emitcode(";", "naked function: no prologue.");
3326 /* here we need to generate the equates for the
3327 register bank if required */
3328 if (FUNC_REGBANK (ftype) != rbank)
3332 rbank = FUNC_REGBANK (ftype);
3333 for (i = 0; i < mcs51_nRegs; i++)
3335 if (regs8051[i].type != REG_BIT)
3337 if (strcmp (regs8051[i].base, "0") == 0)
3338 emitcode ("", "%s = 0x%02x",
3340 8 * rbank + regs8051[i].offset);
3342 emitcode ("", "%s = %s + 0x%02x",
3345 8 * rbank + regs8051[i].offset);
3350 /* if this is an interrupt service routine then
3351 save acc, b, dpl, dph */
3352 if (IFFUNC_ISISR (sym->type))
3356 rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), sym->regsUsed);
3357 if (IFFUNC_HASFCALL(sym->type) || !bitVectIsZero (rsavebits))
3359 emitcode ("push", "bits");
3362 freeBitVect (rsavebits);
3364 if (!inExcludeList ("acc"))
3365 emitcode ("push", "acc");
3366 if (!inExcludeList ("b"))
3367 emitcode ("push", "b");
3368 if (!inExcludeList ("dpl"))
3369 emitcode ("push", "dpl");
3370 if (!inExcludeList ("dph"))
3371 emitcode ("push", "dph");
3372 /* if this isr has no bank i.e. is going to
3373 run with bank 0 , then we need to save more
3375 if (!FUNC_REGBANK (sym->type))
3379 /* if this function does not call any other
3380 function then we can be economical and
3381 save only those registers that are used */
3382 if (!IFFUNC_HASFCALL(sym->type))
3384 /* if any registers used */
3387 /* save the registers used */
3388 for (i = 0; i < sym->regsUsed->size; i++)
3390 if (bitVectBitValue (sym->regsUsed, i))
3397 /* this function has a function call. We cannot
3398 determine register usage so we will have to push the
3400 saveRBank (0, ic, FALSE);
3401 if (options.parms_in_bank1) {
3402 for (i=0; i < 8 ; i++ ) {
3403 emitcode ("push","%s",rb1regs[i]);
3410 /* This ISR uses a non-zero bank.
3412 * We assume that the bank is available for our
3415 * However, if this ISR calls a function which uses some
3416 * other bank, we must save that bank entirely.
3418 unsigned long banksToSave = 0;
3420 if (IFFUNC_HASFCALL(sym->type))
3423 #define MAX_REGISTER_BANKS 4
3428 for (i = ic; i; i = i->next)
3430 if (i->op == ENDFUNCTION)
3432 /* we got to the end OK. */
3440 dtype = operandType (IC_LEFT(i));
3442 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3444 /* Mark this bank for saving. */
3445 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3447 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3451 banksToSave |= (1 << FUNC_REGBANK(dtype));
3454 /* And note that we don't need to do it in
3462 /* This is a mess; we have no idea what
3463 * register bank the called function might
3466 * The only thing I can think of to do is
3467 * throw a warning and hope.
3469 werror(W_FUNCPTR_IN_USING_ISR);
3473 if (banksToSave && options.useXstack)
3475 /* Since we aren't passing it an ic,
3476 * saveRBank will assume r0 is available to abuse.
3478 * So switch to our (trashable) bank now, so
3479 * the caller's R0 isn't trashed.
3481 emitcode ("push", "psw");
3482 emitcode ("mov", "psw,#0x%02x",
3483 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3487 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3489 if (banksToSave & (1 << ix))
3491 saveRBank(ix, NULL, FALSE);
3495 // TODO: this needs a closer look
3496 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3499 /* Set the register bank to the desired value if nothing else */
3500 /* has done so yet. */
3503 emitcode ("push", "psw");
3504 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3509 /* This is a non-ISR function. The caller has already switched register */
3510 /* banks, if necessary, so just handle the callee-saves option. */
3512 /* if callee-save to be used for this function
3513 then save the registers being used in this function */
3514 if (IFFUNC_CALLEESAVES(sym->type))
3518 /* if any registers used */
3521 bool bits_pushed = FALSE;
3522 /* save the registers used */
3523 for (i = 0; i < sym->regsUsed->size; i++)
3525 if (bitVectBitValue (sym->regsUsed, i))
3527 /* remember one saved register for later usage */
3528 if (calleesaves_saved_register < 0)
3529 calleesaves_saved_register = i;
3530 bits_pushed = pushReg (i, bits_pushed);
3540 if (options.useXstack)
3542 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3544 emitcode ("mov", "r0,%s", spname);
3545 emitcode ("inc", "%s", spname);
3546 emitcode ("xch", "a,_bpx");
3547 emitcode ("movx", "@r0,a");
3548 emitcode ("inc", "r0");
3549 emitcode ("mov", "a,r0");
3550 emitcode ("xch", "a,_bpx");
3554 emitcode ("push", "_bp"); /* save the callers stack */
3555 emitcode ("mov", "_bp,sp");
3560 if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3562 /* set up the stack */
3563 emitcode ("push", "_bp"); /* save the callers stack */
3564 emitcode ("mov", "_bp,sp");
3569 /* For some cases it is worthwhile to perform a RECEIVE iCode */
3570 /* before setting up the stack frame completely. */
3571 if (ric && ric->argreg == 1 && IC_RESULT (ric))
3573 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3577 if (rsym && rsym->regType == REG_CND)
3579 if (rsym && (rsym->accuse || rsym->ruonly))
3581 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3582 rsym = rsym->usl.spillLoc;
3585 /* If the RECEIVE operand immediately spills to the first entry on the */
3586 /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3587 /* rather than the usual @r0/r1 machinations. */
3588 if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3592 _G.current_iCode = ric;
3593 D(emitcode ("; genReceive",""));
3594 for (ofs=0; ofs < sym->recvSize; ofs++)
3596 if (!strcmp (fReturn[ofs], "a"))
3597 emitcode ("push", "acc");
3599 emitcode ("push", fReturn[ofs]);
3601 stackAdjust -= sym->recvSize;
3604 assert (stackAdjust>=0);
3607 _G.current_iCode = ic;
3611 /* If the RECEIVE operand is 4 registers, we can do the moves now */
3612 /* to free up the accumulator. */
3613 else if (rsym && rsym->nRegs && sym->recvSize == 4)
3617 _G.current_iCode = ric;
3618 D(emitcode ("; genReceive",""));
3619 for (ofs=0; ofs < sym->recvSize; ofs++)
3621 emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3623 _G.current_iCode = ic;
3629 /* adjust the stack for the function */
3632 int i = stackAdjust;
3634 werror (W_STACK_OVERFLOW, sym->name);
3636 if (i > 3 && accIsFree)
3638 emitcode ("mov", "a,sp");
3639 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3640 emitcode ("mov", "sp,a");
3644 /* The accumulator is not free, so we will need another register */
3645 /* to clobber. No need to worry about a possible conflict with */
3646 /* the above early RECEIVE optimizations since they would have */
3647 /* freed the accumulator if they were generated. */
3649 if (IFFUNC_CALLEESAVES(sym->type))
3651 /* if it's a callee-saves function we need a saved register */
3652 if (calleesaves_saved_register >= 0)
3654 emitcode ("mov", "%s,a", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3655 emitcode ("mov", "a,sp");
3656 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3657 emitcode ("mov", "sp,a");
3658 emitcode ("mov", "a,%s", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3661 /* do it the hard way */
3663 emitcode ("inc", "sp");
3667 /* not callee-saves, we can clobber r0 */
3668 emitcode ("mov", "r0,a");
3669 emitcode ("mov", "a,sp");
3670 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3671 emitcode ("mov", "sp,a");
3672 emitcode ("mov", "a,r0");
3677 emitcode ("inc", "sp");
3682 char i = ((char) sym->xstack & 0xff);
3684 if (i > 3 && accIsFree)
3686 emitcode ("mov", "a,_spx");
3687 emitcode ("add", "a,#0x%02x", i & 0xff);
3688 emitcode ("mov", "_spx,a");
3692 emitcode ("push", "acc");
3693 emitcode ("mov", "a,_spx");
3694 emitcode ("add", "a,#0x%02x", i & 0xff);
3695 emitcode ("mov", "_spx,a");
3696 emitcode ("pop", "acc");
3701 emitcode ("inc", "_spx");
3705 /* if critical function then turn interrupts off */
3706 if (IFFUNC_ISCRITICAL (ftype))
3708 symbol *tlbl = newiTempLabel (NULL);
3709 emitcode ("setb", "c");
3710 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3711 emitcode ("clr", "c");
3713 emitcode ("push", "psw"); /* save old ea via c in psw */
3717 /*-----------------------------------------------------------------*/
3718 /* genEndFunction - generates epilogue for functions */
3719 /*-----------------------------------------------------------------*/
3721 genEndFunction (iCode * ic)
3723 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3724 lineNode *lnp = lineCurr;
3726 bitVect *regsUsedPrologue;
3727 bitVect *regsUnneeded;
3730 _G.currentFunc = NULL;
3731 if (IFFUNC_ISNAKED(sym->type))
3733 emitcode(";", "naked function: no epilogue.");
3734 if (options.debug && currFunc)
3735 debugFile->writeEndFunction (currFunc, ic, 0);
3739 if (IFFUNC_ISCRITICAL (sym->type))
3741 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3743 emitcode ("rlc", "a"); /* save c in a */
3744 emitcode ("pop", "psw"); /* restore ea via c in psw */
3745 emitcode ("mov", "ea,c");
3746 emitcode ("rrc", "a"); /* restore c from a */
3750 emitcode ("pop", "psw"); /* restore ea via c in psw */
3751 emitcode ("mov", "ea,c");
3755 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3757 if (options.useXstack)
3761 emitcode ("mov", "sp,_bp");
3762 emitcode ("pop", "_bp");
3764 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3766 emitcode ("xch", "a,_bpx");
3767 emitcode ("mov", "r0,a");
3768 emitcode ("dec", "r0");
3769 emitcode ("movx", "a,@r0");
3770 emitcode ("xch", "a,_bpx");
3771 emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3774 else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3777 emitcode ("mov", "sp,_bp");
3778 emitcode ("pop", "_bp");
3782 /* restore the register bank */
3783 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3785 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3786 || !options.useXstack)
3788 /* Special case of ISR using non-zero bank with useXstack
3791 emitcode ("pop", "psw");
3795 if (IFFUNC_ISISR (sym->type))
3799 /* now we need to restore the registers */
3800 /* if this isr has no bank i.e. is going to
3801 run with bank 0 , then we need to save more
3803 if (!FUNC_REGBANK (sym->type))
3806 /* if this function does not call any other
3807 function then we can be economical and
3808 save only those registers that are used */
3809 if (!IFFUNC_HASFCALL(sym->type))
3811 /* if any registers used */
3814 /* save the registers used */
3815 for (i = sym->regsUsed->size; i >= 0; i--)
3817 if (bitVectBitValue (sym->regsUsed, i))
3824 if (options.parms_in_bank1) {
3825 for (i = 7 ; i >= 0 ; i-- ) {
3826 emitcode ("pop","%s",rb1regs[i]);
3829 /* this function has a function call. We cannot
3830 determine register usage so we will have to pop the
3832 unsaveRBank (0, ic, FALSE);
3837 /* This ISR uses a non-zero bank.
3839 * Restore any register banks saved by genFunction
3842 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3845 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3847 if (savedBanks & (1 << ix))
3849 unsaveRBank(ix, NULL, FALSE);
3853 if (options.useXstack)
3855 /* Restore bank AFTER calling unsaveRBank,
3856 * since it can trash r0.
3858 emitcode ("pop", "psw");
3862 if (!inExcludeList ("dph"))
3863 emitcode ("pop", "dph");
3864 if (!inExcludeList ("dpl"))
3865 emitcode ("pop", "dpl");
3866 if (!inExcludeList ("b"))
3867 emitcode ("pop", "b");
3868 if (!inExcludeList ("acc"))
3869 emitcode ("pop", "acc");
3871 rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), sym->regsUsed);
3872 if (IFFUNC_HASFCALL(sym->type) || !bitVectIsZero (rsavebits))
3873 emitcode ("pop", "bits");
3874 freeBitVect (rsavebits);
3876 /* if debug then send end of function */
3877 if (options.debug && currFunc)
3879 debugFile->writeEndFunction (currFunc, ic, 1);
3882 emitcode ("reti", "");
3886 if (IFFUNC_CALLEESAVES(sym->type))
3890 /* if any registers used */
3893 /* save the registers used */
3894 for (i = sym->regsUsed->size; i >= 0; i--)
3896 if (bitVectBitValue (sym->regsUsed, i) ||
3897 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3898 emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
3901 else if (mcs51_ptrRegReq)
3903 emitcode ("pop", "%s", REG_WITH_INDEX (R1_IDX)->dname);
3904 emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
3909 /* if debug then send end of function */
3910 if (options.debug && currFunc)
3912 debugFile->writeEndFunction (currFunc, ic, 1);
3915 if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3917 emitcode ("ljmp", "__sdcc_banked_ret");
3921 emitcode ("ret", "");
3925 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3928 /* If this was an interrupt handler using bank 0 that called another */
3929 /* function, then all registers must be saved; nothing to optimized. */
3930 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3931 && !FUNC_REGBANK(sym->type))
3934 /* There are no push/pops to optimize if not callee-saves or ISR */
3935 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3938 /* If there were stack parameters, we cannot optimize without also */
3939 /* fixing all of the stack offsets; this is too dificult to consider. */
3940 if (FUNC_HASSTACKPARM(sym->type))
3943 /* Compute the registers actually used */
3944 regsUsed = newBitVect (mcs51_nRegs);
3945 regsUsedPrologue = newBitVect (mcs51_nRegs);
3948 if (lnp->ic && lnp->ic->op == FUNCTION)
3949 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3951 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3953 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3954 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3961 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3962 && !bitVectBitValue (regsUsed, CND_IDX))
3964 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3965 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3966 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3967 bitVectUnSetBit (regsUsed, CND_IDX);
3970 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3972 /* If this was an interrupt handler that called another function */
3973 /* function, then assume A, B, DPH, & DPL may be modified by it. */
3974 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3976 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3977 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3978 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3979 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3980 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3983 /* Remove the unneeded push/pops */
3984 regsUnneeded = newBitVect (mcs51_nRegs);
3987 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3989 if (!strncmp(lnp->line, "push", 4))
3991 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3992 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3994 connectLine (lnp->prev, lnp->next);
3995 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3998 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
4000 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
4001 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4003 connectLine (lnp->prev, lnp->next);
4004 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4011 for (idx = 0; idx < regsUnneeded->size; idx++)
4012 if (bitVectBitValue (regsUnneeded, idx))
4013 emitcode (";", "eliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
4015 freeBitVect (regsUnneeded);
4016 freeBitVect (regsUsed);
4017 freeBitVect (regsUsedPrologue);
4020 /*-----------------------------------------------------------------*/
4021 /* genRet - generate code for return statement */
4022 /*-----------------------------------------------------------------*/
4026 int size, offset = 0, pushed = 0;
4028 D (emitcode (";", "genRet"));
4030 /* if we have no return value then
4031 just generate the "ret" */
4035 /* we have something to return then
4036 move the return value into place */
4037 aopOp (IC_LEFT (ic), ic, FALSE);
4038 size = AOP_SIZE (IC_LEFT (ic));
4040 if (IS_BIT(_G.currentFunc->etype))
4042 if (!OP_SYMBOL (IC_LEFT (ic))->ruonly)
4043 toCarry (IC_LEFT (ic));
4050 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
4053 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
4054 emitcode ("push", "%s", l);
4059 l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
4060 if (strcmp (fReturn[offset], l))
4061 emitcode ("mov", "%s,%s", fReturn[offset++], l);
4068 if (strcmp (fReturn[pushed], "a"))
4069 emitcode ("pop", fReturn[pushed]);
4071 emitcode ("pop", "acc");
4074 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
4077 /* generate a jump to the return label
4078 if the next is not the return statement */
4079 if (!(ic->next && ic->next->op == LABEL &&
4080 IC_LABEL (ic->next) == returnLabel))
4082 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
4086 /*-----------------------------------------------------------------*/
4087 /* genLabel - generates a label */
4088 /*-----------------------------------------------------------------*/
4090 genLabel (iCode * ic)
4092 /* special case never generate */
4093 if (IC_LABEL (ic) == entryLabel)
4096 emitLabel (IC_LABEL (ic));
4099 /*-----------------------------------------------------------------*/
4100 /* genGoto - generates a ljmp */
4101 /*-----------------------------------------------------------------*/
4103 genGoto (iCode * ic)
4105 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
4108 /*-----------------------------------------------------------------*/
4109 /* findLabelBackwards: walks back through the iCode chain looking */
4110 /* for the given label. Returns number of iCode instructions */
4111 /* between that label and given ic. */
4112 /* Returns zero if label not found. */
4113 /*-----------------------------------------------------------------*/
4115 findLabelBackwards (iCode * ic, int key)
4124 /* If we have any pushes or pops, we cannot predict the distance.
4125 I don't like this at all, this should be dealt with in the
4127 if (ic->op == IPUSH || ic->op == IPOP) {
4131 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4140 /*-----------------------------------------------------------------*/
4141 /* genPlusIncr :- does addition with increment if possible */
4142 /*-----------------------------------------------------------------*/
4144 genPlusIncr (iCode * ic)
4146 unsigned int icount;
4147 unsigned int size = getDataSize (IC_RESULT (ic));
4149 /* will try to generate an increment */
4150 /* if the right side is not a literal
4152 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4155 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4157 D(emitcode (";","genPlusIncr"));
4159 /* if increment >=16 bits in register or direct space */
4160 if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG ||
4161 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4162 (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4163 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4164 !isOperandVolatile (IC_RESULT (ic), FALSE) &&
4172 /* If the next instruction is a goto and the goto target
4173 * is < 10 instructions previous to this, we can generate
4174 * jumps straight to that target.
4176 if (ic->next && ic->next->op == GOTO
4177 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4178 && labelRange <= 10)
4180 D (emitcode (";", "tail increment optimized (range %d)", labelRange));
4181 tlbl = IC_LABEL (ic->next);
4186 tlbl = newiTempLabel (NULL);
4189 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4190 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4191 IS_AOP_PREG (IC_RESULT (ic)))
4192 emitcode ("cjne", "%s,#0x00,%05d$",
4193 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4197 emitcode ("clr", "a");
4198 emitcode ("cjne", "a,%s,%05d$",
4199 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4203 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4206 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4207 IS_AOP_PREG (IC_RESULT (ic)))
4208 emitcode ("cjne", "%s,#0x00,%05d$",
4209 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4212 emitcode ("cjne", "a,%s,%05d$",
4213 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4216 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4220 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4221 IS_AOP_PREG (IC_RESULT (ic)))
4222 emitcode ("cjne", "%s,#0x00,%05d$",
4223 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4227 emitcode ("cjne", "a,%s,%05d$",
4228 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4231 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4241 /* if result is dptr */
4242 if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
4243 (AOP_SIZE (IC_RESULT (ic)) == 2) &&
4244 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
4245 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
4247 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4253 if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
4256 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0);
4257 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1);
4259 emitcode ("inc", "dptr");
4264 /* if the literal value of the right hand side
4265 is greater than 4 then it is not worth it */
4269 /* if the sizes are greater than 1 then we cannot */
4270 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4271 AOP_SIZE (IC_LEFT (ic)) > 1)
4274 /* we can if the aops of the left & result match or
4275 if they are in registers and the registers are the
4277 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4281 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4282 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4283 aopPut (IC_RESULT (ic), "a", 0);
4289 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4298 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4299 emitcode ("inc", "a");
4300 aopPut (IC_RESULT (ic), "a", 0);
4307 /*-----------------------------------------------------------------*/
4308 /* outBitAcc - output a bit in acc */
4309 /*-----------------------------------------------------------------*/
4311 outBitAcc (operand * result)
4313 symbol *tlbl = newiTempLabel (NULL);
4314 /* if the result is a bit */
4315 if (AOP_TYPE (result) == AOP_CRY)
4317 aopPut (result, "a", 0);
4321 emitcode ("jz", "%05d$", tlbl->key + 100);
4322 emitcode ("mov", "a,%s", one);
4328 /*-----------------------------------------------------------------*/
4329 /* genPlusBits - generates code for addition of two bits */
4330 /*-----------------------------------------------------------------*/
4332 genPlusBits (iCode * ic)
4334 D (emitcode (";", "genPlusBits"));
4336 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4337 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4339 symbol *lbl = newiTempLabel (NULL);
4340 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4341 emitcode ("cpl", "c");
4343 outBitC (IC_RESULT (ic));
4347 emitcode ("clr", "a");
4348 emitcode ("rlc", "a");
4349 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4350 emitcode ("addc", "a,%s", zero);
4351 outAcc (IC_RESULT (ic));
4356 /* This is the original version of this code.
4358 * This is being kept around for reference,
4359 * because I am not entirely sure I got it right...
4362 adjustArithmeticResult (iCode * ic)
4364 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4365 AOP_SIZE (IC_LEFT (ic)) == 3 &&
4366 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4367 aopPut (IC_RESULT (ic),
4368 aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4371 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4372 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4373 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4374 aopPut (IC_RESULT (ic),
4375 aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4378 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4379 AOP_SIZE (IC_LEFT (ic)) < 3 &&
4380 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4381 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4382 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4385 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4386 aopPut (IC_RESULT (ic), buffer, 2);
4390 /* This is the pure and virtuous version of this code.
4391 * I'm pretty certain it's right, but not enough to toss the old
4395 adjustArithmeticResult (iCode * ic)
4397 if (opIsGptr (IC_RESULT (ic)) &&
4398 opIsGptr (IC_LEFT (ic)) &&
4399 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4401 aopPut (IC_RESULT (ic),
4402 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4406 if (opIsGptr (IC_RESULT (ic)) &&
4407 opIsGptr (IC_RIGHT (ic)) &&
4408 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4410 aopPut (IC_RESULT (ic),
4411 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4415 if (opIsGptr (IC_RESULT (ic)) &&
4416 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4417 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4418 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4419 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4422 SNPRINTF (buffer, sizeof(buffer),
4423 "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4424 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4429 /*-----------------------------------------------------------------*/
4430 /* genPlus - generates code for addition */
4431 /*-----------------------------------------------------------------*/
4433 genPlus (iCode * ic)
4435 int size, offset = 0;
4438 bool swappedLR = FALSE;
4439 operand *leftOp, *rightOp;
4442 D (emitcode (";", "genPlus"));
4444 /* special cases :- */
4446 aopOp (IC_LEFT (ic), ic, FALSE);
4447 aopOp (IC_RIGHT (ic), ic, FALSE);
4448 aopOp (IC_RESULT (ic), ic, TRUE);
4450 /* if literal, literal on the right or
4451 if left requires ACC or right is already
4453 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4454 (AOP_NEEDSACC (IC_LEFT (ic))) ||
4455 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4457 operand *t = IC_RIGHT (ic);
4458 IC_RIGHT (ic) = IC_LEFT (ic);
4463 /* if both left & right are in bit
4465 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4466 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4472 /* if left in bit space & right literal */
4473 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4474 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4476 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4477 /* if result in bit space */
4478 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4480 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4481 emitcode ("cpl", "c");
4482 outBitC (IC_RESULT (ic));
4486 size = getDataSize (IC_RESULT (ic));
4489 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4490 emitcode ("addc", "a,%s", zero);
4491 aopPut (IC_RESULT (ic), "a", offset++);
4497 /* if I can do an increment instead
4498 of add then GOOD for ME */
4499 if (genPlusIncr (ic) == TRUE)
4502 size = getDataSize (IC_RESULT (ic));
4503 leftOp = IC_LEFT(ic);
4504 rightOp = IC_RIGHT(ic);
4507 /* if this is an add for an array access
4508 at a 256 byte boundary */
4510 && AOP_TYPE (op) == AOP_IMMD
4512 && IS_SPEC (OP_SYM_ETYPE (op))
4513 && SPEC_ABSA (OP_SYM_ETYPE (op))
4514 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4517 D(emitcode ("; genPlus aligned array",""));
4518 aopPut (IC_RESULT (ic),
4519 aopGet (rightOp, 0, FALSE, FALSE),
4522 if( 1 == getDataSize (IC_RIGHT (ic)) )
4524 aopPut (IC_RESULT (ic),
4525 aopGet (leftOp, 1, FALSE, FALSE),
4530 MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4531 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4532 aopPut (IC_RESULT (ic), "a", 1);
4537 /* if the lower bytes of a literal are zero skip the addition */
4538 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4540 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4541 (skip_bytes+1 < size))
4546 D(emitcode ("; genPlus shortcut",""));
4551 if( offset >= skip_bytes )
4553 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4556 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4558 emitcode("xch", "a,b");
4559 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4560 emitcode (add, "a,b");
4563 else if (aopGetUsesAcc (leftOp, offset))
4565 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4566 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4570 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4571 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4573 aopPut (IC_RESULT (ic), "a", offset);
4574 add = "addc"; /* further adds must propagate carry */
4578 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4579 isOperandVolatile (IC_RESULT (ic), FALSE))
4582 aopPut (IC_RESULT (ic),
4583 aopGet (leftOp, offset, FALSE, FALSE),
4590 adjustArithmeticResult (ic);
4593 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4596 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4597 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4601 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4602 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4606 /*-----------------------------------------------------------------*/
4607 /* genMinusDec :- does subtraction with decrement if possible */
4608 /*-----------------------------------------------------------------*/
4610 genMinusDec (iCode * ic)
4612 unsigned int icount;
4613 unsigned int size = getDataSize (IC_RESULT (ic));
4615 /* will try to generate an increment */
4616 /* if the right side is not a literal
4618 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4621 /* if the literal value of the right hand side
4622 is greater than 4 then it is not worth it */
4623 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4626 D (emitcode (";", "genMinusDec"));
4628 /* if decrement >=16 bits in register or direct space */
4629 if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG ||
4630 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4631 (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4632 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4640 /* If the next instruction is a goto and the goto target
4641 * is <= 10 instructions previous to this, we can generate
4642 * jumps straight to that target.
4644 if (ic->next && ic->next->op == GOTO
4645 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4646 && labelRange <= 10)
4648 D (emitcode (";", "tail decrement optimized (range %d)", labelRange));
4649 tlbl = IC_LABEL (ic->next);
4654 tlbl = newiTempLabel (NULL);
4658 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4659 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4660 IS_AOP_PREG (IC_RESULT (ic)))
4661 emitcode ("cjne", "%s,#0xff,%05d$"
4662 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4666 emitcode ("mov", "a,#0xff");
4667 emitcode ("cjne", "a,%s,%05d$"
4668 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4671 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4674 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4675 IS_AOP_PREG (IC_RESULT (ic)))
4676 emitcode ("cjne", "%s,#0xff,%05d$"
4677 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4681 emitcode ("cjne", "a,%s,%05d$"
4682 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4685 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4689 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4690 IS_AOP_PREG (IC_RESULT (ic)))
4691 emitcode ("cjne", "%s,#0xff,%05d$"
4692 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4696 emitcode ("cjne", "a,%s,%05d$"
4697 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4700 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4709 /* if the sizes are greater than 1 then we cannot */
4710 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4711 AOP_SIZE (IC_LEFT (ic)) > 1)
4714 /* we can if the aops of the left & result match or
4715 if they are in registers and the registers are the
4717 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4721 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4723 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4728 l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
4733 emitcode ("dec", "%s", l);
4736 if (AOP_NEEDSACC (IC_RESULT (ic)))
4737 aopPut (IC_RESULT (ic), "a", 0);
4744 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4745 emitcode ("dec", "a");
4746 aopPut (IC_RESULT (ic), "a", 0);
4753 /*-----------------------------------------------------------------*/
4754 /* addSign - complete with sign */
4755 /*-----------------------------------------------------------------*/
4757 addSign (operand * result, int offset, int sign)
4759 int size = (getDataSize (result) - offset);
4764 emitcode ("rlc", "a");
4765 emitcode ("subb", "a,acc");
4768 aopPut (result, "a", offset++);
4775 aopPut (result, zero, offset++);
4781 /*-----------------------------------------------------------------*/
4782 /* genMinusBits - generates code for subtraction of two bits */
4783 /*-----------------------------------------------------------------*/
4785 genMinusBits (iCode * ic)
4787 symbol *lbl = newiTempLabel (NULL);
4789 D (emitcode (";", "genMinusBits"));
4791 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4793 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4794 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4795 emitcode ("cpl", "c");
4797 outBitC (IC_RESULT (ic));
4801 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4802 emitcode ("subb", "a,acc");
4803 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4804 emitcode ("inc", "a");
4806 aopPut (IC_RESULT (ic), "a", 0);
4807 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4811 /*-----------------------------------------------------------------*/
4812 /* genMinus - generates code for subtraction */
4813 /*-----------------------------------------------------------------*/
4815 genMinus (iCode * ic)
4817 int size, offset = 0;
4819 D (emitcode (";", "genMinus"));
4821 aopOp (IC_LEFT (ic), ic, FALSE);
4822 aopOp (IC_RIGHT (ic), ic, FALSE);
4823 aopOp (IC_RESULT (ic), ic, TRUE);
4825 /* special cases :- */
4826 /* if both left & right are in bit space */
4827 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4828 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4834 /* if I can do an decrement instead
4835 of subtract then GOOD for ME */
4836 if (genMinusDec (ic) == TRUE)
4839 size = getDataSize (IC_RESULT (ic));
4841 /* if literal, add a,#-lit, else normal subb */
4842 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4844 unsigned long lit = 0L;
4845 bool useCarry = FALSE;
4847 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4852 if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4854 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4855 if (!offset && !size && lit== (unsigned long) -1)
4857 emitcode ("dec", "a");
4861 /* first add without previous c */
4862 emitcode ("add", "a,#0x%02x",
4863 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4868 emitcode ("addc", "a,#0x%02x",
4869 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4871 aopPut (IC_RESULT (ic), "a", offset++);
4875 /* no need to add zeroes */
4876 if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4878 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4887 operand *leftOp, *rightOp;
4889 leftOp = IC_LEFT(ic);
4890 rightOp = IC_RIGHT(ic);
4894 if (aopGetUsesAcc(rightOp, offset)) {
4895 if (aopGetUsesAcc(leftOp, offset)) {
4898 MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4900 emitcode ("mov", "b,a");
4903 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4904 emitcode ("subb", "a,b");
4907 /* reverse subtraction with 2's complement */
4909 emitcode( "setb", "c");
4911 emitcode( "cpl", "c");
4912 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4913 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4914 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4915 emitcode("cpl", "a");
4916 if (size) /* skip if last byte */
4917 emitcode( "cpl", "c");
4920 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4923 emitcode ("subb", "a,%s",
4924 aopGet(rightOp, offset, FALSE, TRUE));
4927 aopPut (IC_RESULT (ic), "a", offset++);
4931 adjustArithmeticResult (ic);
4934 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4935 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4936 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4940 /*-----------------------------------------------------------------*/
4941 /* genMultbits :- multiplication of bits */
4942 /*-----------------------------------------------------------------*/
4944 genMultbits (operand * left,
4948 D (emitcode (";", "genMultbits"));
4950 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4951 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4955 /*-----------------------------------------------------------------*/
4956 /* genMultOneByte : 8*8=8/16 bit multiplication */
4957 /*-----------------------------------------------------------------*/
4959 genMultOneByte (operand * left,
4964 int size = AOP_SIZE (result);
4965 bool runtimeSign, compiletimeSign;
4966 bool lUnsigned, rUnsigned, pushedB;
4968 D (emitcode (";", "genMultOneByte"));
4970 if (size < 1 || size > 2)
4972 /* this should never happen */
4973 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4974 AOP_SIZE(result), __FILE__, lineno);
4978 /* (if two literals: the value is computed before) */
4979 /* if one literal, literal on the right */
4980 if (AOP_TYPE (left) == AOP_LIT)
4985 /* emitcode (";", "swapped left and right"); */
4987 /* if no literal, unsigned on the right: shorter code */
4988 if ( AOP_TYPE (right) != AOP_LIT
4989 && SPEC_USIGN (getSpec (operandType (left))))
4996 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4997 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5001 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
5002 no need to take care about the signedness! */
5003 || (lUnsigned && rUnsigned))
5005 /* just an unsigned 8 * 8 = 8 multiply
5007 /* emitcode (";","unsigned"); */
5008 /* TODO: check for accumulator clash between left & right aops? */
5010 if (AOP_TYPE (right) == AOP_LIT)
5012 /* moving to accumulator first helps peepholes */
5013 MOVA (aopGet (left, 0, FALSE, FALSE));
5014 MOVB (aopGet (right, 0, FALSE, FALSE));
5018 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5019 MOVA (aopGet (left, 0, FALSE, FALSE));
5022 emitcode ("mul", "ab");
5023 aopPut (result, "a", 0);
5025 aopPut (result, "b", 1);
5031 /* we have to do a signed multiply */
5032 /* emitcode (";", "signed"); */
5034 /* now sign adjust for both left & right */
5036 /* let's see what's needed: */
5037 /* apply negative sign during runtime */
5038 runtimeSign = FALSE;
5039 /* negative sign from literals */
5040 compiletimeSign = FALSE;
5044 if (AOP_TYPE(left) == AOP_LIT)
5046 /* signed literal */
5047 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5049 compiletimeSign = TRUE;
5052 /* signed but not literal */
5058 if (AOP_TYPE(right) == AOP_LIT)
5060 /* signed literal */
5061 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5063 compiletimeSign ^= TRUE;
5066 /* signed but not literal */
5070 /* initialize F0, which stores the runtime sign */
5073 if (compiletimeSign)
5074 emitcode ("setb", "F0"); /* set sign flag */
5076 emitcode ("clr", "F0"); /* reset sign flag */
5079 /* save the signs of the operands */
5080 if (AOP_TYPE(right) == AOP_LIT)
5082 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5084 if (!rUnsigned && val < 0)
5085 emitcode ("mov", "b,#0x%02x", -val);
5087 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5089 else /* ! literal */
5091 if (rUnsigned) /* emitcode (";", "signed"); */
5092 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5095 MOVA (aopGet (right, 0, FALSE, FALSE));
5096 lbl = newiTempLabel (NULL);
5097 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5098 emitcode ("cpl", "F0"); /* complement sign flag */
5099 emitcode ("cpl", "a"); /* 2's complement */
5100 emitcode ("inc", "a");
5102 emitcode ("mov", "b,a");
5106 if (AOP_TYPE(left) == AOP_LIT)
5108 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5110 if (!lUnsigned && val < 0)
5111 emitcode ("mov", "a,#0x%02x", -val);
5113 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5115 else /* ! literal */
5117 MOVA (aopGet (left, 0, FALSE, FALSE));
5121 lbl = newiTempLabel (NULL);
5122 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5123 emitcode ("cpl", "F0"); /* complement sign flag */
5124 emitcode ("cpl", "a"); /* 2's complement */
5125 emitcode ("inc", "a");
5130 /* now the multiplication */
5131 emitcode ("mul", "ab");
5132 if (runtimeSign || compiletimeSign)
5134 lbl = newiTempLabel (NULL);
5136 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5137 emitcode ("cpl", "a"); /* lsb 2's complement */
5139 emitcode ("inc", "a"); /* inc doesn't set carry flag */
5142 emitcode ("add", "a,#1"); /* this sets carry flag */
5143 emitcode ("xch", "a,b");
5144 emitcode ("cpl", "a"); /* msb 2's complement */
5145 emitcode ("addc", "a,#0");
5146 emitcode ("xch", "a,b");
5150 aopPut (result, "a", 0);
5152 aopPut (result, "b", 1);
5157 /*-----------------------------------------------------------------*/
5158 /* genMult - generates code for multiplication */
5159 /*-----------------------------------------------------------------*/
5161 genMult (iCode * ic)
5163 operand *left = IC_LEFT (ic);
5164 operand *right = IC_RIGHT (ic);
5165 operand *result = IC_RESULT (ic);
5167 D (emitcode (";", "genMult"));
5169 /* assign the asmops */
5170 aopOp (left, ic, FALSE);
5171 aopOp (right, ic, FALSE);
5172 aopOp (result, ic, TRUE);
5174 /* special cases first */
5176 if (AOP_TYPE (left) == AOP_CRY &&
5177 AOP_TYPE (right) == AOP_CRY)
5179 genMultbits (left, right, result);
5183 /* if both are of size == 1 */
5184 #if 0 // one of them can be a sloc shared with the result
5185 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
5187 if (getSize(operandType(left)) == 1 &&
5188 getSize(operandType(right)) == 1)
5191 genMultOneByte (left, right, result);
5195 /* should have been converted to function call */
5196 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
5197 getSize(OP_SYMBOL(right)->type));
5201 freeAsmop (result, NULL, ic, TRUE);
5202 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5203 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5206 /*-----------------------------------------------------------------*/
5207 /* genDivbits :- division of bits */
5208 /*-----------------------------------------------------------------*/
5210 genDivbits (operand * left,
5217 D(emitcode ("; genDivbits",""));
5221 /* the result must be bit */
5222 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5223 l = aopGet (left, 0, FALSE, FALSE);
5227 emitcode ("div", "ab");
5228 emitcode ("rrc", "a");
5232 aopPut (result, "c", 0);
5235 /*-----------------------------------------------------------------*/
5236 /* genDivOneByte : 8 bit division */
5237 /*-----------------------------------------------------------------*/
5239 genDivOneByte (operand * left,
5243 bool lUnsigned, rUnsigned, pushedB;
5244 bool runtimeSign, compiletimeSign;
5245 bool accuse = FALSE;
5246 bool pushedA = FALSE;
5250 D(emitcode ("; genDivOneByte",""));
5252 /* Why is it necessary that genDivOneByte() can return an int result?
5255 volatile unsigned char uc;
5256 volatile signed char sc1, sc2;
5269 In all cases a one byte result would overflow, the following cast to int
5270 would return the wrong result.
5272 Two possible solution:
5273 a) cast operands to int, if ((unsigned) / (signed)) or
5274 ((signed) / (signed))
5275 b) return an 16 bit signed int; this is what we're doing here!
5278 size = AOP_SIZE (result) - 1;
5280 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5281 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5285 /* signed or unsigned */
5286 if (lUnsigned && rUnsigned)
5288 /* unsigned is easy */
5289 MOVB (aopGet (right, 0, FALSE, FALSE));
5290 MOVA (aopGet (left, 0, FALSE, FALSE));
5291 emitcode ("div", "ab");
5292 aopPut (result, "a", 0);
5294 aopPut (result, zero, offset++);
5300 /* signed is a little bit more difficult */
5302 /* now sign adjust for both left & right */
5304 /* let's see what's needed: */
5305 /* apply negative sign during runtime */
5306 runtimeSign = FALSE;
5307 /* negative sign from literals */
5308 compiletimeSign = FALSE;
5312 if (AOP_TYPE(left) == AOP_LIT)
5314 /* signed literal */
5315 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5317 compiletimeSign = TRUE;
5320 /* signed but not literal */
5326 if (AOP_TYPE(right) == AOP_LIT)
5328 /* signed literal */
5329 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5331 compiletimeSign ^= TRUE;
5334 /* signed but not literal */
5338 /* initialize F0, which stores the runtime sign */
5341 if (compiletimeSign)
5342 emitcode ("setb", "F0"); /* set sign flag */
5344 emitcode ("clr", "F0"); /* reset sign flag */
5347 /* save the signs of the operands */
5348 if (AOP_TYPE(right) == AOP_LIT)
5350 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5352 if (!rUnsigned && val < 0)
5353 emitcode ("mov", "b,#0x%02x", -val);
5355 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5357 else /* ! literal */
5360 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5363 MOVA (aopGet (right, 0, FALSE, FALSE));
5364 lbl = newiTempLabel (NULL);
5365 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5366 emitcode ("cpl", "F0"); /* complement sign flag */
5367 emitcode ("cpl", "a"); /* 2's complement */
5368 emitcode ("inc", "a");
5370 emitcode ("mov", "b,a");
5374 if (AOP_TYPE(left) == AOP_LIT)
5376 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5378 if (!lUnsigned && val < 0)
5379 emitcode ("mov", "a,#0x%02x", -val);
5381 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5383 else /* ! literal */
5385 MOVA (aopGet (left, 0, FALSE, FALSE));
5389 lbl = newiTempLabel (NULL);
5390 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5391 emitcode ("cpl", "F0"); /* complement sign flag */
5392 emitcode ("cpl", "a"); /* 2's complement */
5393 emitcode ("inc", "a");
5398 /* now the division */
5399 emitcode ("div", "ab");
5401 if (runtimeSign || compiletimeSign)
5403 lbl = newiTempLabel (NULL);
5405 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5406 emitcode ("cpl", "a"); /* lsb 2's complement */
5407 emitcode ("inc", "a");
5410 accuse = aopPut (result, "a", 0);
5413 /* msb is 0x00 or 0xff depending on the sign */
5418 emitcode ("push", "acc");
5421 emitcode ("mov", "c,F0");
5422 emitcode ("subb", "a,acc");
5424 aopPut (result, "a", offset++);
5426 else /* compiletimeSign */
5428 if (aopPutUsesAcc (result, "#0xFF", offset))
5430 emitcode ("push", "acc");
5434 aopPut (result, "#0xff", offset++);
5440 aopPut (result, "a", 0);
5442 aopPut (result, zero, offset++);
5446 emitcode ("pop", "acc");
5450 /*-----------------------------------------------------------------*/
5451 /* genDiv - generates code for division */
5452 /*-----------------------------------------------------------------*/
5456 operand *left = IC_LEFT (ic);
5457 operand *right = IC_RIGHT (ic);
5458 operand *result = IC_RESULT (ic);
5460 D (emitcode (";", "genDiv"));
5462 /* assign the amsops */
5463 aopOp (left, ic, FALSE);
5464 aopOp (right, ic, FALSE);
5465 aopOp (result, ic, TRUE);
5467 /* special cases first */
5469 if (AOP_TYPE (left) == AOP_CRY &&
5470 AOP_TYPE (right) == AOP_CRY)
5472 genDivbits (left, right, result);
5476 /* if both are of size == 1 */
5477 if (AOP_SIZE (left) == 1 &&
5478 AOP_SIZE (right) == 1)
5480 genDivOneByte (left, right, result);
5484 /* should have been converted to function call */
5487 freeAsmop (result, NULL, ic, TRUE);
5488 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5489 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5492 /*-----------------------------------------------------------------*/
5493 /* genModbits :- modulus of bits */
5494 /*-----------------------------------------------------------------*/
5496 genModbits (operand * left,
5503 D (emitcode (";", "genModbits"));
5507 /* the result must be bit */
5508 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5509 l = aopGet (left, 0, FALSE, FALSE);
5513 emitcode ("div", "ab");
5514 emitcode ("mov", "a,b");
5515 emitcode ("rrc", "a");
5519 aopPut (result, "c", 0);
5522 /*-----------------------------------------------------------------*/
5523 /* genModOneByte : 8 bit modulus */
5524 /*-----------------------------------------------------------------*/
5526 genModOneByte (operand * left,
5530 bool lUnsigned, rUnsigned, pushedB;
5531 bool runtimeSign, compiletimeSign;
5535 D (emitcode (";", "genModOneByte"));
5537 size = AOP_SIZE (result) - 1;
5539 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5540 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5542 /* if right is a literal, check it for 2^n */
5543 if (AOP_TYPE(right) == AOP_LIT)
5545 unsigned char val = abs((int) operandLitValue(right));
5546 symbol *lbl2 = NULL;
5550 case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5559 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5560 "modulus of unsigned char by 2^n literal shouldn't be processed here");
5561 /* because iCode should have been changed to genAnd */
5562 /* see file "SDCCopt.c", function "convertToFcall()" */
5564 MOVA (aopGet (left, 0, FALSE, FALSE));
5565 emitcode ("mov", "c,acc.7");
5566 emitcode ("anl", "a,#0x%02x", val - 1);
5567 lbl = newiTempLabel (NULL);
5568 emitcode ("jz", "%05d$", (lbl->key + 100));
5569 emitcode ("jnc", "%05d$", (lbl->key + 100));
5570 emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5576 aopPut (result, "a", 0);
5578 aopPut (result, "#0xff", offs2++);
5579 lbl2 = newiTempLabel (NULL);
5580 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5583 aopPut (result, "a", 0);
5585 aopPut (result, zero, offset++);
5599 /* signed or unsigned */
5600 if (lUnsigned && rUnsigned)
5602 /* unsigned is easy */
5603 MOVB (aopGet (right, 0, FALSE, FALSE));
5604 MOVA (aopGet (left, 0, FALSE, FALSE));
5605 emitcode ("div", "ab");
5606 aopPut (result, "b", 0);
5608 aopPut (result, zero, offset++);
5614 /* signed is a little bit more difficult */
5616 /* now sign adjust for both left & right */
5618 /* modulus: sign of the right operand has no influence on the result! */
5619 if (AOP_TYPE(right) == AOP_LIT)
5621 signed char val = (char) operandLitValue(right);
5623 if (!rUnsigned && val < 0)
5624 emitcode ("mov", "b,#0x%02x", -val);
5626 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5628 else /* not literal */
5631 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5634 MOVA (aopGet (right, 0, FALSE, FALSE));
5635 lbl = newiTempLabel (NULL);
5636 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5637 emitcode ("cpl", "a"); /* 2's complement */
5638 emitcode ("inc", "a");
5640 emitcode ("mov", "b,a");
5644 /* let's see what's needed: */
5645 /* apply negative sign during runtime */
5646 runtimeSign = FALSE;
5647 /* negative sign from literals */
5648 compiletimeSign = FALSE;
5650 /* sign adjust left side */
5651 if (AOP_TYPE(left) == AOP_LIT)
5653 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5655 if (!lUnsigned && val < 0)
5657 compiletimeSign = TRUE; /* set sign flag */
5658 emitcode ("mov", "a,#0x%02x", -val);
5661 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5663 else /* ! literal */
5665 MOVA (aopGet (left, 0, FALSE, FALSE));
5670 emitcode ("clr", "F0"); /* clear sign flag */
5672 lbl = newiTempLabel (NULL);
5673 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5674 emitcode ("setb", "F0"); /* set sign flag */
5675 emitcode ("cpl", "a"); /* 2's complement */
5676 emitcode ("inc", "a");
5681 /* now the modulus */
5682 emitcode ("div", "ab");
5684 if (runtimeSign || compiletimeSign)
5686 emitcode ("mov", "a,b");
5687 lbl = newiTempLabel (NULL);
5689 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5690 emitcode ("cpl", "a"); /* 2's complement */
5691 emitcode ("inc", "a");
5694 aopPut (result, "a", 0);
5697 /* msb is 0x00 or 0xff depending on the sign */
5700 emitcode ("mov", "c,F0");
5701 emitcode ("subb", "a,acc");
5703 aopPut (result, "a", offset++);
5705 else /* compiletimeSign */
5707 aopPut (result, "#0xff", offset++);
5712 aopPut (result, "b", 0);
5714 aopPut (result, zero, offset++);
5720 /*-----------------------------------------------------------------*/
5721 /* genMod - generates code for division */
5722 /*-----------------------------------------------------------------*/
5726 operand *left = IC_LEFT (ic);
5727 operand *right = IC_RIGHT (ic);
5728 operand *result = IC_RESULT (ic);
5730 D (emitcode (";", "genMod"));
5732 /* assign the asmops */
5733 aopOp (left, ic, FALSE);
5734 aopOp (right, ic, FALSE);
5735 aopOp (result, ic, TRUE);
5737 /* special cases first */
5739 if (AOP_TYPE (left) == AOP_CRY &&
5740 AOP_TYPE (right) == AOP_CRY)
5742 genModbits (left, right, result);
5746 /* if both are of size == 1 */
5747 if (AOP_SIZE (left) == 1 &&
5748 AOP_SIZE (right) == 1)
5750 genModOneByte (left, right, result);
5754 /* should have been converted to function call */
5758 freeAsmop (result, NULL, ic, TRUE);
5759 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5760 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5763 /*-----------------------------------------------------------------*/
5764 /* genIfxJump :- will create a jump depending on the ifx */
5765 /*-----------------------------------------------------------------*/
5767 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5770 symbol *tlbl = newiTempLabel (NULL);
5773 D (emitcode (";", "genIfxJump"));
5775 /* if true label then we jump if condition
5779 jlbl = IC_TRUE (ic);
5780 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5781 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5785 /* false label is present */
5786 jlbl = IC_FALSE (ic);
5787 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5788 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5790 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5791 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5793 emitcode (inst, "%05d$", tlbl->key + 100);
5794 freeForBranchAsmop (result);
5795 freeForBranchAsmop (right);
5796 freeForBranchAsmop (left);
5797 emitcode ("ljmp", "%05d$", jlbl->key + 100);
5800 /* mark the icode as generated */
5804 /*-----------------------------------------------------------------*/
5805 /* genCmp :- greater or less than comparison */
5806 /*-----------------------------------------------------------------*/
5808 genCmp (operand * left, operand * right,
5809 operand * result, iCode * ifx, int sign, iCode *ic)
5811 int size, offset = 0;
5812 unsigned long lit = 0L;
5815 D (emitcode (";", "genCmp"));
5817 /* if left & right are bit variables */
5818 if (AOP_TYPE (left) == AOP_CRY &&
5819 AOP_TYPE (right) == AOP_CRY)
5821 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5822 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5826 /* subtract right from left if at the
5827 end the carry flag is set then we know that
5828 left is greater than right */
5829 size = max (AOP_SIZE (left), AOP_SIZE (right));
5831 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5832 if ((size == 1) && !sign &&
5833 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5835 symbol *lbl = newiTempLabel (NULL);
5836 emitcode ("cjne", "%s,%s,%05d$",
5837 aopGet (left, offset, FALSE, FALSE),
5838 aopGet (right, offset, FALSE, FALSE),
5844 if (AOP_TYPE (right) == AOP_LIT)
5846 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5847 /* optimize if(x < 0) or if(x >= 0) */
5856 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5857 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5859 genIfxJump (ifx, "acc.7", left, right, result);
5860 freeAsmop (right, NULL, ic, TRUE);
5861 freeAsmop (left, NULL, ic, TRUE);
5867 emitcode ("rlc", "a");
5874 int bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5875 while (size && (bytelit == 0))
5878 bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5884 MOVA (aopGet (left, offset, FALSE, FALSE));
5885 if (sign && size == 0)
5887 emitcode ("xrl", "a,#0x80");
5888 emitcode ("subb", "a,#0x%02x",
5889 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5893 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5903 bool pushedB = FALSE;
5904 rightInB = aopGetUsesAcc(right, offset);
5908 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5910 MOVA (aopGet (left, offset, FALSE, FALSE));
5911 if (sign && size == 0)
5913 emitcode ("xrl", "a,#0x80");
5918 MOVB (aopGet (right, offset, FALSE, FALSE));
5920 emitcode ("xrl", "b,#0x80");
5921 emitcode ("subb", "a,b");
5926 emitcode ("subb", "a,b");
5928 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5938 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5939 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5940 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5946 /* if the result is used in the next
5947 ifx conditional branch then generate
5948 code a little differently */
5951 genIfxJump (ifx, "c", NULL, NULL, result);
5957 /* leave the result in acc */
5961 /*-----------------------------------------------------------------*/
5962 /* genCmpGt :- greater than comparison */
5963 /*-----------------------------------------------------------------*/
5965 genCmpGt (iCode * ic, iCode * ifx)
5967 operand *left, *right, *result;
5968 sym_link *letype, *retype;
5971 D (emitcode (";", "genCmpGt"));
5973 left = IC_LEFT (ic);
5974 right = IC_RIGHT (ic);
5975 result = IC_RESULT (ic);
5977 letype = getSpec (operandType (left));
5978 retype = getSpec (operandType (right));
5979 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5980 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5981 /* assign the amsops */
5982 aopOp (result, ic, TRUE);
5983 aopOp (left, ic, FALSE);
5984 aopOp (right, ic, FALSE);
5986 genCmp (right, left, result, ifx, sign, ic);
5988 freeAsmop (result, NULL, ic, TRUE);
5991 /*-----------------------------------------------------------------*/
5992 /* genCmpLt - less than comparisons */
5993 /*-----------------------------------------------------------------*/
5995 genCmpLt (iCode * ic, iCode * ifx)
5997 operand *left, *right, *result;
5998 sym_link *letype, *retype;
6001 D (emitcode (";", "genCmpLt"));
6003 left = IC_LEFT (ic);
6004 right = IC_RIGHT (ic);
6005 result = IC_RESULT (ic);
6007 letype = getSpec (operandType (left));
6008 retype = getSpec (operandType (right));
6009 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
6010 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
6011 /* assign the amsops */
6012 aopOp (result, ic, TRUE);
6013 aopOp (left, ic, FALSE);
6014 aopOp (right, ic, FALSE);
6016 genCmp (left, right, result, ifx, sign, ic);
6018 freeAsmop (result, NULL, ic, TRUE);
6021 /*-----------------------------------------------------------------*/
6022 /* gencjneshort - compare and jump if not equal */
6023 /*-----------------------------------------------------------------*/
6025 gencjneshort (operand * left, operand * right, symbol * lbl)
6027 int size = max (AOP_SIZE (left), AOP_SIZE (right));
6029 unsigned long lit = 0L;
6031 D (emitcode (";", "gencjneshort"));
6033 /* if the left side is a literal or
6034 if the right is in a pointer register and left
6036 if ((AOP_TYPE (left) == AOP_LIT) ||
6037 (AOP_TYPE (left) == AOP_IMMD) ||
6038 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6045 if (AOP_TYPE (right) == AOP_LIT)
6046 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6048 /* if the right side is a literal then anything goes */
6049 if (AOP_TYPE (right) == AOP_LIT &&
6050 AOP_TYPE (left) != AOP_DIR &&
6051 AOP_TYPE (left) != AOP_IMMD)
6055 emitcode ("cjne", "%s,%s,%05d$",
6056 aopGet (left, offset, FALSE, FALSE),
6057 aopGet (right, offset, FALSE, FALSE),
6063 /* if the right side is in a register or in direct space or
6064 if the left is a pointer register & right is not */
6065 else if (AOP_TYPE (right) == AOP_REG ||
6066 AOP_TYPE (right) == AOP_DIR ||
6067 AOP_TYPE (right) == AOP_LIT ||
6068 AOP_TYPE (right) == AOP_IMMD ||
6069 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6070 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6074 MOVA (aopGet (left, offset, FALSE, FALSE));
6075 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6076 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6077 emitcode ("jnz", "%05d$", lbl->key + 100);
6079 emitcode ("cjne", "a,%s,%05d$",
6080 aopGet (right, offset, FALSE, TRUE),
6087 /* right is a pointer reg need both a & b */
6090 //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
6091 wassertl(!BINUSE, "B was in use");
6092 MOVB (aopGet (left, offset, FALSE, FALSE));
6093 MOVA (aopGet (right, offset, FALSE, FALSE));
6094 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
6100 /*-----------------------------------------------------------------*/
6101 /* gencjne - compare and jump if not equal */
6102 /*-----------------------------------------------------------------*/
6104 gencjne (operand * left, operand * right, symbol * lbl)
6106 symbol *tlbl = newiTempLabel (NULL);
6108 D (emitcode (";", "gencjne"));
6110 gencjneshort (left, right, lbl);
6112 emitcode ("mov", "a,%s", one);
6113 emitcode ("sjmp", "%05d$", tlbl->key + 100);
6115 emitcode ("clr", "a");
6119 /*-----------------------------------------------------------------*/
6120 /* genCmpEq - generates code for equal to */
6121 /*-----------------------------------------------------------------*/
6123 genCmpEq (iCode * ic, iCode * ifx)
6125 bool swappedLR = FALSE;
6126 operand *left, *right, *result;
6128 D (emitcode (";", "genCmpEq"));
6130 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6131 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6132 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6134 /* if literal, literal on the right or
6135 if the right is in a pointer register and left
6137 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6138 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6140 operand *t = IC_RIGHT (ic);
6141 IC_RIGHT (ic) = IC_LEFT (ic);
6146 if (ifx && !AOP_SIZE (result))
6149 /* if they are both bit variables */
6150 if (AOP_TYPE (left) == AOP_CRY &&
6151 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6153 if (AOP_TYPE (right) == AOP_LIT)
6155 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6158 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6159 emitcode ("cpl", "c");
6163 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6167 emitcode ("clr", "c");
6169 /* AOP_TYPE(right) == AOP_CRY */
6173 symbol *lbl = newiTempLabel (NULL);
6174 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6175 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6176 emitcode ("cpl", "c");
6179 /* if true label then we jump if condition
6181 tlbl = newiTempLabel (NULL);
6184 emitcode ("jnc", "%05d$", tlbl->key + 100);
6185 freeForBranchAsmop (result);
6186 freeForBranchAsmop (right);
6187 freeForBranchAsmop (left);
6188 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6192 emitcode ("jc", "%05d$", tlbl->key + 100);
6193 freeForBranchAsmop (result);
6194 freeForBranchAsmop (right);
6195 freeForBranchAsmop (left);
6196 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6202 tlbl = newiTempLabel (NULL);
6203 gencjneshort (left, right, tlbl);
6206 freeForBranchAsmop (result);
6207 freeForBranchAsmop (right);
6208 freeForBranchAsmop (left);
6209 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6214 symbol *lbl = newiTempLabel (NULL);
6215 emitcode ("sjmp", "%05d$", lbl->key + 100);
6217 freeForBranchAsmop (result);
6218 freeForBranchAsmop (right);
6219 freeForBranchAsmop (left);
6220 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6224 /* mark the icode as generated */
6229 /* if they are both bit variables */
6230 if (AOP_TYPE (left) == AOP_CRY &&
6231 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6233 if (AOP_TYPE (right) == AOP_LIT)
6235 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6238 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6239 emitcode ("cpl", "c");
6243 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6247 emitcode ("clr", "c");
6249 /* AOP_TYPE(right) == AOP_CRY */
6253 symbol *lbl = newiTempLabel (NULL);
6254 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6255 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6256 emitcode ("cpl", "c");
6260 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6267 genIfxJump (ifx, "c", left, right, result);
6270 /* if the result is used in an arithmetic operation
6271 then put the result in place */
6276 gencjne (left, right, newiTempLabel (NULL));
6277 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6279 aopPut (result, "a", 0);
6284 genIfxJump (ifx, "a", left, right, result);
6287 /* if the result is used in an arithmetic operation
6288 then put the result in place */
6289 if (AOP_TYPE (result) != AOP_CRY)
6291 /* leave the result in acc */
6295 freeAsmop (result, NULL, ic, TRUE);
6298 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6299 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6303 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6304 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6308 /*-----------------------------------------------------------------*/
6309 /* ifxForOp - returns the icode containing the ifx for operand */
6310 /*-----------------------------------------------------------------*/
6312 ifxForOp (operand * op, iCode * ic)
6314 /* if true symbol then needs to be assigned */
6315 if (IS_TRUE_SYMOP (op))
6318 /* if this has register type condition and
6319 the next instruction is ifx with the same operand
6320 and live to of the operand is upto the ifx only then */
6322 ic->next->op == IFX &&
6323 IC_COND (ic->next)->key == op->key &&
6324 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6330 /*-----------------------------------------------------------------*/
6331 /* hasInc - operand is incremented before any other use */
6332 /*-----------------------------------------------------------------*/
6334 hasInc (operand *op, iCode *ic, int osize)
6336 sym_link *type = operandType(op);
6337 sym_link *retype = getSpec (type);
6338 iCode *lic = ic->next;
6341 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6342 if (!IS_SYMOP(op)) return NULL;
6344 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6345 if (IS_AGGREGATE(type->next)) return NULL;
6346 if (osize != (isize = getSize(type->next))) return NULL;
6349 /* if operand of the form op = op + <sizeof *op> */
6350 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6351 isOperandEqual(IC_RESULT(lic),op) &&
6352 isOperandLiteral(IC_RIGHT(lic)) &&
6353 operandLitValue(IC_RIGHT(lic)) == isize) {
6356 /* if the operand used or deffed */
6357 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6360 /* if GOTO or IFX */
6361 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6367 /*-----------------------------------------------------------------*/
6368 /* genAndOp - for && operation */
6369 /*-----------------------------------------------------------------*/
6371 genAndOp (iCode * ic)
6373 operand *left, *right, *result;
6376 D (emitcode (";", "genAndOp"));
6378 /* note here that && operations that are in an
6379 if statement are taken away by backPatchLabels
6380 only those used in arthmetic operations remain */
6381 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6382 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6383 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6385 /* if both are bit variables */
6386 if (AOP_TYPE (left) == AOP_CRY &&
6387 AOP_TYPE (right) == AOP_CRY)
6389 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6390 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6395 tlbl = newiTempLabel (NULL);
6397 emitcode ("jz", "%05d$", tlbl->key + 100);
6403 freeAsmop (result, NULL, ic, TRUE);
6404 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6405 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6409 /*-----------------------------------------------------------------*/
6410 /* genOrOp - for || operation */
6411 /*-----------------------------------------------------------------*/
6413 genOrOp (iCode * ic)
6415 operand *left, *right, *result;
6418 D (emitcode (";", "genOrOp"));
6420 /* note here that || operations that are in an
6421 if statement are taken away by backPatchLabels
6422 only those used in arthmetic operations remain */
6423 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6424 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6425 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6427 /* if both are bit variables */
6428 if (AOP_TYPE (left) == AOP_CRY &&
6429 AOP_TYPE (right) == AOP_CRY)
6431 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6432 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6437 tlbl = newiTempLabel (NULL);
6439 emitcode ("jnz", "%05d$", tlbl->key + 100);
6445 freeAsmop (result, NULL, ic, TRUE);
6446 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6447 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6450 /*-----------------------------------------------------------------*/
6451 /* isLiteralBit - test if lit == 2^n */
6452 /*-----------------------------------------------------------------*/
6454 isLiteralBit (unsigned long lit)
6456 unsigned long pw[32] =
6457 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6458 0x100L, 0x200L, 0x400L, 0x800L,
6459 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6460 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6461 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6462 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6463 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6466 for (idx = 0; idx < 32; idx++)
6472 /*-----------------------------------------------------------------*/
6473 /* continueIfTrue - */
6474 /*-----------------------------------------------------------------*/
6476 continueIfTrue (iCode * ic)
6479 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6483 /*-----------------------------------------------------------------*/
6485 /*-----------------------------------------------------------------*/
6487 jumpIfTrue (iCode * ic)
6490 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6494 /*-----------------------------------------------------------------*/
6495 /* jmpTrueOrFalse - */
6496 /*-----------------------------------------------------------------*/
6498 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6500 // ugly but optimized by peephole
6503 symbol *nlbl = newiTempLabel (NULL);
6504 emitcode ("sjmp", "%05d$", nlbl->key + 100);
6506 freeForBranchAsmop (result);
6507 freeForBranchAsmop (right);
6508 freeForBranchAsmop (left);
6509 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6514 freeForBranchAsmop (result);
6515 freeForBranchAsmop (right);
6516 freeForBranchAsmop (left);
6517 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6523 /*-----------------------------------------------------------------*/
6524 /* genAnd - code for and */
6525 /*-----------------------------------------------------------------*/
6527 genAnd (iCode * ic, iCode * ifx)
6529 operand *left, *right, *result;
6530 int size, offset = 0;
6531 unsigned long lit = 0L;
6535 D (emitcode (";", "genAnd"));
6537 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6538 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6539 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6542 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6544 AOP_TYPE (left), AOP_TYPE (right));
6545 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6547 AOP_SIZE (left), AOP_SIZE (right));
6550 /* if left is a literal & right is not then exchange them */
6551 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6552 AOP_NEEDSACC (left))
6554 operand *tmp = right;
6559 /* if result = right then exchange left and right */
6560 if (sameRegs (AOP (result), AOP (right)))
6562 operand *tmp = right;
6567 /* if right is bit then exchange them */
6568 if (AOP_TYPE (right) == AOP_CRY &&
6569 AOP_TYPE (left) != AOP_CRY)
6571 operand *tmp = right;
6575 if (AOP_TYPE (right) == AOP_LIT)
6576 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6578 size = AOP_SIZE (result);
6581 // result = bit & yy;
6582 if (AOP_TYPE (left) == AOP_CRY)
6584 // c = bit & literal;
6585 if (AOP_TYPE (right) == AOP_LIT)
6589 if (size && sameRegs (AOP (result), AOP (left)))
6592 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6597 if (size && (AOP_TYPE (result) == AOP_CRY))
6599 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6602 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6607 emitcode ("clr", "c");
6612 if (AOP_TYPE (right) == AOP_CRY)
6615 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6616 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6621 MOVA (aopGet (right, 0, FALSE, FALSE));
6623 emitcode ("rrc", "a");
6624 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6632 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6633 genIfxJump (ifx, "c", left, right, result);
6637 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6638 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6639 if ((AOP_TYPE (right) == AOP_LIT) &&
6640 (AOP_TYPE (result) == AOP_CRY) &&
6641 (AOP_TYPE (left) != AOP_CRY))
6643 int posbit = isLiteralBit (lit);
6648 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6652 switch (posbit & 0x07)
6654 case 0: emitcode ("rrc", "a");
6656 case 7: emitcode ("rlc", "a");
6658 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6667 SNPRINTF (buffer, sizeof(buffer),
6668 "acc.%d", posbit & 0x07);
6669 genIfxJump (ifx, buffer, left, right, result);
6672 {// what is this case? just found it in ds390/gen.c
6673 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6680 symbol *tlbl = newiTempLabel (NULL);
6681 int sizel = AOP_SIZE (left);
6683 emitcode ("setb", "c");
6686 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6688 MOVA (aopGet (left, offset, FALSE, FALSE));
6690 if ((posbit = isLiteralBit (bytelit)) != 0)
6691 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6694 if (bytelit != 0x0FFL)
6695 emitcode ("anl", "a,%s",
6696 aopGet (right, offset, FALSE, TRUE));
6697 emitcode ("jnz", "%05d$", tlbl->key + 100);
6702 // bit = left & literal
6705 emitcode ("clr", "c");
6708 // if(left & literal)
6712 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6722 /* if left is same as result */
6723 if (sameRegs (AOP (result), AOP (left)))
6725 for (; size--; offset++)
6727 if (AOP_TYPE (right) == AOP_LIT)
6729 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6730 if (bytelit == 0x0FF)
6732 /* dummy read of volatile operand */
6733 if (isOperandVolatile (left, FALSE))
6734 MOVA (aopGet (left, offset, FALSE, FALSE));
6738 else if (bytelit == 0)
6740 aopPut (result, zero, offset);
6742 else if (IS_AOP_PREG (result))
6744 MOVA (aopGet (left, offset, FALSE, TRUE));
6745 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6746 aopPut (result, "a", offset);
6749 emitcode ("anl", "%s,%s",
6750 aopGet (left, offset, FALSE, TRUE),
6751 aopGet (right, offset, FALSE, FALSE));
6755 if (AOP_TYPE (left) == AOP_ACC)
6758 emitcode("mov", "a,b");
6759 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6761 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6763 MOVB (aopGet (left, offset, FALSE, FALSE));
6764 MOVA (aopGet (right, offset, FALSE, FALSE));
6765 emitcode ("anl", "a,b");
6766 aopPut (result, "a", offset);
6768 else if (aopGetUsesAcc (left, offset))
6770 MOVA (aopGet (left, offset, FALSE, FALSE));
6771 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6772 aopPut (result, "a", offset);
6776 MOVA (aopGet (right, offset, FALSE, FALSE));
6777 if (IS_AOP_PREG (result))
6779 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6780 aopPut (result, "a", offset);
6783 emitcode ("anl", "%s,a", aopGet (left, offset, FALSE, TRUE));
6790 // left & result in different registers
6791 if (AOP_TYPE (result) == AOP_CRY)
6794 // if(size), result in bit
6795 // if(!size && ifx), conditional oper: if(left & right)
6796 symbol *tlbl = newiTempLabel (NULL);
6797 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6799 emitcode ("setb", "c");
6802 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6803 && AOP_TYPE(left)==AOP_ACC)
6806 emitcode("mov", "a,b");
6807 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6809 else if (AOP_TYPE(left)==AOP_ACC)
6813 bool pushedB = pushB ();
6814 emitcode("mov", "b,a");
6815 MOVA (aopGet (right, offset, FALSE, FALSE));
6816 emitcode("anl", "a,b");
6821 MOVA (aopGet (right, offset, FALSE, FALSE));
6822 emitcode("anl", "a,b");
6825 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6827 MOVB (aopGet (left, offset, FALSE, FALSE));
6828 MOVA (aopGet (right, offset, FALSE, FALSE));
6829 emitcode ("anl", "a,b");
6831 else if (aopGetUsesAcc (left, offset))
6833 MOVA (aopGet (left, offset, FALSE, FALSE));
6834 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6838 MOVA (aopGet (right, offset, FALSE, FALSE));
6839 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6842 emitcode ("jnz", "%05d$", tlbl->key + 100);
6852 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6858 for (; (size--); offset++)
6861 // result = left & right
6862 if (AOP_TYPE (right) == AOP_LIT)
6864 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6865 if (bytelit == 0x0FF)
6868 aopGet (left, offset, FALSE, FALSE),
6872 else if (bytelit == 0)
6874 /* dummy read of volatile operand */
6875 if (isOperandVolatile (left, FALSE))
6876 MOVA (aopGet (left, offset, FALSE, FALSE));
6877 aopPut (result, zero, offset);
6880 else if (AOP_TYPE (left) == AOP_ACC)
6884 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6885 aopPut (result, "a", offset);
6890 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6891 aopPut (result, "b", offset);
6896 // faster than result <- left, anl result,right
6897 // and better if result is SFR
6898 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6899 && AOP_TYPE(left)==AOP_ACC)
6902 emitcode("mov", "a,b");
6903 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6905 else if (AOP_TYPE(left)==AOP_ACC)
6909 bool pushedB = pushB ();
6910 emitcode("mov", "b,a");
6911 MOVA (aopGet (right, offset, FALSE, FALSE));
6912 emitcode("anl", "a,b");
6917 MOVA (aopGet (right, offset, FALSE, FALSE));
6918 emitcode("anl", "a,b");
6921 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6923 MOVB (aopGet (left, offset, FALSE, FALSE));
6924 MOVA (aopGet (right, offset, FALSE, FALSE));
6925 emitcode ("anl", "a,b");
6927 else if (aopGetUsesAcc (left, offset))
6929 MOVA (aopGet (left, offset, FALSE, FALSE));
6930 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6934 MOVA (aopGet (right, offset, FALSE, FALSE));
6935 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6937 aopPut (result, "a", offset);
6943 freeAsmop (result, NULL, ic, TRUE);
6944 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6945 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6948 /*-----------------------------------------------------------------*/
6949 /* genOr - code for or */
6950 /*-----------------------------------------------------------------*/
6952 genOr (iCode * ic, iCode * ifx)
6954 operand *left, *right, *result;
6955 int size, offset = 0;
6956 unsigned long lit = 0L;
6959 D (emitcode (";", "genOr"));
6961 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6962 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6963 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6966 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6968 AOP_TYPE (left), AOP_TYPE (right));
6969 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6971 AOP_SIZE (left), AOP_SIZE (right));
6974 /* if left is a literal & right is not then exchange them */
6975 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6976 AOP_NEEDSACC (left))
6978 operand *tmp = right;
6983 /* if result = right then exchange them */
6984 if (sameRegs (AOP (result), AOP (right)))
6986 operand *tmp = right;
6991 /* if right is bit then exchange them */
6992 if (AOP_TYPE (right) == AOP_CRY &&
6993 AOP_TYPE (left) != AOP_CRY)
6995 operand *tmp = right;
6999 if (AOP_TYPE (right) == AOP_LIT)
7000 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7002 size = AOP_SIZE (result);
7006 if (AOP_TYPE (left) == AOP_CRY)
7008 if (AOP_TYPE (right) == AOP_LIT)
7010 // c = bit | literal;
7013 // lit != 0 => result = 1
7014 if (AOP_TYPE (result) == AOP_CRY)
7017 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7019 continueIfTrue (ifx);
7022 emitcode ("setb", "c");
7026 // lit == 0 => result = left
7027 if (size && sameRegs (AOP (result), AOP (left)))
7029 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7034 if (AOP_TYPE (right) == AOP_CRY)
7037 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7038 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7043 symbol *tlbl = newiTempLabel (NULL);
7044 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
7045 emitcode ("setb", "c");
7046 emitcode ("jb", "%s,%05d$",
7047 AOP (left)->aopu.aop_dir, tlbl->key + 100);
7049 emitcode ("jnz", "%05d$", tlbl->key + 100);
7050 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7052 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7067 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7068 genIfxJump (ifx, "c", left, right, result);
7072 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7073 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7074 if ((AOP_TYPE (right) == AOP_LIT) &&
7075 (AOP_TYPE (result) == AOP_CRY) &&
7076 (AOP_TYPE (left) != AOP_CRY))
7082 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7084 continueIfTrue (ifx);
7089 // lit = 0, result = boolean(left)
7091 emitcode ("setb", "c");
7095 symbol *tlbl = newiTempLabel (NULL);
7096 emitcode ("jnz", "%05d$", tlbl->key + 100);
7102 genIfxJump (ifx, "a", left, right, result);
7110 /* if left is same as result */
7111 if (sameRegs (AOP (result), AOP (left)))
7113 for (; size--; offset++)
7115 if (AOP_TYPE (right) == AOP_LIT)
7117 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7120 /* dummy read of volatile operand */
7121 if (isOperandVolatile (left, FALSE))
7122 MOVA (aopGet (left, offset, FALSE, FALSE));
7126 else if (bytelit == 0x0FF)
7128 aopPut (result, "#0xFF", offset);
7130 else if (IS_AOP_PREG (left))
7132 MOVA (aopGet (left, offset, FALSE, TRUE));
7133 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7134 aopPut (result, "a", offset);
7138 emitcode ("orl", "%s,%s",
7139 aopGet (left, offset, FALSE, TRUE),
7140 aopGet (right, offset, FALSE, FALSE));
7145 if (AOP_TYPE (left) == AOP_ACC)
7148 emitcode("mov", "a,b");
7149 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7151 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7153 MOVB (aopGet (left, offset, FALSE, FALSE));
7154 MOVA (aopGet (right, offset, FALSE, FALSE));
7155 emitcode ("orl", "a,b");
7156 aopPut (result, "a", offset);
7158 else if (aopGetUsesAcc (left, offset))
7160 MOVA (aopGet (left, offset, FALSE, FALSE));
7161 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7162 aopPut (result, "a", offset);
7166 MOVA (aopGet (right, offset, FALSE, FALSE));
7167 if (IS_AOP_PREG (left))
7169 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7170 aopPut (result, "a", offset);
7174 emitcode ("orl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7182 // left & result in different registers
7183 if (AOP_TYPE (result) == AOP_CRY)
7186 // if(size), result in bit
7187 // if(!size && ifx), conditional oper: if(left | right)
7188 symbol *tlbl = newiTempLabel (NULL);
7189 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7191 emitcode ("setb", "c");
7194 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7195 && AOP_TYPE(left)==AOP_ACC)
7198 emitcode("mov", "a,b");
7199 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7201 else if (AOP_TYPE(left)==AOP_ACC)
7205 bool pushedB = pushB ();
7206 emitcode("mov", "b,a");
7207 MOVA (aopGet (right, offset, FALSE, FALSE));
7208 emitcode("orl", "a,b");
7213 MOVA (aopGet (right, offset, FALSE, FALSE));
7214 emitcode("orl", "a,b");
7217 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7219 MOVB (aopGet (left, offset, FALSE, FALSE));
7220 MOVA (aopGet (right, offset, FALSE, FALSE));
7221 emitcode ("orl", "a,b");
7223 else if (aopGetUsesAcc (left, offset))
7225 MOVA (aopGet (left, offset, FALSE, FALSE));
7226 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7230 MOVA (aopGet (right, offset, FALSE, FALSE));
7231 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7234 emitcode ("jnz", "%05d$", tlbl->key + 100);
7244 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7250 for (; (size--); offset++)
7253 // result = left | right
7254 if (AOP_TYPE (right) == AOP_LIT)
7256 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7260 aopGet (left, offset, FALSE, FALSE),
7264 else if (bytelit == 0x0FF)
7266 /* dummy read of volatile operand */
7267 if (isOperandVolatile (left, FALSE))
7268 MOVA (aopGet (left, offset, FALSE, FALSE));
7269 aopPut (result, "#0xFF", offset);
7273 // faster than result <- left, orl result,right
7274 // and better if result is SFR
7275 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7276 && AOP_TYPE(left)==AOP_ACC)
7279 emitcode("mov", "a,b");
7280 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7282 else if (AOP_TYPE(left)==AOP_ACC)
7286 bool pushedB = pushB ();
7287 emitcode("mov", "b,a");
7288 MOVA (aopGet (right, offset, FALSE, FALSE));
7289 emitcode("orl", "a,b");
7294 MOVA (aopGet (right, offset, FALSE, FALSE));
7295 emitcode("orl", "a,b");
7298 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7300 MOVB (aopGet (left, offset, FALSE, FALSE));
7301 MOVA (aopGet (right, offset, FALSE, FALSE));
7302 emitcode ("orl", "a,b");
7304 else if (aopGetUsesAcc (left, offset))
7306 MOVA (aopGet (left, offset, FALSE, FALSE));
7307 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7311 MOVA (aopGet (right, offset, FALSE, FALSE));
7312 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7314 aopPut (result, "a", offset);
7320 freeAsmop (result, NULL, ic, TRUE);
7321 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7322 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7325 /*-----------------------------------------------------------------*/
7326 /* genXor - code for xclusive or */
7327 /*-----------------------------------------------------------------*/
7329 genXor (iCode * ic, iCode * ifx)
7331 operand *left, *right, *result;
7332 int size, offset = 0;
7333 unsigned long lit = 0L;
7336 D (emitcode (";", "genXor"));
7338 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7339 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7340 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7343 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7345 AOP_TYPE (left), AOP_TYPE (right));
7346 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7348 AOP_SIZE (left), AOP_SIZE (right));
7351 /* if left is a literal & right is not ||
7352 if left needs acc & right does not */
7353 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7354 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7356 operand *tmp = right;
7361 /* if result = right then exchange them */
7362 if (sameRegs (AOP (result), AOP (right)))
7364 operand *tmp = right;
7369 /* if right is bit then exchange them */
7370 if (AOP_TYPE (right) == AOP_CRY &&
7371 AOP_TYPE (left) != AOP_CRY)
7373 operand *tmp = right;
7377 if (AOP_TYPE (right) == AOP_LIT)
7378 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7380 size = AOP_SIZE (result);
7384 if (AOP_TYPE (left) == AOP_CRY)
7386 if (AOP_TYPE (right) == AOP_LIT)
7388 // c = bit & literal;
7391 // lit>>1 != 0 => result = 1
7392 if (AOP_TYPE (result) == AOP_CRY)
7395 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7397 continueIfTrue (ifx);
7400 emitcode ("setb", "c");
7407 // lit == 0, result = left
7408 if (size && sameRegs (AOP (result), AOP (left)))
7410 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7414 // lit == 1, result = not(left)
7415 if (size && sameRegs (AOP (result), AOP (left)))
7417 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7422 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7423 emitcode ("cpl", "c");
7431 symbol *tlbl = newiTempLabel (NULL);
7432 if (AOP_TYPE (right) == AOP_CRY)
7435 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7439 int sizer = AOP_SIZE (right);
7441 // if val>>1 != 0, result = 1
7442 emitcode ("setb", "c");
7445 MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
7447 // test the msb of the lsb
7448 emitcode ("anl", "a,#0xfe");
7449 emitcode ("jnz", "%05d$", tlbl->key + 100);
7453 emitcode ("rrc", "a");
7455 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7456 emitcode ("cpl", "c");
7464 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7465 genIfxJump (ifx, "c", left, right, result);
7469 /* if left is same as result */
7470 if (sameRegs (AOP (result), AOP (left)))
7472 for (; size--; offset++)
7474 if (AOP_TYPE (right) == AOP_LIT)
7476 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7479 /* dummy read of volatile operand */
7480 if (isOperandVolatile (left, FALSE))
7481 MOVA (aopGet (left, offset, FALSE, FALSE));
7485 else if (IS_AOP_PREG (left))
7487 MOVA (aopGet (left, offset, FALSE, TRUE));
7488 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7489 aopPut (result, "a", offset);
7493 emitcode ("xrl", "%s,%s",
7494 aopGet (left, offset, FALSE, TRUE),
7495 aopGet (right, offset, FALSE, FALSE));
7500 if (AOP_TYPE (left) == AOP_ACC)
7503 emitcode("mov", "a,b");
7504 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7506 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7508 MOVB (aopGet (left, offset, FALSE, FALSE));
7509 MOVA (aopGet (right, offset, FALSE, FALSE));
7510 emitcode ("xrl", "a,b");
7511 aopPut (result, "a", offset);
7513 else if (aopGetUsesAcc (left, offset))
7515 MOVA (aopGet (left, offset, FALSE, FALSE));
7516 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7517 aopPut (result, "a", offset);
7521 MOVA (aopGet (right, offset, FALSE, FALSE));
7522 if (IS_AOP_PREG (left))
7524 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7525 aopPut (result, "a", offset);
7528 emitcode ("xrl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7535 // left & result in different registers
7536 if (AOP_TYPE (result) == AOP_CRY)
7539 // if(size), result in bit
7540 // if(!size && ifx), conditional oper: if(left ^ right)
7541 symbol *tlbl = newiTempLabel (NULL);
7542 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7545 emitcode ("setb", "c");
7548 if ((AOP_TYPE (right) == AOP_LIT) &&
7549 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7551 MOVA (aopGet (left, offset, FALSE, FALSE));
7553 else if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7554 && AOP_TYPE(left)==AOP_ACC)
7557 emitcode("mov", "a,b");
7558 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7560 else if (AOP_TYPE(left)==AOP_ACC)
7564 bool pushedB = pushB ();
7565 emitcode("mov", "b,a");
7566 MOVA (aopGet (right, offset, FALSE, FALSE));
7567 emitcode("xrl", "a,b");
7572 MOVA (aopGet (right, offset, FALSE, FALSE));
7573 emitcode("xrl", "a,b");
7576 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7578 MOVB (aopGet (left, offset, FALSE, FALSE));
7579 MOVA (aopGet (right, offset, FALSE, FALSE));
7580 emitcode ("xrl", "a,b");
7582 else if (aopGetUsesAcc (left, offset))
7584 MOVA (aopGet (left, offset, FALSE, FALSE));
7585 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7589 MOVA (aopGet (right, offset, FALSE, FALSE));
7590 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7593 emitcode ("jnz", "%05d$", tlbl->key + 100);
7603 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7607 for (; (size--); offset++)
7610 // result = left ^ right
7611 if (AOP_TYPE (right) == AOP_LIT)
7613 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7617 aopGet (left, offset, FALSE, FALSE),
7622 // faster than result <- left, xrl result,right
7623 // and better if result is SFR
7624 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7625 && AOP_TYPE(left)==AOP_ACC)
7628 emitcode("mov", "a,b");
7629 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7631 else if (AOP_TYPE(left)==AOP_ACC)
7635 bool pushedB = pushB ();
7636 emitcode("mov", "b,a");
7637 MOVA (aopGet (right, offset, FALSE, FALSE));
7638 emitcode("xrl", "a,b");
7643 MOVA (aopGet (right, offset, FALSE, FALSE));
7644 emitcode("xrl", "a,b");
7647 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7649 MOVB (aopGet (left, offset, FALSE, FALSE));
7650 MOVA (aopGet (right, offset, FALSE, FALSE));
7651 emitcode ("xrl", "a,b");
7653 else if (aopGetUsesAcc (left, offset))
7655 MOVA (aopGet (left, offset, FALSE, FALSE));
7656 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7660 MOVA (aopGet (right, offset, FALSE, FALSE));
7661 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7663 aopPut (result, "a", offset);
7669 freeAsmop (result, NULL, ic, TRUE);
7670 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7671 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7674 /*-----------------------------------------------------------------*/
7675 /* genInline - write the inline code out */
7676 /*-----------------------------------------------------------------*/
7678 genInline (iCode * ic)
7680 char *buffer, *bp, *bp1;
7682 D (emitcode (";", "genInline"));
7684 _G.inLine += (!options.asmpeep);
7686 buffer = bp = bp1 = Safe_strdup(IC_INLINE(ic));
7688 /* emit each line as a code */
7699 /* Add \n for labels, not dirs such as c:\mydir */
7700 if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
7714 /* emitcode("",buffer); */
7715 _G.inLine -= (!options.asmpeep);
7718 /*-----------------------------------------------------------------*/
7719 /* genRRC - rotate right with carry */
7720 /*-----------------------------------------------------------------*/
7724 operand *left, *result;
7728 D (emitcode (";", "genRRC"));
7730 /* rotate right with carry */
7731 left = IC_LEFT (ic);
7732 result = IC_RESULT (ic);
7733 aopOp (left, ic, FALSE);
7734 aopOp (result, ic, FALSE);
7736 /* move it to the result */
7737 size = AOP_SIZE (result);
7739 if (size == 1) { /* special case for 1 byte */
7740 l = aopGet (left, offset, FALSE, FALSE);
7742 emitcode ("rr", "a");
7745 /* no need to clear carry, bit7 will be written later */
7748 l = aopGet (left, offset, FALSE, FALSE);
7750 emitcode ("rrc", "a");
7751 if (AOP_SIZE (result) > 1)
7752 aopPut (result, "a", offset--);
7754 /* now we need to put the carry into the
7755 highest order byte of the result */
7756 if (AOP_SIZE (result) > 1)
7758 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7761 emitcode ("mov", "acc.7,c");
7763 aopPut (result, "a", AOP_SIZE (result) - 1);
7764 freeAsmop (result, NULL, ic, TRUE);
7765 freeAsmop (left, NULL, ic, TRUE);
7768 /*-----------------------------------------------------------------*/
7769 /* genRLC - generate code for rotate left with carry */
7770 /*-----------------------------------------------------------------*/
7774 operand *left, *result;
7778 D (emitcode (";", "genRLC"));
7780 /* rotate right with carry */
7781 left = IC_LEFT (ic);
7782 result = IC_RESULT (ic);
7783 aopOp (left, ic, FALSE);
7784 aopOp (result, ic, FALSE);
7786 /* move it to the result */
7787 size = AOP_SIZE (result);
7791 l = aopGet (left, offset, FALSE, FALSE);
7793 if (size == 0) { /* special case for 1 byte */
7797 emitcode("rlc","a"); /* bit0 will be written later */
7798 if (AOP_SIZE (result) > 1)
7800 aopPut (result, "a", offset++);
7805 l = aopGet (left, offset, FALSE, FALSE);
7807 emitcode ("rlc", "a");
7808 if (AOP_SIZE (result) > 1)
7809 aopPut (result, "a", offset++);
7812 /* now we need to put the carry into the
7813 highest order byte of the result */
7814 if (AOP_SIZE (result) > 1)
7816 l = aopGet (result, 0, FALSE, FALSE);
7819 emitcode ("mov", "acc.0,c");
7821 aopPut (result, "a", 0);
7822 freeAsmop (result, NULL, ic, TRUE);
7823 freeAsmop (left, NULL, ic, TRUE);
7826 /*-----------------------------------------------------------------*/
7827 /* genGetHbit - generates code get highest order bit */
7828 /*-----------------------------------------------------------------*/
7830 genGetHbit (iCode * ic)
7832 operand *left, *result;
7834 D (emitcode (";", "genGetHbit"));
7836 left = IC_LEFT (ic);
7837 result = IC_RESULT (ic);
7838 aopOp (left, ic, FALSE);
7839 aopOp (result, ic, FALSE);
7841 /* get the highest order byte into a */
7842 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7843 if (AOP_TYPE (result) == AOP_CRY)
7845 emitcode ("rlc", "a");
7850 emitcode ("rl", "a");
7851 emitcode ("anl", "a,#0x01");
7855 freeAsmop (result, NULL, ic, TRUE);
7856 freeAsmop (left, NULL, ic, TRUE);
7859 /*-----------------------------------------------------------------*/
7860 /* genGetAbit - generates code get a single bit */
7861 /*-----------------------------------------------------------------*/
7863 genGetAbit (iCode * ic)
7865 operand *left, *right, *result;
7868 D (emitcode (";", "genGetAbit"));
7870 left = IC_LEFT (ic);
7871 right = IC_RIGHT (ic);
7872 result = IC_RESULT (ic);
7873 aopOp (left, ic, FALSE);
7874 aopOp (right, ic, FALSE);
7875 aopOp (result, ic, FALSE);
7877 shCount = (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7879 /* get the needed byte into a */
7880 MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7882 if (AOP_TYPE (result) == AOP_CRY)
7885 emitcode ("rlc", "a");
7886 else if ((shCount) == 0)
7887 emitcode ("rrc", "a");
7889 emitcode ("mov", "c,acc[%d]", shCount);
7897 emitcode ("rr", "a");
7900 emitcode ("rr", "a");
7903 emitcode ("anl", "a,#0x01");
7907 emitcode ("mov", "c,acc[%d]", shCount);
7908 emitcode ("clr", "a");
7909 emitcode ("rlc", "a");
7912 emitcode ("swap", "a");
7913 emitcode ("anl", "a,#0x01");
7916 emitcode ("rl", "a");
7919 emitcode ("rl", "a");
7920 emitcode ("anl", "a,#0x01");
7926 freeAsmop (result, NULL, ic, TRUE);
7927 freeAsmop (right, NULL, ic, TRUE);
7928 freeAsmop (left, NULL, ic, TRUE);
7931 /*-----------------------------------------------------------------*/
7932 /* genGetByte - generates code get a single byte */
7933 /*-----------------------------------------------------------------*/
7935 genGetByte (iCode * ic)
7937 operand *left, *right, *result;
7940 D (emitcode (";", "genGetByte"));
7942 left = IC_LEFT (ic);
7943 right = IC_RIGHT (ic);
7944 result = IC_RESULT (ic);
7945 aopOp (left, ic, FALSE);
7946 aopOp (right, ic, FALSE);
7947 aopOp (result, ic, FALSE);
7949 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7951 aopGet (left, offset, FALSE, FALSE),
7954 freeAsmop (result, NULL, ic, TRUE);
7955 freeAsmop (right, NULL, ic, TRUE);
7956 freeAsmop (left, NULL, ic, TRUE);
7959 /*-----------------------------------------------------------------*/
7960 /* genGetWord - generates code get two bytes */
7961 /*-----------------------------------------------------------------*/
7963 genGetWord (iCode * ic)
7965 operand *left, *right, *result;
7968 D (emitcode (";", "genGetWord"));
7970 left = IC_LEFT (ic);
7971 right = IC_RIGHT (ic);
7972 result = IC_RESULT (ic);
7973 aopOp (left, ic, FALSE);
7974 aopOp (right, ic, FALSE);
7975 aopOp (result, ic, FALSE);
7977 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7979 aopGet (left, offset, FALSE, FALSE),
7982 aopGet (left, offset+1, FALSE, FALSE),
7985 freeAsmop (result, NULL, ic, TRUE);
7986 freeAsmop (right, NULL, ic, TRUE);
7987 freeAsmop (left, NULL, ic, TRUE);
7990 /*-----------------------------------------------------------------*/
7991 /* genSwap - generates code to swap nibbles or bytes */
7992 /*-----------------------------------------------------------------*/
7994 genSwap (iCode * ic)
7996 operand *left, *result;
7998 D(emitcode ("; genSwap",""));
8000 left = IC_LEFT (ic);
8001 result = IC_RESULT (ic);
8002 aopOp (left, ic, FALSE);
8003 aopOp (result, ic, FALSE);
8005 switch (AOP_SIZE (left))
8007 case 1: /* swap nibbles in byte */
8008 MOVA (aopGet (left, 0, FALSE, FALSE));
8009 emitcode ("swap", "a");
8010 aopPut (result, "a", 0);
8012 case 2: /* swap bytes in word */
8013 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
8015 MOVA (aopGet (left, 0, FALSE, FALSE));
8016 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8017 aopPut (result, "a", 1);
8019 else if (operandsEqu (left, result))
8022 bool pushedB = FALSE, leftInB = FALSE;
8024 MOVA (aopGet (left, 0, FALSE, FALSE));
8025 if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
8028 emitcode ("mov", "b,a");
8032 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8033 aopPut (result, reg, 1);
8040 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8041 aopPut (result, aopGet (left, 0, FALSE, FALSE), 1);
8045 wassertl(FALSE, "unsupported SWAP operand size");
8048 freeAsmop (result, NULL, ic, TRUE);
8049 freeAsmop (left, NULL, ic, TRUE);
8052 /*-----------------------------------------------------------------*/
8053 /* AccRol - rotate left accumulator by known count */
8054 /*-----------------------------------------------------------------*/
8056 AccRol (int shCount)
8058 shCount &= 0x0007; // shCount : 0..7
8065 emitcode ("rl", "a");
8068 emitcode ("rl", "a");
8069 emitcode ("rl", "a");
8072 emitcode ("swap", "a");
8073 emitcode ("rr", "a");
8076 emitcode ("swap", "a");
8079 emitcode ("swap", "a");
8080 emitcode ("rl", "a");
8083 emitcode ("rr", "a");
8084 emitcode ("rr", "a");
8087 emitcode ("rr", "a");
8092 /*-----------------------------------------------------------------*/
8093 /* AccLsh - left shift accumulator by known count */
8094 /*-----------------------------------------------------------------*/
8096 AccLsh (int shCount)
8101 emitcode ("add", "a,acc");
8102 else if (shCount == 2)
8104 emitcode ("add", "a,acc");
8105 emitcode ("add", "a,acc");
8109 /* rotate left accumulator */
8111 /* and kill the lower order bits */
8112 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
8117 /*-----------------------------------------------------------------*/
8118 /* AccRsh - right shift accumulator by known count */
8119 /*-----------------------------------------------------------------*/
8121 AccRsh (int shCount)
8128 emitcode ("rrc", "a");
8132 /* rotate right accumulator */
8133 AccRol (8 - shCount);
8134 /* and kill the higher order bits */
8135 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8140 /*-----------------------------------------------------------------*/
8141 /* AccSRsh - signed right shift accumulator by known count */
8142 /*-----------------------------------------------------------------*/
8144 AccSRsh (int shCount)
8151 emitcode ("mov", "c,acc.7");
8152 emitcode ("rrc", "a");
8154 else if (shCount == 2)
8156 emitcode ("mov", "c,acc.7");
8157 emitcode ("rrc", "a");
8158 emitcode ("mov", "c,acc.7");
8159 emitcode ("rrc", "a");
8163 tlbl = newiTempLabel (NULL);
8164 /* rotate right accumulator */
8165 AccRol (8 - shCount);
8166 /* and kill the higher order bits */
8167 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8168 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8169 emitcode ("orl", "a,#0x%02x",
8170 (unsigned char) ~SRMask[shCount]);
8176 /*-----------------------------------------------------------------*/
8177 /* shiftR1Left2Result - shift right one byte from left to result */
8178 /*-----------------------------------------------------------------*/
8180 shiftR1Left2Result (operand * left, int offl,
8181 operand * result, int offr,
8182 int shCount, int sign)
8184 MOVA (aopGet (left, offl, FALSE, FALSE));
8185 /* shift right accumulator */
8190 aopPut (result, "a", offr);
8193 /*-----------------------------------------------------------------*/
8194 /* shiftL1Left2Result - shift left one byte from left to result */
8195 /*-----------------------------------------------------------------*/
8197 shiftL1Left2Result (operand * left, int offl,
8198 operand * result, int offr, int shCount)
8201 l = aopGet (left, offl, FALSE, FALSE);
8203 /* shift left accumulator */
8205 aopPut (result, "a", offr);
8208 /*-----------------------------------------------------------------*/
8209 /* movLeft2Result - move byte from left to result */
8210 /*-----------------------------------------------------------------*/
8212 movLeft2Result (operand * left, int offl,
8213 operand * result, int offr, int sign)
8216 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8218 l = aopGet (left, offl, FALSE, FALSE);
8220 if (*l == '@' && (IS_AOP_PREG (result)))
8222 emitcode ("mov", "a,%s", l);
8223 aopPut (result, "a", offr);
8229 aopPut (result, l, offr);
8233 /* MSB sign in acc.7 ! */
8234 if (getDataSize (left) == offl + 1)
8237 aopPut (result, "a", offr);
8244 /*-----------------------------------------------------------------*/
8245 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
8246 /*-----------------------------------------------------------------*/
8250 emitcode ("rrc", "a");
8251 emitcode ("xch", "a,%s", x);
8252 emitcode ("rrc", "a");
8253 emitcode ("xch", "a,%s", x);
8256 /*-----------------------------------------------------------------*/
8257 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
8258 /*-----------------------------------------------------------------*/
8262 emitcode ("xch", "a,%s", x);
8263 emitcode ("rlc", "a");
8264 emitcode ("xch", "a,%s", x);
8265 emitcode ("rlc", "a");
8268 /*-----------------------------------------------------------------*/
8269 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8270 /*-----------------------------------------------------------------*/
8274 emitcode ("xch", "a,%s", x);
8275 emitcode ("add", "a,acc");
8276 emitcode ("xch", "a,%s", x);
8277 emitcode ("rlc", "a");
8280 /*-----------------------------------------------------------------*/
8281 /* AccAXLsh - left shift a:x by known count (0..7) */
8282 /*-----------------------------------------------------------------*/
8284 AccAXLsh (char *x, int shCount)
8299 case 5: // AAAAABBB:CCCCCDDD
8301 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8303 emitcode ("anl", "a,#0x%02x",
8304 SLMask[shCount]); // BBB00000:CCCCCDDD
8306 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8308 AccRol (shCount); // DDDCCCCC:BBB00000
8310 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8312 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8314 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8316 emitcode ("anl", "a,#0x%02x",
8317 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8319 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8321 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8324 case 6: // AAAAAABB:CCCCCCDD
8325 emitcode ("anl", "a,#0x%02x",
8326 SRMask[shCount]); // 000000BB:CCCCCCDD
8327 emitcode ("mov", "c,acc.0"); // c = B
8328 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8330 AccAXRrl1 (x); // BCCCCCCD:D000000B
8331 AccAXRrl1 (x); // BBCCCCCC:DD000000
8333 emitcode("rrc","a");
8334 emitcode("xch","a,%s", x);
8335 emitcode("rrc","a");
8336 emitcode("mov","c,acc.0"); //<< get correct bit
8337 emitcode("xch","a,%s", x);
8339 emitcode("rrc","a");
8340 emitcode("xch","a,%s", x);
8341 emitcode("rrc","a");
8342 emitcode("xch","a,%s", x);
8345 case 7: // a:x <<= 7
8347 emitcode ("anl", "a,#0x%02x",
8348 SRMask[shCount]); // 0000000B:CCCCCCCD
8350 emitcode ("mov", "c,acc.0"); // c = B
8352 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
8354 AccAXRrl1 (x); // BCCCCCCC:D0000000
8362 /*-----------------------------------------------------------------*/
8363 /* AccAXRsh - right shift a:x known count (0..7) */
8364 /*-----------------------------------------------------------------*/
8366 AccAXRsh (char *x, int shCount)
8374 AccAXRrl1 (x); // 0->a:x
8379 AccAXRrl1 (x); // 0->a:x
8382 AccAXRrl1 (x); // 0->a:x
8387 case 5: // AAAAABBB:CCCCCDDD = a:x
8389 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8391 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8393 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8395 emitcode ("anl", "a,#0x%02x",
8396 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8398 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8400 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8402 emitcode ("anl", "a,#0x%02x",
8403 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8405 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8407 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8409 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8412 case 6: // AABBBBBB:CCDDDDDD
8414 emitcode ("mov", "c,acc.7");
8415 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8417 emitcode ("mov", "c,acc.7");
8418 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8420 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8422 emitcode ("anl", "a,#0x%02x",
8423 SRMask[shCount]); // 000000AA:BBBBBBCC
8426 case 7: // ABBBBBBB:CDDDDDDD
8428 emitcode ("mov", "c,acc.7"); // c = A
8430 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8432 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8434 emitcode ("anl", "a,#0x%02x",
8435 SRMask[shCount]); // 0000000A:BBBBBBBC
8443 /*-----------------------------------------------------------------*/
8444 /* AccAXRshS - right shift signed a:x known count (0..7) */
8445 /*-----------------------------------------------------------------*/
8447 AccAXRshS (char *x, int shCount)
8455 emitcode ("mov", "c,acc.7");
8456 AccAXRrl1 (x); // s->a:x
8460 emitcode ("mov", "c,acc.7");
8461 AccAXRrl1 (x); // s->a:x
8463 emitcode ("mov", "c,acc.7");
8464 AccAXRrl1 (x); // s->a:x
8469 case 5: // AAAAABBB:CCCCCDDD = a:x
8471 tlbl = newiTempLabel (NULL);
8472 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8474 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8476 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8478 emitcode ("anl", "a,#0x%02x",
8479 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8481 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8483 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8485 emitcode ("anl", "a,#0x%02x",
8486 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8488 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8490 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8492 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8494 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8495 emitcode ("orl", "a,#0x%02x",
8496 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8499 break; // SSSSAAAA:BBBCCCCC
8501 case 6: // AABBBBBB:CCDDDDDD
8503 tlbl = newiTempLabel (NULL);
8504 emitcode ("mov", "c,acc.7");
8505 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8507 emitcode ("mov", "c,acc.7");
8508 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8510 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8512 emitcode ("anl", "a,#0x%02x",
8513 SRMask[shCount]); // 000000AA:BBBBBBCC
8515 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8516 emitcode ("orl", "a,#0x%02x",
8517 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8521 case 7: // ABBBBBBB:CDDDDDDD
8523 tlbl = newiTempLabel (NULL);
8524 emitcode ("mov", "c,acc.7"); // c = A
8526 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8528 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8530 emitcode ("anl", "a,#0x%02x",
8531 SRMask[shCount]); // 0000000A:BBBBBBBC
8533 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8534 emitcode ("orl", "a,#0x%02x",
8535 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8544 /*-----------------------------------------------------------------*/
8545 /* shiftL2Left2Result - shift left two bytes from left to result */
8546 /*-----------------------------------------------------------------*/
8548 shiftL2Left2Result (operand * left, int offl,
8549 operand * result, int offr, int shCount)
8552 bool pushedB = FALSE;
8555 if (sameRegs (AOP (result), AOP (left)) &&
8556 ((offl + MSB16) == offr))
8558 /* don't crash result[offr] */
8559 MOVA (aopGet (left, offl, FALSE, FALSE));
8560 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8561 usedB = !strncmp(x, "b", 1);
8563 else if (aopGetUsesAcc (result, offr))
8565 movLeft2Result (left, offl, result, offr, 0);
8568 emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8569 MOVA (aopGet (result, offr, FALSE, FALSE));
8570 emitcode ("xch", "a,b");
8575 movLeft2Result (left, offl, result, offr, 0);
8576 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8577 x = aopGet (result, offr, FALSE, FALSE);
8579 /* ax << shCount (x = lsb(result)) */
8580 AccAXLsh (x, shCount);
8583 emitcode ("xch", "a,b");
8584 aopPut (result, "a", offr);
8585 aopPut (result, "b", offr + MSB16);
8590 aopPut (result, "a", offr + MSB16);
8595 /*-----------------------------------------------------------------*/
8596 /* shiftR2Left2Result - shift right two bytes from left to result */
8597 /*-----------------------------------------------------------------*/
8599 shiftR2Left2Result (operand * left, int offl,
8600 operand * result, int offr,
8601 int shCount, int sign)
8604 bool pushedB = FALSE;
8607 if (sameRegs (AOP (result), AOP (left)) &&
8608 ((offl + MSB16) == offr))
8610 /* don't crash result[offr] */
8611 MOVA (aopGet (left, offl, FALSE, FALSE));
8612 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8613 usedB = !strncmp(x, "b", 1);
8615 else if (aopGetUsesAcc (result, offr))
8617 movLeft2Result (left, offl, result, offr, 0);
8620 emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8621 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8626 movLeft2Result (left, offl, result, offr, 0);
8627 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8628 x = aopGet (result, offr, FALSE, FALSE);
8630 /* a:x >> shCount (x = lsb(result)) */
8632 AccAXRshS (x, shCount);
8634 AccAXRsh (x, shCount);
8637 emitcode ("xch", "a,b");
8638 aopPut (result, "a", offr);
8639 emitcode ("xch", "a,b");
8642 if (getDataSize (result) > 1)
8643 aopPut (result, "a", offr + MSB16);
8646 /*-----------------------------------------------------------------*/
8647 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8648 /*-----------------------------------------------------------------*/
8650 shiftLLeftOrResult (operand * left, int offl,
8651 operand * result, int offr, int shCount)
8653 MOVA (aopGet (left, offl, FALSE, FALSE));
8654 /* shift left accumulator */
8656 /* or with result */
8657 if (aopGetUsesAcc (result, offr))
8659 emitcode ("xch", "a,b");
8660 MOVA (aopGet (result, offr, FALSE, FALSE));
8661 emitcode ("orl", "a,b");
8665 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8667 /* back to result */
8668 aopPut (result, "a", offr);
8671 /*-----------------------------------------------------------------*/
8672 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8673 /*-----------------------------------------------------------------*/
8675 shiftRLeftOrResult (operand * left, int offl,
8676 operand * result, int offr, int shCount)
8678 MOVA (aopGet (left, offl, FALSE, FALSE));
8679 /* shift right accumulator */
8681 /* or with result */
8682 if (aopGetUsesAcc(result, offr))
8684 emitcode ("xch", "a,b");
8685 MOVA (aopGet (result, offr, FALSE, FALSE));
8686 emitcode ("orl", "a,b");
8690 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8692 /* back to result */
8693 aopPut (result, "a", offr);
8696 /*-----------------------------------------------------------------*/
8697 /* genlshOne - left shift a one byte quantity by known count */
8698 /*-----------------------------------------------------------------*/
8700 genlshOne (operand * result, operand * left, int shCount)
8702 D (emitcode (";", "genlshOne"));
8704 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8707 /*-----------------------------------------------------------------*/
8708 /* genlshTwo - left shift two bytes by known amount != 0 */
8709 /*-----------------------------------------------------------------*/
8711 genlshTwo (operand * result, operand * left, int shCount)
8715 D (emitcode (";", "genlshTwo"));
8717 size = getDataSize (result);
8719 /* if shCount >= 8 */
8727 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8729 movLeft2Result (left, LSB, result, MSB16, 0);
8731 aopPut (result, zero, LSB);
8734 /* 1 <= shCount <= 7 */
8738 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8740 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8744 /*-----------------------------------------------------------------*/
8745 /* shiftLLong - shift left one long from left to result */
8746 /* offl = LSB or MSB16 */
8747 /*-----------------------------------------------------------------*/
8749 shiftLLong (operand * left, operand * result, int offr)
8752 int size = AOP_SIZE (result);
8754 if (size >= LSB + offr)
8756 l = aopGet (left, LSB, FALSE, FALSE);
8758 emitcode ("add", "a,acc");
8759 if (sameRegs (AOP (left), AOP (result)) &&
8760 size >= MSB16 + offr && offr != LSB)
8761 xch_a_aopGet (left, LSB + offr, FALSE, FALSE);
8763 aopPut (result, "a", LSB + offr);
8766 if (size >= MSB16 + offr)
8768 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8770 l = aopGet (left, MSB16, FALSE, FALSE);
8773 emitcode ("rlc", "a");
8774 if (sameRegs (AOP (left), AOP (result)) &&
8775 size >= MSB24 + offr && offr != LSB)
8776 xch_a_aopGet (left, MSB16 + offr, FALSE, FALSE);
8778 aopPut (result, "a", MSB16 + offr);
8781 if (size >= MSB24 + offr)
8783 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8785 l = aopGet (left, MSB24, FALSE, FALSE);
8788 emitcode ("rlc", "a");
8789 if (sameRegs (AOP (left), AOP (result)) &&
8790 size >= MSB32 + offr && offr != LSB)
8791 xch_a_aopGet (left, MSB24 + offr, FALSE, FALSE);
8793 aopPut (result, "a", MSB24 + offr);
8796 if (size > MSB32 + offr)
8798 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8800 l = aopGet (left, MSB32, FALSE, FALSE);
8803 emitcode ("rlc", "a");
8804 aopPut (result, "a", MSB32 + offr);
8807 aopPut (result, zero, LSB);
8810 /*-----------------------------------------------------------------*/
8811 /* genlshFour - shift four byte by a known amount != 0 */
8812 /*-----------------------------------------------------------------*/
8814 genlshFour (operand * result, operand * left, int shCount)
8818 D (emitcode (";", "genlshFour"));
8820 size = AOP_SIZE (result);
8822 /* if shifting more that 3 bytes */
8827 /* lowest order of left goes to the highest
8828 order of the destination */
8829 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8831 movLeft2Result (left, LSB, result, MSB32, 0);
8832 aopPut (result, zero, LSB);
8833 aopPut (result, zero, MSB16);
8834 aopPut (result, zero, MSB24);
8838 /* more than two bytes */
8839 else if (shCount >= 16)
8841 /* lower order two bytes goes to higher order two bytes */
8843 /* if some more remaining */
8845 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8848 movLeft2Result (left, MSB16, result, MSB32, 0);
8849 movLeft2Result (left, LSB, result, MSB24, 0);
8851 aopPut (result, zero, MSB16);
8852 aopPut (result, zero, LSB);
8856 /* if more than 1 byte */
8857 else if (shCount >= 8)
8859 /* lower order three bytes goes to higher order three bytes */
8864 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8866 movLeft2Result (left, LSB, result, MSB16, 0);
8872 movLeft2Result (left, MSB24, result, MSB32, 0);
8873 movLeft2Result (left, MSB16, result, MSB24, 0);
8874 movLeft2Result (left, LSB, result, MSB16, 0);
8875 aopPut (result, zero, LSB);
8877 else if (shCount == 1)
8878 shiftLLong (left, result, MSB16);
8881 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8882 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8883 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8884 aopPut (result, zero, LSB);
8889 /* 1 <= shCount <= 7 */
8890 else if (shCount <= 2)
8892 shiftLLong (left, result, LSB);
8894 shiftLLong (result, result, LSB);
8896 /* 3 <= shCount <= 7, optimize */
8899 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8900 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8901 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8905 /*-----------------------------------------------------------------*/
8906 /* genLeftShiftLiteral - left shifting by known count */
8907 /*-----------------------------------------------------------------*/
8909 genLeftShiftLiteral (operand * left,
8914 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8917 D (emitcode (";", "genLeftShiftLiteral"));
8919 freeAsmop (right, NULL, ic, TRUE);
8921 aopOp (left, ic, FALSE);
8922 aopOp (result, ic, FALSE);
8924 size = getSize (operandType (result));
8927 emitcode ("; shift left ", "result %d, left %d", size,
8931 /* I suppose that the left size >= result size */
8936 movLeft2Result (left, size, result, size, 0);
8939 else if (shCount >= (size * 8))
8943 aopPut (result, zero, size);
8951 genlshOne (result, left, shCount);
8955 genlshTwo (result, left, shCount);
8959 genlshFour (result, left, shCount);
8962 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8963 "*** ack! mystery literal shift!\n");
8967 freeAsmop (result, NULL, ic, TRUE);
8968 freeAsmop (left, NULL, ic, TRUE);
8971 /*-----------------------------------------------------------------*/
8972 /* genLeftShift - generates code for left shifting */
8973 /*-----------------------------------------------------------------*/
8975 genLeftShift (iCode * ic)
8977 operand *left, *right, *result;
8980 symbol *tlbl, *tlbl1;
8983 D (emitcode (";", "genLeftShift"));
8985 right = IC_RIGHT (ic);
8986 left = IC_LEFT (ic);
8987 result = IC_RESULT (ic);
8989 aopOp (right, ic, FALSE);
8991 /* if the shift count is known then do it
8992 as efficiently as possible */
8993 if (AOP_TYPE (right) == AOP_LIT)
8995 genLeftShiftLiteral (left, right, result, ic);
8999 /* shift count is unknown then we have to form
9000 a loop get the loop count in B : Note: we take
9001 only the lower order byte since shifting
9002 more that 32 bits make no sense anyway, ( the
9003 largest size of an object can be only 32 bits ) */
9006 MOVB (aopGet (right, 0, FALSE, FALSE));
9007 emitcode ("inc", "b");
9008 freeAsmop (right, NULL, ic, TRUE);
9009 aopOp (left, ic, FALSE);
9010 aopOp (result, ic, FALSE);
9012 /* now move the left to the result if they are not the same */
9013 if (!sameRegs (AOP (left), AOP (result)) &&
9014 AOP_SIZE (result) > 1)
9017 size = AOP_SIZE (result);
9021 l = aopGet (left, offset, FALSE, TRUE);
9022 if (*l == '@' && (IS_AOP_PREG (result)))
9025 emitcode ("mov", "a,%s", l);
9026 aopPut (result, "a", offset);
9029 aopPut (result, l, offset);
9034 tlbl = newiTempLabel (NULL);
9035 size = AOP_SIZE (result);
9037 tlbl1 = newiTempLabel (NULL);
9039 /* if it is only one byte then */
9042 symbol *tlbl1 = newiTempLabel (NULL);
9044 l = aopGet (left, 0, FALSE, FALSE);
9046 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9048 emitcode ("add", "a,acc");
9050 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9052 aopPut (result, "a", 0);
9056 reAdjustPreg (AOP (result));
9058 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9060 l = aopGet (result, offset, FALSE, FALSE);
9062 emitcode ("add", "a,acc");
9063 aopPut (result, "a", offset++);
9066 l = aopGet (result, offset, FALSE, FALSE);
9068 emitcode ("rlc", "a");
9069 aopPut (result, "a", offset++);
9071 reAdjustPreg (AOP (result));
9074 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9077 freeAsmop (result, NULL, ic, TRUE);
9078 freeAsmop (left, NULL, ic, TRUE);
9081 /*-----------------------------------------------------------------*/
9082 /* genrshOne - right shift a one byte quantity by known count */
9083 /*-----------------------------------------------------------------*/
9085 genrshOne (operand * result, operand * left,
9086 int shCount, int sign)
9088 D (emitcode (";", "genrshOne"));
9090 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9093 /*-----------------------------------------------------------------*/
9094 /* genrshTwo - right shift two bytes by known amount != 0 */
9095 /*-----------------------------------------------------------------*/
9097 genrshTwo (operand * result, operand * left,
9098 int shCount, int sign)
9100 D (emitcode (";", "genrshTwo"));
9102 /* if shCount >= 8 */
9107 shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
9109 movLeft2Result (left, MSB16, result, LSB, sign);
9110 addSign (result, MSB16, sign);
9113 /* 1 <= shCount <= 7 */
9115 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9118 /*-----------------------------------------------------------------*/
9119 /* shiftRLong - shift right one long from left to result */
9120 /* offl = LSB or MSB16 */
9121 /*-----------------------------------------------------------------*/
9123 shiftRLong (operand * left, int offl,
9124 operand * result, int sign)
9126 bool overlapping = regsInCommon (left, result) || operandsEqu(left, result);
9128 if (overlapping && offl>1)
9130 // we are in big trouble, but this shouldn't happen
9131 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9134 MOVA (aopGet (left, MSB32, FALSE, FALSE));
9141 emitcode ("rlc", "a");
9142 emitcode ("subb", "a,acc");
9143 if (overlapping && sameByte (AOP (left), MSB32, AOP (result), MSB32))
9145 xch_a_aopGet (left, MSB32, FALSE, FALSE);
9149 aopPut (result, "a", MSB32);
9150 MOVA (aopGet (left, MSB32, FALSE, FALSE));
9155 if (aopPutUsesAcc (result, zero, MSB32))
9157 emitcode("xch", "a,b");
9158 aopPut (result, zero, MSB32);
9159 emitcode("xch", "a,b");
9163 aopPut (result, zero, MSB32);
9170 emitcode ("clr", "c");
9174 emitcode ("mov", "c,acc.7");
9177 emitcode ("rrc", "a");
9179 if (overlapping && offl==MSB16 &&
9180 sameByte (AOP (left), MSB24, AOP (result), MSB32-offl))
9182 xch_a_aopGet (left, MSB24, FALSE, FALSE);
9186 aopPut (result, "a", MSB32 - offl);
9187 MOVA (aopGet (left, MSB24, FALSE, FALSE));
9190 emitcode ("rrc", "a");
9191 if (overlapping && offl==MSB16 &&
9192 sameByte (AOP (left), MSB16, AOP (result), MSB24-offl))
9194 xch_a_aopGet (left, MSB16, FALSE, FALSE);
9198 aopPut (result, "a", MSB24 - offl);
9199 MOVA (aopGet (left, MSB16, FALSE, FALSE));
9202 emitcode ("rrc", "a");
9205 aopPut (result, "a", MSB16 - offl);
9210 sameByte (AOP (left), LSB, AOP (result), MSB16-offl))
9212 xch_a_aopGet (left, LSB, FALSE, FALSE);
9216 aopPut (result, "a", MSB16 - offl);
9217 MOVA (aopGet (left, LSB, FALSE, FALSE));
9219 emitcode ("rrc", "a");
9220 aopPut (result, "a", LSB);
9224 /*-----------------------------------------------------------------*/
9225 /* genrshFour - shift four byte by a known amount != 0 */
9226 /*-----------------------------------------------------------------*/
9228 genrshFour (operand * result, operand * left,
9229 int shCount, int sign)
9231 D (emitcode (";", "genrshFour"));
9233 /* if shifting more that 3 bytes */
9238 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9240 movLeft2Result (left, MSB32, result, LSB, sign);
9241 addSign (result, MSB16, sign);
9243 else if (shCount >= 16)
9247 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9250 movLeft2Result (left, MSB24, result, LSB, 0);
9251 movLeft2Result (left, MSB32, result, MSB16, sign);
9253 addSign (result, MSB24, sign);
9255 else if (shCount >= 8)
9260 shiftRLong (left, MSB16, result, sign);
9262 else if (shCount == 0)
9264 movLeft2Result (left, MSB16, result, LSB, 0);
9265 movLeft2Result (left, MSB24, result, MSB16, 0);
9266 movLeft2Result (left, MSB32, result, MSB24, sign);
9267 addSign (result, MSB32, sign);
9271 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9272 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9273 /* the last shift is signed */
9274 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9275 addSign (result, MSB32, sign);
9280 /* 1 <= shCount <= 7 */
9283 shiftRLong (left, LSB, result, sign);
9285 shiftRLong (result, LSB, result, sign);
9289 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9290 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9291 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9296 /*-----------------------------------------------------------------*/
9297 /* genRightShiftLiteral - right shifting by known count */
9298 /*-----------------------------------------------------------------*/
9300 genRightShiftLiteral (operand * left,
9306 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9309 D (emitcode (";", "genRightShiftLiteral"));
9311 freeAsmop (right, NULL, ic, TRUE);
9313 aopOp (left, ic, FALSE);
9314 aopOp (result, ic, FALSE);
9317 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9321 size = getDataSize (left);
9322 /* test the LEFT size !!! */
9324 /* I suppose that the left size >= result size */
9327 size = getDataSize (result);
9329 movLeft2Result (left, size, result, size, 0);
9332 else if (shCount >= (size * 8))
9336 /* get sign in acc.7 */
9337 MOVA (aopGet (left, size - 1, FALSE, FALSE));
9339 addSign (result, LSB, sign);
9346 genrshOne (result, left, shCount, sign);
9350 genrshTwo (result, left, shCount, sign);
9354 genrshFour (result, left, shCount, sign);
9360 freeAsmop (result, NULL, ic, TRUE);
9361 freeAsmop (left, NULL, ic, TRUE);
9364 /*-----------------------------------------------------------------*/
9365 /* genSignedRightShift - right shift of signed number */
9366 /*-----------------------------------------------------------------*/
9368 genSignedRightShift (iCode * ic)
9370 operand *right, *left, *result;
9373 symbol *tlbl, *tlbl1;
9376 D (emitcode (";", "genSignedRightShift"));
9378 /* we do it the hard way put the shift count in b
9379 and loop thru preserving the sign */
9381 right = IC_RIGHT (ic);
9382 left = IC_LEFT (ic);
9383 result = IC_RESULT (ic);
9385 aopOp (right, ic, FALSE);
9388 if (AOP_TYPE (right) == AOP_LIT)
9390 genRightShiftLiteral (left, right, result, ic, 1);
9393 /* shift count is unknown then we have to form
9394 a loop get the loop count in B : Note: we take
9395 only the lower order byte since shifting
9396 more that 32 bits make no sense anyway, ( the
9397 largest size of an object can be only 32 bits ) */
9400 MOVB (aopGet (right, 0, FALSE, FALSE));
9401 emitcode ("inc", "b");
9402 freeAsmop (right, NULL, ic, TRUE);
9403 aopOp (left, ic, FALSE);
9404 aopOp (result, ic, FALSE);
9406 /* now move the left to the result if they are not the
9408 if (!sameRegs (AOP (left), AOP (result)) &&
9409 AOP_SIZE (result) > 1)
9412 size = AOP_SIZE (result);
9416 l = aopGet (left, offset, FALSE, TRUE);
9417 if (*l == '@' && IS_AOP_PREG (result))
9420 emitcode ("mov", "a,%s", l);
9421 aopPut (result, "a", offset);
9424 aopPut (result, l, offset);
9429 /* mov the highest order bit to OVR */
9430 tlbl = newiTempLabel (NULL);
9431 tlbl1 = newiTempLabel (NULL);
9433 size = AOP_SIZE (result);
9435 MOVA (aopGet (left, offset, FALSE, FALSE));
9436 emitcode ("rlc", "a");
9437 emitcode ("mov", "ov,c");
9438 /* if it is only one byte then */
9441 l = aopGet (left, 0, FALSE, FALSE);
9443 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9445 emitcode ("mov", "c,ov");
9446 emitcode ("rrc", "a");
9448 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9450 aopPut (result, "a", 0);
9454 reAdjustPreg (AOP (result));
9455 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9457 emitcode ("mov", "c,ov");
9460 l = aopGet (result, offset, FALSE, FALSE);
9462 emitcode ("rrc", "a");
9463 aopPut (result, "a", offset--);
9465 reAdjustPreg (AOP (result));
9467 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9471 freeAsmop (result, NULL, ic, TRUE);
9472 freeAsmop (left, NULL, ic, TRUE);
9475 /*-----------------------------------------------------------------*/
9476 /* genRightShift - generate code for right shifting */
9477 /*-----------------------------------------------------------------*/
9479 genRightShift (iCode * ic)
9481 operand *right, *left, *result;
9485 symbol *tlbl, *tlbl1;
9488 D (emitcode (";", "genRightShift"));
9490 /* if signed then we do it the hard way preserve the
9491 sign bit moving it inwards */
9492 letype = getSpec (operandType (IC_LEFT (ic)));
9494 if (!SPEC_USIGN (letype))
9496 genSignedRightShift (ic);
9500 /* signed & unsigned types are treated the same : i.e. the
9501 signed is NOT propagated inwards : quoting from the
9502 ANSI - standard : "for E1 >> E2, is equivalent to division
9503 by 2**E2 if unsigned or if it has a non-negative value,
9504 otherwise the result is implementation defined ", MY definition
9505 is that the sign does not get propagated */
9507 right = IC_RIGHT (ic);
9508 left = IC_LEFT (ic);
9509 result = IC_RESULT (ic);
9511 aopOp (right, ic, FALSE);
9513 /* if the shift count is known then do it
9514 as efficiently as possible */
9515 if (AOP_TYPE (right) == AOP_LIT)
9517 genRightShiftLiteral (left, right, result, ic, 0);
9521 /* shift count is unknown then we have to form
9522 a loop get the loop count in B : Note: we take
9523 only the lower order byte since shifting
9524 more that 32 bits make no sense anyway, ( the
9525 largest size of an object can be only 32 bits ) */
9528 MOVB (aopGet (right, 0, FALSE, FALSE));
9529 emitcode ("inc", "b");
9530 freeAsmop (right, NULL, ic, TRUE);
9531 aopOp (left, ic, FALSE);
9532 aopOp (result, ic, FALSE);
9534 /* now move the left to the result if they are not the
9536 if (!sameRegs (AOP (left), AOP (result)) &&
9537 AOP_SIZE (result) > 1)
9539 size = AOP_SIZE (result);
9543 l = aopGet (left, offset, FALSE, TRUE);
9544 if (*l == '@' && IS_AOP_PREG (result))
9547 emitcode ("mov", "a,%s", l);
9548 aopPut (result, "a", offset);
9551 aopPut (result, l, offset);
9556 tlbl = newiTempLabel (NULL);
9557 tlbl1 = newiTempLabel (NULL);
9558 size = AOP_SIZE (result);
9561 /* if it is only one byte then */
9564 l = aopGet (left, 0, FALSE, FALSE);
9566 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9569 emitcode ("rrc", "a");
9571 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9573 aopPut (result, "a", 0);
9577 reAdjustPreg (AOP (result));
9578 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9583 l = aopGet (result, offset, FALSE, FALSE);
9585 emitcode ("rrc", "a");
9586 aopPut (result, "a", offset--);
9588 reAdjustPreg (AOP (result));
9591 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9595 freeAsmop (result, NULL, ic, TRUE);
9596 freeAsmop (left, NULL, ic, TRUE);
9599 /*-----------------------------------------------------------------*/
9600 /* emitPtrByteGet - emits code to get a byte into A through a */
9601 /* pointer register (R0, R1, or DPTR). The */
9602 /* original value of A can be preserved in B. */
9603 /*-----------------------------------------------------------------*/
9605 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9612 emitcode ("mov", "b,a");
9613 emitcode ("mov", "a,@%s", rname);
9618 emitcode ("mov", "b,a");
9619 emitcode ("movx", "a,@%s", rname);
9624 emitcode ("mov", "b,a");
9625 emitcode ("movx", "a,@dptr");
9630 emitcode ("mov", "b,a");
9631 emitcode ("clr", "a");
9632 emitcode ("movc", "a,@a+dptr");
9638 emitcode ("push", "b");
9639 emitcode ("push", "acc");
9641 emitcode ("lcall", "__gptrget");
9643 emitcode ("pop", "b");
9648 /*-----------------------------------------------------------------*/
9649 /* emitPtrByteSet - emits code to set a byte from src through a */
9650 /* pointer register (R0, R1, or DPTR). */
9651 /*-----------------------------------------------------------------*/
9653 emitPtrByteSet (char *rname, int p_type, char *src)
9662 emitcode ("mov", "@%s,a", rname);
9665 emitcode ("mov", "@%s,%s", rname, src);
9670 emitcode ("movx", "@%s,a", rname);
9675 emitcode ("movx", "@dptr,a");
9680 emitcode ("lcall", "__gptrput");
9685 /*-----------------------------------------------------------------*/
9686 /* genUnpackBits - generates code for unpacking bits */
9687 /*-----------------------------------------------------------------*/
9689 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9691 int offset = 0; /* result byte offset */
9692 int rsize; /* result size */
9693 int rlen = 0; /* remaining bitfield length */
9694 sym_link *etype; /* bitfield type information */
9695 int blen; /* bitfield length */
9696 int bstr; /* bitfield starting bit within byte */
9699 D(emitcode ("; genUnpackBits",""));
9701 etype = getSpec (operandType (result));
9702 rsize = getSize (operandType (result));
9703 blen = SPEC_BLEN (etype);
9704 bstr = SPEC_BSTR (etype);
9706 if (ifx && blen <= 8)
9708 emitPtrByteGet (rname, ptype, FALSE);
9711 SNPRINTF (buffer, sizeof(buffer),
9713 genIfxJump (ifx, buffer, NULL, NULL, NULL);
9718 emitcode ("anl", "a,#0x%02x",
9719 (((unsigned char) -1) >> (8 - blen)) << bstr);
9720 genIfxJump (ifx, "a", NULL, NULL, NULL);
9726 /* If the bitfield length is less than a byte */
9729 emitPtrByteGet (rname, ptype, FALSE);
9731 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9732 if (!SPEC_USIGN (etype))
9734 /* signed bitfield */
9735 symbol *tlbl = newiTempLabel (NULL);
9737 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9738 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9741 aopPut (result, "a", offset++);
9745 /* Bit field did not fit in a byte. Copy all
9746 but the partial byte at the end. */
9747 for (rlen=blen;rlen>=8;rlen-=8)
9749 emitPtrByteGet (rname, ptype, FALSE);
9750 aopPut (result, "a", offset++);
9752 emitcode ("inc", "%s", rname);
9755 /* Handle the partial byte at the end */
9758 emitPtrByteGet (rname, ptype, FALSE);
9759 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9760 if (!SPEC_USIGN (etype))
9762 /* signed bitfield */
9763 symbol *tlbl = newiTempLabel (NULL);
9765 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9766 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9769 aopPut (result, "a", offset++);
9777 if (SPEC_USIGN (etype))
9781 /* signed bitfield: sign extension with 0x00 or 0xff */
9782 emitcode ("rlc", "a");
9783 emitcode ("subb", "a,acc");
9789 aopPut (result, source, offset++);
9794 /*-----------------------------------------------------------------*/
9795 /* genDataPointerGet - generates code when ptr offset is known */
9796 /*-----------------------------------------------------------------*/
9798 genDataPointerGet (operand * left,
9804 int size, offset = 0;
9806 D (emitcode (";", "genDataPointerGet"));
9808 aopOp (result, ic, TRUE);
9810 /* get the string representation of the name */
9811 l = aopGet (left, 0, FALSE, TRUE);
9813 size = AOP_SIZE (result);
9818 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
9822 SNPRINTF (buffer, sizeof(buffer), "%s", l);
9824 aopPut (result, buffer, offset++);
9827 freeAsmop (result, NULL, ic, TRUE);
9828 freeAsmop (left, NULL, ic, TRUE);
9831 /*-----------------------------------------------------------------*/
9832 /* genNearPointerGet - emitcode for near pointer fetch */
9833 /*-----------------------------------------------------------------*/
9835 genNearPointerGet (operand * left,
9844 sym_link *rtype, *retype;
9845 sym_link *ltype = operandType (left);
9848 D (emitcode (";", "genNearPointerGet"));
9850 rtype = operandType (result);
9851 retype = getSpec (rtype);
9853 aopOp (left, ic, FALSE);
9855 /* if left is rematerialisable and
9856 result is not bitfield variable type and
9857 the left is pointer to data space i.e
9858 lower 128 bytes of space */
9859 if (AOP_TYPE (left) == AOP_IMMD &&
9860 !IS_BITFIELD (retype) &&
9861 DCL_TYPE (ltype) == POINTER)
9863 genDataPointerGet (left, result, ic);
9867 /* if the value is already in a pointer register
9868 then don't need anything more */
9869 if (!AOP_INPREG (AOP (left)))
9871 if (IS_AOP_PREG (left))
9873 // Aha, it is a pointer, just in disguise.
9874 rname = aopGet (left, 0, FALSE, FALSE);
9877 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9878 __FILE__, __LINE__);
9883 emitcode ("mov", "a%s,%s", rname + 1, rname);
9884 rname++; // skip the '@'.
9889 /* otherwise get a free pointer register */
9891 preg = getFreePtr (ic, &aop, FALSE);
9892 emitcode ("mov", "%s,%s",
9894 aopGet (left, 0, FALSE, TRUE));
9899 rname = aopGet (left, 0, FALSE, FALSE);
9901 //aopOp (result, ic, FALSE);
9902 aopOp (result, ic, result?TRUE:FALSE);
9904 /* if bitfield then unpack the bits */
9905 if (IS_BITFIELD (retype))
9906 genUnpackBits (result, rname, POINTER, ifx);
9909 /* we have can just get the values */
9910 int size = AOP_SIZE (result);
9915 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9918 emitcode ("mov", "a,@%s", rname);
9920 aopPut (result, "a", offset);
9924 SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
9925 aopPut (result, buffer, offset);
9929 emitcode ("inc", "%s", rname);
9933 /* now some housekeeping stuff */
9934 if (aop) /* we had to allocate for this iCode */
9936 if (pi) { /* post increment present */
9937 aopPut (left, rname, 0);
9939 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9943 /* we did not allocate which means left
9944 already in a pointer register, then
9945 if size > 0 && this could be used again
9946 we have to point it back to where it
9948 if ((AOP_SIZE (result) > 1 &&
9949 !OP_SYMBOL (left)->remat &&
9950 (OP_SYMBOL (left)->liveTo > ic->seq ||
9954 int size = AOP_SIZE (result) - 1;
9956 emitcode ("dec", "%s", rname);
9960 if (ifx && !ifx->generated)
9962 genIfxJump (ifx, "a", left, NULL, result);
9966 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9967 freeAsmop (left, NULL, ic, TRUE);
9968 if (pi) pi->generated = 1;
9971 /*-----------------------------------------------------------------*/
9972 /* genPagedPointerGet - emitcode for paged pointer fetch */
9973 /*-----------------------------------------------------------------*/
9975 genPagedPointerGet (operand * left,
9984 sym_link *rtype, *retype;
9986 D (emitcode (";", "genPagedPointerGet"));
9988 rtype = operandType (result);
9989 retype = getSpec (rtype);
9991 aopOp (left, ic, FALSE);
9993 /* if the value is already in a pointer register
9994 then don't need anything more */
9995 if (!AOP_INPREG (AOP (left)))
9997 /* otherwise get a free pointer register */
9999 preg = getFreePtr (ic, &aop, FALSE);
10000 emitcode ("mov", "%s,%s",
10002 aopGet (left, 0, FALSE, TRUE));
10003 rname = preg->name;
10006 rname = aopGet (left, 0, FALSE, FALSE);
10008 aopOp (result, ic, FALSE);
10010 /* if bitfield then unpack the bits */
10011 if (IS_BITFIELD (retype))
10012 genUnpackBits (result, rname, PPOINTER, ifx);
10015 /* we have can just get the values */
10016 int size = AOP_SIZE (result);
10022 emitcode ("movx", "a,@%s", rname);
10024 aopPut (result, "a", offset);
10029 emitcode ("inc", "%s", rname);
10033 /* now some housekeeping stuff */
10034 if (aop) /* we had to allocate for this iCode */
10037 aopPut (left, rname, 0);
10038 freeAsmop (NULL, aop, ic, TRUE);
10042 /* we did not allocate which means left
10043 already in a pointer register, then
10044 if size > 0 && this could be used again
10045 we have to point it back to where it
10047 if ((AOP_SIZE (result) > 1 &&
10048 !OP_SYMBOL (left)->remat &&
10049 (OP_SYMBOL (left)->liveTo > ic->seq ||
10053 int size = AOP_SIZE (result) - 1;
10055 emitcode ("dec", "%s", rname);
10059 if (ifx && !ifx->generated)
10061 genIfxJump (ifx, "a", left, NULL, result);
10065 freeAsmop (result, NULL, ic, TRUE);
10066 freeAsmop (left, NULL, ic, TRUE);
10067 if (pi) pi->generated = 1;
10070 /*--------------------------------------------------------------------*/
10071 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
10072 /*--------------------------------------------------------------------*/
10074 loadDptrFromOperand (operand *op, bool loadBToo)
10076 if (AOP_TYPE (op) != AOP_STR)
10078 /* if this is rematerializable */
10079 if (AOP_TYPE (op) == AOP_IMMD)
10081 emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
10084 if (AOP(op)->aopu.aop_immd.from_cast_remat)
10085 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
10088 wassertl(FALSE, "need pointerCode");
10089 emitcode ("", "; mov b,???");
10090 /* genPointerGet and genPointerSet originally did different
10091 ** things for this case. Both seem wrong.
10092 ** from genPointerGet:
10093 ** emitcode ("mov", "b,#%d", pointerCode (retype));
10094 ** from genPointerSet:
10095 ** emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
10100 else if (AOP_TYPE (op) == AOP_DPTR)
10104 MOVA (aopGet (op, 0, FALSE, FALSE));
10105 emitcode ("push", "acc");
10106 MOVA (aopGet (op, 1, FALSE, FALSE));
10107 emitcode ("push", "acc");
10108 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10109 emitcode ("pop", "dph");
10110 emitcode ("pop", "dpl");
10114 MOVA (aopGet (op, 0, FALSE, FALSE));
10115 emitcode ("push", "acc");
10116 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10117 emitcode ("pop", "dpl");
10121 { /* we need to get it byte by byte */
10122 emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
10123 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10125 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10130 /*-----------------------------------------------------------------*/
10131 /* genFarPointerGet - get value from far space */
10132 /*-----------------------------------------------------------------*/
10134 genFarPointerGet (operand * left,
10135 operand * result, iCode * ic, iCode * pi, iCode * ifx)
10138 sym_link *retype = getSpec (operandType (result));
10140 D (emitcode (";", "genFarPointerGet"));
10142 aopOp (left, ic, FALSE);
10143 loadDptrFromOperand (left, FALSE);
10145 /* so dptr now contains the address */
10146 aopOp (result, ic, FALSE);
10148 /* if bit then unpack */
10149 if (IS_BITFIELD (retype))
10150 genUnpackBits (result, "dptr", FPOINTER, ifx);
10153 size = AOP_SIZE (result);
10158 emitcode ("movx", "a,@dptr");
10160 aopPut (result, "a", offset++);
10162 emitcode ("inc", "dptr");
10166 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10168 aopPut (left, "dpl", 0);
10169 aopPut (left, "dph", 1);
10173 if (ifx && !ifx->generated)
10175 genIfxJump (ifx, "a", left, NULL, result);
10178 freeAsmop (result, NULL, ic, TRUE);
10179 freeAsmop (left, NULL, ic, TRUE);
10182 /*-----------------------------------------------------------------*/
10183 /* genCodePointerGet - get value from code space */
10184 /*-----------------------------------------------------------------*/
10186 genCodePointerGet (operand * left,
10187 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10190 sym_link *retype = getSpec (operandType (result));
10192 D (emitcode (";", "genCodePointerGet"));
10194 aopOp (left, ic, FALSE);
10195 loadDptrFromOperand (left, FALSE);
10197 /* so dptr now contains the address */
10198 aopOp (result, ic, FALSE);
10200 /* if bit then unpack */
10201 if (IS_BITFIELD (retype))
10202 genUnpackBits (result, "dptr", CPOINTER, ifx);
10205 size = AOP_SIZE (result);
10210 emitcode ("clr", "a");
10211 emitcode ("movc", "a,@a+dptr");
10213 aopPut (result, "a", offset++);
10215 emitcode ("inc", "dptr");
10219 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10221 aopPut (left, "dpl", 0);
10222 aopPut (left, "dph", 1);
10226 if (ifx && !ifx->generated)
10228 genIfxJump (ifx, "a", left, NULL, result);
10231 freeAsmop (result, NULL, ic, TRUE);
10232 freeAsmop (left, NULL, ic, TRUE);
10235 /*-----------------------------------------------------------------*/
10236 /* genGenPointerGet - get value from generic pointer space */
10237 /*-----------------------------------------------------------------*/
10239 genGenPointerGet (operand * left,
10240 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10243 sym_link *retype = getSpec (operandType (result));
10245 D (emitcode (";", "genGenPointerGet"));
10247 aopOp (left, ic, FALSE);
10248 loadDptrFromOperand (left, TRUE);
10250 /* so dptr now contains the address */
10251 aopOp (result, ic, FALSE);
10253 /* if bit then unpack */
10254 if (IS_BITFIELD (retype))
10256 genUnpackBits (result, "dptr", GPOINTER, ifx);
10260 size = AOP_SIZE (result);
10265 emitcode ("lcall", "__gptrget");
10267 aopPut (result, "a", offset++);
10269 emitcode ("inc", "dptr");
10273 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10275 aopPut (left, "dpl", 0);
10276 aopPut (left, "dph", 1);
10280 if (ifx && !ifx->generated)
10282 genIfxJump (ifx, "a", left, NULL, result);
10285 freeAsmop (result, NULL, ic, TRUE);
10286 freeAsmop (left, NULL, ic, TRUE);
10289 /*-----------------------------------------------------------------*/
10290 /* genPointerGet - generate code for pointer get */
10291 /*-----------------------------------------------------------------*/
10293 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
10295 operand *left, *result;
10296 sym_link *type, *etype;
10299 D (emitcode (";", "genPointerGet"));
10301 left = IC_LEFT (ic);
10302 result = IC_RESULT (ic);
10304 if (getSize (operandType (result))>1)
10307 /* depending on the type of pointer we need to
10308 move it to the correct pointer register */
10309 type = operandType (left);
10310 etype = getSpec (type);
10311 /* if left is of type of pointer then it is simple */
10312 if (IS_PTR (type) && !IS_FUNC (type->next))
10313 p_type = DCL_TYPE (type);
10316 /* we have to go by the storage class */
10317 p_type = PTR_TYPE (SPEC_OCLS (etype));
10320 /* special case when cast remat */
10321 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10322 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10324 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10325 type = operandType (left);
10326 p_type = DCL_TYPE (type);
10328 /* now that we have the pointer type we assign
10329 the pointer values */
10335 genNearPointerGet (left, result, ic, pi, ifx);
10339 genPagedPointerGet (left, result, ic, pi, ifx);
10343 genFarPointerGet (left, result, ic, pi, ifx);
10347 genCodePointerGet (left, result, ic, pi, ifx);
10351 genGenPointerGet (left, result, ic, pi, ifx);
10357 /*-----------------------------------------------------------------*/
10358 /* genPackBits - generates code for packed bit storage */
10359 /*-----------------------------------------------------------------*/
10361 genPackBits (sym_link * etype,
10363 char *rname, int p_type)
10365 int offset = 0; /* source byte offset */
10366 int rlen = 0; /* remaining bitfield length */
10367 int blen; /* bitfield length */
10368 int bstr; /* bitfield starting bit within byte */
10369 int litval; /* source literal value (if AOP_LIT) */
10370 unsigned char mask; /* bitmask within current byte */
10372 D(emitcode ("; genPackBits",""));
10374 blen = SPEC_BLEN (etype);
10375 bstr = SPEC_BSTR (etype);
10377 /* If the bitfield length is less than a byte */
10380 mask = ((unsigned char) (0xFF << (blen + bstr)) |
10381 (unsigned char) (0xFF >> (8 - bstr)));
10383 if (AOP_TYPE (right) == AOP_LIT)
10385 /* Case with a bitfield length <8 and literal source
10387 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10389 litval &= (~mask) & 0xff;
10390 emitPtrByteGet (rname, p_type, FALSE);
10391 if ((mask|litval)!=0xff)
10392 emitcode ("anl","a,#0x%02x", mask);
10394 emitcode ("orl","a,#0x%02x", litval);
10398 if ((blen==1) && (p_type!=GPOINTER))
10400 /* Case with a bitfield length == 1 and no generic pointer
10402 if (AOP_TYPE (right) == AOP_CRY)
10403 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10406 MOVA (aopGet (right, 0, FALSE, FALSE));
10407 emitcode ("rrc","a");
10409 emitPtrByteGet (rname, p_type, FALSE);
10410 emitcode ("mov","acc.%d,c",bstr);
10415 /* Case with a bitfield length < 8 and arbitrary source
10417 MOVA (aopGet (right, 0, FALSE, FALSE));
10418 /* shift and mask source value */
10420 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10422 pushedB = pushB ();
10423 /* transfer A to B and get next byte */
10424 emitPtrByteGet (rname, p_type, TRUE);
10426 emitcode ("anl", "a,#0x%02x", mask);
10427 emitcode ("orl", "a,b");
10428 if (p_type == GPOINTER)
10429 emitcode ("pop", "b");
10435 emitPtrByteSet (rname, p_type, "a");
10439 /* Bit length is greater than 7 bits. In this case, copy */
10440 /* all except the partial byte at the end */
10441 for (rlen=blen;rlen>=8;rlen-=8)
10443 emitPtrByteSet (rname, p_type,
10444 aopGet (right, offset++, FALSE, TRUE) );
10446 emitcode ("inc", "%s", rname);
10449 /* If there was a partial byte at the end */
10452 mask = (((unsigned char) -1 << rlen) & 0xff);
10454 if (AOP_TYPE (right) == AOP_LIT)
10456 /* Case with partial byte and literal source
10458 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10459 litval >>= (blen-rlen);
10460 litval &= (~mask) & 0xff;
10461 emitPtrByteGet (rname, p_type, FALSE);
10462 if ((mask|litval)!=0xff)
10463 emitcode ("anl","a,#0x%02x", mask);
10465 emitcode ("orl","a,#0x%02x", litval);
10470 /* Case with partial byte and arbitrary source
10472 MOVA (aopGet (right, offset++, FALSE, FALSE));
10473 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10475 pushedB = pushB ();
10476 /* transfer A to B and get next byte */
10477 emitPtrByteGet (rname, p_type, TRUE);
10479 emitcode ("anl", "a,#0x%02x", mask);
10480 emitcode ("orl", "a,b");
10481 if (p_type == GPOINTER)
10482 emitcode ("pop", "b");
10486 emitPtrByteSet (rname, p_type, "a");
10491 /*-----------------------------------------------------------------*/
10492 /* genDataPointerSet - remat pointer to data space */
10493 /*-----------------------------------------------------------------*/
10495 genDataPointerSet (operand * right,
10499 int size, offset = 0;
10500 char *l, buffer[256];
10502 D (emitcode (";", "genDataPointerSet"));
10504 aopOp (right, ic, FALSE);
10506 l = aopGet (result, 0, FALSE, TRUE);
10508 size = AOP_SIZE (right);
10512 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
10514 SNPRINTF (buffer, sizeof(buffer), "%s", l);
10515 emitcode ("mov", "%s,%s", buffer,
10516 aopGet (right, offset++, FALSE, FALSE));
10519 freeAsmop (result, NULL, ic, TRUE);
10520 freeAsmop (right, NULL, ic, TRUE);
10523 /*-----------------------------------------------------------------*/
10524 /* genNearPointerSet - emitcode for near pointer put */
10525 /*-----------------------------------------------------------------*/
10527 genNearPointerSet (operand * right,
10535 sym_link *retype, *letype;
10536 sym_link *ptype = operandType (result);
10538 D (emitcode (";", "genNearPointerSet"));
10540 retype = getSpec (operandType (right));
10541 letype = getSpec (ptype);
10543 aopOp (result, ic, FALSE);
10545 /* if the result is rematerializable &
10546 in data space & not a bit variable */
10547 if (AOP_TYPE (result) == AOP_IMMD &&
10548 DCL_TYPE (ptype) == POINTER &&
10549 !IS_BITVAR (retype) &&
10550 !IS_BITVAR (letype))
10552 genDataPointerSet (right, result, ic);
10556 /* if the value is already in a pointer register
10557 then don't need anything more */
10558 if (!AOP_INPREG (AOP (result)))
10561 //AOP_TYPE (result) == AOP_STK
10562 IS_AOP_PREG(result)
10565 // Aha, it is a pointer, just in disguise.
10566 rname = aopGet (result, 0, FALSE, FALSE);
10569 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10570 __FILE__, __LINE__);
10575 emitcode ("mov", "a%s,%s", rname + 1, rname);
10576 rname++; // skip the '@'.
10581 /* otherwise get a free pointer register */
10582 aop = newAsmop (0);
10583 preg = getFreePtr (ic, &aop, FALSE);
10584 emitcode ("mov", "%s,%s",
10586 aopGet (result, 0, FALSE, TRUE));
10587 rname = preg->name;
10592 rname = aopGet (result, 0, FALSE, FALSE);
10595 aopOp (right, ic, FALSE);
10597 /* if bitfield then unpack the bits */
10598 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10599 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10602 /* we can just get the values */
10603 int size = AOP_SIZE (right);
10608 l = aopGet (right, offset, FALSE, TRUE);
10609 if ((*l == '@') || (strcmp (l, "acc") == 0))
10612 emitcode ("mov", "@%s,a", rname);
10615 emitcode ("mov", "@%s,%s", rname, l);
10617 emitcode ("inc", "%s", rname);
10622 /* now some housekeeping stuff */
10623 if (aop) /* we had to allocate for this iCode */
10626 aopPut (result, rname, 0);
10627 freeAsmop (NULL, aop, ic, TRUE);
10631 /* we did not allocate which means left
10632 already in a pointer register, then
10633 if size > 0 && this could be used again
10634 we have to point it back to where it
10636 if ((AOP_SIZE (right) > 1 &&
10637 !OP_SYMBOL (result)->remat &&
10638 (OP_SYMBOL (result)->liveTo > ic->seq ||
10642 int size = AOP_SIZE (right) - 1;
10644 emitcode ("dec", "%s", rname);
10649 if (pi) pi->generated = 1;
10650 freeAsmop (result, NULL, ic, TRUE);
10651 freeAsmop (right, NULL, ic, TRUE);
10654 /*-----------------------------------------------------------------*/
10655 /* genPagedPointerSet - emitcode for Paged pointer put */
10656 /*-----------------------------------------------------------------*/
10658 genPagedPointerSet (operand * right,
10666 sym_link *retype, *letype;
10668 D (emitcode (";", "genPagedPointerSet"));
10670 retype = getSpec (operandType (right));
10671 letype = getSpec (operandType (result));
10673 aopOp (result, ic, FALSE);
10675 /* if the value is already in a pointer register
10676 then don't need anything more */
10677 if (!AOP_INPREG (AOP (result)))
10679 /* otherwise get a free pointer register */
10680 aop = newAsmop (0);
10681 preg = getFreePtr (ic, &aop, FALSE);
10682 emitcode ("mov", "%s,%s",
10684 aopGet (result, 0, FALSE, TRUE));
10685 rname = preg->name;
10688 rname = aopGet (result, 0, FALSE, FALSE);
10690 aopOp (right, ic, FALSE);
10692 /* if bitfield then unpack the bits */
10693 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10694 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10697 /* we have can just get the values */
10698 int size = AOP_SIZE (right);
10703 l = aopGet (right, offset, FALSE, TRUE);
10705 emitcode ("movx", "@%s,a", rname);
10708 emitcode ("inc", "%s", rname);
10714 /* now some housekeeping stuff */
10715 if (aop) /* we had to allocate for this iCode */
10718 aopPut (result, rname, 0);
10719 freeAsmop (NULL, aop, ic, TRUE);
10723 /* we did not allocate which means left
10724 already in a pointer register, then
10725 if size > 0 && this could be used again
10726 we have to point it back to where it
10728 if (AOP_SIZE (right) > 1 &&
10729 !OP_SYMBOL (result)->remat &&
10730 (OP_SYMBOL (result)->liveTo > ic->seq ||
10733 int size = AOP_SIZE (right) - 1;
10735 emitcode ("dec", "%s", rname);
10740 if (pi) pi->generated = 1;
10741 freeAsmop (result, NULL, ic, TRUE);
10742 freeAsmop (right, NULL, ic, TRUE);
10745 /*-----------------------------------------------------------------*/
10746 /* genFarPointerSet - set value from far space */
10747 /*-----------------------------------------------------------------*/
10749 genFarPointerSet (operand * right,
10750 operand * result, iCode * ic, iCode * pi)
10753 sym_link *retype = getSpec (operandType (right));
10754 sym_link *letype = getSpec (operandType (result));
10756 D(emitcode ("; genFarPointerSet",""));
10758 aopOp (result, ic, FALSE);
10759 loadDptrFromOperand (result, FALSE);
10761 /* so dptr now contains the address */
10762 aopOp (right, ic, FALSE);
10764 /* if bit then unpack */
10765 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10766 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10769 size = AOP_SIZE (right);
10774 char *l = aopGet (right, offset++, FALSE, FALSE);
10776 emitcode ("movx", "@dptr,a");
10778 emitcode ("inc", "dptr");
10781 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10782 aopPut (result, "dpl", 0);
10783 aopPut (result, "dph", 1);
10786 freeAsmop (result, NULL, ic, TRUE);
10787 freeAsmop (right, NULL, ic, TRUE);
10790 /*-----------------------------------------------------------------*/
10791 /* genGenPointerSet - set value from generic pointer space */
10792 /*-----------------------------------------------------------------*/
10794 genGenPointerSet (operand * right,
10795 operand * result, iCode * ic, iCode * pi)
10798 sym_link *retype = getSpec (operandType (right));
10799 sym_link *letype = getSpec (operandType (result));
10801 D (emitcode (";", "genGenPointerSet"));
10803 aopOp (result, ic, FALSE);
10804 loadDptrFromOperand (result, TRUE);
10806 /* so dptr now contains the address */
10807 aopOp (right, ic, FALSE);
10809 /* if bit then unpack */
10810 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10812 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10816 size = AOP_SIZE (right);
10821 char *l = aopGet (right, offset++, FALSE, FALSE);
10823 emitcode ("lcall", "__gptrput");
10825 emitcode ("inc", "dptr");
10829 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10830 aopPut (result, "dpl", 0);
10831 aopPut (result, "dph", 1);
10834 freeAsmop (result, NULL, ic, TRUE);
10835 freeAsmop (right, NULL, ic, TRUE);
10838 /*-----------------------------------------------------------------*/
10839 /* genPointerSet - stores the value into a pointer location */
10840 /*-----------------------------------------------------------------*/
10842 genPointerSet (iCode * ic, iCode *pi)
10844 operand *right, *result;
10845 sym_link *type, *etype;
10848 D (emitcode (";", "genPointerSet"));
10850 right = IC_RIGHT (ic);
10851 result = IC_RESULT (ic);
10853 /* depending on the type of pointer we need to
10854 move it to the correct pointer register */
10855 type = operandType (result);
10856 etype = getSpec (type);
10857 /* if left is of type of pointer then it is simple */
10858 if (IS_PTR (type) && !IS_FUNC (type->next))
10860 p_type = DCL_TYPE (type);
10864 /* we have to go by the storage class */
10865 p_type = PTR_TYPE (SPEC_OCLS (etype));
10868 /* special case when cast remat */
10869 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10870 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10871 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10872 type = operandType (result);
10873 p_type = DCL_TYPE (type);
10876 /* now that we have the pointer type we assign
10877 the pointer values */
10883 genNearPointerSet (right, result, ic, pi);
10887 genPagedPointerSet (right, result, ic, pi);
10891 genFarPointerSet (right, result, ic, pi);
10895 genGenPointerSet (right, result, ic, pi);
10899 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10900 "genPointerSet: illegal pointer type");
10904 /*-----------------------------------------------------------------*/
10905 /* genIfx - generate code for Ifx statement */
10906 /*-----------------------------------------------------------------*/
10908 genIfx (iCode * ic, iCode * popIc)
10910 operand *cond = IC_COND (ic);
10914 D (emitcode (";", "genIfx"));
10916 aopOp (cond, ic, FALSE);
10918 /* get the value into acc */
10919 if (AOP_TYPE (cond) != AOP_CRY)
10926 if (AOP(cond)->aopu.aop_dir)
10927 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10930 /* the result is now in the accumulator or a directly addressable bit */
10931 freeAsmop (cond, NULL, ic, TRUE);
10933 /* if there was something to be popped then do it */
10937 /* if the condition is a bit variable */
10939 genIfxJump(ic, dup, NULL, NULL, NULL);
10940 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10941 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10942 else if (isbit && !IS_ITEMP (cond))
10943 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10945 genIfxJump (ic, "a", NULL, NULL, NULL);
10950 /*-----------------------------------------------------------------*/
10951 /* genAddrOf - generates code for address of */
10952 /*-----------------------------------------------------------------*/
10954 genAddrOf (iCode * ic)
10956 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10959 D (emitcode (";", "genAddrOf"));
10961 aopOp (IC_RESULT (ic), ic, FALSE);
10963 /* if the operand is on the stack then we
10964 need to get the stack offset of this
10968 /* if it has an offset then we need to compute it */
10971 int stack_offset = ((sym->stack < 0) ?
10972 ((char) (sym->stack - _G.nRegsSaved)) :
10973 ((char) sym->stack)) & 0xff;
10974 if ((abs(stack_offset) == 1) &&
10975 !AOP_NEEDSACC(IC_RESULT (ic)) &&
10976 !isOperandVolatile (IC_RESULT (ic), FALSE))
10978 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
10979 if (stack_offset > 0)
10980 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
10982 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
10986 emitcode ("mov", "a,%s", SYM_BP (sym));
10987 emitcode ("add", "a,#0x%02x", stack_offset & 0xff);
10988 aopPut (IC_RESULT (ic), "a", 0);
10993 /* we can just move _bp */
10994 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
10996 /* fill the result with zero */
10997 size = AOP_SIZE (IC_RESULT (ic)) - 1;
11002 aopPut (IC_RESULT (ic), zero, offset++);
11007 /* object not on stack then we need the name */
11008 size = AOP_SIZE (IC_RESULT (ic));
11013 char s[SDCC_NAME_MAX];
11015 sprintf (s, "#(%s >> %d)",
11019 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11020 aopPut (IC_RESULT (ic), s, offset++);
11024 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11028 /*-----------------------------------------------------------------*/
11029 /* genFarFarAssign - assignment when both are in far space */
11030 /*-----------------------------------------------------------------*/
11032 genFarFarAssign (operand * result, operand * right, iCode * ic)
11034 int size = AOP_SIZE (right);
11038 D (emitcode (";", "genFarFarAssign"));
11040 /* first push the right side on to the stack */
11043 l = aopGet (right, offset++, FALSE, FALSE);
11045 emitcode ("push", "acc");
11048 freeAsmop (right, NULL, ic, FALSE);
11049 /* now assign DPTR to result */
11050 aopOp (result, ic, FALSE);
11051 size = AOP_SIZE (result);
11054 emitcode ("pop", "acc");
11055 aopPut (result, "a", --offset);
11057 freeAsmop (result, NULL, ic, FALSE);
11060 /*-----------------------------------------------------------------*/
11061 /* genAssign - generate code for assignment */
11062 /*-----------------------------------------------------------------*/
11064 genAssign (iCode * ic)
11066 operand *result, *right;
11068 unsigned long lit = 0L;
11070 D (emitcode (";", "genAssign"));
11072 result = IC_RESULT (ic);
11073 right = IC_RIGHT (ic);
11075 /* if they are the same */
11076 if (operandsEqu (result, right) &&
11077 !isOperandVolatile (result, FALSE) &&
11078 !isOperandVolatile (right, FALSE))
11081 aopOp (right, ic, FALSE);
11083 /* special case both in far space */
11084 if (AOP_TYPE (right) == AOP_DPTR &&
11085 IS_TRUE_SYMOP (result) &&
11086 isOperandInFarSpace (result))
11088 genFarFarAssign (result, right, ic);
11092 aopOp (result, ic, TRUE);
11094 /* if they are the same registers */
11095 if (sameRegs (AOP (right), AOP (result)) &&
11096 !isOperandVolatile (result, FALSE) &&
11097 !isOperandVolatile (right, FALSE))
11100 /* if the result is a bit */
11101 if (AOP_TYPE (result) == AOP_CRY)
11103 assignBit (result, right);
11107 /* bit variables done */
11109 size = AOP_SIZE (result);
11111 if (AOP_TYPE (right) == AOP_LIT)
11112 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11115 (AOP_TYPE (result) != AOP_REG) &&
11116 (AOP_TYPE (right) == AOP_LIT) &&
11117 !IS_FLOAT (operandType (right)) &&
11120 while ((size) && (lit))
11123 aopGet (right, offset, FALSE, FALSE),
11129 /* And now fill the rest with zeros. */
11132 emitcode ("clr", "a");
11136 aopPut (result, "a", offset);
11145 aopGet (right, offset, FALSE, FALSE),
11152 freeAsmop (result, NULL, ic, TRUE);
11153 freeAsmop (right, NULL, ic, TRUE);
11156 /*-----------------------------------------------------------------*/
11157 /* genJumpTab - generates code for jump table */
11158 /*-----------------------------------------------------------------*/
11160 genJumpTab (iCode * ic)
11162 symbol *jtab,*jtablo,*jtabhi;
11164 unsigned int count;
11166 D (emitcode (";", "genJumpTab"));
11168 count = elementsInSet( IC_JTLABELS (ic) );
11172 /* this algorithm needs 9 cycles and 7 + 3*n bytes
11173 if the switch argument is in a register.
11174 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
11175 /* Peephole may not convert ljmp to sjmp or ret
11176 labelIsReturnOnly & labelInRange must check
11177 currPl->ic->op != JUMPTABLE */
11178 aopOp (IC_JTCOND (ic), ic, FALSE);
11179 /* get the condition into accumulator */
11180 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11182 /* multiply by three */
11183 if (aopGetUsesAcc (IC_JTCOND (ic), 0))
11185 emitcode ("mov", "b,#3");
11186 emitcode ("mul", "ab");
11190 emitcode ("add", "a,acc");
11191 emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
11193 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11195 jtab = newiTempLabel (NULL);
11196 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
11197 emitcode ("jmp", "@a+dptr");
11199 /* now generate the jump labels */
11200 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11201 jtab = setNextItem (IC_JTLABELS (ic)))
11202 emitcode ("ljmp", "%05d$", jtab->key + 100);
11206 /* this algorithm needs 14 cycles and 13 + 2*n bytes
11207 if the switch argument is in a register.
11208 For n>6 this algorithm may be more compact */
11209 jtablo = newiTempLabel (NULL);
11210 jtabhi = newiTempLabel (NULL);
11212 /* get the condition into accumulator.
11213 Using b as temporary storage, if register push/pop is needed */
11214 aopOp (IC_JTCOND (ic), ic, FALSE);
11215 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11216 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
11217 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
11219 // (MB) what if B is in use???
11220 wassertl(!BINUSE, "B was in use");
11221 emitcode ("mov", "b,%s", l);
11224 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11228 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
11229 emitcode ("movc", "a,@a+pc");
11230 emitcode ("push", "acc");
11233 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
11234 emitcode ("movc", "a,@a+pc");
11235 emitcode ("push", "acc");
11239 /* this scales up to n<=255, but needs two more bytes
11240 and changes dptr */
11241 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
11242 emitcode ("movc", "a,@a+dptr");
11243 emitcode ("push", "acc");
11246 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
11247 emitcode ("movc", "a,@a+dptr");
11248 emitcode ("push", "acc");
11251 emitcode ("ret", "");
11253 /* now generate jump table, LSB */
11254 emitLabel (jtablo);
11255 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11256 jtab = setNextItem (IC_JTLABELS (ic)))
11257 emitcode (".db", "%05d$", jtab->key + 100);
11259 /* now generate jump table, MSB */
11260 emitLabel (jtabhi);
11261 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11262 jtab = setNextItem (IC_JTLABELS (ic)))
11263 emitcode (".db", "%05d$>>8", jtab->key + 100);
11267 /*-----------------------------------------------------------------*/
11268 /* genCast - gen code for casting */
11269 /*-----------------------------------------------------------------*/
11271 genCast (iCode * ic)
11273 operand *result = IC_RESULT (ic);
11274 sym_link *ctype = operandType (IC_LEFT (ic));
11275 sym_link *rtype = operandType (IC_RIGHT (ic));
11276 operand *right = IC_RIGHT (ic);
11279 D (emitcode (";", "genCast"));
11281 /* if they are equivalent then do nothing */
11282 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11285 aopOp (right, ic, FALSE);
11286 aopOp (result, ic, FALSE);
11288 /* if the result is a bit (and not a bitfield) */
11289 if (IS_BIT (OP_SYMBOL (result)->type))
11291 assignBit (result, right);
11295 /* if they are the same size : or less */
11296 if (AOP_SIZE (result) <= AOP_SIZE (right))
11299 /* if they are in the same place */
11300 if (sameRegs (AOP (right), AOP (result)))
11303 /* if they in different places then copy */
11304 size = AOP_SIZE (result);
11309 aopGet (right, offset, FALSE, FALSE),
11316 /* if the result is of type pointer */
11317 if (IS_PTR (ctype))
11321 sym_link *type = operandType (right);
11322 sym_link *etype = getSpec (type);
11324 /* pointer to generic pointer */
11325 if (IS_GENPTR (ctype))
11329 p_type = DCL_TYPE (type);
11333 if (SPEC_SCLS(etype)==S_REGISTER) {
11334 // let's assume it is a generic pointer
11337 /* we have to go by the storage class */
11338 p_type = PTR_TYPE (SPEC_OCLS (etype));
11342 /* the first two bytes are known */
11343 size = GPTRSIZE - 1;
11348 aopGet (right, offset, FALSE, FALSE),
11352 /* the last byte depending on type */
11354 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11359 // pointerTypeToGPByte will have bitched.
11363 sprintf(gpValStr, "#0x%x", gpVal);
11364 aopPut (result, gpValStr, GPTRSIZE - 1);
11369 /* just copy the pointers */
11370 size = AOP_SIZE (result);
11375 aopGet (right, offset, FALSE, FALSE),
11382 /* so we now know that the size of destination is greater
11383 than the size of the source */
11384 /* we move to result for the size of source */
11385 size = AOP_SIZE (right);
11390 aopGet (right, offset, FALSE, FALSE),
11395 /* now depending on the sign of the source && destination */
11396 size = AOP_SIZE (result) - AOP_SIZE (right);
11397 /* if unsigned or not an integral type */
11398 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11401 aopPut (result, zero, offset++);
11405 /* we need to extend the sign :{ */
11406 char *l = aopGet (right, AOP_SIZE (right) - 1,
11409 emitcode ("rlc", "a");
11410 emitcode ("subb", "a,acc");
11412 aopPut (result, "a", offset++);
11415 /* we are done hurray !!!! */
11418 freeAsmop (result, NULL, ic, TRUE);
11419 freeAsmop (right, NULL, ic, TRUE);
11422 /*-----------------------------------------------------------------*/
11423 /* genDjnz - generate decrement & jump if not zero instrucion */
11424 /*-----------------------------------------------------------------*/
11426 genDjnz (iCode * ic, iCode * ifx)
11428 symbol *lbl, *lbl1;
11432 /* if the if condition has a false label
11433 then we cannot save */
11434 if (IC_FALSE (ifx))
11437 /* if the minus is not of the form a = a - 1 */
11438 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11439 !IS_OP_LITERAL (IC_RIGHT (ic)))
11442 if (operandLitValue (IC_RIGHT (ic)) != 1)
11445 /* if the size of this greater than one then no
11447 if (getSize (operandType (IC_RESULT (ic))) > 1)
11450 /* otherwise we can save BIG */
11452 D (emitcode (";", "genDjnz"));
11454 lbl = newiTempLabel (NULL);
11455 lbl1 = newiTempLabel (NULL);
11457 aopOp (IC_RESULT (ic), ic, FALSE);
11459 if (AOP_NEEDSACC(IC_RESULT(ic)))
11461 /* If the result is accessed indirectly via
11462 * the accumulator, we must explicitly write
11463 * it back after the decrement.
11465 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11467 if (strcmp(rByte, "a"))
11469 /* Something is hopelessly wrong */
11470 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11471 __FILE__, __LINE__);
11472 /* We can just give up; the generated code will be inefficient,
11473 * but what the hey.
11475 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11478 emitcode ("dec", "%s", rByte);
11479 aopPut (IC_RESULT (ic), rByte, 0);
11480 emitcode ("jnz", "%05d$", lbl->key + 100);
11482 else if (IS_AOP_PREG (IC_RESULT (ic)))
11484 emitcode ("dec", "%s",
11485 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11486 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11487 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11488 ifx->generated = 1;
11489 emitcode ("jnz", "%05d$", lbl->key + 100);
11493 emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11496 emitcode ("sjmp", "%05d$", lbl1->key + 100);
11498 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11501 if (!ifx->generated)
11502 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11503 ifx->generated = 1;
11507 /*-----------------------------------------------------------------*/
11508 /* genReceive - generate code for a receive iCode */
11509 /*-----------------------------------------------------------------*/
11511 genReceive (iCode * ic)
11513 int size = getSize (operandType (IC_RESULT (ic)));
11516 D (emitcode (";", "genReceive"));
11518 if (ic->argreg == 1)
11519 { /* first parameter */
11520 if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11521 isOperandInPagedSpace (IC_RESULT (ic))) &&
11522 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11523 IS_TRUE_SYMOP (IC_RESULT (ic))))
11526 int receivingA = 0;
11529 for (offset = 0; offset<size; offset++)
11530 if (!strcmp (fReturn[offset], "a"))
11535 if (size==1 || getTempRegs(tempRegs, size-1, ic))
11537 for (offset = size-1; offset>0; offset--)
11538 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11539 emitcode("mov","a,%s", fReturn[0]);
11541 aopOp (IC_RESULT (ic), ic, FALSE);
11543 aopPut (IC_RESULT (ic), "a", offset);
11544 for (offset = 1; offset<size; offset++)
11545 aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset);
11551 if (getTempRegs(tempRegs, size, ic))
11553 for (offset = 0; offset<size; offset++)
11554 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11555 aopOp (IC_RESULT (ic), ic, FALSE);
11556 for (offset = 0; offset<size; offset++)
11557 aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset);
11562 offset = fReturnSizeMCS51 - size;
11565 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11566 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11569 aopOp (IC_RESULT (ic), ic, FALSE);
11570 size = AOP_SIZE (IC_RESULT (ic));
11574 emitcode ("pop", "acc");
11575 aopPut (IC_RESULT (ic), "a", offset++);
11581 aopOp (IC_RESULT (ic), ic, FALSE);
11583 assignResultValue (IC_RESULT (ic), NULL);
11586 else if (ic->argreg > 12)
11587 { /* bit parameters */
11588 if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
11590 aopOp (IC_RESULT (ic), ic, FALSE);
11591 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11592 outBitC(IC_RESULT (ic));
11596 { /* other parameters */
11598 aopOp (IC_RESULT (ic), ic, FALSE);
11599 rb1off = ic->argreg;
11602 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
11607 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11610 /*-----------------------------------------------------------------*/
11611 /* genDummyRead - generate code for dummy read of volatiles */
11612 /*-----------------------------------------------------------------*/
11614 genDummyRead (iCode * ic)
11619 D (emitcode(";", "genDummyRead"));
11621 op = IC_RIGHT (ic);
11622 if (op && IS_SYMOP (op))
11624 aopOp (op, ic, FALSE);
11626 /* if the result is a bit */
11627 if (AOP_TYPE (op) == AOP_CRY)
11628 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11631 /* bit variables done */
11633 size = AOP_SIZE (op);
11637 MOVA (aopGet (op, offset, FALSE, FALSE));
11642 freeAsmop (op, NULL, ic, TRUE);
11646 if (op && IS_SYMOP (op))
11648 aopOp (op, ic, FALSE);
11650 /* if the result is a bit */
11651 if (AOP_TYPE (op) == AOP_CRY)
11652 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11655 /* bit variables done */
11657 size = AOP_SIZE (op);
11661 MOVA (aopGet (op, offset, FALSE, FALSE));
11666 freeAsmop (op, NULL, ic, TRUE);
11670 /*-----------------------------------------------------------------*/
11671 /* genCritical - generate code for start of a critical sequence */
11672 /*-----------------------------------------------------------------*/
11674 genCritical (iCode *ic)
11676 symbol *tlbl = newiTempLabel (NULL);
11678 D (emitcode(";", "genCritical"));
11680 if (IC_RESULT (ic))
11682 aopOp (IC_RESULT (ic), ic, TRUE);
11683 aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
11684 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11685 aopPut (IC_RESULT (ic), zero, 0);
11687 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11691 emitcode ("setb", "c");
11692 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11693 emitcode ("clr", "c");
11695 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11699 /*-----------------------------------------------------------------*/
11700 /* genEndCritical - generate code for end of a critical sequence */
11701 /*-----------------------------------------------------------------*/
11703 genEndCritical (iCode *ic)
11705 D(emitcode("; genEndCritical",""));
11709 aopOp (IC_RIGHT (ic), ic, FALSE);
11710 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11712 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11713 emitcode ("mov", "ea,c");
11717 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11718 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11719 emitcode ("rrc", "a");
11720 emitcode ("mov", "ea,c");
11722 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11726 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11727 emitcode ("mov", "ea,c");
11731 /*-----------------------------------------------------------------*/
11732 /* gen51Code - generate code for 8051 based controllers */
11733 /*-----------------------------------------------------------------*/
11735 gen51Code (iCode * lic)
11739 /* int cseq = 0; */
11741 _G.currentFunc = NULL;
11742 lineHead = lineCurr = NULL;
11744 /* print the allocation information */
11745 if (allocInfo && currFunc)
11746 printAllocInfo (currFunc, codeOutBuf);
11747 /* if debug information required */
11748 if (options.debug && currFunc)
11750 debugFile->writeFunction (currFunc, lic);
11752 /* stack pointer name */
11753 if (options.useXstack)
11759 for (ic = lic; ic; ic = ic->next)
11761 _G.current_iCode = ic;
11763 if (ic->lineno && cln != ic->lineno)
11767 debugFile->writeCLine (ic);
11769 if (!options.noCcodeInAsm) {
11770 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
11771 printCLine(ic->filename, ic->lineno));
11776 if (ic->seqPoint && ic->seqPoint != cseq)
11778 emitcode ("", "; sequence point %d", ic->seqPoint);
11779 cseq = ic->seqPoint;
11782 if (options.iCodeInAsm) {
11783 char regsInUse[80];
11788 for (i=0; i<8; i++) {
11789 sprintf (®sInUse[i],
11790 "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11793 strcpy (regsInUse, "--------");
11794 for (i=0; i < 8; i++) {
11795 if (bitVectBitValue (ic->rMask, i))
11797 int offset = regs8051[i].offset;
11798 regsInUse[offset] = offset + '0'; /* show rMask */
11802 iLine = printILine(ic);
11803 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
11806 /* if the result is marked as
11807 spilt and rematerializable or code for
11808 this has already been generated then
11810 if (resultRemat (ic) || ic->generated)
11813 /* depending on the operation */
11833 /* IPOP happens only when trying to restore a
11834 spilt live range, if there is an ifx statement
11835 following this pop then the if statement might
11836 be using some of the registers being popped which
11837 would destory the contents of the register so
11838 we need to check for this condition and handle it */
11840 ic->next->op == IFX &&
11841 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11842 genIfx (ic->next, ic);
11860 genEndFunction (ic);
11880 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11897 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11901 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11908 /* note these two are xlated by algebraic equivalence
11909 in decorateType() in SDCCast.c */
11910 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11911 "got '>=' or '<=' shouldn't have come here");
11915 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11927 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11931 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11935 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11971 genRightShift (ic);
11974 case GET_VALUE_AT_ADDRESS:
11976 hasInc (IC_LEFT (ic), ic,
11977 getSize (operandType (IC_RESULT (ic)))),
11978 ifxForOp (IC_RESULT (ic), ic) );
11982 if (POINTER_SET (ic))
11984 hasInc (IC_RESULT (ic), ic,
11985 getSize (operandType (IC_RIGHT (ic)))));
12011 addSet (&_G.sendSet, ic);
12014 case DUMMY_READ_VOLATILE:
12023 genEndCritical (ic);
12035 _G.current_iCode = NULL;
12037 /* now we are ready to call the
12038 peep hole optimizer */
12039 if (!options.nopeep)
12040 peepHole (&lineHead);
12042 /* now do the actual printing */
12043 printLine (lineHead, codeOutBuf);