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 aop = op->aop = sym->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 aop = op->aop = sym->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 aop = op->aop = sym->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 aopPut (result, "c", 0);
1845 emitcode ("clr", "a");
1846 emitcode ("rlc", "a");
1851 /*-----------------------------------------------------------------*/
1852 /* toBoolean - emit code for orl a,operator(sizeop) */
1853 /*-----------------------------------------------------------------*/
1855 toBoolean (operand * oper)
1857 int size = AOP_SIZE (oper) - 1;
1859 bool AccUsed = FALSE;
1862 while (!AccUsed && size--)
1864 AccUsed |= aopGetUsesAcc(oper, offset++);
1867 size = AOP_SIZE (oper) - 1;
1869 MOVA (aopGet (oper, 0, FALSE, FALSE));
1870 if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1873 emitcode("mov", "b,a");
1876 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1877 emitcode ("orl", "b,a");
1879 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1880 emitcode ("orl", "a,b");
1887 emitcode ("orl", "a,%s",
1888 aopGet (oper, offset++, FALSE, FALSE));
1893 /*-----------------------------------------------------------------*/
1894 /* toCarry - make boolean and move into carry */
1895 /*-----------------------------------------------------------------*/
1897 toCarry (operand * oper)
1899 /* if the operand is a literal then
1900 we know what the value is */
1901 if (AOP_TYPE (oper) == AOP_LIT)
1903 if ((int) operandLitValue (oper))
1908 else if (AOP_TYPE (oper) == AOP_CRY)
1910 emitcode ("mov", "c,%s", oper->aop->aopu.aop_dir);
1914 /* or the operand into a */
1916 /* set C, if a >= 1 */
1917 emitcode ("add", "a,#0xff");
1921 /*-----------------------------------------------------------------*/
1922 /* assignBit - assign operand to bit operand */
1923 /*-----------------------------------------------------------------*/
1925 assignBit (operand * result, operand * right)
1927 /* if the right side is a literal then
1928 we know what the value is */
1929 if (AOP_TYPE (right) == AOP_LIT)
1931 if ((int) operandLitValue (right))
1932 aopPut (result, one, 0);
1934 aopPut (result, zero, 0);
1939 aopPut (result, "c", 0);
1944 /*-------------------------------------------------------------------*/
1945 /* xch_a_aopGet - for exchanging acc with value of the aop */
1946 /*-------------------------------------------------------------------*/
1948 xch_a_aopGet (operand * oper, int offset, bool bit16, bool dname)
1952 if (aopGetUsesAcc (oper, offset))
1954 emitcode("mov", "b,a");
1955 MOVA (aopGet (oper, offset, bit16, dname));
1956 emitcode("xch", "a,b");
1957 aopPut (oper, "a", offset);
1958 emitcode("xch", "a,b");
1963 l = aopGet (oper, offset, bit16, dname);
1964 emitcode("xch", "a,%s", l);
1970 /*-----------------------------------------------------------------*/
1971 /* genNot - generate code for ! operation */
1972 /*-----------------------------------------------------------------*/
1978 D (emitcode (";", "genNot"));
1980 /* assign asmOps to operand & result */
1981 aopOp (IC_LEFT (ic), ic, FALSE);
1982 aopOp (IC_RESULT (ic), ic, TRUE);
1984 /* if in bit space then a special case */
1985 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1987 /* if left==result then cpl bit */
1988 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1990 emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1994 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1995 emitcode ("cpl", "c");
1996 outBitC (IC_RESULT (ic));
2001 toBoolean (IC_LEFT (ic));
2003 /* set C, if a == 0 */
2004 tlbl = newiTempLabel (NULL);
2005 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
2007 outBitC (IC_RESULT (ic));
2010 /* release the aops */
2011 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2012 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2016 /*-----------------------------------------------------------------*/
2017 /* genCpl - generate code for complement */
2018 /*-----------------------------------------------------------------*/
2025 sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
2027 D(emitcode (";", "genCpl"));
2029 /* assign asmOps to operand & result */
2030 aopOp (IC_LEFT (ic), ic, FALSE);
2031 aopOp (IC_RESULT (ic), ic, TRUE);
2033 /* special case if in bit space */
2034 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2038 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
2039 (SPEC_USIGN (letype) && IS_CHAR (letype)))
2041 /* promotion rules are responsible for this strange result:
2042 bit -> int -> ~int -> bit
2043 uchar -> int -> ~int -> bit
2045 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
2049 tlbl=newiTempLabel(NULL);
2050 l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
2051 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
2052 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
2053 IS_AOP_PREG (IC_LEFT (ic)))
2055 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
2060 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
2063 outBitC (IC_RESULT(ic));
2067 size = AOP_SIZE (IC_RESULT (ic));
2070 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2072 emitcode ("cpl", "a");
2073 aopPut (IC_RESULT (ic), "a", offset++);
2078 /* release the aops */
2079 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2080 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2083 /*-----------------------------------------------------------------*/
2084 /* genUminusFloat - unary minus for floating points */
2085 /*-----------------------------------------------------------------*/
2087 genUminusFloat (operand * op, operand * result)
2089 int size, offset = 0;
2092 D (emitcode (";", "genUminusFloat"));
2094 /* for this we just copy and then flip the bit */
2096 size = AOP_SIZE (op) - 1;
2101 aopGet (op, offset, FALSE, FALSE),
2106 l = aopGet (op, offset, FALSE, FALSE);
2109 emitcode ("cpl", "acc.7");
2110 aopPut (result, "a", offset);
2113 /*-----------------------------------------------------------------*/
2114 /* genUminus - unary minus code generation */
2115 /*-----------------------------------------------------------------*/
2117 genUminus (iCode * ic)
2122 D (emitcode (";", "genUminus"));
2125 aopOp (IC_LEFT (ic), ic, FALSE);
2126 aopOp (IC_RESULT (ic), ic, TRUE);
2128 /* if both in bit space then special
2130 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2131 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2134 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2135 emitcode ("cpl", "c");
2136 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2140 optype = operandType (IC_LEFT (ic));
2142 /* if float then do float stuff */
2143 if (IS_FLOAT (optype))
2145 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2149 /* otherwise subtract from zero */
2150 size = AOP_SIZE (IC_LEFT (ic));
2154 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2155 if (!strcmp (l, "a"))
2159 emitcode ("cpl", "a");
2160 emitcode ("addc", "a,#0");
2166 emitcode ("clr", "a");
2167 emitcode ("subb", "a,%s", l);
2169 aopPut (IC_RESULT (ic), "a", offset++);
2172 /* if any remaining bytes in the result */
2173 /* we just need to propagate the sign */
2174 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2176 emitcode ("rlc", "a");
2177 emitcode ("subb", "a,acc");
2179 aopPut (IC_RESULT (ic), "a", offset++);
2183 /* release the aops */
2184 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2185 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2188 /*-----------------------------------------------------------------*/
2189 /* saveRegisters - will look for a call and save the registers */
2190 /*-----------------------------------------------------------------*/
2192 saveRegisters (iCode * lic)
2199 for (ic = lic; ic; ic = ic->next)
2200 if (ic->op == CALL || ic->op == PCALL)
2205 fprintf (stderr, "found parameter push with no function call\n");
2209 /* if the registers have been saved already or don't need to be then
2213 if (IS_SYMOP(IC_LEFT(ic)) &&
2214 (IFFUNC_CALLEESAVES (OP_SYMBOL (IC_LEFT (ic))->type) ||
2215 IFFUNC_ISNAKED (OP_SYM_TYPE (IC_LEFT (ic)))))
2218 /* save the registers in use at this time but skip the
2219 ones for the result */
2220 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2221 mcs51_rUmaskForOp (IC_RESULT(ic)));
2224 if (options.useXstack)
2226 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2227 int nBits = bitVectnBitsOn (rsavebits);
2228 int count = bitVectnBitsOn (rsave);
2232 count = count - nBits + 1;
2233 /* remove all but the first bits as they are pushed all at once */
2234 rsave = bitVectCplAnd (rsave, rsavebits);
2235 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2237 freeBitVect (rsavebits);
2241 regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2242 if (reg->type == REG_BIT)
2244 emitcode ("mov", "a,%s", reg->base);
2248 emitcode ("mov", "a,%s", reg->name);
2250 emitcode ("mov", "r0,%s", spname);
2251 emitcode ("inc", "%s", spname);// allocate before use
2252 emitcode ("movx", "@r0,a");
2253 if (bitVectBitValue (rsave, R0_IDX))
2254 emitcode ("mov", "r0,a");
2256 else if (count != 0)
2258 if (bitVectBitValue (rsave, R0_IDX))
2260 emitcode ("push", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2262 emitcode ("mov", "r0,%s", spname);
2264 emitcode ("add", "a,#%d", count);
2265 emitcode ("mov", "%s,a", spname);
2266 for (i = 0; i < mcs51_nRegs; i++)
2268 if (bitVectBitValue (rsave, i))
2270 regs * reg = REG_WITH_INDEX (i);
2273 emitcode ("pop", "acc");
2274 emitcode ("push", "acc");
2276 else if (reg->type == REG_BIT)
2278 emitcode ("mov", "a,%s", reg->base);
2282 emitcode ("mov", "a,%s", reg->name);
2284 emitcode ("movx", "@r0,a");
2287 emitcode ("inc", "r0");
2291 if (bitVectBitValue (rsave, R0_IDX))
2293 emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2299 bool bits_pushed = FALSE;
2300 for (i = 0; i < mcs51_nRegs; i++)
2302 if (bitVectBitValue (rsave, i))
2304 bits_pushed = pushReg (i, bits_pushed);
2308 freeBitVect (rsave);
2311 /*-----------------------------------------------------------------*/
2312 /* unsaveRegisters - pop the pushed registers */
2313 /*-----------------------------------------------------------------*/
2315 unsaveRegisters (iCode * ic)
2320 /* restore the registers in use at this time but skip the
2321 ones for the result */
2322 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2323 mcs51_rUmaskForOp (IC_RESULT(ic)));
2325 if (options.useXstack)
2327 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2328 int nBits = bitVectnBitsOn (rsavebits);
2329 int count = bitVectnBitsOn (rsave);
2333 count = count - nBits + 1;
2334 /* remove all but the first bits as they are popped all at once */
2335 rsave = bitVectCplAnd (rsave, rsavebits);
2336 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2338 freeBitVect (rsavebits);
2342 regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2343 emitcode ("mov", "r0,%s", spname);
2344 emitcode ("dec", "r0");
2345 emitcode ("movx", "a,@r0");
2346 if (reg->type == REG_BIT)
2348 emitcode ("mov", "%s,a", reg->base);
2352 emitcode ("mov", "%s,a", reg->name);
2354 emitcode ("dec", "%s", spname);
2356 else if (count != 0)
2358 emitcode ("mov", "r0,%s", spname);
2359 for (i = mcs51_nRegs; i >= 0; i--)
2361 if (bitVectBitValue (rsave, i))
2363 regs * reg = REG_WITH_INDEX (i);
2364 emitcode ("dec", "r0");
2365 emitcode ("movx", "a,@r0");
2368 emitcode ("push", "acc");
2370 else if (reg->type == REG_BIT)
2372 emitcode ("mov", "%s,a", reg->base);
2376 emitcode ("mov", "%s,a", reg->name);
2380 emitcode ("mov", "%s,r0", spname);
2381 if (bitVectBitValue (rsave, R0_IDX))
2383 emitcode ("pop", "ar0");
2389 bool bits_popped = FALSE;
2390 for (i = mcs51_nRegs; i >= 0; i--)
2392 if (bitVectBitValue (rsave, i))
2394 bits_popped = popReg (i, bits_popped);
2398 freeBitVect (rsave);
2402 /*-----------------------------------------------------------------*/
2404 /*-----------------------------------------------------------------*/
2406 pushSide (operand * oper, int size)
2411 char *l = aopGet (oper, offset++, FALSE, TRUE);
2412 if (AOP_TYPE (oper) != AOP_REG &&
2413 AOP_TYPE (oper) != AOP_DIR &&
2417 emitcode ("push", "acc");
2421 emitcode ("push", "%s", l);
2426 /*-----------------------------------------------------------------*/
2427 /* assignResultValue - also indicates if acc is in use afterwards */
2428 /*-----------------------------------------------------------------*/
2430 assignResultValue (operand * oper, operand * func)
2433 int size = AOP_SIZE (oper);
2434 bool accuse = FALSE;
2435 bool pushedA = FALSE;
2437 if (func && IS_BIT (OP_SYM_ETYPE (func)))
2443 if ((size > 3) && aopPutUsesAcc (oper, fReturn[offset], offset))
2445 emitcode ("push", "acc");
2450 if ((offset == 3) && pushedA)
2451 emitcode ("pop", "acc");
2452 accuse |= aopPut (oper, fReturn[offset], offset);
2459 /*-----------------------------------------------------------------*/
2460 /* genXpush - pushes onto the external stack */
2461 /*-----------------------------------------------------------------*/
2463 genXpush (iCode * ic)
2465 asmop *aop = newAsmop (0);
2467 int size, offset = 0;
2469 D (emitcode (";", "genXpush"));
2471 aopOp (IC_LEFT (ic), ic, FALSE);
2472 r = getFreePtr (ic, &aop, FALSE);
2474 size = AOP_SIZE (IC_LEFT (ic));
2478 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2479 emitcode ("mov", "%s,%s", r->name, spname);
2480 emitcode ("inc", "%s", spname); // allocate space first
2481 emitcode ("movx", "@%s,a", r->name);
2485 // allocate space first
2486 emitcode ("mov", "%s,%s", r->name, spname);
2488 emitcode ("add", "a,#%d", size);
2489 emitcode ("mov", "%s,a", spname);
2493 MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2494 emitcode ("movx", "@%s,a", r->name);
2495 emitcode ("inc", "%s", r->name);
2499 freeAsmop (NULL, aop, ic, TRUE);
2500 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2503 /*-----------------------------------------------------------------*/
2504 /* genIpush - generate code for pushing this gets a little complex */
2505 /*-----------------------------------------------------------------*/
2507 genIpush (iCode * ic)
2509 int size, offset = 0;
2513 D (emitcode (";", "genIpush"));
2515 /* if this is not a parm push : ie. it is spill push
2516 and spill push is always done on the local stack */
2520 /* and the item is spilt then do nothing */
2521 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2524 aopOp (IC_LEFT (ic), ic, FALSE);
2525 size = AOP_SIZE (IC_LEFT (ic));
2526 /* push it on the stack */
2529 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2535 emitcode ("push", "%s", l);
2540 /* this is a parameter push: in this case we call
2541 the routine to find the call and save those
2542 registers that need to be saved */
2545 /* if use external stack then call the external
2546 stack pushing routine */
2547 if (options.useXstack)
2553 /* then do the push */
2554 aopOp (IC_LEFT (ic), ic, FALSE);
2556 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2557 size = AOP_SIZE (IC_LEFT (ic));
2561 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2562 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2563 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR)
2565 if (strcmp (l, prev) || *l == '@')
2567 emitcode ("push", "acc");
2571 emitcode ("push", "%s", l);
2576 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2579 /*-----------------------------------------------------------------*/
2580 /* genIpop - recover the registers: can happen only for spilling */
2581 /*-----------------------------------------------------------------*/
2583 genIpop (iCode * ic)
2587 D (emitcode (";", "genIpop"));
2589 /* if the temp was not pushed then */
2590 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2593 aopOp (IC_LEFT (ic), ic, FALSE);
2594 size = AOP_SIZE (IC_LEFT (ic));
2595 offset = (size - 1);
2598 emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2602 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2605 /*-----------------------------------------------------------------*/
2606 /* saveRBank - saves an entire register bank on the stack */
2607 /*-----------------------------------------------------------------*/
2609 saveRBank (int bank, iCode * ic, bool pushPsw)
2612 int count = 8 + (pushPsw ? 1 : 0);
2616 if (options.useXstack)
2620 /* Assume r0 is available for use. */
2621 r = REG_WITH_INDEX (R0_IDX);
2626 r = getFreePtr (ic, &aop, FALSE);
2628 // allocate space first
2629 emitcode ("mov", "%s,%s", r->name, spname);
2631 emitcode ("add", "a,#%d", count);
2632 emitcode ("mov", "%s,a", spname);
2635 for (i = 0; i < 8; i++)
2637 if (options.useXstack)
2639 emitcode ("mov", "a,(%s+%d)",
2640 regs8051[i].base, 8 * bank + regs8051[i].offset);
2641 emitcode ("movx", "@%s,a", r->name);
2643 emitcode ("inc", "%s", r->name);
2646 emitcode ("push", "(%s+%d)",
2647 regs8051[i].base, 8 * bank + regs8051[i].offset);
2652 if (options.useXstack)
2654 emitcode ("mov", "a,psw");
2655 emitcode ("movx", "@%s,a", r->name);
2659 emitcode ("push", "psw");
2662 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2667 freeAsmop (NULL, aop, ic, TRUE);
2676 /*-----------------------------------------------------------------*/
2677 /* unsaveRBank - restores the register bank from stack */
2678 /*-----------------------------------------------------------------*/
2680 unsaveRBank (int bank, iCode * ic, bool popPsw)
2686 if (options.useXstack)
2690 /* Assume r0 is available for use. */
2691 r = REG_WITH_INDEX (R0_IDX);;
2696 r = getFreePtr (ic, &aop, FALSE);
2698 emitcode ("mov", "%s,%s", r->name, spname);
2703 if (options.useXstack)
2705 emitcode ("dec", "%s", r->name);
2706 emitcode ("movx", "a,@%s", r->name);
2707 emitcode ("mov", "psw,a");
2711 emitcode ("pop", "psw");
2715 for (i = 7; i >= 0; i--)
2717 if (options.useXstack)
2719 emitcode ("dec", "%s", r->name);
2720 emitcode ("movx", "a,@%s", r->name);
2721 emitcode ("mov", "(%s+%d),a",
2722 regs8051[i].base, 8 * bank + regs8051[i].offset);
2726 emitcode ("pop", "(%s+%d)",
2727 regs8051[i].base, 8 * bank + regs8051[i].offset);
2731 if (options.useXstack)
2733 emitcode ("mov", "%s,%s", spname, r->name);
2738 freeAsmop (NULL, aop, ic, TRUE);
2742 /*-----------------------------------------------------------------*/
2743 /* genSend - gen code for SEND */
2744 /*-----------------------------------------------------------------*/
2745 static void genSend(set *sendSet)
2750 /* first we do all bit parameters */
2751 for (sic = setFirstItem (sendSet); sic;
2752 sic = setNextItem (sendSet))
2754 if (sic->argreg > 12)
2756 int bit = sic->argreg-13;
2758 aopOp (IC_LEFT (sic), sic, FALSE);
2760 /* if left is a literal then
2761 we know what the value is */
2762 if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2764 if (((int) operandLitValue (IC_LEFT (sic))))
2765 emitcode ("setb", "b[%d]", bit);
2767 emitcode ("clr", "b[%d]", bit);
2772 toCarry (IC_LEFT (sic));
2773 emitcode ("mov", "b[%d],c", bit);
2778 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2784 saveRegisters (setFirstItem (sendSet));
2785 emitcode ("mov", "bits,b");
2788 /* then we do all other parameters */
2789 for (sic = setFirstItem (sendSet); sic;
2790 sic = setNextItem (sendSet))
2792 if (sic->argreg <= 12)
2794 int size, offset = 0;
2795 aopOp (IC_LEFT (sic), sic, FALSE);
2796 size = AOP_SIZE (IC_LEFT (sic));
2798 if (sic->argreg == 1)
2802 char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2803 if (strcmp (l, fReturn[offset]))
2805 emitcode ("mov", "%s,%s", fReturn[offset], l);
2814 emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2815 aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2819 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2824 /*-----------------------------------------------------------------*/
2825 /* selectRegBank - emit code to select the register bank */
2826 /*-----------------------------------------------------------------*/
2828 selectRegBank (short bank, bool keepFlags)
2830 /* if f.e. result is in carry */
2833 emitcode ("anl", "psw,#0xE7");
2835 emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2839 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2843 /*-----------------------------------------------------------------*/
2844 /* genCall - generates a call statement */
2845 /*-----------------------------------------------------------------*/
2847 genCall (iCode * ic)
2851 // bool restoreBank = FALSE;
2852 bool swapBanks = FALSE;
2853 bool accuse = FALSE;
2854 bool accPushed = FALSE;
2855 bool resultInF0 = FALSE;
2856 bool assignResultGenerated = FALSE;
2858 D (emitcode (";", "genCall"));
2860 dtype = operandType (IC_LEFT (ic));
2861 etype = getSpec(dtype);
2862 /* if send set is not empty then assign */
2865 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2866 genSend(reverseSet(_G.sendSet));
2868 genSend(_G.sendSet);
2873 /* if we are calling a not _naked function that is not using
2874 the same register bank then we need to save the
2875 destination registers on the stack */
2876 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2877 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2878 !IFFUNC_ISISR (dtype))
2883 /* if caller saves & we have not saved then */
2889 emitcode ("mov", "psw,#0x%02x",
2890 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2894 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2896 if (IFFUNC_CALLEESAVES(dtype))
2898 werror (E_BANKED_WITH_CALLEESAVES);
2902 char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2903 OP_SYMBOL (IC_LEFT (ic))->rname :
2904 OP_SYMBOL (IC_LEFT (ic))->name);
2906 emitcode ("mov", "r0,#%s", l);
2907 emitcode ("mov", "r1,#(%s >> 8)", l);
2908 emitcode ("mov", "r2,#(%s >> 16)", l);
2909 emitcode ("lcall", "__sdcc_banked_call");
2914 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2915 OP_SYMBOL (IC_LEFT (ic))->rname :
2916 OP_SYMBOL (IC_LEFT (ic))->name));
2921 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2924 /* if we need assign a result value */
2925 if ((IS_ITEMP (IC_RESULT (ic)) &&
2926 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2927 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2928 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2929 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2930 IS_TRUE_SYMOP (IC_RESULT (ic)))
2934 aopOp (IC_RESULT (ic), ic, FALSE);
2937 accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2938 assignResultGenerated = TRUE;
2940 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2943 /* adjust the stack for parameters if required */
2947 if (ic->parmBytes > 3)
2951 emitcode ("push", "acc");
2954 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2955 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2956 !assignResultGenerated)
2958 emitcode ("mov", "F0,c");
2962 emitcode ("mov", "a,%s", spname);
2963 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2964 emitcode ("mov", "%s,a", spname);
2966 /* unsaveRegisters from xstack needs acc, but */
2967 /* unsaveRegisters from stack needs this popped */
2968 if (accPushed && !options.useXstack)
2970 emitcode ("pop", "acc");
2975 for (i = 0; i < ic->parmBytes; i++)
2976 emitcode ("dec", "%s", spname);
2979 /* if we had saved some registers then unsave them */
2980 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2982 if (accuse && !accPushed && options.useXstack)
2984 /* xstack needs acc, but doesn't touch normal stack */
2985 emitcode ("push", "acc");
2988 unsaveRegisters (ic);
2991 // /* if register bank was saved then pop them */
2993 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2995 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
2998 emitcode ("mov", "c,F0");
3000 aopOp (IC_RESULT (ic), ic, FALSE);
3001 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3002 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3006 emitcode ("pop", "acc");
3009 /*-----------------------------------------------------------------*/
3010 /* genPcall - generates a call by pointer statement */
3011 /*-----------------------------------------------------------------*/
3013 genPcall (iCode * ic)
3017 symbol *rlbl = newiTempLabel (NULL);
3018 // bool restoreBank=FALSE;
3019 bool swapBanks = FALSE;
3020 bool resultInF0 = FALSE;
3022 D (emitcode (";", "genPcall"));
3024 dtype = operandType (IC_LEFT (ic))->next;
3025 etype = getSpec(dtype);
3026 /* if caller saves & we have not saved then */
3030 /* if we are calling a not _naked function that is not using
3031 the same register bank then we need to save the
3032 destination registers on the stack */
3033 if (currFunc && dtype && !IFFUNC_ISNAKED (dtype) &&
3034 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
3035 !IFFUNC_ISISR (dtype))
3037 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3038 // restoreBank=TRUE;
3040 // need caution message to user here
3043 if (IS_LITERAL (etype))
3045 /* if send set is not empty then assign */
3048 genSend(reverseSet(_G.sendSet));
3054 emitcode ("mov", "psw,#0x%02x",
3055 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3058 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT (getSpec(dtype)))
3060 if (IFFUNC_CALLEESAVES (dtype))
3062 werror (E_BANKED_WITH_CALLEESAVES);
3066 char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
3068 emitcode ("mov", "r0,#%s", l);
3069 emitcode ("mov", "r1,#(%s >> 8)", l);
3070 emitcode ("mov", "r2,#(%s >> 16)", l);
3071 emitcode ("lcall", "__sdcc_banked_call");
3076 emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
3081 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT (getSpec(dtype)))
3083 if (IFFUNC_CALLEESAVES (dtype))
3085 werror (E_BANKED_WITH_CALLEESAVES);
3089 aopOp (IC_LEFT (ic), ic, FALSE);
3093 /* what if aopGet needs r0 or r1 ??? */
3094 emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3095 emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3096 emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3100 int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
3101 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3102 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3103 emitcode ("mov", "0x%02x,%s", reg, aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3106 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3108 /* if send set is not empty then assign */
3111 genSend(reverseSet(_G.sendSet));
3117 emitcode ("mov", "psw,#0x%02x",
3118 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3122 emitcode ("lcall", "__sdcc_banked_call");
3125 else if (_G.sendSet)
3127 /* push the return address on to the stack */
3128 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
3129 emitcode ("push", "acc");
3130 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
3131 emitcode ("push", "acc");
3133 /* now push the calling address */
3134 aopOp (IC_LEFT (ic), ic, FALSE);
3136 pushSide (IC_LEFT (ic), FPTRSIZE);
3138 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3140 /* if send set is not empty the assign */
3143 genSend(reverseSet(_G.sendSet));
3149 emitcode ("mov", "psw,#0x%02x",
3150 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3154 emitcode ("ret", "");
3157 else /* the send set is empty */
3160 /* now get the calling address into dptr */
3161 aopOp (IC_LEFT (ic), ic, FALSE);
3163 l = aopGet (IC_LEFT (ic), 0, FALSE, FALSE);
3164 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3166 emitcode ("mov", "r0,%s", l);
3167 l = aopGet (IC_LEFT (ic), 1, FALSE, FALSE);
3168 emitcode ("mov", "dph,%s", l);
3169 emitcode ("mov", "dpl,r0");
3173 emitcode ("mov", "dpl,%s", l);
3174 l = aopGet (IC_LEFT (ic), 1, FALSE, FALSE);
3175 emitcode ("mov", "dph,%s", l);
3178 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3182 emitcode ("mov", "psw,#0x%02x",
3183 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3187 emitcode ("lcall", "__sdcc_call_dptr");
3192 selectRegBank (FUNC_REGBANK (currFunc->type), IS_BIT (etype));
3195 /* if we need assign a result value */
3196 if ((IS_ITEMP (IC_RESULT (ic)) &&
3197 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3198 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3199 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3200 IS_TRUE_SYMOP (IC_RESULT (ic)))
3204 aopOp (IC_RESULT (ic), ic, FALSE);
3207 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3209 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3212 /* adjust the stack for parameters if required */
3216 if (ic->parmBytes > 3)
3218 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3219 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3221 emitcode ("mov", "F0,c");
3225 emitcode ("mov", "a,%s", spname);
3226 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3227 emitcode ("mov", "%s,a", spname);
3230 for (i = 0; i < ic->parmBytes; i++)
3231 emitcode ("dec", "%s", spname);
3234 // /* if register bank was saved then unsave them */
3236 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3238 /* if we had saved some registers then unsave them */
3239 if (ic->regsSaved && !IFFUNC_CALLEESAVES (dtype))
3240 unsaveRegisters (ic);
3242 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3245 emitcode ("mov", "c,F0");
3247 aopOp (IC_RESULT (ic), ic, FALSE);
3248 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3249 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3253 /*-----------------------------------------------------------------*/
3254 /* resultRemat - result is rematerializable */
3255 /*-----------------------------------------------------------------*/
3257 resultRemat (iCode * ic)
3259 if (SKIP_IC (ic) || ic->op == IFX)
3262 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3264 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3265 if (sym->remat && !POINTER_SET (ic))
3272 /*-----------------------------------------------------------------*/
3273 /* inExcludeList - return 1 if the string is in exclude Reg list */
3274 /*-----------------------------------------------------------------*/
3276 regsCmp(void *p1, void *p2)
3278 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3282 inExcludeList (char *s)
3284 const char *p = setFirstItem(options.excludeRegsSet);
3286 if (p == NULL || STRCASECMP(p, "none") == 0)
3290 return isinSetWith(options.excludeRegsSet, s, regsCmp);
3293 /*-----------------------------------------------------------------*/
3294 /* genFunction - generated code for function entry */
3295 /*-----------------------------------------------------------------*/
3297 genFunction (iCode * ic)
3299 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3301 bool switchedPSW = FALSE;
3302 int calleesaves_saved_register = -1;
3303 int stackAdjust = sym->stack;
3304 int accIsFree = sym->recvSize < 4;
3305 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3306 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3309 /* create the function header */
3310 emitcode (";", "-----------------------------------------");
3311 emitcode (";", " function %s", sym->name);
3312 emitcode (";", "-----------------------------------------");
3314 emitcode ("", "%s:", sym->rname);
3315 lineCurr->isLabel = 1;
3316 ftype = operandType (IC_LEFT (ic));
3317 _G.currentFunc = sym;
3319 if (IFFUNC_ISNAKED(ftype))
3321 emitcode(";", "naked function: no prologue.");
3325 /* here we need to generate the equates for the
3326 register bank if required */
3327 if (FUNC_REGBANK (ftype) != rbank)
3331 rbank = FUNC_REGBANK (ftype);
3332 for (i = 0; i < mcs51_nRegs; i++)
3334 if (regs8051[i].type != REG_BIT)
3336 if (strcmp (regs8051[i].base, "0") == 0)
3337 emitcode ("", "%s = 0x%02x",
3339 8 * rbank + regs8051[i].offset);
3341 emitcode ("", "%s = %s + 0x%02x",
3344 8 * rbank + regs8051[i].offset);
3349 /* if this is an interrupt service routine then
3350 save acc, b, dpl, dph */
3351 if (IFFUNC_ISISR (sym->type))
3355 rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), sym->regsUsed);
3356 if (IFFUNC_HASFCALL(sym->type) || !bitVectIsZero (rsavebits))
3358 emitcode ("push", "bits");
3361 freeBitVect (rsavebits);
3363 if (!inExcludeList ("acc"))
3364 emitcode ("push", "acc");
3365 if (!inExcludeList ("b"))
3366 emitcode ("push", "b");
3367 if (!inExcludeList ("dpl"))
3368 emitcode ("push", "dpl");
3369 if (!inExcludeList ("dph"))
3370 emitcode ("push", "dph");
3371 /* if this isr has no bank i.e. is going to
3372 run with bank 0 , then we need to save more
3374 if (!FUNC_REGBANK (sym->type))
3378 /* if this function does not call any other
3379 function then we can be economical and
3380 save only those registers that are used */
3381 if (!IFFUNC_HASFCALL(sym->type))
3383 /* if any registers used */
3386 /* save the registers used */
3387 for (i = 0; i < sym->regsUsed->size; i++)
3389 if (bitVectBitValue (sym->regsUsed, i))
3396 /* this function has a function call. We cannot
3397 determine register usage so we will have to push the
3399 saveRBank (0, ic, FALSE);
3400 if (options.parms_in_bank1) {
3401 for (i=0; i < 8 ; i++ ) {
3402 emitcode ("push","%s",rb1regs[i]);
3409 /* This ISR uses a non-zero bank.
3411 * We assume that the bank is available for our
3414 * However, if this ISR calls a function which uses some
3415 * other bank, we must save that bank entirely.
3417 unsigned long banksToSave = 0;
3419 if (IFFUNC_HASFCALL(sym->type))
3422 #define MAX_REGISTER_BANKS 4
3427 for (i = ic; i; i = i->next)
3429 if (i->op == ENDFUNCTION)
3431 /* we got to the end OK. */
3439 dtype = operandType (IC_LEFT(i));
3441 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3443 /* Mark this bank for saving. */
3444 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3446 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3450 banksToSave |= (1 << FUNC_REGBANK(dtype));
3453 /* And note that we don't need to do it in
3461 /* This is a mess; we have no idea what
3462 * register bank the called function might
3465 * The only thing I can think of to do is
3466 * throw a warning and hope.
3468 werror(W_FUNCPTR_IN_USING_ISR);
3472 if (banksToSave && options.useXstack)
3474 /* Since we aren't passing it an ic,
3475 * saveRBank will assume r0 is available to abuse.
3477 * So switch to our (trashable) bank now, so
3478 * the caller's R0 isn't trashed.
3480 emitcode ("push", "psw");
3481 emitcode ("mov", "psw,#0x%02x",
3482 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3486 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3488 if (banksToSave & (1 << ix))
3490 saveRBank(ix, NULL, FALSE);
3494 // TODO: this needs a closer look
3495 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3498 /* Set the register bank to the desired value if nothing else */
3499 /* has done so yet. */
3502 emitcode ("push", "psw");
3503 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3508 /* This is a non-ISR function. The caller has already switched register */
3509 /* banks, if necessary, so just handle the callee-saves option. */
3511 /* if callee-save to be used for this function
3512 then save the registers being used in this function */
3513 if (IFFUNC_CALLEESAVES(sym->type))
3517 /* if any registers used */
3520 bool bits_pushed = FALSE;
3521 /* save the registers used */
3522 for (i = 0; i < sym->regsUsed->size; i++)
3524 if (bitVectBitValue (sym->regsUsed, i))
3526 /* remember one saved register for later usage */
3527 if (calleesaves_saved_register < 0)
3528 calleesaves_saved_register = i;
3529 bits_pushed = pushReg (i, bits_pushed);
3539 if (options.useXstack)
3541 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3543 emitcode ("mov", "r0,%s", spname);
3544 emitcode ("inc", "%s", spname);
3545 emitcode ("xch", "a,_bpx");
3546 emitcode ("movx", "@r0,a");
3547 emitcode ("inc", "r0");
3548 emitcode ("mov", "a,r0");
3549 emitcode ("xch", "a,_bpx");
3553 emitcode ("push", "_bp"); /* save the callers stack */
3554 emitcode ("mov", "_bp,sp");
3559 if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3561 /* set up the stack */
3562 emitcode ("push", "_bp"); /* save the callers stack */
3563 emitcode ("mov", "_bp,sp");
3568 /* For some cases it is worthwhile to perform a RECEIVE iCode */
3569 /* before setting up the stack frame completely. */
3570 if (ric && ric->argreg == 1 && IC_RESULT (ric))
3572 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3576 if (rsym && rsym->regType == REG_CND)
3578 if (rsym && (rsym->accuse || rsym->ruonly))
3580 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3581 rsym = rsym->usl.spillLoc;
3584 /* If the RECEIVE operand immediately spills to the first entry on the */
3585 /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3586 /* rather than the usual @r0/r1 machinations. */
3587 if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3591 _G.current_iCode = ric;
3592 D(emitcode ("; genReceive",""));
3593 for (ofs=0; ofs < sym->recvSize; ofs++)
3595 if (!strcmp (fReturn[ofs], "a"))
3596 emitcode ("push", "acc");
3598 emitcode ("push", fReturn[ofs]);
3600 stackAdjust -= sym->recvSize;
3603 assert (stackAdjust>=0);
3606 _G.current_iCode = ic;
3610 /* If the RECEIVE operand is 4 registers, we can do the moves now */
3611 /* to free up the accumulator. */
3612 else if (rsym && rsym->nRegs && sym->recvSize == 4)
3616 _G.current_iCode = ric;
3617 D(emitcode ("; genReceive",""));
3618 for (ofs=0; ofs < sym->recvSize; ofs++)
3620 emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3622 _G.current_iCode = ic;
3628 /* adjust the stack for the function */
3631 int i = stackAdjust;
3633 werror (W_STACK_OVERFLOW, sym->name);
3635 if (i > 3 && accIsFree)
3637 emitcode ("mov", "a,sp");
3638 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3639 emitcode ("mov", "sp,a");
3643 /* The accumulator is not free, so we will need another register */
3644 /* to clobber. No need to worry about a possible conflict with */
3645 /* the above early RECEIVE optimizations since they would have */
3646 /* freed the accumulator if they were generated. */
3648 if (IFFUNC_CALLEESAVES(sym->type))
3650 /* if it's a callee-saves function we need a saved register */
3651 if (calleesaves_saved_register >= 0)
3653 emitcode ("mov", "%s,a", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3654 emitcode ("mov", "a,sp");
3655 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3656 emitcode ("mov", "sp,a");
3657 emitcode ("mov", "a,%s", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3660 /* do it the hard way */
3662 emitcode ("inc", "sp");
3666 /* not callee-saves, we can clobber r0 */
3667 emitcode ("mov", "r0,a");
3668 emitcode ("mov", "a,sp");
3669 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3670 emitcode ("mov", "sp,a");
3671 emitcode ("mov", "a,r0");
3676 emitcode ("inc", "sp");
3681 char i = ((char) sym->xstack & 0xff);
3683 if (i > 3 && accIsFree)
3685 emitcode ("mov", "a,_spx");
3686 emitcode ("add", "a,#0x%02x", i & 0xff);
3687 emitcode ("mov", "_spx,a");
3691 emitcode ("push", "acc");
3692 emitcode ("mov", "a,_spx");
3693 emitcode ("add", "a,#0x%02x", i & 0xff);
3694 emitcode ("mov", "_spx,a");
3695 emitcode ("pop", "acc");
3700 emitcode ("inc", "_spx");
3704 /* if critical function then turn interrupts off */
3705 if (IFFUNC_ISCRITICAL (ftype))
3707 symbol *tlbl = newiTempLabel (NULL);
3708 emitcode ("setb", "c");
3709 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3710 emitcode ("clr", "c");
3712 emitcode ("push", "psw"); /* save old ea via c in psw */
3716 /*-----------------------------------------------------------------*/
3717 /* genEndFunction - generates epilogue for functions */
3718 /*-----------------------------------------------------------------*/
3720 genEndFunction (iCode * ic)
3722 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3723 lineNode *lnp = lineCurr;
3725 bitVect *regsUsedPrologue;
3726 bitVect *regsUnneeded;
3729 _G.currentFunc = NULL;
3730 if (IFFUNC_ISNAKED(sym->type))
3732 emitcode(";", "naked function: no epilogue.");
3733 if (options.debug && currFunc)
3734 debugFile->writeEndFunction (currFunc, ic, 0);
3738 if (IFFUNC_ISCRITICAL (sym->type))
3740 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3742 emitcode ("rlc", "a"); /* save c in a */
3743 emitcode ("pop", "psw"); /* restore ea via c in psw */
3744 emitcode ("mov", "ea,c");
3745 emitcode ("rrc", "a"); /* restore c from a */
3749 emitcode ("pop", "psw"); /* restore ea via c in psw */
3750 emitcode ("mov", "ea,c");
3754 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3756 if (options.useXstack)
3760 emitcode ("mov", "sp,_bp");
3761 emitcode ("pop", "_bp");
3763 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3765 emitcode ("xch", "a,_bpx");
3766 emitcode ("mov", "r0,a");
3767 emitcode ("dec", "r0");
3768 emitcode ("movx", "a,@r0");
3769 emitcode ("xch", "a,_bpx");
3770 emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3773 else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3776 emitcode ("mov", "sp,_bp");
3777 emitcode ("pop", "_bp");
3781 /* restore the register bank */
3782 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3784 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3785 || !options.useXstack)
3787 /* Special case of ISR using non-zero bank with useXstack
3790 emitcode ("pop", "psw");
3794 if (IFFUNC_ISISR (sym->type))
3798 /* now we need to restore the registers */
3799 /* if this isr has no bank i.e. is going to
3800 run with bank 0 , then we need to save more
3802 if (!FUNC_REGBANK (sym->type))
3805 /* if this function does not call any other
3806 function then we can be economical and
3807 save only those registers that are used */
3808 if (!IFFUNC_HASFCALL(sym->type))
3810 /* if any registers used */
3813 /* save the registers used */
3814 for (i = sym->regsUsed->size; i >= 0; i--)
3816 if (bitVectBitValue (sym->regsUsed, i))
3823 if (options.parms_in_bank1) {
3824 for (i = 7 ; i >= 0 ; i-- ) {
3825 emitcode ("pop","%s",rb1regs[i]);
3828 /* this function has a function call. We cannot
3829 determine register usage so we will have to pop the
3831 unsaveRBank (0, ic, FALSE);
3836 /* This ISR uses a non-zero bank.
3838 * Restore any register banks saved by genFunction
3841 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3844 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3846 if (savedBanks & (1 << ix))
3848 unsaveRBank(ix, NULL, FALSE);
3852 if (options.useXstack)
3854 /* Restore bank AFTER calling unsaveRBank,
3855 * since it can trash r0.
3857 emitcode ("pop", "psw");
3861 if (!inExcludeList ("dph"))
3862 emitcode ("pop", "dph");
3863 if (!inExcludeList ("dpl"))
3864 emitcode ("pop", "dpl");
3865 if (!inExcludeList ("b"))
3866 emitcode ("pop", "b");
3867 if (!inExcludeList ("acc"))
3868 emitcode ("pop", "acc");
3870 rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), sym->regsUsed);
3871 if (IFFUNC_HASFCALL(sym->type) || !bitVectIsZero (rsavebits))
3872 emitcode ("pop", "bits");
3873 freeBitVect (rsavebits);
3875 /* if debug then send end of function */
3876 if (options.debug && currFunc)
3878 debugFile->writeEndFunction (currFunc, ic, 1);
3881 emitcode ("reti", "");
3885 if (IFFUNC_CALLEESAVES(sym->type))
3889 /* if any registers used */
3892 /* save the registers used */
3893 for (i = sym->regsUsed->size; i >= 0; i--)
3895 if (bitVectBitValue (sym->regsUsed, i) ||
3896 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3897 emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
3900 else if (mcs51_ptrRegReq)
3902 emitcode ("pop", "%s", REG_WITH_INDEX (R1_IDX)->dname);
3903 emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
3908 /* if debug then send end of function */
3909 if (options.debug && currFunc)
3911 debugFile->writeEndFunction (currFunc, ic, 1);
3914 if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3916 emitcode ("ljmp", "__sdcc_banked_ret");
3920 emitcode ("ret", "");
3924 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3927 /* If this was an interrupt handler using bank 0 that called another */
3928 /* function, then all registers must be saved; nothing to optimized. */
3929 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3930 && !FUNC_REGBANK(sym->type))
3933 /* There are no push/pops to optimize if not callee-saves or ISR */
3934 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3937 /* If there were stack parameters, we cannot optimize without also */
3938 /* fixing all of the stack offsets; this is too dificult to consider. */
3939 if (FUNC_HASSTACKPARM(sym->type))
3942 /* Compute the registers actually used */
3943 regsUsed = newBitVect (mcs51_nRegs);
3944 regsUsedPrologue = newBitVect (mcs51_nRegs);
3947 if (lnp->ic && lnp->ic->op == FUNCTION)
3948 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3950 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3952 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3953 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3960 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3961 && !bitVectBitValue (regsUsed, CND_IDX))
3963 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3964 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3965 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3966 bitVectUnSetBit (regsUsed, CND_IDX);
3969 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3971 /* If this was an interrupt handler that called another function */
3972 /* function, then assume A, B, DPH, & DPL may be modified by it. */
3973 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3975 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3976 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3977 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3978 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3979 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3982 /* Remove the unneeded push/pops */
3983 regsUnneeded = newBitVect (mcs51_nRegs);
3986 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3988 if (!strncmp(lnp->line, "push", 4))
3990 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3991 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3993 connectLine (lnp->prev, lnp->next);
3994 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3997 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3999 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
4000 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4002 connectLine (lnp->prev, lnp->next);
4003 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4010 for (idx = 0; idx < regsUnneeded->size; idx++)
4011 if (bitVectBitValue (regsUnneeded, idx))
4012 emitcode (";", "eliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
4014 freeBitVect (regsUnneeded);
4015 freeBitVect (regsUsed);
4016 freeBitVect (regsUsedPrologue);
4019 /*-----------------------------------------------------------------*/
4020 /* genRet - generate code for return statement */
4021 /*-----------------------------------------------------------------*/
4025 int size, offset = 0, pushed = 0;
4027 D (emitcode (";", "genRet"));
4029 /* if we have no return value then
4030 just generate the "ret" */
4034 /* we have something to return then
4035 move the return value into place */
4036 aopOp (IC_LEFT (ic), ic, FALSE);
4037 size = AOP_SIZE (IC_LEFT (ic));
4039 if (IS_BIT(_G.currentFunc->etype))
4041 toCarry (IC_LEFT (ic));
4048 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
4051 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
4052 emitcode ("push", "%s", l);
4057 l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
4058 if (strcmp (fReturn[offset], l))
4059 emitcode ("mov", "%s,%s", fReturn[offset++], l);
4066 if (strcmp (fReturn[pushed], "a"))
4067 emitcode ("pop", fReturn[pushed]);
4069 emitcode ("pop", "acc");
4072 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
4075 /* generate a jump to the return label
4076 if the next is not the return statement */
4077 if (!(ic->next && ic->next->op == LABEL &&
4078 IC_LABEL (ic->next) == returnLabel))
4080 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
4084 /*-----------------------------------------------------------------*/
4085 /* genLabel - generates a label */
4086 /*-----------------------------------------------------------------*/
4088 genLabel (iCode * ic)
4090 /* special case never generate */
4091 if (IC_LABEL (ic) == entryLabel)
4094 emitLabel (IC_LABEL (ic));
4097 /*-----------------------------------------------------------------*/
4098 /* genGoto - generates a ljmp */
4099 /*-----------------------------------------------------------------*/
4101 genGoto (iCode * ic)
4103 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
4106 /*-----------------------------------------------------------------*/
4107 /* findLabelBackwards: walks back through the iCode chain looking */
4108 /* for the given label. Returns number of iCode instructions */
4109 /* between that label and given ic. */
4110 /* Returns zero if label not found. */
4111 /*-----------------------------------------------------------------*/
4113 findLabelBackwards (iCode * ic, int key)
4122 /* If we have any pushes or pops, we cannot predict the distance.
4123 I don't like this at all, this should be dealt with in the
4125 if (ic->op == IPUSH || ic->op == IPOP) {
4129 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4138 /*-----------------------------------------------------------------*/
4139 /* genPlusIncr :- does addition with increment if possible */
4140 /*-----------------------------------------------------------------*/
4142 genPlusIncr (iCode * ic)
4144 unsigned int icount;
4145 unsigned int size = getDataSize (IC_RESULT (ic));
4147 /* will try to generate an increment */
4148 /* if the right side is not a literal
4150 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4153 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4155 D(emitcode (";","genPlusIncr"));
4157 /* if increment >=16 bits in register or direct space */
4158 if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG ||
4159 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4160 (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4161 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4162 !isOperandVolatile (IC_RESULT (ic), FALSE) &&
4170 /* If the next instruction is a goto and the goto target
4171 * is < 10 instructions previous to this, we can generate
4172 * jumps straight to that target.
4174 if (ic->next && ic->next->op == GOTO
4175 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4176 && labelRange <= 10)
4178 D (emitcode (";", "tail increment optimized (range %d)", labelRange));
4179 tlbl = IC_LABEL (ic->next);
4184 tlbl = newiTempLabel (NULL);
4187 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4188 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4189 IS_AOP_PREG (IC_RESULT (ic)))
4190 emitcode ("cjne", "%s,#0x00,%05d$",
4191 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4195 emitcode ("clr", "a");
4196 emitcode ("cjne", "a,%s,%05d$",
4197 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4201 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4204 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4205 IS_AOP_PREG (IC_RESULT (ic)))
4206 emitcode ("cjne", "%s,#0x00,%05d$",
4207 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4210 emitcode ("cjne", "a,%s,%05d$",
4211 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4214 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4218 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4219 IS_AOP_PREG (IC_RESULT (ic)))
4220 emitcode ("cjne", "%s,#0x00,%05d$",
4221 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4225 emitcode ("cjne", "a,%s,%05d$",
4226 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4229 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4239 /* if result is dptr */
4240 if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
4241 (AOP_SIZE (IC_RESULT (ic)) == 2) &&
4242 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
4243 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
4245 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4251 if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
4254 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0);
4255 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1);
4257 emitcode ("inc", "dptr");
4262 /* if the literal value of the right hand side
4263 is greater than 4 then it is not worth it */
4267 /* if the sizes are greater than 1 then we cannot */
4268 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4269 AOP_SIZE (IC_LEFT (ic)) > 1)
4272 /* we can if the aops of the left & result match or
4273 if they are in registers and the registers are the
4275 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4279 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4280 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4281 aopPut (IC_RESULT (ic), "a", 0);
4287 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4296 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4297 emitcode ("inc", "a");
4298 aopPut (IC_RESULT (ic), "a", 0);
4305 /*-----------------------------------------------------------------*/
4306 /* outBitAcc - output a bit in acc */
4307 /*-----------------------------------------------------------------*/
4309 outBitAcc (operand * result)
4311 symbol *tlbl = newiTempLabel (NULL);
4312 /* if the result is a bit */
4313 if (AOP_TYPE (result) == AOP_CRY)
4315 aopPut (result, "a", 0);
4319 emitcode ("jz", "%05d$", tlbl->key + 100);
4320 emitcode ("mov", "a,%s", one);
4326 /*-----------------------------------------------------------------*/
4327 /* genPlusBits - generates code for addition of two bits */
4328 /*-----------------------------------------------------------------*/
4330 genPlusBits (iCode * ic)
4332 D (emitcode (";", "genPlusBits"));
4334 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4335 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4337 symbol *lbl = newiTempLabel (NULL);
4338 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4339 emitcode ("cpl", "c");
4341 outBitC (IC_RESULT (ic));
4345 emitcode ("clr", "a");
4346 emitcode ("rlc", "a");
4347 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4348 emitcode ("addc", "a,%s", zero);
4349 outAcc (IC_RESULT (ic));
4354 /* This is the original version of this code.
4356 * This is being kept around for reference,
4357 * because I am not entirely sure I got it right...
4360 adjustArithmeticResult (iCode * ic)
4362 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4363 AOP_SIZE (IC_LEFT (ic)) == 3 &&
4364 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4365 aopPut (IC_RESULT (ic),
4366 aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4369 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4370 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4371 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4372 aopPut (IC_RESULT (ic),
4373 aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4376 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4377 AOP_SIZE (IC_LEFT (ic)) < 3 &&
4378 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4379 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4380 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4383 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4384 aopPut (IC_RESULT (ic), buffer, 2);
4388 /* This is the pure and virtuous version of this code.
4389 * I'm pretty certain it's right, but not enough to toss the old
4393 adjustArithmeticResult (iCode * ic)
4395 if (opIsGptr (IC_RESULT (ic)) &&
4396 opIsGptr (IC_LEFT (ic)) &&
4397 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4399 aopPut (IC_RESULT (ic),
4400 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4404 if (opIsGptr (IC_RESULT (ic)) &&
4405 opIsGptr (IC_RIGHT (ic)) &&
4406 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4408 aopPut (IC_RESULT (ic),
4409 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4413 if (opIsGptr (IC_RESULT (ic)) &&
4414 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4415 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4416 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4417 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4420 SNPRINTF (buffer, sizeof(buffer),
4421 "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4422 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4427 /*-----------------------------------------------------------------*/
4428 /* genPlus - generates code for addition */
4429 /*-----------------------------------------------------------------*/
4431 genPlus (iCode * ic)
4433 int size, offset = 0;
4436 bool swappedLR = FALSE;
4437 operand *leftOp, *rightOp;
4440 D (emitcode (";", "genPlus"));
4442 /* special cases :- */
4444 aopOp (IC_LEFT (ic), ic, FALSE);
4445 aopOp (IC_RIGHT (ic), ic, FALSE);
4446 aopOp (IC_RESULT (ic), ic, TRUE);
4448 /* if literal, literal on the right or
4449 if left requires ACC or right is already
4451 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4452 (AOP_NEEDSACC (IC_LEFT (ic))) ||
4453 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4455 operand *t = IC_RIGHT (ic);
4456 IC_RIGHT (ic) = IC_LEFT (ic);
4461 /* if both left & right are in bit
4463 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4464 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4470 /* if left in bit space & right literal */
4471 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4472 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4474 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4475 /* if result in bit space */
4476 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4478 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4479 emitcode ("cpl", "c");
4480 outBitC (IC_RESULT (ic));
4484 size = getDataSize (IC_RESULT (ic));
4487 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4488 emitcode ("addc", "a,%s", zero);
4489 aopPut (IC_RESULT (ic), "a", offset++);
4495 /* if I can do an increment instead
4496 of add then GOOD for ME */
4497 if (genPlusIncr (ic) == TRUE)
4500 size = getDataSize (IC_RESULT (ic));
4501 leftOp = IC_LEFT(ic);
4502 rightOp = IC_RIGHT(ic);
4505 /* if this is an add for an array access
4506 at a 256 byte boundary */
4508 && AOP_TYPE (op) == AOP_IMMD
4510 && IS_SPEC (OP_SYM_ETYPE (op))
4511 && SPEC_ABSA (OP_SYM_ETYPE (op))
4512 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4515 D(emitcode ("; genPlus aligned array",""));
4516 aopPut (IC_RESULT (ic),
4517 aopGet (rightOp, 0, FALSE, FALSE),
4520 if( 1 == getDataSize (IC_RIGHT (ic)) )
4522 aopPut (IC_RESULT (ic),
4523 aopGet (leftOp, 1, FALSE, FALSE),
4528 MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4529 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4530 aopPut (IC_RESULT (ic), "a", 1);
4535 /* if the lower bytes of a literal are zero skip the addition */
4536 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4538 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4539 (skip_bytes+1 < size))
4544 D(emitcode ("; genPlus shortcut",""));
4549 if( offset >= skip_bytes )
4551 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4554 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4556 emitcode("xch", "a,b");
4557 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4558 emitcode (add, "a,b");
4561 else if (aopGetUsesAcc (leftOp, offset))
4563 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4564 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4568 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4569 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4571 aopPut (IC_RESULT (ic), "a", offset);
4572 add = "addc"; /* further adds must propagate carry */
4576 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4577 isOperandVolatile (IC_RESULT (ic), FALSE))
4580 aopPut (IC_RESULT (ic),
4581 aopGet (leftOp, offset, FALSE, FALSE),
4588 adjustArithmeticResult (ic);
4591 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4594 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4595 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4599 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4600 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4604 /*-----------------------------------------------------------------*/
4605 /* genMinusDec :- does subtraction with decrement if possible */
4606 /*-----------------------------------------------------------------*/
4608 genMinusDec (iCode * ic)
4610 unsigned int icount;
4611 unsigned int size = getDataSize (IC_RESULT (ic));
4613 /* will try to generate an increment */
4614 /* if the right side is not a literal
4616 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4619 /* if the literal value of the right hand side
4620 is greater than 4 then it is not worth it */
4621 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4624 D (emitcode (";", "genMinusDec"));
4626 /* if decrement >=16 bits in register or direct space */
4627 if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG ||
4628 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4629 (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4630 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4638 /* If the next instruction is a goto and the goto target
4639 * is <= 10 instructions previous to this, we can generate
4640 * jumps straight to that target.
4642 if (ic->next && ic->next->op == GOTO
4643 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4644 && labelRange <= 10)
4646 D (emitcode (";", "tail decrement optimized (range %d)", labelRange));
4647 tlbl = IC_LABEL (ic->next);
4652 tlbl = newiTempLabel (NULL);
4656 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4657 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4658 IS_AOP_PREG (IC_RESULT (ic)))
4659 emitcode ("cjne", "%s,#0xff,%05d$"
4660 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4664 emitcode ("mov", "a,#0xff");
4665 emitcode ("cjne", "a,%s,%05d$"
4666 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4669 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4672 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4673 IS_AOP_PREG (IC_RESULT (ic)))
4674 emitcode ("cjne", "%s,#0xff,%05d$"
4675 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4679 emitcode ("cjne", "a,%s,%05d$"
4680 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4683 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4687 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4688 IS_AOP_PREG (IC_RESULT (ic)))
4689 emitcode ("cjne", "%s,#0xff,%05d$"
4690 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4694 emitcode ("cjne", "a,%s,%05d$"
4695 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4698 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4707 /* if the sizes are greater than 1 then we cannot */
4708 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4709 AOP_SIZE (IC_LEFT (ic)) > 1)
4712 /* we can if the aops of the left & result match or
4713 if they are in registers and the registers are the
4715 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4719 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4721 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4726 l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
4731 emitcode ("dec", "%s", l);
4734 if (AOP_NEEDSACC (IC_RESULT (ic)))
4735 aopPut (IC_RESULT (ic), "a", 0);
4742 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4743 emitcode ("dec", "a");
4744 aopPut (IC_RESULT (ic), "a", 0);
4751 /*-----------------------------------------------------------------*/
4752 /* addSign - complete with sign */
4753 /*-----------------------------------------------------------------*/
4755 addSign (operand * result, int offset, int sign)
4757 int size = (getDataSize (result) - offset);
4762 emitcode ("rlc", "a");
4763 emitcode ("subb", "a,acc");
4766 aopPut (result, "a", offset++);
4773 aopPut (result, zero, offset++);
4779 /*-----------------------------------------------------------------*/
4780 /* genMinusBits - generates code for subtraction of two bits */
4781 /*-----------------------------------------------------------------*/
4783 genMinusBits (iCode * ic)
4785 symbol *lbl = newiTempLabel (NULL);
4787 D (emitcode (";", "genMinusBits"));
4789 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4791 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4792 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4793 emitcode ("cpl", "c");
4795 outBitC (IC_RESULT (ic));
4799 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4800 emitcode ("subb", "a,acc");
4801 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4802 emitcode ("inc", "a");
4804 aopPut (IC_RESULT (ic), "a", 0);
4805 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4809 /*-----------------------------------------------------------------*/
4810 /* genMinus - generates code for subtraction */
4811 /*-----------------------------------------------------------------*/
4813 genMinus (iCode * ic)
4815 int size, offset = 0;
4817 D (emitcode (";", "genMinus"));
4819 aopOp (IC_LEFT (ic), ic, FALSE);
4820 aopOp (IC_RIGHT (ic), ic, FALSE);
4821 aopOp (IC_RESULT (ic), ic, TRUE);
4823 /* special cases :- */
4824 /* if both left & right are in bit space */
4825 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4826 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4832 /* if I can do an decrement instead
4833 of subtract then GOOD for ME */
4834 if (genMinusDec (ic) == TRUE)
4837 size = getDataSize (IC_RESULT (ic));
4839 /* if literal, add a,#-lit, else normal subb */
4840 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4842 unsigned long lit = 0L;
4843 bool useCarry = FALSE;
4845 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4850 if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4852 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4853 if (!offset && !size && lit== (unsigned long) -1)
4855 emitcode ("dec", "a");
4859 /* first add without previous c */
4860 emitcode ("add", "a,#0x%02x",
4861 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4866 emitcode ("addc", "a,#0x%02x",
4867 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4869 aopPut (IC_RESULT (ic), "a", offset++);
4873 /* no need to add zeroes */
4874 if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4876 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4885 operand *leftOp, *rightOp;
4887 leftOp = IC_LEFT(ic);
4888 rightOp = IC_RIGHT(ic);
4892 if (aopGetUsesAcc(rightOp, offset)) {
4893 if (aopGetUsesAcc(leftOp, offset)) {
4896 MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4898 emitcode ("mov", "b,a");
4901 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4902 emitcode ("subb", "a,b");
4905 /* reverse subtraction with 2's complement */
4907 emitcode( "setb", "c");
4909 emitcode( "cpl", "c");
4910 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4911 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4912 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4913 emitcode("cpl", "a");
4914 if (size) /* skip if last byte */
4915 emitcode( "cpl", "c");
4918 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4921 emitcode ("subb", "a,%s",
4922 aopGet(rightOp, offset, FALSE, TRUE));
4925 aopPut (IC_RESULT (ic), "a", offset++);
4929 adjustArithmeticResult (ic);
4932 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4933 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4934 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4938 /*-----------------------------------------------------------------*/
4939 /* genMultbits :- multiplication of bits */
4940 /*-----------------------------------------------------------------*/
4942 genMultbits (operand * left,
4946 D (emitcode (";", "genMultbits"));
4948 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4949 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4953 /*-----------------------------------------------------------------*/
4954 /* genMultOneByte : 8*8=8/16 bit multiplication */
4955 /*-----------------------------------------------------------------*/
4957 genMultOneByte (operand * left,
4962 int size = AOP_SIZE (result);
4963 bool runtimeSign, compiletimeSign;
4964 bool lUnsigned, rUnsigned, pushedB;
4966 D (emitcode (";", "genMultOneByte"));
4968 if (size < 1 || size > 2)
4970 /* this should never happen */
4971 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4972 AOP_SIZE(result), __FILE__, lineno);
4976 /* (if two literals: the value is computed before) */
4977 /* if one literal, literal on the right */
4978 if (AOP_TYPE (left) == AOP_LIT)
4983 /* emitcode (";", "swapped left and right"); */
4985 /* if no literal, unsigned on the right: shorter code */
4986 if ( AOP_TYPE (right) != AOP_LIT
4987 && SPEC_USIGN (getSpec (operandType (left))))
4994 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4995 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4999 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
5000 no need to take care about the signedness! */
5001 || (lUnsigned && rUnsigned))
5003 /* just an unsigned 8 * 8 = 8 multiply
5005 /* emitcode (";","unsigned"); */
5006 /* TODO: check for accumulator clash between left & right aops? */
5008 if (AOP_TYPE (right) == AOP_LIT)
5010 /* moving to accumulator first helps peepholes */
5011 MOVA (aopGet (left, 0, FALSE, FALSE));
5012 MOVB (aopGet (right, 0, FALSE, FALSE));
5016 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5017 MOVA (aopGet (left, 0, FALSE, FALSE));
5020 emitcode ("mul", "ab");
5021 aopPut (result, "a", 0);
5023 aopPut (result, "b", 1);
5029 /* we have to do a signed multiply */
5030 /* emitcode (";", "signed"); */
5032 /* now sign adjust for both left & right */
5034 /* let's see what's needed: */
5035 /* apply negative sign during runtime */
5036 runtimeSign = FALSE;
5037 /* negative sign from literals */
5038 compiletimeSign = FALSE;
5042 if (AOP_TYPE(left) == AOP_LIT)
5044 /* signed literal */
5045 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5047 compiletimeSign = TRUE;
5050 /* signed but not literal */
5056 if (AOP_TYPE(right) == AOP_LIT)
5058 /* signed literal */
5059 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5061 compiletimeSign ^= TRUE;
5064 /* signed but not literal */
5068 /* initialize F0, which stores the runtime sign */
5071 if (compiletimeSign)
5072 emitcode ("setb", "F0"); /* set sign flag */
5074 emitcode ("clr", "F0"); /* reset sign flag */
5077 /* save the signs of the operands */
5078 if (AOP_TYPE(right) == AOP_LIT)
5080 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5082 if (!rUnsigned && val < 0)
5083 emitcode ("mov", "b,#0x%02x", -val);
5085 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5087 else /* ! literal */
5089 if (rUnsigned) /* emitcode (";", "signed"); */
5090 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5093 MOVA (aopGet (right, 0, FALSE, FALSE));
5094 lbl = newiTempLabel (NULL);
5095 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5096 emitcode ("cpl", "F0"); /* complement sign flag */
5097 emitcode ("cpl", "a"); /* 2's complement */
5098 emitcode ("inc", "a");
5100 emitcode ("mov", "b,a");
5104 if (AOP_TYPE(left) == AOP_LIT)
5106 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5108 if (!lUnsigned && val < 0)
5109 emitcode ("mov", "a,#0x%02x", -val);
5111 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5113 else /* ! literal */
5115 MOVA (aopGet (left, 0, FALSE, FALSE));
5119 lbl = newiTempLabel (NULL);
5120 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5121 emitcode ("cpl", "F0"); /* complement sign flag */
5122 emitcode ("cpl", "a"); /* 2's complement */
5123 emitcode ("inc", "a");
5128 /* now the multiplication */
5129 emitcode ("mul", "ab");
5130 if (runtimeSign || compiletimeSign)
5132 lbl = newiTempLabel (NULL);
5134 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5135 emitcode ("cpl", "a"); /* lsb 2's complement */
5137 emitcode ("inc", "a"); /* inc doesn't set carry flag */
5140 emitcode ("add", "a,#1"); /* this sets carry flag */
5141 emitcode ("xch", "a,b");
5142 emitcode ("cpl", "a"); /* msb 2's complement */
5143 emitcode ("addc", "a,#0");
5144 emitcode ("xch", "a,b");
5148 aopPut (result, "a", 0);
5150 aopPut (result, "b", 1);
5155 /*-----------------------------------------------------------------*/
5156 /* genMult - generates code for multiplication */
5157 /*-----------------------------------------------------------------*/
5159 genMult (iCode * ic)
5161 operand *left = IC_LEFT (ic);
5162 operand *right = IC_RIGHT (ic);
5163 operand *result = IC_RESULT (ic);
5165 D (emitcode (";", "genMult"));
5167 /* assign the asmops */
5168 aopOp (left, ic, FALSE);
5169 aopOp (right, ic, FALSE);
5170 aopOp (result, ic, TRUE);
5172 /* special cases first */
5174 if (AOP_TYPE (left) == AOP_CRY &&
5175 AOP_TYPE (right) == AOP_CRY)
5177 genMultbits (left, right, result);
5181 /* if both are of size == 1 */
5182 #if 0 // one of them can be a sloc shared with the result
5183 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
5185 if (getSize(operandType(left)) == 1 &&
5186 getSize(operandType(right)) == 1)
5189 genMultOneByte (left, right, result);
5193 /* should have been converted to function call */
5194 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
5195 getSize(OP_SYMBOL(right)->type));
5199 freeAsmop (result, NULL, ic, TRUE);
5200 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5201 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5204 /*-----------------------------------------------------------------*/
5205 /* genDivbits :- division of bits */
5206 /*-----------------------------------------------------------------*/
5208 genDivbits (operand * left,
5215 D(emitcode ("; genDivbits",""));
5219 /* the result must be bit */
5220 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5221 l = aopGet (left, 0, FALSE, FALSE);
5225 emitcode ("div", "ab");
5226 emitcode ("rrc", "a");
5230 aopPut (result, "c", 0);
5233 /*-----------------------------------------------------------------*/
5234 /* genDivOneByte : 8 bit division */
5235 /*-----------------------------------------------------------------*/
5237 genDivOneByte (operand * left,
5241 bool lUnsigned, rUnsigned, pushedB;
5242 bool runtimeSign, compiletimeSign;
5243 bool accuse = FALSE;
5244 bool pushedA = FALSE;
5248 D(emitcode ("; genDivOneByte",""));
5250 /* Why is it necessary that genDivOneByte() can return an int result?
5253 volatile unsigned char uc;
5254 volatile signed char sc1, sc2;
5267 In all cases a one byte result would overflow, the following cast to int
5268 would return the wrong result.
5270 Two possible solution:
5271 a) cast operands to int, if ((unsigned) / (signed)) or
5272 ((signed) / (signed))
5273 b) return an 16 bit signed int; this is what we're doing here!
5276 size = AOP_SIZE (result) - 1;
5278 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5279 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5283 /* signed or unsigned */
5284 if (lUnsigned && rUnsigned)
5286 /* unsigned is easy */
5287 MOVB (aopGet (right, 0, FALSE, FALSE));
5288 MOVA (aopGet (left, 0, FALSE, FALSE));
5289 emitcode ("div", "ab");
5290 aopPut (result, "a", 0);
5292 aopPut (result, zero, offset++);
5298 /* signed is a little bit more difficult */
5300 /* now sign adjust for both left & right */
5302 /* let's see what's needed: */
5303 /* apply negative sign during runtime */
5304 runtimeSign = FALSE;
5305 /* negative sign from literals */
5306 compiletimeSign = FALSE;
5310 if (AOP_TYPE(left) == AOP_LIT)
5312 /* signed literal */
5313 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5315 compiletimeSign = TRUE;
5318 /* signed but not literal */
5324 if (AOP_TYPE(right) == AOP_LIT)
5326 /* signed literal */
5327 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5329 compiletimeSign ^= TRUE;
5332 /* signed but not literal */
5336 /* initialize F0, which stores the runtime sign */
5339 if (compiletimeSign)
5340 emitcode ("setb", "F0"); /* set sign flag */
5342 emitcode ("clr", "F0"); /* reset sign flag */
5345 /* save the signs of the operands */
5346 if (AOP_TYPE(right) == AOP_LIT)
5348 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5350 if (!rUnsigned && val < 0)
5351 emitcode ("mov", "b,#0x%02x", -val);
5353 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5355 else /* ! literal */
5358 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5361 MOVA (aopGet (right, 0, FALSE, FALSE));
5362 lbl = newiTempLabel (NULL);
5363 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5364 emitcode ("cpl", "F0"); /* complement sign flag */
5365 emitcode ("cpl", "a"); /* 2's complement */
5366 emitcode ("inc", "a");
5368 emitcode ("mov", "b,a");
5372 if (AOP_TYPE(left) == AOP_LIT)
5374 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5376 if (!lUnsigned && val < 0)
5377 emitcode ("mov", "a,#0x%02x", -val);
5379 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5381 else /* ! literal */
5383 MOVA (aopGet (left, 0, FALSE, FALSE));
5387 lbl = newiTempLabel (NULL);
5388 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5389 emitcode ("cpl", "F0"); /* complement sign flag */
5390 emitcode ("cpl", "a"); /* 2's complement */
5391 emitcode ("inc", "a");
5396 /* now the division */
5397 emitcode ("div", "ab");
5399 if (runtimeSign || compiletimeSign)
5401 lbl = newiTempLabel (NULL);
5403 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5404 emitcode ("cpl", "a"); /* lsb 2's complement */
5405 emitcode ("inc", "a");
5408 accuse = aopPut (result, "a", 0);
5411 /* msb is 0x00 or 0xff depending on the sign */
5416 emitcode ("push", "acc");
5419 emitcode ("mov", "c,F0");
5420 emitcode ("subb", "a,acc");
5422 aopPut (result, "a", offset++);
5424 else /* compiletimeSign */
5426 if (aopPutUsesAcc (result, "#0xFF", offset))
5428 emitcode ("push", "acc");
5432 aopPut (result, "#0xff", offset++);
5438 aopPut (result, "a", 0);
5440 aopPut (result, zero, offset++);
5444 emitcode ("pop", "acc");
5448 /*-----------------------------------------------------------------*/
5449 /* genDiv - generates code for division */
5450 /*-----------------------------------------------------------------*/
5454 operand *left = IC_LEFT (ic);
5455 operand *right = IC_RIGHT (ic);
5456 operand *result = IC_RESULT (ic);
5458 D (emitcode (";", "genDiv"));
5460 /* assign the amsops */
5461 aopOp (left, ic, FALSE);
5462 aopOp (right, ic, FALSE);
5463 aopOp (result, ic, TRUE);
5465 /* special cases first */
5467 if (AOP_TYPE (left) == AOP_CRY &&
5468 AOP_TYPE (right) == AOP_CRY)
5470 genDivbits (left, right, result);
5474 /* if both are of size == 1 */
5475 if (AOP_SIZE (left) == 1 &&
5476 AOP_SIZE (right) == 1)
5478 genDivOneByte (left, right, result);
5482 /* should have been converted to function call */
5485 freeAsmop (result, NULL, ic, TRUE);
5486 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5487 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5490 /*-----------------------------------------------------------------*/
5491 /* genModbits :- modulus of bits */
5492 /*-----------------------------------------------------------------*/
5494 genModbits (operand * left,
5501 D (emitcode (";", "genModbits"));
5505 /* the result must be bit */
5506 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5507 l = aopGet (left, 0, FALSE, FALSE);
5511 emitcode ("div", "ab");
5512 emitcode ("mov", "a,b");
5513 emitcode ("rrc", "a");
5517 aopPut (result, "c", 0);
5520 /*-----------------------------------------------------------------*/
5521 /* genModOneByte : 8 bit modulus */
5522 /*-----------------------------------------------------------------*/
5524 genModOneByte (operand * left,
5528 bool lUnsigned, rUnsigned, pushedB;
5529 bool runtimeSign, compiletimeSign;
5533 D (emitcode (";", "genModOneByte"));
5535 size = AOP_SIZE (result) - 1;
5537 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5538 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5540 /* if right is a literal, check it for 2^n */
5541 if (AOP_TYPE(right) == AOP_LIT)
5543 unsigned char val = abs((int) operandLitValue(right));
5544 symbol *lbl2 = NULL;
5548 case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5557 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5558 "modulus of unsigned char by 2^n literal shouldn't be processed here");
5559 /* because iCode should have been changed to genAnd */
5560 /* see file "SDCCopt.c", function "convertToFcall()" */
5562 MOVA (aopGet (left, 0, FALSE, FALSE));
5563 emitcode ("mov", "c,acc.7");
5564 emitcode ("anl", "a,#0x%02x", val - 1);
5565 lbl = newiTempLabel (NULL);
5566 emitcode ("jz", "%05d$", (lbl->key + 100));
5567 emitcode ("jnc", "%05d$", (lbl->key + 100));
5568 emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5574 aopPut (result, "a", 0);
5576 aopPut (result, "#0xff", offs2++);
5577 lbl2 = newiTempLabel (NULL);
5578 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5581 aopPut (result, "a", 0);
5583 aopPut (result, zero, offset++);
5597 /* signed or unsigned */
5598 if (lUnsigned && rUnsigned)
5600 /* unsigned is easy */
5601 MOVB (aopGet (right, 0, FALSE, FALSE));
5602 MOVA (aopGet (left, 0, FALSE, FALSE));
5603 emitcode ("div", "ab");
5604 aopPut (result, "b", 0);
5606 aopPut (result, zero, offset++);
5612 /* signed is a little bit more difficult */
5614 /* now sign adjust for both left & right */
5616 /* modulus: sign of the right operand has no influence on the result! */
5617 if (AOP_TYPE(right) == AOP_LIT)
5619 signed char val = (char) operandLitValue(right);
5621 if (!rUnsigned && val < 0)
5622 emitcode ("mov", "b,#0x%02x", -val);
5624 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5626 else /* not literal */
5629 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5632 MOVA (aopGet (right, 0, FALSE, FALSE));
5633 lbl = newiTempLabel (NULL);
5634 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5635 emitcode ("cpl", "a"); /* 2's complement */
5636 emitcode ("inc", "a");
5638 emitcode ("mov", "b,a");
5642 /* let's see what's needed: */
5643 /* apply negative sign during runtime */
5644 runtimeSign = FALSE;
5645 /* negative sign from literals */
5646 compiletimeSign = FALSE;
5648 /* sign adjust left side */
5649 if (AOP_TYPE(left) == AOP_LIT)
5651 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5653 if (!lUnsigned && val < 0)
5655 compiletimeSign = TRUE; /* set sign flag */
5656 emitcode ("mov", "a,#0x%02x", -val);
5659 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5661 else /* ! literal */
5663 MOVA (aopGet (left, 0, FALSE, FALSE));
5668 emitcode ("clr", "F0"); /* clear sign flag */
5670 lbl = newiTempLabel (NULL);
5671 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5672 emitcode ("setb", "F0"); /* set sign flag */
5673 emitcode ("cpl", "a"); /* 2's complement */
5674 emitcode ("inc", "a");
5679 /* now the modulus */
5680 emitcode ("div", "ab");
5682 if (runtimeSign || compiletimeSign)
5684 emitcode ("mov", "a,b");
5685 lbl = newiTempLabel (NULL);
5687 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5688 emitcode ("cpl", "a"); /* 2's complement */
5689 emitcode ("inc", "a");
5692 aopPut (result, "a", 0);
5695 /* msb is 0x00 or 0xff depending on the sign */
5698 emitcode ("mov", "c,F0");
5699 emitcode ("subb", "a,acc");
5701 aopPut (result, "a", offset++);
5703 else /* compiletimeSign */
5705 aopPut (result, "#0xff", offset++);
5710 aopPut (result, "b", 0);
5712 aopPut (result, zero, offset++);
5718 /*-----------------------------------------------------------------*/
5719 /* genMod - generates code for division */
5720 /*-----------------------------------------------------------------*/
5724 operand *left = IC_LEFT (ic);
5725 operand *right = IC_RIGHT (ic);
5726 operand *result = IC_RESULT (ic);
5728 D (emitcode (";", "genMod"));
5730 /* assign the asmops */
5731 aopOp (left, ic, FALSE);
5732 aopOp (right, ic, FALSE);
5733 aopOp (result, ic, TRUE);
5735 /* special cases first */
5737 if (AOP_TYPE (left) == AOP_CRY &&
5738 AOP_TYPE (right) == AOP_CRY)
5740 genModbits (left, right, result);
5744 /* if both are of size == 1 */
5745 if (AOP_SIZE (left) == 1 &&
5746 AOP_SIZE (right) == 1)
5748 genModOneByte (left, right, result);
5752 /* should have been converted to function call */
5756 freeAsmop (result, NULL, ic, TRUE);
5757 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5758 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5761 /*-----------------------------------------------------------------*/
5762 /* genIfxJump :- will create a jump depending on the ifx */
5763 /*-----------------------------------------------------------------*/
5765 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5768 symbol *tlbl = newiTempLabel (NULL);
5771 D (emitcode (";", "genIfxJump"));
5773 /* if true label then we jump if condition
5777 jlbl = IC_TRUE (ic);
5778 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5779 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5783 /* false label is present */
5784 jlbl = IC_FALSE (ic);
5785 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5786 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5788 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5789 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5791 emitcode (inst, "%05d$", tlbl->key + 100);
5792 freeForBranchAsmop (result);
5793 freeForBranchAsmop (right);
5794 freeForBranchAsmop (left);
5795 emitcode ("ljmp", "%05d$", jlbl->key + 100);
5798 /* mark the icode as generated */
5802 /*-----------------------------------------------------------------*/
5803 /* genCmp :- greater or less than comparison */
5804 /*-----------------------------------------------------------------*/
5806 genCmp (operand * left, operand * right,
5807 operand * result, iCode * ifx, int sign, iCode *ic)
5809 int size, offset = 0;
5810 unsigned long lit = 0L;
5813 D (emitcode (";", "genCmp"));
5815 /* if left & right are bit variables */
5816 if (AOP_TYPE (left) == AOP_CRY &&
5817 AOP_TYPE (right) == AOP_CRY)
5819 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5820 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5824 /* subtract right from left if at the
5825 end the carry flag is set then we know that
5826 left is greater than right */
5827 size = max (AOP_SIZE (left), AOP_SIZE (right));
5829 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5830 if ((size == 1) && !sign &&
5831 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5833 symbol *lbl = newiTempLabel (NULL);
5834 emitcode ("cjne", "%s,%s,%05d$",
5835 aopGet (left, offset, FALSE, FALSE),
5836 aopGet (right, offset, FALSE, FALSE),
5842 if (AOP_TYPE (right) == AOP_LIT)
5844 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5845 /* optimize if(x < 0) or if(x >= 0) */
5854 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5855 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5857 genIfxJump (ifx, "acc.7", left, right, result);
5858 freeAsmop (right, NULL, ic, TRUE);
5859 freeAsmop (left, NULL, ic, TRUE);
5865 emitcode ("rlc", "a");
5872 int bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5873 while (size && (bytelit == 0))
5876 bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5882 MOVA (aopGet (left, offset, FALSE, FALSE));
5883 if (sign && size == 0)
5885 emitcode ("xrl", "a,#0x80");
5886 emitcode ("subb", "a,#0x%02x",
5887 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5891 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5901 bool pushedB = FALSE;
5902 rightInB = aopGetUsesAcc(right, offset);
5906 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5908 MOVA (aopGet (left, offset, FALSE, FALSE));
5909 if (sign && size == 0)
5911 emitcode ("xrl", "a,#0x80");
5916 MOVB (aopGet (right, offset, FALSE, FALSE));
5918 emitcode ("xrl", "b,#0x80");
5919 emitcode ("subb", "a,b");
5924 emitcode ("subb", "a,b");
5926 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5936 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5937 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5938 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5944 /* if the result is used in the next
5945 ifx conditional branch then generate
5946 code a little differently */
5949 genIfxJump (ifx, "c", NULL, NULL, result);
5955 /* leave the result in acc */
5959 /*-----------------------------------------------------------------*/
5960 /* genCmpGt :- greater than comparison */
5961 /*-----------------------------------------------------------------*/
5963 genCmpGt (iCode * ic, iCode * ifx)
5965 operand *left, *right, *result;
5966 sym_link *letype, *retype;
5969 D (emitcode (";", "genCmpGt"));
5971 left = IC_LEFT (ic);
5972 right = IC_RIGHT (ic);
5973 result = IC_RESULT (ic);
5975 letype = getSpec (operandType (left));
5976 retype = getSpec (operandType (right));
5977 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5978 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5979 /* assign the amsops */
5980 aopOp (result, ic, TRUE);
5981 aopOp (left, ic, FALSE);
5982 aopOp (right, ic, FALSE);
5984 genCmp (right, left, result, ifx, sign, ic);
5986 freeAsmop (result, NULL, ic, TRUE);
5989 /*-----------------------------------------------------------------*/
5990 /* genCmpLt - less than comparisons */
5991 /*-----------------------------------------------------------------*/
5993 genCmpLt (iCode * ic, iCode * ifx)
5995 operand *left, *right, *result;
5996 sym_link *letype, *retype;
5999 D (emitcode (";", "genCmpLt"));
6001 left = IC_LEFT (ic);
6002 right = IC_RIGHT (ic);
6003 result = IC_RESULT (ic);
6005 letype = getSpec (operandType (left));
6006 retype = getSpec (operandType (right));
6007 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
6008 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
6009 /* assign the amsops */
6010 aopOp (result, ic, TRUE);
6011 aopOp (left, ic, FALSE);
6012 aopOp (right, ic, FALSE);
6014 genCmp (left, right, result, ifx, sign, ic);
6016 freeAsmop (result, NULL, ic, TRUE);
6019 /*-----------------------------------------------------------------*/
6020 /* gencjneshort - compare and jump if not equal */
6021 /*-----------------------------------------------------------------*/
6023 gencjneshort (operand * left, operand * right, symbol * lbl)
6025 int size = max (AOP_SIZE (left), AOP_SIZE (right));
6027 unsigned long lit = 0L;
6029 D (emitcode (";", "gencjneshort"));
6031 /* if the left side is a literal or
6032 if the right is in a pointer register and left
6034 if ((AOP_TYPE (left) == AOP_LIT) ||
6035 (AOP_TYPE (left) == AOP_IMMD) ||
6036 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6043 if (AOP_TYPE (right) == AOP_LIT)
6044 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6046 /* if the right side is a literal then anything goes */
6047 if (AOP_TYPE (right) == AOP_LIT &&
6048 AOP_TYPE (left) != AOP_DIR &&
6049 AOP_TYPE (left) != AOP_IMMD)
6053 emitcode ("cjne", "%s,%s,%05d$",
6054 aopGet (left, offset, FALSE, FALSE),
6055 aopGet (right, offset, FALSE, FALSE),
6061 /* if the right side is in a register or in direct space or
6062 if the left is a pointer register & right is not */
6063 else if (AOP_TYPE (right) == AOP_REG ||
6064 AOP_TYPE (right) == AOP_DIR ||
6065 AOP_TYPE (right) == AOP_LIT ||
6066 AOP_TYPE (right) == AOP_IMMD ||
6067 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6068 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6072 MOVA (aopGet (left, offset, FALSE, FALSE));
6073 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6074 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6075 emitcode ("jnz", "%05d$", lbl->key + 100);
6077 emitcode ("cjne", "a,%s,%05d$",
6078 aopGet (right, offset, FALSE, TRUE),
6085 /* right is a pointer reg need both a & b */
6088 //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
6089 wassertl(!BINUSE, "B was in use");
6090 MOVB (aopGet (left, offset, FALSE, FALSE));
6091 MOVA (aopGet (right, offset, FALSE, FALSE));
6092 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
6098 /*-----------------------------------------------------------------*/
6099 /* gencjne - compare and jump if not equal */
6100 /*-----------------------------------------------------------------*/
6102 gencjne (operand * left, operand * right, symbol * lbl)
6104 symbol *tlbl = newiTempLabel (NULL);
6106 D (emitcode (";", "gencjne"));
6108 gencjneshort (left, right, lbl);
6110 emitcode ("mov", "a,%s", one);
6111 emitcode ("sjmp", "%05d$", tlbl->key + 100);
6113 emitcode ("clr", "a");
6117 /*-----------------------------------------------------------------*/
6118 /* genCmpEq - generates code for equal to */
6119 /*-----------------------------------------------------------------*/
6121 genCmpEq (iCode * ic, iCode * ifx)
6123 bool swappedLR = FALSE;
6124 operand *left, *right, *result;
6126 D (emitcode (";", "genCmpEq"));
6128 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6129 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6130 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6132 /* if literal, literal on the right or
6133 if the right is in a pointer register and left
6135 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6136 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6138 operand *t = IC_RIGHT (ic);
6139 IC_RIGHT (ic) = IC_LEFT (ic);
6144 if (ifx && !AOP_SIZE (result))
6147 /* if they are both bit variables */
6148 if (AOP_TYPE (left) == AOP_CRY &&
6149 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6151 if (AOP_TYPE (right) == AOP_LIT)
6153 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6156 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6157 emitcode ("cpl", "c");
6161 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6165 emitcode ("clr", "c");
6167 /* AOP_TYPE(right) == AOP_CRY */
6171 symbol *lbl = newiTempLabel (NULL);
6172 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6173 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6174 emitcode ("cpl", "c");
6177 /* if true label then we jump if condition
6179 tlbl = newiTempLabel (NULL);
6182 emitcode ("jnc", "%05d$", tlbl->key + 100);
6183 freeForBranchAsmop (result);
6184 freeForBranchAsmop (right);
6185 freeForBranchAsmop (left);
6186 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6190 emitcode ("jc", "%05d$", tlbl->key + 100);
6191 freeForBranchAsmop (result);
6192 freeForBranchAsmop (right);
6193 freeForBranchAsmop (left);
6194 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6200 tlbl = newiTempLabel (NULL);
6201 gencjneshort (left, right, tlbl);
6204 freeForBranchAsmop (result);
6205 freeForBranchAsmop (right);
6206 freeForBranchAsmop (left);
6207 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6212 symbol *lbl = newiTempLabel (NULL);
6213 emitcode ("sjmp", "%05d$", lbl->key + 100);
6215 freeForBranchAsmop (result);
6216 freeForBranchAsmop (right);
6217 freeForBranchAsmop (left);
6218 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6222 /* mark the icode as generated */
6227 /* if they are both bit variables */
6228 if (AOP_TYPE (left) == AOP_CRY &&
6229 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6231 if (AOP_TYPE (right) == AOP_LIT)
6233 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6236 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6237 emitcode ("cpl", "c");
6241 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6245 emitcode ("clr", "c");
6247 /* AOP_TYPE(right) == AOP_CRY */
6251 symbol *lbl = newiTempLabel (NULL);
6252 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6253 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6254 emitcode ("cpl", "c");
6258 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6265 genIfxJump (ifx, "c", left, right, result);
6268 /* if the result is used in an arithmetic operation
6269 then put the result in place */
6274 gencjne (left, right, newiTempLabel (NULL));
6275 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6277 aopPut (result, "a", 0);
6282 genIfxJump (ifx, "a", left, right, result);
6285 /* if the result is used in an arithmetic operation
6286 then put the result in place */
6287 if (AOP_TYPE (result) != AOP_CRY)
6289 /* leave the result in acc */
6293 freeAsmop (result, NULL, ic, TRUE);
6296 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6297 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6301 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6302 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6306 /*-----------------------------------------------------------------*/
6307 /* ifxForOp - returns the icode containing the ifx for operand */
6308 /*-----------------------------------------------------------------*/
6310 ifxForOp (operand * op, iCode * ic)
6312 /* if true symbol then needs to be assigned */
6313 if (IS_TRUE_SYMOP (op))
6316 /* if this has register type condition and
6317 the next instruction is ifx with the same operand
6318 and live to of the operand is upto the ifx only then */
6320 ic->next->op == IFX &&
6321 IC_COND (ic->next)->key == op->key &&
6322 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6328 /*-----------------------------------------------------------------*/
6329 /* hasInc - operand is incremented before any other use */
6330 /*-----------------------------------------------------------------*/
6332 hasInc (operand *op, iCode *ic, int osize)
6334 sym_link *type = operandType(op);
6335 sym_link *retype = getSpec (type);
6336 iCode *lic = ic->next;
6339 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6340 if (!IS_SYMOP(op)) return NULL;
6342 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6343 if (IS_AGGREGATE(type->next)) return NULL;
6344 if (osize != (isize = getSize(type->next))) return NULL;
6347 /* if operand of the form op = op + <sizeof *op> */
6348 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6349 isOperandEqual(IC_RESULT(lic),op) &&
6350 isOperandLiteral(IC_RIGHT(lic)) &&
6351 operandLitValue(IC_RIGHT(lic)) == isize) {
6354 /* if the operand used or deffed */
6355 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6358 /* if GOTO or IFX */
6359 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6365 /*-----------------------------------------------------------------*/
6366 /* genAndOp - for && operation */
6367 /*-----------------------------------------------------------------*/
6369 genAndOp (iCode * ic)
6371 operand *left, *right, *result;
6374 D (emitcode (";", "genAndOp"));
6376 /* note here that && operations that are in an
6377 if statement are taken away by backPatchLabels
6378 only those used in arthmetic operations remain */
6379 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6380 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6381 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6383 /* if both are bit variables */
6384 if (AOP_TYPE (left) == AOP_CRY &&
6385 AOP_TYPE (right) == AOP_CRY)
6387 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6388 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6393 tlbl = newiTempLabel (NULL);
6395 emitcode ("jz", "%05d$", tlbl->key + 100);
6401 freeAsmop (result, NULL, ic, TRUE);
6402 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6403 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6407 /*-----------------------------------------------------------------*/
6408 /* genOrOp - for || operation */
6409 /*-----------------------------------------------------------------*/
6411 genOrOp (iCode * ic)
6413 operand *left, *right, *result;
6416 D (emitcode (";", "genOrOp"));
6418 /* note here that || operations that are in an
6419 if statement are taken away by backPatchLabels
6420 only those used in arthmetic operations remain */
6421 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6422 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6423 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6425 /* if both are bit variables */
6426 if (AOP_TYPE (left) == AOP_CRY &&
6427 AOP_TYPE (right) == AOP_CRY)
6429 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6430 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6435 tlbl = newiTempLabel (NULL);
6437 emitcode ("jnz", "%05d$", tlbl->key + 100);
6443 freeAsmop (result, NULL, ic, TRUE);
6444 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6445 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6448 /*-----------------------------------------------------------------*/
6449 /* isLiteralBit - test if lit == 2^n */
6450 /*-----------------------------------------------------------------*/
6452 isLiteralBit (unsigned long lit)
6454 unsigned long pw[32] =
6455 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6456 0x100L, 0x200L, 0x400L, 0x800L,
6457 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6458 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6459 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6460 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6461 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6464 for (idx = 0; idx < 32; idx++)
6470 /*-----------------------------------------------------------------*/
6471 /* continueIfTrue - */
6472 /*-----------------------------------------------------------------*/
6474 continueIfTrue (iCode * ic)
6477 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6481 /*-----------------------------------------------------------------*/
6483 /*-----------------------------------------------------------------*/
6485 jumpIfTrue (iCode * ic)
6488 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6492 /*-----------------------------------------------------------------*/
6493 /* jmpTrueOrFalse - */
6494 /*-----------------------------------------------------------------*/
6496 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6498 // ugly but optimized by peephole
6501 symbol *nlbl = newiTempLabel (NULL);
6502 emitcode ("sjmp", "%05d$", nlbl->key + 100);
6504 freeForBranchAsmop (result);
6505 freeForBranchAsmop (right);
6506 freeForBranchAsmop (left);
6507 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6512 freeForBranchAsmop (result);
6513 freeForBranchAsmop (right);
6514 freeForBranchAsmop (left);
6515 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6521 /*-----------------------------------------------------------------*/
6522 /* genAnd - code for and */
6523 /*-----------------------------------------------------------------*/
6525 genAnd (iCode * ic, iCode * ifx)
6527 operand *left, *right, *result;
6528 int size, offset = 0;
6529 unsigned long lit = 0L;
6533 D (emitcode (";", "genAnd"));
6535 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6536 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6537 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6540 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6542 AOP_TYPE (left), AOP_TYPE (right));
6543 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6545 AOP_SIZE (left), AOP_SIZE (right));
6548 /* if left is a literal & right is not then exchange them */
6549 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6550 AOP_NEEDSACC (left))
6552 operand *tmp = right;
6557 /* if result = right then exchange left and right */
6558 if (sameRegs (AOP (result), AOP (right)))
6560 operand *tmp = right;
6565 /* if right is bit then exchange them */
6566 if (AOP_TYPE (right) == AOP_CRY &&
6567 AOP_TYPE (left) != AOP_CRY)
6569 operand *tmp = right;
6573 if (AOP_TYPE (right) == AOP_LIT)
6574 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6576 size = AOP_SIZE (result);
6579 // result = bit & yy;
6580 if (AOP_TYPE (left) == AOP_CRY)
6582 // c = bit & literal;
6583 if (AOP_TYPE (right) == AOP_LIT)
6587 if (size && sameRegs (AOP (result), AOP (left)))
6590 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6595 if (size && (AOP_TYPE (result) == AOP_CRY))
6597 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6600 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6605 emitcode ("clr", "c");
6610 if (AOP_TYPE (right) == AOP_CRY)
6613 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6614 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6619 MOVA (aopGet (right, 0, FALSE, FALSE));
6621 emitcode ("rrc", "a");
6622 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6630 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6631 genIfxJump (ifx, "c", left, right, result);
6635 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6636 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6637 if ((AOP_TYPE (right) == AOP_LIT) &&
6638 (AOP_TYPE (result) == AOP_CRY) &&
6639 (AOP_TYPE (left) != AOP_CRY))
6641 int posbit = isLiteralBit (lit);
6646 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6650 switch (posbit & 0x07)
6652 case 0: emitcode ("rrc", "a");
6654 case 7: emitcode ("rlc", "a");
6656 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6665 SNPRINTF (buffer, sizeof(buffer),
6666 "acc.%d", posbit & 0x07);
6667 genIfxJump (ifx, buffer, left, right, result);
6670 {// what is this case? just found it in ds390/gen.c
6671 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6678 symbol *tlbl = newiTempLabel (NULL);
6679 int sizel = AOP_SIZE (left);
6681 emitcode ("setb", "c");
6684 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6686 MOVA (aopGet (left, offset, FALSE, FALSE));
6688 if ((posbit = isLiteralBit (bytelit)) != 0)
6689 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6692 if (bytelit != 0x0FFL)
6693 emitcode ("anl", "a,%s",
6694 aopGet (right, offset, FALSE, TRUE));
6695 emitcode ("jnz", "%05d$", tlbl->key + 100);
6700 // bit = left & literal
6703 emitcode ("clr", "c");
6706 // if(left & literal)
6710 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6720 /* if left is same as result */
6721 if (sameRegs (AOP (result), AOP (left)))
6723 for (; size--; offset++)
6725 if (AOP_TYPE (right) == AOP_LIT)
6727 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6728 if (bytelit == 0x0FF)
6730 /* dummy read of volatile operand */
6731 if (isOperandVolatile (left, FALSE))
6732 MOVA (aopGet (left, offset, FALSE, FALSE));
6736 else if (bytelit == 0)
6738 aopPut (result, zero, offset);
6740 else if (IS_AOP_PREG (result))
6742 MOVA (aopGet (left, offset, FALSE, TRUE));
6743 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6744 aopPut (result, "a", offset);
6747 emitcode ("anl", "%s,%s",
6748 aopGet (left, offset, FALSE, TRUE),
6749 aopGet (right, offset, FALSE, FALSE));
6753 if (AOP_TYPE (left) == AOP_ACC)
6756 emitcode("mov", "a,b");
6757 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6759 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6761 MOVB (aopGet (left, offset, FALSE, FALSE));
6762 MOVA (aopGet (right, offset, FALSE, FALSE));
6763 emitcode ("anl", "a,b");
6764 aopPut (result, "a", offset);
6766 else if (aopGetUsesAcc (left, offset))
6768 MOVA (aopGet (left, offset, FALSE, FALSE));
6769 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6770 aopPut (result, "a", offset);
6774 MOVA (aopGet (right, offset, FALSE, FALSE));
6775 if (IS_AOP_PREG (result))
6777 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6778 aopPut (result, "a", offset);
6781 emitcode ("anl", "%s,a", aopGet (left, offset, FALSE, TRUE));
6788 // left & result in different registers
6789 if (AOP_TYPE (result) == AOP_CRY)
6792 // if(size), result in bit
6793 // if(!size && ifx), conditional oper: if(left & right)
6794 symbol *tlbl = newiTempLabel (NULL);
6795 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6797 emitcode ("setb", "c");
6800 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6801 && AOP_TYPE(left)==AOP_ACC)
6804 emitcode("mov", "a,b");
6805 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6807 else if (AOP_TYPE(left)==AOP_ACC)
6811 bool pushedB = pushB ();
6812 emitcode("mov", "b,a");
6813 MOVA (aopGet (right, offset, FALSE, FALSE));
6814 emitcode("anl", "a,b");
6819 MOVA (aopGet (right, offset, FALSE, FALSE));
6820 emitcode("anl", "a,b");
6823 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6825 MOVB (aopGet (left, offset, FALSE, FALSE));
6826 MOVA (aopGet (right, offset, FALSE, FALSE));
6827 emitcode ("anl", "a,b");
6829 else if (aopGetUsesAcc (left, offset))
6831 MOVA (aopGet (left, offset, FALSE, FALSE));
6832 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6836 MOVA (aopGet (right, offset, FALSE, FALSE));
6837 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6840 emitcode ("jnz", "%05d$", tlbl->key + 100);
6850 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6856 for (; (size--); offset++)
6859 // result = left & right
6860 if (AOP_TYPE (right) == AOP_LIT)
6862 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6863 if (bytelit == 0x0FF)
6866 aopGet (left, offset, FALSE, FALSE),
6870 else if (bytelit == 0)
6872 /* dummy read of volatile operand */
6873 if (isOperandVolatile (left, FALSE))
6874 MOVA (aopGet (left, offset, FALSE, FALSE));
6875 aopPut (result, zero, offset);
6878 else if (AOP_TYPE (left) == AOP_ACC)
6882 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6883 aopPut (result, "a", offset);
6888 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6889 aopPut (result, "b", offset);
6894 // faster than result <- left, anl result,right
6895 // and better if result is SFR
6896 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6897 && AOP_TYPE(left)==AOP_ACC)
6900 emitcode("mov", "a,b");
6901 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6903 else if (AOP_TYPE(left)==AOP_ACC)
6907 bool pushedB = pushB ();
6908 emitcode("mov", "b,a");
6909 MOVA (aopGet (right, offset, FALSE, FALSE));
6910 emitcode("anl", "a,b");
6915 MOVA (aopGet (right, offset, FALSE, FALSE));
6916 emitcode("anl", "a,b");
6919 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6921 MOVB (aopGet (left, offset, FALSE, FALSE));
6922 MOVA (aopGet (right, offset, FALSE, FALSE));
6923 emitcode ("anl", "a,b");
6925 else if (aopGetUsesAcc (left, offset))
6927 MOVA (aopGet (left, offset, FALSE, FALSE));
6928 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6932 MOVA (aopGet (right, offset, FALSE, FALSE));
6933 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6935 aopPut (result, "a", offset);
6941 freeAsmop (result, NULL, ic, TRUE);
6942 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6943 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6946 /*-----------------------------------------------------------------*/
6947 /* genOr - code for or */
6948 /*-----------------------------------------------------------------*/
6950 genOr (iCode * ic, iCode * ifx)
6952 operand *left, *right, *result;
6953 int size, offset = 0;
6954 unsigned long lit = 0L;
6957 D (emitcode (";", "genOr"));
6959 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6960 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6961 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6964 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6966 AOP_TYPE (left), AOP_TYPE (right));
6967 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6969 AOP_SIZE (left), AOP_SIZE (right));
6972 /* if left is a literal & right is not then exchange them */
6973 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6974 AOP_NEEDSACC (left))
6976 operand *tmp = right;
6981 /* if result = right then exchange them */
6982 if (sameRegs (AOP (result), AOP (right)))
6984 operand *tmp = right;
6989 /* if right is bit then exchange them */
6990 if (AOP_TYPE (right) == AOP_CRY &&
6991 AOP_TYPE (left) != AOP_CRY)
6993 operand *tmp = right;
6997 if (AOP_TYPE (right) == AOP_LIT)
6998 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7000 size = AOP_SIZE (result);
7004 if (AOP_TYPE (left) == AOP_CRY)
7006 if (AOP_TYPE (right) == AOP_LIT)
7008 // c = bit | literal;
7011 // lit != 0 => result = 1
7012 if (AOP_TYPE (result) == AOP_CRY)
7015 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7017 continueIfTrue (ifx);
7020 emitcode ("setb", "c");
7024 // lit == 0 => result = left
7025 if (size && sameRegs (AOP (result), AOP (left)))
7027 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7032 if (AOP_TYPE (right) == AOP_CRY)
7035 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7036 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7041 symbol *tlbl = newiTempLabel (NULL);
7042 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
7043 emitcode ("setb", "c");
7044 emitcode ("jb", "%s,%05d$",
7045 AOP (left)->aopu.aop_dir, tlbl->key + 100);
7047 emitcode ("jnz", "%05d$", tlbl->key + 100);
7048 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7050 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7065 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7066 genIfxJump (ifx, "c", left, right, result);
7070 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7071 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7072 if ((AOP_TYPE (right) == AOP_LIT) &&
7073 (AOP_TYPE (result) == AOP_CRY) &&
7074 (AOP_TYPE (left) != AOP_CRY))
7080 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7082 continueIfTrue (ifx);
7087 // lit = 0, result = boolean(left)
7089 emitcode ("setb", "c");
7093 symbol *tlbl = newiTempLabel (NULL);
7094 emitcode ("jnz", "%05d$", tlbl->key + 100);
7100 genIfxJump (ifx, "a", left, right, result);
7108 /* if left is same as result */
7109 if (sameRegs (AOP (result), AOP (left)))
7111 for (; size--; offset++)
7113 if (AOP_TYPE (right) == AOP_LIT)
7115 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7118 /* dummy read of volatile operand */
7119 if (isOperandVolatile (left, FALSE))
7120 MOVA (aopGet (left, offset, FALSE, FALSE));
7124 else if (bytelit == 0x0FF)
7126 aopPut (result, "#0xFF", offset);
7128 else if (IS_AOP_PREG (left))
7130 MOVA (aopGet (left, offset, FALSE, TRUE));
7131 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7132 aopPut (result, "a", offset);
7136 emitcode ("orl", "%s,%s",
7137 aopGet (left, offset, FALSE, TRUE),
7138 aopGet (right, offset, FALSE, FALSE));
7143 if (AOP_TYPE (left) == AOP_ACC)
7146 emitcode("mov", "a,b");
7147 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7149 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7151 MOVB (aopGet (left, offset, FALSE, FALSE));
7152 MOVA (aopGet (right, offset, FALSE, FALSE));
7153 emitcode ("orl", "a,b");
7154 aopPut (result, "a", offset);
7156 else if (aopGetUsesAcc (left, offset))
7158 MOVA (aopGet (left, offset, FALSE, FALSE));
7159 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7160 aopPut (result, "a", offset);
7164 MOVA (aopGet (right, offset, FALSE, FALSE));
7165 if (IS_AOP_PREG (left))
7167 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7168 aopPut (result, "a", offset);
7172 emitcode ("orl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7180 // left & result in different registers
7181 if (AOP_TYPE (result) == AOP_CRY)
7184 // if(size), result in bit
7185 // if(!size && ifx), conditional oper: if(left | right)
7186 symbol *tlbl = newiTempLabel (NULL);
7187 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7189 emitcode ("setb", "c");
7192 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7193 && AOP_TYPE(left)==AOP_ACC)
7196 emitcode("mov", "a,b");
7197 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7199 else if (AOP_TYPE(left)==AOP_ACC)
7203 bool pushedB = pushB ();
7204 emitcode("mov", "b,a");
7205 MOVA (aopGet (right, offset, FALSE, FALSE));
7206 emitcode("orl", "a,b");
7211 MOVA (aopGet (right, offset, FALSE, FALSE));
7212 emitcode("orl", "a,b");
7215 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7217 MOVB (aopGet (left, offset, FALSE, FALSE));
7218 MOVA (aopGet (right, offset, FALSE, FALSE));
7219 emitcode ("orl", "a,b");
7221 else if (aopGetUsesAcc (left, offset))
7223 MOVA (aopGet (left, offset, FALSE, FALSE));
7224 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7228 MOVA (aopGet (right, offset, FALSE, FALSE));
7229 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7232 emitcode ("jnz", "%05d$", tlbl->key + 100);
7242 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7248 for (; (size--); offset++)
7251 // result = left | right
7252 if (AOP_TYPE (right) == AOP_LIT)
7254 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7258 aopGet (left, offset, FALSE, FALSE),
7262 else if (bytelit == 0x0FF)
7264 /* dummy read of volatile operand */
7265 if (isOperandVolatile (left, FALSE))
7266 MOVA (aopGet (left, offset, FALSE, FALSE));
7267 aopPut (result, "#0xFF", offset);
7271 // faster than result <- left, orl result,right
7272 // and better if result is SFR
7273 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7274 && AOP_TYPE(left)==AOP_ACC)
7277 emitcode("mov", "a,b");
7278 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7280 else if (AOP_TYPE(left)==AOP_ACC)
7284 bool pushedB = pushB ();
7285 emitcode("mov", "b,a");
7286 MOVA (aopGet (right, offset, FALSE, FALSE));
7287 emitcode("orl", "a,b");
7292 MOVA (aopGet (right, offset, FALSE, FALSE));
7293 emitcode("orl", "a,b");
7296 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7298 MOVB (aopGet (left, offset, FALSE, FALSE));
7299 MOVA (aopGet (right, offset, FALSE, FALSE));
7300 emitcode ("orl", "a,b");
7302 else if (aopGetUsesAcc (left, offset))
7304 MOVA (aopGet (left, offset, FALSE, FALSE));
7305 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7309 MOVA (aopGet (right, offset, FALSE, FALSE));
7310 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7312 aopPut (result, "a", offset);
7318 freeAsmop (result, NULL, ic, TRUE);
7319 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7320 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7323 /*-----------------------------------------------------------------*/
7324 /* genXor - code for xclusive or */
7325 /*-----------------------------------------------------------------*/
7327 genXor (iCode * ic, iCode * ifx)
7329 operand *left, *right, *result;
7330 int size, offset = 0;
7331 unsigned long lit = 0L;
7334 D (emitcode (";", "genXor"));
7336 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7337 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7338 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7341 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7343 AOP_TYPE (left), AOP_TYPE (right));
7344 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7346 AOP_SIZE (left), AOP_SIZE (right));
7349 /* if left is a literal & right is not ||
7350 if left needs acc & right does not */
7351 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7352 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7354 operand *tmp = right;
7359 /* if result = right then exchange them */
7360 if (sameRegs (AOP (result), AOP (right)))
7362 operand *tmp = right;
7367 /* if right is bit then exchange them */
7368 if (AOP_TYPE (right) == AOP_CRY &&
7369 AOP_TYPE (left) != AOP_CRY)
7371 operand *tmp = right;
7375 if (AOP_TYPE (right) == AOP_LIT)
7376 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7378 size = AOP_SIZE (result);
7382 if (AOP_TYPE (left) == AOP_CRY)
7384 if (AOP_TYPE (right) == AOP_LIT)
7386 // c = bit & literal;
7389 // lit>>1 != 0 => result = 1
7390 if (AOP_TYPE (result) == AOP_CRY)
7393 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7395 continueIfTrue (ifx);
7398 emitcode ("setb", "c");
7405 // lit == 0, result = left
7406 if (size && sameRegs (AOP (result), AOP (left)))
7408 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7412 // lit == 1, result = not(left)
7413 if (size && sameRegs (AOP (result), AOP (left)))
7415 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7420 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7421 emitcode ("cpl", "c");
7429 symbol *tlbl = newiTempLabel (NULL);
7430 if (AOP_TYPE (right) == AOP_CRY)
7433 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7437 int sizer = AOP_SIZE (right);
7439 // if val>>1 != 0, result = 1
7440 emitcode ("setb", "c");
7443 MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
7445 // test the msb of the lsb
7446 emitcode ("anl", "a,#0xfe");
7447 emitcode ("jnz", "%05d$", tlbl->key + 100);
7451 emitcode ("rrc", "a");
7453 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7454 emitcode ("cpl", "c");
7462 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7463 genIfxJump (ifx, "c", left, right, result);
7467 /* if left is same as result */
7468 if (sameRegs (AOP (result), AOP (left)))
7470 for (; size--; offset++)
7472 if (AOP_TYPE (right) == AOP_LIT)
7474 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7477 /* dummy read of volatile operand */
7478 if (isOperandVolatile (left, FALSE))
7479 MOVA (aopGet (left, offset, FALSE, FALSE));
7483 else if (IS_AOP_PREG (left))
7485 MOVA (aopGet (left, offset, FALSE, TRUE));
7486 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7487 aopPut (result, "a", offset);
7491 emitcode ("xrl", "%s,%s",
7492 aopGet (left, offset, FALSE, TRUE),
7493 aopGet (right, offset, FALSE, FALSE));
7498 if (AOP_TYPE (left) == AOP_ACC)
7501 emitcode("mov", "a,b");
7502 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7504 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7506 MOVB (aopGet (left, offset, FALSE, FALSE));
7507 MOVA (aopGet (right, offset, FALSE, FALSE));
7508 emitcode ("xrl", "a,b");
7509 aopPut (result, "a", offset);
7511 else if (aopGetUsesAcc (left, offset))
7513 MOVA (aopGet (left, offset, FALSE, FALSE));
7514 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7515 aopPut (result, "a", offset);
7519 MOVA (aopGet (right, offset, FALSE, FALSE));
7520 if (IS_AOP_PREG (left))
7522 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7523 aopPut (result, "a", offset);
7526 emitcode ("xrl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7533 // left & result in different registers
7534 if (AOP_TYPE (result) == AOP_CRY)
7537 // if(size), result in bit
7538 // if(!size && ifx), conditional oper: if(left ^ right)
7539 symbol *tlbl = newiTempLabel (NULL);
7540 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7543 emitcode ("setb", "c");
7546 if ((AOP_TYPE (right) == AOP_LIT) &&
7547 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7549 MOVA (aopGet (left, offset, FALSE, FALSE));
7551 else if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7552 && AOP_TYPE(left)==AOP_ACC)
7555 emitcode("mov", "a,b");
7556 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7558 else if (AOP_TYPE(left)==AOP_ACC)
7562 bool pushedB = pushB ();
7563 emitcode("mov", "b,a");
7564 MOVA (aopGet (right, offset, FALSE, FALSE));
7565 emitcode("xrl", "a,b");
7570 MOVA (aopGet (right, offset, FALSE, FALSE));
7571 emitcode("xrl", "a,b");
7574 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7576 MOVB (aopGet (left, offset, FALSE, FALSE));
7577 MOVA (aopGet (right, offset, FALSE, FALSE));
7578 emitcode ("xrl", "a,b");
7580 else if (aopGetUsesAcc (left, offset))
7582 MOVA (aopGet (left, offset, FALSE, FALSE));
7583 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7587 MOVA (aopGet (right, offset, FALSE, FALSE));
7588 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7591 emitcode ("jnz", "%05d$", tlbl->key + 100);
7601 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7605 for (; (size--); offset++)
7608 // result = left ^ right
7609 if (AOP_TYPE (right) == AOP_LIT)
7611 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7615 aopGet (left, offset, FALSE, FALSE),
7620 // faster than result <- left, xrl result,right
7621 // and better if result is SFR
7622 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7623 && AOP_TYPE(left)==AOP_ACC)
7626 emitcode("mov", "a,b");
7627 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7629 else if (AOP_TYPE(left)==AOP_ACC)
7633 bool pushedB = pushB ();
7634 emitcode("mov", "b,a");
7635 MOVA (aopGet (right, offset, FALSE, FALSE));
7636 emitcode("xrl", "a,b");
7641 MOVA (aopGet (right, offset, FALSE, FALSE));
7642 emitcode("xrl", "a,b");
7645 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7647 MOVB (aopGet (left, offset, FALSE, FALSE));
7648 MOVA (aopGet (right, offset, FALSE, FALSE));
7649 emitcode ("xrl", "a,b");
7651 else if (aopGetUsesAcc (left, offset))
7653 MOVA (aopGet (left, offset, FALSE, FALSE));
7654 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7658 MOVA (aopGet (right, offset, FALSE, FALSE));
7659 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7661 aopPut (result, "a", offset);
7667 freeAsmop (result, NULL, ic, TRUE);
7668 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7669 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7672 /*-----------------------------------------------------------------*/
7673 /* genInline - write the inline code out */
7674 /*-----------------------------------------------------------------*/
7676 genInline (iCode * ic)
7678 char *buffer, *bp, *bp1;
7680 D (emitcode (";", "genInline"));
7682 _G.inLine += (!options.asmpeep);
7684 buffer = bp = bp1 = Safe_strdup(IC_INLINE(ic));
7686 /* emit each line as a code */
7697 /* Add \n for labels, not dirs such as c:\mydir */
7698 if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
7712 /* emitcode("",buffer); */
7713 _G.inLine -= (!options.asmpeep);
7716 /*-----------------------------------------------------------------*/
7717 /* genRRC - rotate right with carry */
7718 /*-----------------------------------------------------------------*/
7722 operand *left, *result;
7726 D (emitcode (";", "genRRC"));
7728 /* rotate right with carry */
7729 left = IC_LEFT (ic);
7730 result = IC_RESULT (ic);
7731 aopOp (left, ic, FALSE);
7732 aopOp (result, ic, FALSE);
7734 /* move it to the result */
7735 size = AOP_SIZE (result);
7737 if (size == 1) { /* special case for 1 byte */
7738 l = aopGet (left, offset, FALSE, FALSE);
7740 emitcode ("rr", "a");
7743 /* no need to clear carry, bit7 will be written later */
7746 l = aopGet (left, offset, FALSE, FALSE);
7748 emitcode ("rrc", "a");
7749 if (AOP_SIZE (result) > 1)
7750 aopPut (result, "a", offset--);
7752 /* now we need to put the carry into the
7753 highest order byte of the result */
7754 if (AOP_SIZE (result) > 1)
7756 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7759 emitcode ("mov", "acc.7,c");
7761 aopPut (result, "a", AOP_SIZE (result) - 1);
7762 freeAsmop (result, NULL, ic, TRUE);
7763 freeAsmop (left, NULL, ic, TRUE);
7766 /*-----------------------------------------------------------------*/
7767 /* genRLC - generate code for rotate left with carry */
7768 /*-----------------------------------------------------------------*/
7772 operand *left, *result;
7776 D (emitcode (";", "genRLC"));
7778 /* rotate right with carry */
7779 left = IC_LEFT (ic);
7780 result = IC_RESULT (ic);
7781 aopOp (left, ic, FALSE);
7782 aopOp (result, ic, FALSE);
7784 /* move it to the result */
7785 size = AOP_SIZE (result);
7789 l = aopGet (left, offset, FALSE, FALSE);
7791 if (size == 0) { /* special case for 1 byte */
7795 emitcode("rlc","a"); /* bit0 will be written later */
7796 if (AOP_SIZE (result) > 1)
7798 aopPut (result, "a", offset++);
7803 l = aopGet (left, offset, FALSE, FALSE);
7805 emitcode ("rlc", "a");
7806 if (AOP_SIZE (result) > 1)
7807 aopPut (result, "a", offset++);
7810 /* now we need to put the carry into the
7811 highest order byte of the result */
7812 if (AOP_SIZE (result) > 1)
7814 l = aopGet (result, 0, FALSE, FALSE);
7817 emitcode ("mov", "acc.0,c");
7819 aopPut (result, "a", 0);
7820 freeAsmop (result, NULL, ic, TRUE);
7821 freeAsmop (left, NULL, ic, TRUE);
7824 /*-----------------------------------------------------------------*/
7825 /* genGetHbit - generates code get highest order bit */
7826 /*-----------------------------------------------------------------*/
7828 genGetHbit (iCode * ic)
7830 operand *left, *result;
7832 D (emitcode (";", "genGetHbit"));
7834 left = IC_LEFT (ic);
7835 result = IC_RESULT (ic);
7836 aopOp (left, ic, FALSE);
7837 aopOp (result, ic, FALSE);
7839 /* get the highest order byte into a */
7840 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7841 if (AOP_TYPE (result) == AOP_CRY)
7843 emitcode ("rlc", "a");
7848 emitcode ("rl", "a");
7849 emitcode ("anl", "a,#0x01");
7853 freeAsmop (result, NULL, ic, TRUE);
7854 freeAsmop (left, NULL, ic, TRUE);
7857 /*-----------------------------------------------------------------*/
7858 /* genGetAbit - generates code get a single bit */
7859 /*-----------------------------------------------------------------*/
7861 genGetAbit (iCode * ic)
7863 operand *left, *right, *result;
7866 D (emitcode (";", "genGetAbit"));
7868 left = IC_LEFT (ic);
7869 right = IC_RIGHT (ic);
7870 result = IC_RESULT (ic);
7871 aopOp (left, ic, FALSE);
7872 aopOp (right, ic, FALSE);
7873 aopOp (result, ic, FALSE);
7875 shCount = (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7877 /* get the needed byte into a */
7878 MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7880 if (AOP_TYPE (result) == AOP_CRY)
7883 emitcode ("rlc", "a");
7884 else if ((shCount) == 0)
7885 emitcode ("rrc", "a");
7887 emitcode ("mov", "c,acc[%d]", shCount);
7895 emitcode ("rr", "a");
7898 emitcode ("rr", "a");
7901 emitcode ("anl", "a,#0x01");
7905 emitcode ("mov", "c,acc[%d]", shCount);
7906 emitcode ("clr", "a");
7907 emitcode ("rlc", "a");
7910 emitcode ("swap", "a");
7911 emitcode ("anl", "a,#0x01");
7914 emitcode ("rl", "a");
7917 emitcode ("rl", "a");
7918 emitcode ("anl", "a,#0x01");
7924 freeAsmop (result, NULL, ic, TRUE);
7925 freeAsmop (right, NULL, ic, TRUE);
7926 freeAsmop (left, NULL, ic, TRUE);
7929 /*-----------------------------------------------------------------*/
7930 /* genGetByte - generates code get a single byte */
7931 /*-----------------------------------------------------------------*/
7933 genGetByte (iCode * ic)
7935 operand *left, *right, *result;
7938 D (emitcode (";", "genGetByte"));
7940 left = IC_LEFT (ic);
7941 right = IC_RIGHT (ic);
7942 result = IC_RESULT (ic);
7943 aopOp (left, ic, FALSE);
7944 aopOp (right, ic, FALSE);
7945 aopOp (result, ic, FALSE);
7947 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7949 aopGet (left, offset, FALSE, FALSE),
7952 freeAsmop (result, NULL, ic, TRUE);
7953 freeAsmop (right, NULL, ic, TRUE);
7954 freeAsmop (left, NULL, ic, TRUE);
7957 /*-----------------------------------------------------------------*/
7958 /* genGetWord - generates code get two bytes */
7959 /*-----------------------------------------------------------------*/
7961 genGetWord (iCode * ic)
7963 operand *left, *right, *result;
7966 D (emitcode (";", "genGetWord"));
7968 left = IC_LEFT (ic);
7969 right = IC_RIGHT (ic);
7970 result = IC_RESULT (ic);
7971 aopOp (left, ic, FALSE);
7972 aopOp (right, ic, FALSE);
7973 aopOp (result, ic, FALSE);
7975 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7977 aopGet (left, offset, FALSE, FALSE),
7980 aopGet (left, offset+1, FALSE, FALSE),
7983 freeAsmop (result, NULL, ic, TRUE);
7984 freeAsmop (right, NULL, ic, TRUE);
7985 freeAsmop (left, NULL, ic, TRUE);
7988 /*-----------------------------------------------------------------*/
7989 /* genSwap - generates code to swap nibbles or bytes */
7990 /*-----------------------------------------------------------------*/
7992 genSwap (iCode * ic)
7994 operand *left, *result;
7996 D(emitcode ("; genSwap",""));
7998 left = IC_LEFT (ic);
7999 result = IC_RESULT (ic);
8000 aopOp (left, ic, FALSE);
8001 aopOp (result, ic, FALSE);
8003 switch (AOP_SIZE (left))
8005 case 1: /* swap nibbles in byte */
8006 MOVA (aopGet (left, 0, FALSE, FALSE));
8007 emitcode ("swap", "a");
8008 aopPut (result, "a", 0);
8010 case 2: /* swap bytes in word */
8011 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
8013 MOVA (aopGet (left, 0, FALSE, FALSE));
8014 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8015 aopPut (result, "a", 1);
8017 else if (operandsEqu (left, result))
8020 bool pushedB = FALSE, leftInB = FALSE;
8022 MOVA (aopGet (left, 0, FALSE, FALSE));
8023 if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
8026 emitcode ("mov", "b,a");
8030 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8031 aopPut (result, reg, 1);
8038 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8039 aopPut (result, aopGet (left, 0, FALSE, FALSE), 1);
8043 wassertl(FALSE, "unsupported SWAP operand size");
8046 freeAsmop (result, NULL, ic, TRUE);
8047 freeAsmop (left, NULL, ic, TRUE);
8050 /*-----------------------------------------------------------------*/
8051 /* AccRol - rotate left accumulator by known count */
8052 /*-----------------------------------------------------------------*/
8054 AccRol (int shCount)
8056 shCount &= 0x0007; // shCount : 0..7
8063 emitcode ("rl", "a");
8066 emitcode ("rl", "a");
8067 emitcode ("rl", "a");
8070 emitcode ("swap", "a");
8071 emitcode ("rr", "a");
8074 emitcode ("swap", "a");
8077 emitcode ("swap", "a");
8078 emitcode ("rl", "a");
8081 emitcode ("rr", "a");
8082 emitcode ("rr", "a");
8085 emitcode ("rr", "a");
8090 /*-----------------------------------------------------------------*/
8091 /* AccLsh - left shift accumulator by known count */
8092 /*-----------------------------------------------------------------*/
8094 AccLsh (int shCount)
8099 emitcode ("add", "a,acc");
8100 else if (shCount == 2)
8102 emitcode ("add", "a,acc");
8103 emitcode ("add", "a,acc");
8107 /* rotate left accumulator */
8109 /* and kill the lower order bits */
8110 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
8115 /*-----------------------------------------------------------------*/
8116 /* AccRsh - right shift accumulator by known count */
8117 /*-----------------------------------------------------------------*/
8119 AccRsh (int shCount)
8126 emitcode ("rrc", "a");
8130 /* rotate right accumulator */
8131 AccRol (8 - shCount);
8132 /* and kill the higher order bits */
8133 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8138 /*-----------------------------------------------------------------*/
8139 /* AccSRsh - signed right shift accumulator by known count */
8140 /*-----------------------------------------------------------------*/
8142 AccSRsh (int shCount)
8149 emitcode ("mov", "c,acc.7");
8150 emitcode ("rrc", "a");
8152 else if (shCount == 2)
8154 emitcode ("mov", "c,acc.7");
8155 emitcode ("rrc", "a");
8156 emitcode ("mov", "c,acc.7");
8157 emitcode ("rrc", "a");
8161 tlbl = newiTempLabel (NULL);
8162 /* rotate right accumulator */
8163 AccRol (8 - shCount);
8164 /* and kill the higher order bits */
8165 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8166 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8167 emitcode ("orl", "a,#0x%02x",
8168 (unsigned char) ~SRMask[shCount]);
8174 /*-----------------------------------------------------------------*/
8175 /* shiftR1Left2Result - shift right one byte from left to result */
8176 /*-----------------------------------------------------------------*/
8178 shiftR1Left2Result (operand * left, int offl,
8179 operand * result, int offr,
8180 int shCount, int sign)
8182 MOVA (aopGet (left, offl, FALSE, FALSE));
8183 /* shift right accumulator */
8188 aopPut (result, "a", offr);
8191 /*-----------------------------------------------------------------*/
8192 /* shiftL1Left2Result - shift left one byte from left to result */
8193 /*-----------------------------------------------------------------*/
8195 shiftL1Left2Result (operand * left, int offl,
8196 operand * result, int offr, int shCount)
8199 l = aopGet (left, offl, FALSE, FALSE);
8201 /* shift left accumulator */
8203 aopPut (result, "a", offr);
8206 /*-----------------------------------------------------------------*/
8207 /* movLeft2Result - move byte from left to result */
8208 /*-----------------------------------------------------------------*/
8210 movLeft2Result (operand * left, int offl,
8211 operand * result, int offr, int sign)
8214 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8216 l = aopGet (left, offl, FALSE, FALSE);
8218 if (*l == '@' && (IS_AOP_PREG (result)))
8220 emitcode ("mov", "a,%s", l);
8221 aopPut (result, "a", offr);
8227 aopPut (result, l, offr);
8231 /* MSB sign in acc.7 ! */
8232 if (getDataSize (left) == offl + 1)
8235 aopPut (result, "a", offr);
8242 /*-----------------------------------------------------------------*/
8243 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
8244 /*-----------------------------------------------------------------*/
8248 emitcode ("rrc", "a");
8249 emitcode ("xch", "a,%s", x);
8250 emitcode ("rrc", "a");
8251 emitcode ("xch", "a,%s", x);
8254 /*-----------------------------------------------------------------*/
8255 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
8256 /*-----------------------------------------------------------------*/
8260 emitcode ("xch", "a,%s", x);
8261 emitcode ("rlc", "a");
8262 emitcode ("xch", "a,%s", x);
8263 emitcode ("rlc", "a");
8266 /*-----------------------------------------------------------------*/
8267 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8268 /*-----------------------------------------------------------------*/
8272 emitcode ("xch", "a,%s", x);
8273 emitcode ("add", "a,acc");
8274 emitcode ("xch", "a,%s", x);
8275 emitcode ("rlc", "a");
8278 /*-----------------------------------------------------------------*/
8279 /* AccAXLsh - left shift a:x by known count (0..7) */
8280 /*-----------------------------------------------------------------*/
8282 AccAXLsh (char *x, int shCount)
8297 case 5: // AAAAABBB:CCCCCDDD
8299 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8301 emitcode ("anl", "a,#0x%02x",
8302 SLMask[shCount]); // BBB00000:CCCCCDDD
8304 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8306 AccRol (shCount); // DDDCCCCC:BBB00000
8308 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8310 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8312 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8314 emitcode ("anl", "a,#0x%02x",
8315 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8317 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8319 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8322 case 6: // AAAAAABB:CCCCCCDD
8323 emitcode ("anl", "a,#0x%02x",
8324 SRMask[shCount]); // 000000BB:CCCCCCDD
8325 emitcode ("mov", "c,acc.0"); // c = B
8326 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8328 AccAXRrl1 (x); // BCCCCCCD:D000000B
8329 AccAXRrl1 (x); // BBCCCCCC:DD000000
8331 emitcode("rrc","a");
8332 emitcode("xch","a,%s", x);
8333 emitcode("rrc","a");
8334 emitcode("mov","c,acc.0"); //<< get correct bit
8335 emitcode("xch","a,%s", x);
8337 emitcode("rrc","a");
8338 emitcode("xch","a,%s", x);
8339 emitcode("rrc","a");
8340 emitcode("xch","a,%s", x);
8343 case 7: // a:x <<= 7
8345 emitcode ("anl", "a,#0x%02x",
8346 SRMask[shCount]); // 0000000B:CCCCCCCD
8348 emitcode ("mov", "c,acc.0"); // c = B
8350 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
8352 AccAXRrl1 (x); // BCCCCCCC:D0000000
8360 /*-----------------------------------------------------------------*/
8361 /* AccAXRsh - right shift a:x known count (0..7) */
8362 /*-----------------------------------------------------------------*/
8364 AccAXRsh (char *x, int shCount)
8372 AccAXRrl1 (x); // 0->a:x
8377 AccAXRrl1 (x); // 0->a:x
8380 AccAXRrl1 (x); // 0->a:x
8385 case 5: // AAAAABBB:CCCCCDDD = a:x
8387 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8389 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8391 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8393 emitcode ("anl", "a,#0x%02x",
8394 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8396 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8398 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8400 emitcode ("anl", "a,#0x%02x",
8401 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8403 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8405 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8407 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8410 case 6: // AABBBBBB:CCDDDDDD
8412 emitcode ("mov", "c,acc.7");
8413 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8415 emitcode ("mov", "c,acc.7");
8416 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8418 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8420 emitcode ("anl", "a,#0x%02x",
8421 SRMask[shCount]); // 000000AA:BBBBBBCC
8424 case 7: // ABBBBBBB:CDDDDDDD
8426 emitcode ("mov", "c,acc.7"); // c = A
8428 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8430 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8432 emitcode ("anl", "a,#0x%02x",
8433 SRMask[shCount]); // 0000000A:BBBBBBBC
8441 /*-----------------------------------------------------------------*/
8442 /* AccAXRshS - right shift signed a:x known count (0..7) */
8443 /*-----------------------------------------------------------------*/
8445 AccAXRshS (char *x, int shCount)
8453 emitcode ("mov", "c,acc.7");
8454 AccAXRrl1 (x); // s->a:x
8458 emitcode ("mov", "c,acc.7");
8459 AccAXRrl1 (x); // s->a:x
8461 emitcode ("mov", "c,acc.7");
8462 AccAXRrl1 (x); // s->a:x
8467 case 5: // AAAAABBB:CCCCCDDD = a:x
8469 tlbl = newiTempLabel (NULL);
8470 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8472 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8474 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8476 emitcode ("anl", "a,#0x%02x",
8477 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8479 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8481 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8483 emitcode ("anl", "a,#0x%02x",
8484 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8486 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8488 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8490 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8492 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8493 emitcode ("orl", "a,#0x%02x",
8494 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8497 break; // SSSSAAAA:BBBCCCCC
8499 case 6: // AABBBBBB:CCDDDDDD
8501 tlbl = newiTempLabel (NULL);
8502 emitcode ("mov", "c,acc.7");
8503 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8505 emitcode ("mov", "c,acc.7");
8506 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8508 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8510 emitcode ("anl", "a,#0x%02x",
8511 SRMask[shCount]); // 000000AA:BBBBBBCC
8513 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8514 emitcode ("orl", "a,#0x%02x",
8515 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8519 case 7: // ABBBBBBB:CDDDDDDD
8521 tlbl = newiTempLabel (NULL);
8522 emitcode ("mov", "c,acc.7"); // c = A
8524 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8526 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8528 emitcode ("anl", "a,#0x%02x",
8529 SRMask[shCount]); // 0000000A:BBBBBBBC
8531 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8532 emitcode ("orl", "a,#0x%02x",
8533 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8542 /*-----------------------------------------------------------------*/
8543 /* shiftL2Left2Result - shift left two bytes from left to result */
8544 /*-----------------------------------------------------------------*/
8546 shiftL2Left2Result (operand * left, int offl,
8547 operand * result, int offr, int shCount)
8550 bool pushedB = FALSE;
8553 if (sameRegs (AOP (result), AOP (left)) &&
8554 ((offl + MSB16) == offr))
8556 /* don't crash result[offr] */
8557 MOVA (aopGet (left, offl, FALSE, FALSE));
8558 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8559 usedB = !strncmp(x, "b", 1);
8561 else if (aopGetUsesAcc (result, offr))
8563 movLeft2Result (left, offl, result, offr, 0);
8566 emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8567 MOVA (aopGet (result, offr, FALSE, FALSE));
8568 emitcode ("xch", "a,b");
8573 movLeft2Result (left, offl, result, offr, 0);
8574 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8575 x = aopGet (result, offr, FALSE, FALSE);
8577 /* ax << shCount (x = lsb(result)) */
8578 AccAXLsh (x, shCount);
8581 emitcode ("xch", "a,b");
8582 aopPut (result, "a", offr);
8583 aopPut (result, "b", offr + MSB16);
8588 aopPut (result, "a", offr + MSB16);
8593 /*-----------------------------------------------------------------*/
8594 /* shiftR2Left2Result - shift right two bytes from left to result */
8595 /*-----------------------------------------------------------------*/
8597 shiftR2Left2Result (operand * left, int offl,
8598 operand * result, int offr,
8599 int shCount, int sign)
8602 bool pushedB = FALSE;
8605 if (sameRegs (AOP (result), AOP (left)) &&
8606 ((offl + MSB16) == offr))
8608 /* don't crash result[offr] */
8609 MOVA (aopGet (left, offl, FALSE, FALSE));
8610 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8611 usedB = !strncmp(x, "b", 1);
8613 else if (aopGetUsesAcc (result, offr))
8615 movLeft2Result (left, offl, result, offr, 0);
8618 emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8619 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8624 movLeft2Result (left, offl, result, offr, 0);
8625 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8626 x = aopGet (result, offr, FALSE, FALSE);
8628 /* a:x >> shCount (x = lsb(result)) */
8630 AccAXRshS (x, shCount);
8632 AccAXRsh (x, shCount);
8635 emitcode ("xch", "a,b");
8636 aopPut (result, "a", offr);
8637 emitcode ("xch", "a,b");
8640 if (getDataSize (result) > 1)
8641 aopPut (result, "a", offr + MSB16);
8644 /*-----------------------------------------------------------------*/
8645 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8646 /*-----------------------------------------------------------------*/
8648 shiftLLeftOrResult (operand * left, int offl,
8649 operand * result, int offr, int shCount)
8651 MOVA (aopGet (left, offl, FALSE, FALSE));
8652 /* shift left accumulator */
8654 /* or with result */
8655 if (aopGetUsesAcc (result, offr))
8657 emitcode ("xch", "a,b");
8658 MOVA (aopGet (result, offr, FALSE, FALSE));
8659 emitcode ("orl", "a,b");
8663 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8665 /* back to result */
8666 aopPut (result, "a", offr);
8669 /*-----------------------------------------------------------------*/
8670 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8671 /*-----------------------------------------------------------------*/
8673 shiftRLeftOrResult (operand * left, int offl,
8674 operand * result, int offr, int shCount)
8676 MOVA (aopGet (left, offl, FALSE, FALSE));
8677 /* shift right accumulator */
8679 /* or with result */
8680 if (aopGetUsesAcc(result, offr))
8682 emitcode ("xch", "a,b");
8683 MOVA (aopGet (result, offr, FALSE, FALSE));
8684 emitcode ("orl", "a,b");
8688 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8690 /* back to result */
8691 aopPut (result, "a", offr);
8694 /*-----------------------------------------------------------------*/
8695 /* genlshOne - left shift a one byte quantity by known count */
8696 /*-----------------------------------------------------------------*/
8698 genlshOne (operand * result, operand * left, int shCount)
8700 D (emitcode (";", "genlshOne"));
8702 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8705 /*-----------------------------------------------------------------*/
8706 /* genlshTwo - left shift two bytes by known amount != 0 */
8707 /*-----------------------------------------------------------------*/
8709 genlshTwo (operand * result, operand * left, int shCount)
8713 D (emitcode (";", "genlshTwo"));
8715 size = getDataSize (result);
8717 /* if shCount >= 8 */
8725 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8727 movLeft2Result (left, LSB, result, MSB16, 0);
8729 aopPut (result, zero, LSB);
8732 /* 1 <= shCount <= 7 */
8736 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8738 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8742 /*-----------------------------------------------------------------*/
8743 /* shiftLLong - shift left one long from left to result */
8744 /* offl = LSB or MSB16 */
8745 /*-----------------------------------------------------------------*/
8747 shiftLLong (operand * left, operand * result, int offr)
8750 int size = AOP_SIZE (result);
8752 if (size >= LSB + offr)
8754 l = aopGet (left, LSB, FALSE, FALSE);
8756 emitcode ("add", "a,acc");
8757 if (sameRegs (AOP (left), AOP (result)) &&
8758 size >= MSB16 + offr && offr != LSB)
8759 xch_a_aopGet (left, LSB + offr, FALSE, FALSE);
8761 aopPut (result, "a", LSB + offr);
8764 if (size >= MSB16 + offr)
8766 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8768 l = aopGet (left, MSB16, FALSE, FALSE);
8771 emitcode ("rlc", "a");
8772 if (sameRegs (AOP (left), AOP (result)) &&
8773 size >= MSB24 + offr && offr != LSB)
8774 xch_a_aopGet (left, MSB16 + offr, FALSE, FALSE);
8776 aopPut (result, "a", MSB16 + offr);
8779 if (size >= MSB24 + offr)
8781 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8783 l = aopGet (left, MSB24, FALSE, FALSE);
8786 emitcode ("rlc", "a");
8787 if (sameRegs (AOP (left), AOP (result)) &&
8788 size >= MSB32 + offr && offr != LSB)
8789 xch_a_aopGet (left, MSB24 + offr, FALSE, FALSE);
8791 aopPut (result, "a", MSB24 + offr);
8794 if (size > MSB32 + offr)
8796 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8798 l = aopGet (left, MSB32, FALSE, FALSE);
8801 emitcode ("rlc", "a");
8802 aopPut (result, "a", MSB32 + offr);
8805 aopPut (result, zero, LSB);
8808 /*-----------------------------------------------------------------*/
8809 /* genlshFour - shift four byte by a known amount != 0 */
8810 /*-----------------------------------------------------------------*/
8812 genlshFour (operand * result, operand * left, int shCount)
8816 D (emitcode (";", "genlshFour"));
8818 size = AOP_SIZE (result);
8820 /* if shifting more that 3 bytes */
8825 /* lowest order of left goes to the highest
8826 order of the destination */
8827 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8829 movLeft2Result (left, LSB, result, MSB32, 0);
8830 aopPut (result, zero, LSB);
8831 aopPut (result, zero, MSB16);
8832 aopPut (result, zero, MSB24);
8836 /* more than two bytes */
8837 else if (shCount >= 16)
8839 /* lower order two bytes goes to higher order two bytes */
8841 /* if some more remaining */
8843 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8846 movLeft2Result (left, MSB16, result, MSB32, 0);
8847 movLeft2Result (left, LSB, result, MSB24, 0);
8849 aopPut (result, zero, MSB16);
8850 aopPut (result, zero, LSB);
8854 /* if more than 1 byte */
8855 else if (shCount >= 8)
8857 /* lower order three bytes goes to higher order three bytes */
8862 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8864 movLeft2Result (left, LSB, result, MSB16, 0);
8870 movLeft2Result (left, MSB24, result, MSB32, 0);
8871 movLeft2Result (left, MSB16, result, MSB24, 0);
8872 movLeft2Result (left, LSB, result, MSB16, 0);
8873 aopPut (result, zero, LSB);
8875 else if (shCount == 1)
8876 shiftLLong (left, result, MSB16);
8879 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8880 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8881 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8882 aopPut (result, zero, LSB);
8887 /* 1 <= shCount <= 7 */
8888 else if (shCount <= 2)
8890 shiftLLong (left, result, LSB);
8892 shiftLLong (result, result, LSB);
8894 /* 3 <= shCount <= 7, optimize */
8897 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8898 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8899 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8903 /*-----------------------------------------------------------------*/
8904 /* genLeftShiftLiteral - left shifting by known count */
8905 /*-----------------------------------------------------------------*/
8907 genLeftShiftLiteral (operand * left,
8912 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8915 D (emitcode (";", "genLeftShiftLiteral"));
8917 freeAsmop (right, NULL, ic, TRUE);
8919 aopOp (left, ic, FALSE);
8920 aopOp (result, ic, FALSE);
8922 size = getSize (operandType (result));
8925 emitcode ("; shift left ", "result %d, left %d", size,
8929 /* I suppose that the left size >= result size */
8934 movLeft2Result (left, size, result, size, 0);
8937 else if (shCount >= (size * 8))
8941 aopPut (result, zero, size);
8949 genlshOne (result, left, shCount);
8953 genlshTwo (result, left, shCount);
8957 genlshFour (result, left, shCount);
8960 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8961 "*** ack! mystery literal shift!\n");
8965 freeAsmop (result, NULL, ic, TRUE);
8966 freeAsmop (left, NULL, ic, TRUE);
8969 /*-----------------------------------------------------------------*/
8970 /* genLeftShift - generates code for left shifting */
8971 /*-----------------------------------------------------------------*/
8973 genLeftShift (iCode * ic)
8975 operand *left, *right, *result;
8978 symbol *tlbl, *tlbl1;
8981 D (emitcode (";", "genLeftShift"));
8983 right = IC_RIGHT (ic);
8984 left = IC_LEFT (ic);
8985 result = IC_RESULT (ic);
8987 aopOp (right, ic, FALSE);
8989 /* if the shift count is known then do it
8990 as efficiently as possible */
8991 if (AOP_TYPE (right) == AOP_LIT)
8993 genLeftShiftLiteral (left, right, result, ic);
8997 /* shift count is unknown then we have to form
8998 a loop get the loop count in B : Note: we take
8999 only the lower order byte since shifting
9000 more that 32 bits make no sense anyway, ( the
9001 largest size of an object can be only 32 bits ) */
9004 MOVB (aopGet (right, 0, FALSE, FALSE));
9005 emitcode ("inc", "b");
9006 freeAsmop (right, NULL, ic, TRUE);
9007 aopOp (left, ic, FALSE);
9008 aopOp (result, ic, FALSE);
9010 /* now move the left to the result if they are not the same */
9011 if (!sameRegs (AOP (left), AOP (result)) &&
9012 AOP_SIZE (result) > 1)
9015 size = AOP_SIZE (result);
9019 l = aopGet (left, offset, FALSE, TRUE);
9020 if (*l == '@' && (IS_AOP_PREG (result)))
9023 emitcode ("mov", "a,%s", l);
9024 aopPut (result, "a", offset);
9027 aopPut (result, l, offset);
9032 tlbl = newiTempLabel (NULL);
9033 size = AOP_SIZE (result);
9035 tlbl1 = newiTempLabel (NULL);
9037 /* if it is only one byte then */
9040 symbol *tlbl1 = newiTempLabel (NULL);
9042 l = aopGet (left, 0, FALSE, FALSE);
9044 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9046 emitcode ("add", "a,acc");
9048 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9050 aopPut (result, "a", 0);
9054 reAdjustPreg (AOP (result));
9056 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9058 l = aopGet (result, offset, FALSE, FALSE);
9060 emitcode ("add", "a,acc");
9061 aopPut (result, "a", offset++);
9064 l = aopGet (result, offset, FALSE, FALSE);
9066 emitcode ("rlc", "a");
9067 aopPut (result, "a", offset++);
9069 reAdjustPreg (AOP (result));
9072 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9075 freeAsmop (result, NULL, ic, TRUE);
9076 freeAsmop (left, NULL, ic, TRUE);
9079 /*-----------------------------------------------------------------*/
9080 /* genrshOne - right shift a one byte quantity by known count */
9081 /*-----------------------------------------------------------------*/
9083 genrshOne (operand * result, operand * left,
9084 int shCount, int sign)
9086 D (emitcode (";", "genrshOne"));
9088 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9091 /*-----------------------------------------------------------------*/
9092 /* genrshTwo - right shift two bytes by known amount != 0 */
9093 /*-----------------------------------------------------------------*/
9095 genrshTwo (operand * result, operand * left,
9096 int shCount, int sign)
9098 D (emitcode (";", "genrshTwo"));
9100 /* if shCount >= 8 */
9105 shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
9107 movLeft2Result (left, MSB16, result, LSB, sign);
9108 addSign (result, MSB16, sign);
9111 /* 1 <= shCount <= 7 */
9113 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9116 /*-----------------------------------------------------------------*/
9117 /* shiftRLong - shift right one long from left to result */
9118 /* offl = LSB or MSB16 */
9119 /*-----------------------------------------------------------------*/
9121 shiftRLong (operand * left, int offl,
9122 operand * result, int sign)
9124 bool overlapping = regsInCommon (left, result) || operandsEqu(left, result);
9126 if (overlapping && offl>1)
9128 // we are in big trouble, but this shouldn't happen
9129 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9132 MOVA (aopGet (left, MSB32, FALSE, FALSE));
9139 emitcode ("rlc", "a");
9140 emitcode ("subb", "a,acc");
9141 if (overlapping && sameByte (AOP (left), MSB32, AOP (result), MSB32))
9143 xch_a_aopGet (left, MSB32, FALSE, FALSE);
9147 aopPut (result, "a", MSB32);
9148 MOVA (aopGet (left, MSB32, FALSE, FALSE));
9153 if (aopPutUsesAcc (result, zero, MSB32))
9155 emitcode("xch", "a,b");
9156 aopPut (result, zero, MSB32);
9157 emitcode("xch", "a,b");
9161 aopPut (result, zero, MSB32);
9168 emitcode ("clr", "c");
9172 emitcode ("mov", "c,acc.7");
9175 emitcode ("rrc", "a");
9177 if (overlapping && offl==MSB16 &&
9178 sameByte (AOP (left), MSB24, AOP (result), MSB32-offl))
9180 xch_a_aopGet (left, MSB24, FALSE, FALSE);
9184 aopPut (result, "a", MSB32 - offl);
9185 MOVA (aopGet (left, MSB24, FALSE, FALSE));
9188 emitcode ("rrc", "a");
9189 if (overlapping && offl==MSB16 &&
9190 sameByte (AOP (left), MSB16, AOP (result), MSB24-offl))
9192 xch_a_aopGet (left, MSB16, FALSE, FALSE);
9196 aopPut (result, "a", MSB24 - offl);
9197 MOVA (aopGet (left, MSB16, FALSE, FALSE));
9200 emitcode ("rrc", "a");
9203 aopPut (result, "a", MSB16 - offl);
9208 sameByte (AOP (left), LSB, AOP (result), MSB16-offl))
9210 xch_a_aopGet (left, LSB, FALSE, FALSE);
9214 aopPut (result, "a", MSB16 - offl);
9215 MOVA (aopGet (left, LSB, FALSE, FALSE));
9217 emitcode ("rrc", "a");
9218 aopPut (result, "a", LSB);
9222 /*-----------------------------------------------------------------*/
9223 /* genrshFour - shift four byte by a known amount != 0 */
9224 /*-----------------------------------------------------------------*/
9226 genrshFour (operand * result, operand * left,
9227 int shCount, int sign)
9229 D (emitcode (";", "genrshFour"));
9231 /* if shifting more that 3 bytes */
9236 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9238 movLeft2Result (left, MSB32, result, LSB, sign);
9239 addSign (result, MSB16, sign);
9241 else if (shCount >= 16)
9245 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9248 movLeft2Result (left, MSB24, result, LSB, 0);
9249 movLeft2Result (left, MSB32, result, MSB16, sign);
9251 addSign (result, MSB24, sign);
9253 else if (shCount >= 8)
9258 shiftRLong (left, MSB16, result, sign);
9260 else if (shCount == 0)
9262 movLeft2Result (left, MSB16, result, LSB, 0);
9263 movLeft2Result (left, MSB24, result, MSB16, 0);
9264 movLeft2Result (left, MSB32, result, MSB24, sign);
9265 addSign (result, MSB32, sign);
9269 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9270 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9271 /* the last shift is signed */
9272 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9273 addSign (result, MSB32, sign);
9278 /* 1 <= shCount <= 7 */
9281 shiftRLong (left, LSB, result, sign);
9283 shiftRLong (result, LSB, result, sign);
9287 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9288 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9289 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9294 /*-----------------------------------------------------------------*/
9295 /* genRightShiftLiteral - right shifting by known count */
9296 /*-----------------------------------------------------------------*/
9298 genRightShiftLiteral (operand * left,
9304 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9307 D (emitcode (";", "genRightShiftLiteral"));
9309 freeAsmop (right, NULL, ic, TRUE);
9311 aopOp (left, ic, FALSE);
9312 aopOp (result, ic, FALSE);
9315 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9319 size = getDataSize (left);
9320 /* test the LEFT size !!! */
9322 /* I suppose that the left size >= result size */
9325 size = getDataSize (result);
9327 movLeft2Result (left, size, result, size, 0);
9330 else if (shCount >= (size * 8))
9334 /* get sign in acc.7 */
9335 MOVA (aopGet (left, size - 1, FALSE, FALSE));
9337 addSign (result, LSB, sign);
9344 genrshOne (result, left, shCount, sign);
9348 genrshTwo (result, left, shCount, sign);
9352 genrshFour (result, left, shCount, sign);
9358 freeAsmop (result, NULL, ic, TRUE);
9359 freeAsmop (left, NULL, ic, TRUE);
9362 /*-----------------------------------------------------------------*/
9363 /* genSignedRightShift - right shift of signed number */
9364 /*-----------------------------------------------------------------*/
9366 genSignedRightShift (iCode * ic)
9368 operand *right, *left, *result;
9371 symbol *tlbl, *tlbl1;
9374 D (emitcode (";", "genSignedRightShift"));
9376 /* we do it the hard way put the shift count in b
9377 and loop thru preserving the sign */
9379 right = IC_RIGHT (ic);
9380 left = IC_LEFT (ic);
9381 result = IC_RESULT (ic);
9383 aopOp (right, ic, FALSE);
9386 if (AOP_TYPE (right) == AOP_LIT)
9388 genRightShiftLiteral (left, right, result, ic, 1);
9391 /* shift count is unknown then we have to form
9392 a loop get the loop count in B : Note: we take
9393 only the lower order byte since shifting
9394 more that 32 bits make no sense anyway, ( the
9395 largest size of an object can be only 32 bits ) */
9398 MOVB (aopGet (right, 0, FALSE, FALSE));
9399 emitcode ("inc", "b");
9400 freeAsmop (right, NULL, ic, TRUE);
9401 aopOp (left, ic, FALSE);
9402 aopOp (result, ic, FALSE);
9404 /* now move the left to the result if they are not the
9406 if (!sameRegs (AOP (left), AOP (result)) &&
9407 AOP_SIZE (result) > 1)
9410 size = AOP_SIZE (result);
9414 l = aopGet (left, offset, FALSE, TRUE);
9415 if (*l == '@' && IS_AOP_PREG (result))
9418 emitcode ("mov", "a,%s", l);
9419 aopPut (result, "a", offset);
9422 aopPut (result, l, offset);
9427 /* mov the highest order bit to OVR */
9428 tlbl = newiTempLabel (NULL);
9429 tlbl1 = newiTempLabel (NULL);
9431 size = AOP_SIZE (result);
9433 MOVA (aopGet (left, offset, FALSE, FALSE));
9434 emitcode ("rlc", "a");
9435 emitcode ("mov", "ov,c");
9436 /* if it is only one byte then */
9439 l = aopGet (left, 0, FALSE, FALSE);
9441 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9443 emitcode ("mov", "c,ov");
9444 emitcode ("rrc", "a");
9446 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9448 aopPut (result, "a", 0);
9452 reAdjustPreg (AOP (result));
9453 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9455 emitcode ("mov", "c,ov");
9458 l = aopGet (result, offset, FALSE, FALSE);
9460 emitcode ("rrc", "a");
9461 aopPut (result, "a", offset--);
9463 reAdjustPreg (AOP (result));
9465 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9469 freeAsmop (result, NULL, ic, TRUE);
9470 freeAsmop (left, NULL, ic, TRUE);
9473 /*-----------------------------------------------------------------*/
9474 /* genRightShift - generate code for right shifting */
9475 /*-----------------------------------------------------------------*/
9477 genRightShift (iCode * ic)
9479 operand *right, *left, *result;
9483 symbol *tlbl, *tlbl1;
9486 D (emitcode (";", "genRightShift"));
9488 /* if signed then we do it the hard way preserve the
9489 sign bit moving it inwards */
9490 letype = getSpec (operandType (IC_LEFT (ic)));
9492 if (!SPEC_USIGN (letype))
9494 genSignedRightShift (ic);
9498 /* signed & unsigned types are treated the same : i.e. the
9499 signed is NOT propagated inwards : quoting from the
9500 ANSI - standard : "for E1 >> E2, is equivalent to division
9501 by 2**E2 if unsigned or if it has a non-negative value,
9502 otherwise the result is implementation defined ", MY definition
9503 is that the sign does not get propagated */
9505 right = IC_RIGHT (ic);
9506 left = IC_LEFT (ic);
9507 result = IC_RESULT (ic);
9509 aopOp (right, ic, FALSE);
9511 /* if the shift count is known then do it
9512 as efficiently as possible */
9513 if (AOP_TYPE (right) == AOP_LIT)
9515 genRightShiftLiteral (left, right, result, ic, 0);
9519 /* shift count is unknown then we have to form
9520 a loop get the loop count in B : Note: we take
9521 only the lower order byte since shifting
9522 more that 32 bits make no sense anyway, ( the
9523 largest size of an object can be only 32 bits ) */
9526 MOVB (aopGet (right, 0, FALSE, FALSE));
9527 emitcode ("inc", "b");
9528 freeAsmop (right, NULL, ic, TRUE);
9529 aopOp (left, ic, FALSE);
9530 aopOp (result, ic, FALSE);
9532 /* now move the left to the result if they are not the
9534 if (!sameRegs (AOP (left), AOP (result)) &&
9535 AOP_SIZE (result) > 1)
9537 size = AOP_SIZE (result);
9541 l = aopGet (left, offset, FALSE, TRUE);
9542 if (*l == '@' && IS_AOP_PREG (result))
9545 emitcode ("mov", "a,%s", l);
9546 aopPut (result, "a", offset);
9549 aopPut (result, l, offset);
9554 tlbl = newiTempLabel (NULL);
9555 tlbl1 = newiTempLabel (NULL);
9556 size = AOP_SIZE (result);
9559 /* if it is only one byte then */
9562 l = aopGet (left, 0, FALSE, FALSE);
9564 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9567 emitcode ("rrc", "a");
9569 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9571 aopPut (result, "a", 0);
9575 reAdjustPreg (AOP (result));
9576 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9581 l = aopGet (result, offset, FALSE, FALSE);
9583 emitcode ("rrc", "a");
9584 aopPut (result, "a", offset--);
9586 reAdjustPreg (AOP (result));
9589 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9593 freeAsmop (result, NULL, ic, TRUE);
9594 freeAsmop (left, NULL, ic, TRUE);
9597 /*-----------------------------------------------------------------*/
9598 /* emitPtrByteGet - emits code to get a byte into A through a */
9599 /* pointer register (R0, R1, or DPTR). The */
9600 /* original value of A can be preserved in B. */
9601 /*-----------------------------------------------------------------*/
9603 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9610 emitcode ("mov", "b,a");
9611 emitcode ("mov", "a,@%s", rname);
9616 emitcode ("mov", "b,a");
9617 emitcode ("movx", "a,@%s", rname);
9622 emitcode ("mov", "b,a");
9623 emitcode ("movx", "a,@dptr");
9628 emitcode ("mov", "b,a");
9629 emitcode ("clr", "a");
9630 emitcode ("movc", "a,@a+dptr");
9636 emitcode ("push", "b");
9637 emitcode ("push", "acc");
9639 emitcode ("lcall", "__gptrget");
9641 emitcode ("pop", "b");
9646 /*-----------------------------------------------------------------*/
9647 /* emitPtrByteSet - emits code to set a byte from src through a */
9648 /* pointer register (R0, R1, or DPTR). */
9649 /*-----------------------------------------------------------------*/
9651 emitPtrByteSet (char *rname, int p_type, char *src)
9660 emitcode ("mov", "@%s,a", rname);
9663 emitcode ("mov", "@%s,%s", rname, src);
9668 emitcode ("movx", "@%s,a", rname);
9673 emitcode ("movx", "@dptr,a");
9678 emitcode ("lcall", "__gptrput");
9683 /*-----------------------------------------------------------------*/
9684 /* genUnpackBits - generates code for unpacking bits */
9685 /*-----------------------------------------------------------------*/
9687 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9689 int offset = 0; /* result byte offset */
9690 int rsize; /* result size */
9691 int rlen = 0; /* remaining bitfield length */
9692 sym_link *etype; /* bitfield type information */
9693 int blen; /* bitfield length */
9694 int bstr; /* bitfield starting bit within byte */
9697 D(emitcode ("; genUnpackBits",""));
9699 etype = getSpec (operandType (result));
9700 rsize = getSize (operandType (result));
9701 blen = SPEC_BLEN (etype);
9702 bstr = SPEC_BSTR (etype);
9704 if (ifx && blen <= 8)
9706 emitPtrByteGet (rname, ptype, FALSE);
9709 SNPRINTF (buffer, sizeof(buffer),
9711 genIfxJump (ifx, buffer, NULL, NULL, NULL);
9716 emitcode ("anl", "a,#0x%02x",
9717 (((unsigned char) -1) >> (8 - blen)) << bstr);
9718 genIfxJump (ifx, "a", NULL, NULL, NULL);
9724 /* If the bitfield length is less than a byte */
9727 emitPtrByteGet (rname, ptype, FALSE);
9729 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9730 if (!SPEC_USIGN (etype))
9732 /* signed bitfield */
9733 symbol *tlbl = newiTempLabel (NULL);
9735 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9736 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9739 aopPut (result, "a", offset++);
9743 /* Bit field did not fit in a byte. Copy all
9744 but the partial byte at the end. */
9745 for (rlen=blen;rlen>=8;rlen-=8)
9747 emitPtrByteGet (rname, ptype, FALSE);
9748 aopPut (result, "a", offset++);
9750 emitcode ("inc", "%s", rname);
9753 /* Handle the partial byte at the end */
9756 emitPtrByteGet (rname, ptype, FALSE);
9757 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9758 if (!SPEC_USIGN (etype))
9760 /* signed bitfield */
9761 symbol *tlbl = newiTempLabel (NULL);
9763 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9764 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9767 aopPut (result, "a", offset++);
9775 if (SPEC_USIGN (etype))
9779 /* signed bitfield: sign extension with 0x00 or 0xff */
9780 emitcode ("rlc", "a");
9781 emitcode ("subb", "a,acc");
9787 aopPut (result, source, offset++);
9792 /*-----------------------------------------------------------------*/
9793 /* genDataPointerGet - generates code when ptr offset is known */
9794 /*-----------------------------------------------------------------*/
9796 genDataPointerGet (operand * left,
9802 int size, offset = 0;
9804 D (emitcode (";", "genDataPointerGet"));
9806 aopOp (result, ic, TRUE);
9808 /* get the string representation of the name */
9809 l = aopGet (left, 0, FALSE, TRUE);
9811 size = AOP_SIZE (result);
9816 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
9820 SNPRINTF (buffer, sizeof(buffer), "%s", l);
9822 aopPut (result, buffer, offset++);
9825 freeAsmop (result, NULL, ic, TRUE);
9826 freeAsmop (left, NULL, ic, TRUE);
9829 /*-----------------------------------------------------------------*/
9830 /* genNearPointerGet - emitcode for near pointer fetch */
9831 /*-----------------------------------------------------------------*/
9833 genNearPointerGet (operand * left,
9842 sym_link *rtype, *retype;
9843 sym_link *ltype = operandType (left);
9846 D (emitcode (";", "genNearPointerGet"));
9848 rtype = operandType (result);
9849 retype = getSpec (rtype);
9851 aopOp (left, ic, FALSE);
9853 /* if left is rematerialisable and
9854 result is not bitfield variable type and
9855 the left is pointer to data space i.e
9856 lower 128 bytes of space */
9857 if (AOP_TYPE (left) == AOP_IMMD &&
9858 !IS_BITFIELD (retype) &&
9859 DCL_TYPE (ltype) == POINTER)
9861 genDataPointerGet (left, result, ic);
9865 /* if the value is already in a pointer register
9866 then don't need anything more */
9867 if (!AOP_INPREG (AOP (left)))
9869 if (IS_AOP_PREG (left))
9871 // Aha, it is a pointer, just in disguise.
9872 rname = aopGet (left, 0, FALSE, FALSE);
9875 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9876 __FILE__, __LINE__);
9881 emitcode ("mov", "a%s,%s", rname + 1, rname);
9882 rname++; // skip the '@'.
9887 /* otherwise get a free pointer register */
9889 preg = getFreePtr (ic, &aop, FALSE);
9890 emitcode ("mov", "%s,%s",
9892 aopGet (left, 0, FALSE, TRUE));
9897 rname = aopGet (left, 0, FALSE, FALSE);
9899 //aopOp (result, ic, FALSE);
9900 aopOp (result, ic, result?TRUE:FALSE);
9902 /* if bitfield then unpack the bits */
9903 if (IS_BITFIELD (retype))
9904 genUnpackBits (result, rname, POINTER, ifx);
9907 /* we have can just get the values */
9908 int size = AOP_SIZE (result);
9913 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9916 emitcode ("mov", "a,@%s", rname);
9918 aopPut (result, "a", offset);
9922 SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
9923 aopPut (result, buffer, offset);
9927 emitcode ("inc", "%s", rname);
9931 /* now some housekeeping stuff */
9932 if (aop) /* we had to allocate for this iCode */
9934 if (pi) { /* post increment present */
9935 aopPut (left, rname, 0);
9937 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9941 /* we did not allocate which means left
9942 already in a pointer register, then
9943 if size > 0 && this could be used again
9944 we have to point it back to where it
9946 if ((AOP_SIZE (result) > 1 &&
9947 !OP_SYMBOL (left)->remat &&
9948 (OP_SYMBOL (left)->liveTo > ic->seq ||
9952 int size = AOP_SIZE (result) - 1;
9954 emitcode ("dec", "%s", rname);
9958 if (ifx && !ifx->generated)
9960 genIfxJump (ifx, "a", left, NULL, result);
9964 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9965 freeAsmop (left, NULL, ic, TRUE);
9966 if (pi) pi->generated = 1;
9969 /*-----------------------------------------------------------------*/
9970 /* genPagedPointerGet - emitcode for paged pointer fetch */
9971 /*-----------------------------------------------------------------*/
9973 genPagedPointerGet (operand * left,
9982 sym_link *rtype, *retype;
9984 D (emitcode (";", "genPagedPointerGet"));
9986 rtype = operandType (result);
9987 retype = getSpec (rtype);
9989 aopOp (left, ic, FALSE);
9991 /* if the value is already in a pointer register
9992 then don't need anything more */
9993 if (!AOP_INPREG (AOP (left)))
9995 /* otherwise get a free pointer register */
9997 preg = getFreePtr (ic, &aop, FALSE);
9998 emitcode ("mov", "%s,%s",
10000 aopGet (left, 0, FALSE, TRUE));
10001 rname = preg->name;
10004 rname = aopGet (left, 0, FALSE, FALSE);
10006 aopOp (result, ic, FALSE);
10008 /* if bitfield then unpack the bits */
10009 if (IS_BITFIELD (retype))
10010 genUnpackBits (result, rname, PPOINTER, ifx);
10013 /* we have can just get the values */
10014 int size = AOP_SIZE (result);
10020 emitcode ("movx", "a,@%s", rname);
10022 aopPut (result, "a", offset);
10027 emitcode ("inc", "%s", rname);
10031 /* now some housekeeping stuff */
10032 if (aop) /* we had to allocate for this iCode */
10035 aopPut (left, rname, 0);
10036 freeAsmop (NULL, aop, ic, TRUE);
10040 /* we did not allocate which means left
10041 already in a pointer register, then
10042 if size > 0 && this could be used again
10043 we have to point it back to where it
10045 if ((AOP_SIZE (result) > 1 &&
10046 !OP_SYMBOL (left)->remat &&
10047 (OP_SYMBOL (left)->liveTo > ic->seq ||
10051 int size = AOP_SIZE (result) - 1;
10053 emitcode ("dec", "%s", rname);
10057 if (ifx && !ifx->generated)
10059 genIfxJump (ifx, "a", left, NULL, result);
10063 freeAsmop (result, NULL, ic, TRUE);
10064 freeAsmop (left, NULL, ic, TRUE);
10065 if (pi) pi->generated = 1;
10068 /*--------------------------------------------------------------------*/
10069 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
10070 /*--------------------------------------------------------------------*/
10072 loadDptrFromOperand (operand *op, bool loadBToo)
10074 if (AOP_TYPE (op) != AOP_STR)
10076 /* if this is rematerializable */
10077 if (AOP_TYPE (op) == AOP_IMMD)
10079 emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
10082 if (AOP(op)->aopu.aop_immd.from_cast_remat)
10083 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
10086 wassertl(FALSE, "need pointerCode");
10087 emitcode ("", "; mov b,???");
10088 /* genPointerGet and genPointerSet originally did different
10089 ** things for this case. Both seem wrong.
10090 ** from genPointerGet:
10091 ** emitcode ("mov", "b,#%d", pointerCode (retype));
10092 ** from genPointerSet:
10093 ** emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
10098 else if (AOP_TYPE (op) == AOP_DPTR)
10102 MOVA (aopGet (op, 0, FALSE, FALSE));
10103 emitcode ("push", "acc");
10104 MOVA (aopGet (op, 1, FALSE, FALSE));
10105 emitcode ("push", "acc");
10106 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10107 emitcode ("pop", "dph");
10108 emitcode ("pop", "dpl");
10112 MOVA (aopGet (op, 0, FALSE, FALSE));
10113 emitcode ("push", "acc");
10114 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10115 emitcode ("pop", "dpl");
10119 { /* we need to get it byte by byte */
10120 emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
10121 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10123 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10128 /*-----------------------------------------------------------------*/
10129 /* genFarPointerGet - get value from far space */
10130 /*-----------------------------------------------------------------*/
10132 genFarPointerGet (operand * left,
10133 operand * result, iCode * ic, iCode * pi, iCode * ifx)
10136 sym_link *retype = getSpec (operandType (result));
10138 D (emitcode (";", "genFarPointerGet"));
10140 aopOp (left, ic, FALSE);
10141 loadDptrFromOperand (left, FALSE);
10143 /* so dptr now contains the address */
10144 aopOp (result, ic, FALSE);
10146 /* if bit then unpack */
10147 if (IS_BITFIELD (retype))
10148 genUnpackBits (result, "dptr", FPOINTER, ifx);
10151 size = AOP_SIZE (result);
10156 emitcode ("movx", "a,@dptr");
10158 aopPut (result, "a", offset++);
10160 emitcode ("inc", "dptr");
10164 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10166 aopPut (left, "dpl", 0);
10167 aopPut (left, "dph", 1);
10171 if (ifx && !ifx->generated)
10173 genIfxJump (ifx, "a", left, NULL, result);
10176 freeAsmop (result, NULL, ic, TRUE);
10177 freeAsmop (left, NULL, ic, TRUE);
10180 /*-----------------------------------------------------------------*/
10181 /* genCodePointerGet - get value from code space */
10182 /*-----------------------------------------------------------------*/
10184 genCodePointerGet (operand * left,
10185 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10188 sym_link *retype = getSpec (operandType (result));
10190 D (emitcode (";", "genCodePointerGet"));
10192 aopOp (left, ic, FALSE);
10193 loadDptrFromOperand (left, FALSE);
10195 /* so dptr now contains the address */
10196 aopOp (result, ic, FALSE);
10198 /* if bit then unpack */
10199 if (IS_BITFIELD (retype))
10200 genUnpackBits (result, "dptr", CPOINTER, ifx);
10203 size = AOP_SIZE (result);
10208 emitcode ("clr", "a");
10209 emitcode ("movc", "a,@a+dptr");
10211 aopPut (result, "a", offset++);
10213 emitcode ("inc", "dptr");
10217 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10219 aopPut (left, "dpl", 0);
10220 aopPut (left, "dph", 1);
10224 if (ifx && !ifx->generated)
10226 genIfxJump (ifx, "a", left, NULL, result);
10229 freeAsmop (result, NULL, ic, TRUE);
10230 freeAsmop (left, NULL, ic, TRUE);
10233 /*-----------------------------------------------------------------*/
10234 /* genGenPointerGet - get value from generic pointer space */
10235 /*-----------------------------------------------------------------*/
10237 genGenPointerGet (operand * left,
10238 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10241 sym_link *retype = getSpec (operandType (result));
10243 D (emitcode (";", "genGenPointerGet"));
10245 aopOp (left, ic, FALSE);
10246 loadDptrFromOperand (left, TRUE);
10248 /* so dptr now contains the address */
10249 aopOp (result, ic, FALSE);
10251 /* if bit then unpack */
10252 if (IS_BITFIELD (retype))
10254 genUnpackBits (result, "dptr", GPOINTER, ifx);
10258 size = AOP_SIZE (result);
10263 emitcode ("lcall", "__gptrget");
10265 aopPut (result, "a", offset++);
10267 emitcode ("inc", "dptr");
10271 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10273 aopPut (left, "dpl", 0);
10274 aopPut (left, "dph", 1);
10278 if (ifx && !ifx->generated)
10280 genIfxJump (ifx, "a", left, NULL, result);
10283 freeAsmop (result, NULL, ic, TRUE);
10284 freeAsmop (left, NULL, ic, TRUE);
10287 /*-----------------------------------------------------------------*/
10288 /* genPointerGet - generate code for pointer get */
10289 /*-----------------------------------------------------------------*/
10291 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
10293 operand *left, *result;
10294 sym_link *type, *etype;
10297 D (emitcode (";", "genPointerGet"));
10299 left = IC_LEFT (ic);
10300 result = IC_RESULT (ic);
10302 if (getSize (operandType (result))>1)
10305 /* depending on the type of pointer we need to
10306 move it to the correct pointer register */
10307 type = operandType (left);
10308 etype = getSpec (type);
10309 /* if left is of type of pointer then it is simple */
10310 if (IS_PTR (type) && !IS_FUNC (type->next))
10311 p_type = DCL_TYPE (type);
10314 /* we have to go by the storage class */
10315 p_type = PTR_TYPE (SPEC_OCLS (etype));
10318 /* special case when cast remat */
10319 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10320 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10322 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10323 type = operandType (left);
10324 p_type = DCL_TYPE (type);
10326 /* now that we have the pointer type we assign
10327 the pointer values */
10333 genNearPointerGet (left, result, ic, pi, ifx);
10337 genPagedPointerGet (left, result, ic, pi, ifx);
10341 genFarPointerGet (left, result, ic, pi, ifx);
10345 genCodePointerGet (left, result, ic, pi, ifx);
10349 genGenPointerGet (left, result, ic, pi, ifx);
10355 /*-----------------------------------------------------------------*/
10356 /* genPackBits - generates code for packed bit storage */
10357 /*-----------------------------------------------------------------*/
10359 genPackBits (sym_link * etype,
10361 char *rname, int p_type)
10363 int offset = 0; /* source byte offset */
10364 int rlen = 0; /* remaining bitfield length */
10365 int blen; /* bitfield length */
10366 int bstr; /* bitfield starting bit within byte */
10367 int litval; /* source literal value (if AOP_LIT) */
10368 unsigned char mask; /* bitmask within current byte */
10370 D(emitcode ("; genPackBits",""));
10372 blen = SPEC_BLEN (etype);
10373 bstr = SPEC_BSTR (etype);
10375 /* If the bitfield length is less than a byte */
10378 mask = ((unsigned char) (0xFF << (blen + bstr)) |
10379 (unsigned char) (0xFF >> (8 - bstr)));
10381 if (AOP_TYPE (right) == AOP_LIT)
10383 /* Case with a bitfield length <8 and literal source
10385 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10387 litval &= (~mask) & 0xff;
10388 emitPtrByteGet (rname, p_type, FALSE);
10389 if ((mask|litval)!=0xff)
10390 emitcode ("anl","a,#0x%02x", mask);
10392 emitcode ("orl","a,#0x%02x", litval);
10396 if ((blen==1) && (p_type!=GPOINTER))
10398 /* Case with a bitfield length == 1 and no generic pointer
10400 if (AOP_TYPE (right) == AOP_CRY)
10401 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10404 MOVA (aopGet (right, 0, FALSE, FALSE));
10405 emitcode ("rrc","a");
10407 emitPtrByteGet (rname, p_type, FALSE);
10408 emitcode ("mov","acc.%d,c",bstr);
10413 /* Case with a bitfield length < 8 and arbitrary source
10415 MOVA (aopGet (right, 0, FALSE, FALSE));
10416 /* shift and mask source value */
10418 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10420 pushedB = pushB ();
10421 /* transfer A to B and get next byte */
10422 emitPtrByteGet (rname, p_type, TRUE);
10424 emitcode ("anl", "a,#0x%02x", mask);
10425 emitcode ("orl", "a,b");
10426 if (p_type == GPOINTER)
10427 emitcode ("pop", "b");
10433 emitPtrByteSet (rname, p_type, "a");
10437 /* Bit length is greater than 7 bits. In this case, copy */
10438 /* all except the partial byte at the end */
10439 for (rlen=blen;rlen>=8;rlen-=8)
10441 emitPtrByteSet (rname, p_type,
10442 aopGet (right, offset++, FALSE, TRUE) );
10444 emitcode ("inc", "%s", rname);
10447 /* If there was a partial byte at the end */
10450 mask = (((unsigned char) -1 << rlen) & 0xff);
10452 if (AOP_TYPE (right) == AOP_LIT)
10454 /* Case with partial byte and literal source
10456 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10457 litval >>= (blen-rlen);
10458 litval &= (~mask) & 0xff;
10459 emitPtrByteGet (rname, p_type, FALSE);
10460 if ((mask|litval)!=0xff)
10461 emitcode ("anl","a,#0x%02x", mask);
10463 emitcode ("orl","a,#0x%02x", litval);
10468 /* Case with partial byte and arbitrary source
10470 MOVA (aopGet (right, offset++, FALSE, FALSE));
10471 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10473 pushedB = pushB ();
10474 /* transfer A to B and get next byte */
10475 emitPtrByteGet (rname, p_type, TRUE);
10477 emitcode ("anl", "a,#0x%02x", mask);
10478 emitcode ("orl", "a,b");
10479 if (p_type == GPOINTER)
10480 emitcode ("pop", "b");
10484 emitPtrByteSet (rname, p_type, "a");
10489 /*-----------------------------------------------------------------*/
10490 /* genDataPointerSet - remat pointer to data space */
10491 /*-----------------------------------------------------------------*/
10493 genDataPointerSet (operand * right,
10497 int size, offset = 0;
10498 char *l, buffer[256];
10500 D (emitcode (";", "genDataPointerSet"));
10502 aopOp (right, ic, FALSE);
10504 l = aopGet (result, 0, FALSE, TRUE);
10506 size = AOP_SIZE (right);
10510 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
10512 SNPRINTF (buffer, sizeof(buffer), "%s", l);
10513 emitcode ("mov", "%s,%s", buffer,
10514 aopGet (right, offset++, FALSE, FALSE));
10517 freeAsmop (result, NULL, ic, TRUE);
10518 freeAsmop (right, NULL, ic, TRUE);
10521 /*-----------------------------------------------------------------*/
10522 /* genNearPointerSet - emitcode for near pointer put */
10523 /*-----------------------------------------------------------------*/
10525 genNearPointerSet (operand * right,
10533 sym_link *retype, *letype;
10534 sym_link *ptype = operandType (result);
10536 D (emitcode (";", "genNearPointerSet"));
10538 retype = getSpec (operandType (right));
10539 letype = getSpec (ptype);
10541 aopOp (result, ic, FALSE);
10543 /* if the result is rematerializable &
10544 in data space & not a bit variable */
10545 if (AOP_TYPE (result) == AOP_IMMD &&
10546 DCL_TYPE (ptype) == POINTER &&
10547 !IS_BITVAR (retype) &&
10548 !IS_BITVAR (letype))
10550 genDataPointerSet (right, result, ic);
10554 /* if the value is already in a pointer register
10555 then don't need anything more */
10556 if (!AOP_INPREG (AOP (result)))
10559 //AOP_TYPE (result) == AOP_STK
10560 IS_AOP_PREG(result)
10563 // Aha, it is a pointer, just in disguise.
10564 rname = aopGet (result, 0, FALSE, FALSE);
10567 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10568 __FILE__, __LINE__);
10573 emitcode ("mov", "a%s,%s", rname + 1, rname);
10574 rname++; // skip the '@'.
10579 /* otherwise get a free pointer register */
10580 aop = newAsmop (0);
10581 preg = getFreePtr (ic, &aop, FALSE);
10582 emitcode ("mov", "%s,%s",
10584 aopGet (result, 0, FALSE, TRUE));
10585 rname = preg->name;
10590 rname = aopGet (result, 0, FALSE, FALSE);
10593 aopOp (right, ic, FALSE);
10595 /* if bitfield then unpack the bits */
10596 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10597 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10600 /* we can just get the values */
10601 int size = AOP_SIZE (right);
10606 l = aopGet (right, offset, FALSE, TRUE);
10607 if ((*l == '@') || (strcmp (l, "acc") == 0))
10610 emitcode ("mov", "@%s,a", rname);
10613 emitcode ("mov", "@%s,%s", rname, l);
10615 emitcode ("inc", "%s", rname);
10620 /* now some housekeeping stuff */
10621 if (aop) /* we had to allocate for this iCode */
10624 aopPut (result, rname, 0);
10625 freeAsmop (NULL, aop, ic, TRUE);
10629 /* we did not allocate which means left
10630 already in a pointer register, then
10631 if size > 0 && this could be used again
10632 we have to point it back to where it
10634 if ((AOP_SIZE (right) > 1 &&
10635 !OP_SYMBOL (result)->remat &&
10636 (OP_SYMBOL (result)->liveTo > ic->seq ||
10640 int size = AOP_SIZE (right) - 1;
10642 emitcode ("dec", "%s", rname);
10647 if (pi) pi->generated = 1;
10648 freeAsmop (result, NULL, ic, TRUE);
10649 freeAsmop (right, NULL, ic, TRUE);
10652 /*-----------------------------------------------------------------*/
10653 /* genPagedPointerSet - emitcode for Paged pointer put */
10654 /*-----------------------------------------------------------------*/
10656 genPagedPointerSet (operand * right,
10664 sym_link *retype, *letype;
10666 D (emitcode (";", "genPagedPointerSet"));
10668 retype = getSpec (operandType (right));
10669 letype = getSpec (operandType (result));
10671 aopOp (result, ic, FALSE);
10673 /* if the value is already in a pointer register
10674 then don't need anything more */
10675 if (!AOP_INPREG (AOP (result)))
10677 /* otherwise get a free pointer register */
10678 aop = newAsmop (0);
10679 preg = getFreePtr (ic, &aop, FALSE);
10680 emitcode ("mov", "%s,%s",
10682 aopGet (result, 0, FALSE, TRUE));
10683 rname = preg->name;
10686 rname = aopGet (result, 0, FALSE, FALSE);
10688 aopOp (right, ic, FALSE);
10690 /* if bitfield then unpack the bits */
10691 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10692 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10695 /* we have can just get the values */
10696 int size = AOP_SIZE (right);
10701 l = aopGet (right, offset, FALSE, TRUE);
10703 emitcode ("movx", "@%s,a", rname);
10706 emitcode ("inc", "%s", rname);
10712 /* now some housekeeping stuff */
10713 if (aop) /* we had to allocate for this iCode */
10716 aopPut (result, rname, 0);
10717 freeAsmop (NULL, aop, ic, TRUE);
10721 /* we did not allocate which means left
10722 already in a pointer register, then
10723 if size > 0 && this could be used again
10724 we have to point it back to where it
10726 if (AOP_SIZE (right) > 1 &&
10727 !OP_SYMBOL (result)->remat &&
10728 (OP_SYMBOL (result)->liveTo > ic->seq ||
10731 int size = AOP_SIZE (right) - 1;
10733 emitcode ("dec", "%s", rname);
10738 if (pi) pi->generated = 1;
10739 freeAsmop (result, NULL, ic, TRUE);
10740 freeAsmop (right, NULL, ic, TRUE);
10743 /*-----------------------------------------------------------------*/
10744 /* genFarPointerSet - set value from far space */
10745 /*-----------------------------------------------------------------*/
10747 genFarPointerSet (operand * right,
10748 operand * result, iCode * ic, iCode * pi)
10751 sym_link *retype = getSpec (operandType (right));
10752 sym_link *letype = getSpec (operandType (result));
10754 D(emitcode ("; genFarPointerSet",""));
10756 aopOp (result, ic, FALSE);
10757 loadDptrFromOperand (result, FALSE);
10759 /* so dptr now contains the address */
10760 aopOp (right, ic, FALSE);
10762 /* if bit then unpack */
10763 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10764 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10767 size = AOP_SIZE (right);
10772 char *l = aopGet (right, offset++, FALSE, FALSE);
10774 emitcode ("movx", "@dptr,a");
10776 emitcode ("inc", "dptr");
10779 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10780 aopPut (result, "dpl", 0);
10781 aopPut (result, "dph", 1);
10784 freeAsmop (result, NULL, ic, TRUE);
10785 freeAsmop (right, NULL, ic, TRUE);
10788 /*-----------------------------------------------------------------*/
10789 /* genGenPointerSet - set value from generic pointer space */
10790 /*-----------------------------------------------------------------*/
10792 genGenPointerSet (operand * right,
10793 operand * result, iCode * ic, iCode * pi)
10796 sym_link *retype = getSpec (operandType (right));
10797 sym_link *letype = getSpec (operandType (result));
10799 D (emitcode (";", "genGenPointerSet"));
10801 aopOp (result, ic, FALSE);
10802 loadDptrFromOperand (result, TRUE);
10804 /* so dptr now contains the address */
10805 aopOp (right, ic, FALSE);
10807 /* if bit then unpack */
10808 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10810 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10814 size = AOP_SIZE (right);
10819 char *l = aopGet (right, offset++, FALSE, FALSE);
10821 emitcode ("lcall", "__gptrput");
10823 emitcode ("inc", "dptr");
10827 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10828 aopPut (result, "dpl", 0);
10829 aopPut (result, "dph", 1);
10832 freeAsmop (result, NULL, ic, TRUE);
10833 freeAsmop (right, NULL, ic, TRUE);
10836 /*-----------------------------------------------------------------*/
10837 /* genPointerSet - stores the value into a pointer location */
10838 /*-----------------------------------------------------------------*/
10840 genPointerSet (iCode * ic, iCode *pi)
10842 operand *right, *result;
10843 sym_link *type, *etype;
10846 D (emitcode (";", "genPointerSet"));
10848 right = IC_RIGHT (ic);
10849 result = IC_RESULT (ic);
10851 /* depending on the type of pointer we need to
10852 move it to the correct pointer register */
10853 type = operandType (result);
10854 etype = getSpec (type);
10855 /* if left is of type of pointer then it is simple */
10856 if (IS_PTR (type) && !IS_FUNC (type->next))
10858 p_type = DCL_TYPE (type);
10862 /* we have to go by the storage class */
10863 p_type = PTR_TYPE (SPEC_OCLS (etype));
10866 /* special case when cast remat */
10867 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10868 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10869 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10870 type = operandType (result);
10871 p_type = DCL_TYPE (type);
10874 /* now that we have the pointer type we assign
10875 the pointer values */
10881 genNearPointerSet (right, result, ic, pi);
10885 genPagedPointerSet (right, result, ic, pi);
10889 genFarPointerSet (right, result, ic, pi);
10893 genGenPointerSet (right, result, ic, pi);
10897 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10898 "genPointerSet: illegal pointer type");
10902 /*-----------------------------------------------------------------*/
10903 /* genIfx - generate code for Ifx statement */
10904 /*-----------------------------------------------------------------*/
10906 genIfx (iCode * ic, iCode * popIc)
10908 operand *cond = IC_COND (ic);
10912 D (emitcode (";", "genIfx"));
10914 aopOp (cond, ic, FALSE);
10916 /* get the value into acc */
10917 if (AOP_TYPE (cond) != AOP_CRY)
10924 if (AOP(cond)->aopu.aop_dir)
10925 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10928 /* the result is now in the accumulator or a directly addressable bit */
10929 freeAsmop (cond, NULL, ic, TRUE);
10931 /* if there was something to be popped then do it */
10935 /* if the condition is a bit variable */
10937 genIfxJump(ic, dup, NULL, NULL, NULL);
10938 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10939 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10940 else if (isbit && !IS_ITEMP (cond))
10941 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10943 genIfxJump (ic, "a", NULL, NULL, NULL);
10948 /*-----------------------------------------------------------------*/
10949 /* genAddrOf - generates code for address of */
10950 /*-----------------------------------------------------------------*/
10952 genAddrOf (iCode * ic)
10954 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10957 D (emitcode (";", "genAddrOf"));
10959 aopOp (IC_RESULT (ic), ic, FALSE);
10961 /* if the operand is on the stack then we
10962 need to get the stack offset of this
10966 /* if it has an offset then we need to compute it */
10969 int stack_offset = ((sym->stack < 0) ?
10970 ((char) (sym->stack - _G.nRegsSaved)) :
10971 ((char) sym->stack)) & 0xff;
10972 if ((abs(stack_offset) == 1) &&
10973 !AOP_NEEDSACC(IC_RESULT (ic)) &&
10974 !isOperandVolatile (IC_RESULT (ic), FALSE))
10976 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
10977 if (stack_offset > 0)
10978 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
10980 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
10984 emitcode ("mov", "a,%s", SYM_BP (sym));
10985 emitcode ("add", "a,#0x%02x", stack_offset & 0xff);
10986 aopPut (IC_RESULT (ic), "a", 0);
10991 /* we can just move _bp */
10992 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
10994 /* fill the result with zero */
10995 size = AOP_SIZE (IC_RESULT (ic)) - 1;
11000 aopPut (IC_RESULT (ic), zero, offset++);
11005 /* object not on stack then we need the name */
11006 size = AOP_SIZE (IC_RESULT (ic));
11011 char s[SDCC_NAME_MAX];
11013 sprintf (s, "#(%s >> %d)",
11017 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11018 aopPut (IC_RESULT (ic), s, offset++);
11022 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11026 /*-----------------------------------------------------------------*/
11027 /* genFarFarAssign - assignment when both are in far space */
11028 /*-----------------------------------------------------------------*/
11030 genFarFarAssign (operand * result, operand * right, iCode * ic)
11032 int size = AOP_SIZE (right);
11036 D (emitcode (";", "genFarFarAssign"));
11038 /* first push the right side on to the stack */
11041 l = aopGet (right, offset++, FALSE, FALSE);
11043 emitcode ("push", "acc");
11046 freeAsmop (right, NULL, ic, FALSE);
11047 /* now assign DPTR to result */
11048 aopOp (result, ic, FALSE);
11049 size = AOP_SIZE (result);
11052 emitcode ("pop", "acc");
11053 aopPut (result, "a", --offset);
11055 freeAsmop (result, NULL, ic, FALSE);
11058 /*-----------------------------------------------------------------*/
11059 /* genAssign - generate code for assignment */
11060 /*-----------------------------------------------------------------*/
11062 genAssign (iCode * ic)
11064 operand *result, *right;
11066 unsigned long lit = 0L;
11068 D (emitcode (";", "genAssign"));
11070 result = IC_RESULT (ic);
11071 right = IC_RIGHT (ic);
11073 /* if they are the same */
11074 if (operandsEqu (result, right) &&
11075 !isOperandVolatile (result, FALSE) &&
11076 !isOperandVolatile (right, FALSE))
11079 aopOp (right, ic, FALSE);
11081 /* special case both in far space */
11082 if (AOP_TYPE (right) == AOP_DPTR &&
11083 IS_TRUE_SYMOP (result) &&
11084 isOperandInFarSpace (result))
11086 genFarFarAssign (result, right, ic);
11090 aopOp (result, ic, TRUE);
11092 /* if they are the same registers */
11093 if (sameRegs (AOP (right), AOP (result)) &&
11094 !isOperandVolatile (result, FALSE) &&
11095 !isOperandVolatile (right, FALSE))
11098 /* if the result is a bit */
11099 if (AOP_TYPE (result) == AOP_CRY)
11101 assignBit (result, right);
11105 /* bit variables done */
11107 size = AOP_SIZE (result);
11109 if (AOP_TYPE (right) == AOP_LIT)
11110 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11113 (AOP_TYPE (result) != AOP_REG) &&
11114 (AOP_TYPE (right) == AOP_LIT) &&
11115 !IS_FLOAT (operandType (right)) &&
11118 while ((size) && (lit))
11121 aopGet (right, offset, FALSE, FALSE),
11127 /* And now fill the rest with zeros. */
11130 emitcode ("clr", "a");
11134 aopPut (result, "a", offset);
11143 aopGet (right, offset, FALSE, FALSE),
11150 freeAsmop (result, NULL, ic, TRUE);
11151 freeAsmop (right, NULL, ic, TRUE);
11154 /*-----------------------------------------------------------------*/
11155 /* genJumpTab - generates code for jump table */
11156 /*-----------------------------------------------------------------*/
11158 genJumpTab (iCode * ic)
11160 symbol *jtab,*jtablo,*jtabhi;
11162 unsigned int count;
11164 D (emitcode (";", "genJumpTab"));
11166 count = elementsInSet( IC_JTLABELS (ic) );
11170 /* this algorithm needs 9 cycles and 7 + 3*n bytes
11171 if the switch argument is in a register.
11172 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
11173 /* Peephole may not convert ljmp to sjmp or ret
11174 labelIsReturnOnly & labelInRange must check
11175 currPl->ic->op != JUMPTABLE */
11176 aopOp (IC_JTCOND (ic), ic, FALSE);
11177 /* get the condition into accumulator */
11178 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11180 /* multiply by three */
11181 if (aopGetUsesAcc (IC_JTCOND (ic), 0))
11183 emitcode ("mov", "b,#3");
11184 emitcode ("mul", "ab");
11188 emitcode ("add", "a,acc");
11189 emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
11191 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11193 jtab = newiTempLabel (NULL);
11194 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
11195 emitcode ("jmp", "@a+dptr");
11197 /* now generate the jump labels */
11198 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11199 jtab = setNextItem (IC_JTLABELS (ic)))
11200 emitcode ("ljmp", "%05d$", jtab->key + 100);
11204 /* this algorithm needs 14 cycles and 13 + 2*n bytes
11205 if the switch argument is in a register.
11206 For n>6 this algorithm may be more compact */
11207 jtablo = newiTempLabel (NULL);
11208 jtabhi = newiTempLabel (NULL);
11210 /* get the condition into accumulator.
11211 Using b as temporary storage, if register push/pop is needed */
11212 aopOp (IC_JTCOND (ic), ic, FALSE);
11213 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11214 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
11215 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
11217 // (MB) what if B is in use???
11218 wassertl(!BINUSE, "B was in use");
11219 emitcode ("mov", "b,%s", l);
11222 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11226 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
11227 emitcode ("movc", "a,@a+pc");
11228 emitcode ("push", "acc");
11231 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
11232 emitcode ("movc", "a,@a+pc");
11233 emitcode ("push", "acc");
11237 /* this scales up to n<=255, but needs two more bytes
11238 and changes dptr */
11239 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
11240 emitcode ("movc", "a,@a+dptr");
11241 emitcode ("push", "acc");
11244 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
11245 emitcode ("movc", "a,@a+dptr");
11246 emitcode ("push", "acc");
11249 emitcode ("ret", "");
11251 /* now generate jump table, LSB */
11252 emitLabel (jtablo);
11253 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11254 jtab = setNextItem (IC_JTLABELS (ic)))
11255 emitcode (".db", "%05d$", jtab->key + 100);
11257 /* now generate jump table, MSB */
11258 emitLabel (jtabhi);
11259 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11260 jtab = setNextItem (IC_JTLABELS (ic)))
11261 emitcode (".db", "%05d$>>8", jtab->key + 100);
11265 /*-----------------------------------------------------------------*/
11266 /* genCast - gen code for casting */
11267 /*-----------------------------------------------------------------*/
11269 genCast (iCode * ic)
11271 operand *result = IC_RESULT (ic);
11272 sym_link *ctype = operandType (IC_LEFT (ic));
11273 sym_link *rtype = operandType (IC_RIGHT (ic));
11274 operand *right = IC_RIGHT (ic);
11277 D (emitcode (";", "genCast"));
11279 /* if they are equivalent then do nothing */
11280 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11283 aopOp (right, ic, FALSE);
11284 aopOp (result, ic, FALSE);
11286 /* if the result is a bit (and not a bitfield) */
11287 if (IS_BIT (OP_SYMBOL (result)->type))
11289 assignBit (result, right);
11293 /* if they are the same size : or less */
11294 if (AOP_SIZE (result) <= AOP_SIZE (right))
11297 /* if they are in the same place */
11298 if (sameRegs (AOP (right), AOP (result)))
11301 /* if they in different places then copy */
11302 size = AOP_SIZE (result);
11307 aopGet (right, offset, FALSE, FALSE),
11314 /* if the result is of type pointer */
11315 if (IS_PTR (ctype))
11319 sym_link *type = operandType (right);
11320 sym_link *etype = getSpec (type);
11322 /* pointer to generic pointer */
11323 if (IS_GENPTR (ctype))
11327 p_type = DCL_TYPE (type);
11331 if (SPEC_SCLS(etype)==S_REGISTER) {
11332 // let's assume it is a generic pointer
11335 /* we have to go by the storage class */
11336 p_type = PTR_TYPE (SPEC_OCLS (etype));
11340 /* the first two bytes are known */
11341 size = GPTRSIZE - 1;
11346 aopGet (right, offset, FALSE, FALSE),
11350 /* the last byte depending on type */
11352 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11357 // pointerTypeToGPByte will have bitched.
11361 sprintf(gpValStr, "#0x%x", gpVal);
11362 aopPut (result, gpValStr, GPTRSIZE - 1);
11367 /* just copy the pointers */
11368 size = AOP_SIZE (result);
11373 aopGet (right, offset, FALSE, FALSE),
11380 /* so we now know that the size of destination is greater
11381 than the size of the source */
11382 /* we move to result for the size of source */
11383 size = AOP_SIZE (right);
11388 aopGet (right, offset, FALSE, FALSE),
11393 /* now depending on the sign of the source && destination */
11394 size = AOP_SIZE (result) - AOP_SIZE (right);
11395 /* if unsigned or not an integral type */
11396 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11399 aopPut (result, zero, offset++);
11403 /* we need to extend the sign :{ */
11404 char *l = aopGet (right, AOP_SIZE (right) - 1,
11407 emitcode ("rlc", "a");
11408 emitcode ("subb", "a,acc");
11410 aopPut (result, "a", offset++);
11413 /* we are done hurray !!!! */
11416 freeAsmop (result, NULL, ic, TRUE);
11417 freeAsmop (right, NULL, ic, TRUE);
11420 /*-----------------------------------------------------------------*/
11421 /* genDjnz - generate decrement & jump if not zero instrucion */
11422 /*-----------------------------------------------------------------*/
11424 genDjnz (iCode * ic, iCode * ifx)
11426 symbol *lbl, *lbl1;
11430 /* if the if condition has a false label
11431 then we cannot save */
11432 if (IC_FALSE (ifx))
11435 /* if the minus is not of the form a = a - 1 */
11436 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11437 !IS_OP_LITERAL (IC_RIGHT (ic)))
11440 if (operandLitValue (IC_RIGHT (ic)) != 1)
11443 /* if the size of this greater than one then no
11445 if (getSize (operandType (IC_RESULT (ic))) > 1)
11448 /* otherwise we can save BIG */
11450 D (emitcode (";", "genDjnz"));
11452 lbl = newiTempLabel (NULL);
11453 lbl1 = newiTempLabel (NULL);
11455 aopOp (IC_RESULT (ic), ic, FALSE);
11457 if (AOP_NEEDSACC(IC_RESULT(ic)))
11459 /* If the result is accessed indirectly via
11460 * the accumulator, we must explicitly write
11461 * it back after the decrement.
11463 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11465 if (strcmp(rByte, "a"))
11467 /* Something is hopelessly wrong */
11468 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11469 __FILE__, __LINE__);
11470 /* We can just give up; the generated code will be inefficient,
11471 * but what the hey.
11473 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11476 emitcode ("dec", "%s", rByte);
11477 aopPut (IC_RESULT (ic), rByte, 0);
11478 emitcode ("jnz", "%05d$", lbl->key + 100);
11480 else if (IS_AOP_PREG (IC_RESULT (ic)))
11482 emitcode ("dec", "%s",
11483 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11484 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11485 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11486 ifx->generated = 1;
11487 emitcode ("jnz", "%05d$", lbl->key + 100);
11491 emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11494 emitcode ("sjmp", "%05d$", lbl1->key + 100);
11496 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11499 if (!ifx->generated)
11500 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11501 ifx->generated = 1;
11505 /*-----------------------------------------------------------------*/
11506 /* genReceive - generate code for a receive iCode */
11507 /*-----------------------------------------------------------------*/
11509 genReceive (iCode * ic)
11511 int size = getSize (operandType (IC_RESULT (ic)));
11514 D (emitcode (";", "genReceive"));
11516 if (ic->argreg == 1)
11517 { /* first parameter */
11518 if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11519 isOperandInPagedSpace (IC_RESULT (ic))) &&
11520 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11521 IS_TRUE_SYMOP (IC_RESULT (ic))))
11524 int receivingA = 0;
11527 for (offset = 0; offset<size; offset++)
11528 if (!strcmp (fReturn[offset], "a"))
11533 if (size==1 || getTempRegs(tempRegs, size-1, ic))
11535 for (offset = size-1; offset>0; offset--)
11536 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11537 emitcode("mov","a,%s", fReturn[0]);
11539 aopOp (IC_RESULT (ic), ic, FALSE);
11541 aopPut (IC_RESULT (ic), "a", offset);
11542 for (offset = 1; offset<size; offset++)
11543 aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset);
11549 if (getTempRegs(tempRegs, size, ic))
11551 for (offset = 0; offset<size; offset++)
11552 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11553 aopOp (IC_RESULT (ic), ic, FALSE);
11554 for (offset = 0; offset<size; offset++)
11555 aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset);
11560 offset = fReturnSizeMCS51 - size;
11563 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11564 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11567 aopOp (IC_RESULT (ic), ic, FALSE);
11568 size = AOP_SIZE (IC_RESULT (ic));
11572 emitcode ("pop", "acc");
11573 aopPut (IC_RESULT (ic), "a", offset++);
11579 aopOp (IC_RESULT (ic), ic, FALSE);
11581 assignResultValue (IC_RESULT (ic), NULL);
11584 else if (ic->argreg > 12)
11585 { /* bit parameters */
11586 if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
11588 aopOp (IC_RESULT (ic), ic, FALSE);
11589 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11590 outBitC(IC_RESULT (ic));
11594 { /* other parameters */
11596 aopOp (IC_RESULT (ic), ic, FALSE);
11597 rb1off = ic->argreg;
11600 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
11605 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11608 /*-----------------------------------------------------------------*/
11609 /* genDummyRead - generate code for dummy read of volatiles */
11610 /*-----------------------------------------------------------------*/
11612 genDummyRead (iCode * ic)
11617 D (emitcode(";", "genDummyRead"));
11619 op = IC_RIGHT (ic);
11620 if (op && IS_SYMOP (op))
11622 aopOp (op, ic, FALSE);
11624 /* if the result is a bit */
11625 if (AOP_TYPE (op) == AOP_CRY)
11626 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11629 /* bit variables done */
11631 size = AOP_SIZE (op);
11635 MOVA (aopGet (op, offset, FALSE, FALSE));
11640 freeAsmop (op, NULL, ic, TRUE);
11644 if (op && IS_SYMOP (op))
11646 aopOp (op, ic, FALSE);
11648 /* if the result is a bit */
11649 if (AOP_TYPE (op) == AOP_CRY)
11650 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11653 /* bit variables done */
11655 size = AOP_SIZE (op);
11659 MOVA (aopGet (op, offset, FALSE, FALSE));
11664 freeAsmop (op, NULL, ic, TRUE);
11668 /*-----------------------------------------------------------------*/
11669 /* genCritical - generate code for start of a critical sequence */
11670 /*-----------------------------------------------------------------*/
11672 genCritical (iCode *ic)
11674 symbol *tlbl = newiTempLabel (NULL);
11676 D (emitcode(";", "genCritical"));
11678 if (IC_RESULT (ic))
11680 aopOp (IC_RESULT (ic), ic, TRUE);
11681 aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
11682 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11683 aopPut (IC_RESULT (ic), zero, 0);
11685 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11689 emitcode ("setb", "c");
11690 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11691 emitcode ("clr", "c");
11693 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11697 /*-----------------------------------------------------------------*/
11698 /* genEndCritical - generate code for end of a critical sequence */
11699 /*-----------------------------------------------------------------*/
11701 genEndCritical (iCode *ic)
11703 D(emitcode("; genEndCritical",""));
11707 aopOp (IC_RIGHT (ic), ic, FALSE);
11708 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11710 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11711 emitcode ("mov", "ea,c");
11715 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11716 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11717 emitcode ("rrc", "a");
11718 emitcode ("mov", "ea,c");
11720 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11724 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11725 emitcode ("mov", "ea,c");
11729 /*-----------------------------------------------------------------*/
11730 /* gen51Code - generate code for 8051 based controllers */
11731 /*-----------------------------------------------------------------*/
11733 gen51Code (iCode * lic)
11737 /* int cseq = 0; */
11739 _G.currentFunc = NULL;
11740 lineHead = lineCurr = NULL;
11742 /* print the allocation information */
11743 if (allocInfo && currFunc)
11744 printAllocInfo (currFunc, codeOutBuf);
11745 /* if debug information required */
11746 if (options.debug && currFunc)
11748 debugFile->writeFunction (currFunc, lic);
11750 /* stack pointer name */
11751 if (options.useXstack)
11757 for (ic = lic; ic; ic = ic->next)
11759 _G.current_iCode = ic;
11761 if (ic->lineno && cln != ic->lineno)
11765 debugFile->writeCLine (ic);
11767 if (!options.noCcodeInAsm) {
11768 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
11769 printCLine(ic->filename, ic->lineno));
11774 if (ic->seqPoint && ic->seqPoint != cseq)
11776 emitcode ("", "; sequence point %d", ic->seqPoint);
11777 cseq = ic->seqPoint;
11780 if (options.iCodeInAsm) {
11781 char regsInUse[80];
11786 for (i=0; i<8; i++) {
11787 sprintf (®sInUse[i],
11788 "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11791 strcpy (regsInUse, "--------");
11792 for (i=0; i < 8; i++) {
11793 if (bitVectBitValue (ic->rMask, i))
11795 int offset = regs8051[i].offset;
11796 regsInUse[offset] = offset + '0'; /* show rMask */
11800 iLine = printILine(ic);
11801 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
11804 /* if the result is marked as
11805 spilt and rematerializable or code for
11806 this has already been generated then
11808 if (resultRemat (ic) || ic->generated)
11811 /* depending on the operation */
11831 /* IPOP happens only when trying to restore a
11832 spilt live range, if there is an ifx statement
11833 following this pop then the if statement might
11834 be using some of the registers being popped which
11835 would destory the contents of the register so
11836 we need to check for this condition and handle it */
11838 ic->next->op == IFX &&
11839 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11840 genIfx (ic->next, ic);
11858 genEndFunction (ic);
11878 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11895 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11899 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11906 /* note these two are xlated by algebraic equivalence
11907 in decorateType() in SDCCast.c */
11908 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11909 "got '>=' or '<=' shouldn't have come here");
11913 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11925 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11929 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11933 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11969 genRightShift (ic);
11972 case GET_VALUE_AT_ADDRESS:
11974 hasInc (IC_LEFT (ic), ic,
11975 getSize (operandType (IC_RESULT (ic)))),
11976 ifxForOp (IC_RESULT (ic), ic) );
11980 if (POINTER_SET (ic))
11982 hasInc (IC_RESULT (ic), ic,
11983 getSize (operandType (IC_RIGHT (ic)))));
12009 addSet (&_G.sendSet, ic);
12012 case DUMMY_READ_VOLATILE:
12021 genEndCritical (ic);
12033 _G.current_iCode = NULL;
12035 /* now we are ready to call the
12036 peep hole optimizer */
12037 if (!options.nopeep)
12038 peepHole (&lineHead);
12040 /* now do the actual printing */
12041 printLine (lineHead, codeOutBuf);