1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for 8051
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
27 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
28 Made everything static
29 -------------------------------------------------------------------------*/
31 #define D(x) do if (options.verboseAsm) {x;} while(0)
37 #include "SDCCglobl.h"
41 #include "SDCCpeeph.h"
45 #include "dbuf_string.h"
47 char *aopLiteral (value * val, int offset);
48 char *aopLiteralLong (value * val, int offset, int size);
51 /* this is the down and dirty file with all kinds of
52 kludgy & hacky stuff. This is what it is all about
53 CODE GENERATION for a specific MCU . some of the
54 routines may be reusable, will have to see */
56 static char *zero = "#0x00";
57 static char *one = "#0x01";
61 {"dpl", "dph", "b", "a"};
62 unsigned fReturnSizeMCS51 = 4; /* shared with ralloc.c */
63 char **fReturn = fReturn8051;
64 static char *accUse[] =
67 static unsigned short rbank = -1;
69 #define REG_WITH_INDEX mcs51_regWithIdx
71 #define AOP(op) op->aop
72 #define AOP_TYPE(op) AOP(op)->type
73 #define AOP_SIZE(op) AOP(op)->size
74 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
75 AOP_TYPE(x) == AOP_R0))
77 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
78 AOP_TYPE(x) == AOP_DPTR || \
81 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
82 (x->aopu.aop_reg[0] == REG_WITH_INDEX(R0_IDX) || \
83 x->aopu.aop_reg[0] == REG_WITH_INDEX(R1_IDX) )))
85 #define SYM_BP(sym) (SPEC_OCLS (sym->etype)->paged ? "_bpx" : "_bp")
87 #define R0INB _G.bu.bs.r0InB
88 #define R1INB _G.bu.bs.r1InB
89 #define OPINB _G.bu.bs.OpInB
90 #define BINUSE _G.bu.BInUse
100 short r0InB : 2;//2 so we can see it overflow
101 short r1InB : 2;//2 so we can see it overflow
102 short OpInB : 2;//2 so we can see it overflow
111 iCode *current_iCode;
116 static char *rb1regs[] = {
117 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7",
118 "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7"
121 extern struct dbuf_s *codeOutBuf;
123 #define RESULTONSTACK(x) \
124 (IC_RESULT(x) && IC_RESULT(x)->aop && \
125 IC_RESULT(x)->aop->type == AOP_STK )
127 #define MOVA(x) mova(x) /* use function to avoid multiple eval */
128 #define MOVB(x) movb(x)
130 #define CLRC emitcode("clr","c")
131 #define SETC emitcode("setb","c")
133 static lineNode *lineHead = NULL;
134 static lineNode *lineCurr = NULL;
136 static unsigned char SLMask[] =
137 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
138 0xE0, 0xC0, 0x80, 0x00};
139 static unsigned char SRMask[] =
140 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
141 0x07, 0x03, 0x01, 0x00};
148 /*-----------------------------------------------------------------*/
149 /* emitcode - writes the code into a file : for now it is simple */
150 /*-----------------------------------------------------------------*/
152 emitcode (const char *inst, const char *fmt,...)
156 const char *lbp, *lb;
158 dbuf_init (&dbuf, INITIAL_INLINEASM);
164 dbuf_append_str (&dbuf, inst);
168 dbuf_append_char (&dbuf, '\t');
169 dbuf_tvprintf (&dbuf, fmt, ap);
174 dbuf_tvprintf (&dbuf, fmt, ap);
177 lbp = lb = dbuf_c_str(&dbuf);
179 while (isspace ((unsigned char)*lbp))
188 lineCurr = (lineCurr ?
189 connectLine (lineCurr, newLineNode (lb)) :
190 (lineHead = newLineNode (lb)));
193 lineCurr->isInline = _G.inLine;
194 lineCurr->isDebug = _G.debugLine;
195 lineCurr->ic = _G.current_iCode;
196 lineCurr->isComment = (*lbp==';');
203 emitLabel (symbol *tlbl)
205 emitcode ("", "%05d$:", tlbl->key + 100);
206 lineCurr->isLabel = 1;
209 /*-----------------------------------------------------------------*/
210 /* mcs51_emitDebuggerSymbol - associate the current code location */
211 /* with a debugger symbol */
212 /*-----------------------------------------------------------------*/
214 mcs51_emitDebuggerSymbol (char * debugSym)
217 emitcode ("", "%s ==.", debugSym);
221 /*-----------------------------------------------------------------*/
222 /* mova - moves specified value into accumulator */
223 /*-----------------------------------------------------------------*/
227 /* do some early peephole optimization */
228 if (!strncmp(x, "a", 2) || !strncmp(x, "acc", 4))
231 /* if it is a literal mov try to get it cheaper */
236 emitcode("mov", "a,%s", x);
239 /*-----------------------------------------------------------------*/
240 /* movb - moves specified value into register b */
241 /*-----------------------------------------------------------------*/
245 /* do some early peephole optimization */
246 if (!strncmp(x, "b", 2))
249 /* if it is a literal mov try to get it cheaper */
252 emitcode("mov","b,%s", rtrackGetLit(x));
256 emitcode("mov","b,%s", x);
259 /*-----------------------------------------------------------------*/
260 /* pushB - saves register B if necessary */
261 /*-----------------------------------------------------------------*/
265 bool pushedB = FALSE;
269 emitcode ("push", "b");
270 // printf("B was in use !\n");
280 /*-----------------------------------------------------------------*/
281 /* popB - restores value of register B if necessary */
282 /*-----------------------------------------------------------------*/
288 emitcode ("pop", "b");
296 /*-----------------------------------------------------------------*/
297 /* pushReg - saves register */
298 /*-----------------------------------------------------------------*/
300 pushReg (int index, bool bits_pushed)
302 regs * reg = REG_WITH_INDEX (index);
303 if (reg->type == REG_BIT)
306 emitcode ("push", "%s", reg->base);
310 emitcode ("push", "%s", reg->dname);
314 /*-----------------------------------------------------------------*/
315 /* popReg - restores register */
316 /*-----------------------------------------------------------------*/
318 popReg (int index, bool bits_popped)
320 regs * reg = REG_WITH_INDEX (index);
321 if (reg->type == REG_BIT)
324 emitcode ("pop", "%s", reg->base);
328 emitcode ("pop", "%s", reg->dname);
332 /*-----------------------------------------------------------------*/
333 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
334 /*-----------------------------------------------------------------*/
336 getFreePtr (iCode * ic, asmop ** aopp, bool result)
341 /* the logic: if r0 & r1 used in the instruction
342 then we are in trouble otherwise */
344 /* first check if r0 & r1 are used by this
345 instruction, in which case we are in trouble */
346 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
347 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
352 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
353 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
355 /* if no usage of r0 then return it */
358 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
359 (*aopp)->type = AOP_R0;
361 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
364 /* if no usage of r1 then return it */
367 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
368 (*aopp)->type = AOP_R1;
370 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R1_IDX);
373 /* now we know they both have usage */
374 /* if r0 not used in this instruction */
377 /* push it if not already pushed */
380 MOVB (REG_WITH_INDEX (R0_IDX)->dname);
383 else if (!_G.r0Pushed)
385 emitcode ("push", "%s",
386 REG_WITH_INDEX (R0_IDX)->dname);
390 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
391 (*aopp)->type = AOP_R0;
393 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
396 /* if r1 not used then */
400 /* push it if not already pushed */
403 MOVB (REG_WITH_INDEX (R1_IDX)->dname);
406 else if (!_G.r1Pushed)
408 emitcode ("push", "%s",
409 REG_WITH_INDEX (R1_IDX)->dname);
413 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
414 (*aopp)->type = AOP_R1;
415 return REG_WITH_INDEX (R1_IDX);
419 /* I said end of world, but not quite end of world yet */
420 /* if this is a result then we can push it on the stack */
423 (*aopp)->type = AOP_STK;
426 /* in the case that result AND left AND right needs a pointer reg
427 we can safely use the result's */
428 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX))
430 (*aopp)->type = AOP_R0;
431 return REG_WITH_INDEX (R0_IDX);
433 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX))
435 (*aopp)->type = AOP_R1;
436 return REG_WITH_INDEX (R1_IDX);
439 /* now this is REALLY the end of the world */
440 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
441 "getFreePtr should never reach here");
446 /*-----------------------------------------------------------------*/
447 /* getTempRegs - initialize an array of pointers to GPR registers */
448 /* that are not in use. Returns 1 if the requested */
449 /* number of registers were available, 0 otherwise. */
450 /*-----------------------------------------------------------------*/
452 getTempRegs(regs **tempRegs, int size, iCode *ic)
459 ic = _G.current_iCode;
465 freeRegs = newBitVect(8);
466 bitVectSetBit (freeRegs, R2_IDX);
467 bitVectSetBit (freeRegs, R3_IDX);
468 bitVectSetBit (freeRegs, R4_IDX);
469 bitVectSetBit (freeRegs, R5_IDX);
470 bitVectSetBit (freeRegs, R6_IDX);
471 bitVectSetBit (freeRegs, R7_IDX);
473 if (IFFUNC_CALLEESAVES(_G.currentFunc->type))
475 bitVect * newfreeRegs;
476 newfreeRegs = bitVectIntersect (freeRegs, _G.currentFunc->regsUsed);
477 freeBitVect(freeRegs);
478 freeRegs = newfreeRegs;
480 freeRegs = bitVectCplAnd (freeRegs, ic->rMask);
483 for (i=0; i<freeRegs->size; i++)
485 if (bitVectBitValue(freeRegs,i))
486 tempRegs[offset++] = REG_WITH_INDEX(i);
489 freeBitVect(freeRegs);
494 freeBitVect(freeRegs);
499 /*-----------------------------------------------------------------*/
500 /* newAsmop - creates a new asmOp */
501 /*-----------------------------------------------------------------*/
503 newAsmop (short type)
507 aop = Safe_calloc (1, sizeof (asmop));
513 /*-----------------------------------------------------------------*/
514 /* pointerCode - returns the code for a pointer type */
515 /*-----------------------------------------------------------------*/
517 pointerCode (sym_link * etype)
520 return PTR_TYPE (SPEC_OCLS (etype));
524 /*-----------------------------------------------------------------*/
525 /* leftRightUseAcc - returns size of accumulator use by operands */
526 /*-----------------------------------------------------------------*/
528 leftRightUseAcc(iCode *ic)
537 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
538 "null iCode pointer");
545 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
548 size = getSize (OP_SYMBOL (op)->type);
553 else if (ic->op == JUMPTABLE)
556 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
559 size = getSize (OP_SYMBOL (op)->type);
567 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
570 size = getSize (OP_SYMBOL (op)->type);
575 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
578 size = getSize (OP_SYMBOL (op)->type);
590 /*-----------------------------------------------------------------*/
591 /* aopForSym - for a true symbol */
592 /*-----------------------------------------------------------------*/
594 aopForSym (iCode * ic, symbol * sym, bool result)
598 bool accuse = leftRightUseAcc (ic) || _G.accInUse;
600 wassertl (ic != NULL, "Got a null iCode");
601 wassertl (sym != NULL, "Got a null symbol");
603 space = SPEC_OCLS (sym->etype);
605 /* if already has one */
608 sym->aop->allocated++;
612 /* assign depending on the storage class */
613 /* if it is on the stack or indirectly addressable */
614 /* space we need to assign either r0 or r1 to it */
615 if (sym->onStack || sym->iaccess)
617 sym->aop = aop = newAsmop (0);
618 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
619 aop->size = getSize (sym->type);
621 /* now assign the address of the variable to
622 the pointer register */
623 if (aop->type != AOP_STK)
627 signed char offset = ((sym->stack < 0) ?
628 ((signed char) (sym->stack - _G.nRegsSaved)) :
629 ((signed char) sym->stack)) & 0xff;
631 if ((abs(offset) <= 3) ||
632 (accuse && (abs(offset) <= 7)))
634 emitcode ("mov", "%s,%s",
635 aop->aopu.aop_ptr->name, SYM_BP (sym));
638 emitcode ("dec", aop->aopu.aop_ptr->name);
643 emitcode ("inc", aop->aopu.aop_ptr->name);
650 emitcode ("push", "acc");
651 emitcode ("mov", "a,%s", SYM_BP (sym));
652 emitcode ("add", "a,#0x%02x", offset & 0xff);
653 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
655 emitcode ("pop", "acc");
660 emitcode ("mov", "%s,#%s",
661 aop->aopu.aop_ptr->name,
664 aop->paged = space->paged;
667 aop->aopu.aop_stk = sym->stack;
671 /* if in bit space */
672 if (IN_BITSPACE (space))
674 sym->aop = aop = newAsmop (AOP_CRY);
675 aop->aopu.aop_dir = sym->rname;
676 aop->size = getSize (sym->type);
679 /* if it is in direct space */
680 if (IN_DIRSPACE (space))
682 //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
683 //printTypeChainRaw(sym->type, NULL);
684 //printf("space = %s\n", space ? space->sname : "NULL");
685 sym->aop = aop = newAsmop (AOP_DIR);
686 aop->aopu.aop_dir = sym->rname;
687 aop->size = getSize (sym->type);
691 /* special case for a function */
692 if (IS_FUNC (sym->type))
694 sym->aop = aop = newAsmop (AOP_IMMD);
695 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
696 aop->size = getSize (sym->type);
700 /* only remaining is far space */
701 /* in which case DPTR gets the address */
702 sym->aop = aop = newAsmop (AOP_DPTR);
703 emitcode ("mov", "dptr,#%s", sym->rname);
704 aop->size = getSize (sym->type);
706 /* if it is in code space */
707 if (IN_CODESPACE (space))
713 /*-----------------------------------------------------------------*/
714 /* aopForRemat - rematerialzes an object */
715 /*-----------------------------------------------------------------*/
717 aopForRemat (symbol * sym)
719 iCode *ic = sym->rematiCode;
720 asmop *aop = newAsmop (AOP_IMMD);
727 val += (int) operandLitValue (IC_RIGHT (ic));
728 else if (ic->op == '-')
729 val -= (int) operandLitValue (IC_RIGHT (ic));
730 else if (IS_CAST_ICODE(ic)) {
731 sym_link *from_type = operandType(IC_RIGHT(ic));
732 aop->aopu.aop_immd.from_cast_remat = 1;
733 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
734 ptr_type = pointerTypeToGPByte (DCL_TYPE(from_type), NULL, NULL);
738 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
743 SNPRINTF (buffer, sizeof(buffer),
745 OP_SYMBOL (IC_LEFT (ic))->rname,
746 val >= 0 ? '+' : '-',
751 strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
754 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
755 /* set immd2 field if required */
756 if (aop->aopu.aop_immd.from_cast_remat)
758 SNPRINTF (buffer, sizeof(buffer), "#0x%02x", ptr_type);
759 aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
765 /*-----------------------------------------------------------------*/
766 /* regsInCommon - two operands have some registers in common */
767 /*-----------------------------------------------------------------*/
769 regsInCommon (operand * op1, operand * op2)
774 /* if they have registers in common */
775 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
778 sym1 = OP_SYMBOL (op1);
779 sym2 = OP_SYMBOL (op2);
781 if (sym1->nRegs == 0 || sym2->nRegs == 0)
784 for (i = 0; i < sym1->nRegs; i++)
790 for (j = 0; j < sym2->nRegs; j++)
795 if (sym2->regs[j] == sym1->regs[i])
803 /*-----------------------------------------------------------------*/
804 /* operandsEqu - equivalent */
805 /*-----------------------------------------------------------------*/
807 operandsEqu (operand * op1, operand * op2)
811 /* if they're not symbols */
812 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
815 sym1 = OP_SYMBOL (op1);
816 sym2 = OP_SYMBOL (op2);
818 /* if both are itemps & one is spilt
819 and the other is not then false */
820 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
821 sym1->isspilt != sym2->isspilt)
824 /* if they are the same */
828 /* if they have the same rname */
829 if (sym1->rname[0] && sym2->rname[0] &&
830 strcmp (sym1->rname, sym2->rname) == 0 &&
831 !(IS_PARM (op2) && IS_ITEMP (op1)))
834 /* if left is a tmp & right is not */
835 if (IS_ITEMP (op1) &&
838 (sym1->usl.spillLoc == sym2))
841 if (IS_ITEMP (op2) &&
845 (sym2->usl.spillLoc == sym1))
851 /*-----------------------------------------------------------------*/
852 /* sameByte - two asmops have the same address at given offsets */
853 /*-----------------------------------------------------------------*/
855 sameByte (asmop * aop1, int off1, asmop * aop2, int off2)
857 if (aop1 == aop2 && off1 == off2)
860 if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
863 if (aop1->type != aop2->type)
866 if (aop1->aopu.aop_reg[off1] != aop2->aopu.aop_reg[off2])
872 /*-----------------------------------------------------------------*/
873 /* sameRegs - two asmops have the same registers */
874 /*-----------------------------------------------------------------*/
876 sameRegs (asmop * aop1, asmop * aop2)
883 if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
886 if (aop1->type != aop2->type)
889 if (aop1->size != aop2->size)
892 for (i = 0; i < aop1->size; i++)
893 if (aop1->aopu.aop_reg[i] != aop2->aopu.aop_reg[i])
899 /*-----------------------------------------------------------------*/
900 /* aopOp - allocates an asmop for an operand : */
901 /*-----------------------------------------------------------------*/
903 aopOp (operand * op, iCode * ic, bool result)
912 /* if this a literal */
913 if (IS_OP_LITERAL (op))
915 op->aop = aop = newAsmop (AOP_LIT);
916 aop->aopu.aop_lit = op->operand.valOperand;
917 aop->size = getSize (operandType (op));
921 /* if already has a asmop then continue */
924 op->aop->allocated++;
928 /* if the underlying symbol has a aop */
929 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
931 op->aop = OP_SYMBOL (op)->aop;
932 op->aop->allocated++;
936 /* if this is a true symbol */
937 if (IS_TRUE_SYMOP (op))
939 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
943 /* this is a temporary : this has
949 e) can be a return use only */
951 sym = OP_SYMBOL (op);
953 /* if the type is a conditional */
954 if (sym->regType == REG_CND)
956 sym->aop = op->aop = aop = newAsmop (AOP_CRY);
957 aop->size = sym->ruonly ? 1 : 0;
961 /* if it is spilt then two situations
963 b) has a spill location */
964 if (sym->isspilt || sym->nRegs == 0)
967 /* rematerialize it NOW */
970 sym->aop = op->aop = aop = aopForRemat (sym);
971 aop->size = getSize (sym->type);
978 sym->aop = op->aop = aop = newAsmop (AOP_ACC);
979 aop->size = getSize (sym->type);
980 for (i = 0; i < 2; i++)
981 aop->aopu.aop_str[i] = accUse[i];
989 sym->aop = op->aop = aop = newAsmop (AOP_STR);
990 aop->size = getSize (sym->type);
991 for (i = 0; i < fReturnSizeMCS51; i++)
992 aop->aopu.aop_str[i] = fReturn[i];
996 if (sym->usl.spillLoc)
998 asmop *oldAsmOp = NULL;
1000 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1002 /* force a new aop if sizes differ */
1003 oldAsmOp = sym->usl.spillLoc->aop;
1004 sym->usl.spillLoc->aop = NULL;
1006 sym->aop = op->aop = aop =
1007 aopForSym (ic, sym->usl.spillLoc, result);
1008 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1010 /* Don't reuse the new aop, go with the last one */
1011 sym->usl.spillLoc->aop = oldAsmOp;
1013 aop->size = getSize (sym->type);
1017 /* else must be a dummy iTemp */
1018 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1019 aop->size = getSize (sym->type);
1023 /* if the type is a bit register */
1024 if (sym->regType == REG_BIT)
1026 sym->aop = op->aop = aop = newAsmop (AOP_CRY);
1027 aop->size = sym->nRegs;//1???
1028 aop->aopu.aop_reg[0] = sym->regs[0];
1029 aop->aopu.aop_dir = sym->regs[0]->name;
1033 /* must be in a register */
1034 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1035 aop->size = sym->nRegs;
1036 for (i = 0; i < sym->nRegs; i++)
1037 aop->aopu.aop_reg[i] = sym->regs[i];
1040 /*-----------------------------------------------------------------*/
1041 /* freeAsmop - free up the asmop given to an operand */
1042 /*----------------------------------------------------------------*/
1044 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1061 /* depending on the asmop type only three cases need work
1062 AOP_R0, AOP_R1 & AOP_STK */
1068 emitcode ("mov", "r0,b");
1071 else if (_G.r0Pushed)
1075 emitcode ("pop", "ar0");
1079 bitVectUnSetBit (ic->rUsed, R0_IDX);
1085 emitcode ("mov", "r1,b");
1088 else if (_G.r1Pushed)
1092 emitcode ("pop", "ar1");
1096 bitVectUnSetBit (ic->rUsed, R1_IDX);
1102 int stk = aop->aopu.aop_stk + aop->size - 1;
1103 bitVectUnSetBit (ic->rUsed, R0_IDX);
1104 bitVectUnSetBit (ic->rUsed, R1_IDX);
1106 getFreePtr (ic, &aop, FALSE);
1110 emitcode ("mov", "a,_bp");
1111 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1112 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1116 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1121 emitcode ("pop", "acc");
1122 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1125 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1128 freeAsmop (op, NULL, ic, TRUE);
1131 emitcode ("pop", "ar1");
1136 emitcode ("pop", "ar0");
1144 /* all other cases just dealloc */
1150 OP_SYMBOL (op)->aop = NULL;
1151 /* if the symbol has a spill */
1153 SPIL_LOC (op)->aop = NULL;
1158 /*------------------------------------------------------------------*/
1159 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
1160 /* pop r0 or r1 off stack if pushed */
1161 /*------------------------------------------------------------------*/
1163 freeForBranchAsmop (operand * op)
1175 if (!aop->allocated)
1183 emitcode ("mov", "r0,b");
1185 else if (_G.r0Pushed)
1187 emitcode ("pop", "ar0");
1194 emitcode ("mov", "r1,b");
1196 else if (_G.r1Pushed)
1198 emitcode ("pop", "ar1");
1205 int stk = aop->aopu.aop_stk + aop->size - 1;
1207 emitcode ("mov", "b,r0");
1210 emitcode ("mov", "a,_bp");
1211 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1212 emitcode ("mov", "r0,a");
1216 emitcode ("mov", "r0,_bp");
1221 emitcode ("pop", "acc");
1222 emitcode ("mov", "@r0,a");
1225 emitcode ("dec", "r0");
1227 emitcode ("mov", "r0,b");
1233 /*-----------------------------------------------------------------*/
1234 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
1235 /* clobber the accumulator */
1236 /*-----------------------------------------------------------------*/
1238 aopGetUsesAcc (operand * oper, int offset)
1240 asmop * aop = AOP (oper);
1242 if (offset > (aop->size - 1))
1260 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1271 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1277 /* Error case --- will have been caught already */
1283 /*-------------------------------------------------------------------*/
1284 /* aopGet - for fetching value of the aop */
1285 /*-------------------------------------------------------------------*/
1287 aopGet (operand * oper, int offset, bool bit16, bool dname)
1289 asmop * aop = AOP (oper);
1291 /* offset is greater than
1293 if (offset > (aop->size - 1) &&
1294 aop->type != AOP_LIT)
1297 /* depending on type */
1305 /* if we need to increment it */
1306 while (offset > aop->coff)
1308 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1312 while (offset < aop->coff)
1314 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1321 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1322 return (dname ? "acc" : "a");
1324 SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1325 return Safe_strdup(buffer);
1328 if (aop->code && aop->coff==0 && offset>=1) {
1329 emitcode ("mov", "a,#0x%02x", offset);
1330 emitcode ("movc", "a,@a+dptr");
1331 return (dname ? "acc" : "a");
1334 while (offset > aop->coff)
1336 emitcode ("inc", "dptr");
1340 while (offset < aop->coff)
1342 emitcode ("lcall", "__decdptr");
1349 emitcode ("clr", "a");
1350 emitcode ("movc", "a,@a+dptr");
1354 emitcode ("movx", "a,@dptr");
1356 return (dname ? "acc" : "a");
1359 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1361 SNPRINTF(buffer, sizeof(buffer),
1362 "%s",aop->aopu.aop_immd.aop_immd2);
1366 SNPRINTF(buffer, sizeof(buffer),
1367 "#%s", aop->aopu.aop_immd.aop_immd1);
1371 SNPRINTF (buffer, sizeof(buffer),
1373 aop->aopu.aop_immd.aop_immd1,
1378 SNPRINTF (buffer, sizeof(buffer),
1380 aop->aopu.aop_immd.aop_immd1);
1382 return Safe_strdup(buffer);
1385 if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
1387 SNPRINTF (buffer, sizeof(buffer),
1389 aop->aopu.aop_dir, offset * 8);
1393 SNPRINTF (buffer, sizeof(buffer),
1400 SNPRINTF (buffer, sizeof(buffer),
1405 return Safe_strdup(buffer);
1409 return aop->aopu.aop_reg[offset]->dname;
1411 return aop->aopu.aop_reg[offset]->name;
1414 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1415 emitcode ("clr", "a");
1416 emitcode ("rlc", "a");
1417 return (dname ? "acc" : "a");
1420 if (!offset && dname)
1422 return aop->aopu.aop_str[offset];
1425 return aopLiteral (aop->aopu.aop_lit, offset);
1429 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1433 return aop->aopu.aop_str[offset];
1437 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1438 "aopget got unsupported aop->type");
1442 /*-----------------------------------------------------------------*/
1443 /* aopPutUsesAcc - indicates ahead of time whether aopPut() will */
1444 /* clobber the accumulator */
1445 /*-----------------------------------------------------------------*/
1447 aopPutUsesAcc (operand * oper, const char *s, int offset)
1449 asmop * aop = AOP (oper);
1451 if (offset > (aop->size - 1))
1461 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1467 return ((aop->paged) || (*s == '@'));
1471 return (!aop->aopu.aop_dir || strcmp(s, aop->aopu.aop_dir));
1479 /* Error case --- will have been caught already */
1485 /*-----------------------------------------------------------------*/
1486 /* aopPut - puts a string for a aop and indicates if acc is in use */
1487 /*-----------------------------------------------------------------*/
1489 aopPut (operand * result, const char *s, int offset)
1491 bool bvolatile = isOperandVolatile (result, FALSE);
1492 bool accuse = FALSE;
1493 asmop * aop = AOP (result);
1495 if (aop->size && offset > (aop->size - 1))
1497 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1498 "aopPut got offset > aop->size");
1502 /* will assign value to value */
1503 /* depending on where it is ofcourse */
1507 MOVA (s); /* read s in case it was volatile */
1512 if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1514 SNPRINTF (buffer, sizeof(buffer),
1516 aop->aopu.aop_dir, offset * 8);
1520 SNPRINTF (buffer, sizeof(buffer),
1522 aop->aopu.aop_dir, offset);
1526 SNPRINTF (buffer, sizeof(buffer),
1531 if (strcmp (buffer, s) || bvolatile)
1533 emitcode ("mov", "%s,%s", buffer, s);
1535 if (!strcmp (buffer, "acc"))
1542 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1543 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1546 strcmp (s, "r0") == 0 ||
1547 strcmp (s, "r1") == 0 ||
1548 strcmp (s, "r2") == 0 ||
1549 strcmp (s, "r3") == 0 ||
1550 strcmp (s, "r4") == 0 ||
1551 strcmp (s, "r5") == 0 ||
1552 strcmp (s, "r6") == 0 ||
1553 strcmp (s, "r7") == 0)
1555 emitcode ("mov", "%s,%s",
1556 aop->aopu.aop_reg[offset]->dname, s);
1560 emitcode ("mov", "%s,%s",
1561 aop->aopu.aop_reg[offset]->name, s);
1569 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1570 "aopPut writing to code space");
1574 while (offset > aop->coff)
1577 emitcode ("inc", "dptr");
1580 while (offset < aop->coff)
1583 emitcode ("lcall", "__decdptr");
1588 /* if not in accumulator */
1591 emitcode ("movx", "@dptr,a");
1596 while (offset > aop->coff)
1599 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1601 while (offset < aop->coff)
1604 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1611 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1616 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1618 else if (strcmp (s, "r0") == 0 ||
1619 strcmp (s, "r1") == 0 ||
1620 strcmp (s, "r2") == 0 ||
1621 strcmp (s, "r3") == 0 ||
1622 strcmp (s, "r4") == 0 ||
1623 strcmp (s, "r5") == 0 ||
1624 strcmp (s, "r6") == 0 ||
1625 strcmp (s, "r7") == 0)
1628 SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1629 emitcode ("mov", "@%s,%s",
1630 aop->aopu.aop_ptr->name, buffer);
1634 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1639 if (strcmp (s, "a") == 0)
1641 emitcode ("push", "acc");
1646 emitcode ("push", "acc");
1648 else if (strcmp (s, "r0") == 0 ||
1649 strcmp (s, "r1") == 0 ||
1650 strcmp (s, "r2") == 0 ||
1651 strcmp (s, "r3") == 0 ||
1652 strcmp (s, "r4") == 0 ||
1653 strcmp (s, "r5") == 0 ||
1654 strcmp (s, "r6") == 0 ||
1655 strcmp (s, "r7") == 0)
1658 SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1659 emitcode ("push", buffer);
1663 emitcode ("push", s);
1669 /* if result no bit variable */
1670 if (!aop->aopu.aop_dir)
1672 assert (!strcmp (s, "c"));
1673 /* inefficient: move carry into A and use jz/jnz */
1674 emitcode ("clr", "a");
1675 emitcode ("rlc", "a");
1679 emitcode ("clr", "%s", aop->aopu.aop_dir);
1681 emitcode ("setb", "%s", aop->aopu.aop_dir);
1682 else if (!strcmp (s, "c"))
1683 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1684 else if (strcmp (s, aop->aopu.aop_dir))
1687 /* set C, if a >= 1 */
1688 emitcode ("add", "a,#0xff");
1689 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1695 if (strcmp (aop->aopu.aop_str[offset], s) || bvolatile)
1696 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1702 if (!offset && (strcmp (s, "acc") == 0) && !bvolatile)
1705 if (strcmp (aop->aopu.aop_str[offset], s) && !bvolatile)
1706 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1710 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1711 "aopPut got unsupported aop->type");
1720 /*-----------------------------------------------------------------*/
1721 /* pointToEnd :- points to the last byte of the operand */
1722 /*-----------------------------------------------------------------*/
1724 pointToEnd (asmop * aop)
1730 aop->coff = count = (aop->size - 1);
1736 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1740 emitcode ("inc", "dptr");
1747 /*-----------------------------------------------------------------*/
1748 /* reAdjustPreg - points a register back to where it should */
1749 /*-----------------------------------------------------------------*/
1751 reAdjustPreg (asmop * aop)
1753 if ((aop->coff==0) || (aop->size <= 1))
1761 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1766 emitcode ("lcall", "__decdptr");
1773 /*-----------------------------------------------------------------*/
1774 /* opIsGptr: returns non-zero if the passed operand is */
1775 /* a generic pointer type. */
1776 /*-----------------------------------------------------------------*/
1778 opIsGptr (operand * op)
1780 sym_link *type = operandType (op);
1782 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1789 /*-----------------------------------------------------------------*/
1790 /* getDataSize - get the operand data size */
1791 /*-----------------------------------------------------------------*/
1793 getDataSize (operand * op)
1796 size = AOP_SIZE (op);
1797 if (size == GPTRSIZE)
1799 sym_link *type = operandType (op);
1800 if (IS_GENPTR (type))
1802 /* generic pointer; arithmetic operations
1803 * should ignore the high byte (pointer type).
1811 /*-----------------------------------------------------------------*/
1812 /* outAcc - output Acc */
1813 /*-----------------------------------------------------------------*/
1815 outAcc (operand * result)
1818 size = getDataSize (result);
1821 aopPut (result, "a", 0);
1824 /* unsigned or positive */
1827 aopPut (result, zero, offset++);
1832 /*-----------------------------------------------------------------*/
1833 /* outBitC - output a bit C */
1834 /*-----------------------------------------------------------------*/
1836 outBitC (operand * result)
1838 /* if the result is bit */
1839 if (AOP_TYPE (result) == AOP_CRY)
1841 if (!OP_SYMBOL (result)->ruonly)
1842 aopPut (result, "c", 0);
1846 emitcode ("clr", "a");
1847 emitcode ("rlc", "a");
1852 /*-----------------------------------------------------------------*/
1853 /* toBoolean - emit code for orl a,operator(sizeop) */
1854 /*-----------------------------------------------------------------*/
1856 toBoolean (operand * oper)
1858 int size = AOP_SIZE (oper) - 1;
1860 bool AccUsed = FALSE;
1863 while (!AccUsed && size--)
1865 AccUsed |= aopGetUsesAcc(oper, offset++);
1868 size = AOP_SIZE (oper) - 1;
1870 MOVA (aopGet (oper, 0, FALSE, FALSE));
1871 if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1874 emitcode("mov", "b,a");
1877 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1878 emitcode ("orl", "b,a");
1880 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1881 emitcode ("orl", "a,b");
1888 emitcode ("orl", "a,%s",
1889 aopGet (oper, offset++, FALSE, FALSE));
1894 /*-----------------------------------------------------------------*/
1895 /* toCarry - make boolean and move into carry */
1896 /*-----------------------------------------------------------------*/
1898 toCarry (operand * oper)
1900 /* if the operand is a literal then
1901 we know what the value is */
1902 if (AOP_TYPE (oper) == AOP_LIT)
1904 if ((int) operandLitValue (oper))
1909 else if (AOP_TYPE (oper) == AOP_CRY)
1911 emitcode ("mov", "c,%s", oper->aop->aopu.aop_dir);
1915 /* or the operand into a */
1917 /* set C, if a >= 1 */
1918 emitcode ("add", "a,#0xff");
1922 /*-----------------------------------------------------------------*/
1923 /* assignBit - assign operand to bit operand */
1924 /*-----------------------------------------------------------------*/
1926 assignBit (operand * result, operand * right)
1928 /* if the right side is a literal then
1929 we know what the value is */
1930 if (AOP_TYPE (right) == AOP_LIT)
1932 if ((int) operandLitValue (right))
1933 aopPut (result, one, 0);
1935 aopPut (result, zero, 0);
1940 aopPut (result, "c", 0);
1945 /*-------------------------------------------------------------------*/
1946 /* xch_a_aopGet - for exchanging acc with value of the aop */
1947 /*-------------------------------------------------------------------*/
1949 xch_a_aopGet (operand * oper, int offset, bool bit16, bool dname)
1953 if (aopGetUsesAcc (oper, offset))
1955 emitcode("mov", "b,a");
1956 MOVA (aopGet (oper, offset, bit16, dname));
1957 emitcode("xch", "a,b");
1958 aopPut (oper, "a", offset);
1959 emitcode("xch", "a,b");
1964 l = aopGet (oper, offset, bit16, dname);
1965 emitcode("xch", "a,%s", l);
1971 /*-----------------------------------------------------------------*/
1972 /* genNot - generate code for ! operation */
1973 /*-----------------------------------------------------------------*/
1979 D (emitcode (";", "genNot"));
1981 /* assign asmOps to operand & result */
1982 aopOp (IC_LEFT (ic), ic, FALSE);
1983 aopOp (IC_RESULT (ic), ic, TRUE);
1985 /* if in bit space then a special case */
1986 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1988 /* if left==result then cpl bit */
1989 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1991 emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1995 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1996 emitcode ("cpl", "c");
1997 outBitC (IC_RESULT (ic));
2002 toBoolean (IC_LEFT (ic));
2004 /* set C, if a == 0 */
2005 tlbl = newiTempLabel (NULL);
2006 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
2008 outBitC (IC_RESULT (ic));
2011 /* release the aops */
2012 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2013 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2017 /*-----------------------------------------------------------------*/
2018 /* genCpl - generate code for complement */
2019 /*-----------------------------------------------------------------*/
2026 sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
2028 D(emitcode (";", "genCpl"));
2030 /* assign asmOps to operand & result */
2031 aopOp (IC_LEFT (ic), ic, FALSE);
2032 aopOp (IC_RESULT (ic), ic, TRUE);
2034 /* special case if in bit space */
2035 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2039 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
2040 (SPEC_USIGN (letype) && IS_CHAR (letype)))
2042 /* promotion rules are responsible for this strange result:
2043 bit -> int -> ~int -> bit
2044 uchar -> int -> ~int -> bit
2046 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
2050 tlbl=newiTempLabel(NULL);
2051 l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
2052 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
2053 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
2054 IS_AOP_PREG (IC_LEFT (ic)))
2056 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
2061 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
2064 outBitC (IC_RESULT(ic));
2068 size = AOP_SIZE (IC_RESULT (ic));
2071 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2073 emitcode ("cpl", "a");
2074 aopPut (IC_RESULT (ic), "a", offset++);
2079 /* release the aops */
2080 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2081 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2084 /*-----------------------------------------------------------------*/
2085 /* genUminusFloat - unary minus for floating points */
2086 /*-----------------------------------------------------------------*/
2088 genUminusFloat (operand * op, operand * result)
2090 int size, offset = 0;
2093 D (emitcode (";", "genUminusFloat"));
2095 /* for this we just copy and then flip the bit */
2097 size = AOP_SIZE (op) - 1;
2102 aopGet (op, offset, FALSE, FALSE),
2107 l = aopGet (op, offset, FALSE, FALSE);
2110 emitcode ("cpl", "acc.7");
2111 aopPut (result, "a", offset);
2114 /*-----------------------------------------------------------------*/
2115 /* genUminus - unary minus code generation */
2116 /*-----------------------------------------------------------------*/
2118 genUminus (iCode * ic)
2123 D (emitcode (";", "genUminus"));
2126 aopOp (IC_LEFT (ic), ic, FALSE);
2127 aopOp (IC_RESULT (ic), ic, TRUE);
2129 /* if both in bit space then special
2131 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2132 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2135 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2136 emitcode ("cpl", "c");
2137 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2141 optype = operandType (IC_LEFT (ic));
2143 /* if float then do float stuff */
2144 if (IS_FLOAT (optype))
2146 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2150 /* otherwise subtract from zero */
2151 size = AOP_SIZE (IC_LEFT (ic));
2155 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2156 if (!strcmp (l, "a"))
2160 emitcode ("cpl", "a");
2161 emitcode ("addc", "a,#0");
2167 emitcode ("clr", "a");
2168 emitcode ("subb", "a,%s", l);
2170 aopPut (IC_RESULT (ic), "a", offset++);
2173 /* if any remaining bytes in the result */
2174 /* we just need to propagate the sign */
2175 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2177 emitcode ("rlc", "a");
2178 emitcode ("subb", "a,acc");
2180 aopPut (IC_RESULT (ic), "a", offset++);
2184 /* release the aops */
2185 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2186 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2189 /*-----------------------------------------------------------------*/
2190 /* saveRegisters - will look for a call and save the registers */
2191 /*-----------------------------------------------------------------*/
2193 saveRegisters (iCode * lic)
2200 for (ic = lic; ic; ic = ic->next)
2201 if (ic->op == CALL || ic->op == PCALL)
2206 fprintf (stderr, "found parameter push with no function call\n");
2210 /* if the registers have been saved already or don't need to be then
2214 if (IS_SYMOP(IC_LEFT(ic)) &&
2215 (IFFUNC_CALLEESAVES (OP_SYMBOL (IC_LEFT (ic))->type) ||
2216 IFFUNC_ISNAKED (OP_SYM_TYPE (IC_LEFT (ic)))))
2219 /* save the registers in use at this time but skip the
2220 ones for the result */
2221 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2222 mcs51_rUmaskForOp (IC_RESULT(ic)));
2225 if (options.useXstack)
2227 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2228 int nBits = bitVectnBitsOn (rsavebits);
2229 int count = bitVectnBitsOn (rsave);
2233 count = count - nBits + 1;
2234 /* remove all but the first bits as they are pushed all at once */
2235 rsave = bitVectCplAnd (rsave, rsavebits);
2236 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2238 freeBitVect (rsavebits);
2242 regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2243 if (reg->type == REG_BIT)
2245 emitcode ("mov", "a,%s", reg->base);
2249 emitcode ("mov", "a,%s", reg->name);
2251 emitcode ("mov", "r0,%s", spname);
2252 emitcode ("inc", "%s", spname);// allocate before use
2253 emitcode ("movx", "@r0,a");
2254 if (bitVectBitValue (rsave, R0_IDX))
2255 emitcode ("mov", "r0,a");
2257 else if (count != 0)
2259 if (bitVectBitValue (rsave, R0_IDX))
2261 emitcode ("push", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2263 emitcode ("mov", "r0,%s", spname);
2265 emitcode ("add", "a,#%d", count);
2266 emitcode ("mov", "%s,a", spname);
2267 for (i = 0; i < mcs51_nRegs; i++)
2269 if (bitVectBitValue (rsave, i))
2271 regs * reg = REG_WITH_INDEX (i);
2274 emitcode ("pop", "acc");
2275 emitcode ("push", "acc");
2277 else if (reg->type == REG_BIT)
2279 emitcode ("mov", "a,%s", reg->base);
2283 emitcode ("mov", "a,%s", reg->name);
2285 emitcode ("movx", "@r0,a");
2288 emitcode ("inc", "r0");
2292 if (bitVectBitValue (rsave, R0_IDX))
2294 emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2300 bool bits_pushed = FALSE;
2301 for (i = 0; i < mcs51_nRegs; i++)
2303 if (bitVectBitValue (rsave, i))
2305 bits_pushed = pushReg (i, bits_pushed);
2309 freeBitVect (rsave);
2312 /*-----------------------------------------------------------------*/
2313 /* unsaveRegisters - pop the pushed registers */
2314 /*-----------------------------------------------------------------*/
2316 unsaveRegisters (iCode * ic)
2321 /* restore the registers in use at this time but skip the
2322 ones for the result */
2323 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2324 mcs51_rUmaskForOp (IC_RESULT(ic)));
2326 if (options.useXstack)
2328 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2329 int nBits = bitVectnBitsOn (rsavebits);
2330 int count = bitVectnBitsOn (rsave);
2334 count = count - nBits + 1;
2335 /* remove all but the first bits as they are popped all at once */
2336 rsave = bitVectCplAnd (rsave, rsavebits);
2337 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2339 freeBitVect (rsavebits);
2343 regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2344 emitcode ("mov", "r0,%s", spname);
2345 emitcode ("dec", "r0");
2346 emitcode ("movx", "a,@r0");
2347 if (reg->type == REG_BIT)
2349 emitcode ("mov", "%s,a", reg->base);
2353 emitcode ("mov", "%s,a", reg->name);
2355 emitcode ("dec", "%s", spname);
2357 else if (count != 0)
2359 emitcode ("mov", "r0,%s", spname);
2360 for (i = mcs51_nRegs; i >= 0; i--)
2362 if (bitVectBitValue (rsave, i))
2364 regs * reg = REG_WITH_INDEX (i);
2365 emitcode ("dec", "r0");
2366 emitcode ("movx", "a,@r0");
2369 emitcode ("push", "acc");
2371 else if (reg->type == REG_BIT)
2373 emitcode ("mov", "%s,a", reg->base);
2377 emitcode ("mov", "%s,a", reg->name);
2381 emitcode ("mov", "%s,r0", spname);
2382 if (bitVectBitValue (rsave, R0_IDX))
2384 emitcode ("pop", "ar0");
2390 bool bits_popped = FALSE;
2391 for (i = mcs51_nRegs; i >= 0; i--)
2393 if (bitVectBitValue (rsave, i))
2395 bits_popped = popReg (i, bits_popped);
2399 freeBitVect (rsave);
2403 /*-----------------------------------------------------------------*/
2405 /*-----------------------------------------------------------------*/
2407 pushSide (operand * oper, int size)
2412 char *l = aopGet (oper, offset++, FALSE, TRUE);
2413 if (AOP_TYPE (oper) != AOP_REG &&
2414 AOP_TYPE (oper) != AOP_DIR &&
2418 emitcode ("push", "acc");
2422 emitcode ("push", "%s", l);
2427 /*-----------------------------------------------------------------*/
2428 /* assignResultValue - also indicates if acc is in use afterwards */
2429 /*-----------------------------------------------------------------*/
2431 assignResultValue (operand * oper, operand * func)
2434 int size = AOP_SIZE (oper);
2435 bool accuse = FALSE;
2436 bool pushedA = FALSE;
2438 if (func && IS_BIT (OP_SYM_ETYPE (func)))
2444 if ((size > 3) && aopPutUsesAcc (oper, fReturn[offset], offset))
2446 emitcode ("push", "acc");
2451 if ((offset == 3) && pushedA)
2452 emitcode ("pop", "acc");
2453 accuse |= aopPut (oper, fReturn[offset], offset);
2460 /*-----------------------------------------------------------------*/
2461 /* genXpush - pushes onto the external stack */
2462 /*-----------------------------------------------------------------*/
2464 genXpush (iCode * ic)
2466 asmop *aop = newAsmop (0);
2468 int size, offset = 0;
2470 D (emitcode (";", "genXpush"));
2472 aopOp (IC_LEFT (ic), ic, FALSE);
2473 r = getFreePtr (ic, &aop, FALSE);
2475 size = AOP_SIZE (IC_LEFT (ic));
2479 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2480 emitcode ("mov", "%s,%s", r->name, spname);
2481 emitcode ("inc", "%s", spname); // allocate space first
2482 emitcode ("movx", "@%s,a", r->name);
2486 // allocate space first
2487 emitcode ("mov", "%s,%s", r->name, spname);
2489 emitcode ("add", "a,#%d", size);
2490 emitcode ("mov", "%s,a", spname);
2494 MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2495 emitcode ("movx", "@%s,a", r->name);
2496 emitcode ("inc", "%s", r->name);
2500 freeAsmop (NULL, aop, ic, TRUE);
2501 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2504 /*-----------------------------------------------------------------*/
2505 /* genIpush - generate code for pushing this gets a little complex */
2506 /*-----------------------------------------------------------------*/
2508 genIpush (iCode * ic)
2510 int size, offset = 0;
2514 D (emitcode (";", "genIpush"));
2516 /* if this is not a parm push : ie. it is spill push
2517 and spill push is always done on the local stack */
2521 /* and the item is spilt then do nothing */
2522 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2525 aopOp (IC_LEFT (ic), ic, FALSE);
2526 size = AOP_SIZE (IC_LEFT (ic));
2527 /* push it on the stack */
2530 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2536 emitcode ("push", "%s", l);
2541 /* this is a parameter push: in this case we call
2542 the routine to find the call and save those
2543 registers that need to be saved */
2546 /* if use external stack then call the external
2547 stack pushing routine */
2548 if (options.useXstack)
2554 /* then do the push */
2555 aopOp (IC_LEFT (ic), ic, FALSE);
2557 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2558 size = AOP_SIZE (IC_LEFT (ic));
2562 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2563 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2564 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR)
2566 if (strcmp (l, prev) || *l == '@')
2568 emitcode ("push", "acc");
2572 emitcode ("push", "%s", l);
2577 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2580 /*-----------------------------------------------------------------*/
2581 /* genIpop - recover the registers: can happen only for spilling */
2582 /*-----------------------------------------------------------------*/
2584 genIpop (iCode * ic)
2588 D (emitcode (";", "genIpop"));
2590 /* if the temp was not pushed then */
2591 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2594 aopOp (IC_LEFT (ic), ic, FALSE);
2595 size = AOP_SIZE (IC_LEFT (ic));
2596 offset = (size - 1);
2599 emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2603 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2606 /*-----------------------------------------------------------------*/
2607 /* saveRBank - saves an entire register bank on the stack */
2608 /*-----------------------------------------------------------------*/
2610 saveRBank (int bank, iCode * ic, bool pushPsw)
2613 int count = 8 + (pushPsw ? 1 : 0);
2617 if (options.useXstack)
2621 /* Assume r0 is available for use. */
2622 r = REG_WITH_INDEX (R0_IDX);
2627 r = getFreePtr (ic, &aop, FALSE);
2629 // allocate space first
2630 emitcode ("mov", "%s,%s", r->name, spname);
2632 emitcode ("add", "a,#%d", count);
2633 emitcode ("mov", "%s,a", spname);
2636 for (i = 0; i < 8; i++)
2638 if (options.useXstack)
2640 emitcode ("mov", "a,(%s+%d)",
2641 regs8051[i].base, 8 * bank + regs8051[i].offset);
2642 emitcode ("movx", "@%s,a", r->name);
2644 emitcode ("inc", "%s", r->name);
2647 emitcode ("push", "(%s+%d)",
2648 regs8051[i].base, 8 * bank + regs8051[i].offset);
2653 if (options.useXstack)
2655 emitcode ("mov", "a,psw");
2656 emitcode ("movx", "@%s,a", r->name);
2660 emitcode ("push", "psw");
2663 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2668 freeAsmop (NULL, aop, ic, TRUE);
2677 /*-----------------------------------------------------------------*/
2678 /* unsaveRBank - restores the register bank from stack */
2679 /*-----------------------------------------------------------------*/
2681 unsaveRBank (int bank, iCode * ic, bool popPsw)
2687 if (options.useXstack)
2691 /* Assume r0 is available for use. */
2692 r = REG_WITH_INDEX (R0_IDX);;
2697 r = getFreePtr (ic, &aop, FALSE);
2699 emitcode ("mov", "%s,%s", r->name, spname);
2704 if (options.useXstack)
2706 emitcode ("dec", "%s", r->name);
2707 emitcode ("movx", "a,@%s", r->name);
2708 emitcode ("mov", "psw,a");
2712 emitcode ("pop", "psw");
2716 for (i = 7; i >= 0; i--)
2718 if (options.useXstack)
2720 emitcode ("dec", "%s", r->name);
2721 emitcode ("movx", "a,@%s", r->name);
2722 emitcode ("mov", "(%s+%d),a",
2723 regs8051[i].base, 8 * bank + regs8051[i].offset);
2727 emitcode ("pop", "(%s+%d)",
2728 regs8051[i].base, 8 * bank + regs8051[i].offset);
2732 if (options.useXstack)
2734 emitcode ("mov", "%s,%s", spname, r->name);
2739 freeAsmop (NULL, aop, ic, TRUE);
2743 /*-----------------------------------------------------------------*/
2744 /* genSend - gen code for SEND */
2745 /*-----------------------------------------------------------------*/
2746 static void genSend(set *sendSet)
2751 /* first we do all bit parameters */
2752 for (sic = setFirstItem (sendSet); sic;
2753 sic = setNextItem (sendSet))
2755 if (sic->argreg > 12)
2757 int bit = sic->argreg-13;
2759 aopOp (IC_LEFT (sic), sic, FALSE);
2761 /* if left is a literal then
2762 we know what the value is */
2763 if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2765 if (((int) operandLitValue (IC_LEFT (sic))))
2766 emitcode ("setb", "b[%d]", bit);
2768 emitcode ("clr", "b[%d]", bit);
2773 toCarry (IC_LEFT (sic));
2774 emitcode ("mov", "b[%d],c", bit);
2779 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2785 saveRegisters (setFirstItem (sendSet));
2786 emitcode ("mov", "bits,b");
2789 /* then we do all other parameters */
2790 for (sic = setFirstItem (sendSet); sic;
2791 sic = setNextItem (sendSet))
2793 if (sic->argreg <= 12)
2795 int size, offset = 0;
2796 aopOp (IC_LEFT (sic), sic, FALSE);
2797 size = AOP_SIZE (IC_LEFT (sic));
2799 if (sic->argreg == 1)
2803 char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2804 if (strcmp (l, fReturn[offset]))
2806 emitcode ("mov", "%s,%s", fReturn[offset], l);
2815 emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2816 aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2820 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2825 /*-----------------------------------------------------------------*/
2826 /* selectRegBank - emit code to select the register bank */
2827 /*-----------------------------------------------------------------*/
2829 selectRegBank (short bank, bool keepFlags)
2831 /* if f.e. result is in carry */
2834 emitcode ("anl", "psw,#0xE7");
2836 emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2840 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2844 /*-----------------------------------------------------------------*/
2845 /* genCall - generates a call statement */
2846 /*-----------------------------------------------------------------*/
2848 genCall (iCode * ic)
2852 // bool restoreBank = FALSE;
2853 bool swapBanks = FALSE;
2854 bool accuse = FALSE;
2855 bool accPushed = FALSE;
2856 bool resultInF0 = FALSE;
2857 bool assignResultGenerated = FALSE;
2859 D (emitcode (";", "genCall"));
2861 dtype = operandType (IC_LEFT (ic));
2862 etype = getSpec(dtype);
2863 /* if send set is not empty then assign */
2866 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2867 genSend(reverseSet(_G.sendSet));
2869 genSend(_G.sendSet);
2874 /* if we are calling a not _naked function that is not using
2875 the same register bank then we need to save the
2876 destination registers on the stack */
2877 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2878 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2879 !IFFUNC_ISISR (dtype))
2884 /* if caller saves & we have not saved then */
2890 emitcode ("mov", "psw,#0x%02x",
2891 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2895 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2897 if (IFFUNC_CALLEESAVES(dtype))
2899 werror (E_BANKED_WITH_CALLEESAVES);
2903 char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2904 OP_SYMBOL (IC_LEFT (ic))->rname :
2905 OP_SYMBOL (IC_LEFT (ic))->name);
2907 emitcode ("mov", "r0,#%s", l);
2908 emitcode ("mov", "r1,#(%s >> 8)", l);
2909 emitcode ("mov", "r2,#(%s >> 16)", l);
2910 emitcode ("lcall", "__sdcc_banked_call");
2915 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2916 OP_SYMBOL (IC_LEFT (ic))->rname :
2917 OP_SYMBOL (IC_LEFT (ic))->name));
2922 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2925 /* if we need assign a result value */
2926 if ((IS_ITEMP (IC_RESULT (ic)) &&
2927 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2928 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2929 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2930 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2931 IS_TRUE_SYMOP (IC_RESULT (ic)))
2935 aopOp (IC_RESULT (ic), ic, FALSE);
2938 accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2939 assignResultGenerated = TRUE;
2941 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2944 /* adjust the stack for parameters if required */
2948 if (ic->parmBytes > 3)
2952 emitcode ("push", "acc");
2955 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2956 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2957 !assignResultGenerated)
2959 emitcode ("mov", "F0,c");
2963 emitcode ("mov", "a,%s", spname);
2964 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2965 emitcode ("mov", "%s,a", spname);
2967 /* unsaveRegisters from xstack needs acc, but */
2968 /* unsaveRegisters from stack needs this popped */
2969 if (accPushed && !options.useXstack)
2971 emitcode ("pop", "acc");
2976 for (i = 0; i < ic->parmBytes; i++)
2977 emitcode ("dec", "%s", spname);
2980 /* if we had saved some registers then unsave them */
2981 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2983 if (accuse && !accPushed && options.useXstack)
2985 /* xstack needs acc, but doesn't touch normal stack */
2986 emitcode ("push", "acc");
2989 unsaveRegisters (ic);
2992 // /* if register bank was saved then pop them */
2994 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2996 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
2999 emitcode ("mov", "c,F0");
3001 aopOp (IC_RESULT (ic), ic, FALSE);
3002 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3003 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3007 emitcode ("pop", "acc");
3010 /*-----------------------------------------------------------------*/
3011 /* genPcall - generates a call by pointer statement */
3012 /*-----------------------------------------------------------------*/
3014 genPcall (iCode * ic)
3018 symbol *rlbl = newiTempLabel (NULL);
3019 // bool restoreBank=FALSE;
3020 bool swapBanks = FALSE;
3021 bool resultInF0 = FALSE;
3023 D (emitcode (";", "genPcall"));
3025 dtype = operandType (IC_LEFT (ic))->next;
3026 etype = getSpec(dtype);
3027 /* if caller saves & we have not saved then */
3031 /* if we are calling a not _naked function that is not using
3032 the same register bank then we need to save the
3033 destination registers on the stack */
3034 if (currFunc && dtype && !IFFUNC_ISNAKED (dtype) &&
3035 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
3036 !IFFUNC_ISISR (dtype))
3038 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3039 // restoreBank=TRUE;
3041 // need caution message to user here
3044 if (IS_LITERAL (etype))
3046 /* if send set is not empty then assign */
3049 genSend(reverseSet(_G.sendSet));
3055 emitcode ("mov", "psw,#0x%02x",
3056 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3059 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT (getSpec(dtype)))
3061 if (IFFUNC_CALLEESAVES (dtype))
3063 werror (E_BANKED_WITH_CALLEESAVES);
3067 char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
3069 emitcode ("mov", "r0,#%s", l);
3070 emitcode ("mov", "r1,#(%s >> 8)", l);
3071 emitcode ("mov", "r2,#(%s >> 16)", l);
3072 emitcode ("lcall", "__sdcc_banked_call");
3077 emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
3082 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT (getSpec(dtype)))
3084 if (IFFUNC_CALLEESAVES (dtype))
3086 werror (E_BANKED_WITH_CALLEESAVES);
3090 aopOp (IC_LEFT (ic), ic, FALSE);
3094 /* what if aopGet needs r0 or r1 ??? */
3095 emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3096 emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3097 emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3101 int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
3102 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3103 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3104 emitcode ("mov", "0x%02x,%s", reg, aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3107 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3109 /* if send set is not empty then assign */
3112 genSend(reverseSet(_G.sendSet));
3118 emitcode ("mov", "psw,#0x%02x",
3119 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3123 emitcode ("lcall", "__sdcc_banked_call");
3126 else if (_G.sendSet)
3128 /* push the return address on to the stack */
3129 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
3130 emitcode ("push", "acc");
3131 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
3132 emitcode ("push", "acc");
3134 /* now push the calling address */
3135 aopOp (IC_LEFT (ic), ic, FALSE);
3137 pushSide (IC_LEFT (ic), FPTRSIZE);
3139 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3141 /* if send set is not empty the assign */
3144 genSend(reverseSet(_G.sendSet));
3150 emitcode ("mov", "psw,#0x%02x",
3151 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3155 emitcode ("ret", "");
3158 else /* the send set is empty */
3161 /* now get the calling address into dptr */
3162 aopOp (IC_LEFT (ic), ic, FALSE);
3164 l = aopGet (IC_LEFT (ic), 0, FALSE, FALSE);
3165 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3167 emitcode ("mov", "r0,%s", l);
3168 l = aopGet (IC_LEFT (ic), 1, FALSE, FALSE);
3169 emitcode ("mov", "dph,%s", l);
3170 emitcode ("mov", "dpl,r0");
3174 emitcode ("mov", "dpl,%s", l);
3175 l = aopGet (IC_LEFT (ic), 1, FALSE, FALSE);
3176 emitcode ("mov", "dph,%s", l);
3179 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3183 emitcode ("mov", "psw,#0x%02x",
3184 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3188 emitcode ("lcall", "__sdcc_call_dptr");
3193 selectRegBank (FUNC_REGBANK (currFunc->type), IS_BIT (etype));
3196 /* if we need assign a result value */
3197 if ((IS_ITEMP (IC_RESULT (ic)) &&
3198 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3199 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3200 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3201 IS_TRUE_SYMOP (IC_RESULT (ic)))
3205 aopOp (IC_RESULT (ic), ic, FALSE);
3208 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3210 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3213 /* adjust the stack for parameters if required */
3217 if (ic->parmBytes > 3)
3219 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3220 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3222 emitcode ("mov", "F0,c");
3226 emitcode ("mov", "a,%s", spname);
3227 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3228 emitcode ("mov", "%s,a", spname);
3231 for (i = 0; i < ic->parmBytes; i++)
3232 emitcode ("dec", "%s", spname);
3235 // /* if register bank was saved then unsave them */
3237 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3239 /* if we had saved some registers then unsave them */
3240 if (ic->regsSaved && !IFFUNC_CALLEESAVES (dtype))
3241 unsaveRegisters (ic);
3243 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3246 emitcode ("mov", "c,F0");
3248 aopOp (IC_RESULT (ic), ic, FALSE);
3249 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3250 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3254 /*-----------------------------------------------------------------*/
3255 /* resultRemat - result is rematerializable */
3256 /*-----------------------------------------------------------------*/
3258 resultRemat (iCode * ic)
3260 if (SKIP_IC (ic) || ic->op == IFX)
3263 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3265 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3266 if (sym->remat && !POINTER_SET (ic))
3273 /*-----------------------------------------------------------------*/
3274 /* inExcludeList - return 1 if the string is in exclude Reg list */
3275 /*-----------------------------------------------------------------*/
3277 regsCmp(void *p1, void *p2)
3279 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3283 inExcludeList (char *s)
3285 const char *p = setFirstItem(options.excludeRegsSet);
3287 if (p == NULL || STRCASECMP(p, "none") == 0)
3291 return isinSetWith(options.excludeRegsSet, s, regsCmp);
3294 /*-----------------------------------------------------------------*/
3295 /* genFunction - generated code for function entry */
3296 /*-----------------------------------------------------------------*/
3298 genFunction (iCode * ic)
3300 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3302 bool switchedPSW = FALSE;
3303 int calleesaves_saved_register = -1;
3304 int stackAdjust = sym->stack;
3305 int accIsFree = sym->recvSize < 4;
3306 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3307 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3310 /* create the function header */
3311 emitcode (";", "-----------------------------------------");
3312 emitcode (";", " function %s", sym->name);
3313 emitcode (";", "-----------------------------------------");
3315 emitcode ("", "%s:", sym->rname);
3316 lineCurr->isLabel = 1;
3317 ftype = operandType (IC_LEFT (ic));
3318 _G.currentFunc = sym;
3320 if (IFFUNC_ISNAKED(ftype))
3322 emitcode(";", "naked function: no prologue.");
3326 /* here we need to generate the equates for the
3327 register bank if required */
3328 if (FUNC_REGBANK (ftype) != rbank)
3332 rbank = FUNC_REGBANK (ftype);
3333 for (i = 0; i < mcs51_nRegs; i++)
3335 if (regs8051[i].type != REG_BIT)
3337 if (strcmp (regs8051[i].base, "0") == 0)
3338 emitcode ("", "%s = 0x%02x",
3340 8 * rbank + regs8051[i].offset);
3342 emitcode ("", "%s = %s + 0x%02x",
3345 8 * rbank + regs8051[i].offset);
3350 /* if this is an interrupt service routine then
3351 save acc, b, dpl, dph */
3352 if (IFFUNC_ISISR (sym->type))
3356 rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), sym->regsUsed);
3357 if (IFFUNC_HASFCALL(sym->type) || !bitVectIsZero (rsavebits))
3359 emitcode ("push", "bits");
3362 freeBitVect (rsavebits);
3364 if (!inExcludeList ("acc"))
3365 emitcode ("push", "acc");
3366 if (!inExcludeList ("b"))
3367 emitcode ("push", "b");
3368 if (!inExcludeList ("dpl"))
3369 emitcode ("push", "dpl");
3370 if (!inExcludeList ("dph"))
3371 emitcode ("push", "dph");
3372 /* if this isr has no bank i.e. is going to
3373 run with bank 0 , then we need to save more
3375 if (!FUNC_REGBANK (sym->type))
3379 /* if this function does not call any other
3380 function then we can be economical and
3381 save only those registers that are used */
3382 if (!IFFUNC_HASFCALL(sym->type))
3384 /* if any registers used */
3387 /* save the registers used */
3388 for (i = 0; i < sym->regsUsed->size; i++)
3390 if (bitVectBitValue (sym->regsUsed, i))
3397 /* this function has a function call. We cannot
3398 determine register usage so we will have to push the
3400 saveRBank (0, ic, FALSE);
3401 if (options.parms_in_bank1) {
3402 for (i=0; i < 8 ; i++ ) {
3403 emitcode ("push","%s",rb1regs[i]);
3410 /* This ISR uses a non-zero bank.
3412 * We assume that the bank is available for our
3415 * However, if this ISR calls a function which uses some
3416 * other bank, we must save that bank entirely.
3418 unsigned long banksToSave = 0;
3420 if (IFFUNC_HASFCALL(sym->type))
3423 #define MAX_REGISTER_BANKS 4
3428 for (i = ic; i; i = i->next)
3430 if (i->op == ENDFUNCTION)
3432 /* we got to the end OK. */
3440 dtype = operandType (IC_LEFT(i));
3442 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3444 /* Mark this bank for saving. */
3445 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3447 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3451 banksToSave |= (1 << FUNC_REGBANK(dtype));
3454 /* And note that we don't need to do it in
3462 /* This is a mess; we have no idea what
3463 * register bank the called function might
3466 * The only thing I can think of to do is
3467 * throw a warning and hope.
3469 werror(W_FUNCPTR_IN_USING_ISR);
3473 if (banksToSave && options.useXstack)
3475 /* Since we aren't passing it an ic,
3476 * saveRBank will assume r0 is available to abuse.
3478 * So switch to our (trashable) bank now, so
3479 * the caller's R0 isn't trashed.
3481 emitcode ("push", "psw");
3482 emitcode ("mov", "psw,#0x%02x",
3483 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3487 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3489 if (banksToSave & (1 << ix))
3491 saveRBank(ix, NULL, FALSE);
3495 // TODO: this needs a closer look
3496 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3499 /* Set the register bank to the desired value if nothing else */
3500 /* has done so yet. */
3503 emitcode ("push", "psw");
3504 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3509 /* This is a non-ISR function. The caller has already switched register */
3510 /* banks, if necessary, so just handle the callee-saves option. */
3512 /* if callee-save to be used for this function
3513 then save the registers being used in this function */
3514 if (IFFUNC_CALLEESAVES(sym->type))
3518 /* if any registers used */
3521 bool bits_pushed = FALSE;
3522 /* save the registers used */
3523 for (i = 0; i < sym->regsUsed->size; i++)
3525 if (bitVectBitValue (sym->regsUsed, i))
3527 /* remember one saved register for later usage */
3528 if (calleesaves_saved_register < 0)
3529 calleesaves_saved_register = i;
3530 bits_pushed = pushReg (i, bits_pushed);
3540 if (options.useXstack)
3542 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3544 emitcode ("mov", "r0,%s", spname);
3545 emitcode ("inc", "%s", spname);
3546 emitcode ("xch", "a,_bpx");
3547 emitcode ("movx", "@r0,a");
3548 emitcode ("inc", "r0");
3549 emitcode ("mov", "a,r0");
3550 emitcode ("xch", "a,_bpx");
3554 emitcode ("push", "_bp"); /* save the callers stack */
3555 emitcode ("mov", "_bp,sp");
3560 if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3562 /* set up the stack */
3563 emitcode ("push", "_bp"); /* save the callers stack */
3564 emitcode ("mov", "_bp,sp");
3569 /* For some cases it is worthwhile to perform a RECEIVE iCode */
3570 /* before setting up the stack frame completely. */
3571 if (ric && ric->argreg == 1 && IC_RESULT (ric))
3573 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3577 if (rsym && rsym->regType == REG_CND)
3579 if (rsym && (rsym->accuse || rsym->ruonly))
3581 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3582 rsym = rsym->usl.spillLoc;
3585 /* If the RECEIVE operand immediately spills to the first entry on the */
3586 /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3587 /* rather than the usual @r0/r1 machinations. */
3588 if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3592 _G.current_iCode = ric;
3593 D(emitcode ("; genReceive",""));
3594 for (ofs=0; ofs < sym->recvSize; ofs++)
3596 if (!strcmp (fReturn[ofs], "a"))
3597 emitcode ("push", "acc");
3599 emitcode ("push", fReturn[ofs]);
3601 stackAdjust -= sym->recvSize;
3604 assert (stackAdjust>=0);
3607 _G.current_iCode = ic;
3611 /* If the RECEIVE operand is 4 registers, we can do the moves now */
3612 /* to free up the accumulator. */
3613 else if (rsym && rsym->nRegs && sym->recvSize == 4)
3617 _G.current_iCode = ric;
3618 D(emitcode ("; genReceive",""));
3619 for (ofs=0; ofs < sym->recvSize; ofs++)
3621 emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3623 _G.current_iCode = ic;
3629 /* adjust the stack for the function */
3632 int i = stackAdjust;
3634 werror (W_STACK_OVERFLOW, sym->name);
3636 if (i > 3 && accIsFree)
3638 emitcode ("mov", "a,sp");
3639 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3640 emitcode ("mov", "sp,a");
3644 /* The accumulator is not free, so we will need another register */
3645 /* to clobber. No need to worry about a possible conflict with */
3646 /* the above early RECEIVE optimizations since they would have */
3647 /* freed the accumulator if they were generated. */
3649 if (IFFUNC_CALLEESAVES(sym->type))
3651 /* if it's a callee-saves function we need a saved register */
3652 if (calleesaves_saved_register >= 0)
3654 emitcode ("mov", "%s,a", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3655 emitcode ("mov", "a,sp");
3656 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3657 emitcode ("mov", "sp,a");
3658 emitcode ("mov", "a,%s", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3661 /* do it the hard way */
3663 emitcode ("inc", "sp");
3667 /* not callee-saves, we can clobber r0 */
3668 emitcode ("mov", "r0,a");
3669 emitcode ("mov", "a,sp");
3670 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3671 emitcode ("mov", "sp,a");
3672 emitcode ("mov", "a,r0");
3677 emitcode ("inc", "sp");
3682 char i = ((char) sym->xstack & 0xff);
3684 if (i > 3 && accIsFree)
3686 emitcode ("mov", "a,_spx");
3687 emitcode ("add", "a,#0x%02x", i & 0xff);
3688 emitcode ("mov", "_spx,a");
3692 emitcode ("push", "acc");
3693 emitcode ("mov", "a,_spx");
3694 emitcode ("add", "a,#0x%02x", i & 0xff);
3695 emitcode ("mov", "_spx,a");
3696 emitcode ("pop", "acc");
3701 emitcode ("inc", "_spx");
3705 /* if critical function then turn interrupts off */
3706 if (IFFUNC_ISCRITICAL (ftype))
3708 symbol *tlbl = newiTempLabel (NULL);
3709 emitcode ("setb", "c");
3710 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3711 emitcode ("clr", "c");
3713 emitcode ("push", "psw"); /* save old ea via c in psw */
3717 /*-----------------------------------------------------------------*/
3718 /* genEndFunction - generates epilogue for functions */
3719 /*-----------------------------------------------------------------*/
3721 genEndFunction (iCode * ic)
3723 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3724 lineNode *lnp = lineCurr;
3726 bitVect *regsUsedPrologue;
3727 bitVect *regsUnneeded;
3730 _G.currentFunc = NULL;
3731 if (IFFUNC_ISNAKED(sym->type))
3733 emitcode(";", "naked function: no epilogue.");
3734 if (options.debug && currFunc)
3735 debugFile->writeEndFunction (currFunc, ic, 0);
3739 if (IFFUNC_ISCRITICAL (sym->type))
3741 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3743 emitcode ("rlc", "a"); /* save c in a */
3744 emitcode ("pop", "psw"); /* restore ea via c in psw */
3745 emitcode ("mov", "ea,c");
3746 emitcode ("rrc", "a"); /* restore c from a */
3750 emitcode ("pop", "psw"); /* restore ea via c in psw */
3751 emitcode ("mov", "ea,c");
3755 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3757 if (options.useXstack)
3761 emitcode ("mov", "sp,_bp");
3762 emitcode ("pop", "_bp");
3764 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3766 emitcode ("xch", "a,_bpx");
3767 emitcode ("mov", "r0,a");
3768 emitcode ("dec", "r0");
3769 emitcode ("movx", "a,@r0");
3770 emitcode ("xch", "a,_bpx");
3771 emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3774 else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3777 emitcode ("mov", "sp,_bp");
3778 emitcode ("pop", "_bp");
3782 /* restore the register bank */
3783 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3785 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3786 || !options.useXstack)
3788 /* Special case of ISR using non-zero bank with useXstack
3791 emitcode ("pop", "psw");
3795 if (IFFUNC_ISISR (sym->type))
3799 /* now we need to restore the registers */
3800 /* if this isr has no bank i.e. is going to
3801 run with bank 0 , then we need to save more
3803 if (!FUNC_REGBANK (sym->type))
3806 /* if this function does not call any other
3807 function then we can be economical and
3808 save only those registers that are used */
3809 if (!IFFUNC_HASFCALL(sym->type))
3811 /* if any registers used */
3814 /* save the registers used */
3815 for (i = sym->regsUsed->size; i >= 0; i--)
3817 if (bitVectBitValue (sym->regsUsed, i))
3824 if (options.parms_in_bank1) {
3825 for (i = 7 ; i >= 0 ; i-- ) {
3826 emitcode ("pop","%s",rb1regs[i]);
3829 /* this function has a function call. We cannot
3830 determine register usage so we will have to pop the
3832 unsaveRBank (0, ic, FALSE);
3837 /* This ISR uses a non-zero bank.
3839 * Restore any register banks saved by genFunction
3842 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3845 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3847 if (savedBanks & (1 << ix))
3849 unsaveRBank(ix, NULL, FALSE);
3853 if (options.useXstack)
3855 /* Restore bank AFTER calling unsaveRBank,
3856 * since it can trash r0.
3858 emitcode ("pop", "psw");
3862 if (!inExcludeList ("dph"))
3863 emitcode ("pop", "dph");
3864 if (!inExcludeList ("dpl"))
3865 emitcode ("pop", "dpl");
3866 if (!inExcludeList ("b"))
3867 emitcode ("pop", "b");
3868 if (!inExcludeList ("acc"))
3869 emitcode ("pop", "acc");
3871 rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), sym->regsUsed);
3872 if (IFFUNC_HASFCALL(sym->type) || !bitVectIsZero (rsavebits))
3873 emitcode ("pop", "bits");
3874 freeBitVect (rsavebits);
3876 /* if debug then send end of function */
3877 if (options.debug && currFunc)
3879 debugFile->writeEndFunction (currFunc, ic, 1);
3882 emitcode ("reti", "");
3886 if (IFFUNC_CALLEESAVES(sym->type))
3890 /* if any registers used */
3893 /* save the registers used */
3894 for (i = sym->regsUsed->size; i >= 0; i--)
3896 if (bitVectBitValue (sym->regsUsed, i) ||
3897 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3898 emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
3901 else if (mcs51_ptrRegReq)
3903 emitcode ("pop", "%s", REG_WITH_INDEX (R1_IDX)->dname);
3904 emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
3909 /* if debug then send end of function */
3910 if (options.debug && currFunc)
3912 debugFile->writeEndFunction (currFunc, ic, 1);
3915 if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3917 emitcode ("ljmp", "__sdcc_banked_ret");
3921 emitcode ("ret", "");
3925 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3928 /* If this was an interrupt handler using bank 0 that called another */
3929 /* function, then all registers must be saved; nothing to optimized. */
3930 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3931 && !FUNC_REGBANK(sym->type))
3934 /* There are no push/pops to optimize if not callee-saves or ISR */
3935 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3938 /* If there were stack parameters, we cannot optimize without also */
3939 /* fixing all of the stack offsets; this is too dificult to consider. */
3940 if (FUNC_HASSTACKPARM(sym->type))
3943 /* Compute the registers actually used */
3944 regsUsed = newBitVect (mcs51_nRegs);
3945 regsUsedPrologue = newBitVect (mcs51_nRegs);
3948 if (lnp->ic && lnp->ic->op == FUNCTION)
3949 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3951 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3953 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3954 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3961 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3962 && !bitVectBitValue (regsUsed, CND_IDX))
3964 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3965 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3966 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3967 bitVectUnSetBit (regsUsed, CND_IDX);
3970 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3972 /* If this was an interrupt handler that called another function */
3973 /* function, then assume A, B, DPH, & DPL may be modified by it. */
3974 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3976 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3977 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3978 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3979 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3980 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3983 /* Remove the unneeded push/pops */
3984 regsUnneeded = newBitVect (mcs51_nRegs);
3987 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3989 if (!strncmp(lnp->line, "push", 4))
3991 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3992 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3994 connectLine (lnp->prev, lnp->next);
3995 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3998 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
4000 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
4001 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4003 connectLine (lnp->prev, lnp->next);
4004 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4011 for (idx = 0; idx < regsUnneeded->size; idx++)
4012 if (bitVectBitValue (regsUnneeded, idx))
4013 emitcode (";", "eliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
4015 freeBitVect (regsUnneeded);
4016 freeBitVect (regsUsed);
4017 freeBitVect (regsUsedPrologue);
4020 /*-----------------------------------------------------------------*/
4021 /* genRet - generate code for return statement */
4022 /*-----------------------------------------------------------------*/
4026 int size, offset = 0, pushed = 0;
4028 D (emitcode (";", "genRet"));
4030 /* if we have no return value then
4031 just generate the "ret" */
4035 /* we have something to return then
4036 move the return value into place */
4037 aopOp (IC_LEFT (ic), ic, FALSE);
4038 size = AOP_SIZE (IC_LEFT (ic));
4040 if (IS_BIT(_G.currentFunc->etype))
4042 if (!(IS_SYMOP (IC_LEFT (ic)) && OP_SYMBOL (IC_LEFT (ic))->ruonly))
4043 toCarry (IC_LEFT (ic));
4050 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
4053 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
4054 emitcode ("push", "%s", l);
4059 l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
4060 if (strcmp (fReturn[offset], l))
4061 emitcode ("mov", "%s,%s", fReturn[offset++], l);
4068 if (strcmp (fReturn[pushed], "a"))
4069 emitcode ("pop", fReturn[pushed]);
4071 emitcode ("pop", "acc");
4074 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
4077 /* generate a jump to the return label
4078 if the next is not the return statement */
4079 if (!(ic->next && ic->next->op == LABEL &&
4080 IC_LABEL (ic->next) == returnLabel))
4082 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
4086 /*-----------------------------------------------------------------*/
4087 /* genLabel - generates a label */
4088 /*-----------------------------------------------------------------*/
4090 genLabel (iCode * ic)
4092 /* special case never generate */
4093 if (IC_LABEL (ic) == entryLabel)
4096 emitLabel (IC_LABEL (ic));
4099 /*-----------------------------------------------------------------*/
4100 /* genGoto - generates a ljmp */
4101 /*-----------------------------------------------------------------*/
4103 genGoto (iCode * ic)
4105 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
4108 /*-----------------------------------------------------------------*/
4109 /* findLabelBackwards: walks back through the iCode chain looking */
4110 /* for the given label. Returns number of iCode instructions */
4111 /* between that label and given ic. */
4112 /* Returns zero if label not found. */
4113 /*-----------------------------------------------------------------*/
4115 findLabelBackwards (iCode * ic, int key)
4124 /* If we have any pushes or pops, we cannot predict the distance.
4125 I don't like this at all, this should be dealt with in the
4127 if (ic->op == IPUSH || ic->op == IPOP) {
4131 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4140 /*-----------------------------------------------------------------*/
4141 /* genPlusIncr :- does addition with increment if possible */
4142 /*-----------------------------------------------------------------*/
4144 genPlusIncr (iCode * ic)
4146 unsigned int icount;
4147 unsigned int size = getDataSize (IC_RESULT (ic));
4149 /* will try to generate an increment */
4150 /* if the right side is not a literal
4152 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4155 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4157 D(emitcode (";","genPlusIncr"));
4159 /* if increment >=16 bits in register or direct space */
4160 if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG ||
4161 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4162 (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4163 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4164 !isOperandVolatile (IC_RESULT (ic), FALSE) &&
4172 /* If the next instruction is a goto and the goto target
4173 * is < 10 instructions previous to this, we can generate
4174 * jumps straight to that target.
4176 if (ic->next && ic->next->op == GOTO
4177 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4178 && labelRange <= 10)
4180 D (emitcode (";", "tail increment optimized (range %d)", labelRange));
4181 tlbl = IC_LABEL (ic->next);
4186 tlbl = newiTempLabel (NULL);
4189 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4190 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4191 IS_AOP_PREG (IC_RESULT (ic)))
4192 emitcode ("cjne", "%s,#0x00,%05d$",
4193 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4197 emitcode ("clr", "a");
4198 emitcode ("cjne", "a,%s,%05d$",
4199 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4203 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4206 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4207 IS_AOP_PREG (IC_RESULT (ic)))
4208 emitcode ("cjne", "%s,#0x00,%05d$",
4209 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4212 emitcode ("cjne", "a,%s,%05d$",
4213 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4216 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4220 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4221 IS_AOP_PREG (IC_RESULT (ic)))
4222 emitcode ("cjne", "%s,#0x00,%05d$",
4223 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4227 emitcode ("cjne", "a,%s,%05d$",
4228 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4231 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4241 /* if result is dptr */
4242 if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
4243 (AOP_SIZE (IC_RESULT (ic)) == 2) &&
4244 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
4245 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
4247 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4253 if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
4256 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0);
4257 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1);
4259 emitcode ("inc", "dptr");
4264 /* if the literal value of the right hand side
4265 is greater than 4 then it is not worth it */
4269 /* if the sizes are greater than 1 then we cannot */
4270 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4271 AOP_SIZE (IC_LEFT (ic)) > 1)
4274 /* we can if the aops of the left & result match or
4275 if they are in registers and the registers are the
4277 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4281 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4282 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4283 aopPut (IC_RESULT (ic), "a", 0);
4289 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4298 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4299 emitcode ("inc", "a");
4300 aopPut (IC_RESULT (ic), "a", 0);
4307 /*-----------------------------------------------------------------*/
4308 /* outBitAcc - output a bit in acc */
4309 /*-----------------------------------------------------------------*/
4311 outBitAcc (operand * result)
4313 symbol *tlbl = newiTempLabel (NULL);
4314 /* if the result is a bit */
4315 if (AOP_TYPE (result) == AOP_CRY)
4317 aopPut (result, "a", 0);
4321 emitcode ("jz", "%05d$", tlbl->key + 100);
4322 emitcode ("mov", "a,%s", one);
4328 /*-----------------------------------------------------------------*/
4329 /* genPlusBits - generates code for addition of two bits */
4330 /*-----------------------------------------------------------------*/
4332 genPlusBits (iCode * ic)
4334 D (emitcode (";", "genPlusBits"));
4336 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4337 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4339 symbol *lbl = newiTempLabel (NULL);
4340 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4341 emitcode ("cpl", "c");
4343 outBitC (IC_RESULT (ic));
4347 emitcode ("clr", "a");
4348 emitcode ("rlc", "a");
4349 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4350 emitcode ("addc", "a,%s", zero);
4351 outAcc (IC_RESULT (ic));
4356 /* This is the original version of this code.
4358 * This is being kept around for reference,
4359 * because I am not entirely sure I got it right...
4362 adjustArithmeticResult (iCode * ic)
4364 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4365 AOP_SIZE (IC_LEFT (ic)) == 3 &&
4366 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4367 aopPut (IC_RESULT (ic),
4368 aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4371 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4372 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4373 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4374 aopPut (IC_RESULT (ic),
4375 aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4378 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4379 AOP_SIZE (IC_LEFT (ic)) < 3 &&
4380 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4381 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4382 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4385 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4386 aopPut (IC_RESULT (ic), buffer, 2);
4390 /* This is the pure and virtuous version of this code.
4391 * I'm pretty certain it's right, but not enough to toss the old
4395 adjustArithmeticResult (iCode * ic)
4397 if (opIsGptr (IC_RESULT (ic)) &&
4398 opIsGptr (IC_LEFT (ic)) &&
4399 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4401 aopPut (IC_RESULT (ic),
4402 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4406 if (opIsGptr (IC_RESULT (ic)) &&
4407 opIsGptr (IC_RIGHT (ic)) &&
4408 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4410 aopPut (IC_RESULT (ic),
4411 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4415 if (opIsGptr (IC_RESULT (ic)) &&
4416 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4417 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4418 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4419 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4422 SNPRINTF (buffer, sizeof(buffer),
4423 "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4424 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4429 /*-----------------------------------------------------------------*/
4430 /* genPlus - generates code for addition */
4431 /*-----------------------------------------------------------------*/
4433 genPlus (iCode * ic)
4435 int size, offset = 0;
4438 bool swappedLR = FALSE;
4439 operand *leftOp, *rightOp;
4442 D (emitcode (";", "genPlus"));
4444 /* special cases :- */
4446 aopOp (IC_LEFT (ic), ic, FALSE);
4447 aopOp (IC_RIGHT (ic), ic, FALSE);
4448 aopOp (IC_RESULT (ic), ic, TRUE);
4450 /* if literal, literal on the right or
4451 if left requires ACC or right is already
4453 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4454 (AOP_NEEDSACC (IC_LEFT (ic))) ||
4455 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4457 operand *t = IC_RIGHT (ic);
4458 IC_RIGHT (ic) = IC_LEFT (ic);
4463 /* if both left & right are in bit
4465 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4466 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4472 /* if left in bit space & right literal */
4473 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4474 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4476 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4477 /* if result in bit space */
4478 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4480 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4481 emitcode ("cpl", "c");
4482 outBitC (IC_RESULT (ic));
4486 size = getDataSize (IC_RESULT (ic));
4489 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4490 emitcode ("addc", "a,%s", zero);
4491 aopPut (IC_RESULT (ic), "a", offset++);
4497 /* if I can do an increment instead
4498 of add then GOOD for ME */
4499 if (genPlusIncr (ic) == TRUE)
4502 size = getDataSize (IC_RESULT (ic));
4503 leftOp = IC_LEFT(ic);
4504 rightOp = IC_RIGHT(ic);
4507 /* if this is an add for an array access
4508 at a 256 byte boundary */
4510 && AOP_TYPE (op) == AOP_IMMD
4512 && IS_SPEC (OP_SYM_ETYPE (op))
4513 && SPEC_ABSA (OP_SYM_ETYPE (op))
4514 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4517 D(emitcode ("; genPlus aligned array",""));
4518 aopPut (IC_RESULT (ic),
4519 aopGet (rightOp, 0, FALSE, FALSE),
4522 if( 1 == getDataSize (IC_RIGHT (ic)) )
4524 aopPut (IC_RESULT (ic),
4525 aopGet (leftOp, 1, FALSE, FALSE),
4530 MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4531 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4532 aopPut (IC_RESULT (ic), "a", 1);
4537 /* if the lower bytes of a literal are zero skip the addition */
4538 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4540 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4541 (skip_bytes+1 < size))
4546 D(emitcode ("; genPlus shortcut",""));
4551 if( offset >= skip_bytes )
4553 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4556 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4558 emitcode("xch", "a,b");
4559 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4560 emitcode (add, "a,b");
4563 else if (aopGetUsesAcc (leftOp, offset))
4565 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4566 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4570 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4571 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4573 aopPut (IC_RESULT (ic), "a", offset);
4574 add = "addc"; /* further adds must propagate carry */
4578 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4579 isOperandVolatile (IC_RESULT (ic), FALSE))
4582 aopPut (IC_RESULT (ic),
4583 aopGet (leftOp, offset, FALSE, FALSE),
4590 adjustArithmeticResult (ic);
4593 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4596 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4597 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4601 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4602 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4606 /*-----------------------------------------------------------------*/
4607 /* genMinusDec :- does subtraction with decrement if possible */
4608 /*-----------------------------------------------------------------*/
4610 genMinusDec (iCode * ic)
4612 unsigned int icount;
4613 unsigned int size = getDataSize (IC_RESULT (ic));
4615 /* will try to generate an increment */
4616 /* if the right side is not a literal
4618 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4621 /* if the literal value of the right hand side
4622 is greater than 4 then it is not worth it */
4623 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4626 D (emitcode (";", "genMinusDec"));
4628 /* if decrement >=16 bits in register or direct space */
4629 if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG ||
4630 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4631 (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4632 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4640 /* If the next instruction is a goto and the goto target
4641 * is <= 10 instructions previous to this, we can generate
4642 * jumps straight to that target.
4644 if (ic->next && ic->next->op == GOTO
4645 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4646 && labelRange <= 10)
4648 D (emitcode (";", "tail decrement optimized (range %d)", labelRange));
4649 tlbl = IC_LABEL (ic->next);
4654 tlbl = newiTempLabel (NULL);
4658 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4659 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4660 IS_AOP_PREG (IC_RESULT (ic)))
4661 emitcode ("cjne", "%s,#0xff,%05d$"
4662 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4666 emitcode ("mov", "a,#0xff");
4667 emitcode ("cjne", "a,%s,%05d$"
4668 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4671 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4674 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4675 IS_AOP_PREG (IC_RESULT (ic)))
4676 emitcode ("cjne", "%s,#0xff,%05d$"
4677 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4681 emitcode ("cjne", "a,%s,%05d$"
4682 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4685 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4689 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4690 IS_AOP_PREG (IC_RESULT (ic)))
4691 emitcode ("cjne", "%s,#0xff,%05d$"
4692 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4696 emitcode ("cjne", "a,%s,%05d$"
4697 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4700 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4709 /* if the sizes are greater than 1 then we cannot */
4710 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4711 AOP_SIZE (IC_LEFT (ic)) > 1)
4714 /* we can if the aops of the left & result match or
4715 if they are in registers and the registers are the
4717 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4721 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4723 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4728 l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
4733 emitcode ("dec", "%s", l);
4736 if (AOP_NEEDSACC (IC_RESULT (ic)))
4737 aopPut (IC_RESULT (ic), "a", 0);
4744 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4745 emitcode ("dec", "a");
4746 aopPut (IC_RESULT (ic), "a", 0);
4753 /*-----------------------------------------------------------------*/
4754 /* addSign - complete with sign */
4755 /*-----------------------------------------------------------------*/
4757 addSign (operand * result, int offset, int sign)
4759 int size = (getDataSize (result) - offset);
4764 emitcode ("rlc", "a");
4765 emitcode ("subb", "a,acc");
4768 aopPut (result, "a", offset++);
4775 aopPut (result, zero, offset++);
4781 /*-----------------------------------------------------------------*/
4782 /* genMinusBits - generates code for subtraction of two bits */
4783 /*-----------------------------------------------------------------*/
4785 genMinusBits (iCode * ic)
4787 symbol *lbl = newiTempLabel (NULL);
4789 D (emitcode (";", "genMinusBits"));
4791 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4793 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4794 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4795 emitcode ("cpl", "c");
4797 outBitC (IC_RESULT (ic));
4801 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4802 emitcode ("subb", "a,acc");
4803 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4804 emitcode ("inc", "a");
4806 aopPut (IC_RESULT (ic), "a", 0);
4807 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4811 /*-----------------------------------------------------------------*/
4812 /* genMinus - generates code for subtraction */
4813 /*-----------------------------------------------------------------*/
4815 genMinus (iCode * ic)
4817 int size, offset = 0;
4819 D (emitcode (";", "genMinus"));
4821 aopOp (IC_LEFT (ic), ic, FALSE);
4822 aopOp (IC_RIGHT (ic), ic, FALSE);
4823 aopOp (IC_RESULT (ic), ic, TRUE);
4825 /* special cases :- */
4826 /* if both left & right are in bit space */
4827 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4828 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4834 /* if I can do an decrement instead
4835 of subtract then GOOD for ME */
4836 if (genMinusDec (ic) == TRUE)
4839 size = getDataSize (IC_RESULT (ic));
4841 /* if literal, add a,#-lit, else normal subb */
4842 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4844 unsigned long lit = 0L;
4845 bool useCarry = FALSE;
4847 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4852 if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4854 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4855 if (!offset && !size && lit== (unsigned long) -1)
4857 emitcode ("dec", "a");
4861 /* first add without previous c */
4862 emitcode ("add", "a,#0x%02x",
4863 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4868 emitcode ("addc", "a,#0x%02x",
4869 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4871 aopPut (IC_RESULT (ic), "a", offset++);
4875 /* no need to add zeroes */
4876 if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4878 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4887 operand *leftOp, *rightOp;
4889 leftOp = IC_LEFT(ic);
4890 rightOp = IC_RIGHT(ic);
4894 if (aopGetUsesAcc(rightOp, offset)) {
4895 if (aopGetUsesAcc(leftOp, offset)) {
4898 MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4900 emitcode ("mov", "b,a");
4903 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4904 emitcode ("subb", "a,b");
4907 /* reverse subtraction with 2's complement */
4909 emitcode( "setb", "c");
4911 emitcode( "cpl", "c");
4912 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4913 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4914 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4915 emitcode("cpl", "a");
4916 if (size) /* skip if last byte */
4917 emitcode( "cpl", "c");
4920 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4923 emitcode ("subb", "a,%s",
4924 aopGet(rightOp, offset, FALSE, TRUE));
4927 aopPut (IC_RESULT (ic), "a", offset++);
4931 adjustArithmeticResult (ic);
4934 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4935 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4936 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4940 /*-----------------------------------------------------------------*/
4941 /* genMultbits :- multiplication of bits */
4942 /*-----------------------------------------------------------------*/
4944 genMultbits (operand * left,
4948 D (emitcode (";", "genMultbits"));
4950 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4951 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4955 /*-----------------------------------------------------------------*/
4956 /* genMultOneByte : 8*8=8/16 bit multiplication */
4957 /*-----------------------------------------------------------------*/
4959 genMultOneByte (operand * left,
4964 int size = AOP_SIZE (result);
4965 bool runtimeSign, compiletimeSign;
4966 bool lUnsigned, rUnsigned, pushedB;
4968 D (emitcode (";", "genMultOneByte"));
4970 if (size < 1 || size > 2)
4972 /* this should never happen */
4973 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4974 AOP_SIZE(result), __FILE__, lineno);
4978 /* (if two literals: the value is computed before) */
4979 /* if one literal, literal on the right */
4980 if (AOP_TYPE (left) == AOP_LIT)
4985 /* emitcode (";", "swapped left and right"); */
4987 /* if no literal, unsigned on the right: shorter code */
4988 if ( AOP_TYPE (right) != AOP_LIT
4989 && SPEC_USIGN (getSpec (operandType (left))))
4996 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4997 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5001 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
5002 no need to take care about the signedness! */
5003 || (lUnsigned && rUnsigned))
5005 /* just an unsigned 8 * 8 = 8 multiply
5007 /* emitcode (";","unsigned"); */
5008 /* TODO: check for accumulator clash between left & right aops? */
5010 if (AOP_TYPE (right) == AOP_LIT)
5012 /* moving to accumulator first helps peepholes */
5013 MOVA (aopGet (left, 0, FALSE, FALSE));
5014 MOVB (aopGet (right, 0, FALSE, FALSE));
5018 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5019 MOVA (aopGet (left, 0, FALSE, FALSE));
5022 emitcode ("mul", "ab");
5023 aopPut (result, "a", 0);
5025 aopPut (result, "b", 1);
5031 /* we have to do a signed multiply */
5032 /* emitcode (";", "signed"); */
5034 /* now sign adjust for both left & right */
5036 /* let's see what's needed: */
5037 /* apply negative sign during runtime */
5038 runtimeSign = FALSE;
5039 /* negative sign from literals */
5040 compiletimeSign = FALSE;
5044 if (AOP_TYPE(left) == AOP_LIT)
5046 /* signed literal */
5047 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5049 compiletimeSign = TRUE;
5052 /* signed but not literal */
5058 if (AOP_TYPE(right) == AOP_LIT)
5060 /* signed literal */
5061 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5063 compiletimeSign ^= TRUE;
5066 /* signed but not literal */
5070 /* initialize F0, which stores the runtime sign */
5073 if (compiletimeSign)
5074 emitcode ("setb", "F0"); /* set sign flag */
5076 emitcode ("clr", "F0"); /* reset sign flag */
5079 /* save the signs of the operands */
5080 if (AOP_TYPE(right) == AOP_LIT)
5082 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5084 if (!rUnsigned && val < 0)
5085 emitcode ("mov", "b,#0x%02x", -val);
5087 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5089 else /* ! literal */
5091 if (rUnsigned) /* emitcode (";", "signed"); */
5092 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5095 MOVA (aopGet (right, 0, FALSE, FALSE));
5096 lbl = newiTempLabel (NULL);
5097 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5098 emitcode ("cpl", "F0"); /* complement sign flag */
5099 emitcode ("cpl", "a"); /* 2's complement */
5100 emitcode ("inc", "a");
5102 emitcode ("mov", "b,a");
5106 if (AOP_TYPE(left) == AOP_LIT)
5108 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5110 if (!lUnsigned && val < 0)
5111 emitcode ("mov", "a,#0x%02x", -val);
5113 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5115 else /* ! literal */
5117 MOVA (aopGet (left, 0, FALSE, FALSE));
5121 lbl = newiTempLabel (NULL);
5122 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5123 emitcode ("cpl", "F0"); /* complement sign flag */
5124 emitcode ("cpl", "a"); /* 2's complement */
5125 emitcode ("inc", "a");
5130 /* now the multiplication */
5131 emitcode ("mul", "ab");
5132 if (runtimeSign || compiletimeSign)
5134 lbl = newiTempLabel (NULL);
5136 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5137 emitcode ("cpl", "a"); /* lsb 2's complement */
5139 emitcode ("inc", "a"); /* inc doesn't set carry flag */
5142 emitcode ("add", "a,#1"); /* this sets carry flag */
5143 emitcode ("xch", "a,b");
5144 emitcode ("cpl", "a"); /* msb 2's complement */
5145 emitcode ("addc", "a,#0");
5146 emitcode ("xch", "a,b");
5150 aopPut (result, "a", 0);
5152 aopPut (result, "b", 1);
5157 /*-----------------------------------------------------------------*/
5158 /* genMult - generates code for multiplication */
5159 /*-----------------------------------------------------------------*/
5161 genMult (iCode * ic)
5163 operand *left = IC_LEFT (ic);
5164 operand *right = IC_RIGHT (ic);
5165 operand *result = IC_RESULT (ic);
5167 D (emitcode (";", "genMult"));
5169 /* assign the asmops */
5170 aopOp (left, ic, FALSE);
5171 aopOp (right, ic, FALSE);
5172 aopOp (result, ic, TRUE);
5174 /* special cases first */
5176 if (AOP_TYPE (left) == AOP_CRY &&
5177 AOP_TYPE (right) == AOP_CRY)
5179 genMultbits (left, right, result);
5183 /* if both are of size == 1 */
5184 #if 0 // one of them can be a sloc shared with the result
5185 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
5187 if (getSize(operandType(left)) == 1 &&
5188 getSize(operandType(right)) == 1)
5191 genMultOneByte (left, right, result);
5195 /* should have been converted to function call */
5196 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
5197 getSize(OP_SYMBOL(right)->type));
5201 freeAsmop (result, NULL, ic, TRUE);
5202 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5203 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5206 /*-----------------------------------------------------------------*/
5207 /* genDivbits :- division of bits */
5208 /*-----------------------------------------------------------------*/
5210 genDivbits (operand * left,
5217 D(emitcode ("; genDivbits",""));
5221 /* the result must be bit */
5222 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5223 l = aopGet (left, 0, FALSE, FALSE);
5227 emitcode ("div", "ab");
5228 emitcode ("rrc", "a");
5232 aopPut (result, "c", 0);
5235 /*-----------------------------------------------------------------*/
5236 /* genDivOneByte : 8 bit division */
5237 /*-----------------------------------------------------------------*/
5239 genDivOneByte (operand * left,
5243 bool lUnsigned, rUnsigned, pushedB;
5244 bool runtimeSign, compiletimeSign;
5245 bool accuse = FALSE;
5246 bool pushedA = FALSE;
5250 D(emitcode ("; genDivOneByte",""));
5252 /* Why is it necessary that genDivOneByte() can return an int result?
5255 volatile unsigned char uc;
5256 volatile signed char sc1, sc2;
5269 In all cases a one byte result would overflow, the following cast to int
5270 would return the wrong result.
5272 Two possible solution:
5273 a) cast operands to int, if ((unsigned) / (signed)) or
5274 ((signed) / (signed))
5275 b) return an 16 bit signed int; this is what we're doing here!
5278 size = AOP_SIZE (result) - 1;
5280 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5281 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5285 /* signed or unsigned */
5286 if (lUnsigned && rUnsigned)
5288 /* unsigned is easy */
5289 MOVB (aopGet (right, 0, FALSE, FALSE));
5290 MOVA (aopGet (left, 0, FALSE, FALSE));
5291 emitcode ("div", "ab");
5292 aopPut (result, "a", 0);
5294 aopPut (result, zero, offset++);
5300 /* signed is a little bit more difficult */
5302 /* now sign adjust for both left & right */
5304 /* let's see what's needed: */
5305 /* apply negative sign during runtime */
5306 runtimeSign = FALSE;
5307 /* negative sign from literals */
5308 compiletimeSign = FALSE;
5312 if (AOP_TYPE(left) == AOP_LIT)
5314 /* signed literal */
5315 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5317 compiletimeSign = TRUE;
5320 /* signed but not literal */
5326 if (AOP_TYPE(right) == AOP_LIT)
5328 /* signed literal */
5329 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5331 compiletimeSign ^= TRUE;
5334 /* signed but not literal */
5338 /* initialize F0, which stores the runtime sign */
5341 if (compiletimeSign)
5342 emitcode ("setb", "F0"); /* set sign flag */
5344 emitcode ("clr", "F0"); /* reset sign flag */
5347 /* save the signs of the operands */
5348 if (AOP_TYPE(right) == AOP_LIT)
5350 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5352 if (!rUnsigned && val < 0)
5353 emitcode ("mov", "b,#0x%02x", -val);
5355 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5357 else /* ! literal */
5360 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5363 MOVA (aopGet (right, 0, FALSE, FALSE));
5364 lbl = newiTempLabel (NULL);
5365 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5366 emitcode ("cpl", "F0"); /* complement sign flag */
5367 emitcode ("cpl", "a"); /* 2's complement */
5368 emitcode ("inc", "a");
5370 emitcode ("mov", "b,a");
5374 if (AOP_TYPE(left) == AOP_LIT)
5376 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5378 if (!lUnsigned && val < 0)
5379 emitcode ("mov", "a,#0x%02x", -val);
5381 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5383 else /* ! literal */
5385 MOVA (aopGet (left, 0, FALSE, FALSE));
5389 lbl = newiTempLabel (NULL);
5390 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5391 emitcode ("cpl", "F0"); /* complement sign flag */
5392 emitcode ("cpl", "a"); /* 2's complement */
5393 emitcode ("inc", "a");
5398 /* now the division */
5399 emitcode ("div", "ab");
5401 if (runtimeSign || compiletimeSign)
5403 lbl = newiTempLabel (NULL);
5405 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5406 emitcode ("cpl", "a"); /* lsb 2's complement */
5407 emitcode ("inc", "a");
5410 accuse = aopPut (result, "a", 0);
5413 /* msb is 0x00 or 0xff depending on the sign */
5418 emitcode ("push", "acc");
5421 emitcode ("mov", "c,F0");
5422 emitcode ("subb", "a,acc");
5424 aopPut (result, "a", offset++);
5426 else /* compiletimeSign */
5428 if (aopPutUsesAcc (result, "#0xFF", offset))
5430 emitcode ("push", "acc");
5434 aopPut (result, "#0xff", offset++);
5440 aopPut (result, "a", 0);
5442 aopPut (result, zero, offset++);
5446 emitcode ("pop", "acc");
5450 /*-----------------------------------------------------------------*/
5451 /* genDiv - generates code for division */
5452 /*-----------------------------------------------------------------*/
5456 operand *left = IC_LEFT (ic);
5457 operand *right = IC_RIGHT (ic);
5458 operand *result = IC_RESULT (ic);
5460 D (emitcode (";", "genDiv"));
5462 /* assign the asmops */
5463 aopOp (left, ic, FALSE);
5464 aopOp (right, ic, FALSE);
5465 aopOp (result, ic, TRUE);
5467 /* special cases first */
5469 if (AOP_TYPE (left) == AOP_CRY &&
5470 AOP_TYPE (right) == AOP_CRY)
5472 genDivbits (left, right, result);
5476 /* if both are of size == 1 */
5477 if (AOP_SIZE (left) == 1 &&
5478 AOP_SIZE (right) == 1)
5480 genDivOneByte (left, right, result);
5484 /* should have been converted to function call */
5487 freeAsmop (result, NULL, ic, TRUE);
5488 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5489 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5492 /*-----------------------------------------------------------------*/
5493 /* genModbits :- modulus of bits */
5494 /*-----------------------------------------------------------------*/
5496 genModbits (operand * left,
5503 D (emitcode (";", "genModbits"));
5507 /* the result must be bit */
5508 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5509 l = aopGet (left, 0, FALSE, FALSE);
5513 emitcode ("div", "ab");
5514 emitcode ("mov", "a,b");
5515 emitcode ("rrc", "a");
5519 aopPut (result, "c", 0);
5522 /*-----------------------------------------------------------------*/
5523 /* genModOneByte : 8 bit modulus */
5524 /*-----------------------------------------------------------------*/
5526 genModOneByte (operand * left,
5530 bool lUnsigned, rUnsigned, pushedB;
5531 bool runtimeSign, compiletimeSign;
5535 D (emitcode (";", "genModOneByte"));
5537 size = AOP_SIZE (result) - 1;
5539 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5540 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5542 /* if right is a literal, check it for 2^n */
5543 if (AOP_TYPE(right) == AOP_LIT)
5545 unsigned char val = abs((int) operandLitValue(right));
5546 symbol *lbl2 = NULL;
5550 case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5559 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5560 "modulus of unsigned char by 2^n literal shouldn't be processed here");
5561 /* because iCode should have been changed to genAnd */
5562 /* see file "SDCCopt.c", function "convertToFcall()" */
5564 MOVA (aopGet (left, 0, FALSE, FALSE));
5565 emitcode ("mov", "c,acc.7");
5566 emitcode ("anl", "a,#0x%02x", val - 1);
5567 lbl = newiTempLabel (NULL);
5568 emitcode ("jz", "%05d$", (lbl->key + 100));
5569 emitcode ("jnc", "%05d$", (lbl->key + 100));
5570 emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5576 aopPut (result, "a", 0);
5578 aopPut (result, "#0xff", offs2++);
5579 lbl2 = newiTempLabel (NULL);
5580 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5583 aopPut (result, "a", 0);
5585 aopPut (result, zero, offset++);
5599 /* signed or unsigned */
5600 if (lUnsigned && rUnsigned)
5602 /* unsigned is easy */
5603 MOVB (aopGet (right, 0, FALSE, FALSE));
5604 MOVA (aopGet (left, 0, FALSE, FALSE));
5605 emitcode ("div", "ab");
5606 aopPut (result, "b", 0);
5608 aopPut (result, zero, offset++);
5614 /* signed is a little bit more difficult */
5616 /* now sign adjust for both left & right */
5618 /* modulus: sign of the right operand has no influence on the result! */
5619 if (AOP_TYPE(right) == AOP_LIT)
5621 signed char val = (char) operandLitValue(right);
5623 if (!rUnsigned && val < 0)
5624 emitcode ("mov", "b,#0x%02x", -val);
5626 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5628 else /* not literal */
5631 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5634 MOVA (aopGet (right, 0, FALSE, FALSE));
5635 lbl = newiTempLabel (NULL);
5636 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5637 emitcode ("cpl", "a"); /* 2's complement */
5638 emitcode ("inc", "a");
5640 emitcode ("mov", "b,a");
5644 /* let's see what's needed: */
5645 /* apply negative sign during runtime */
5646 runtimeSign = FALSE;
5647 /* negative sign from literals */
5648 compiletimeSign = FALSE;
5650 /* sign adjust left side */
5651 if (AOP_TYPE(left) == AOP_LIT)
5653 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5655 if (!lUnsigned && val < 0)
5657 compiletimeSign = TRUE; /* set sign flag */
5658 emitcode ("mov", "a,#0x%02x", -val);
5661 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5663 else /* ! literal */
5665 MOVA (aopGet (left, 0, FALSE, FALSE));
5670 emitcode ("clr", "F0"); /* clear sign flag */
5672 lbl = newiTempLabel (NULL);
5673 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5674 emitcode ("setb", "F0"); /* set sign flag */
5675 emitcode ("cpl", "a"); /* 2's complement */
5676 emitcode ("inc", "a");
5681 /* now the modulus */
5682 emitcode ("div", "ab");
5684 if (runtimeSign || compiletimeSign)
5686 emitcode ("mov", "a,b");
5687 lbl = newiTempLabel (NULL);
5689 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5690 emitcode ("cpl", "a"); /* 2's complement */
5691 emitcode ("inc", "a");
5694 aopPut (result, "a", 0);
5697 /* msb is 0x00 or 0xff depending on the sign */
5700 emitcode ("mov", "c,F0");
5701 emitcode ("subb", "a,acc");
5703 aopPut (result, "a", offset++);
5705 else /* compiletimeSign */
5707 aopPut (result, "#0xff", offset++);
5712 aopPut (result, "b", 0);
5714 aopPut (result, zero, offset++);
5720 /*-----------------------------------------------------------------*/
5721 /* genMod - generates code for division */
5722 /*-----------------------------------------------------------------*/
5726 operand *left = IC_LEFT (ic);
5727 operand *right = IC_RIGHT (ic);
5728 operand *result = IC_RESULT (ic);
5730 D (emitcode (";", "genMod"));
5732 /* assign the asmops */
5733 aopOp (left, ic, FALSE);
5734 aopOp (right, ic, FALSE);
5735 aopOp (result, ic, TRUE);
5737 /* special cases first */
5739 if (AOP_TYPE (left) == AOP_CRY &&
5740 AOP_TYPE (right) == AOP_CRY)
5742 genModbits (left, right, result);
5746 /* if both are of size == 1 */
5747 if (AOP_SIZE (left) == 1 &&
5748 AOP_SIZE (right) == 1)
5750 genModOneByte (left, right, result);
5754 /* should have been converted to function call */
5758 freeAsmop (result, NULL, ic, TRUE);
5759 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5760 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5763 /*-----------------------------------------------------------------*/
5764 /* genIfxJump :- will create a jump depending on the ifx */
5765 /*-----------------------------------------------------------------*/
5767 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5770 symbol *tlbl = newiTempLabel (NULL);
5773 D (emitcode (";", "genIfxJump"));
5775 /* if true label then we jump if condition
5779 jlbl = IC_TRUE (ic);
5780 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5781 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5785 /* false label is present */
5786 jlbl = IC_FALSE (ic);
5787 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5788 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5790 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5791 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5793 emitcode (inst, "%05d$", tlbl->key + 100);
5794 freeForBranchAsmop (result);
5795 freeForBranchAsmop (right);
5796 freeForBranchAsmop (left);
5797 emitcode ("ljmp", "%05d$", jlbl->key + 100);
5800 /* mark the icode as generated */
5804 /*-----------------------------------------------------------------*/
5805 /* genCmp :- greater or less than comparison */
5806 /*-----------------------------------------------------------------*/
5808 genCmp (operand * left, operand * right,
5809 operand * result, iCode * ifx, int sign, iCode *ic)
5811 int size, offset = 0;
5812 unsigned long lit = 0L;
5815 D (emitcode (";", "genCmp"));
5817 /* if left & right are bit variables */
5818 if (AOP_TYPE (left) == AOP_CRY &&
5819 AOP_TYPE (right) == AOP_CRY)
5821 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5822 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5826 /* subtract right from left if at the
5827 end the carry flag is set then we know that
5828 left is greater than right */
5829 size = max (AOP_SIZE (left), AOP_SIZE (right));
5831 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5832 if ((size == 1) && !sign &&
5833 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5835 symbol *lbl = newiTempLabel (NULL);
5836 emitcode ("cjne", "%s,%s,%05d$",
5837 aopGet (left, offset, FALSE, FALSE),
5838 aopGet (right, offset, FALSE, FALSE),
5844 if (AOP_TYPE (right) == AOP_LIT)
5846 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5847 /* optimize if(x < 0) or if(x >= 0) */
5856 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5857 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5859 genIfxJump (ifx, "acc.7", left, right, result);
5860 freeAsmop (right, NULL, ic, TRUE);
5861 freeAsmop (left, NULL, ic, TRUE);
5867 emitcode ("rlc", "a");
5874 int bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5875 while (size && (bytelit == 0))
5878 bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5884 MOVA (aopGet (left, offset, FALSE, FALSE));
5885 if (sign && size == 0)
5887 emitcode ("xrl", "a,#0x80");
5888 emitcode ("subb", "a,#0x%02x",
5889 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5893 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5903 bool pushedB = FALSE;
5904 rightInB = aopGetUsesAcc(right, offset);
5908 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5910 MOVA (aopGet (left, offset, FALSE, FALSE));
5911 if (sign && size == 0)
5913 emitcode ("xrl", "a,#0x80");
5918 MOVB (aopGet (right, offset, FALSE, FALSE));
5920 emitcode ("xrl", "b,#0x80");
5921 emitcode ("subb", "a,b");
5926 emitcode ("subb", "a,b");
5928 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5938 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5939 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5940 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5946 /* if the result is used in the next
5947 ifx conditional branch then generate
5948 code a little differently */
5951 genIfxJump (ifx, "c", NULL, NULL, result);
5957 /* leave the result in acc */
5961 /*-----------------------------------------------------------------*/
5962 /* genCmpGt :- greater than comparison */
5963 /*-----------------------------------------------------------------*/
5965 genCmpGt (iCode * ic, iCode * ifx)
5967 operand *left, *right, *result;
5968 sym_link *letype, *retype;
5971 D (emitcode (";", "genCmpGt"));
5973 left = IC_LEFT (ic);
5974 right = IC_RIGHT (ic);
5975 result = IC_RESULT (ic);
5977 letype = getSpec (operandType (left));
5978 retype = getSpec (operandType (right));
5979 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5980 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5981 /* assign the asmops */
5982 aopOp (result, ic, TRUE);
5983 aopOp (left, ic, FALSE);
5984 aopOp (right, ic, FALSE);
5986 genCmp (right, left, result, ifx, sign, ic);
5988 freeAsmop (result, NULL, ic, TRUE);
5991 /*-----------------------------------------------------------------*/
5992 /* genCmpLt - less than comparisons */
5993 /*-----------------------------------------------------------------*/
5995 genCmpLt (iCode * ic, iCode * ifx)
5997 operand *left, *right, *result;
5998 sym_link *letype, *retype;
6001 D (emitcode (";", "genCmpLt"));
6003 left = IC_LEFT (ic);
6004 right = IC_RIGHT (ic);
6005 result = IC_RESULT (ic);
6007 letype = getSpec (operandType (left));
6008 retype = getSpec (operandType (right));
6009 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
6010 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
6011 /* assign the asmops */
6012 aopOp (result, ic, TRUE);
6013 aopOp (left, ic, FALSE);
6014 aopOp (right, ic, FALSE);
6016 genCmp (left, right, result, ifx, sign, ic);
6018 freeAsmop (result, NULL, ic, TRUE);
6021 /*-----------------------------------------------------------------*/
6022 /* gencjneshort - compare and jump if not equal */
6023 /*-----------------------------------------------------------------*/
6025 gencjneshort (operand * left, operand * right, symbol * lbl)
6027 int size = max (AOP_SIZE (left), AOP_SIZE (right));
6029 unsigned long lit = 0L;
6031 D (emitcode (";", "gencjneshort"));
6033 /* if the left side is a literal or
6034 if the right is in a pointer register and left
6036 if ((AOP_TYPE (left) == AOP_LIT) ||
6037 (AOP_TYPE (left) == AOP_IMMD) ||
6038 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6045 if (AOP_TYPE (right) == AOP_LIT)
6046 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6048 /* if the right side is a literal then anything goes */
6049 if (AOP_TYPE (right) == AOP_LIT &&
6050 AOP_TYPE (left) != AOP_DIR &&
6051 AOP_TYPE (left) != AOP_IMMD)
6055 emitcode ("cjne", "%s,%s,%05d$",
6056 aopGet (left, offset, FALSE, FALSE),
6057 aopGet (right, offset, FALSE, FALSE),
6063 /* if the right side is in a register or in direct space or
6064 if the left is a pointer register & right is not */
6065 else if (AOP_TYPE (right) == AOP_REG ||
6066 AOP_TYPE (right) == AOP_DIR ||
6067 AOP_TYPE (right) == AOP_LIT ||
6068 AOP_TYPE (right) == AOP_IMMD ||
6069 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6070 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6074 MOVA (aopGet (left, offset, FALSE, FALSE));
6075 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6076 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6077 emitcode ("jnz", "%05d$", lbl->key + 100);
6079 emitcode ("cjne", "a,%s,%05d$",
6080 aopGet (right, offset, FALSE, TRUE),
6087 /* right is a pointer reg need both a & b */
6090 //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
6091 wassertl(!BINUSE, "B was in use");
6092 MOVB (aopGet (left, offset, FALSE, FALSE));
6093 MOVA (aopGet (right, offset, FALSE, FALSE));
6094 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
6100 /*-----------------------------------------------------------------*/
6101 /* gencjne - compare and jump if not equal */
6102 /*-----------------------------------------------------------------*/
6104 gencjne (operand * left, operand * right, symbol * lbl)
6106 symbol *tlbl = newiTempLabel (NULL);
6108 D (emitcode (";", "gencjne"));
6110 gencjneshort (left, right, lbl);
6112 emitcode ("mov", "a,%s", one);
6113 emitcode ("sjmp", "%05d$", tlbl->key + 100);
6115 emitcode ("clr", "a");
6119 /*-----------------------------------------------------------------*/
6120 /* genCmpEq - generates code for equal to */
6121 /*-----------------------------------------------------------------*/
6123 genCmpEq (iCode * ic, iCode * ifx)
6125 bool swappedLR = FALSE;
6126 operand *left, *right, *result;
6128 D (emitcode (";", "genCmpEq"));
6130 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6131 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6132 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6134 /* if literal, literal on the right or
6135 if the right is in a pointer register and left
6137 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6138 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6140 operand *t = IC_RIGHT (ic);
6141 IC_RIGHT (ic) = IC_LEFT (ic);
6146 if (ifx && !AOP_SIZE (result))
6149 /* if they are both bit variables */
6150 if (AOP_TYPE (left) == AOP_CRY &&
6151 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6153 if (AOP_TYPE (right) == AOP_LIT)
6155 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6158 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6159 emitcode ("cpl", "c");
6163 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6167 emitcode ("clr", "c");
6169 /* AOP_TYPE(right) == AOP_CRY */
6173 symbol *lbl = newiTempLabel (NULL);
6174 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6175 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6176 emitcode ("cpl", "c");
6179 /* if true label then we jump if condition
6181 tlbl = newiTempLabel (NULL);
6184 emitcode ("jnc", "%05d$", tlbl->key + 100);
6185 freeForBranchAsmop (result);
6186 freeForBranchAsmop (right);
6187 freeForBranchAsmop (left);
6188 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6192 emitcode ("jc", "%05d$", tlbl->key + 100);
6193 freeForBranchAsmop (result);
6194 freeForBranchAsmop (right);
6195 freeForBranchAsmop (left);
6196 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6202 tlbl = newiTempLabel (NULL);
6203 gencjneshort (left, right, tlbl);
6206 freeForBranchAsmop (result);
6207 freeForBranchAsmop (right);
6208 freeForBranchAsmop (left);
6209 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6214 symbol *lbl = newiTempLabel (NULL);
6215 emitcode ("sjmp", "%05d$", lbl->key + 100);
6217 freeForBranchAsmop (result);
6218 freeForBranchAsmop (right);
6219 freeForBranchAsmop (left);
6220 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6224 /* mark the icode as generated */
6229 /* if they are both bit variables */
6230 if (AOP_TYPE (left) == AOP_CRY &&
6231 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6233 if (AOP_TYPE (right) == AOP_LIT)
6235 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6238 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6239 emitcode ("cpl", "c");
6243 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6247 emitcode ("clr", "c");
6249 /* AOP_TYPE(right) == AOP_CRY */
6253 symbol *lbl = newiTempLabel (NULL);
6254 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6255 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6256 emitcode ("cpl", "c");
6260 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6267 genIfxJump (ifx, "c", left, right, result);
6270 /* if the result is used in an arithmetic operation
6271 then put the result in place */
6276 gencjne (left, right, newiTempLabel (NULL));
6277 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6279 aopPut (result, "a", 0);
6284 genIfxJump (ifx, "a", left, right, result);
6287 /* if the result is used in an arithmetic operation
6288 then put the result in place */
6289 if (AOP_TYPE (result) != AOP_CRY)
6291 /* leave the result in acc */
6295 freeAsmop (result, NULL, ic, TRUE);
6298 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6299 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6303 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6304 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6308 /*-----------------------------------------------------------------*/
6309 /* ifxForOp - returns the icode containing the ifx for operand */
6310 /*-----------------------------------------------------------------*/
6312 ifxForOp (operand * op, iCode * ic)
6314 /* if true symbol then needs to be assigned */
6315 if (IS_TRUE_SYMOP (op))
6318 /* if this has register type condition and
6319 the next instruction is ifx with the same operand
6320 and live to of the operand is upto the ifx only then */
6322 ic->next->op == IFX &&
6323 IC_COND (ic->next)->key == op->key &&
6324 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6330 /*-----------------------------------------------------------------*/
6331 /* hasInc - operand is incremented before any other use */
6332 /*-----------------------------------------------------------------*/
6334 hasInc (operand *op, iCode *ic, int osize)
6336 sym_link *type = operandType(op);
6337 sym_link *retype = getSpec (type);
6338 iCode *lic = ic->next;
6341 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6342 if (!IS_SYMOP(op)) return NULL;
6344 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6345 if (IS_AGGREGATE(type->next)) return NULL;
6346 if (osize != (isize = getSize(type->next))) return NULL;
6349 /* if operand of the form op = op + <sizeof *op> */
6350 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6351 isOperandEqual(IC_RESULT(lic),op) &&
6352 isOperandLiteral(IC_RIGHT(lic)) &&
6353 operandLitValue(IC_RIGHT(lic)) == isize) {
6356 /* if the operand used or deffed */
6357 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6360 /* if GOTO or IFX */
6361 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6367 /*-----------------------------------------------------------------*/
6368 /* genAndOp - for && operation */
6369 /*-----------------------------------------------------------------*/
6371 genAndOp (iCode * ic)
6373 operand *left, *right, *result;
6376 D (emitcode (";", "genAndOp"));
6378 /* note here that && operations that are in an
6379 if statement are taken away by backPatchLabels
6380 only those used in arthmetic operations remain */
6381 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6382 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6383 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6385 /* if both are bit variables */
6386 if (AOP_TYPE (left) == AOP_CRY &&
6387 AOP_TYPE (right) == AOP_CRY)
6389 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6390 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6395 tlbl = newiTempLabel (NULL);
6397 emitcode ("jz", "%05d$", tlbl->key + 100);
6403 freeAsmop (result, NULL, ic, TRUE);
6404 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6405 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6409 /*-----------------------------------------------------------------*/
6410 /* genOrOp - for || operation */
6411 /*-----------------------------------------------------------------*/
6413 genOrOp (iCode * ic)
6415 operand *left, *right, *result;
6418 D (emitcode (";", "genOrOp"));
6420 /* note here that || operations that are in an
6421 if statement are taken away by backPatchLabels
6422 only those used in arthmetic operations remain */
6423 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6424 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6425 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6427 /* if both are bit variables */
6428 if (AOP_TYPE (left) == AOP_CRY &&
6429 AOP_TYPE (right) == AOP_CRY)
6431 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6432 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6437 tlbl = newiTempLabel (NULL);
6439 emitcode ("jnz", "%05d$", tlbl->key + 100);
6445 freeAsmop (result, NULL, ic, TRUE);
6446 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6447 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6450 /*-----------------------------------------------------------------*/
6451 /* isLiteralBit - test if lit == 2^n */
6452 /*-----------------------------------------------------------------*/
6454 isLiteralBit (unsigned long lit)
6456 unsigned long pw[32] =
6457 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6458 0x100L, 0x200L, 0x400L, 0x800L,
6459 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6460 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6461 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6462 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6463 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6466 for (idx = 0; idx < 32; idx++)
6472 /*-----------------------------------------------------------------*/
6473 /* continueIfTrue - */
6474 /*-----------------------------------------------------------------*/
6476 continueIfTrue (iCode * ic)
6479 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6483 /*-----------------------------------------------------------------*/
6485 /*-----------------------------------------------------------------*/
6487 jumpIfTrue (iCode * ic)
6490 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6494 /*-----------------------------------------------------------------*/
6495 /* jmpTrueOrFalse - */
6496 /*-----------------------------------------------------------------*/
6498 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6500 // ugly but optimized by peephole
6503 symbol *nlbl = newiTempLabel (NULL);
6504 emitcode ("sjmp", "%05d$", nlbl->key + 100);
6506 freeForBranchAsmop (result);
6507 freeForBranchAsmop (right);
6508 freeForBranchAsmop (left);
6509 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6514 freeForBranchAsmop (result);
6515 freeForBranchAsmop (right);
6516 freeForBranchAsmop (left);
6517 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6523 /*-----------------------------------------------------------------*/
6524 /* genAnd - code for and */
6525 /*-----------------------------------------------------------------*/
6527 genAnd (iCode * ic, iCode * ifx)
6529 operand *left, *right, *result;
6530 int size, offset = 0;
6531 unsigned long lit = 0L;
6535 D (emitcode (";", "genAnd"));
6537 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6538 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6539 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6542 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6544 AOP_TYPE (left), AOP_TYPE (right));
6545 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6547 AOP_SIZE (left), AOP_SIZE (right));
6550 /* if left is a literal & right is not then exchange them */
6551 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6552 AOP_NEEDSACC (left))
6554 operand *tmp = right;
6559 /* if result = right then exchange left and right */
6560 if (sameRegs (AOP (result), AOP (right)))
6562 operand *tmp = right;
6567 /* if right is bit then exchange them */
6568 if (AOP_TYPE (right) == AOP_CRY &&
6569 AOP_TYPE (left) != AOP_CRY)
6571 operand *tmp = right;
6575 if (AOP_TYPE (right) == AOP_LIT)
6576 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6578 size = AOP_SIZE (result);
6581 // result = bit & yy;
6582 if (AOP_TYPE (left) == AOP_CRY)
6584 // c = bit & literal;
6585 if (AOP_TYPE (right) == AOP_LIT)
6589 if (size && sameRegs (AOP (result), AOP (left)))
6592 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6597 if (size && (AOP_TYPE (result) == AOP_CRY))
6599 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6602 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6607 emitcode ("clr", "c");
6612 if (AOP_TYPE (right) == AOP_CRY)
6615 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6616 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6621 MOVA (aopGet (right, 0, FALSE, FALSE));
6623 emitcode ("rrc", "a");
6624 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6632 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6633 genIfxJump (ifx, "c", left, right, result);
6637 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6638 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6639 if ((AOP_TYPE (right) == AOP_LIT) &&
6640 (AOP_TYPE (result) == AOP_CRY) &&
6641 (AOP_TYPE (left) != AOP_CRY))
6643 int posbit = isLiteralBit (lit);
6648 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6652 switch (posbit & 0x07)
6654 case 0: emitcode ("rrc", "a");
6656 case 7: emitcode ("rlc", "a");
6658 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6667 SNPRINTF (buffer, sizeof(buffer),
6668 "acc.%d", posbit & 0x07);
6669 genIfxJump (ifx, buffer, left, right, result);
6672 {// what is this case? just found it in ds390/gen.c
6673 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6680 symbol *tlbl = newiTempLabel (NULL);
6681 int sizel = AOP_SIZE (left);
6683 emitcode ("setb", "c");
6686 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6688 MOVA (aopGet (left, offset, FALSE, FALSE));
6690 if ((posbit = isLiteralBit (bytelit)) != 0)
6691 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6694 if (bytelit != 0x0FFL)
6695 emitcode ("anl", "a,%s",
6696 aopGet (right, offset, FALSE, TRUE));
6697 emitcode ("jnz", "%05d$", tlbl->key + 100);
6702 // bit = left & literal
6705 emitcode ("clr", "c");
6708 // if(left & literal)
6712 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6722 /* if left is same as result */
6723 if (sameRegs (AOP (result), AOP (left)))
6725 for (; size--; offset++)
6727 if (AOP_TYPE (right) == AOP_LIT)
6729 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6730 if (bytelit == 0x0FF)
6732 /* dummy read of volatile operand */
6733 if (isOperandVolatile (left, FALSE))
6734 MOVA (aopGet (left, offset, FALSE, FALSE));
6738 else if (bytelit == 0)
6740 aopPut (result, zero, offset);
6742 else if (IS_AOP_PREG (result))
6744 MOVA (aopGet (left, offset, FALSE, TRUE));
6745 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6746 aopPut (result, "a", offset);
6749 emitcode ("anl", "%s,%s",
6750 aopGet (left, offset, FALSE, TRUE),
6751 aopGet (right, offset, FALSE, FALSE));
6755 if (AOP_TYPE (left) == AOP_ACC)
6758 emitcode("mov", "a,b");
6759 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6761 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6763 MOVB (aopGet (left, offset, FALSE, FALSE));
6764 MOVA (aopGet (right, offset, FALSE, FALSE));
6765 emitcode ("anl", "a,b");
6766 aopPut (result, "a", offset);
6768 else if (aopGetUsesAcc (left, offset))
6770 MOVA (aopGet (left, offset, FALSE, FALSE));
6771 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6772 aopPut (result, "a", offset);
6776 MOVA (aopGet (right, offset, FALSE, FALSE));
6777 if (IS_AOP_PREG (result))
6779 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6780 aopPut (result, "a", offset);
6783 emitcode ("anl", "%s,a", aopGet (left, offset, FALSE, TRUE));
6790 // left & result in different registers
6791 if (AOP_TYPE (result) == AOP_CRY)
6794 // if(size), result in bit
6795 // if(!size && ifx), conditional oper: if(left & right)
6796 symbol *tlbl = newiTempLabel (NULL);
6797 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6799 emitcode ("setb", "c");
6802 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6803 && AOP_TYPE(left)==AOP_ACC)
6806 emitcode("mov", "a,b");
6807 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6809 else if (AOP_TYPE(left)==AOP_ACC)
6813 bool pushedB = pushB ();
6814 emitcode("mov", "b,a");
6815 MOVA (aopGet (right, offset, FALSE, FALSE));
6816 emitcode("anl", "a,b");
6821 MOVA (aopGet (right, offset, FALSE, FALSE));
6822 emitcode("anl", "a,b");
6825 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6827 MOVB (aopGet (left, offset, FALSE, FALSE));
6828 MOVA (aopGet (right, offset, FALSE, FALSE));
6829 emitcode ("anl", "a,b");
6831 else if (aopGetUsesAcc (left, offset))
6833 MOVA (aopGet (left, offset, FALSE, FALSE));
6834 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6838 MOVA (aopGet (right, offset, FALSE, FALSE));
6839 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6842 emitcode ("jnz", "%05d$", tlbl->key + 100);
6852 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6858 for (; (size--); offset++)
6861 // result = left & right
6862 if (AOP_TYPE (right) == AOP_LIT)
6864 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6865 if (bytelit == 0x0FF)
6868 aopGet (left, offset, FALSE, FALSE),
6872 else if (bytelit == 0)
6874 /* dummy read of volatile operand */
6875 if (isOperandVolatile (left, FALSE))
6876 MOVA (aopGet (left, offset, FALSE, FALSE));
6877 aopPut (result, zero, offset);
6880 else if (AOP_TYPE (left) == AOP_ACC)
6884 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6885 aopPut (result, "a", offset);
6890 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6891 aopPut (result, "b", offset);
6896 // faster than result <- left, anl result,right
6897 // and better if result is SFR
6898 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6899 && AOP_TYPE(left)==AOP_ACC)
6902 emitcode("mov", "a,b");
6903 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6905 else if (AOP_TYPE(left)==AOP_ACC)
6909 bool pushedB = pushB ();
6910 emitcode("mov", "b,a");
6911 MOVA (aopGet (right, offset, FALSE, FALSE));
6912 emitcode("anl", "a,b");
6917 MOVA (aopGet (right, offset, FALSE, FALSE));
6918 emitcode("anl", "a,b");
6921 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6923 MOVB (aopGet (left, offset, FALSE, FALSE));
6924 MOVA (aopGet (right, offset, FALSE, FALSE));
6925 emitcode ("anl", "a,b");
6927 else if (aopGetUsesAcc (left, offset))
6929 MOVA (aopGet (left, offset, FALSE, FALSE));
6930 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6934 MOVA (aopGet (right, offset, FALSE, FALSE));
6935 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6937 aopPut (result, "a", offset);
6943 freeAsmop (result, NULL, ic, TRUE);
6944 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6945 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6948 /*-----------------------------------------------------------------*/
6949 /* genOr - code for or */
6950 /*-----------------------------------------------------------------*/
6952 genOr (iCode * ic, iCode * ifx)
6954 operand *left, *right, *result;
6955 int size, offset = 0;
6956 unsigned long lit = 0L;
6959 D (emitcode (";", "genOr"));
6961 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6962 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6963 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6966 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6968 AOP_TYPE (left), AOP_TYPE (right));
6969 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6971 AOP_SIZE (left), AOP_SIZE (right));
6974 /* if left is a literal & right is not then exchange them */
6975 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6976 AOP_NEEDSACC (left))
6978 operand *tmp = right;
6983 /* if result = right then exchange them */
6984 if (sameRegs (AOP (result), AOP (right)))
6986 operand *tmp = right;
6991 /* if right is bit then exchange them */
6992 if (AOP_TYPE (right) == AOP_CRY &&
6993 AOP_TYPE (left) != AOP_CRY)
6995 operand *tmp = right;
6999 if (AOP_TYPE (right) == AOP_LIT)
7000 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7002 size = AOP_SIZE (result);
7006 if (AOP_TYPE (left) == AOP_CRY)
7008 if (AOP_TYPE (right) == AOP_LIT)
7010 // c = bit | literal;
7013 // lit != 0 => result = 1
7014 if (AOP_TYPE (result) == AOP_CRY)
7017 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7019 continueIfTrue (ifx);
7022 emitcode ("setb", "c");
7026 // lit == 0 => result = left
7027 if (size && sameRegs (AOP (result), AOP (left)))
7029 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7034 if (AOP_TYPE (right) == AOP_CRY)
7037 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7038 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7043 symbol *tlbl = newiTempLabel (NULL);
7044 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
7045 emitcode ("setb", "c");
7046 emitcode ("jb", "%s,%05d$",
7047 AOP (left)->aopu.aop_dir, tlbl->key + 100);
7049 emitcode ("jnz", "%05d$", tlbl->key + 100);
7050 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7052 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7067 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7068 genIfxJump (ifx, "c", left, right, result);
7072 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7073 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7074 if ((AOP_TYPE (right) == AOP_LIT) &&
7075 (AOP_TYPE (result) == AOP_CRY) &&
7076 (AOP_TYPE (left) != AOP_CRY))
7082 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7084 continueIfTrue (ifx);
7089 // lit = 0, result = boolean(left)
7091 emitcode ("setb", "c");
7095 symbol *tlbl = newiTempLabel (NULL);
7096 emitcode ("jnz", "%05d$", tlbl->key + 100);
7102 genIfxJump (ifx, "a", left, right, result);
7110 /* if left is same as result */
7111 if (sameRegs (AOP (result), AOP (left)))
7113 for (; size--; offset++)
7115 if (AOP_TYPE (right) == AOP_LIT)
7117 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7120 /* dummy read of volatile operand */
7121 if (isOperandVolatile (left, FALSE))
7122 MOVA (aopGet (left, offset, FALSE, FALSE));
7126 else if (bytelit == 0x0FF)
7128 aopPut (result, "#0xFF", offset);
7130 else if (IS_AOP_PREG (left))
7132 MOVA (aopGet (left, offset, FALSE, TRUE));
7133 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7134 aopPut (result, "a", offset);
7138 emitcode ("orl", "%s,%s",
7139 aopGet (left, offset, FALSE, TRUE),
7140 aopGet (right, offset, FALSE, FALSE));
7145 if (AOP_TYPE (left) == AOP_ACC)
7148 emitcode("mov", "a,b");
7149 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7151 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7153 MOVB (aopGet (left, offset, FALSE, FALSE));
7154 MOVA (aopGet (right, offset, FALSE, FALSE));
7155 emitcode ("orl", "a,b");
7156 aopPut (result, "a", offset);
7158 else if (aopGetUsesAcc (left, offset))
7160 MOVA (aopGet (left, offset, FALSE, FALSE));
7161 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7162 aopPut (result, "a", offset);
7166 MOVA (aopGet (right, offset, FALSE, FALSE));
7167 if (IS_AOP_PREG (left))
7169 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7170 aopPut (result, "a", offset);
7174 emitcode ("orl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7182 // left & result in different registers
7183 if (AOP_TYPE (result) == AOP_CRY)
7186 // if(size), result in bit
7187 // if(!size && ifx), conditional oper: if(left | right)
7188 symbol *tlbl = newiTempLabel (NULL);
7189 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7191 emitcode ("setb", "c");
7194 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7195 && AOP_TYPE(left)==AOP_ACC)
7198 emitcode("mov", "a,b");
7199 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7201 else if (AOP_TYPE(left)==AOP_ACC)
7205 bool pushedB = pushB ();
7206 emitcode("mov", "b,a");
7207 MOVA (aopGet (right, offset, FALSE, FALSE));
7208 emitcode("orl", "a,b");
7213 MOVA (aopGet (right, offset, FALSE, FALSE));
7214 emitcode("orl", "a,b");
7217 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7219 MOVB (aopGet (left, offset, FALSE, FALSE));
7220 MOVA (aopGet (right, offset, FALSE, FALSE));
7221 emitcode ("orl", "a,b");
7223 else if (aopGetUsesAcc (left, offset))
7225 MOVA (aopGet (left, offset, FALSE, FALSE));
7226 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7230 MOVA (aopGet (right, offset, FALSE, FALSE));
7231 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7234 emitcode ("jnz", "%05d$", tlbl->key + 100);
7244 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7250 for (; (size--); offset++)
7253 // result = left | right
7254 if (AOP_TYPE (right) == AOP_LIT)
7256 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7260 aopGet (left, offset, FALSE, FALSE),
7264 else if (bytelit == 0x0FF)
7266 /* dummy read of volatile operand */
7267 if (isOperandVolatile (left, FALSE))
7268 MOVA (aopGet (left, offset, FALSE, FALSE));
7269 aopPut (result, "#0xFF", offset);
7273 // faster than result <- left, orl result,right
7274 // and better if result is SFR
7275 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7276 && AOP_TYPE(left)==AOP_ACC)
7279 emitcode("mov", "a,b");
7280 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7282 else if (AOP_TYPE(left)==AOP_ACC)
7286 bool pushedB = pushB ();
7287 emitcode("mov", "b,a");
7288 MOVA (aopGet (right, offset, FALSE, FALSE));
7289 emitcode("orl", "a,b");
7294 MOVA (aopGet (right, offset, FALSE, FALSE));
7295 emitcode("orl", "a,b");
7298 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7300 MOVB (aopGet (left, offset, FALSE, FALSE));
7301 MOVA (aopGet (right, offset, FALSE, FALSE));
7302 emitcode ("orl", "a,b");
7304 else if (aopGetUsesAcc (left, offset))
7306 MOVA (aopGet (left, offset, FALSE, FALSE));
7307 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7311 MOVA (aopGet (right, offset, FALSE, FALSE));
7312 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7314 aopPut (result, "a", offset);
7320 freeAsmop (result, NULL, ic, TRUE);
7321 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7322 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7325 /*-----------------------------------------------------------------*/
7326 /* genXor - code for xclusive or */
7327 /*-----------------------------------------------------------------*/
7329 genXor (iCode * ic, iCode * ifx)
7331 operand *left, *right, *result;
7332 int size, offset = 0;
7333 unsigned long lit = 0L;
7336 D (emitcode (";", "genXor"));
7338 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7339 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7340 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7343 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7345 AOP_TYPE (left), AOP_TYPE (right));
7346 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7348 AOP_SIZE (left), AOP_SIZE (right));
7351 /* if left is a literal & right is not ||
7352 if left needs acc & right does not */
7353 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7354 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7356 operand *tmp = right;
7361 /* if result = right then exchange them */
7362 if (sameRegs (AOP (result), AOP (right)))
7364 operand *tmp = right;
7369 /* if right is bit then exchange them */
7370 if (AOP_TYPE (right) == AOP_CRY &&
7371 AOP_TYPE (left) != AOP_CRY)
7373 operand *tmp = right;
7378 if (AOP_TYPE (right) == AOP_LIT)
7379 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7381 size = AOP_SIZE (result);
7385 if (AOP_TYPE (left) == AOP_CRY)
7387 if (AOP_TYPE (right) == AOP_LIT)
7389 // c = bit & literal;
7392 // lit>>1 != 0 => result = 1
7393 if (AOP_TYPE (result) == AOP_CRY)
7396 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7398 continueIfTrue (ifx);
7401 emitcode ("setb", "c");
7408 // lit == 0, result = left
7409 if (size && sameRegs (AOP (result), AOP (left)))
7411 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7415 // lit == 1, result = not(left)
7416 if (size && sameRegs (AOP (result), AOP (left)))
7418 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7423 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7424 emitcode ("cpl", "c");
7432 symbol *tlbl = newiTempLabel (NULL);
7433 if (AOP_TYPE (right) == AOP_CRY)
7436 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7440 int sizer = AOP_SIZE (right);
7442 // if val>>1 != 0, result = 1
7443 emitcode ("setb", "c");
7446 MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
7448 // test the msb of the lsb
7449 emitcode ("anl", "a,#0xfe");
7450 emitcode ("jnz", "%05d$", tlbl->key + 100);
7454 emitcode ("rrc", "a");
7456 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7457 emitcode ("cpl", "c");
7465 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7466 genIfxJump (ifx, "c", left, right, result);
7470 /* if left is same as result */
7471 if (sameRegs (AOP (result), AOP (left)))
7473 for (; size--; offset++)
7475 if (AOP_TYPE (right) == AOP_LIT)
7477 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7480 /* dummy read of volatile operand */
7481 if (isOperandVolatile (left, FALSE))
7482 MOVA (aopGet (left, offset, FALSE, FALSE));
7486 else if (IS_AOP_PREG (left))
7488 MOVA (aopGet (left, offset, FALSE, TRUE));
7489 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7490 aopPut (result, "a", offset);
7494 emitcode ("xrl", "%s,%s",
7495 aopGet (left, offset, FALSE, TRUE),
7496 aopGet (right, offset, FALSE, FALSE));
7501 if (AOP_TYPE (left) == AOP_ACC)
7504 emitcode("mov", "a,b");
7505 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7507 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7509 MOVB (aopGet (left, offset, FALSE, FALSE));
7510 MOVA (aopGet (right, offset, FALSE, FALSE));
7511 emitcode ("xrl", "a,b");
7512 aopPut (result, "a", offset);
7514 else if (aopGetUsesAcc (left, offset))
7516 MOVA (aopGet (left, offset, FALSE, FALSE));
7517 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7518 aopPut (result, "a", offset);
7522 MOVA (aopGet (right, offset, FALSE, FALSE));
7523 if (IS_AOP_PREG (left))
7525 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7526 aopPut (result, "a", offset);
7529 emitcode ("xrl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7536 // left & result in different registers
7537 if (AOP_TYPE (result) == AOP_CRY)
7540 // if(size), result in bit
7541 // if(!size && ifx), conditional oper: if(left ^ right)
7542 symbol *tlbl = newiTempLabel (NULL);
7543 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7546 emitcode ("setb", "c");
7549 if ((AOP_TYPE (right) == AOP_LIT) &&
7550 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7552 MOVA (aopGet (left, offset, FALSE, FALSE));
7554 else if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7555 && AOP_TYPE(left)==AOP_ACC)
7558 emitcode("mov", "a,b");
7559 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7561 else if (AOP_TYPE(left)==AOP_ACC)
7565 bool pushedB = pushB ();
7566 emitcode("mov", "b,a");
7567 MOVA (aopGet (right, offset, FALSE, FALSE));
7568 emitcode("xrl", "a,b");
7573 MOVA (aopGet (right, offset, FALSE, FALSE));
7574 emitcode("xrl", "a,b");
7577 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7579 MOVB (aopGet (left, offset, FALSE, FALSE));
7580 MOVA (aopGet (right, offset, FALSE, FALSE));
7581 emitcode ("xrl", "a,b");
7583 else if (aopGetUsesAcc (left, offset))
7585 MOVA (aopGet (left, offset, FALSE, FALSE));
7586 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7590 MOVA (aopGet (right, offset, FALSE, FALSE));
7591 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7594 emitcode ("jnz", "%05d$", tlbl->key + 100);
7604 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7608 for (; (size--); offset++)
7611 // result = left ^ right
7612 if (AOP_TYPE (right) == AOP_LIT)
7614 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7618 aopGet (left, offset, FALSE, FALSE),
7623 // faster than result <- left, xrl result,right
7624 // and better if result is SFR
7625 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7626 && AOP_TYPE(left)==AOP_ACC)
7629 emitcode("mov", "a,b");
7630 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7632 else if (AOP_TYPE(left)==AOP_ACC)
7636 bool pushedB = pushB ();
7637 emitcode("mov", "b,a");
7638 MOVA (aopGet (right, offset, FALSE, FALSE));
7639 emitcode("xrl", "a,b");
7644 MOVA (aopGet (right, offset, FALSE, FALSE));
7645 emitcode("xrl", "a,b");
7648 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7650 MOVB (aopGet (left, offset, FALSE, FALSE));
7651 MOVA (aopGet (right, offset, FALSE, FALSE));
7652 emitcode ("xrl", "a,b");
7654 else if (aopGetUsesAcc (left, offset))
7656 MOVA (aopGet (left, offset, FALSE, FALSE));
7657 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7661 MOVA (aopGet (right, offset, FALSE, FALSE));
7662 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7664 aopPut (result, "a", offset);
7670 freeAsmop (result, NULL, ic, TRUE);
7671 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7672 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7675 /*-----------------------------------------------------------------*/
7676 /* genInline - write the inline code out */
7677 /*-----------------------------------------------------------------*/
7679 genInline (iCode * ic)
7681 char *buffer, *bp, *bp1;
7683 D (emitcode (";", "genInline"));
7685 _G.inLine += (!options.asmpeep);
7687 buffer = bp = bp1 = Safe_strdup(IC_INLINE(ic));
7689 /* emit each line as a code */
7700 /* Add \n for labels, not dirs such as c:\mydir */
7701 if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
7715 /* emitcode("",buffer); */
7716 _G.inLine -= (!options.asmpeep);
7719 /*-----------------------------------------------------------------*/
7720 /* genRRC - rotate right with carry */
7721 /*-----------------------------------------------------------------*/
7725 operand *left, *result;
7729 D (emitcode (";", "genRRC"));
7731 /* rotate right with carry */
7732 left = IC_LEFT (ic);
7733 result = IC_RESULT (ic);
7734 aopOp (left, ic, FALSE);
7735 aopOp (result, ic, FALSE);
7737 /* move it to the result */
7738 size = AOP_SIZE (result);
7740 if (size == 1) { /* special case for 1 byte */
7741 l = aopGet (left, offset, FALSE, FALSE);
7743 emitcode ("rr", "a");
7746 /* no need to clear carry, bit7 will be written later */
7749 l = aopGet (left, offset, FALSE, FALSE);
7751 emitcode ("rrc", "a");
7752 if (AOP_SIZE (result) > 1)
7753 aopPut (result, "a", offset--);
7755 /* now we need to put the carry into the
7756 highest order byte of the result */
7757 if (AOP_SIZE (result) > 1)
7759 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7762 emitcode ("mov", "acc.7,c");
7764 aopPut (result, "a", AOP_SIZE (result) - 1);
7765 freeAsmop (result, NULL, ic, TRUE);
7766 freeAsmop (left, NULL, ic, TRUE);
7769 /*-----------------------------------------------------------------*/
7770 /* genRLC - generate code for rotate left with carry */
7771 /*-----------------------------------------------------------------*/
7775 operand *left, *result;
7779 D (emitcode (";", "genRLC"));
7781 /* rotate right with carry */
7782 left = IC_LEFT (ic);
7783 result = IC_RESULT (ic);
7784 aopOp (left, ic, FALSE);
7785 aopOp (result, ic, FALSE);
7787 /* move it to the result */
7788 size = AOP_SIZE (result);
7792 l = aopGet (left, offset, FALSE, FALSE);
7794 if (size == 0) { /* special case for 1 byte */
7798 emitcode("rlc","a"); /* bit0 will be written later */
7799 if (AOP_SIZE (result) > 1)
7801 aopPut (result, "a", offset++);
7806 l = aopGet (left, offset, FALSE, FALSE);
7808 emitcode ("rlc", "a");
7809 if (AOP_SIZE (result) > 1)
7810 aopPut (result, "a", offset++);
7813 /* now we need to put the carry into the
7814 highest order byte of the result */
7815 if (AOP_SIZE (result) > 1)
7817 l = aopGet (result, 0, FALSE, FALSE);
7820 emitcode ("mov", "acc.0,c");
7822 aopPut (result, "a", 0);
7823 freeAsmop (result, NULL, ic, TRUE);
7824 freeAsmop (left, NULL, ic, TRUE);
7827 /*-----------------------------------------------------------------*/
7828 /* genGetHbit - generates code get highest order bit */
7829 /*-----------------------------------------------------------------*/
7831 genGetHbit (iCode * ic)
7833 operand *left, *result;
7835 D (emitcode (";", "genGetHbit"));
7837 left = IC_LEFT (ic);
7838 result = IC_RESULT (ic);
7839 aopOp (left, ic, FALSE);
7840 aopOp (result, ic, FALSE);
7842 /* get the highest order byte into a */
7843 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7844 if (AOP_TYPE (result) == AOP_CRY)
7846 emitcode ("rlc", "a");
7851 emitcode ("rl", "a");
7852 emitcode ("anl", "a,#0x01");
7856 freeAsmop (result, NULL, ic, TRUE);
7857 freeAsmop (left, NULL, ic, TRUE);
7860 /*-----------------------------------------------------------------*/
7861 /* genGetAbit - generates code get a single bit */
7862 /*-----------------------------------------------------------------*/
7864 genGetAbit (iCode * ic)
7866 operand *left, *right, *result;
7869 D (emitcode (";", "genGetAbit"));
7871 left = IC_LEFT (ic);
7872 right = IC_RIGHT (ic);
7873 result = IC_RESULT (ic);
7874 aopOp (left, ic, FALSE);
7875 aopOp (right, ic, FALSE);
7876 aopOp (result, ic, FALSE);
7878 shCount = (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7880 /* get the needed byte into a */
7881 MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7883 if (AOP_TYPE (result) == AOP_CRY)
7886 emitcode ("rlc", "a");
7887 else if ((shCount) == 0)
7888 emitcode ("rrc", "a");
7890 emitcode ("mov", "c,acc[%d]", shCount);
7898 emitcode ("rr", "a");
7901 emitcode ("rr", "a");
7904 emitcode ("anl", "a,#0x01");
7908 emitcode ("mov", "c,acc[%d]", shCount);
7909 emitcode ("clr", "a");
7910 emitcode ("rlc", "a");
7913 emitcode ("swap", "a");
7914 emitcode ("anl", "a,#0x01");
7917 emitcode ("rl", "a");
7920 emitcode ("rl", "a");
7921 emitcode ("anl", "a,#0x01");
7927 freeAsmop (result, NULL, ic, TRUE);
7928 freeAsmop (right, NULL, ic, TRUE);
7929 freeAsmop (left, NULL, ic, TRUE);
7932 /*-----------------------------------------------------------------*/
7933 /* genGetByte - generates code get a single byte */
7934 /*-----------------------------------------------------------------*/
7936 genGetByte (iCode * ic)
7938 operand *left, *right, *result;
7941 D (emitcode (";", "genGetByte"));
7943 left = IC_LEFT (ic);
7944 right = IC_RIGHT (ic);
7945 result = IC_RESULT (ic);
7946 aopOp (left, ic, FALSE);
7947 aopOp (right, ic, FALSE);
7948 aopOp (result, ic, FALSE);
7950 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7952 aopGet (left, offset, FALSE, FALSE),
7955 freeAsmop (result, NULL, ic, TRUE);
7956 freeAsmop (right, NULL, ic, TRUE);
7957 freeAsmop (left, NULL, ic, TRUE);
7960 /*-----------------------------------------------------------------*/
7961 /* genGetWord - generates code get two bytes */
7962 /*-----------------------------------------------------------------*/
7964 genGetWord (iCode * ic)
7966 operand *left, *right, *result;
7969 D (emitcode (";", "genGetWord"));
7971 left = IC_LEFT (ic);
7972 right = IC_RIGHT (ic);
7973 result = IC_RESULT (ic);
7974 aopOp (left, ic, FALSE);
7975 aopOp (right, ic, FALSE);
7976 aopOp (result, ic, FALSE);
7978 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7980 aopGet (left, offset, FALSE, FALSE),
7983 aopGet (left, offset+1, FALSE, FALSE),
7986 freeAsmop (result, NULL, ic, TRUE);
7987 freeAsmop (right, NULL, ic, TRUE);
7988 freeAsmop (left, NULL, ic, TRUE);
7991 /*-----------------------------------------------------------------*/
7992 /* genSwap - generates code to swap nibbles or bytes */
7993 /*-----------------------------------------------------------------*/
7995 genSwap (iCode * ic)
7997 operand *left, *result;
7999 D(emitcode ("; genSwap",""));
8001 left = IC_LEFT (ic);
8002 result = IC_RESULT (ic);
8003 aopOp (left, ic, FALSE);
8004 aopOp (result, ic, FALSE);
8006 switch (AOP_SIZE (left))
8008 case 1: /* swap nibbles in byte */
8009 MOVA (aopGet (left, 0, FALSE, FALSE));
8010 emitcode ("swap", "a");
8011 aopPut (result, "a", 0);
8013 case 2: /* swap bytes in word */
8014 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
8016 MOVA (aopGet (left, 0, FALSE, FALSE));
8017 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8018 aopPut (result, "a", 1);
8020 else if (operandsEqu (left, result))
8023 bool pushedB = FALSE, leftInB = FALSE;
8025 MOVA (aopGet (left, 0, FALSE, FALSE));
8026 if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
8029 emitcode ("mov", "b,a");
8033 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8034 aopPut (result, reg, 1);
8041 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8042 aopPut (result, aopGet (left, 0, FALSE, FALSE), 1);
8046 wassertl(FALSE, "unsupported SWAP operand size");
8049 freeAsmop (result, NULL, ic, TRUE);
8050 freeAsmop (left, NULL, ic, TRUE);
8053 /*-----------------------------------------------------------------*/
8054 /* AccRol - rotate left accumulator by known count */
8055 /*-----------------------------------------------------------------*/
8057 AccRol (int shCount)
8059 shCount &= 0x0007; // shCount : 0..7
8066 emitcode ("rl", "a");
8069 emitcode ("rl", "a");
8070 emitcode ("rl", "a");
8073 emitcode ("swap", "a");
8074 emitcode ("rr", "a");
8077 emitcode ("swap", "a");
8080 emitcode ("swap", "a");
8081 emitcode ("rl", "a");
8084 emitcode ("rr", "a");
8085 emitcode ("rr", "a");
8088 emitcode ("rr", "a");
8093 /*-----------------------------------------------------------------*/
8094 /* AccLsh - left shift accumulator by known count */
8095 /*-----------------------------------------------------------------*/
8097 AccLsh (int shCount)
8102 emitcode ("add", "a,acc");
8103 else if (shCount == 2)
8105 emitcode ("add", "a,acc");
8106 emitcode ("add", "a,acc");
8110 /* rotate left accumulator */
8112 /* and kill the lower order bits */
8113 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
8118 /*-----------------------------------------------------------------*/
8119 /* AccRsh - right shift accumulator by known count */
8120 /*-----------------------------------------------------------------*/
8122 AccRsh (int shCount)
8129 emitcode ("rrc", "a");
8133 /* rotate right accumulator */
8134 AccRol (8 - shCount);
8135 /* and kill the higher order bits */
8136 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8141 /*-----------------------------------------------------------------*/
8142 /* AccSRsh - signed right shift accumulator by known count */
8143 /*-----------------------------------------------------------------*/
8145 AccSRsh (int shCount)
8152 emitcode ("mov", "c,acc.7");
8153 emitcode ("rrc", "a");
8155 else if (shCount == 2)
8157 emitcode ("mov", "c,acc.7");
8158 emitcode ("rrc", "a");
8159 emitcode ("mov", "c,acc.7");
8160 emitcode ("rrc", "a");
8164 tlbl = newiTempLabel (NULL);
8165 /* rotate right accumulator */
8166 AccRol (8 - shCount);
8167 /* and kill the higher order bits */
8168 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8169 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8170 emitcode ("orl", "a,#0x%02x",
8171 (unsigned char) ~SRMask[shCount]);
8177 /*-----------------------------------------------------------------*/
8178 /* shiftR1Left2Result - shift right one byte from left to result */
8179 /*-----------------------------------------------------------------*/
8181 shiftR1Left2Result (operand * left, int offl,
8182 operand * result, int offr,
8183 int shCount, int sign)
8185 MOVA (aopGet (left, offl, FALSE, FALSE));
8186 /* shift right accumulator */
8191 aopPut (result, "a", offr);
8194 /*-----------------------------------------------------------------*/
8195 /* shiftL1Left2Result - shift left one byte from left to result */
8196 /*-----------------------------------------------------------------*/
8198 shiftL1Left2Result (operand * left, int offl,
8199 operand * result, int offr, int shCount)
8202 l = aopGet (left, offl, FALSE, FALSE);
8204 /* shift left accumulator */
8206 aopPut (result, "a", offr);
8209 /*-----------------------------------------------------------------*/
8210 /* movLeft2Result - move byte from left to result */
8211 /*-----------------------------------------------------------------*/
8213 movLeft2Result (operand * left, int offl,
8214 operand * result, int offr, int sign)
8217 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8219 l = aopGet (left, offl, FALSE, FALSE);
8221 if (*l == '@' && (IS_AOP_PREG (result)))
8223 emitcode ("mov", "a,%s", l);
8224 aopPut (result, "a", offr);
8230 aopPut (result, l, offr);
8234 /* MSB sign in acc.7 ! */
8235 if (getDataSize (left) == offl + 1)
8238 aopPut (result, "a", offr);
8245 /*-----------------------------------------------------------------*/
8246 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
8247 /*-----------------------------------------------------------------*/
8251 emitcode ("rrc", "a");
8252 emitcode ("xch", "a,%s", x);
8253 emitcode ("rrc", "a");
8254 emitcode ("xch", "a,%s", x);
8257 /*-----------------------------------------------------------------*/
8258 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
8259 /*-----------------------------------------------------------------*/
8263 emitcode ("xch", "a,%s", x);
8264 emitcode ("rlc", "a");
8265 emitcode ("xch", "a,%s", x);
8266 emitcode ("rlc", "a");
8269 /*-----------------------------------------------------------------*/
8270 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8271 /*-----------------------------------------------------------------*/
8275 emitcode ("xch", "a,%s", x);
8276 emitcode ("add", "a,acc");
8277 emitcode ("xch", "a,%s", x);
8278 emitcode ("rlc", "a");
8281 /*-----------------------------------------------------------------*/
8282 /* AccAXLsh - left shift a:x by known count (0..7) */
8283 /*-----------------------------------------------------------------*/
8285 AccAXLsh (char *x, int shCount)
8300 case 5: // AAAAABBB:CCCCCDDD
8302 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8304 emitcode ("anl", "a,#0x%02x",
8305 SLMask[shCount]); // BBB00000:CCCCCDDD
8307 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8309 AccRol (shCount); // DDDCCCCC:BBB00000
8311 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8313 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8315 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8317 emitcode ("anl", "a,#0x%02x",
8318 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8320 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8322 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8325 case 6: // AAAAAABB:CCCCCCDD
8326 emitcode ("anl", "a,#0x%02x",
8327 SRMask[shCount]); // 000000BB:CCCCCCDD
8328 emitcode ("mov", "c,acc.0"); // c = B
8329 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8331 AccAXRrl1 (x); // BCCCCCCD:D000000B
8332 AccAXRrl1 (x); // BBCCCCCC:DD000000
8334 emitcode("rrc","a");
8335 emitcode("xch","a,%s", x);
8336 emitcode("rrc","a");
8337 emitcode("mov","c,acc.0"); //<< get correct bit
8338 emitcode("xch","a,%s", x);
8340 emitcode("rrc","a");
8341 emitcode("xch","a,%s", x);
8342 emitcode("rrc","a");
8343 emitcode("xch","a,%s", x);
8346 case 7: // a:x <<= 7
8348 emitcode ("anl", "a,#0x%02x",
8349 SRMask[shCount]); // 0000000B:CCCCCCCD
8351 emitcode ("mov", "c,acc.0"); // c = B
8353 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
8355 AccAXRrl1 (x); // BCCCCCCC:D0000000
8363 /*-----------------------------------------------------------------*/
8364 /* AccAXRsh - right shift a:x known count (0..7) */
8365 /*-----------------------------------------------------------------*/
8367 AccAXRsh (char *x, int shCount)
8375 AccAXRrl1 (x); // 0->a:x
8380 AccAXRrl1 (x); // 0->a:x
8383 AccAXRrl1 (x); // 0->a:x
8388 case 5: // AAAAABBB:CCCCCDDD = a:x
8390 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8392 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8394 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8396 emitcode ("anl", "a,#0x%02x",
8397 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8399 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8401 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8403 emitcode ("anl", "a,#0x%02x",
8404 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8406 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8408 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8410 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8413 case 6: // AABBBBBB:CCDDDDDD
8415 emitcode ("mov", "c,acc.7");
8416 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8418 emitcode ("mov", "c,acc.7");
8419 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8421 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8423 emitcode ("anl", "a,#0x%02x",
8424 SRMask[shCount]); // 000000AA:BBBBBBCC
8427 case 7: // ABBBBBBB:CDDDDDDD
8429 emitcode ("mov", "c,acc.7"); // c = A
8431 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8433 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8435 emitcode ("anl", "a,#0x%02x",
8436 SRMask[shCount]); // 0000000A:BBBBBBBC
8444 /*-----------------------------------------------------------------*/
8445 /* AccAXRshS - right shift signed a:x known count (0..7) */
8446 /*-----------------------------------------------------------------*/
8448 AccAXRshS (char *x, int shCount)
8456 emitcode ("mov", "c,acc.7");
8457 AccAXRrl1 (x); // s->a:x
8461 emitcode ("mov", "c,acc.7");
8462 AccAXRrl1 (x); // s->a:x
8464 emitcode ("mov", "c,acc.7");
8465 AccAXRrl1 (x); // s->a:x
8470 case 5: // AAAAABBB:CCCCCDDD = a:x
8472 tlbl = newiTempLabel (NULL);
8473 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8475 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8477 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8479 emitcode ("anl", "a,#0x%02x",
8480 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8482 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8484 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8486 emitcode ("anl", "a,#0x%02x",
8487 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8489 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8491 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8493 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8495 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8496 emitcode ("orl", "a,#0x%02x",
8497 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8500 break; // SSSSAAAA:BBBCCCCC
8502 case 6: // AABBBBBB:CCDDDDDD
8504 tlbl = newiTempLabel (NULL);
8505 emitcode ("mov", "c,acc.7");
8506 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8508 emitcode ("mov", "c,acc.7");
8509 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8511 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8513 emitcode ("anl", "a,#0x%02x",
8514 SRMask[shCount]); // 000000AA:BBBBBBCC
8516 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8517 emitcode ("orl", "a,#0x%02x",
8518 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8522 case 7: // ABBBBBBB:CDDDDDDD
8524 tlbl = newiTempLabel (NULL);
8525 emitcode ("mov", "c,acc.7"); // c = A
8527 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8529 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8531 emitcode ("anl", "a,#0x%02x",
8532 SRMask[shCount]); // 0000000A:BBBBBBBC
8534 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8535 emitcode ("orl", "a,#0x%02x",
8536 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8545 /*-----------------------------------------------------------------*/
8546 /* shiftL2Left2Result - shift left two bytes from left to result */
8547 /*-----------------------------------------------------------------*/
8549 shiftL2Left2Result (operand * left, int offl,
8550 operand * result, int offr, int shCount)
8553 bool pushedB = FALSE;
8556 if (sameRegs (AOP (result), AOP (left)) &&
8557 ((offl + MSB16) == offr))
8559 /* don't crash result[offr] */
8560 MOVA (aopGet (left, offl, FALSE, FALSE));
8561 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8562 usedB = !strncmp(x, "b", 1);
8564 else if (aopGetUsesAcc (result, offr))
8566 movLeft2Result (left, offl, result, offr, 0);
8569 emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8570 MOVA (aopGet (result, offr, FALSE, FALSE));
8571 emitcode ("xch", "a,b");
8576 movLeft2Result (left, offl, result, offr, 0);
8577 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8578 x = aopGet (result, offr, FALSE, FALSE);
8580 /* ax << shCount (x = lsb(result)) */
8581 AccAXLsh (x, shCount);
8584 emitcode ("xch", "a,b");
8585 aopPut (result, "a", offr);
8586 aopPut (result, "b", offr + MSB16);
8591 aopPut (result, "a", offr + MSB16);
8596 /*-----------------------------------------------------------------*/
8597 /* shiftR2Left2Result - shift right two bytes from left to result */
8598 /*-----------------------------------------------------------------*/
8600 shiftR2Left2Result (operand * left, int offl,
8601 operand * result, int offr,
8602 int shCount, int sign)
8605 bool pushedB = FALSE;
8608 if (sameRegs (AOP (result), AOP (left)) &&
8609 ((offl + MSB16) == offr))
8611 /* don't crash result[offr] */
8612 MOVA (aopGet (left, offl, FALSE, FALSE));
8613 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8614 usedB = !strncmp(x, "b", 1);
8616 else if (aopGetUsesAcc (result, offr))
8618 movLeft2Result (left, offl, result, offr, 0);
8621 emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8622 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8627 movLeft2Result (left, offl, result, offr, 0);
8628 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8629 x = aopGet (result, offr, FALSE, FALSE);
8631 /* a:x >> shCount (x = lsb(result)) */
8633 AccAXRshS (x, shCount);
8635 AccAXRsh (x, shCount);
8638 emitcode ("xch", "a,b");
8639 aopPut (result, "a", offr);
8640 emitcode ("xch", "a,b");
8643 if (getDataSize (result) > 1)
8644 aopPut (result, "a", offr + MSB16);
8647 /*-----------------------------------------------------------------*/
8648 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8649 /*-----------------------------------------------------------------*/
8651 shiftLLeftOrResult (operand * left, int offl,
8652 operand * result, int offr, int shCount)
8654 MOVA (aopGet (left, offl, FALSE, FALSE));
8655 /* shift left accumulator */
8657 /* or with result */
8658 if (aopGetUsesAcc (result, offr))
8660 emitcode ("xch", "a,b");
8661 MOVA (aopGet (result, offr, FALSE, FALSE));
8662 emitcode ("orl", "a,b");
8666 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8668 /* back to result */
8669 aopPut (result, "a", offr);
8672 /*-----------------------------------------------------------------*/
8673 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8674 /*-----------------------------------------------------------------*/
8676 shiftRLeftOrResult (operand * left, int offl,
8677 operand * result, int offr, int shCount)
8679 MOVA (aopGet (left, offl, FALSE, FALSE));
8680 /* shift right accumulator */
8682 /* or with result */
8683 if (aopGetUsesAcc(result, offr))
8685 emitcode ("xch", "a,b");
8686 MOVA (aopGet (result, offr, FALSE, FALSE));
8687 emitcode ("orl", "a,b");
8691 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8693 /* back to result */
8694 aopPut (result, "a", offr);
8697 /*-----------------------------------------------------------------*/
8698 /* genlshOne - left shift a one byte quantity by known count */
8699 /*-----------------------------------------------------------------*/
8701 genlshOne (operand * result, operand * left, int shCount)
8703 D (emitcode (";", "genlshOne"));
8705 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8708 /*-----------------------------------------------------------------*/
8709 /* genlshTwo - left shift two bytes by known amount != 0 */
8710 /*-----------------------------------------------------------------*/
8712 genlshTwo (operand * result, operand * left, int shCount)
8716 D (emitcode (";", "genlshTwo"));
8718 size = getDataSize (result);
8720 /* if shCount >= 8 */
8728 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8730 movLeft2Result (left, LSB, result, MSB16, 0);
8732 aopPut (result, zero, LSB);
8735 /* 1 <= shCount <= 7 */
8739 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8741 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8745 /*-----------------------------------------------------------------*/
8746 /* shiftLLong - shift left one long from left to result */
8747 /* offl = LSB or MSB16 */
8748 /*-----------------------------------------------------------------*/
8750 shiftLLong (operand * left, operand * result, int offr)
8753 int size = AOP_SIZE (result);
8755 if (size >= LSB + offr)
8757 l = aopGet (left, LSB, FALSE, FALSE);
8759 emitcode ("add", "a,acc");
8760 if (sameRegs (AOP (left), AOP (result)) &&
8761 size >= MSB16 + offr && offr != LSB)
8762 xch_a_aopGet (left, LSB + offr, FALSE, FALSE);
8764 aopPut (result, "a", LSB + offr);
8767 if (size >= MSB16 + offr)
8769 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8771 l = aopGet (left, MSB16, FALSE, FALSE);
8774 emitcode ("rlc", "a");
8775 if (sameRegs (AOP (left), AOP (result)) &&
8776 size >= MSB24 + offr && offr != LSB)
8777 xch_a_aopGet (left, MSB16 + offr, FALSE, FALSE);
8779 aopPut (result, "a", MSB16 + offr);
8782 if (size >= MSB24 + offr)
8784 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8786 l = aopGet (left, MSB24, FALSE, FALSE);
8789 emitcode ("rlc", "a");
8790 if (sameRegs (AOP (left), AOP (result)) &&
8791 size >= MSB32 + offr && offr != LSB)
8792 xch_a_aopGet (left, MSB24 + offr, FALSE, FALSE);
8794 aopPut (result, "a", MSB24 + offr);
8797 if (size > MSB32 + offr)
8799 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8801 l = aopGet (left, MSB32, FALSE, FALSE);
8804 emitcode ("rlc", "a");
8805 aopPut (result, "a", MSB32 + offr);
8808 aopPut (result, zero, LSB);
8811 /*-----------------------------------------------------------------*/
8812 /* genlshFour - shift four byte by a known amount != 0 */
8813 /*-----------------------------------------------------------------*/
8815 genlshFour (operand * result, operand * left, int shCount)
8819 D (emitcode (";", "genlshFour"));
8821 size = AOP_SIZE (result);
8823 /* if shifting more that 3 bytes */
8828 /* lowest order of left goes to the highest
8829 order of the destination */
8830 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8832 movLeft2Result (left, LSB, result, MSB32, 0);
8833 aopPut (result, zero, LSB);
8834 aopPut (result, zero, MSB16);
8835 aopPut (result, zero, MSB24);
8839 /* more than two bytes */
8840 else if (shCount >= 16)
8842 /* lower order two bytes goes to higher order two bytes */
8844 /* if some more remaining */
8846 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8849 movLeft2Result (left, MSB16, result, MSB32, 0);
8850 movLeft2Result (left, LSB, result, MSB24, 0);
8852 aopPut (result, zero, MSB16);
8853 aopPut (result, zero, LSB);
8857 /* if more than 1 byte */
8858 else if (shCount >= 8)
8860 /* lower order three bytes goes to higher order three bytes */
8865 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8867 movLeft2Result (left, LSB, result, MSB16, 0);
8873 movLeft2Result (left, MSB24, result, MSB32, 0);
8874 movLeft2Result (left, MSB16, result, MSB24, 0);
8875 movLeft2Result (left, LSB, result, MSB16, 0);
8876 aopPut (result, zero, LSB);
8878 else if (shCount == 1)
8879 shiftLLong (left, result, MSB16);
8882 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8883 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8884 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8885 aopPut (result, zero, LSB);
8890 /* 1 <= shCount <= 7 */
8891 else if (shCount <= 2)
8893 shiftLLong (left, result, LSB);
8895 shiftLLong (result, result, LSB);
8897 /* 3 <= shCount <= 7, optimize */
8900 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8901 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8902 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8906 /*-----------------------------------------------------------------*/
8907 /* genLeftShiftLiteral - left shifting by known count */
8908 /*-----------------------------------------------------------------*/
8910 genLeftShiftLiteral (operand * left,
8915 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8918 D (emitcode (";", "genLeftShiftLiteral"));
8920 freeAsmop (right, NULL, ic, TRUE);
8922 aopOp (left, ic, FALSE);
8923 aopOp (result, ic, FALSE);
8925 size = getSize (operandType (result));
8928 emitcode ("; shift left ", "result %d, left %d", size,
8932 /* I suppose that the left size >= result size */
8937 movLeft2Result (left, size, result, size, 0);
8940 else if (shCount >= (size * 8))
8944 aopPut (result, zero, size);
8952 genlshOne (result, left, shCount);
8956 genlshTwo (result, left, shCount);
8960 genlshFour (result, left, shCount);
8963 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8964 "*** ack! mystery literal shift!\n");
8968 freeAsmop (result, NULL, ic, TRUE);
8969 freeAsmop (left, NULL, ic, TRUE);
8972 /*-----------------------------------------------------------------*/
8973 /* genLeftShift - generates code for left shifting */
8974 /*-----------------------------------------------------------------*/
8976 genLeftShift (iCode * ic)
8978 operand *left, *right, *result;
8981 symbol *tlbl, *tlbl1;
8984 D (emitcode (";", "genLeftShift"));
8986 right = IC_RIGHT (ic);
8987 left = IC_LEFT (ic);
8988 result = IC_RESULT (ic);
8990 aopOp (right, ic, FALSE);
8992 /* if the shift count is known then do it
8993 as efficiently as possible */
8994 if (AOP_TYPE (right) == AOP_LIT)
8996 genLeftShiftLiteral (left, right, result, ic);
9000 /* shift count is unknown then we have to form
9001 a loop get the loop count in B : Note: we take
9002 only the lower order byte since shifting
9003 more that 32 bits make no sense anyway, ( the
9004 largest size of an object can be only 32 bits ) */
9007 MOVB (aopGet (right, 0, FALSE, FALSE));
9008 emitcode ("inc", "b");
9009 freeAsmop (right, NULL, ic, TRUE);
9010 aopOp (left, ic, FALSE);
9011 aopOp (result, ic, FALSE);
9013 /* now move the left to the result if they are not the same */
9014 if (!sameRegs (AOP (left), AOP (result)) &&
9015 AOP_SIZE (result) > 1)
9018 size = AOP_SIZE (result);
9022 l = aopGet (left, offset, FALSE, TRUE);
9023 if (*l == '@' && (IS_AOP_PREG (result)))
9026 emitcode ("mov", "a,%s", l);
9027 aopPut (result, "a", offset);
9030 aopPut (result, l, offset);
9035 tlbl = newiTempLabel (NULL);
9036 size = AOP_SIZE (result);
9038 tlbl1 = newiTempLabel (NULL);
9040 /* if it is only one byte then */
9043 symbol *tlbl1 = newiTempLabel (NULL);
9045 l = aopGet (left, 0, FALSE, FALSE);
9047 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9049 emitcode ("add", "a,acc");
9051 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9053 aopPut (result, "a", 0);
9057 reAdjustPreg (AOP (result));
9059 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9061 l = aopGet (result, offset, FALSE, FALSE);
9063 emitcode ("add", "a,acc");
9064 aopPut (result, "a", offset++);
9067 l = aopGet (result, offset, FALSE, FALSE);
9069 emitcode ("rlc", "a");
9070 aopPut (result, "a", offset++);
9072 reAdjustPreg (AOP (result));
9075 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9078 freeAsmop (result, NULL, ic, TRUE);
9079 freeAsmop (left, NULL, ic, TRUE);
9082 /*-----------------------------------------------------------------*/
9083 /* genrshOne - right shift a one byte quantity by known count */
9084 /*-----------------------------------------------------------------*/
9086 genrshOne (operand * result, operand * left,
9087 int shCount, int sign)
9089 D (emitcode (";", "genrshOne"));
9091 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9094 /*-----------------------------------------------------------------*/
9095 /* genrshTwo - right shift two bytes by known amount != 0 */
9096 /*-----------------------------------------------------------------*/
9098 genrshTwo (operand * result, operand * left,
9099 int shCount, int sign)
9101 D (emitcode (";", "genrshTwo"));
9103 /* if shCount >= 8 */
9108 shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
9110 movLeft2Result (left, MSB16, result, LSB, sign);
9111 addSign (result, MSB16, sign);
9114 /* 1 <= shCount <= 7 */
9116 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9119 /*-----------------------------------------------------------------*/
9120 /* shiftRLong - shift right one long from left to result */
9121 /* offl = LSB or MSB16 */
9122 /*-----------------------------------------------------------------*/
9124 shiftRLong (operand * left, int offl,
9125 operand * result, int sign)
9127 bool overlapping = regsInCommon (left, result) || operandsEqu(left, result);
9129 if (overlapping && offl>1)
9131 // we are in big trouble, but this shouldn't happen
9132 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9135 MOVA (aopGet (left, MSB32, FALSE, FALSE));
9142 emitcode ("rlc", "a");
9143 emitcode ("subb", "a,acc");
9144 if (overlapping && sameByte (AOP (left), MSB32, AOP (result), MSB32))
9146 xch_a_aopGet (left, MSB32, FALSE, FALSE);
9150 aopPut (result, "a", MSB32);
9151 MOVA (aopGet (left, MSB32, FALSE, FALSE));
9156 if (aopPutUsesAcc (result, zero, MSB32))
9158 emitcode("xch", "a,b");
9159 aopPut (result, zero, MSB32);
9160 emitcode("xch", "a,b");
9164 aopPut (result, zero, MSB32);
9171 emitcode ("clr", "c");
9175 emitcode ("mov", "c,acc.7");
9178 emitcode ("rrc", "a");
9180 if (overlapping && offl==MSB16 &&
9181 sameByte (AOP (left), MSB24, AOP (result), MSB32-offl))
9183 xch_a_aopGet (left, MSB24, FALSE, FALSE);
9187 aopPut (result, "a", MSB32 - offl);
9188 MOVA (aopGet (left, MSB24, FALSE, FALSE));
9191 emitcode ("rrc", "a");
9192 if (overlapping && offl==MSB16 &&
9193 sameByte (AOP (left), MSB16, AOP (result), MSB24-offl))
9195 xch_a_aopGet (left, MSB16, FALSE, FALSE);
9199 aopPut (result, "a", MSB24 - offl);
9200 MOVA (aopGet (left, MSB16, FALSE, FALSE));
9203 emitcode ("rrc", "a");
9206 aopPut (result, "a", MSB16 - offl);
9211 sameByte (AOP (left), LSB, AOP (result), MSB16-offl))
9213 xch_a_aopGet (left, LSB, FALSE, FALSE);
9217 aopPut (result, "a", MSB16 - offl);
9218 MOVA (aopGet (left, LSB, FALSE, FALSE));
9220 emitcode ("rrc", "a");
9221 aopPut (result, "a", LSB);
9225 /*-----------------------------------------------------------------*/
9226 /* genrshFour - shift four byte by a known amount != 0 */
9227 /*-----------------------------------------------------------------*/
9229 genrshFour (operand * result, operand * left,
9230 int shCount, int sign)
9232 D (emitcode (";", "genrshFour"));
9234 /* if shifting more that 3 bytes */
9239 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9241 movLeft2Result (left, MSB32, result, LSB, sign);
9242 addSign (result, MSB16, sign);
9244 else if (shCount >= 16)
9248 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9251 movLeft2Result (left, MSB24, result, LSB, 0);
9252 movLeft2Result (left, MSB32, result, MSB16, sign);
9254 addSign (result, MSB24, sign);
9256 else if (shCount >= 8)
9261 shiftRLong (left, MSB16, result, sign);
9263 else if (shCount == 0)
9265 movLeft2Result (left, MSB16, result, LSB, 0);
9266 movLeft2Result (left, MSB24, result, MSB16, 0);
9267 movLeft2Result (left, MSB32, result, MSB24, sign);
9268 addSign (result, MSB32, sign);
9272 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9273 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9274 /* the last shift is signed */
9275 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9276 addSign (result, MSB32, sign);
9281 /* 1 <= shCount <= 7 */
9284 shiftRLong (left, LSB, result, sign);
9286 shiftRLong (result, LSB, result, sign);
9290 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9291 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9292 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9297 /*-----------------------------------------------------------------*/
9298 /* genRightShiftLiteral - right shifting by known count */
9299 /*-----------------------------------------------------------------*/
9301 genRightShiftLiteral (operand * left,
9307 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9310 D (emitcode (";", "genRightShiftLiteral"));
9312 freeAsmop (right, NULL, ic, TRUE);
9314 aopOp (left, ic, FALSE);
9315 aopOp (result, ic, FALSE);
9318 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9322 size = getDataSize (left);
9323 /* test the LEFT size !!! */
9325 /* I suppose that the left size >= result size */
9328 size = getDataSize (result);
9330 movLeft2Result (left, size, result, size, 0);
9333 else if (shCount >= (size * 8))
9337 /* get sign in acc.7 */
9338 MOVA (aopGet (left, size - 1, FALSE, FALSE));
9340 addSign (result, LSB, sign);
9347 genrshOne (result, left, shCount, sign);
9351 genrshTwo (result, left, shCount, sign);
9355 genrshFour (result, left, shCount, sign);
9361 freeAsmop (result, NULL, ic, TRUE);
9362 freeAsmop (left, NULL, ic, TRUE);
9365 /*-----------------------------------------------------------------*/
9366 /* genSignedRightShift - right shift of signed number */
9367 /*-----------------------------------------------------------------*/
9369 genSignedRightShift (iCode * ic)
9371 operand *right, *left, *result;
9374 symbol *tlbl, *tlbl1;
9377 D (emitcode (";", "genSignedRightShift"));
9379 /* we do it the hard way put the shift count in b
9380 and loop thru preserving the sign */
9382 right = IC_RIGHT (ic);
9383 left = IC_LEFT (ic);
9384 result = IC_RESULT (ic);
9386 aopOp (right, ic, FALSE);
9389 if (AOP_TYPE (right) == AOP_LIT)
9391 genRightShiftLiteral (left, right, result, ic, 1);
9394 /* shift count is unknown then we have to form
9395 a loop get the loop count in B : Note: we take
9396 only the lower order byte since shifting
9397 more that 32 bits make no sense anyway, ( the
9398 largest size of an object can be only 32 bits ) */
9401 MOVB (aopGet (right, 0, FALSE, FALSE));
9402 emitcode ("inc", "b");
9403 freeAsmop (right, NULL, ic, TRUE);
9404 aopOp (left, ic, FALSE);
9405 aopOp (result, ic, FALSE);
9407 /* now move the left to the result if they are not the
9409 if (!sameRegs (AOP (left), AOP (result)) &&
9410 AOP_SIZE (result) > 1)
9413 size = AOP_SIZE (result);
9417 l = aopGet (left, offset, FALSE, TRUE);
9418 if (*l == '@' && IS_AOP_PREG (result))
9421 emitcode ("mov", "a,%s", l);
9422 aopPut (result, "a", offset);
9425 aopPut (result, l, offset);
9430 /* mov the highest order bit to OVR */
9431 tlbl = newiTempLabel (NULL);
9432 tlbl1 = newiTempLabel (NULL);
9434 size = AOP_SIZE (result);
9436 MOVA (aopGet (left, offset, FALSE, FALSE));
9437 emitcode ("rlc", "a");
9438 emitcode ("mov", "ov,c");
9439 /* if it is only one byte then */
9442 l = aopGet (left, 0, FALSE, FALSE);
9444 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9446 emitcode ("mov", "c,ov");
9447 emitcode ("rrc", "a");
9449 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9451 aopPut (result, "a", 0);
9455 reAdjustPreg (AOP (result));
9456 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9458 emitcode ("mov", "c,ov");
9461 l = aopGet (result, offset, FALSE, FALSE);
9463 emitcode ("rrc", "a");
9464 aopPut (result, "a", offset--);
9466 reAdjustPreg (AOP (result));
9468 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9472 freeAsmop (result, NULL, ic, TRUE);
9473 freeAsmop (left, NULL, ic, TRUE);
9476 /*-----------------------------------------------------------------*/
9477 /* genRightShift - generate code for right shifting */
9478 /*-----------------------------------------------------------------*/
9480 genRightShift (iCode * ic)
9482 operand *right, *left, *result;
9486 symbol *tlbl, *tlbl1;
9489 D (emitcode (";", "genRightShift"));
9491 /* if signed then we do it the hard way preserve the
9492 sign bit moving it inwards */
9493 letype = getSpec (operandType (IC_LEFT (ic)));
9495 if (!SPEC_USIGN (letype))
9497 genSignedRightShift (ic);
9501 /* signed & unsigned types are treated the same : i.e. the
9502 signed is NOT propagated inwards : quoting from the
9503 ANSI - standard : "for E1 >> E2, is equivalent to division
9504 by 2**E2 if unsigned or if it has a non-negative value,
9505 otherwise the result is implementation defined ", MY definition
9506 is that the sign does not get propagated */
9508 right = IC_RIGHT (ic);
9509 left = IC_LEFT (ic);
9510 result = IC_RESULT (ic);
9512 aopOp (right, ic, FALSE);
9514 /* if the shift count is known then do it
9515 as efficiently as possible */
9516 if (AOP_TYPE (right) == AOP_LIT)
9518 genRightShiftLiteral (left, right, result, ic, 0);
9522 /* shift count is unknown then we have to form
9523 a loop get the loop count in B : Note: we take
9524 only the lower order byte since shifting
9525 more that 32 bits make no sense anyway, ( the
9526 largest size of an object can be only 32 bits ) */
9529 MOVB (aopGet (right, 0, FALSE, FALSE));
9530 emitcode ("inc", "b");
9531 freeAsmop (right, NULL, ic, TRUE);
9532 aopOp (left, ic, FALSE);
9533 aopOp (result, ic, FALSE);
9535 /* now move the left to the result if they are not the
9537 if (!sameRegs (AOP (left), AOP (result)) &&
9538 AOP_SIZE (result) > 1)
9540 size = AOP_SIZE (result);
9544 l = aopGet (left, offset, FALSE, TRUE);
9545 if (*l == '@' && IS_AOP_PREG (result))
9548 emitcode ("mov", "a,%s", l);
9549 aopPut (result, "a", offset);
9552 aopPut (result, l, offset);
9557 tlbl = newiTempLabel (NULL);
9558 tlbl1 = newiTempLabel (NULL);
9559 size = AOP_SIZE (result);
9562 /* if it is only one byte then */
9565 l = aopGet (left, 0, FALSE, FALSE);
9567 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9570 emitcode ("rrc", "a");
9572 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9574 aopPut (result, "a", 0);
9578 reAdjustPreg (AOP (result));
9579 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9584 l = aopGet (result, offset, FALSE, FALSE);
9586 emitcode ("rrc", "a");
9587 aopPut (result, "a", offset--);
9589 reAdjustPreg (AOP (result));
9592 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9596 freeAsmop (result, NULL, ic, TRUE);
9597 freeAsmop (left, NULL, ic, TRUE);
9600 /*-----------------------------------------------------------------*/
9601 /* emitPtrByteGet - emits code to get a byte into A through a */
9602 /* pointer register (R0, R1, or DPTR). The */
9603 /* original value of A can be preserved in B. */
9604 /*-----------------------------------------------------------------*/
9606 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9613 emitcode ("mov", "b,a");
9614 emitcode ("mov", "a,@%s", rname);
9619 emitcode ("mov", "b,a");
9620 emitcode ("movx", "a,@%s", rname);
9625 emitcode ("mov", "b,a");
9626 emitcode ("movx", "a,@dptr");
9631 emitcode ("mov", "b,a");
9632 emitcode ("clr", "a");
9633 emitcode ("movc", "a,@a+dptr");
9639 emitcode ("push", "b");
9640 emitcode ("push", "acc");
9642 emitcode ("lcall", "__gptrget");
9644 emitcode ("pop", "b");
9649 /*-----------------------------------------------------------------*/
9650 /* emitPtrByteSet - emits code to set a byte from src through a */
9651 /* pointer register (R0, R1, or DPTR). */
9652 /*-----------------------------------------------------------------*/
9654 emitPtrByteSet (char *rname, int p_type, char *src)
9663 emitcode ("mov", "@%s,a", rname);
9666 emitcode ("mov", "@%s,%s", rname, src);
9671 emitcode ("movx", "@%s,a", rname);
9676 emitcode ("movx", "@dptr,a");
9681 emitcode ("lcall", "__gptrput");
9686 /*-----------------------------------------------------------------*/
9687 /* genUnpackBits - generates code for unpacking bits */
9688 /*-----------------------------------------------------------------*/
9690 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9692 int offset = 0; /* result byte offset */
9693 int rsize; /* result size */
9694 int rlen = 0; /* remaining bitfield length */
9695 sym_link *etype; /* bitfield type information */
9696 int blen; /* bitfield length */
9697 int bstr; /* bitfield starting bit within byte */
9700 D(emitcode ("; genUnpackBits",""));
9702 etype = getSpec (operandType (result));
9703 rsize = getSize (operandType (result));
9704 blen = SPEC_BLEN (etype);
9705 bstr = SPEC_BSTR (etype);
9707 if (ifx && blen <= 8)
9709 emitPtrByteGet (rname, ptype, FALSE);
9712 SNPRINTF (buffer, sizeof(buffer),
9714 genIfxJump (ifx, buffer, NULL, NULL, NULL);
9719 emitcode ("anl", "a,#0x%02x",
9720 (((unsigned char) -1) >> (8 - blen)) << bstr);
9721 genIfxJump (ifx, "a", NULL, NULL, NULL);
9727 /* If the bitfield length is less than a byte */
9730 emitPtrByteGet (rname, ptype, FALSE);
9732 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9733 if (!SPEC_USIGN (etype))
9735 /* signed bitfield */
9736 symbol *tlbl = newiTempLabel (NULL);
9738 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9739 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9742 aopPut (result, "a", offset++);
9746 /* Bit field did not fit in a byte. Copy all
9747 but the partial byte at the end. */
9748 for (rlen=blen;rlen>=8;rlen-=8)
9750 emitPtrByteGet (rname, ptype, FALSE);
9751 aopPut (result, "a", offset++);
9753 emitcode ("inc", "%s", rname);
9756 /* Handle the partial byte at the end */
9759 emitPtrByteGet (rname, ptype, FALSE);
9760 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9761 if (!SPEC_USIGN (etype))
9763 /* signed bitfield */
9764 symbol *tlbl = newiTempLabel (NULL);
9766 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9767 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9770 aopPut (result, "a", offset++);
9778 if (SPEC_USIGN (etype))
9782 /* signed bitfield: sign extension with 0x00 or 0xff */
9783 emitcode ("rlc", "a");
9784 emitcode ("subb", "a,acc");
9790 aopPut (result, source, offset++);
9795 /*-----------------------------------------------------------------*/
9796 /* genDataPointerGet - generates code when ptr offset is known */
9797 /*-----------------------------------------------------------------*/
9799 genDataPointerGet (operand * left,
9805 int size, offset = 0;
9807 D (emitcode (";", "genDataPointerGet"));
9809 aopOp (result, ic, TRUE);
9811 /* get the string representation of the name */
9812 l = aopGet (left, 0, FALSE, TRUE);
9814 size = AOP_SIZE (result);
9819 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
9823 SNPRINTF (buffer, sizeof(buffer), "%s", l);
9825 aopPut (result, buffer, offset++);
9828 freeAsmop (result, NULL, ic, TRUE);
9829 freeAsmop (left, NULL, ic, TRUE);
9832 /*-----------------------------------------------------------------*/
9833 /* genNearPointerGet - emitcode for near pointer fetch */
9834 /*-----------------------------------------------------------------*/
9836 genNearPointerGet (operand * left,
9845 sym_link *rtype, *retype;
9846 sym_link *ltype = operandType (left);
9849 D (emitcode (";", "genNearPointerGet"));
9851 rtype = operandType (result);
9852 retype = getSpec (rtype);
9854 aopOp (left, ic, FALSE);
9856 /* if left is rematerialisable and
9857 result is not bitfield variable type and
9858 the left is pointer to data space i.e
9859 lower 128 bytes of space */
9860 if (AOP_TYPE (left) == AOP_IMMD &&
9861 !IS_BITFIELD (retype) &&
9862 DCL_TYPE (ltype) == POINTER)
9864 genDataPointerGet (left, result, ic);
9868 /* if the value is already in a pointer register
9869 then don't need anything more */
9870 if (!AOP_INPREG (AOP (left)))
9872 if (IS_AOP_PREG (left))
9874 // Aha, it is a pointer, just in disguise.
9875 rname = aopGet (left, 0, FALSE, FALSE);
9878 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9879 __FILE__, __LINE__);
9884 emitcode ("mov", "a%s,%s", rname + 1, rname);
9885 rname++; // skip the '@'.
9890 /* otherwise get a free pointer register */
9892 preg = getFreePtr (ic, &aop, FALSE);
9893 emitcode ("mov", "%s,%s",
9895 aopGet (left, 0, FALSE, TRUE));
9900 rname = aopGet (left, 0, FALSE, FALSE);
9902 //aopOp (result, ic, FALSE);
9903 aopOp (result, ic, result?TRUE:FALSE);
9905 /* if bitfield then unpack the bits */
9906 if (IS_BITFIELD (retype))
9907 genUnpackBits (result, rname, POINTER, ifx);
9910 /* we have can just get the values */
9911 int size = AOP_SIZE (result);
9916 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9919 emitcode ("mov", "a,@%s", rname);
9921 aopPut (result, "a", offset);
9925 SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
9926 aopPut (result, buffer, offset);
9930 emitcode ("inc", "%s", rname);
9934 /* now some housekeeping stuff */
9935 if (aop) /* we had to allocate for this iCode */
9937 if (pi) { /* post increment present */
9938 aopPut (left, rname, 0);
9940 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9944 /* we did not allocate which means left
9945 already in a pointer register, then
9946 if size > 0 && this could be used again
9947 we have to point it back to where it
9949 if ((AOP_SIZE (result) > 1 &&
9950 !OP_SYMBOL (left)->remat &&
9951 (OP_SYMBOL (left)->liveTo > ic->seq ||
9955 int size = AOP_SIZE (result) - 1;
9957 emitcode ("dec", "%s", rname);
9961 if (ifx && !ifx->generated)
9963 genIfxJump (ifx, "a", left, NULL, result);
9967 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9968 freeAsmop (left, NULL, ic, TRUE);
9969 if (pi) pi->generated = 1;
9972 /*-----------------------------------------------------------------*/
9973 /* genPagedPointerGet - emitcode for paged pointer fetch */
9974 /*-----------------------------------------------------------------*/
9976 genPagedPointerGet (operand * left,
9985 sym_link *rtype, *retype;
9987 D (emitcode (";", "genPagedPointerGet"));
9989 rtype = operandType (result);
9990 retype = getSpec (rtype);
9992 aopOp (left, ic, FALSE);
9994 /* if the value is already in a pointer register
9995 then don't need anything more */
9996 if (!AOP_INPREG (AOP (left)))
9998 /* otherwise get a free pointer register */
10000 preg = getFreePtr (ic, &aop, FALSE);
10001 emitcode ("mov", "%s,%s",
10003 aopGet (left, 0, FALSE, TRUE));
10004 rname = preg->name;
10007 rname = aopGet (left, 0, FALSE, FALSE);
10009 aopOp (result, ic, FALSE);
10011 /* if bitfield then unpack the bits */
10012 if (IS_BITFIELD (retype))
10013 genUnpackBits (result, rname, PPOINTER, ifx);
10016 /* we have can just get the values */
10017 int size = AOP_SIZE (result);
10023 emitcode ("movx", "a,@%s", rname);
10025 aopPut (result, "a", offset);
10030 emitcode ("inc", "%s", rname);
10034 /* now some housekeeping stuff */
10035 if (aop) /* we had to allocate for this iCode */
10038 aopPut (left, rname, 0);
10039 freeAsmop (NULL, aop, ic, TRUE);
10043 /* we did not allocate which means left
10044 already in a pointer register, then
10045 if size > 0 && this could be used again
10046 we have to point it back to where it
10048 if ((AOP_SIZE (result) > 1 &&
10049 !OP_SYMBOL (left)->remat &&
10050 (OP_SYMBOL (left)->liveTo > ic->seq ||
10054 int size = AOP_SIZE (result) - 1;
10056 emitcode ("dec", "%s", rname);
10060 if (ifx && !ifx->generated)
10062 genIfxJump (ifx, "a", left, NULL, result);
10066 freeAsmop (result, NULL, ic, TRUE);
10067 freeAsmop (left, NULL, ic, TRUE);
10068 if (pi) pi->generated = 1;
10071 /*--------------------------------------------------------------------*/
10072 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
10073 /*--------------------------------------------------------------------*/
10075 loadDptrFromOperand (operand *op, bool loadBToo)
10077 if (AOP_TYPE (op) != AOP_STR)
10079 /* if this is rematerializable */
10080 if (AOP_TYPE (op) == AOP_IMMD)
10082 emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
10085 if (AOP(op)->aopu.aop_immd.from_cast_remat)
10086 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
10089 wassertl(FALSE, "need pointerCode");
10090 emitcode ("", "; mov b,???");
10091 /* genPointerGet and genPointerSet originally did different
10092 ** things for this case. Both seem wrong.
10093 ** from genPointerGet:
10094 ** emitcode ("mov", "b,#%d", pointerCode (retype));
10095 ** from genPointerSet:
10096 ** emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
10101 else if (AOP_TYPE (op) == AOP_DPTR)
10105 MOVA (aopGet (op, 0, FALSE, FALSE));
10106 emitcode ("push", "acc");
10107 MOVA (aopGet (op, 1, FALSE, FALSE));
10108 emitcode ("push", "acc");
10109 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10110 emitcode ("pop", "dph");
10111 emitcode ("pop", "dpl");
10115 MOVA (aopGet (op, 0, FALSE, FALSE));
10116 emitcode ("push", "acc");
10117 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10118 emitcode ("pop", "dpl");
10122 { /* we need to get it byte by byte */
10123 emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
10124 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10126 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10131 /*-----------------------------------------------------------------*/
10132 /* genFarPointerGet - get value from far space */
10133 /*-----------------------------------------------------------------*/
10135 genFarPointerGet (operand * left,
10136 operand * result, iCode * ic, iCode * pi, iCode * ifx)
10139 sym_link *retype = getSpec (operandType (result));
10141 D (emitcode (";", "genFarPointerGet"));
10143 aopOp (left, ic, FALSE);
10144 loadDptrFromOperand (left, FALSE);
10146 /* so dptr now contains the address */
10147 aopOp (result, ic, FALSE);
10149 /* if bit then unpack */
10150 if (IS_BITFIELD (retype))
10151 genUnpackBits (result, "dptr", FPOINTER, ifx);
10154 size = AOP_SIZE (result);
10159 emitcode ("movx", "a,@dptr");
10161 aopPut (result, "a", offset++);
10163 emitcode ("inc", "dptr");
10167 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10169 aopPut (left, "dpl", 0);
10170 aopPut (left, "dph", 1);
10174 if (ifx && !ifx->generated)
10176 genIfxJump (ifx, "a", left, NULL, result);
10179 freeAsmop (result, NULL, ic, TRUE);
10180 freeAsmop (left, NULL, ic, TRUE);
10183 /*-----------------------------------------------------------------*/
10184 /* genCodePointerGet - get value from code space */
10185 /*-----------------------------------------------------------------*/
10187 genCodePointerGet (operand * left,
10188 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10191 sym_link *retype = getSpec (operandType (result));
10193 D (emitcode (";", "genCodePointerGet"));
10195 aopOp (left, ic, FALSE);
10196 loadDptrFromOperand (left, FALSE);
10198 /* so dptr now contains the address */
10199 aopOp (result, ic, FALSE);
10201 /* if bit then unpack */
10202 if (IS_BITFIELD (retype))
10203 genUnpackBits (result, "dptr", CPOINTER, ifx);
10206 size = AOP_SIZE (result);
10211 emitcode ("clr", "a");
10212 emitcode ("movc", "a,@a+dptr");
10214 aopPut (result, "a", offset++);
10216 emitcode ("inc", "dptr");
10220 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10222 aopPut (left, "dpl", 0);
10223 aopPut (left, "dph", 1);
10227 if (ifx && !ifx->generated)
10229 genIfxJump (ifx, "a", left, NULL, result);
10232 freeAsmop (result, NULL, ic, TRUE);
10233 freeAsmop (left, NULL, ic, TRUE);
10236 /*-----------------------------------------------------------------*/
10237 /* genGenPointerGet - get value from generic pointer space */
10238 /*-----------------------------------------------------------------*/
10240 genGenPointerGet (operand * left,
10241 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10244 sym_link *retype = getSpec (operandType (result));
10246 D (emitcode (";", "genGenPointerGet"));
10248 aopOp (left, ic, FALSE);
10249 loadDptrFromOperand (left, TRUE);
10251 /* so dptr now contains the address */
10252 aopOp (result, ic, FALSE);
10254 /* if bit then unpack */
10255 if (IS_BITFIELD (retype))
10257 genUnpackBits (result, "dptr", GPOINTER, ifx);
10261 size = AOP_SIZE (result);
10266 emitcode ("lcall", "__gptrget");
10268 aopPut (result, "a", offset++);
10270 emitcode ("inc", "dptr");
10274 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10276 aopPut (left, "dpl", 0);
10277 aopPut (left, "dph", 1);
10281 if (ifx && !ifx->generated)
10283 genIfxJump (ifx, "a", left, NULL, result);
10286 freeAsmop (result, NULL, ic, TRUE);
10287 freeAsmop (left, NULL, ic, TRUE);
10290 /*-----------------------------------------------------------------*/
10291 /* genPointerGet - generate code for pointer get */
10292 /*-----------------------------------------------------------------*/
10294 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
10296 operand *left, *result;
10297 sym_link *type, *etype;
10300 D (emitcode (";", "genPointerGet"));
10302 left = IC_LEFT (ic);
10303 result = IC_RESULT (ic);
10305 if (getSize (operandType (result))>1)
10308 /* depending on the type of pointer we need to
10309 move it to the correct pointer register */
10310 type = operandType (left);
10311 etype = getSpec (type);
10312 /* if left is of type of pointer then it is simple */
10313 if (IS_PTR (type) && !IS_FUNC (type->next))
10314 p_type = DCL_TYPE (type);
10317 /* we have to go by the storage class */
10318 p_type = PTR_TYPE (SPEC_OCLS (etype));
10321 /* special case when cast remat */
10322 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10323 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10325 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10326 type = operandType (left);
10327 p_type = DCL_TYPE (type);
10329 /* now that we have the pointer type we assign
10330 the pointer values */
10336 genNearPointerGet (left, result, ic, pi, ifx);
10340 genPagedPointerGet (left, result, ic, pi, ifx);
10344 genFarPointerGet (left, result, ic, pi, ifx);
10348 genCodePointerGet (left, result, ic, pi, ifx);
10352 genGenPointerGet (left, result, ic, pi, ifx);
10358 /*-----------------------------------------------------------------*/
10359 /* genPackBits - generates code for packed bit storage */
10360 /*-----------------------------------------------------------------*/
10362 genPackBits (sym_link * etype,
10364 char *rname, int p_type)
10366 int offset = 0; /* source byte offset */
10367 int rlen = 0; /* remaining bitfield length */
10368 int blen; /* bitfield length */
10369 int bstr; /* bitfield starting bit within byte */
10370 int litval; /* source literal value (if AOP_LIT) */
10371 unsigned char mask; /* bitmask within current byte */
10373 D(emitcode ("; genPackBits",""));
10375 blen = SPEC_BLEN (etype);
10376 bstr = SPEC_BSTR (etype);
10378 /* If the bitfield length is less than a byte */
10381 mask = ((unsigned char) (0xFF << (blen + bstr)) |
10382 (unsigned char) (0xFF >> (8 - bstr)));
10384 if (AOP_TYPE (right) == AOP_LIT)
10386 /* Case with a bitfield length <8 and literal source
10388 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10390 litval &= (~mask) & 0xff;
10391 emitPtrByteGet (rname, p_type, FALSE);
10392 if ((mask|litval)!=0xff)
10393 emitcode ("anl","a,#0x%02x", mask);
10395 emitcode ("orl","a,#0x%02x", litval);
10399 if ((blen==1) && (p_type!=GPOINTER))
10401 /* Case with a bitfield length == 1 and no generic pointer
10403 if (AOP_TYPE (right) == AOP_CRY)
10404 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10407 MOVA (aopGet (right, 0, FALSE, FALSE));
10408 emitcode ("rrc","a");
10410 emitPtrByteGet (rname, p_type, FALSE);
10411 emitcode ("mov","acc.%d,c",bstr);
10416 /* Case with a bitfield length < 8 and arbitrary source
10418 MOVA (aopGet (right, 0, FALSE, FALSE));
10419 /* shift and mask source value */
10421 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10423 pushedB = pushB ();
10424 /* transfer A to B and get next byte */
10425 emitPtrByteGet (rname, p_type, TRUE);
10427 emitcode ("anl", "a,#0x%02x", mask);
10428 emitcode ("orl", "a,b");
10429 if (p_type == GPOINTER)
10430 emitcode ("pop", "b");
10436 emitPtrByteSet (rname, p_type, "a");
10440 /* Bit length is greater than 7 bits. In this case, copy */
10441 /* all except the partial byte at the end */
10442 for (rlen=blen;rlen>=8;rlen-=8)
10444 emitPtrByteSet (rname, p_type,
10445 aopGet (right, offset++, FALSE, TRUE) );
10447 emitcode ("inc", "%s", rname);
10450 /* If there was a partial byte at the end */
10453 mask = (((unsigned char) -1 << rlen) & 0xff);
10455 if (AOP_TYPE (right) == AOP_LIT)
10457 /* Case with partial byte and literal source
10459 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10460 litval >>= (blen-rlen);
10461 litval &= (~mask) & 0xff;
10462 emitPtrByteGet (rname, p_type, FALSE);
10463 if ((mask|litval)!=0xff)
10464 emitcode ("anl","a,#0x%02x", mask);
10466 emitcode ("orl","a,#0x%02x", litval);
10471 /* Case with partial byte and arbitrary source
10473 MOVA (aopGet (right, offset++, FALSE, FALSE));
10474 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10476 pushedB = pushB ();
10477 /* transfer A to B and get next byte */
10478 emitPtrByteGet (rname, p_type, TRUE);
10480 emitcode ("anl", "a,#0x%02x", mask);
10481 emitcode ("orl", "a,b");
10482 if (p_type == GPOINTER)
10483 emitcode ("pop", "b");
10487 emitPtrByteSet (rname, p_type, "a");
10492 /*-----------------------------------------------------------------*/
10493 /* genDataPointerSet - remat pointer to data space */
10494 /*-----------------------------------------------------------------*/
10496 genDataPointerSet (operand * right,
10500 int size, offset = 0;
10501 char *l, buffer[256];
10503 D (emitcode (";", "genDataPointerSet"));
10505 aopOp (right, ic, FALSE);
10507 l = aopGet (result, 0, FALSE, TRUE);
10509 size = AOP_SIZE (right);
10513 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
10515 SNPRINTF (buffer, sizeof(buffer), "%s", l);
10516 emitcode ("mov", "%s,%s", buffer,
10517 aopGet (right, offset++, FALSE, FALSE));
10520 freeAsmop (result, NULL, ic, TRUE);
10521 freeAsmop (right, NULL, ic, TRUE);
10524 /*-----------------------------------------------------------------*/
10525 /* genNearPointerSet - emitcode for near pointer put */
10526 /*-----------------------------------------------------------------*/
10528 genNearPointerSet (operand * right,
10536 sym_link *retype, *letype;
10537 sym_link *ptype = operandType (result);
10539 D (emitcode (";", "genNearPointerSet"));
10541 retype = getSpec (operandType (right));
10542 letype = getSpec (ptype);
10544 aopOp (result, ic, FALSE);
10546 /* if the result is rematerializable &
10547 in data space & not a bit variable */
10548 if (AOP_TYPE (result) == AOP_IMMD &&
10549 DCL_TYPE (ptype) == POINTER &&
10550 !IS_BITVAR (retype) &&
10551 !IS_BITVAR (letype))
10553 genDataPointerSet (right, result, ic);
10557 /* if the value is already in a pointer register
10558 then don't need anything more */
10559 if (!AOP_INPREG (AOP (result)))
10562 //AOP_TYPE (result) == AOP_STK
10563 IS_AOP_PREG(result)
10566 // Aha, it is a pointer, just in disguise.
10567 rname = aopGet (result, 0, FALSE, FALSE);
10570 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10571 __FILE__, __LINE__);
10576 emitcode ("mov", "a%s,%s", rname + 1, rname);
10577 rname++; // skip the '@'.
10582 /* otherwise get a free pointer register */
10583 aop = newAsmop (0);
10584 preg = getFreePtr (ic, &aop, FALSE);
10585 emitcode ("mov", "%s,%s",
10587 aopGet (result, 0, FALSE, TRUE));
10588 rname = preg->name;
10593 rname = aopGet (result, 0, FALSE, FALSE);
10596 aopOp (right, ic, FALSE);
10598 /* if bitfield then unpack the bits */
10599 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10600 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10603 /* we can just get the values */
10604 int size = AOP_SIZE (right);
10609 l = aopGet (right, offset, FALSE, TRUE);
10610 if ((*l == '@') || (strcmp (l, "acc") == 0))
10613 emitcode ("mov", "@%s,a", rname);
10616 emitcode ("mov", "@%s,%s", rname, l);
10618 emitcode ("inc", "%s", rname);
10623 /* now some housekeeping stuff */
10624 if (aop) /* we had to allocate for this iCode */
10627 aopPut (result, rname, 0);
10628 freeAsmop (NULL, aop, ic, TRUE);
10632 /* we did not allocate which means left
10633 already in a pointer register, then
10634 if size > 0 && this could be used again
10635 we have to point it back to where it
10637 if ((AOP_SIZE (right) > 1 &&
10638 !OP_SYMBOL (result)->remat &&
10639 (OP_SYMBOL (result)->liveTo > ic->seq ||
10643 int size = AOP_SIZE (right) - 1;
10645 emitcode ("dec", "%s", rname);
10650 if (pi) pi->generated = 1;
10651 freeAsmop (result, NULL, ic, TRUE);
10652 freeAsmop (right, NULL, ic, TRUE);
10655 /*-----------------------------------------------------------------*/
10656 /* genPagedPointerSet - emitcode for Paged pointer put */
10657 /*-----------------------------------------------------------------*/
10659 genPagedPointerSet (operand * right,
10667 sym_link *retype, *letype;
10669 D (emitcode (";", "genPagedPointerSet"));
10671 retype = getSpec (operandType (right));
10672 letype = getSpec (operandType (result));
10674 aopOp (result, ic, FALSE);
10676 /* if the value is already in a pointer register
10677 then don't need anything more */
10678 if (!AOP_INPREG (AOP (result)))
10680 /* otherwise get a free pointer register */
10681 aop = newAsmop (0);
10682 preg = getFreePtr (ic, &aop, FALSE);
10683 emitcode ("mov", "%s,%s",
10685 aopGet (result, 0, FALSE, TRUE));
10686 rname = preg->name;
10689 rname = aopGet (result, 0, FALSE, FALSE);
10691 aopOp (right, ic, FALSE);
10693 /* if bitfield then unpack the bits */
10694 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10695 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10698 /* we have can just get the values */
10699 int size = AOP_SIZE (right);
10704 l = aopGet (right, offset, FALSE, TRUE);
10706 emitcode ("movx", "@%s,a", rname);
10709 emitcode ("inc", "%s", rname);
10715 /* now some housekeeping stuff */
10716 if (aop) /* we had to allocate for this iCode */
10719 aopPut (result, rname, 0);
10720 freeAsmop (NULL, aop, ic, TRUE);
10724 /* we did not allocate which means left
10725 already in a pointer register, then
10726 if size > 0 && this could be used again
10727 we have to point it back to where it
10729 if (AOP_SIZE (right) > 1 &&
10730 !OP_SYMBOL (result)->remat &&
10731 (OP_SYMBOL (result)->liveTo > ic->seq ||
10734 int size = AOP_SIZE (right) - 1;
10736 emitcode ("dec", "%s", rname);
10741 if (pi) pi->generated = 1;
10742 freeAsmop (result, NULL, ic, TRUE);
10743 freeAsmop (right, NULL, ic, TRUE);
10746 /*-----------------------------------------------------------------*/
10747 /* genFarPointerSet - set value from far space */
10748 /*-----------------------------------------------------------------*/
10750 genFarPointerSet (operand * right,
10751 operand * result, iCode * ic, iCode * pi)
10754 sym_link *retype = getSpec (operandType (right));
10755 sym_link *letype = getSpec (operandType (result));
10757 D(emitcode ("; genFarPointerSet",""));
10759 aopOp (result, ic, FALSE);
10760 loadDptrFromOperand (result, FALSE);
10762 /* so dptr now contains the address */
10763 aopOp (right, ic, FALSE);
10765 /* if bit then unpack */
10766 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10767 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10770 size = AOP_SIZE (right);
10775 char *l = aopGet (right, offset++, FALSE, FALSE);
10777 emitcode ("movx", "@dptr,a");
10779 emitcode ("inc", "dptr");
10782 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10783 aopPut (result, "dpl", 0);
10784 aopPut (result, "dph", 1);
10787 freeAsmop (result, NULL, ic, TRUE);
10788 freeAsmop (right, NULL, ic, TRUE);
10791 /*-----------------------------------------------------------------*/
10792 /* genGenPointerSet - set value from generic pointer space */
10793 /*-----------------------------------------------------------------*/
10795 genGenPointerSet (operand * right,
10796 operand * result, iCode * ic, iCode * pi)
10799 sym_link *retype = getSpec (operandType (right));
10800 sym_link *letype = getSpec (operandType (result));
10802 D (emitcode (";", "genGenPointerSet"));
10804 aopOp (result, ic, FALSE);
10805 loadDptrFromOperand (result, TRUE);
10807 /* so dptr now contains the address */
10808 aopOp (right, ic, FALSE);
10810 /* if bit then unpack */
10811 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10813 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10817 size = AOP_SIZE (right);
10822 char *l = aopGet (right, offset++, FALSE, FALSE);
10824 emitcode ("lcall", "__gptrput");
10826 emitcode ("inc", "dptr");
10830 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10831 aopPut (result, "dpl", 0);
10832 aopPut (result, "dph", 1);
10835 freeAsmop (result, NULL, ic, TRUE);
10836 freeAsmop (right, NULL, ic, TRUE);
10839 /*-----------------------------------------------------------------*/
10840 /* genPointerSet - stores the value into a pointer location */
10841 /*-----------------------------------------------------------------*/
10843 genPointerSet (iCode * ic, iCode *pi)
10845 operand *right, *result;
10846 sym_link *type, *etype;
10849 D (emitcode (";", "genPointerSet"));
10851 right = IC_RIGHT (ic);
10852 result = IC_RESULT (ic);
10854 /* depending on the type of pointer we need to
10855 move it to the correct pointer register */
10856 type = operandType (result);
10857 etype = getSpec (type);
10858 /* if left is of type of pointer then it is simple */
10859 if (IS_PTR (type) && !IS_FUNC (type->next))
10861 p_type = DCL_TYPE (type);
10865 /* we have to go by the storage class */
10866 p_type = PTR_TYPE (SPEC_OCLS (etype));
10869 /* special case when cast remat */
10870 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10871 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10872 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10873 type = operandType (result);
10874 p_type = DCL_TYPE (type);
10877 /* now that we have the pointer type we assign
10878 the pointer values */
10884 genNearPointerSet (right, result, ic, pi);
10888 genPagedPointerSet (right, result, ic, pi);
10892 genFarPointerSet (right, result, ic, pi);
10896 genGenPointerSet (right, result, ic, pi);
10900 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10901 "genPointerSet: illegal pointer type");
10905 /*-----------------------------------------------------------------*/
10906 /* genIfx - generate code for Ifx statement */
10907 /*-----------------------------------------------------------------*/
10909 genIfx (iCode * ic, iCode * popIc)
10911 operand *cond = IC_COND (ic);
10915 D (emitcode (";", "genIfx"));
10917 aopOp (cond, ic, FALSE);
10919 /* get the value into acc */
10920 if (AOP_TYPE (cond) != AOP_CRY)
10927 if (AOP(cond)->aopu.aop_dir)
10928 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10931 /* the result is now in the accumulator or a directly addressable bit */
10932 freeAsmop (cond, NULL, ic, TRUE);
10934 /* if there was something to be popped then do it */
10938 /* if the condition is a bit variable */
10940 genIfxJump(ic, dup, NULL, NULL, NULL);
10941 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10942 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10943 else if (isbit && !IS_ITEMP (cond))
10944 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10946 genIfxJump (ic, "a", NULL, NULL, NULL);
10951 /*-----------------------------------------------------------------*/
10952 /* genAddrOf - generates code for address of */
10953 /*-----------------------------------------------------------------*/
10955 genAddrOf (iCode * ic)
10957 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10960 D (emitcode (";", "genAddrOf"));
10962 aopOp (IC_RESULT (ic), ic, FALSE);
10964 /* if the operand is on the stack then we
10965 need to get the stack offset of this
10969 /* if it has an offset then we need to compute it */
10972 int stack_offset = ((sym->stack < 0) ?
10973 ((char) (sym->stack - _G.nRegsSaved)) :
10974 ((char) sym->stack)) & 0xff;
10975 if ((abs(stack_offset) == 1) &&
10976 !AOP_NEEDSACC(IC_RESULT (ic)) &&
10977 !isOperandVolatile (IC_RESULT (ic), FALSE))
10979 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
10980 if (stack_offset > 0)
10981 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
10983 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
10987 emitcode ("mov", "a,%s", SYM_BP (sym));
10988 emitcode ("add", "a,#0x%02x", stack_offset & 0xff);
10989 aopPut (IC_RESULT (ic), "a", 0);
10994 /* we can just move _bp */
10995 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
10997 /* fill the result with zero */
10998 size = AOP_SIZE (IC_RESULT (ic)) - 1;
11003 aopPut (IC_RESULT (ic), zero, offset++);
11008 /* object not on stack then we need the name */
11009 size = AOP_SIZE (IC_RESULT (ic));
11014 char s[SDCC_NAME_MAX];
11016 sprintf (s, "#(%s >> %d)",
11020 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11021 aopPut (IC_RESULT (ic), s, offset++);
11025 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11029 /*-----------------------------------------------------------------*/
11030 /* genFarFarAssign - assignment when both are in far space */
11031 /*-----------------------------------------------------------------*/
11033 genFarFarAssign (operand * result, operand * right, iCode * ic)
11035 int size = AOP_SIZE (right);
11039 D (emitcode (";", "genFarFarAssign"));
11041 /* first push the right side on to the stack */
11044 l = aopGet (right, offset++, FALSE, FALSE);
11046 emitcode ("push", "acc");
11049 freeAsmop (right, NULL, ic, FALSE);
11050 /* now assign DPTR to result */
11051 aopOp (result, ic, FALSE);
11052 size = AOP_SIZE (result);
11055 emitcode ("pop", "acc");
11056 aopPut (result, "a", --offset);
11058 freeAsmop (result, NULL, ic, FALSE);
11061 /*-----------------------------------------------------------------*/
11062 /* genAssign - generate code for assignment */
11063 /*-----------------------------------------------------------------*/
11065 genAssign (iCode * ic)
11067 operand *result, *right;
11069 unsigned long lit = 0L;
11071 D (emitcode (";", "genAssign"));
11073 result = IC_RESULT (ic);
11074 right = IC_RIGHT (ic);
11076 /* if they are the same */
11077 if (operandsEqu (result, right) &&
11078 !isOperandVolatile (result, FALSE) &&
11079 !isOperandVolatile (right, FALSE))
11082 aopOp (right, ic, FALSE);
11084 /* special case both in far space */
11085 if (AOP_TYPE (right) == AOP_DPTR &&
11086 IS_TRUE_SYMOP (result) &&
11087 isOperandInFarSpace (result))
11089 genFarFarAssign (result, right, ic);
11093 aopOp (result, ic, TRUE);
11095 /* if they are the same registers */
11096 if (sameRegs (AOP (right), AOP (result)) &&
11097 !isOperandVolatile (result, FALSE) &&
11098 !isOperandVolatile (right, FALSE))
11101 /* if the result is a bit */
11102 if (AOP_TYPE (result) == AOP_CRY)
11104 assignBit (result, right);
11108 /* bit variables done */
11110 size = AOP_SIZE (result);
11112 if (AOP_TYPE (right) == AOP_LIT)
11113 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11116 (AOP_TYPE (result) != AOP_REG) &&
11117 (AOP_TYPE (right) == AOP_LIT) &&
11118 !IS_FLOAT (operandType (right)) &&
11121 while ((size) && (lit))
11124 aopGet (right, offset, FALSE, FALSE),
11130 /* And now fill the rest with zeros. */
11133 emitcode ("clr", "a");
11137 aopPut (result, "a", offset);
11146 aopGet (right, offset, FALSE, FALSE),
11153 freeAsmop (result, NULL, ic, TRUE);
11154 freeAsmop (right, NULL, ic, TRUE);
11157 /*-----------------------------------------------------------------*/
11158 /* genJumpTab - generates code for jump table */
11159 /*-----------------------------------------------------------------*/
11161 genJumpTab (iCode * ic)
11163 symbol *jtab,*jtablo,*jtabhi;
11165 unsigned int count;
11167 D (emitcode (";", "genJumpTab"));
11169 count = elementsInSet( IC_JTLABELS (ic) );
11173 /* this algorithm needs 9 cycles and 7 + 3*n bytes
11174 if the switch argument is in a register.
11175 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
11176 /* Peephole may not convert ljmp to sjmp or ret
11177 labelIsReturnOnly & labelInRange must check
11178 currPl->ic->op != JUMPTABLE */
11179 aopOp (IC_JTCOND (ic), ic, FALSE);
11180 /* get the condition into accumulator */
11181 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11183 /* multiply by three */
11184 if (aopGetUsesAcc (IC_JTCOND (ic), 0))
11186 emitcode ("mov", "b,#3");
11187 emitcode ("mul", "ab");
11191 emitcode ("add", "a,acc");
11192 emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
11194 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11196 jtab = newiTempLabel (NULL);
11197 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
11198 emitcode ("jmp", "@a+dptr");
11200 /* now generate the jump labels */
11201 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11202 jtab = setNextItem (IC_JTLABELS (ic)))
11203 emitcode ("ljmp", "%05d$", jtab->key + 100);
11207 /* this algorithm needs 14 cycles and 13 + 2*n bytes
11208 if the switch argument is in a register.
11209 For n>6 this algorithm may be more compact */
11210 jtablo = newiTempLabel (NULL);
11211 jtabhi = newiTempLabel (NULL);
11213 /* get the condition into accumulator.
11214 Using b as temporary storage, if register push/pop is needed */
11215 aopOp (IC_JTCOND (ic), ic, FALSE);
11216 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11217 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
11218 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
11220 // (MB) what if B is in use???
11221 wassertl(!BINUSE, "B was in use");
11222 emitcode ("mov", "b,%s", l);
11225 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11229 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
11230 emitcode ("movc", "a,@a+pc");
11231 emitcode ("push", "acc");
11234 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
11235 emitcode ("movc", "a,@a+pc");
11236 emitcode ("push", "acc");
11240 /* this scales up to n<=255, but needs two more bytes
11241 and changes dptr */
11242 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
11243 emitcode ("movc", "a,@a+dptr");
11244 emitcode ("push", "acc");
11247 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
11248 emitcode ("movc", "a,@a+dptr");
11249 emitcode ("push", "acc");
11252 emitcode ("ret", "");
11254 /* now generate jump table, LSB */
11255 emitLabel (jtablo);
11256 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11257 jtab = setNextItem (IC_JTLABELS (ic)))
11258 emitcode (".db", "%05d$", jtab->key + 100);
11260 /* now generate jump table, MSB */
11261 emitLabel (jtabhi);
11262 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11263 jtab = setNextItem (IC_JTLABELS (ic)))
11264 emitcode (".db", "%05d$>>8", jtab->key + 100);
11268 /*-----------------------------------------------------------------*/
11269 /* genCast - gen code for casting */
11270 /*-----------------------------------------------------------------*/
11272 genCast (iCode * ic)
11274 operand *result = IC_RESULT (ic);
11275 sym_link *ctype = operandType (IC_LEFT (ic));
11276 sym_link *rtype = operandType (IC_RIGHT (ic));
11277 operand *right = IC_RIGHT (ic);
11280 D (emitcode (";", "genCast"));
11282 /* if they are equivalent then do nothing */
11283 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11286 aopOp (right, ic, FALSE);
11287 aopOp (result, ic, FALSE);
11289 /* if the result is a bit (and not a bitfield) */
11290 if (IS_BIT (OP_SYMBOL (result)->type))
11292 assignBit (result, right);
11296 /* if they are the same size : or less */
11297 if (AOP_SIZE (result) <= AOP_SIZE (right))
11300 /* if they are in the same place */
11301 if (sameRegs (AOP (right), AOP (result)))
11304 /* if they in different places then copy */
11305 size = AOP_SIZE (result);
11310 aopGet (right, offset, FALSE, FALSE),
11317 /* if the result is of type pointer */
11318 if (IS_PTR (ctype))
11322 sym_link *type = operandType (right);
11323 sym_link *etype = getSpec (type);
11325 /* pointer to generic pointer */
11326 if (IS_GENPTR (ctype))
11330 p_type = DCL_TYPE (type);
11334 if (SPEC_SCLS(etype)==S_REGISTER) {
11335 // let's assume it is a generic pointer
11338 /* we have to go by the storage class */
11339 p_type = PTR_TYPE (SPEC_OCLS (etype));
11343 /* the first two bytes are known */
11344 size = GPTRSIZE - 1;
11349 aopGet (right, offset, FALSE, FALSE),
11353 /* the last byte depending on type */
11355 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11360 // pointerTypeToGPByte will have bitched.
11364 sprintf(gpValStr, "#0x%x", gpVal);
11365 aopPut (result, gpValStr, GPTRSIZE - 1);
11370 /* just copy the pointers */
11371 size = AOP_SIZE (result);
11376 aopGet (right, offset, FALSE, FALSE),
11383 /* so we now know that the size of destination is greater
11384 than the size of the source */
11385 /* we move to result for the size of source */
11386 size = AOP_SIZE (right);
11391 aopGet (right, offset, FALSE, FALSE),
11396 /* now depending on the sign of the source && destination */
11397 size = AOP_SIZE (result) - AOP_SIZE (right);
11398 /* if unsigned or not an integral type */
11399 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11402 aopPut (result, zero, offset++);
11406 /* we need to extend the sign :{ */
11407 char *l = aopGet (right, AOP_SIZE (right) - 1,
11410 emitcode ("rlc", "a");
11411 emitcode ("subb", "a,acc");
11413 aopPut (result, "a", offset++);
11416 /* we are done hurray !!!! */
11419 freeAsmop (result, NULL, ic, TRUE);
11420 freeAsmop (right, NULL, ic, TRUE);
11423 /*-----------------------------------------------------------------*/
11424 /* genDjnz - generate decrement & jump if not zero instrucion */
11425 /*-----------------------------------------------------------------*/
11427 genDjnz (iCode * ic, iCode * ifx)
11429 symbol *lbl, *lbl1;
11433 /* if the if condition has a false label
11434 then we cannot save */
11435 if (IC_FALSE (ifx))
11438 /* if the minus is not of the form a = a - 1 */
11439 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11440 !IS_OP_LITERAL (IC_RIGHT (ic)))
11443 if (operandLitValue (IC_RIGHT (ic)) != 1)
11446 /* if the size of this greater than one then no
11448 if (getSize (operandType (IC_RESULT (ic))) > 1)
11451 /* otherwise we can save BIG */
11453 D (emitcode (";", "genDjnz"));
11455 lbl = newiTempLabel (NULL);
11456 lbl1 = newiTempLabel (NULL);
11458 aopOp (IC_RESULT (ic), ic, FALSE);
11460 if (AOP_NEEDSACC(IC_RESULT(ic)))
11462 /* If the result is accessed indirectly via
11463 * the accumulator, we must explicitly write
11464 * it back after the decrement.
11466 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11468 if (strcmp(rByte, "a"))
11470 /* Something is hopelessly wrong */
11471 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11472 __FILE__, __LINE__);
11473 /* We can just give up; the generated code will be inefficient,
11474 * but what the hey.
11476 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11479 emitcode ("dec", "%s", rByte);
11480 aopPut (IC_RESULT (ic), rByte, 0);
11481 emitcode ("jnz", "%05d$", lbl->key + 100);
11483 else if (IS_AOP_PREG (IC_RESULT (ic)))
11485 emitcode ("dec", "%s",
11486 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11487 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11488 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11489 ifx->generated = 1;
11490 emitcode ("jnz", "%05d$", lbl->key + 100);
11494 emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11497 emitcode ("sjmp", "%05d$", lbl1->key + 100);
11499 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11502 if (!ifx->generated)
11503 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11504 ifx->generated = 1;
11508 /*-----------------------------------------------------------------*/
11509 /* genReceive - generate code for a receive iCode */
11510 /*-----------------------------------------------------------------*/
11512 genReceive (iCode * ic)
11514 int size = getSize (operandType (IC_RESULT (ic)));
11517 D (emitcode (";", "genReceive"));
11519 if (ic->argreg == 1)
11520 { /* first parameter */
11521 if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11522 isOperandInPagedSpace (IC_RESULT (ic))) &&
11523 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11524 IS_TRUE_SYMOP (IC_RESULT (ic))))
11527 int receivingA = 0;
11530 for (offset = 0; offset<size; offset++)
11531 if (!strcmp (fReturn[offset], "a"))
11536 if (size==1 || getTempRegs(tempRegs, size-1, ic))
11538 for (offset = size-1; offset>0; offset--)
11539 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11540 emitcode("mov","a,%s", fReturn[0]);
11542 aopOp (IC_RESULT (ic), ic, FALSE);
11544 aopPut (IC_RESULT (ic), "a", offset);
11545 for (offset = 1; offset<size; offset++)
11546 aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset);
11552 if (getTempRegs(tempRegs, size, ic))
11554 for (offset = 0; offset<size; offset++)
11555 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11556 aopOp (IC_RESULT (ic), ic, FALSE);
11557 for (offset = 0; offset<size; offset++)
11558 aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset);
11563 offset = fReturnSizeMCS51 - size;
11566 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11567 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11570 aopOp (IC_RESULT (ic), ic, FALSE);
11571 size = AOP_SIZE (IC_RESULT (ic));
11575 emitcode ("pop", "acc");
11576 aopPut (IC_RESULT (ic), "a", offset++);
11582 aopOp (IC_RESULT (ic), ic, FALSE);
11584 assignResultValue (IC_RESULT (ic), NULL);
11587 else if (ic->argreg > 12)
11588 { /* bit parameters */
11589 if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
11591 aopOp (IC_RESULT (ic), ic, FALSE);
11592 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11593 outBitC(IC_RESULT (ic));
11597 { /* other parameters */
11599 aopOp (IC_RESULT (ic), ic, FALSE);
11600 rb1off = ic->argreg;
11603 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
11608 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11611 /*-----------------------------------------------------------------*/
11612 /* genDummyRead - generate code for dummy read of volatiles */
11613 /*-----------------------------------------------------------------*/
11615 genDummyRead (iCode * ic)
11620 D (emitcode(";", "genDummyRead"));
11622 op = IC_RIGHT (ic);
11623 if (op && IS_SYMOP (op))
11625 aopOp (op, ic, FALSE);
11627 /* if the result is a bit */
11628 if (AOP_TYPE (op) == AOP_CRY)
11629 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11632 /* bit variables done */
11634 size = AOP_SIZE (op);
11638 MOVA (aopGet (op, offset, FALSE, FALSE));
11643 freeAsmop (op, NULL, ic, TRUE);
11647 if (op && IS_SYMOP (op))
11649 aopOp (op, ic, FALSE);
11651 /* if the result is a bit */
11652 if (AOP_TYPE (op) == AOP_CRY)
11653 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11656 /* bit variables done */
11658 size = AOP_SIZE (op);
11662 MOVA (aopGet (op, offset, FALSE, FALSE));
11667 freeAsmop (op, NULL, ic, TRUE);
11671 /*-----------------------------------------------------------------*/
11672 /* genCritical - generate code for start of a critical sequence */
11673 /*-----------------------------------------------------------------*/
11675 genCritical (iCode *ic)
11677 symbol *tlbl = newiTempLabel (NULL);
11679 D (emitcode(";", "genCritical"));
11681 if (IC_RESULT (ic))
11683 aopOp (IC_RESULT (ic), ic, TRUE);
11684 aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
11685 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11686 aopPut (IC_RESULT (ic), zero, 0);
11688 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11692 emitcode ("setb", "c");
11693 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11694 emitcode ("clr", "c");
11696 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11700 /*-----------------------------------------------------------------*/
11701 /* genEndCritical - generate code for end of a critical sequence */
11702 /*-----------------------------------------------------------------*/
11704 genEndCritical (iCode *ic)
11706 D(emitcode("; genEndCritical",""));
11710 aopOp (IC_RIGHT (ic), ic, FALSE);
11711 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11713 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11714 emitcode ("mov", "ea,c");
11718 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11719 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11720 emitcode ("rrc", "a");
11721 emitcode ("mov", "ea,c");
11723 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11727 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11728 emitcode ("mov", "ea,c");
11732 /*-----------------------------------------------------------------*/
11733 /* gen51Code - generate code for 8051 based controllers */
11734 /*-----------------------------------------------------------------*/
11736 gen51Code (iCode * lic)
11740 /* int cseq = 0; */
11742 _G.currentFunc = NULL;
11743 lineHead = lineCurr = NULL;
11745 /* print the allocation information */
11746 if (allocInfo && currFunc)
11747 printAllocInfo (currFunc, codeOutBuf);
11748 /* if debug information required */
11749 if (options.debug && currFunc)
11751 debugFile->writeFunction (currFunc, lic);
11753 /* stack pointer name */
11754 if (options.useXstack)
11760 for (ic = lic; ic; ic = ic->next)
11762 _G.current_iCode = ic;
11764 if (ic->lineno && cln != ic->lineno)
11768 debugFile->writeCLine (ic);
11770 if (!options.noCcodeInAsm) {
11771 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
11772 printCLine(ic->filename, ic->lineno));
11777 if (ic->seqPoint && ic->seqPoint != cseq)
11779 emitcode ("", "; sequence point %d", ic->seqPoint);
11780 cseq = ic->seqPoint;
11783 if (options.iCodeInAsm) {
11784 char regsInUse[80];
11789 for (i=0; i<8; i++) {
11790 sprintf (®sInUse[i],
11791 "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11794 strcpy (regsInUse, "--------");
11795 for (i=0; i < 8; i++) {
11796 if (bitVectBitValue (ic->rMask, i))
11798 int offset = regs8051[i].offset;
11799 regsInUse[offset] = offset + '0'; /* show rMask */
11803 iLine = printILine(ic);
11804 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
11807 /* if the result is marked as
11808 spilt and rematerializable or code for
11809 this has already been generated then
11811 if (resultRemat (ic) || ic->generated)
11814 /* depending on the operation */
11834 /* IPOP happens only when trying to restore a
11835 spilt live range, if there is an ifx statement
11836 following this pop then the if statement might
11837 be using some of the registers being popped which
11838 would destory the contents of the register so
11839 we need to check for this condition and handle it */
11841 ic->next->op == IFX &&
11842 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11843 genIfx (ic->next, ic);
11861 genEndFunction (ic);
11881 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11898 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11902 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11909 /* note these two are xlated by algebraic equivalence
11910 in decorateType() in SDCCast.c */
11911 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11912 "got '>=' or '<=' shouldn't have come here");
11916 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11928 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11932 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11936 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11972 genRightShift (ic);
11975 case GET_VALUE_AT_ADDRESS:
11977 hasInc (IC_LEFT (ic), ic,
11978 getSize (operandType (IC_RESULT (ic)))),
11979 ifxForOp (IC_RESULT (ic), ic) );
11983 if (POINTER_SET (ic))
11985 hasInc (IC_RESULT (ic), ic,
11986 getSize (operandType (IC_RIGHT (ic)))));
12012 addSet (&_G.sendSet, ic);
12015 case DUMMY_READ_VOLATILE:
12024 genEndCritical (ic);
12036 _G.current_iCode = NULL;
12038 /* now we are ready to call the
12039 peep hole optimizer */
12040 if (!options.nopeep)
12041 peepHole (&lineHead);
12043 /* now do the actual printing */
12044 printLine (lineHead, codeOutBuf);