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 -------------------------------------------------------------------------*/
38 #include "SDCCglobl.h"
42 #include "SDCCpeeph.h"
46 #include "dbuf_string.h"
48 char *aopLiteral (value * val, int offset);
49 char *aopLiteralLong (value * val, int offset, int size);
52 /* this is the down and dirty file with all kinds of
53 kludgy & hacky stuff. This is what it is all about
54 CODE GENERATION for a specific MCU . some of the
55 routines may be reusable, will have to see */
57 static char *zero = "#0x00";
58 static char *one = "#0x01";
62 {"dpl", "dph", "b", "a"};
63 unsigned fReturnSizeMCS51 = 4; /* shared with ralloc.c */
64 char **fReturn = fReturn8051;
65 static char *accUse[] =
68 static unsigned short rbank = -1;
70 #define REG_WITH_INDEX mcs51_regWithIdx
72 #define AOP(op) op->aop
73 #define AOP_TYPE(op) AOP(op)->type
74 #define AOP_SIZE(op) AOP(op)->size
75 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
76 AOP_TYPE(x) == AOP_R0))
78 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
79 AOP_TYPE(x) == AOP_DPTR || \
82 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
83 (x->aopu.aop_reg[0] == REG_WITH_INDEX(R0_IDX) || \
84 x->aopu.aop_reg[0] == REG_WITH_INDEX(R1_IDX) )))
86 #define SYM_BP(sym) (SPEC_OCLS (sym->etype)->paged ? "_bpx" : "_bp")
88 #define R0INB _G.bu.bs.r0InB
89 #define R1INB _G.bu.bs.r1InB
90 #define OPINB _G.bu.bs.OpInB
91 #define BINUSE _G.bu.BInUse
101 short r0InB : 2;//2 so we can see it overflow
102 short r1InB : 2;//2 so we can see it overflow
103 short OpInB : 2;//2 so we can see it overflow
112 iCode *current_iCode;
117 static char *rb1regs[] = {
118 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7",
119 "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7"
122 extern struct dbuf_s *codeOutBuf;
123 static void saveRBank (int, iCode *, bool);
125 #define RESULTONSTACK(x) \
126 (IC_RESULT(x) && IC_RESULT(x)->aop && \
127 IC_RESULT(x)->aop->type == AOP_STK )
129 #define MOVA(x) mova(x) /* use function to avoid multiple eval */
130 #define MOVB(x) movb(x)
132 #define CLRC emitcode("clr","c")
133 #define SETC emitcode("setb","c")
135 static lineNode *lineHead = NULL;
136 static lineNode *lineCurr = NULL;
138 static unsigned char SLMask[] =
139 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
140 0xE0, 0xC0, 0x80, 0x00};
141 static unsigned char SRMask[] =
142 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
143 0x07, 0x03, 0x01, 0x00};
150 /*-----------------------------------------------------------------*/
151 /* emitcode - writes the code into a file : for now it is simple */
152 /*-----------------------------------------------------------------*/
154 emitcode (const char *inst, const char *fmt,...)
158 const char *lbp, *lb;
160 dbuf_init (&dbuf, INITIAL_INLINEASM);
166 dbuf_append_str (&dbuf, inst);
170 dbuf_append_char (&dbuf, '\t');
171 dbuf_tvprintf (&dbuf, fmt, ap);
176 dbuf_tvprintf (&dbuf, fmt, ap);
179 lbp = lb = dbuf_c_str(&dbuf);
181 while (isspace ((unsigned char)*lbp))
190 lineCurr = (lineCurr ?
191 connectLine (lineCurr, newLineNode (lb)) :
192 (lineHead = newLineNode (lb)));
195 lineCurr->isInline = _G.inLine;
196 lineCurr->isDebug = _G.debugLine;
197 lineCurr->ic = _G.current_iCode;
198 lineCurr->isComment = (*lbp==';');
205 emitLabel (symbol *tlbl)
207 emitcode ("", "%05d$:", tlbl->key + 100);
208 lineCurr->isLabel = 1;
211 /*-----------------------------------------------------------------*/
212 /* mcs51_emitDebuggerSymbol - associate the current code location */
213 /* with a debugger symbol */
214 /*-----------------------------------------------------------------*/
216 mcs51_emitDebuggerSymbol (char * debugSym)
219 emitcode ("", "%s ==.", debugSym);
223 /*-----------------------------------------------------------------*/
224 /* mova - moves specified value into accumulator */
225 /*-----------------------------------------------------------------*/
229 /* do some early peephole optimization */
230 if (!strncmp(x, "a", 2) || !strncmp(x, "acc", 4))
233 /* if it is a literal mov try to get it cheaper */
238 emitcode("mov", "a,%s", x);
241 /*-----------------------------------------------------------------*/
242 /* movb - moves specified value into register b */
243 /*-----------------------------------------------------------------*/
247 /* do some early peephole optimization */
248 if (!strncmp(x, "b", 2))
251 /* if it is a literal mov try to get it cheaper */
254 emitcode("mov","b,%s", rtrackGetLit(x));
258 emitcode("mov","b,%s", x);
261 /*-----------------------------------------------------------------*/
262 /* pushB - saves register B if necessary */
263 /*-----------------------------------------------------------------*/
267 bool pushedB = FALSE;
271 emitcode ("push", "b");
272 // printf("B was in use !\n");
282 /*-----------------------------------------------------------------*/
283 /* popB - restores value of register B if necessary */
284 /*-----------------------------------------------------------------*/
290 emitcode ("pop", "b");
298 /*-----------------------------------------------------------------*/
299 /* pushReg - saves register */
300 /*-----------------------------------------------------------------*/
302 pushReg (int index, bool bits_pushed)
304 regs * reg = REG_WITH_INDEX (index);
305 if (reg->type == REG_BIT)
308 emitcode ("push", "%s", reg->base);
312 emitcode ("push", "%s", reg->dname);
316 /*-----------------------------------------------------------------*/
317 /* popReg - restores register */
318 /*-----------------------------------------------------------------*/
320 popReg (int index, bool bits_popped)
322 regs * reg = REG_WITH_INDEX (index);
323 if (reg->type == REG_BIT)
326 emitcode ("pop", "%s", reg->base);
330 emitcode ("pop", "%s", reg->dname);
334 /*-----------------------------------------------------------------*/
335 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
336 /*-----------------------------------------------------------------*/
338 getFreePtr (iCode * ic, asmop ** aopp, bool result)
343 /* the logic: if r0 & r1 used in the instruction
344 then we are in trouble otherwise */
346 /* first check if r0 & r1 are used by this
347 instruction, in which case we are in trouble */
348 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
349 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
354 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
355 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
357 /* if no usage of r0 then return it */
360 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
361 (*aopp)->type = AOP_R0;
363 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
366 /* if no usage of r1 then return it */
369 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
370 (*aopp)->type = AOP_R1;
372 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R1_IDX);
375 /* now we know they both have usage */
376 /* if r0 not used in this instruction */
379 /* push it if not already pushed */
382 MOVB (REG_WITH_INDEX (R0_IDX)->dname);
385 else if (!_G.r0Pushed)
387 emitcode ("push", "%s",
388 REG_WITH_INDEX (R0_IDX)->dname);
392 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
393 (*aopp)->type = AOP_R0;
395 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
398 /* if r1 not used then */
402 /* push it if not already pushed */
405 MOVB (REG_WITH_INDEX (R1_IDX)->dname);
408 else if (!_G.r1Pushed)
410 emitcode ("push", "%s",
411 REG_WITH_INDEX (R1_IDX)->dname);
415 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
416 (*aopp)->type = AOP_R1;
417 return REG_WITH_INDEX (R1_IDX);
421 /* I said end of world, but not quite end of world yet */
422 /* if this is a result then we can push it on the stack */
425 (*aopp)->type = AOP_STK;
428 /* in the case that result AND left AND right needs a pointer reg
429 we can safely use the result's */
430 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX))
432 (*aopp)->type = AOP_R0;
433 return REG_WITH_INDEX (R0_IDX);
435 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX))
437 (*aopp)->type = AOP_R1;
438 return REG_WITH_INDEX (R1_IDX);
441 /* now this is REALLY the end of the world */
442 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
443 "getFreePtr should never reach here");
448 /*-----------------------------------------------------------------*/
449 /* getTempRegs - initialize an array of pointers to GPR registers */
450 /* that are not in use. Returns 1 if the requested */
451 /* number of registers were available, 0 otherwise. */
452 /*-----------------------------------------------------------------*/
454 getTempRegs(regs **tempRegs, int size, iCode *ic)
461 ic = _G.current_iCode;
467 freeRegs = newBitVect(8);
468 bitVectSetBit (freeRegs, R2_IDX);
469 bitVectSetBit (freeRegs, R3_IDX);
470 bitVectSetBit (freeRegs, R4_IDX);
471 bitVectSetBit (freeRegs, R5_IDX);
472 bitVectSetBit (freeRegs, R6_IDX);
473 bitVectSetBit (freeRegs, R7_IDX);
475 if (IFFUNC_CALLEESAVES(_G.currentFunc->type))
477 bitVect * newfreeRegs;
478 newfreeRegs = bitVectIntersect (freeRegs, _G.currentFunc->regsUsed);
479 freeBitVect(freeRegs);
480 freeRegs = newfreeRegs;
482 freeRegs = bitVectCplAnd (freeRegs, ic->rMask);
485 for (i=0; i<freeRegs->size; i++)
487 if (bitVectBitValue(freeRegs,i))
488 tempRegs[offset++] = REG_WITH_INDEX(i);
491 freeBitVect(freeRegs);
496 freeBitVect(freeRegs);
501 /*-----------------------------------------------------------------*/
502 /* newAsmop - creates a new asmOp */
503 /*-----------------------------------------------------------------*/
505 newAsmop (short type)
509 aop = Safe_calloc (1, sizeof (asmop));
515 /*-----------------------------------------------------------------*/
516 /* pointerCode - returns the code for a pointer type */
517 /*-----------------------------------------------------------------*/
519 pointerCode (sym_link * etype)
522 return PTR_TYPE (SPEC_OCLS (etype));
526 /*-----------------------------------------------------------------*/
527 /* leftRightUseAcc - returns size of accumulator use by operands */
528 /*-----------------------------------------------------------------*/
530 leftRightUseAcc(iCode *ic)
539 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
540 "null iCode pointer");
547 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
550 size = getSize (OP_SYMBOL (op)->type);
555 else if (ic->op == JUMPTABLE)
558 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
561 size = getSize (OP_SYMBOL (op)->type);
569 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
572 size = getSize (OP_SYMBOL (op)->type);
577 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
580 size = getSize (OP_SYMBOL (op)->type);
592 /*-----------------------------------------------------------------*/
593 /* aopForSym - for a true symbol */
594 /*-----------------------------------------------------------------*/
596 aopForSym (iCode * ic, symbol * sym, bool result)
600 bool accuse = leftRightUseAcc (ic) || _G.accInUse;
602 wassertl (ic != NULL, "Got a null iCode");
603 wassertl (sym != NULL, "Got a null symbol");
605 space = SPEC_OCLS (sym->etype);
607 /* if already has one */
610 sym->aop->allocated++;
614 /* assign depending on the storage class */
615 /* if it is on the stack or indirectly addressable */
616 /* space we need to assign either r0 or r1 to it */
617 if (sym->onStack || sym->iaccess)
619 sym->aop = aop = newAsmop (0);
620 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
621 aop->size = getSize (sym->type);
623 /* now assign the address of the variable to
624 the pointer register */
625 if (aop->type != AOP_STK)
629 signed char offset = ((sym->stack < 0) ?
630 ((signed char) (sym->stack - _G.nRegsSaved)) :
631 ((signed char) sym->stack)) & 0xff;
633 if ((abs(offset) <= 3) ||
634 (accuse && (abs(offset) <= 7)))
636 emitcode ("mov", "%s,%s",
637 aop->aopu.aop_ptr->name, SYM_BP (sym));
640 emitcode ("dec", aop->aopu.aop_ptr->name);
645 emitcode ("inc", aop->aopu.aop_ptr->name);
652 emitcode ("push", "acc");
653 emitcode ("mov", "a,%s", SYM_BP (sym));
654 emitcode ("add", "a,#0x%02x", offset & 0xff);
655 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
657 emitcode ("pop", "acc");
662 emitcode ("mov", "%s,#%s",
663 aop->aopu.aop_ptr->name,
666 aop->paged = space->paged;
669 aop->aopu.aop_stk = sym->stack;
673 /* if in bit space */
674 if (IN_BITSPACE (space))
676 sym->aop = aop = newAsmop (AOP_CRY);
677 aop->aopu.aop_dir = sym->rname;
678 aop->size = getSize (sym->type);
681 /* if it is in direct space */
682 if (IN_DIRSPACE (space))
684 //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
685 //printTypeChainRaw(sym->type, NULL);
686 //printf("space = %s\n", space ? space->sname : "NULL");
687 sym->aop = aop = newAsmop (AOP_DIR);
688 aop->aopu.aop_dir = sym->rname;
689 aop->size = getSize (sym->type);
693 /* special case for a function */
694 if (IS_FUNC (sym->type))
696 sym->aop = aop = newAsmop (AOP_IMMD);
697 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
698 aop->size = getSize (sym->type);
702 /* only remaining is far space */
703 /* in which case DPTR gets the address */
704 sym->aop = aop = newAsmop (AOP_DPTR);
705 emitcode ("mov", "dptr,#%s", sym->rname);
706 aop->size = getSize (sym->type);
708 /* if it is in code space */
709 if (IN_CODESPACE (space))
715 /*-----------------------------------------------------------------*/
716 /* aopForRemat - rematerialzes an object */
717 /*-----------------------------------------------------------------*/
719 aopForRemat (symbol * sym)
721 iCode *ic = sym->rematiCode;
722 asmop *aop = newAsmop (AOP_IMMD);
729 val += (int) operandLitValue (IC_RIGHT (ic));
730 else if (ic->op == '-')
731 val -= (int) operandLitValue (IC_RIGHT (ic));
732 else if (IS_CAST_ICODE(ic)) {
733 sym_link *from_type = operandType(IC_RIGHT(ic));
734 aop->aopu.aop_immd.from_cast_remat = 1;
735 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
736 ptr_type = pointerTypeToGPByte (DCL_TYPE(from_type), NULL, NULL);
740 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
745 SNPRINTF (buffer, sizeof(buffer),
747 OP_SYMBOL (IC_LEFT (ic))->rname,
748 val >= 0 ? '+' : '-',
753 strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
756 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
757 /* set immd2 field if required */
758 if (aop->aopu.aop_immd.from_cast_remat)
760 SNPRINTF (buffer, sizeof(buffer), "#0x%02x", ptr_type);
761 aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
767 /*-----------------------------------------------------------------*/
768 /* regsInCommon - two operands have some registers in common */
769 /*-----------------------------------------------------------------*/
771 regsInCommon (operand * op1, operand * op2)
776 /* if they have registers in common */
777 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
780 sym1 = OP_SYMBOL (op1);
781 sym2 = OP_SYMBOL (op2);
783 if (sym1->nRegs == 0 || sym2->nRegs == 0)
786 for (i = 0; i < sym1->nRegs; i++)
792 for (j = 0; j < sym2->nRegs; j++)
797 if (sym2->regs[j] == sym1->regs[i])
805 /*-----------------------------------------------------------------*/
806 /* operandsEqu - equivalent */
807 /*-----------------------------------------------------------------*/
809 operandsEqu (operand * op1, operand * op2)
813 /* if they're not symbols */
814 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
817 sym1 = OP_SYMBOL (op1);
818 sym2 = OP_SYMBOL (op2);
820 /* if both are itemps & one is spilt
821 and the other is not then false */
822 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
823 sym1->isspilt != sym2->isspilt)
826 /* if they are the same */
830 /* if they have the same rname */
831 if (sym1->rname[0] && sym2->rname[0] &&
832 strcmp (sym1->rname, sym2->rname) == 0 &&
833 !(IS_PARM (op2) && IS_ITEMP (op1)))
836 /* if left is a tmp & right is not */
837 if (IS_ITEMP (op1) &&
840 (sym1->usl.spillLoc == sym2))
843 if (IS_ITEMP (op2) &&
847 (sym2->usl.spillLoc == sym1))
853 /*-----------------------------------------------------------------*/
854 /* sameByte - two asmops have the same address at given offsets */
855 /*-----------------------------------------------------------------*/
857 sameByte (asmop * aop1, int off1, asmop * aop2, int off2)
859 if (aop1 == aop2 && off1 == off2)
862 if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
865 if (aop1->type != aop2->type)
868 if (aop1->aopu.aop_reg[off1] != aop2->aopu.aop_reg[off2])
874 /*-----------------------------------------------------------------*/
875 /* sameRegs - two asmops have the same registers */
876 /*-----------------------------------------------------------------*/
878 sameRegs (asmop * aop1, asmop * aop2)
885 if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
888 if (aop1->type != aop2->type)
891 if (aop1->size != aop2->size)
894 for (i = 0; i < aop1->size; i++)
895 if (aop1->aopu.aop_reg[i] != aop2->aopu.aop_reg[i])
901 /*-----------------------------------------------------------------*/
902 /* aopOp - allocates an asmop for an operand : */
903 /*-----------------------------------------------------------------*/
905 aopOp (operand * op, iCode * ic, bool result)
914 /* if this a literal */
915 if (IS_OP_LITERAL (op))
917 op->aop = aop = newAsmop (AOP_LIT);
918 aop->aopu.aop_lit = op->operand.valOperand;
919 aop->size = getSize (operandType (op));
923 /* if already has a asmop then continue */
926 op->aop->allocated++;
930 /* if the underlying symbol has a aop */
931 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
933 op->aop = OP_SYMBOL (op)->aop;
934 op->aop->allocated++;
938 /* if this is a true symbol */
939 if (IS_TRUE_SYMOP (op))
941 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
945 /* this is a temporary : this has
951 e) can be a return use only */
953 sym = OP_SYMBOL (op);
955 /* if the type is a conditional */
956 if (sym->regType == REG_CND)
958 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
963 /* if it is spilt then two situations
965 b) has a spill location */
966 if (sym->isspilt || sym->nRegs == 0)
969 /* rematerialize it NOW */
972 sym->aop = op->aop = aop = aopForRemat (sym);
973 aop->size = getSize (sym->type);
980 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
981 aop->size = getSize (sym->type);
982 for (i = 0; i < 2; i++)
983 aop->aopu.aop_str[i] = accUse[i];
991 aop = op->aop = sym->aop = newAsmop (AOP_STR);
992 aop->size = getSize (sym->type);
993 for (i = 0; i < fReturnSizeMCS51; i++)
994 aop->aopu.aop_str[i] = fReturn[i];
998 if (sym->usl.spillLoc)
1000 asmop *oldAsmOp = NULL;
1002 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1004 /* force a new aop if sizes differ */
1005 oldAsmOp = sym->usl.spillLoc->aop;
1006 sym->usl.spillLoc->aop = NULL;
1008 sym->aop = op->aop = aop =
1009 aopForSym (ic, sym->usl.spillLoc, result);
1010 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1012 /* Don't reuse the new aop, go with the last one */
1013 sym->usl.spillLoc->aop = oldAsmOp;
1015 aop->size = getSize (sym->type);
1019 /* else must be a dummy iTemp */
1020 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1021 aop->size = getSize (sym->type);
1025 /* if the type is a bit register */
1026 if (sym->regType == REG_BIT)
1028 sym->aop = op->aop = aop = newAsmop (AOP_CRY);
1029 aop->size = sym->nRegs;//1???
1030 aop->aopu.aop_reg[0] = sym->regs[0];
1031 aop->aopu.aop_dir = sym->regs[0]->name;
1035 /* must be in a register */
1036 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1037 aop->size = sym->nRegs;
1038 for (i = 0; i < sym->nRegs; i++)
1039 aop->aopu.aop_reg[i] = sym->regs[i];
1042 /*-----------------------------------------------------------------*/
1043 /* freeAsmop - free up the asmop given to an operand */
1044 /*----------------------------------------------------------------*/
1046 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1063 /* depending on the asmop type only three cases need work
1064 AOP_R0, AOP_R1 & AOP_STK */
1070 emitcode ("mov", "r0,b");
1073 else if (_G.r0Pushed)
1077 emitcode ("pop", "ar0");
1081 bitVectUnSetBit (ic->rUsed, R0_IDX);
1087 emitcode ("mov", "r1,b");
1090 else if (_G.r1Pushed)
1094 emitcode ("pop", "ar1");
1098 bitVectUnSetBit (ic->rUsed, R1_IDX);
1104 int stk = aop->aopu.aop_stk + aop->size - 1;
1105 bitVectUnSetBit (ic->rUsed, R0_IDX);
1106 bitVectUnSetBit (ic->rUsed, R1_IDX);
1108 getFreePtr (ic, &aop, FALSE);
1112 emitcode ("mov", "a,_bp");
1113 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1114 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1118 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1123 emitcode ("pop", "acc");
1124 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1127 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1130 freeAsmop (op, NULL, ic, TRUE);
1133 emitcode ("pop", "ar1");
1138 emitcode ("pop", "ar0");
1146 /* all other cases just dealloc */
1152 OP_SYMBOL (op)->aop = NULL;
1153 /* if the symbol has a spill */
1155 SPIL_LOC (op)->aop = NULL;
1160 /*------------------------------------------------------------------*/
1161 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
1162 /* pop r0 or r1 off stack if pushed */
1163 /*------------------------------------------------------------------*/
1165 freeForBranchAsmop (operand * op)
1177 if (!aop->allocated)
1185 emitcode ("mov", "r0,b");
1187 else if (_G.r0Pushed)
1189 emitcode ("pop", "ar0");
1196 emitcode ("mov", "r1,b");
1198 else if (_G.r1Pushed)
1200 emitcode ("pop", "ar1");
1207 int stk = aop->aopu.aop_stk + aop->size - 1;
1209 emitcode ("mov", "b,r0");
1212 emitcode ("mov", "a,_bp");
1213 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1214 emitcode ("mov", "r0,a");
1218 emitcode ("mov", "r0,_bp");
1223 emitcode ("pop", "acc");
1224 emitcode ("mov", "@r0,a");
1227 emitcode ("dec", "r0");
1229 emitcode ("mov", "r0,b");
1235 /*-----------------------------------------------------------------*/
1236 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
1237 /* clobber the accumulator */
1238 /*-----------------------------------------------------------------*/
1240 aopGetUsesAcc (operand * oper, int offset)
1242 asmop * aop = AOP (oper);
1244 if (offset > (aop->size - 1))
1262 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1273 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1279 /* Error case --- will have been caught already */
1285 /*-------------------------------------------------------------------*/
1286 /* aopGet - for fetching value of the aop */
1287 /*-------------------------------------------------------------------*/
1289 aopGet (operand * oper, int offset, bool bit16, bool dname)
1291 asmop * aop = AOP (oper);
1293 /* offset is greater than
1295 if (offset > (aop->size - 1) &&
1296 aop->type != AOP_LIT)
1299 /* depending on type */
1307 /* if we need to increment it */
1308 while (offset > aop->coff)
1310 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1314 while (offset < aop->coff)
1316 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1323 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1324 return (dname ? "acc" : "a");
1326 SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1327 return Safe_strdup(buffer);
1330 if (aop->code && aop->coff==0 && offset>=1) {
1331 emitcode ("mov", "a,#0x%02x", offset);
1332 emitcode ("movc", "a,@a+dptr");
1333 return (dname ? "acc" : "a");
1336 while (offset > aop->coff)
1338 emitcode ("inc", "dptr");
1342 while (offset < aop->coff)
1344 emitcode ("lcall", "__decdptr");
1351 emitcode ("clr", "a");
1352 emitcode ("movc", "a,@a+dptr");
1356 emitcode ("movx", "a,@dptr");
1358 return (dname ? "acc" : "a");
1361 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1363 SNPRINTF(buffer, sizeof(buffer),
1364 "%s",aop->aopu.aop_immd.aop_immd2);
1368 SNPRINTF(buffer, sizeof(buffer),
1369 "#%s", aop->aopu.aop_immd.aop_immd1);
1373 SNPRINTF (buffer, sizeof(buffer),
1375 aop->aopu.aop_immd.aop_immd1,
1380 SNPRINTF (buffer, sizeof(buffer),
1382 aop->aopu.aop_immd.aop_immd1);
1384 return Safe_strdup(buffer);
1387 if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
1389 SNPRINTF (buffer, sizeof(buffer),
1391 aop->aopu.aop_dir, offset * 8);
1395 SNPRINTF (buffer, sizeof(buffer),
1402 SNPRINTF (buffer, sizeof(buffer),
1407 return Safe_strdup(buffer);
1411 return aop->aopu.aop_reg[offset]->dname;
1413 return aop->aopu.aop_reg[offset]->name;
1416 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1417 emitcode ("clr", "a");
1418 emitcode ("rlc", "a");
1419 return (dname ? "acc" : "a");
1422 if (!offset && dname)
1424 return aop->aopu.aop_str[offset];
1427 return aopLiteral (aop->aopu.aop_lit, offset);
1431 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1435 return aop->aopu.aop_str[offset];
1439 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1440 "aopget got unsupported aop->type");
1444 /*-----------------------------------------------------------------*/
1445 /* aopPutUsesAcc - indicates ahead of time whether aopPut() will */
1446 /* clobber the accumulator */
1447 /*-----------------------------------------------------------------*/
1449 aopPutUsesAcc (operand * oper, const char *s, int offset)
1451 asmop * aop = AOP (oper);
1453 if (offset > (aop->size - 1))
1463 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1469 return ((aop->paged) || (*s == '@'));
1473 return (!aop->aopu.aop_dir || strcmp(s, aop->aopu.aop_dir));
1481 /* Error case --- will have been caught already */
1487 /*-----------------------------------------------------------------*/
1488 /* aopPut - puts a string for a aop and indicates if acc is in use */
1489 /*-----------------------------------------------------------------*/
1491 aopPut (operand * result, const char *s, int offset)
1493 bool bvolatile = isOperandVolatile (result, FALSE);
1494 bool accuse = FALSE;
1495 asmop * aop = AOP (result);
1497 if (aop->size && offset > (aop->size - 1))
1499 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1500 "aopPut got offset > aop->size");
1504 /* will assign value to value */
1505 /* depending on where it is ofcourse */
1509 MOVA (s); /* read s in case it was volatile */
1514 if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1516 SNPRINTF (buffer, sizeof(buffer),
1518 aop->aopu.aop_dir, offset * 8);
1522 SNPRINTF (buffer, sizeof(buffer),
1524 aop->aopu.aop_dir, offset);
1528 SNPRINTF (buffer, sizeof(buffer),
1533 if (strcmp (buffer, s) || bvolatile)
1535 emitcode ("mov", "%s,%s", buffer, s);
1537 if (!strcmp (buffer, "acc"))
1544 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1545 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1548 strcmp (s, "r0") == 0 ||
1549 strcmp (s, "r1") == 0 ||
1550 strcmp (s, "r2") == 0 ||
1551 strcmp (s, "r3") == 0 ||
1552 strcmp (s, "r4") == 0 ||
1553 strcmp (s, "r5") == 0 ||
1554 strcmp (s, "r6") == 0 ||
1555 strcmp (s, "r7") == 0)
1557 emitcode ("mov", "%s,%s",
1558 aop->aopu.aop_reg[offset]->dname, s);
1562 emitcode ("mov", "%s,%s",
1563 aop->aopu.aop_reg[offset]->name, s);
1571 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1572 "aopPut writing to code space");
1576 while (offset > aop->coff)
1579 emitcode ("inc", "dptr");
1582 while (offset < aop->coff)
1585 emitcode ("lcall", "__decdptr");
1590 /* if not in accumulator */
1593 emitcode ("movx", "@dptr,a");
1598 while (offset > aop->coff)
1601 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1603 while (offset < aop->coff)
1606 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1613 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1618 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1620 else if (strcmp (s, "r0") == 0 ||
1621 strcmp (s, "r1") == 0 ||
1622 strcmp (s, "r2") == 0 ||
1623 strcmp (s, "r3") == 0 ||
1624 strcmp (s, "r4") == 0 ||
1625 strcmp (s, "r5") == 0 ||
1626 strcmp (s, "r6") == 0 ||
1627 strcmp (s, "r7") == 0)
1630 SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1631 emitcode ("mov", "@%s,%s",
1632 aop->aopu.aop_ptr->name, buffer);
1636 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1641 if (strcmp (s, "a") == 0)
1643 emitcode ("push", "acc");
1648 emitcode ("push", "acc");
1650 else if (strcmp (s, "r0") == 0 ||
1651 strcmp (s, "r1") == 0 ||
1652 strcmp (s, "r2") == 0 ||
1653 strcmp (s, "r3") == 0 ||
1654 strcmp (s, "r4") == 0 ||
1655 strcmp (s, "r5") == 0 ||
1656 strcmp (s, "r6") == 0 ||
1657 strcmp (s, "r7") == 0)
1660 SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1661 emitcode ("push", buffer);
1665 emitcode ("push", s);
1671 /* if result no bit variable */
1672 if (!aop->aopu.aop_dir)
1674 assert (!strcmp (s, "c"));
1675 /* inefficient: move carry into A and use jz/jnz */
1676 emitcode ("clr", "a");
1677 emitcode ("rlc", "a");
1681 emitcode ("clr", "%s", aop->aopu.aop_dir);
1683 emitcode ("setb", "%s", aop->aopu.aop_dir);
1684 else if (!strcmp (s, "c"))
1685 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1686 else if (strcmp (s, aop->aopu.aop_dir))
1689 /* set C, if a >= 1 */
1690 emitcode ("add", "a,#0xff");
1691 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1697 if (strcmp (aop->aopu.aop_str[offset], s) || bvolatile)
1698 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1704 if (!offset && (strcmp (s, "acc") == 0) && !bvolatile)
1707 if (strcmp (aop->aopu.aop_str[offset], s) && !bvolatile)
1708 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1712 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1713 "aopPut got unsupported aop->type");
1722 /*-----------------------------------------------------------------*/
1723 /* pointToEnd :- points to the last byte of the operand */
1724 /*-----------------------------------------------------------------*/
1726 pointToEnd (asmop * aop)
1732 aop->coff = count = (aop->size - 1);
1738 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1742 emitcode ("inc", "dptr");
1749 /*-----------------------------------------------------------------*/
1750 /* reAdjustPreg - points a register back to where it should */
1751 /*-----------------------------------------------------------------*/
1753 reAdjustPreg (asmop * aop)
1755 if ((aop->coff==0) || (aop->size <= 1))
1763 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1768 emitcode ("lcall", "__decdptr");
1775 /*-----------------------------------------------------------------*/
1776 /* opIsGptr: returns non-zero if the passed operand is */
1777 /* a generic pointer type. */
1778 /*-----------------------------------------------------------------*/
1780 opIsGptr (operand * op)
1782 sym_link *type = operandType (op);
1784 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1791 /*-----------------------------------------------------------------*/
1792 /* getDataSize - get the operand data size */
1793 /*-----------------------------------------------------------------*/
1795 getDataSize (operand * op)
1798 size = AOP_SIZE (op);
1799 if (size == GPTRSIZE)
1801 sym_link *type = operandType (op);
1802 if (IS_GENPTR (type))
1804 /* generic pointer; arithmetic operations
1805 * should ignore the high byte (pointer type).
1813 /*-----------------------------------------------------------------*/
1814 /* outAcc - output Acc */
1815 /*-----------------------------------------------------------------*/
1817 outAcc (operand * result)
1820 size = getDataSize (result);
1823 aopPut (result, "a", 0);
1826 /* unsigned or positive */
1829 aopPut (result, zero, offset++);
1834 /*-----------------------------------------------------------------*/
1835 /* outBitC - output a bit C */
1836 /*-----------------------------------------------------------------*/
1838 outBitC (operand * result)
1840 /* if the result is bit */
1841 if (AOP_TYPE (result) == AOP_CRY)
1843 aopPut (result, "c", 0);
1847 emitcode ("clr", "a");
1848 emitcode ("rlc", "a");
1853 /*-----------------------------------------------------------------*/
1854 /* toBoolean - emit code for orl a,operator(sizeop) */
1855 /*-----------------------------------------------------------------*/
1857 toBoolean (operand * oper)
1859 int size = AOP_SIZE (oper) - 1;
1861 bool AccUsed = FALSE;
1864 while (!AccUsed && size--)
1866 AccUsed |= aopGetUsesAcc(oper, offset++);
1869 size = AOP_SIZE (oper) - 1;
1871 MOVA (aopGet (oper, 0, FALSE, FALSE));
1872 if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1875 emitcode("mov", "b,a");
1878 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1879 emitcode ("orl", "b,a");
1881 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1882 emitcode ("orl", "a,b");
1889 emitcode ("orl", "a,%s",
1890 aopGet (oper, offset++, FALSE, FALSE));
1895 /*-----------------------------------------------------------------*/
1896 /* toCarry - make boolean and move into carry */
1897 /*-----------------------------------------------------------------*/
1899 toCarry (operand * oper)
1901 /* if the operand is a literal then
1902 we know what the value is */
1903 if (AOP_TYPE (oper) == AOP_LIT)
1905 if ((int) operandLitValue (oper))
1910 else if (AOP_TYPE (oper) == AOP_CRY)
1912 emitcode ("mov", "c,%s", oper->aop->aopu.aop_dir);
1916 /* or the operand into a */
1918 /* set C, if a >= 1 */
1919 emitcode ("add", "a,#0xff");
1923 /*-----------------------------------------------------------------*/
1924 /* assignBit - assign operand to bit operand */
1925 /*-----------------------------------------------------------------*/
1927 assignBit (operand * result, operand * right)
1929 /* if the right side is a literal then
1930 we know what the value is */
1931 if (AOP_TYPE (right) == AOP_LIT)
1933 if ((int) operandLitValue (right))
1934 aopPut (result, one, 0);
1936 aopPut (result, zero, 0);
1941 aopPut (result, "c", 0);
1946 /*-------------------------------------------------------------------*/
1947 /* xch_a_aopGet - for exchanging acc with value of the aop */
1948 /*-------------------------------------------------------------------*/
1950 xch_a_aopGet (operand * oper, int offset, bool bit16, bool dname)
1954 if (aopGetUsesAcc (oper, offset))
1956 emitcode("mov", "b,a");
1957 MOVA (aopGet (oper, offset, bit16, dname));
1958 emitcode("xch", "a,b");
1959 aopPut (oper, "a", offset);
1960 emitcode("xch", "a,b");
1965 l = aopGet (oper, offset, bit16, dname);
1966 emitcode("xch", "a,%s", l);
1972 /*-----------------------------------------------------------------*/
1973 /* genNot - generate code for ! operation */
1974 /*-----------------------------------------------------------------*/
1980 D (emitcode (";", "genNot"));
1982 /* assign asmOps to operand & result */
1983 aopOp (IC_LEFT (ic), ic, FALSE);
1984 aopOp (IC_RESULT (ic), ic, TRUE);
1986 /* if in bit space then a special case */
1987 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1989 /* if left==result then cpl bit */
1990 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1992 emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1996 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1997 emitcode ("cpl", "c");
1998 outBitC (IC_RESULT (ic));
2003 toBoolean (IC_LEFT (ic));
2005 /* set C, if a == 0 */
2006 tlbl = newiTempLabel (NULL);
2007 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
2009 outBitC (IC_RESULT (ic));
2012 /* release the aops */
2013 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2014 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2018 /*-----------------------------------------------------------------*/
2019 /* genCpl - generate code for complement */
2020 /*-----------------------------------------------------------------*/
2027 sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
2029 D(emitcode (";", "genCpl"));
2031 /* assign asmOps to operand & result */
2032 aopOp (IC_LEFT (ic), ic, FALSE);
2033 aopOp (IC_RESULT (ic), ic, TRUE);
2035 /* special case if in bit space */
2036 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2040 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
2041 (SPEC_USIGN (letype) && IS_CHAR (letype)))
2043 /* promotion rules are responsible for this strange result:
2044 bit -> int -> ~int -> bit
2045 uchar -> int -> ~int -> bit
2047 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
2051 tlbl=newiTempLabel(NULL);
2052 l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
2053 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
2054 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
2055 IS_AOP_PREG (IC_LEFT (ic)))
2057 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
2062 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
2065 outBitC (IC_RESULT(ic));
2069 size = AOP_SIZE (IC_RESULT (ic));
2072 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2074 emitcode ("cpl", "a");
2075 aopPut (IC_RESULT (ic), "a", offset++);
2080 /* release the aops */
2081 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2082 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2085 /*-----------------------------------------------------------------*/
2086 /* genUminusFloat - unary minus for floating points */
2087 /*-----------------------------------------------------------------*/
2089 genUminusFloat (operand * op, operand * result)
2091 int size, offset = 0;
2094 D (emitcode (";", "genUminusFloat"));
2096 /* for this we just copy and then flip the bit */
2098 size = AOP_SIZE (op) - 1;
2103 aopGet (op, offset, FALSE, FALSE),
2108 l = aopGet (op, offset, FALSE, FALSE);
2111 emitcode ("cpl", "acc.7");
2112 aopPut (result, "a", offset);
2115 /*-----------------------------------------------------------------*/
2116 /* genUminus - unary minus code generation */
2117 /*-----------------------------------------------------------------*/
2119 genUminus (iCode * ic)
2124 D (emitcode (";", "genUminus"));
2127 aopOp (IC_LEFT (ic), ic, FALSE);
2128 aopOp (IC_RESULT (ic), ic, TRUE);
2130 /* if both in bit space then special
2132 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2133 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2136 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2137 emitcode ("cpl", "c");
2138 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2142 optype = operandType (IC_LEFT (ic));
2144 /* if float then do float stuff */
2145 if (IS_FLOAT (optype))
2147 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2151 /* otherwise subtract from zero */
2152 size = AOP_SIZE (IC_LEFT (ic));
2156 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2157 if (!strcmp (l, "a"))
2161 emitcode ("cpl", "a");
2162 emitcode ("addc", "a,#0");
2168 emitcode ("clr", "a");
2169 emitcode ("subb", "a,%s", l);
2171 aopPut (IC_RESULT (ic), "a", offset++);
2174 /* if any remaining bytes in the result */
2175 /* we just need to propagate the sign */
2176 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2178 emitcode ("rlc", "a");
2179 emitcode ("subb", "a,acc");
2181 aopPut (IC_RESULT (ic), "a", offset++);
2185 /* release the aops */
2186 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2187 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2190 /*-----------------------------------------------------------------*/
2191 /* saveRegisters - will look for a call and save the registers */
2192 /*-----------------------------------------------------------------*/
2194 saveRegisters (iCode * lic)
2201 for (ic = lic; ic; ic = ic->next)
2202 if (ic->op == CALL || ic->op == PCALL)
2207 fprintf (stderr, "found parameter push with no function call\n");
2211 /* if the registers have been saved already or don't need to be then
2215 if (IS_SYMOP(IC_LEFT(ic)) &&
2216 (IFFUNC_CALLEESAVES (OP_SYMBOL (IC_LEFT (ic))->type) ||
2217 IFFUNC_ISNAKED (OP_SYM_TYPE (IC_LEFT (ic)))))
2220 /* save the registers in use at this time but skip the
2221 ones for the result */
2222 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2223 mcs51_rUmaskForOp (IC_RESULT(ic)));
2226 if (options.useXstack)
2228 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2229 int nBits = bitVectnBitsOn (rsavebits);
2230 int count = bitVectnBitsOn (rsave);
2234 count = count - nBits + 1;
2235 /* remove all but the first bits as they are pushed all at once */
2236 rsave = bitVectCplAnd (rsave, rsavebits);
2237 rsave = bitVectSetBit (rsave, bitVectFirstBit (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);
2311 /*-----------------------------------------------------------------*/
2312 /* unsaveRegisters - pop the pushed registers */
2313 /*-----------------------------------------------------------------*/
2315 unsaveRegisters (iCode * ic)
2320 /* restore the registers in use at this time but skip the
2321 ones for the result */
2322 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2323 mcs51_rUmaskForOp (IC_RESULT(ic)));
2325 if (options.useXstack)
2327 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2328 int nBits = bitVectnBitsOn (rsavebits);
2329 int count = bitVectnBitsOn (rsave);
2333 count = count - nBits + 1;
2334 /* remove all but the first bits as they are popped all at once */
2335 rsave = bitVectCplAnd (rsave, rsavebits);
2336 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2341 regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2342 emitcode ("mov", "r0,%s", spname);
2343 emitcode ("dec", "r0");
2344 emitcode ("movx", "a,@r0");
2345 if (reg->type == REG_BIT)
2347 emitcode ("mov", "%s,a", reg->base);
2351 emitcode ("mov", "%s,a", reg->name);
2353 emitcode ("dec", "%s", spname);
2355 else if (count != 0)
2357 emitcode ("mov", "r0,%s", spname);
2358 for (i = mcs51_nRegs; i >= 0; i--)
2360 if (bitVectBitValue (rsave, i))
2362 regs * reg = REG_WITH_INDEX (i);
2363 emitcode ("dec", "r0");
2364 emitcode ("movx", "a,@r0");
2367 emitcode ("push", "acc");
2369 else if (reg->type == REG_BIT)
2371 emitcode ("mov", "%s,a", reg->base);
2375 emitcode ("mov", "%s,a", reg->name);
2379 emitcode ("mov", "%s,r0", spname);
2380 if (bitVectBitValue (rsave, R0_IDX))
2382 emitcode ("pop", "ar0");
2388 bool bits_popped = FALSE;
2389 for (i = mcs51_nRegs; i >= 0; i--)
2391 if (bitVectBitValue (rsave, i))
2393 bits_popped = popReg (i, bits_popped);
2400 /*-----------------------------------------------------------------*/
2402 /*-----------------------------------------------------------------*/
2404 pushSide (operand * oper, int size)
2409 char *l = aopGet (oper, offset++, FALSE, TRUE);
2410 if (AOP_TYPE (oper) != AOP_REG &&
2411 AOP_TYPE (oper) != AOP_DIR &&
2415 emitcode ("push", "acc");
2419 emitcode ("push", "%s", l);
2424 /*-----------------------------------------------------------------*/
2425 /* assignResultValue - also indicates if acc is in use afterwards */
2426 /*-----------------------------------------------------------------*/
2428 assignResultValue (operand * oper, operand * func)
2431 int size = AOP_SIZE (oper);
2432 bool accuse = FALSE;
2433 bool pushedA = FALSE;
2435 if (func && IS_BIT (OP_SYM_ETYPE (func)))
2441 if ((size > 3) && aopPutUsesAcc (oper, fReturn[offset], offset))
2443 emitcode ("push", "acc");
2448 if ((offset == 3) && pushedA)
2449 emitcode ("pop", "acc");
2450 accuse |= aopPut (oper, fReturn[offset], offset);
2457 /*-----------------------------------------------------------------*/
2458 /* genXpush - pushes onto the external stack */
2459 /*-----------------------------------------------------------------*/
2461 genXpush (iCode * ic)
2463 asmop *aop = newAsmop (0);
2465 int size, offset = 0;
2467 D (emitcode (";", "genXpush"));
2469 aopOp (IC_LEFT (ic), ic, FALSE);
2470 r = getFreePtr (ic, &aop, FALSE);
2472 size = AOP_SIZE (IC_LEFT (ic));
2476 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2477 emitcode ("mov", "%s,%s", r->name, spname);
2478 emitcode ("inc", "%s", spname); // allocate space first
2479 emitcode ("movx", "@%s,a", r->name);
2483 // allocate space first
2484 emitcode ("mov", "%s,%s", r->name, spname);
2486 emitcode ("add", "a,#%d", size);
2487 emitcode ("mov", "%s,a", spname);
2491 MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2492 emitcode ("movx", "@%s,a", r->name);
2493 emitcode ("inc", "%s", r->name);
2497 freeAsmop (NULL, aop, ic, TRUE);
2498 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2501 /*-----------------------------------------------------------------*/
2502 /* genIpush - generate code for pushing this gets a little complex */
2503 /*-----------------------------------------------------------------*/
2505 genIpush (iCode * ic)
2507 int size, offset = 0;
2511 D (emitcode (";", "genIpush"));
2513 /* if this is not a parm push : ie. it is spill push
2514 and spill push is always done on the local stack */
2518 /* and the item is spilt then do nothing */
2519 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2522 aopOp (IC_LEFT (ic), ic, FALSE);
2523 size = AOP_SIZE (IC_LEFT (ic));
2524 /* push it on the stack */
2527 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2533 emitcode ("push", "%s", l);
2538 /* this is a parameter push: in this case we call
2539 the routine to find the call and save those
2540 registers that need to be saved */
2543 /* if use external stack then call the external
2544 stack pushing routine */
2545 if (options.useXstack)
2551 /* then do the push */
2552 aopOp (IC_LEFT (ic), ic, FALSE);
2554 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2555 size = AOP_SIZE (IC_LEFT (ic));
2559 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2560 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2561 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR)
2563 if (strcmp (l, prev) || *l == '@')
2565 emitcode ("push", "acc");
2569 emitcode ("push", "%s", l);
2574 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2577 /*-----------------------------------------------------------------*/
2578 /* genIpop - recover the registers: can happen only for spilling */
2579 /*-----------------------------------------------------------------*/
2581 genIpop (iCode * ic)
2585 D (emitcode (";", "genIpop"));
2587 /* if the temp was not pushed then */
2588 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2591 aopOp (IC_LEFT (ic), ic, FALSE);
2592 size = AOP_SIZE (IC_LEFT (ic));
2593 offset = (size - 1);
2596 emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2600 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2603 /*-----------------------------------------------------------------*/
2604 /* saveRBank - saves an entire register bank on the stack */
2605 /*-----------------------------------------------------------------*/
2607 saveRBank (int bank, iCode * ic, bool pushPsw)
2610 int count = 8 + ((mcs51_nRegs > 8) ? 1 : 0) + (pushPsw ? 1 : 0);
2614 if (options.useXstack)
2618 /* Assume r0 is available for use. */
2619 r = REG_WITH_INDEX (R0_IDX);;
2624 r = getFreePtr (ic, &aop, FALSE);
2626 // allocate space first
2627 emitcode ("mov", "%s,%s", r->name, spname);
2629 emitcode ("add", "a,#%d", count);
2630 emitcode ("mov", "%s,a", spname);
2633 for (i = 0; i < 8; i++)
2635 if (options.useXstack)
2637 emitcode ("mov", "a,(%s+%d)",
2638 regs8051[i].base, 8 * bank + regs8051[i].offset);
2639 emitcode ("movx", "@%s,a", r->name);
2641 emitcode ("inc", "%s", r->name);
2644 emitcode ("push", "(%s+%d)",
2645 regs8051[i].base, 8 * bank + regs8051[i].offset);
2648 if (mcs51_nRegs > 8)
2650 if (options.useXstack)
2652 emitcode ("mov", "a,bits");
2653 emitcode ("movx", "@%s,a", r->name);
2655 emitcode ("inc", "%s", r->name);
2659 emitcode ("push", "bits");
2666 if (options.useXstack)
2668 emitcode ("mov", "a,psw");
2669 emitcode ("movx", "@%s,a", r->name);
2673 emitcode ("push", "psw");
2676 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2681 freeAsmop (NULL, aop, ic, TRUE);
2690 /*-----------------------------------------------------------------*/
2691 /* unsaveRBank - restores the register bank from stack */
2692 /*-----------------------------------------------------------------*/
2694 unsaveRBank (int bank, iCode * ic, bool popPsw)
2700 if (options.useXstack)
2704 /* Assume r0 is available for use. */
2705 r = REG_WITH_INDEX (R0_IDX);;
2710 r = getFreePtr (ic, &aop, FALSE);
2712 emitcode ("mov", "%s,%s", r->name, spname);
2717 if (options.useXstack)
2719 emitcode ("dec", "%s", r->name);
2720 emitcode ("movx", "a,@%s", r->name);
2721 emitcode ("mov", "psw,a");
2725 emitcode ("pop", "psw");
2729 if (mcs51_nRegs > 8)
2731 if (options.useXstack)
2733 emitcode ("dec", "%s", r->name);
2734 emitcode ("movx", "a,@%s", r->name);
2735 emitcode ("mov", "bits,a");
2739 emitcode ("pop", "bits");
2743 for (i = 7; i >= 0; i--)
2745 if (options.useXstack)
2747 emitcode ("dec", "%s", r->name);
2748 emitcode ("movx", "a,@%s", r->name);
2749 emitcode ("mov", "(%s+%d),a",
2750 regs8051[i].base, 8 * bank + regs8051[i].offset);
2754 emitcode ("pop", "(%s+%d)",
2755 regs8051[i].base, 8 * bank + regs8051[i].offset);
2759 if (options.useXstack)
2761 emitcode ("mov", "%s,%s", spname, r->name);
2766 freeAsmop (NULL, aop, ic, TRUE);
2770 /*-----------------------------------------------------------------*/
2771 /* genSend - gen code for SEND */
2772 /*-----------------------------------------------------------------*/
2773 static void genSend(set *sendSet)
2778 /* first we do all bit parameters */
2779 for (sic = setFirstItem (sendSet); sic;
2780 sic = setNextItem (sendSet))
2782 if (sic->argreg > 12)
2784 int bit = sic->argreg-13;
2786 aopOp (IC_LEFT (sic), sic, FALSE);
2788 /* if left is a literal then
2789 we know what the value is */
2790 if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2792 if (((int) operandLitValue (IC_LEFT (sic))))
2793 emitcode ("setb", "b[%d]", bit);
2795 emitcode ("clr", "b[%d]", bit);
2800 toCarry (IC_LEFT (sic));
2801 emitcode ("mov", "b[%d],c", bit);
2806 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2812 saveRegisters (setFirstItem (sendSet));
2813 emitcode ("mov", "bits,b");
2816 /* then we do all other parameters */
2817 for (sic = setFirstItem (sendSet); sic;
2818 sic = setNextItem (sendSet))
2820 if (sic->argreg <= 12)
2822 int size, offset = 0;
2823 aopOp (IC_LEFT (sic), sic, FALSE);
2824 size = AOP_SIZE (IC_LEFT (sic));
2826 if (sic->argreg == 1)
2830 char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2831 if (strcmp (l, fReturn[offset]))
2833 emitcode ("mov", "%s,%s", fReturn[offset], l);
2842 emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2843 aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2847 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2852 /*-----------------------------------------------------------------*/
2853 /* selectRegBank - emit code to select the register bank */
2854 /*-----------------------------------------------------------------*/
2856 selectRegBank (short bank, bool keepFlags)
2858 /* if f.e. result is in carry */
2861 emitcode ("anl", "psw,#0xE7");
2863 emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2867 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2871 /*-----------------------------------------------------------------*/
2872 /* genCall - generates a call statement */
2873 /*-----------------------------------------------------------------*/
2875 genCall (iCode * ic)
2879 // bool restoreBank = FALSE;
2880 bool swapBanks = FALSE;
2881 bool accuse = FALSE;
2882 bool accPushed = FALSE;
2883 bool resultInF0 = FALSE;
2884 bool assignResultGenerated = FALSE;
2886 D (emitcode (";", "genCall"));
2888 dtype = operandType (IC_LEFT (ic));
2889 etype = getSpec(dtype);
2890 /* if send set is not empty then assign */
2893 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2894 genSend(reverseSet(_G.sendSet));
2896 genSend(_G.sendSet);
2901 /* if we are calling a not _naked function that is not using
2902 the same register bank then we need to save the
2903 destination registers on the stack */
2904 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2905 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2906 !IFFUNC_ISISR (dtype))
2911 /* if caller saves & we have not saved then */
2917 emitcode ("mov", "psw,#0x%02x",
2918 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2922 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2924 if (IFFUNC_CALLEESAVES(dtype))
2926 werror (E_BANKED_WITH_CALLEESAVES);
2930 char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2931 OP_SYMBOL (IC_LEFT (ic))->rname :
2932 OP_SYMBOL (IC_LEFT (ic))->name);
2934 emitcode ("mov", "r0,#%s", l);
2935 emitcode ("mov", "r1,#(%s >> 8)", l);
2936 emitcode ("mov", "r2,#(%s >> 16)", l);
2937 emitcode ("lcall", "__sdcc_banked_call");
2942 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2943 OP_SYMBOL (IC_LEFT (ic))->rname :
2944 OP_SYMBOL (IC_LEFT (ic))->name));
2949 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2952 /* if we need assign a result value */
2953 if ((IS_ITEMP (IC_RESULT (ic)) &&
2954 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2955 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2956 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2957 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2958 IS_TRUE_SYMOP (IC_RESULT (ic)))
2962 aopOp (IC_RESULT (ic), ic, FALSE);
2965 accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2966 assignResultGenerated = TRUE;
2968 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2971 /* adjust the stack for parameters if required */
2975 if (ic->parmBytes > 3)
2979 emitcode ("push", "acc");
2982 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2983 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2984 !assignResultGenerated)
2986 emitcode ("mov", "F0,c");
2990 emitcode ("mov", "a,%s", spname);
2991 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2992 emitcode ("mov", "%s,a", spname);
2994 /* unsaveRegisters from xstack needs acc, but */
2995 /* unsaveRegisters from stack needs this popped */
2996 if (accPushed && !options.useXstack)
2998 emitcode ("pop", "acc");
3003 for (i = 0; i < ic->parmBytes; i++)
3004 emitcode ("dec", "%s", spname);
3007 /* if we had saved some registers then unsave them */
3008 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3010 if (accuse && !accPushed && options.useXstack)
3012 /* xstack needs acc, but doesn't touch normal stack */
3013 emitcode ("push", "acc");
3016 unsaveRegisters (ic);
3019 // /* if register bank was saved then pop them */
3021 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
3023 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
3026 emitcode ("mov", "c,F0");
3028 aopOp (IC_RESULT (ic), ic, FALSE);
3029 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3030 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3034 emitcode ("pop", "acc");
3037 /*-----------------------------------------------------------------*/
3038 /* genPcall - generates a call by pointer statement */
3039 /*-----------------------------------------------------------------*/
3041 genPcall (iCode * ic)
3045 symbol *rlbl = newiTempLabel (NULL);
3046 // bool restoreBank=FALSE;
3047 bool swapBanks = FALSE;
3048 bool resultInF0 = FALSE;
3050 D (emitcode (";", "genPcall"));
3052 dtype = operandType (IC_LEFT (ic))->next;
3053 etype = getSpec(dtype);
3054 /* if caller saves & we have not saved then */
3058 /* if we are calling a not _naked function that is not using
3059 the same register bank then we need to save the
3060 destination registers on the stack */
3061 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
3062 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
3063 !IFFUNC_ISISR (dtype))
3065 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3066 // restoreBank=TRUE;
3068 // need caution message to user here
3071 if (IS_LITERAL (etype))
3073 /* if send set is not empty then assign */
3076 genSend(reverseSet(_G.sendSet));
3082 emitcode ("mov", "psw,#0x%02x",
3083 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3086 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
3088 if (IFFUNC_CALLEESAVES(dtype))
3090 werror (E_BANKED_WITH_CALLEESAVES);
3094 char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
3096 emitcode ("mov", "r0,#%s", l);
3097 emitcode ("mov", "r1,#(%s >> 8)", l);
3098 emitcode ("mov", "r2,#(%s >> 16)", l);
3099 emitcode ("lcall", "__sdcc_banked_call");
3104 emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
3109 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
3111 if (IFFUNC_CALLEESAVES(dtype))
3113 werror (E_BANKED_WITH_CALLEESAVES);
3117 aopOp (IC_LEFT (ic), ic, FALSE);
3121 /* what if aopGet needs r0 or r1 ??? */
3122 emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3123 emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3124 emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3128 int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
3129 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3130 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3131 emitcode ("mov", "0x%02x,%s", reg, aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3134 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3136 /* if send set is not empty then assign */
3139 genSend(reverseSet(_G.sendSet));
3145 emitcode ("mov", "psw,#0x%02x",
3146 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3150 emitcode ("lcall", "__sdcc_banked_call");
3153 else if (_G.sendSet)
3155 /* push the return address on to the stack */
3156 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
3157 emitcode ("push", "acc");
3158 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
3159 emitcode ("push", "acc");
3161 /* now push the calling address */
3162 aopOp (IC_LEFT (ic), ic, FALSE);
3164 pushSide (IC_LEFT (ic), FPTRSIZE);
3166 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3168 /* if send set is not empty the assign */
3171 genSend(reverseSet(_G.sendSet));
3177 emitcode ("mov", "psw,#0x%02x",
3178 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3182 emitcode ("ret", "");
3185 else /* the send set is empty */
3188 /* now get the calling address into dptr */
3189 aopOp (IC_LEFT (ic), ic, FALSE);
3191 l = aopGet (IC_LEFT (ic), 0, FALSE, FALSE);
3192 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3194 emitcode ("mov", "r0,%s", l);
3195 l = aopGet (IC_LEFT (ic), 1, FALSE, FALSE);
3196 emitcode ("mov", "dph,%s", l);
3197 emitcode ("mov", "dpl,r0");
3201 emitcode ("mov", "dpl,%s", l);
3202 l = aopGet (IC_LEFT (ic), 1, FALSE, FALSE);
3203 emitcode ("mov", "dph,%s", l);
3206 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3210 emitcode ("mov", "psw,#0x%02x",
3211 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3215 emitcode ("lcall", "__sdcc_call_dptr");
3220 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
3223 /* if we need assign a result value */
3224 if ((IS_ITEMP (IC_RESULT (ic)) &&
3225 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3226 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3227 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3228 IS_TRUE_SYMOP (IC_RESULT (ic)))
3232 aopOp (IC_RESULT (ic), ic, FALSE);
3235 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3237 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3240 /* adjust the stack for parameters if required */
3244 if (ic->parmBytes > 3)
3246 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3247 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3249 emitcode ("mov", "F0,c");
3253 emitcode ("mov", "a,%s", spname);
3254 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3255 emitcode ("mov", "%s,a", spname);
3258 for (i = 0; i < ic->parmBytes; i++)
3259 emitcode ("dec", "%s", spname);
3262 // /* if register bank was saved then unsave them */
3264 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3266 /* if we had saved some registers then unsave them */
3267 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3268 unsaveRegisters (ic);
3270 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3273 emitcode ("mov", "c,F0");
3275 aopOp (IC_RESULT (ic), ic, FALSE);
3276 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3277 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3281 /*-----------------------------------------------------------------*/
3282 /* resultRemat - result is rematerializable */
3283 /*-----------------------------------------------------------------*/
3285 resultRemat (iCode * ic)
3287 if (SKIP_IC (ic) || ic->op == IFX)
3290 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3292 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3293 if (sym->remat && !POINTER_SET (ic))
3300 /*-----------------------------------------------------------------*/
3301 /* inExcludeList - return 1 if the string is in exclude Reg list */
3302 /*-----------------------------------------------------------------*/
3304 regsCmp(void *p1, void *p2)
3306 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3310 inExcludeList (char *s)
3312 const char *p = setFirstItem(options.excludeRegsSet);
3314 if (p == NULL || STRCASECMP(p, "none") == 0)
3318 return isinSetWith(options.excludeRegsSet, s, regsCmp);
3321 /*-----------------------------------------------------------------*/
3322 /* genFunction - generated code for function entry */
3323 /*-----------------------------------------------------------------*/
3325 genFunction (iCode * ic)
3327 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3329 bool switchedPSW = FALSE;
3330 int calleesaves_saved_register = -1;
3331 int stackAdjust = sym->stack;
3332 int accIsFree = sym->recvSize < 4;
3333 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3334 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3337 /* create the function header */
3338 emitcode (";", "-----------------------------------------");
3339 emitcode (";", " function %s", sym->name);
3340 emitcode (";", "-----------------------------------------");
3342 emitcode ("", "%s:", sym->rname);
3343 lineCurr->isLabel = 1;
3344 ftype = operandType (IC_LEFT (ic));
3345 _G.currentFunc = sym;
3347 if (IFFUNC_ISNAKED(ftype))
3349 emitcode(";", "naked function: no prologue.");
3353 /* here we need to generate the equates for the
3354 register bank if required */
3355 if (FUNC_REGBANK (ftype) != rbank)
3359 rbank = FUNC_REGBANK (ftype);
3360 for (i = 0; i < mcs51_nRegs; i++)
3362 if (regs8051[i].type != REG_BIT)
3364 if (strcmp (regs8051[i].base, "0") == 0)
3365 emitcode ("", "%s = 0x%02x",
3367 8 * rbank + regs8051[i].offset);
3369 emitcode ("", "%s = %s + 0x%02x",
3372 8 * rbank + regs8051[i].offset);
3377 /* if this is an interrupt service routine then
3378 save acc, b, dpl, dph */
3379 if (IFFUNC_ISISR (sym->type))
3381 if (!inExcludeList ("acc"))
3382 emitcode ("push", "acc");
3383 if (!inExcludeList ("b"))
3384 emitcode ("push", "b");
3385 if (!inExcludeList ("dpl"))
3386 emitcode ("push", "dpl");
3387 if (!inExcludeList ("dph"))
3388 emitcode ("push", "dph");
3389 /* if this isr has no bank i.e. is going to
3390 run with bank 0 , then we need to save more
3392 if (!FUNC_REGBANK (sym->type))
3396 /* if this function does not call any other
3397 function then we can be economical and
3398 save only those registers that are used */
3399 if (!IFFUNC_HASFCALL(sym->type))
3401 /* if any registers used */
3404 bool bits_pushed = FALSE;
3405 /* save the registers used */
3406 for (i = 0; i < sym->regsUsed->size; i++)
3408 if (bitVectBitValue (sym->regsUsed, i))
3409 bits_pushed = pushReg (i, bits_pushed);
3415 /* this function has a function call. We cannot
3416 determine register usage so we will have to push the
3418 saveRBank (0, ic, FALSE);
3419 if (options.parms_in_bank1) {
3420 for (i=0; i < 8 ; i++ ) {
3421 emitcode ("push","%s",rb1regs[i]);
3428 /* This ISR uses a non-zero bank.
3430 * We assume that the bank is available for our
3433 * However, if this ISR calls a function which uses some
3434 * other bank, we must save that bank entirely.
3436 unsigned long banksToSave = 0;
3438 if (IFFUNC_HASFCALL(sym->type))
3441 #define MAX_REGISTER_BANKS 4
3446 for (i = ic; i; i = i->next)
3448 if (i->op == ENDFUNCTION)
3450 /* we got to the end OK. */
3458 dtype = operandType (IC_LEFT(i));
3460 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3462 /* Mark this bank for saving. */
3463 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3465 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3469 banksToSave |= (1 << FUNC_REGBANK(dtype));
3472 /* And note that we don't need to do it in
3480 /* This is a mess; we have no idea what
3481 * register bank the called function might
3484 * The only thing I can think of to do is
3485 * throw a warning and hope.
3487 werror(W_FUNCPTR_IN_USING_ISR);
3491 if (banksToSave && options.useXstack)
3493 /* Since we aren't passing it an ic,
3494 * saveRBank will assume r0 is available to abuse.
3496 * So switch to our (trashable) bank now, so
3497 * the caller's R0 isn't trashed.
3499 emitcode ("push", "psw");
3500 emitcode ("mov", "psw,#0x%02x",
3501 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3505 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3507 if (banksToSave & (1 << ix))
3509 saveRBank(ix, NULL, FALSE);
3513 // TODO: this needs a closer look
3514 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3517 /* Set the register bank to the desired value if nothing else */
3518 /* has done so yet. */
3521 emitcode ("push", "psw");
3522 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3527 /* This is a non-ISR function. The caller has already switched register */
3528 /* banks, if necessary, so just handle the callee-saves option. */
3530 /* if callee-save to be used for this function
3531 then save the registers being used in this function */
3532 if (IFFUNC_CALLEESAVES(sym->type))
3536 /* if any registers used */
3539 bool bits_pushed = FALSE;
3540 /* save the registers used */
3541 for (i = 0; i < sym->regsUsed->size; i++)
3543 if (bitVectBitValue (sym->regsUsed, i))
3545 /* remember one saved register for later usage */
3546 if (calleesaves_saved_register < 0)
3547 calleesaves_saved_register = i;
3548 bits_pushed = pushReg (i, bits_pushed);
3558 if (options.useXstack)
3560 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3562 emitcode ("mov", "r0,%s", spname);
3563 emitcode ("inc", "%s", spname);
3564 emitcode ("xch", "a,_bpx");
3565 emitcode ("movx", "@r0,a");
3566 emitcode ("inc", "r0");
3567 emitcode ("mov", "a,r0");
3568 emitcode ("xch", "a,_bpx");
3572 emitcode ("push", "_bp"); /* save the callers stack */
3573 emitcode ("mov", "_bp,sp");
3578 if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3580 /* set up the stack */
3581 emitcode ("push", "_bp"); /* save the callers stack */
3582 emitcode ("mov", "_bp,sp");
3587 /* For some cases it is worthwhile to perform a RECEIVE iCode */
3588 /* before setting up the stack frame completely. */
3589 if (ric && ric->argreg == 1 && IC_RESULT (ric))
3591 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3595 if (rsym && rsym->regType == REG_CND)
3597 if (rsym && (rsym->accuse || rsym->ruonly))
3599 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3600 rsym = rsym->usl.spillLoc;
3603 /* If the RECEIVE operand immediately spills to the first entry on the */
3604 /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3605 /* rather than the usual @r0/r1 machinations. */
3606 if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3610 _G.current_iCode = ric;
3611 D(emitcode ("; genReceive",""));
3612 for (ofs=0; ofs < sym->recvSize; ofs++)
3614 if (!strcmp (fReturn[ofs], "a"))
3615 emitcode ("push", "acc");
3617 emitcode ("push", fReturn[ofs]);
3619 stackAdjust -= sym->recvSize;
3622 assert (stackAdjust>=0);
3625 _G.current_iCode = ic;
3629 /* If the RECEIVE operand is 4 registers, we can do the moves now */
3630 /* to free up the accumulator. */
3631 else if (rsym && rsym->nRegs && sym->recvSize == 4)
3635 _G.current_iCode = ric;
3636 D(emitcode ("; genReceive",""));
3637 for (ofs=0; ofs < sym->recvSize; ofs++)
3639 emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3641 _G.current_iCode = ic;
3647 /* adjust the stack for the function */
3650 int i = stackAdjust;
3652 werror (W_STACK_OVERFLOW, sym->name);
3654 if (i > 3 && accIsFree)
3656 emitcode ("mov", "a,sp");
3657 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3658 emitcode ("mov", "sp,a");
3662 /* The accumulator is not free, so we will need another register */
3663 /* to clobber. No need to worry about a possible conflict with */
3664 /* the above early RECEIVE optimizations since they would have */
3665 /* freed the accumulator if they were generated. */
3667 if (IFFUNC_CALLEESAVES(sym->type))
3669 /* if it's a callee-saves function we need a saved register */
3670 if (calleesaves_saved_register >= 0)
3672 emitcode ("mov", "%s,a", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3673 emitcode ("mov", "a,sp");
3674 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3675 emitcode ("mov", "sp,a");
3676 emitcode ("mov", "a,%s", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3679 /* do it the hard way */
3681 emitcode ("inc", "sp");
3685 /* not callee-saves, we can clobber r0 */
3686 emitcode ("mov", "r0,a");
3687 emitcode ("mov", "a,sp");
3688 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3689 emitcode ("mov", "sp,a");
3690 emitcode ("mov", "a,r0");
3695 emitcode ("inc", "sp");
3700 char i = ((char) sym->xstack & 0xff);
3702 if (i > 3 && accIsFree)
3704 emitcode ("mov", "a,_spx");
3705 emitcode ("add", "a,#0x%02x", i & 0xff);
3706 emitcode ("mov", "_spx,a");
3710 emitcode ("push", "acc");
3711 emitcode ("mov", "a,_spx");
3712 emitcode ("add", "a,#0x%02x", i & 0xff);
3713 emitcode ("mov", "_spx,a");
3714 emitcode ("pop", "acc");
3719 emitcode ("inc", "_spx");
3723 /* if critical function then turn interrupts off */
3724 if (IFFUNC_ISCRITICAL (ftype))
3726 symbol *tlbl = newiTempLabel (NULL);
3727 emitcode ("setb", "c");
3728 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3729 emitcode ("clr", "c");
3731 emitcode ("push", "psw"); /* save old ea via c in psw */
3735 /*-----------------------------------------------------------------*/
3736 /* genEndFunction - generates epilogue for functions */
3737 /*-----------------------------------------------------------------*/
3739 genEndFunction (iCode * ic)
3741 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3742 lineNode *lnp = lineCurr;
3744 bitVect *regsUsedPrologue;
3745 bitVect *regsUnneeded;
3748 _G.currentFunc = NULL;
3749 if (IFFUNC_ISNAKED(sym->type))
3751 emitcode(";", "naked function: no epilogue.");
3752 if (options.debug && currFunc)
3753 debugFile->writeEndFunction (currFunc, ic, 0);
3757 if (IFFUNC_ISCRITICAL (sym->type))
3759 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3761 emitcode ("rlc", "a"); /* save c in a */
3762 emitcode ("pop", "psw"); /* restore ea via c in psw */
3763 emitcode ("mov", "ea,c");
3764 emitcode ("rrc", "a"); /* restore c from a */
3768 emitcode ("pop", "psw"); /* restore ea via c in psw */
3769 emitcode ("mov", "ea,c");
3773 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3775 if (options.useXstack)
3779 emitcode ("mov", "sp,_bp");
3780 emitcode ("pop", "_bp");
3782 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3784 emitcode ("xch", "a,_bpx");
3785 emitcode ("mov", "r0,a");
3786 emitcode ("dec", "r0");
3787 emitcode ("movx", "a,@r0");
3788 emitcode ("xch", "a,_bpx");
3789 emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3792 else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3795 emitcode ("mov", "sp,_bp");
3796 emitcode ("pop", "_bp");
3800 /* restore the register bank */
3801 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3803 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3804 || !options.useXstack)
3806 /* Special case of ISR using non-zero bank with useXstack
3809 emitcode ("pop", "psw");
3813 if (IFFUNC_ISISR (sym->type))
3816 /* now we need to restore the registers */
3817 /* if this isr has no bank i.e. is going to
3818 run with bank 0 , then we need to save more
3820 if (!FUNC_REGBANK (sym->type))
3823 /* if this function does not call any other
3824 function then we can be economical and
3825 save only those registers that are used */
3826 if (!IFFUNC_HASFCALL(sym->type))
3828 /* if any registers used */
3831 bool bits_popped = FALSE;
3832 /* save the registers used */
3833 for (i = sym->regsUsed->size; i >= 0; i--)
3835 if (bitVectBitValue (sym->regsUsed, i))
3836 bits_popped = popReg (i, bits_popped);
3842 if (options.parms_in_bank1) {
3843 for (i = 7 ; i >= 0 ; i-- ) {
3844 emitcode ("pop","%s",rb1regs[i]);
3847 /* this function has a function call cannot
3848 determines register usage so we will have to pop the
3850 unsaveRBank (0, ic, FALSE);
3855 /* This ISR uses a non-zero bank.
3857 * Restore any register banks saved by genFunction
3860 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3863 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3865 if (savedBanks & (1 << ix))
3867 unsaveRBank(ix, NULL, FALSE);
3871 if (options.useXstack)
3873 /* Restore bank AFTER calling unsaveRBank,
3874 * since it can trash r0.
3876 emitcode ("pop", "psw");
3880 if (!inExcludeList ("dph"))
3881 emitcode ("pop", "dph");
3882 if (!inExcludeList ("dpl"))
3883 emitcode ("pop", "dpl");
3884 if (!inExcludeList ("b"))
3885 emitcode ("pop", "b");
3886 if (!inExcludeList ("acc"))
3887 emitcode ("pop", "acc");
3889 /* if debug then send end of function */
3890 if (options.debug && currFunc)
3892 debugFile->writeEndFunction (currFunc, ic, 1);
3895 emitcode ("reti", "");
3899 if (IFFUNC_CALLEESAVES(sym->type))
3903 /* if any registers used */
3906 /* save the registers used */
3907 for (i = sym->regsUsed->size; i >= 0; i--)
3909 if (bitVectBitValue (sym->regsUsed, i) ||
3910 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3911 emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
3914 else if (mcs51_ptrRegReq)
3916 emitcode ("pop", "%s", REG_WITH_INDEX (R1_IDX)->dname);
3917 emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
3922 /* if debug then send end of function */
3923 if (options.debug && currFunc)
3925 debugFile->writeEndFunction (currFunc, ic, 1);
3928 if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3930 emitcode ("ljmp", "__sdcc_banked_ret");
3934 emitcode ("ret", "");
3938 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3941 /* If this was an interrupt handler using bank 0 that called another */
3942 /* function, then all registers must be saved; nothing to optimized. */
3943 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3944 && !FUNC_REGBANK(sym->type))
3947 /* There are no push/pops to optimize if not callee-saves or ISR */
3948 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3951 /* If there were stack parameters, we cannot optimize without also */
3952 /* fixing all of the stack offsets; this is too dificult to consider. */
3953 if (FUNC_HASSTACKPARM(sym->type))
3956 /* Compute the registers actually used */
3957 regsUsed = newBitVect (mcs51_nRegs);
3958 regsUsedPrologue = newBitVect (mcs51_nRegs);
3961 if (lnp->ic && lnp->ic->op == FUNCTION)
3962 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3964 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3966 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3967 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3974 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3975 && !bitVectBitValue (regsUsed, CND_IDX))
3977 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3978 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3979 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3980 bitVectUnSetBit (regsUsed, CND_IDX);
3983 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3985 /* If this was an interrupt handler that called another function */
3986 /* function, then assume A, B, DPH, & DPL may be modified by it. */
3987 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3989 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3990 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3991 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3992 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3993 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3996 /* Remove the unneeded push/pops */
3997 regsUnneeded = newBitVect (mcs51_nRegs);
4000 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
4002 if (!strncmp(lnp->line, "push", 4))
4004 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
4005 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4007 connectLine (lnp->prev, lnp->next);
4008 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4011 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
4013 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
4014 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4016 connectLine (lnp->prev, lnp->next);
4017 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4024 for (idx = 0; idx < regsUnneeded->size; idx++)
4025 if (bitVectBitValue (regsUnneeded, idx))
4026 emitcode (";", "eliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
4028 freeBitVect (regsUnneeded);
4029 freeBitVect (regsUsed);
4030 freeBitVect (regsUsedPrologue);
4033 /*-----------------------------------------------------------------*/
4034 /* genRet - generate code for return statement */
4035 /*-----------------------------------------------------------------*/
4039 int size, offset = 0, pushed = 0;
4041 D (emitcode (";", "genRet"));
4043 /* if we have no return value then
4044 just generate the "ret" */
4048 /* we have something to return then
4049 move the return value into place */
4050 aopOp (IC_LEFT (ic), ic, FALSE);
4051 size = AOP_SIZE (IC_LEFT (ic));
4053 if (IS_BIT(_G.currentFunc->etype))
4055 toCarry (IC_LEFT (ic));
4062 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
4065 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
4066 emitcode ("push", "%s", l);
4071 l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
4072 if (strcmp (fReturn[offset], l))
4073 emitcode ("mov", "%s,%s", fReturn[offset++], l);
4080 if (strcmp (fReturn[pushed], "a"))
4081 emitcode ("pop", fReturn[pushed]);
4083 emitcode ("pop", "acc");
4086 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
4089 /* generate a jump to the return label
4090 if the next is not the return statement */
4091 if (!(ic->next && ic->next->op == LABEL &&
4092 IC_LABEL (ic->next) == returnLabel))
4094 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
4098 /*-----------------------------------------------------------------*/
4099 /* genLabel - generates a label */
4100 /*-----------------------------------------------------------------*/
4102 genLabel (iCode * ic)
4104 /* special case never generate */
4105 if (IC_LABEL (ic) == entryLabel)
4108 emitLabel (IC_LABEL (ic));
4111 /*-----------------------------------------------------------------*/
4112 /* genGoto - generates a ljmp */
4113 /*-----------------------------------------------------------------*/
4115 genGoto (iCode * ic)
4117 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
4120 /*-----------------------------------------------------------------*/
4121 /* findLabelBackwards: walks back through the iCode chain looking */
4122 /* for the given label. Returns number of iCode instructions */
4123 /* between that label and given ic. */
4124 /* Returns zero if label not found. */
4125 /*-----------------------------------------------------------------*/
4127 findLabelBackwards (iCode * ic, int key)
4136 /* If we have any pushes or pops, we cannot predict the distance.
4137 I don't like this at all, this should be dealt with in the
4139 if (ic->op == IPUSH || ic->op == IPOP) {
4143 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4152 /*-----------------------------------------------------------------*/
4153 /* genPlusIncr :- does addition with increment if possible */
4154 /*-----------------------------------------------------------------*/
4156 genPlusIncr (iCode * ic)
4158 unsigned int icount;
4159 unsigned int size = getDataSize (IC_RESULT (ic));
4161 /* will try to generate an increment */
4162 /* if the right side is not a literal
4164 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4167 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4169 D(emitcode (";","genPlusIncr"));
4171 /* if increment >=16 bits in register or direct space */
4172 if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG ||
4173 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4174 (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4175 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4176 !isOperandVolatile (IC_RESULT (ic), FALSE) &&
4184 /* If the next instruction is a goto and the goto target
4185 * is < 10 instructions previous to this, we can generate
4186 * jumps straight to that target.
4188 if (ic->next && ic->next->op == GOTO
4189 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4190 && labelRange <= 10)
4192 D (emitcode (";", "tail increment optimized (range %d)", labelRange));
4193 tlbl = IC_LABEL (ic->next);
4198 tlbl = newiTempLabel (NULL);
4201 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4202 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4203 IS_AOP_PREG (IC_RESULT (ic)))
4204 emitcode ("cjne", "%s,#0x00,%05d$",
4205 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4209 emitcode ("clr", "a");
4210 emitcode ("cjne", "a,%s,%05d$",
4211 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4215 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4218 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4219 IS_AOP_PREG (IC_RESULT (ic)))
4220 emitcode ("cjne", "%s,#0x00,%05d$",
4221 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4224 emitcode ("cjne", "a,%s,%05d$",
4225 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4228 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4232 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4233 IS_AOP_PREG (IC_RESULT (ic)))
4234 emitcode ("cjne", "%s,#0x00,%05d$",
4235 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4239 emitcode ("cjne", "a,%s,%05d$",
4240 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4243 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4253 /* if result is dptr */
4254 if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
4255 (AOP_SIZE (IC_RESULT (ic)) == 2) &&
4256 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
4257 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
4259 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4265 if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
4268 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0);
4269 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1);
4271 emitcode ("inc", "dptr");
4276 /* if the literal value of the right hand side
4277 is greater than 4 then it is not worth it */
4281 /* if the sizes are greater than 1 then we cannot */
4282 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4283 AOP_SIZE (IC_LEFT (ic)) > 1)
4286 /* we can if the aops of the left & result match or
4287 if they are in registers and the registers are the
4289 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4293 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4294 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4295 aopPut (IC_RESULT (ic), "a", 0);
4301 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4310 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4311 emitcode ("inc", "a");
4312 aopPut (IC_RESULT (ic), "a", 0);
4319 /*-----------------------------------------------------------------*/
4320 /* outBitAcc - output a bit in acc */
4321 /*-----------------------------------------------------------------*/
4323 outBitAcc (operand * result)
4325 symbol *tlbl = newiTempLabel (NULL);
4326 /* if the result is a bit */
4327 if (AOP_TYPE (result) == AOP_CRY)
4329 aopPut (result, "a", 0);
4333 emitcode ("jz", "%05d$", tlbl->key + 100);
4334 emitcode ("mov", "a,%s", one);
4340 /*-----------------------------------------------------------------*/
4341 /* genPlusBits - generates code for addition of two bits */
4342 /*-----------------------------------------------------------------*/
4344 genPlusBits (iCode * ic)
4346 D (emitcode (";", "genPlusBits"));
4348 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4349 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4351 symbol *lbl = newiTempLabel (NULL);
4352 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4353 emitcode ("cpl", "c");
4355 outBitC (IC_RESULT (ic));
4359 emitcode ("clr", "a");
4360 emitcode ("rlc", "a");
4361 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4362 emitcode ("addc", "a,%s", zero);
4363 outAcc (IC_RESULT (ic));
4368 /* This is the original version of this code.
4370 * This is being kept around for reference,
4371 * because I am not entirely sure I got it right...
4374 adjustArithmeticResult (iCode * ic)
4376 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4377 AOP_SIZE (IC_LEFT (ic)) == 3 &&
4378 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4379 aopPut (IC_RESULT (ic),
4380 aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4383 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4384 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4385 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4386 aopPut (IC_RESULT (ic),
4387 aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4390 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4391 AOP_SIZE (IC_LEFT (ic)) < 3 &&
4392 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4393 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4394 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4397 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4398 aopPut (IC_RESULT (ic), buffer, 2);
4402 /* This is the pure and virtuous version of this code.
4403 * I'm pretty certain it's right, but not enough to toss the old
4407 adjustArithmeticResult (iCode * ic)
4409 if (opIsGptr (IC_RESULT (ic)) &&
4410 opIsGptr (IC_LEFT (ic)) &&
4411 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4413 aopPut (IC_RESULT (ic),
4414 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4418 if (opIsGptr (IC_RESULT (ic)) &&
4419 opIsGptr (IC_RIGHT (ic)) &&
4420 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4422 aopPut (IC_RESULT (ic),
4423 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4427 if (opIsGptr (IC_RESULT (ic)) &&
4428 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4429 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4430 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4431 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4434 SNPRINTF (buffer, sizeof(buffer),
4435 "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4436 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4441 /*-----------------------------------------------------------------*/
4442 /* genPlus - generates code for addition */
4443 /*-----------------------------------------------------------------*/
4445 genPlus (iCode * ic)
4447 int size, offset = 0;
4450 bool swappedLR = FALSE;
4451 operand *leftOp, *rightOp;
4454 D (emitcode (";", "genPlus"));
4456 /* special cases :- */
4458 aopOp (IC_LEFT (ic), ic, FALSE);
4459 aopOp (IC_RIGHT (ic), ic, FALSE);
4460 aopOp (IC_RESULT (ic), ic, TRUE);
4462 /* if literal, literal on the right or
4463 if left requires ACC or right is already
4465 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4466 (AOP_NEEDSACC (IC_LEFT (ic))) ||
4467 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4469 operand *t = IC_RIGHT (ic);
4470 IC_RIGHT (ic) = IC_LEFT (ic);
4475 /* if both left & right are in bit
4477 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4478 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4484 /* if left in bit space & right literal */
4485 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4486 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4488 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4489 /* if result in bit space */
4490 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4492 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4493 emitcode ("cpl", "c");
4494 outBitC (IC_RESULT (ic));
4498 size = getDataSize (IC_RESULT (ic));
4501 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4502 emitcode ("addc", "a,%s", zero);
4503 aopPut (IC_RESULT (ic), "a", offset++);
4509 /* if I can do an increment instead
4510 of add then GOOD for ME */
4511 if (genPlusIncr (ic) == TRUE)
4514 size = getDataSize (IC_RESULT (ic));
4515 leftOp = IC_LEFT(ic);
4516 rightOp = IC_RIGHT(ic);
4519 /* if this is an add for an array access
4520 at a 256 byte boundary */
4522 && AOP_TYPE (op) == AOP_IMMD
4524 && IS_SPEC (OP_SYM_ETYPE (op))
4525 && SPEC_ABSA (OP_SYM_ETYPE (op))
4526 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4529 D(emitcode ("; genPlus aligned array",""));
4530 aopPut (IC_RESULT (ic),
4531 aopGet (rightOp, 0, FALSE, FALSE),
4534 if( 1 == getDataSize (IC_RIGHT (ic)) )
4536 aopPut (IC_RESULT (ic),
4537 aopGet (leftOp, 1, FALSE, FALSE),
4542 MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4543 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4544 aopPut (IC_RESULT (ic), "a", 1);
4549 /* if the lower bytes of a literal are zero skip the addition */
4550 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4552 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4553 (skip_bytes+1 < size))
4558 D(emitcode ("; genPlus shortcut",""));
4563 if( offset >= skip_bytes )
4565 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4568 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4570 emitcode("xch", "a,b");
4571 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4572 emitcode (add, "a,b");
4575 else if (aopGetUsesAcc (leftOp, offset))
4577 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4578 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4582 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4583 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4585 aopPut (IC_RESULT (ic), "a", offset);
4586 add = "addc"; /* further adds must propagate carry */
4590 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4591 isOperandVolatile (IC_RESULT (ic), FALSE))
4594 aopPut (IC_RESULT (ic),
4595 aopGet (leftOp, offset, FALSE, FALSE),
4602 adjustArithmeticResult (ic);
4605 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4608 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4609 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4613 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4614 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4618 /*-----------------------------------------------------------------*/
4619 /* genMinusDec :- does subtraction with decrement if possible */
4620 /*-----------------------------------------------------------------*/
4622 genMinusDec (iCode * ic)
4624 unsigned int icount;
4625 unsigned int size = getDataSize (IC_RESULT (ic));
4627 /* will try to generate an increment */
4628 /* if the right side is not a literal
4630 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4633 /* if the literal value of the right hand side
4634 is greater than 4 then it is not worth it */
4635 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4638 D (emitcode (";", "genMinusDec"));
4640 /* if decrement >=16 bits in register or direct space */
4641 if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG ||
4642 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4643 (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4644 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4652 /* If the next instruction is a goto and the goto target
4653 * is <= 10 instructions previous to this, we can generate
4654 * jumps straight to that target.
4656 if (ic->next && ic->next->op == GOTO
4657 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4658 && labelRange <= 10)
4660 D (emitcode (";", "tail decrement optimized (range %d)", labelRange));
4661 tlbl = IC_LABEL (ic->next);
4666 tlbl = newiTempLabel (NULL);
4670 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4671 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4672 IS_AOP_PREG (IC_RESULT (ic)))
4673 emitcode ("cjne", "%s,#0xff,%05d$"
4674 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4678 emitcode ("mov", "a,#0xff");
4679 emitcode ("cjne", "a,%s,%05d$"
4680 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4683 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4686 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4687 IS_AOP_PREG (IC_RESULT (ic)))
4688 emitcode ("cjne", "%s,#0xff,%05d$"
4689 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4693 emitcode ("cjne", "a,%s,%05d$"
4694 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4697 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4701 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4702 IS_AOP_PREG (IC_RESULT (ic)))
4703 emitcode ("cjne", "%s,#0xff,%05d$"
4704 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4708 emitcode ("cjne", "a,%s,%05d$"
4709 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4712 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4721 /* if the sizes are greater than 1 then we cannot */
4722 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4723 AOP_SIZE (IC_LEFT (ic)) > 1)
4726 /* we can if the aops of the left & result match or
4727 if they are in registers and the registers are the
4729 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4733 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4735 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4740 l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
4745 emitcode ("dec", "%s", l);
4748 if (AOP_NEEDSACC (IC_RESULT (ic)))
4749 aopPut (IC_RESULT (ic), "a", 0);
4756 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4757 emitcode ("dec", "a");
4758 aopPut (IC_RESULT (ic), "a", 0);
4765 /*-----------------------------------------------------------------*/
4766 /* addSign - complete with sign */
4767 /*-----------------------------------------------------------------*/
4769 addSign (operand * result, int offset, int sign)
4771 int size = (getDataSize (result) - offset);
4776 emitcode ("rlc", "a");
4777 emitcode ("subb", "a,acc");
4780 aopPut (result, "a", offset++);
4787 aopPut (result, zero, offset++);
4793 /*-----------------------------------------------------------------*/
4794 /* genMinusBits - generates code for subtraction of two bits */
4795 /*-----------------------------------------------------------------*/
4797 genMinusBits (iCode * ic)
4799 symbol *lbl = newiTempLabel (NULL);
4801 D (emitcode (";", "genMinusBits"));
4803 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4805 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4806 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4807 emitcode ("cpl", "c");
4809 outBitC (IC_RESULT (ic));
4813 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4814 emitcode ("subb", "a,acc");
4815 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4816 emitcode ("inc", "a");
4818 aopPut (IC_RESULT (ic), "a", 0);
4819 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4823 /*-----------------------------------------------------------------*/
4824 /* genMinus - generates code for subtraction */
4825 /*-----------------------------------------------------------------*/
4827 genMinus (iCode * ic)
4829 int size, offset = 0;
4831 D (emitcode (";", "genMinus"));
4833 aopOp (IC_LEFT (ic), ic, FALSE);
4834 aopOp (IC_RIGHT (ic), ic, FALSE);
4835 aopOp (IC_RESULT (ic), ic, TRUE);
4837 /* special cases :- */
4838 /* if both left & right are in bit space */
4839 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4840 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4846 /* if I can do an decrement instead
4847 of subtract then GOOD for ME */
4848 if (genMinusDec (ic) == TRUE)
4851 size = getDataSize (IC_RESULT (ic));
4853 /* if literal, add a,#-lit, else normal subb */
4854 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4856 unsigned long lit = 0L;
4857 bool useCarry = FALSE;
4859 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4864 if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4866 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4867 if (!offset && !size && lit== (unsigned long) -1)
4869 emitcode ("dec", "a");
4873 /* first add without previous c */
4874 emitcode ("add", "a,#0x%02x",
4875 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4880 emitcode ("addc", "a,#0x%02x",
4881 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4883 aopPut (IC_RESULT (ic), "a", offset++);
4887 /* no need to add zeroes */
4888 if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4890 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4899 operand *leftOp, *rightOp;
4901 leftOp = IC_LEFT(ic);
4902 rightOp = IC_RIGHT(ic);
4906 if (aopGetUsesAcc(rightOp, offset)) {
4907 if (aopGetUsesAcc(leftOp, offset)) {
4910 MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4912 emitcode ("mov", "b,a");
4915 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4916 emitcode ("subb", "a,b");
4919 /* reverse subtraction with 2's complement */
4921 emitcode( "setb", "c");
4923 emitcode( "cpl", "c");
4924 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4925 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4926 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4927 emitcode("cpl", "a");
4928 if (size) /* skip if last byte */
4929 emitcode( "cpl", "c");
4932 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4935 emitcode ("subb", "a,%s",
4936 aopGet(rightOp, offset, FALSE, TRUE));
4939 aopPut (IC_RESULT (ic), "a", offset++);
4943 adjustArithmeticResult (ic);
4946 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4947 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4948 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4952 /*-----------------------------------------------------------------*/
4953 /* genMultbits :- multiplication of bits */
4954 /*-----------------------------------------------------------------*/
4956 genMultbits (operand * left,
4960 D (emitcode (";", "genMultbits"));
4962 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4963 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4967 /*-----------------------------------------------------------------*/
4968 /* genMultOneByte : 8*8=8/16 bit multiplication */
4969 /*-----------------------------------------------------------------*/
4971 genMultOneByte (operand * left,
4976 int size = AOP_SIZE (result);
4977 bool runtimeSign, compiletimeSign;
4978 bool lUnsigned, rUnsigned, pushedB;
4980 D (emitcode (";", "genMultOneByte"));
4982 if (size < 1 || size > 2)
4984 /* this should never happen */
4985 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4986 AOP_SIZE(result), __FILE__, lineno);
4990 /* (if two literals: the value is computed before) */
4991 /* if one literal, literal on the right */
4992 if (AOP_TYPE (left) == AOP_LIT)
4997 /* emitcode (";", "swapped left and right"); */
4999 /* if no literal, unsigned on the right: shorter code */
5000 if ( AOP_TYPE (right) != AOP_LIT
5001 && SPEC_USIGN (getSpec (operandType (left))))
5008 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5009 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5013 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
5014 no need to take care about the signedness! */
5015 || (lUnsigned && rUnsigned))
5017 /* just an unsigned 8 * 8 = 8 multiply
5019 /* emitcode (";","unsigned"); */
5020 /* TODO: check for accumulator clash between left & right aops? */
5022 if (AOP_TYPE (right) == AOP_LIT)
5024 /* moving to accumulator first helps peepholes */
5025 MOVA (aopGet (left, 0, FALSE, FALSE));
5026 MOVB (aopGet (right, 0, FALSE, FALSE));
5030 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5031 MOVA (aopGet (left, 0, FALSE, FALSE));
5034 emitcode ("mul", "ab");
5035 aopPut (result, "a", 0);
5037 aopPut (result, "b", 1);
5043 /* we have to do a signed multiply */
5044 /* emitcode (";", "signed"); */
5046 /* now sign adjust for both left & right */
5048 /* let's see what's needed: */
5049 /* apply negative sign during runtime */
5050 runtimeSign = FALSE;
5051 /* negative sign from literals */
5052 compiletimeSign = FALSE;
5056 if (AOP_TYPE(left) == AOP_LIT)
5058 /* signed literal */
5059 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5061 compiletimeSign = TRUE;
5064 /* signed but not literal */
5070 if (AOP_TYPE(right) == AOP_LIT)
5072 /* signed literal */
5073 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5075 compiletimeSign ^= TRUE;
5078 /* signed but not literal */
5082 /* initialize F0, which stores the runtime sign */
5085 if (compiletimeSign)
5086 emitcode ("setb", "F0"); /* set sign flag */
5088 emitcode ("clr", "F0"); /* reset sign flag */
5091 /* save the signs of the operands */
5092 if (AOP_TYPE(right) == AOP_LIT)
5094 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5096 if (!rUnsigned && val < 0)
5097 emitcode ("mov", "b,#0x%02x", -val);
5099 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5101 else /* ! literal */
5103 if (rUnsigned) /* emitcode (";", "signed"); */
5104 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5107 MOVA (aopGet (right, 0, FALSE, FALSE));
5108 lbl = newiTempLabel (NULL);
5109 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5110 emitcode ("cpl", "F0"); /* complement sign flag */
5111 emitcode ("cpl", "a"); /* 2's complement */
5112 emitcode ("inc", "a");
5114 emitcode ("mov", "b,a");
5118 if (AOP_TYPE(left) == AOP_LIT)
5120 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5122 if (!lUnsigned && val < 0)
5123 emitcode ("mov", "a,#0x%02x", -val);
5125 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5127 else /* ! literal */
5129 MOVA (aopGet (left, 0, FALSE, FALSE));
5133 lbl = newiTempLabel (NULL);
5134 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5135 emitcode ("cpl", "F0"); /* complement sign flag */
5136 emitcode ("cpl", "a"); /* 2's complement */
5137 emitcode ("inc", "a");
5142 /* now the multiplication */
5143 emitcode ("mul", "ab");
5144 if (runtimeSign || compiletimeSign)
5146 lbl = newiTempLabel (NULL);
5148 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5149 emitcode ("cpl", "a"); /* lsb 2's complement */
5151 emitcode ("inc", "a"); /* inc doesn't set carry flag */
5154 emitcode ("add", "a,#1"); /* this sets carry flag */
5155 emitcode ("xch", "a,b");
5156 emitcode ("cpl", "a"); /* msb 2's complement */
5157 emitcode ("addc", "a,#0");
5158 emitcode ("xch", "a,b");
5162 aopPut (result, "a", 0);
5164 aopPut (result, "b", 1);
5169 /*-----------------------------------------------------------------*/
5170 /* genMult - generates code for multiplication */
5171 /*-----------------------------------------------------------------*/
5173 genMult (iCode * ic)
5175 operand *left = IC_LEFT (ic);
5176 operand *right = IC_RIGHT (ic);
5177 operand *result = IC_RESULT (ic);
5179 D (emitcode (";", "genMult"));
5181 /* assign the asmops */
5182 aopOp (left, ic, FALSE);
5183 aopOp (right, ic, FALSE);
5184 aopOp (result, ic, TRUE);
5186 /* special cases first */
5188 if (AOP_TYPE (left) == AOP_CRY &&
5189 AOP_TYPE (right) == AOP_CRY)
5191 genMultbits (left, right, result);
5195 /* if both are of size == 1 */
5196 #if 0 // one of them can be a sloc shared with the result
5197 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
5199 if (getSize(operandType(left)) == 1 &&
5200 getSize(operandType(right)) == 1)
5203 genMultOneByte (left, right, result);
5207 /* should have been converted to function call */
5208 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
5209 getSize(OP_SYMBOL(right)->type));
5213 freeAsmop (result, NULL, ic, TRUE);
5214 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5215 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5218 /*-----------------------------------------------------------------*/
5219 /* genDivbits :- division of bits */
5220 /*-----------------------------------------------------------------*/
5222 genDivbits (operand * left,
5229 D(emitcode ("; genDivbits",""));
5233 /* the result must be bit */
5234 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5235 l = aopGet (left, 0, FALSE, FALSE);
5239 emitcode ("div", "ab");
5240 emitcode ("rrc", "a");
5244 aopPut (result, "c", 0);
5247 /*-----------------------------------------------------------------*/
5248 /* genDivOneByte : 8 bit division */
5249 /*-----------------------------------------------------------------*/
5251 genDivOneByte (operand * left,
5255 bool lUnsigned, rUnsigned, pushedB;
5256 bool runtimeSign, compiletimeSign;
5257 bool accuse = FALSE;
5258 bool pushedA = FALSE;
5262 D(emitcode ("; genDivOneByte",""));
5264 /* Why is it necessary that genDivOneByte() can return an int result?
5267 volatile unsigned char uc;
5268 volatile signed char sc1, sc2;
5281 In all cases a one byte result would overflow, the following cast to int
5282 would return the wrong result.
5284 Two possible solution:
5285 a) cast operands to int, if ((unsigned) / (signed)) or
5286 ((signed) / (signed))
5287 b) return an 16 bit signed int; this is what we're doing here!
5290 size = AOP_SIZE (result) - 1;
5292 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5293 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5297 /* signed or unsigned */
5298 if (lUnsigned && rUnsigned)
5300 /* unsigned is easy */
5301 MOVB (aopGet (right, 0, FALSE, FALSE));
5302 MOVA (aopGet (left, 0, FALSE, FALSE));
5303 emitcode ("div", "ab");
5304 aopPut (result, "a", 0);
5306 aopPut (result, zero, offset++);
5312 /* signed is a little bit more difficult */
5314 /* now sign adjust for both left & right */
5316 /* let's see what's needed: */
5317 /* apply negative sign during runtime */
5318 runtimeSign = FALSE;
5319 /* negative sign from literals */
5320 compiletimeSign = FALSE;
5324 if (AOP_TYPE(left) == AOP_LIT)
5326 /* signed literal */
5327 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5329 compiletimeSign = TRUE;
5332 /* signed but not literal */
5338 if (AOP_TYPE(right) == AOP_LIT)
5340 /* signed literal */
5341 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5343 compiletimeSign ^= TRUE;
5346 /* signed but not literal */
5350 /* initialize F0, which stores the runtime sign */
5353 if (compiletimeSign)
5354 emitcode ("setb", "F0"); /* set sign flag */
5356 emitcode ("clr", "F0"); /* reset sign flag */
5359 /* save the signs of the operands */
5360 if (AOP_TYPE(right) == AOP_LIT)
5362 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5364 if (!rUnsigned && val < 0)
5365 emitcode ("mov", "b,#0x%02x", -val);
5367 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5369 else /* ! literal */
5372 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5375 MOVA (aopGet (right, 0, FALSE, FALSE));
5376 lbl = newiTempLabel (NULL);
5377 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5378 emitcode ("cpl", "F0"); /* complement sign flag */
5379 emitcode ("cpl", "a"); /* 2's complement */
5380 emitcode ("inc", "a");
5382 emitcode ("mov", "b,a");
5386 if (AOP_TYPE(left) == AOP_LIT)
5388 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5390 if (!lUnsigned && val < 0)
5391 emitcode ("mov", "a,#0x%02x", -val);
5393 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5395 else /* ! literal */
5397 MOVA (aopGet (left, 0, FALSE, FALSE));
5401 lbl = newiTempLabel (NULL);
5402 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5403 emitcode ("cpl", "F0"); /* complement sign flag */
5404 emitcode ("cpl", "a"); /* 2's complement */
5405 emitcode ("inc", "a");
5410 /* now the division */
5411 emitcode ("div", "ab");
5413 if (runtimeSign || compiletimeSign)
5415 lbl = newiTempLabel (NULL);
5417 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5418 emitcode ("cpl", "a"); /* lsb 2's complement */
5419 emitcode ("inc", "a");
5422 accuse = aopPut (result, "a", 0);
5425 /* msb is 0x00 or 0xff depending on the sign */
5430 emitcode ("push", "acc");
5433 emitcode ("mov", "c,F0");
5434 emitcode ("subb", "a,acc");
5436 aopPut (result, "a", offset++);
5438 else /* compiletimeSign */
5440 if (aopPutUsesAcc (result, "#0xFF", offset))
5442 emitcode ("push", "acc");
5446 aopPut (result, "#0xff", offset++);
5452 aopPut (result, "a", 0);
5454 aopPut (result, zero, offset++);
5458 emitcode ("pop", "acc");
5462 /*-----------------------------------------------------------------*/
5463 /* genDiv - generates code for division */
5464 /*-----------------------------------------------------------------*/
5468 operand *left = IC_LEFT (ic);
5469 operand *right = IC_RIGHT (ic);
5470 operand *result = IC_RESULT (ic);
5472 D (emitcode (";", "genDiv"));
5474 /* assign the amsops */
5475 aopOp (left, ic, FALSE);
5476 aopOp (right, ic, FALSE);
5477 aopOp (result, ic, TRUE);
5479 /* special cases first */
5481 if (AOP_TYPE (left) == AOP_CRY &&
5482 AOP_TYPE (right) == AOP_CRY)
5484 genDivbits (left, right, result);
5488 /* if both are of size == 1 */
5489 if (AOP_SIZE (left) == 1 &&
5490 AOP_SIZE (right) == 1)
5492 genDivOneByte (left, right, result);
5496 /* should have been converted to function call */
5499 freeAsmop (result, NULL, ic, TRUE);
5500 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5501 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5504 /*-----------------------------------------------------------------*/
5505 /* genModbits :- modulus of bits */
5506 /*-----------------------------------------------------------------*/
5508 genModbits (operand * left,
5515 D (emitcode (";", "genModbits"));
5519 /* the result must be bit */
5520 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5521 l = aopGet (left, 0, FALSE, FALSE);
5525 emitcode ("div", "ab");
5526 emitcode ("mov", "a,b");
5527 emitcode ("rrc", "a");
5531 aopPut (result, "c", 0);
5534 /*-----------------------------------------------------------------*/
5535 /* genModOneByte : 8 bit modulus */
5536 /*-----------------------------------------------------------------*/
5538 genModOneByte (operand * left,
5542 bool lUnsigned, rUnsigned, pushedB;
5543 bool runtimeSign, compiletimeSign;
5547 D (emitcode (";", "genModOneByte"));
5549 size = AOP_SIZE (result) - 1;
5551 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5552 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5554 /* if right is a literal, check it for 2^n */
5555 if (AOP_TYPE(right) == AOP_LIT)
5557 unsigned char val = abs((int) operandLitValue(right));
5558 symbol *lbl2 = NULL;
5562 case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5571 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5572 "modulus of unsigned char by 2^n literal shouldn't be processed here");
5573 /* because iCode should have been changed to genAnd */
5574 /* see file "SDCCopt.c", function "convertToFcall()" */
5576 MOVA (aopGet (left, 0, FALSE, FALSE));
5577 emitcode ("mov", "c,acc.7");
5578 emitcode ("anl", "a,#0x%02x", val - 1);
5579 lbl = newiTempLabel (NULL);
5580 emitcode ("jz", "%05d$", (lbl->key + 100));
5581 emitcode ("jnc", "%05d$", (lbl->key + 100));
5582 emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5588 aopPut (result, "a", 0);
5590 aopPut (result, "#0xff", offs2++);
5591 lbl2 = newiTempLabel (NULL);
5592 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5595 aopPut (result, "a", 0);
5597 aopPut (result, zero, offset++);
5611 /* signed or unsigned */
5612 if (lUnsigned && rUnsigned)
5614 /* unsigned is easy */
5615 MOVB (aopGet (right, 0, FALSE, FALSE));
5616 MOVA (aopGet (left, 0, FALSE, FALSE));
5617 emitcode ("div", "ab");
5618 aopPut (result, "b", 0);
5620 aopPut (result, zero, offset++);
5626 /* signed is a little bit more difficult */
5628 /* now sign adjust for both left & right */
5630 /* modulus: sign of the right operand has no influence on the result! */
5631 if (AOP_TYPE(right) == AOP_LIT)
5633 signed char val = (char) operandLitValue(right);
5635 if (!rUnsigned && val < 0)
5636 emitcode ("mov", "b,#0x%02x", -val);
5638 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5640 else /* not literal */
5643 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5646 MOVA (aopGet (right, 0, FALSE, FALSE));
5647 lbl = newiTempLabel (NULL);
5648 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5649 emitcode ("cpl", "a"); /* 2's complement */
5650 emitcode ("inc", "a");
5652 emitcode ("mov", "b,a");
5656 /* let's see what's needed: */
5657 /* apply negative sign during runtime */
5658 runtimeSign = FALSE;
5659 /* negative sign from literals */
5660 compiletimeSign = FALSE;
5662 /* sign adjust left side */
5663 if (AOP_TYPE(left) == AOP_LIT)
5665 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5667 if (!lUnsigned && val < 0)
5669 compiletimeSign = TRUE; /* set sign flag */
5670 emitcode ("mov", "a,#0x%02x", -val);
5673 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5675 else /* ! literal */
5677 MOVA (aopGet (left, 0, FALSE, FALSE));
5682 emitcode ("clr", "F0"); /* clear sign flag */
5684 lbl = newiTempLabel (NULL);
5685 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5686 emitcode ("setb", "F0"); /* set sign flag */
5687 emitcode ("cpl", "a"); /* 2's complement */
5688 emitcode ("inc", "a");
5693 /* now the modulus */
5694 emitcode ("div", "ab");
5696 if (runtimeSign || compiletimeSign)
5698 emitcode ("mov", "a,b");
5699 lbl = newiTempLabel (NULL);
5701 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5702 emitcode ("cpl", "a"); /* 2's complement */
5703 emitcode ("inc", "a");
5706 aopPut (result, "a", 0);
5709 /* msb is 0x00 or 0xff depending on the sign */
5712 emitcode ("mov", "c,F0");
5713 emitcode ("subb", "a,acc");
5715 aopPut (result, "a", offset++);
5717 else /* compiletimeSign */
5719 aopPut (result, "#0xff", offset++);
5724 aopPut (result, "b", 0);
5726 aopPut (result, zero, offset++);
5732 /*-----------------------------------------------------------------*/
5733 /* genMod - generates code for division */
5734 /*-----------------------------------------------------------------*/
5738 operand *left = IC_LEFT (ic);
5739 operand *right = IC_RIGHT (ic);
5740 operand *result = IC_RESULT (ic);
5742 D (emitcode (";", "genMod"));
5744 /* assign the asmops */
5745 aopOp (left, ic, FALSE);
5746 aopOp (right, ic, FALSE);
5747 aopOp (result, ic, TRUE);
5749 /* special cases first */
5751 if (AOP_TYPE (left) == AOP_CRY &&
5752 AOP_TYPE (right) == AOP_CRY)
5754 genModbits (left, right, result);
5758 /* if both are of size == 1 */
5759 if (AOP_SIZE (left) == 1 &&
5760 AOP_SIZE (right) == 1)
5762 genModOneByte (left, right, result);
5766 /* should have been converted to function call */
5770 freeAsmop (result, NULL, ic, TRUE);
5771 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5772 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5775 /*-----------------------------------------------------------------*/
5776 /* genIfxJump :- will create a jump depending on the ifx */
5777 /*-----------------------------------------------------------------*/
5779 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5782 symbol *tlbl = newiTempLabel (NULL);
5785 D (emitcode (";", "genIfxJump"));
5787 /* if true label then we jump if condition
5791 jlbl = IC_TRUE (ic);
5792 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5793 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5797 /* false label is present */
5798 jlbl = IC_FALSE (ic);
5799 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5800 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5802 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5803 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5805 emitcode (inst, "%05d$", tlbl->key + 100);
5806 freeForBranchAsmop (result);
5807 freeForBranchAsmop (right);
5808 freeForBranchAsmop (left);
5809 emitcode ("ljmp", "%05d$", jlbl->key + 100);
5812 /* mark the icode as generated */
5816 /*-----------------------------------------------------------------*/
5817 /* genCmp :- greater or less than comparison */
5818 /*-----------------------------------------------------------------*/
5820 genCmp (operand * left, operand * right,
5821 operand * result, iCode * ifx, int sign, iCode *ic)
5823 int size, offset = 0;
5824 unsigned long lit = 0L;
5827 D (emitcode (";", "genCmp"));
5829 /* if left & right are bit variables */
5830 if (AOP_TYPE (left) == AOP_CRY &&
5831 AOP_TYPE (right) == AOP_CRY)
5833 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5834 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5838 /* subtract right from left if at the
5839 end the carry flag is set then we know that
5840 left is greater than right */
5841 size = max (AOP_SIZE (left), AOP_SIZE (right));
5843 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5844 if ((size == 1) && !sign &&
5845 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5847 symbol *lbl = newiTempLabel (NULL);
5848 emitcode ("cjne", "%s,%s,%05d$",
5849 aopGet (left, offset, FALSE, FALSE),
5850 aopGet (right, offset, FALSE, FALSE),
5856 if (AOP_TYPE (right) == AOP_LIT)
5858 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5859 /* optimize if(x < 0) or if(x >= 0) */
5868 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5869 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5871 genIfxJump (ifx, "acc.7", left, right, result);
5872 freeAsmop (right, NULL, ic, TRUE);
5873 freeAsmop (left, NULL, ic, TRUE);
5879 emitcode ("rlc", "a");
5886 int bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5887 while (size && (bytelit == 0))
5890 bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5896 MOVA (aopGet (left, offset, FALSE, FALSE));
5897 if (sign && size == 0)
5899 emitcode ("xrl", "a,#0x80");
5900 emitcode ("subb", "a,#0x%02x",
5901 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5905 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5915 bool pushedB = FALSE;
5916 rightInB = aopGetUsesAcc(right, offset);
5920 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5922 MOVA (aopGet (left, offset, FALSE, FALSE));
5923 if (sign && size == 0)
5925 emitcode ("xrl", "a,#0x80");
5930 MOVB (aopGet (right, offset, FALSE, FALSE));
5932 emitcode ("xrl", "b,#0x80");
5933 emitcode ("subb", "a,b");
5938 emitcode ("subb", "a,b");
5940 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5950 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5951 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5952 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5958 /* if the result is used in the next
5959 ifx conditional branch then generate
5960 code a little differently */
5963 genIfxJump (ifx, "c", NULL, NULL, result);
5969 /* leave the result in acc */
5973 /*-----------------------------------------------------------------*/
5974 /* genCmpGt :- greater than comparison */
5975 /*-----------------------------------------------------------------*/
5977 genCmpGt (iCode * ic, iCode * ifx)
5979 operand *left, *right, *result;
5980 sym_link *letype, *retype;
5983 D (emitcode (";", "genCmpGt"));
5985 left = IC_LEFT (ic);
5986 right = IC_RIGHT (ic);
5987 result = IC_RESULT (ic);
5989 letype = getSpec (operandType (left));
5990 retype = getSpec (operandType (right));
5991 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5992 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5993 /* assign the amsops */
5994 aopOp (result, ic, TRUE);
5995 aopOp (left, ic, FALSE);
5996 aopOp (right, ic, FALSE);
5998 genCmp (right, left, result, ifx, sign, ic);
6000 freeAsmop (result, NULL, ic, TRUE);
6003 /*-----------------------------------------------------------------*/
6004 /* genCmpLt - less than comparisons */
6005 /*-----------------------------------------------------------------*/
6007 genCmpLt (iCode * ic, iCode * ifx)
6009 operand *left, *right, *result;
6010 sym_link *letype, *retype;
6013 D (emitcode (";", "genCmpLt"));
6015 left = IC_LEFT (ic);
6016 right = IC_RIGHT (ic);
6017 result = IC_RESULT (ic);
6019 letype = getSpec (operandType (left));
6020 retype = getSpec (operandType (right));
6021 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
6022 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
6023 /* assign the amsops */
6024 aopOp (result, ic, TRUE);
6025 aopOp (left, ic, FALSE);
6026 aopOp (right, ic, FALSE);
6028 genCmp (left, right, result, ifx, sign, ic);
6030 freeAsmop (result, NULL, ic, TRUE);
6033 /*-----------------------------------------------------------------*/
6034 /* gencjneshort - compare and jump if not equal */
6035 /*-----------------------------------------------------------------*/
6037 gencjneshort (operand * left, operand * right, symbol * lbl)
6039 int size = max (AOP_SIZE (left), AOP_SIZE (right));
6041 unsigned long lit = 0L;
6043 D (emitcode (";", "gencjneshort"));
6045 /* if the left side is a literal or
6046 if the right is in a pointer register and left
6048 if ((AOP_TYPE (left) == AOP_LIT) ||
6049 (AOP_TYPE (left) == AOP_IMMD) ||
6050 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6057 if (AOP_TYPE (right) == AOP_LIT)
6058 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6060 /* if the right side is a literal then anything goes */
6061 if (AOP_TYPE (right) == AOP_LIT &&
6062 AOP_TYPE (left) != AOP_DIR &&
6063 AOP_TYPE (left) != AOP_IMMD)
6067 emitcode ("cjne", "%s,%s,%05d$",
6068 aopGet (left, offset, FALSE, FALSE),
6069 aopGet (right, offset, FALSE, FALSE),
6075 /* if the right side is in a register or in direct space or
6076 if the left is a pointer register & right is not */
6077 else if (AOP_TYPE (right) == AOP_REG ||
6078 AOP_TYPE (right) == AOP_DIR ||
6079 AOP_TYPE (right) == AOP_LIT ||
6080 AOP_TYPE (right) == AOP_IMMD ||
6081 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6082 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6086 MOVA (aopGet (left, offset, FALSE, FALSE));
6087 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6088 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6089 emitcode ("jnz", "%05d$", lbl->key + 100);
6091 emitcode ("cjne", "a,%s,%05d$",
6092 aopGet (right, offset, FALSE, TRUE),
6099 /* right is a pointer reg need both a & b */
6102 //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
6103 wassertl(!BINUSE, "B was in use");
6104 MOVB (aopGet (left, offset, FALSE, FALSE));
6105 MOVA (aopGet (right, offset, FALSE, FALSE));
6106 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
6112 /*-----------------------------------------------------------------*/
6113 /* gencjne - compare and jump if not equal */
6114 /*-----------------------------------------------------------------*/
6116 gencjne (operand * left, operand * right, symbol * lbl)
6118 symbol *tlbl = newiTempLabel (NULL);
6120 D (emitcode (";", "gencjne"));
6122 gencjneshort (left, right, lbl);
6124 emitcode ("mov", "a,%s", one);
6125 emitcode ("sjmp", "%05d$", tlbl->key + 100);
6127 emitcode ("clr", "a");
6131 /*-----------------------------------------------------------------*/
6132 /* genCmpEq - generates code for equal to */
6133 /*-----------------------------------------------------------------*/
6135 genCmpEq (iCode * ic, iCode * ifx)
6137 bool swappedLR = FALSE;
6138 operand *left, *right, *result;
6140 D (emitcode (";", "genCmpEq"));
6142 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6143 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6144 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6146 /* if literal, literal on the right or
6147 if the right is in a pointer register and left
6149 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6150 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6152 operand *t = IC_RIGHT (ic);
6153 IC_RIGHT (ic) = IC_LEFT (ic);
6158 if (ifx && !AOP_SIZE (result))
6161 /* if they are both bit variables */
6162 if (AOP_TYPE (left) == AOP_CRY &&
6163 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6165 if (AOP_TYPE (right) == AOP_LIT)
6167 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6170 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6171 emitcode ("cpl", "c");
6175 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6179 emitcode ("clr", "c");
6181 /* AOP_TYPE(right) == AOP_CRY */
6185 symbol *lbl = newiTempLabel (NULL);
6186 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6187 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6188 emitcode ("cpl", "c");
6191 /* if true label then we jump if condition
6193 tlbl = newiTempLabel (NULL);
6196 emitcode ("jnc", "%05d$", tlbl->key + 100);
6197 freeForBranchAsmop (result);
6198 freeForBranchAsmop (right);
6199 freeForBranchAsmop (left);
6200 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6204 emitcode ("jc", "%05d$", tlbl->key + 100);
6205 freeForBranchAsmop (result);
6206 freeForBranchAsmop (right);
6207 freeForBranchAsmop (left);
6208 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6214 tlbl = newiTempLabel (NULL);
6215 gencjneshort (left, right, tlbl);
6218 freeForBranchAsmop (result);
6219 freeForBranchAsmop (right);
6220 freeForBranchAsmop (left);
6221 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6226 symbol *lbl = newiTempLabel (NULL);
6227 emitcode ("sjmp", "%05d$", lbl->key + 100);
6229 freeForBranchAsmop (result);
6230 freeForBranchAsmop (right);
6231 freeForBranchAsmop (left);
6232 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6236 /* mark the icode as generated */
6241 /* if they are both bit variables */
6242 if (AOP_TYPE (left) == AOP_CRY &&
6243 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6245 if (AOP_TYPE (right) == AOP_LIT)
6247 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6250 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6251 emitcode ("cpl", "c");
6255 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6259 emitcode ("clr", "c");
6261 /* AOP_TYPE(right) == AOP_CRY */
6265 symbol *lbl = newiTempLabel (NULL);
6266 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6267 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6268 emitcode ("cpl", "c");
6272 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6279 genIfxJump (ifx, "c", left, right, result);
6282 /* if the result is used in an arithmetic operation
6283 then put the result in place */
6288 gencjne (left, right, newiTempLabel (NULL));
6289 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6291 aopPut (result, "a", 0);
6296 genIfxJump (ifx, "a", left, right, result);
6299 /* if the result is used in an arithmetic operation
6300 then put the result in place */
6301 if (AOP_TYPE (result) != AOP_CRY)
6303 /* leave the result in acc */
6307 freeAsmop (result, NULL, ic, TRUE);
6310 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6311 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6315 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6316 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6320 /*-----------------------------------------------------------------*/
6321 /* ifxForOp - returns the icode containing the ifx for operand */
6322 /*-----------------------------------------------------------------*/
6324 ifxForOp (operand * op, iCode * ic)
6326 /* if true symbol then needs to be assigned */
6327 if (IS_TRUE_SYMOP (op))
6330 /* if this has register type condition and
6331 the next instruction is ifx with the same operand
6332 and live to of the operand is upto the ifx only then */
6334 ic->next->op == IFX &&
6335 IC_COND (ic->next)->key == op->key &&
6336 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6342 /*-----------------------------------------------------------------*/
6343 /* hasInc - operand is incremented before any other use */
6344 /*-----------------------------------------------------------------*/
6346 hasInc (operand *op, iCode *ic, int osize)
6348 sym_link *type = operandType(op);
6349 sym_link *retype = getSpec (type);
6350 iCode *lic = ic->next;
6353 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6354 if (!IS_SYMOP(op)) return NULL;
6356 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6357 if (IS_AGGREGATE(type->next)) return NULL;
6358 if (osize != (isize = getSize(type->next))) return NULL;
6361 /* if operand of the form op = op + <sizeof *op> */
6362 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6363 isOperandEqual(IC_RESULT(lic),op) &&
6364 isOperandLiteral(IC_RIGHT(lic)) &&
6365 operandLitValue(IC_RIGHT(lic)) == isize) {
6368 /* if the operand used or deffed */
6369 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6372 /* if GOTO or IFX */
6373 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6379 /*-----------------------------------------------------------------*/
6380 /* genAndOp - for && operation */
6381 /*-----------------------------------------------------------------*/
6383 genAndOp (iCode * ic)
6385 operand *left, *right, *result;
6388 D (emitcode (";", "genAndOp"));
6390 /* note here that && operations that are in an
6391 if statement are taken away by backPatchLabels
6392 only those used in arthmetic operations remain */
6393 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6394 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6395 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6397 /* if both are bit variables */
6398 if (AOP_TYPE (left) == AOP_CRY &&
6399 AOP_TYPE (right) == AOP_CRY)
6401 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6402 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6407 tlbl = newiTempLabel (NULL);
6409 emitcode ("jz", "%05d$", tlbl->key + 100);
6415 freeAsmop (result, NULL, ic, TRUE);
6416 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6417 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6421 /*-----------------------------------------------------------------*/
6422 /* genOrOp - for || operation */
6423 /*-----------------------------------------------------------------*/
6425 genOrOp (iCode * ic)
6427 operand *left, *right, *result;
6430 D (emitcode (";", "genOrOp"));
6432 /* note here that || operations that are in an
6433 if statement are taken away by backPatchLabels
6434 only those used in arthmetic operations remain */
6435 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6436 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6437 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6439 /* if both are bit variables */
6440 if (AOP_TYPE (left) == AOP_CRY &&
6441 AOP_TYPE (right) == AOP_CRY)
6443 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6444 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6449 tlbl = newiTempLabel (NULL);
6451 emitcode ("jnz", "%05d$", tlbl->key + 100);
6457 freeAsmop (result, NULL, ic, TRUE);
6458 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6459 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6462 /*-----------------------------------------------------------------*/
6463 /* isLiteralBit - test if lit == 2^n */
6464 /*-----------------------------------------------------------------*/
6466 isLiteralBit (unsigned long lit)
6468 unsigned long pw[32] =
6469 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6470 0x100L, 0x200L, 0x400L, 0x800L,
6471 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6472 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6473 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6474 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6475 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6478 for (idx = 0; idx < 32; idx++)
6484 /*-----------------------------------------------------------------*/
6485 /* continueIfTrue - */
6486 /*-----------------------------------------------------------------*/
6488 continueIfTrue (iCode * ic)
6491 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6495 /*-----------------------------------------------------------------*/
6497 /*-----------------------------------------------------------------*/
6499 jumpIfTrue (iCode * ic)
6502 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6506 /*-----------------------------------------------------------------*/
6507 /* jmpTrueOrFalse - */
6508 /*-----------------------------------------------------------------*/
6510 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6512 // ugly but optimized by peephole
6515 symbol *nlbl = newiTempLabel (NULL);
6516 emitcode ("sjmp", "%05d$", nlbl->key + 100);
6518 freeForBranchAsmop (result);
6519 freeForBranchAsmop (right);
6520 freeForBranchAsmop (left);
6521 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6526 freeForBranchAsmop (result);
6527 freeForBranchAsmop (right);
6528 freeForBranchAsmop (left);
6529 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6535 /*-----------------------------------------------------------------*/
6536 /* genAnd - code for and */
6537 /*-----------------------------------------------------------------*/
6539 genAnd (iCode * ic, iCode * ifx)
6541 operand *left, *right, *result;
6542 int size, offset = 0;
6543 unsigned long lit = 0L;
6547 D (emitcode (";", "genAnd"));
6549 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6550 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6551 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6554 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6556 AOP_TYPE (left), AOP_TYPE (right));
6557 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6559 AOP_SIZE (left), AOP_SIZE (right));
6562 /* if left is a literal & right is not then exchange them */
6563 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6564 AOP_NEEDSACC (left))
6566 operand *tmp = right;
6571 /* if result = right then exchange left and right */
6572 if (sameRegs (AOP (result), AOP (right)))
6574 operand *tmp = right;
6579 /* if right is bit then exchange them */
6580 if (AOP_TYPE (right) == AOP_CRY &&
6581 AOP_TYPE (left) != AOP_CRY)
6583 operand *tmp = right;
6587 if (AOP_TYPE (right) == AOP_LIT)
6588 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6590 size = AOP_SIZE (result);
6593 // result = bit & yy;
6594 if (AOP_TYPE (left) == AOP_CRY)
6596 // c = bit & literal;
6597 if (AOP_TYPE (right) == AOP_LIT)
6601 if (size && sameRegs (AOP (result), AOP (left)))
6604 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6609 if (size && (AOP_TYPE (result) == AOP_CRY))
6611 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6614 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6619 emitcode ("clr", "c");
6624 if (AOP_TYPE (right) == AOP_CRY)
6627 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6628 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6633 MOVA (aopGet (right, 0, FALSE, FALSE));
6635 emitcode ("rrc", "a");
6636 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6644 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6645 genIfxJump (ifx, "c", left, right, result);
6649 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6650 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6651 if ((AOP_TYPE (right) == AOP_LIT) &&
6652 (AOP_TYPE (result) == AOP_CRY) &&
6653 (AOP_TYPE (left) != AOP_CRY))
6655 int posbit = isLiteralBit (lit);
6660 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6664 switch (posbit & 0x07)
6666 case 0: emitcode ("rrc", "a");
6668 case 7: emitcode ("rlc", "a");
6670 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6679 SNPRINTF (buffer, sizeof(buffer),
6680 "acc.%d", posbit & 0x07);
6681 genIfxJump (ifx, buffer, left, right, result);
6684 {// what is this case? just found it in ds390/gen.c
6685 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6692 symbol *tlbl = newiTempLabel (NULL);
6693 int sizel = AOP_SIZE (left);
6695 emitcode ("setb", "c");
6698 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6700 MOVA (aopGet (left, offset, FALSE, FALSE));
6702 if ((posbit = isLiteralBit (bytelit)) != 0)
6703 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6706 if (bytelit != 0x0FFL)
6707 emitcode ("anl", "a,%s",
6708 aopGet (right, offset, FALSE, TRUE));
6709 emitcode ("jnz", "%05d$", tlbl->key + 100);
6714 // bit = left & literal
6717 emitcode ("clr", "c");
6720 // if(left & literal)
6724 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6734 /* if left is same as result */
6735 if (sameRegs (AOP (result), AOP (left)))
6737 for (; size--; offset++)
6739 if (AOP_TYPE (right) == AOP_LIT)
6741 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6742 if (bytelit == 0x0FF)
6744 /* dummy read of volatile operand */
6745 if (isOperandVolatile (left, FALSE))
6746 MOVA (aopGet (left, offset, FALSE, FALSE));
6750 else if (bytelit == 0)
6752 aopPut (result, zero, offset);
6754 else if (IS_AOP_PREG (result))
6756 MOVA (aopGet (left, offset, FALSE, TRUE));
6757 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6758 aopPut (result, "a", offset);
6761 emitcode ("anl", "%s,%s",
6762 aopGet (left, offset, FALSE, TRUE),
6763 aopGet (right, offset, FALSE, FALSE));
6767 if (AOP_TYPE (left) == AOP_ACC)
6770 emitcode("mov", "a,b");
6771 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6773 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6775 MOVB (aopGet (left, offset, FALSE, FALSE));
6776 MOVA (aopGet (right, offset, FALSE, FALSE));
6777 emitcode ("anl", "a,b");
6778 aopPut (result, "a", offset);
6780 else if (aopGetUsesAcc (left, offset))
6782 MOVA (aopGet (left, offset, FALSE, FALSE));
6783 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6784 aopPut (result, "a", offset);
6788 MOVA (aopGet (right, offset, FALSE, FALSE));
6789 if (IS_AOP_PREG (result))
6791 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6792 aopPut (result, "a", offset);
6795 emitcode ("anl", "%s,a", aopGet (left, offset, FALSE, TRUE));
6802 // left & result in different registers
6803 if (AOP_TYPE (result) == AOP_CRY)
6806 // if(size), result in bit
6807 // if(!size && ifx), conditional oper: if(left & right)
6808 symbol *tlbl = newiTempLabel (NULL);
6809 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6811 emitcode ("setb", "c");
6814 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6815 && AOP_TYPE(left)==AOP_ACC)
6818 emitcode("mov", "a,b");
6819 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6821 else if (AOP_TYPE(left)==AOP_ACC)
6825 bool pushedB = pushB ();
6826 emitcode("mov", "b,a");
6827 MOVA (aopGet (right, offset, FALSE, FALSE));
6828 emitcode("anl", "a,b");
6833 MOVA (aopGet (right, offset, FALSE, FALSE));
6834 emitcode("anl", "a,b");
6837 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6839 MOVB (aopGet (left, offset, FALSE, FALSE));
6840 MOVA (aopGet (right, offset, FALSE, FALSE));
6841 emitcode ("anl", "a,b");
6843 else if (aopGetUsesAcc (left, offset))
6845 MOVA (aopGet (left, offset, FALSE, FALSE));
6846 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6850 MOVA (aopGet (right, offset, FALSE, FALSE));
6851 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6854 emitcode ("jnz", "%05d$", tlbl->key + 100);
6864 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6870 for (; (size--); offset++)
6873 // result = left & right
6874 if (AOP_TYPE (right) == AOP_LIT)
6876 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6877 if (bytelit == 0x0FF)
6880 aopGet (left, offset, FALSE, FALSE),
6884 else if (bytelit == 0)
6886 /* dummy read of volatile operand */
6887 if (isOperandVolatile (left, FALSE))
6888 MOVA (aopGet (left, offset, FALSE, FALSE));
6889 aopPut (result, zero, offset);
6892 else if (AOP_TYPE (left) == AOP_ACC)
6896 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6897 aopPut (result, "a", offset);
6902 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6903 aopPut (result, "b", offset);
6908 // faster than result <- left, anl result,right
6909 // and better if result is SFR
6910 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6911 && AOP_TYPE(left)==AOP_ACC)
6914 emitcode("mov", "a,b");
6915 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6917 else if (AOP_TYPE(left)==AOP_ACC)
6921 bool pushedB = pushB ();
6922 emitcode("mov", "b,a");
6923 MOVA (aopGet (right, offset, FALSE, FALSE));
6924 emitcode("anl", "a,b");
6929 MOVA (aopGet (right, offset, FALSE, FALSE));
6930 emitcode("anl", "a,b");
6933 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6935 MOVB (aopGet (left, offset, FALSE, FALSE));
6936 MOVA (aopGet (right, offset, FALSE, FALSE));
6937 emitcode ("anl", "a,b");
6939 else if (aopGetUsesAcc (left, offset))
6941 MOVA (aopGet (left, offset, FALSE, FALSE));
6942 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6946 MOVA (aopGet (right, offset, FALSE, FALSE));
6947 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6949 aopPut (result, "a", offset);
6955 freeAsmop (result, NULL, ic, TRUE);
6956 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6957 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6960 /*-----------------------------------------------------------------*/
6961 /* genOr - code for or */
6962 /*-----------------------------------------------------------------*/
6964 genOr (iCode * ic, iCode * ifx)
6966 operand *left, *right, *result;
6967 int size, offset = 0;
6968 unsigned long lit = 0L;
6971 D (emitcode (";", "genOr"));
6973 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6974 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6975 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6978 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6980 AOP_TYPE (left), AOP_TYPE (right));
6981 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6983 AOP_SIZE (left), AOP_SIZE (right));
6986 /* if left is a literal & right is not then exchange them */
6987 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6988 AOP_NEEDSACC (left))
6990 operand *tmp = right;
6995 /* if result = right then exchange them */
6996 if (sameRegs (AOP (result), AOP (right)))
6998 operand *tmp = right;
7003 /* if right is bit then exchange them */
7004 if (AOP_TYPE (right) == AOP_CRY &&
7005 AOP_TYPE (left) != AOP_CRY)
7007 operand *tmp = right;
7011 if (AOP_TYPE (right) == AOP_LIT)
7012 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7014 size = AOP_SIZE (result);
7018 if (AOP_TYPE (left) == AOP_CRY)
7020 if (AOP_TYPE (right) == AOP_LIT)
7022 // c = bit | literal;
7025 // lit != 0 => result = 1
7026 if (AOP_TYPE (result) == AOP_CRY)
7029 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7031 continueIfTrue (ifx);
7034 emitcode ("setb", "c");
7038 // lit == 0 => result = left
7039 if (size && sameRegs (AOP (result), AOP (left)))
7041 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7046 if (AOP_TYPE (right) == AOP_CRY)
7049 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7050 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7055 symbol *tlbl = newiTempLabel (NULL);
7056 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
7057 emitcode ("setb", "c");
7058 emitcode ("jb", "%s,%05d$",
7059 AOP (left)->aopu.aop_dir, tlbl->key + 100);
7061 emitcode ("jnz", "%05d$", tlbl->key + 100);
7062 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7064 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7079 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7080 genIfxJump (ifx, "c", left, right, result);
7084 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7085 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7086 if ((AOP_TYPE (right) == AOP_LIT) &&
7087 (AOP_TYPE (result) == AOP_CRY) &&
7088 (AOP_TYPE (left) != AOP_CRY))
7094 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7096 continueIfTrue (ifx);
7101 // lit = 0, result = boolean(left)
7103 emitcode ("setb", "c");
7107 symbol *tlbl = newiTempLabel (NULL);
7108 emitcode ("jnz", "%05d$", tlbl->key + 100);
7114 genIfxJump (ifx, "a", left, right, result);
7122 /* if left is same as result */
7123 if (sameRegs (AOP (result), AOP (left)))
7125 for (; size--; offset++)
7127 if (AOP_TYPE (right) == AOP_LIT)
7129 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7132 /* dummy read of volatile operand */
7133 if (isOperandVolatile (left, FALSE))
7134 MOVA (aopGet (left, offset, FALSE, FALSE));
7138 else if (bytelit == 0x0FF)
7140 aopPut (result, "#0xFF", offset);
7142 else if (IS_AOP_PREG (left))
7144 MOVA (aopGet (left, offset, FALSE, TRUE));
7145 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7146 aopPut (result, "a", offset);
7150 emitcode ("orl", "%s,%s",
7151 aopGet (left, offset, FALSE, TRUE),
7152 aopGet (right, offset, FALSE, FALSE));
7157 if (AOP_TYPE (left) == AOP_ACC)
7160 emitcode("mov", "a,b");
7161 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7163 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7165 MOVB (aopGet (left, offset, FALSE, FALSE));
7166 MOVA (aopGet (right, offset, FALSE, FALSE));
7167 emitcode ("orl", "a,b");
7168 aopPut (result, "a", offset);
7170 else if (aopGetUsesAcc (left, offset))
7172 MOVA (aopGet (left, offset, FALSE, FALSE));
7173 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7174 aopPut (result, "a", offset);
7178 MOVA (aopGet (right, offset, FALSE, FALSE));
7179 if (IS_AOP_PREG (left))
7181 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7182 aopPut (result, "a", offset);
7186 emitcode ("orl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7194 // left & result in different registers
7195 if (AOP_TYPE (result) == AOP_CRY)
7198 // if(size), result in bit
7199 // if(!size && ifx), conditional oper: if(left | right)
7200 symbol *tlbl = newiTempLabel (NULL);
7201 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7203 emitcode ("setb", "c");
7206 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7207 && AOP_TYPE(left)==AOP_ACC)
7210 emitcode("mov", "a,b");
7211 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7213 else if (AOP_TYPE(left)==AOP_ACC)
7217 bool pushedB = pushB ();
7218 emitcode("mov", "b,a");
7219 MOVA (aopGet (right, offset, FALSE, FALSE));
7220 emitcode("orl", "a,b");
7225 MOVA (aopGet (right, offset, FALSE, FALSE));
7226 emitcode("orl", "a,b");
7229 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7231 MOVB (aopGet (left, offset, FALSE, FALSE));
7232 MOVA (aopGet (right, offset, FALSE, FALSE));
7233 emitcode ("orl", "a,b");
7235 else if (aopGetUsesAcc (left, offset))
7237 MOVA (aopGet (left, offset, FALSE, FALSE));
7238 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7242 MOVA (aopGet (right, offset, FALSE, FALSE));
7243 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7246 emitcode ("jnz", "%05d$", tlbl->key + 100);
7256 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7262 for (; (size--); offset++)
7265 // result = left | right
7266 if (AOP_TYPE (right) == AOP_LIT)
7268 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7272 aopGet (left, offset, FALSE, FALSE),
7276 else if (bytelit == 0x0FF)
7278 /* dummy read of volatile operand */
7279 if (isOperandVolatile (left, FALSE))
7280 MOVA (aopGet (left, offset, FALSE, FALSE));
7281 aopPut (result, "#0xFF", offset);
7285 // faster than result <- left, orl result,right
7286 // and better if result is SFR
7287 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7288 && AOP_TYPE(left)==AOP_ACC)
7291 emitcode("mov", "a,b");
7292 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7294 else if (AOP_TYPE(left)==AOP_ACC)
7298 bool pushedB = pushB ();
7299 emitcode("mov", "b,a");
7300 MOVA (aopGet (right, offset, FALSE, FALSE));
7301 emitcode("orl", "a,b");
7306 MOVA (aopGet (right, offset, FALSE, FALSE));
7307 emitcode("orl", "a,b");
7310 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7312 MOVB (aopGet (left, offset, FALSE, FALSE));
7313 MOVA (aopGet (right, offset, FALSE, FALSE));
7314 emitcode ("orl", "a,b");
7316 else if (aopGetUsesAcc (left, offset))
7318 MOVA (aopGet (left, offset, FALSE, FALSE));
7319 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7323 MOVA (aopGet (right, offset, FALSE, FALSE));
7324 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7326 aopPut (result, "a", offset);
7332 freeAsmop (result, NULL, ic, TRUE);
7333 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7334 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7337 /*-----------------------------------------------------------------*/
7338 /* genXor - code for xclusive or */
7339 /*-----------------------------------------------------------------*/
7341 genXor (iCode * ic, iCode * ifx)
7343 operand *left, *right, *result;
7344 int size, offset = 0;
7345 unsigned long lit = 0L;
7348 D (emitcode (";", "genXor"));
7350 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7351 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7352 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7355 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7357 AOP_TYPE (left), AOP_TYPE (right));
7358 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7360 AOP_SIZE (left), AOP_SIZE (right));
7363 /* if left is a literal & right is not ||
7364 if left needs acc & right does not */
7365 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7366 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7368 operand *tmp = right;
7373 /* if result = right then exchange them */
7374 if (sameRegs (AOP (result), AOP (right)))
7376 operand *tmp = right;
7381 /* if right is bit then exchange them */
7382 if (AOP_TYPE (right) == AOP_CRY &&
7383 AOP_TYPE (left) != AOP_CRY)
7385 operand *tmp = right;
7389 if (AOP_TYPE (right) == AOP_LIT)
7390 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7392 size = AOP_SIZE (result);
7396 if (AOP_TYPE (left) == AOP_CRY)
7398 if (AOP_TYPE (right) == AOP_LIT)
7400 // c = bit & literal;
7403 // lit>>1 != 0 => result = 1
7404 if (AOP_TYPE (result) == AOP_CRY)
7407 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7409 continueIfTrue (ifx);
7412 emitcode ("setb", "c");
7419 // lit == 0, result = left
7420 if (size && sameRegs (AOP (result), AOP (left)))
7422 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7426 // lit == 1, result = not(left)
7427 if (size && sameRegs (AOP (result), AOP (left)))
7429 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7434 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7435 emitcode ("cpl", "c");
7443 symbol *tlbl = newiTempLabel (NULL);
7444 if (AOP_TYPE (right) == AOP_CRY)
7447 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7451 int sizer = AOP_SIZE (right);
7453 // if val>>1 != 0, result = 1
7454 emitcode ("setb", "c");
7457 MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
7459 // test the msb of the lsb
7460 emitcode ("anl", "a,#0xfe");
7461 emitcode ("jnz", "%05d$", tlbl->key + 100);
7465 emitcode ("rrc", "a");
7467 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7468 emitcode ("cpl", "c");
7476 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7477 genIfxJump (ifx, "c", left, right, result);
7481 /* if left is same as result */
7482 if (sameRegs (AOP (result), AOP (left)))
7484 for (; size--; offset++)
7486 if (AOP_TYPE (right) == AOP_LIT)
7488 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7491 /* dummy read of volatile operand */
7492 if (isOperandVolatile (left, FALSE))
7493 MOVA (aopGet (left, offset, FALSE, FALSE));
7497 else if (IS_AOP_PREG (left))
7499 MOVA (aopGet (left, offset, FALSE, TRUE));
7500 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7501 aopPut (result, "a", offset);
7505 emitcode ("xrl", "%s,%s",
7506 aopGet (left, offset, FALSE, TRUE),
7507 aopGet (right, offset, FALSE, FALSE));
7512 if (AOP_TYPE (left) == AOP_ACC)
7515 emitcode("mov", "a,b");
7516 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7518 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7520 MOVB (aopGet (left, offset, FALSE, FALSE));
7521 MOVA (aopGet (right, offset, FALSE, FALSE));
7522 emitcode ("xrl", "a,b");
7523 aopPut (result, "a", offset);
7525 else if (aopGetUsesAcc (left, offset))
7527 MOVA (aopGet (left, offset, FALSE, FALSE));
7528 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7529 aopPut (result, "a", offset);
7533 MOVA (aopGet (right, offset, FALSE, FALSE));
7534 if (IS_AOP_PREG (left))
7536 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7537 aopPut (result, "a", offset);
7540 emitcode ("xrl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7547 // left & result in different registers
7548 if (AOP_TYPE (result) == AOP_CRY)
7551 // if(size), result in bit
7552 // if(!size && ifx), conditional oper: if(left ^ right)
7553 symbol *tlbl = newiTempLabel (NULL);
7554 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7557 emitcode ("setb", "c");
7560 if ((AOP_TYPE (right) == AOP_LIT) &&
7561 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7563 MOVA (aopGet (left, offset, FALSE, FALSE));
7565 else if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7566 && AOP_TYPE(left)==AOP_ACC)
7569 emitcode("mov", "a,b");
7570 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7572 else if (AOP_TYPE(left)==AOP_ACC)
7576 bool pushedB = pushB ();
7577 emitcode("mov", "b,a");
7578 MOVA (aopGet (right, offset, FALSE, FALSE));
7579 emitcode("xrl", "a,b");
7584 MOVA (aopGet (right, offset, FALSE, FALSE));
7585 emitcode("xrl", "a,b");
7588 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7590 MOVB (aopGet (left, offset, FALSE, FALSE));
7591 MOVA (aopGet (right, offset, FALSE, FALSE));
7592 emitcode ("xrl", "a,b");
7594 else if (aopGetUsesAcc (left, offset))
7596 MOVA (aopGet (left, offset, FALSE, FALSE));
7597 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7601 MOVA (aopGet (right, offset, FALSE, FALSE));
7602 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7605 emitcode ("jnz", "%05d$", tlbl->key + 100);
7615 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7619 for (; (size--); offset++)
7622 // result = left ^ right
7623 if (AOP_TYPE (right) == AOP_LIT)
7625 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7629 aopGet (left, offset, FALSE, FALSE),
7634 // faster than result <- left, xrl result,right
7635 // and better if result is SFR
7636 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7637 && AOP_TYPE(left)==AOP_ACC)
7640 emitcode("mov", "a,b");
7641 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7643 else if (AOP_TYPE(left)==AOP_ACC)
7647 bool pushedB = pushB ();
7648 emitcode("mov", "b,a");
7649 MOVA (aopGet (right, offset, FALSE, FALSE));
7650 emitcode("xrl", "a,b");
7655 MOVA (aopGet (right, offset, FALSE, FALSE));
7656 emitcode("xrl", "a,b");
7659 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7661 MOVB (aopGet (left, offset, FALSE, FALSE));
7662 MOVA (aopGet (right, offset, FALSE, FALSE));
7663 emitcode ("xrl", "a,b");
7665 else if (aopGetUsesAcc (left, offset))
7667 MOVA (aopGet (left, offset, FALSE, FALSE));
7668 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7672 MOVA (aopGet (right, offset, FALSE, FALSE));
7673 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7675 aopPut (result, "a", offset);
7681 freeAsmop (result, NULL, ic, TRUE);
7682 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7683 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7686 /*-----------------------------------------------------------------*/
7687 /* genInline - write the inline code out */
7688 /*-----------------------------------------------------------------*/
7690 genInline (iCode * ic)
7692 char *buffer, *bp, *bp1;
7694 D (emitcode (";", "genInline"));
7696 _G.inLine += (!options.asmpeep);
7698 buffer = bp = bp1 = Safe_strdup(IC_INLINE(ic));
7700 /* emit each line as a code */
7711 /* Add \n for labels, not dirs such as c:\mydir */
7712 if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
7726 /* emitcode("",buffer); */
7727 _G.inLine -= (!options.asmpeep);
7730 /*-----------------------------------------------------------------*/
7731 /* genRRC - rotate right with carry */
7732 /*-----------------------------------------------------------------*/
7736 operand *left, *result;
7740 D (emitcode (";", "genRRC"));
7742 /* rotate right with carry */
7743 left = IC_LEFT (ic);
7744 result = IC_RESULT (ic);
7745 aopOp (left, ic, FALSE);
7746 aopOp (result, ic, FALSE);
7748 /* move it to the result */
7749 size = AOP_SIZE (result);
7751 if (size == 1) { /* special case for 1 byte */
7752 l = aopGet (left, offset, FALSE, FALSE);
7754 emitcode ("rr", "a");
7757 /* no need to clear carry, bit7 will be written later */
7760 l = aopGet (left, offset, FALSE, FALSE);
7762 emitcode ("rrc", "a");
7763 if (AOP_SIZE (result) > 1)
7764 aopPut (result, "a", offset--);
7766 /* now we need to put the carry into the
7767 highest order byte of the result */
7768 if (AOP_SIZE (result) > 1)
7770 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7773 emitcode ("mov", "acc.7,c");
7775 aopPut (result, "a", AOP_SIZE (result) - 1);
7776 freeAsmop (result, NULL, ic, TRUE);
7777 freeAsmop (left, NULL, ic, TRUE);
7780 /*-----------------------------------------------------------------*/
7781 /* genRLC - generate code for rotate left with carry */
7782 /*-----------------------------------------------------------------*/
7786 operand *left, *result;
7790 D (emitcode (";", "genRLC"));
7792 /* rotate right with carry */
7793 left = IC_LEFT (ic);
7794 result = IC_RESULT (ic);
7795 aopOp (left, ic, FALSE);
7796 aopOp (result, ic, FALSE);
7798 /* move it to the result */
7799 size = AOP_SIZE (result);
7803 l = aopGet (left, offset, FALSE, FALSE);
7805 if (size == 0) { /* special case for 1 byte */
7809 emitcode("rlc","a"); /* bit0 will be written later */
7810 if (AOP_SIZE (result) > 1)
7812 aopPut (result, "a", offset++);
7817 l = aopGet (left, offset, FALSE, FALSE);
7819 emitcode ("rlc", "a");
7820 if (AOP_SIZE (result) > 1)
7821 aopPut (result, "a", offset++);
7824 /* now we need to put the carry into the
7825 highest order byte of the result */
7826 if (AOP_SIZE (result) > 1)
7828 l = aopGet (result, 0, FALSE, FALSE);
7831 emitcode ("mov", "acc.0,c");
7833 aopPut (result, "a", 0);
7834 freeAsmop (result, NULL, ic, TRUE);
7835 freeAsmop (left, NULL, ic, TRUE);
7838 /*-----------------------------------------------------------------*/
7839 /* genGetHbit - generates code get highest order bit */
7840 /*-----------------------------------------------------------------*/
7842 genGetHbit (iCode * ic)
7844 operand *left, *result;
7846 D (emitcode (";", "genGetHbit"));
7848 left = IC_LEFT (ic);
7849 result = IC_RESULT (ic);
7850 aopOp (left, ic, FALSE);
7851 aopOp (result, ic, FALSE);
7853 /* get the highest order byte into a */
7854 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7855 if (AOP_TYPE (result) == AOP_CRY)
7857 emitcode ("rlc", "a");
7862 emitcode ("rl", "a");
7863 emitcode ("anl", "a,#0x01");
7867 freeAsmop (result, NULL, ic, TRUE);
7868 freeAsmop (left, NULL, ic, TRUE);
7871 /*-----------------------------------------------------------------*/
7872 /* genGetAbit - generates code get a single bit */
7873 /*-----------------------------------------------------------------*/
7875 genGetAbit (iCode * ic)
7877 operand *left, *right, *result;
7880 D (emitcode (";", "genGetAbit"));
7882 left = IC_LEFT (ic);
7883 right = IC_RIGHT (ic);
7884 result = IC_RESULT (ic);
7885 aopOp (left, ic, FALSE);
7886 aopOp (right, ic, FALSE);
7887 aopOp (result, ic, FALSE);
7889 shCount = (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7891 /* get the needed byte into a */
7892 MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7894 if (AOP_TYPE (result) == AOP_CRY)
7897 emitcode ("rlc", "a");
7898 else if ((shCount) == 0)
7899 emitcode ("rrc", "a");
7901 emitcode ("mov", "c,acc[%d]", shCount);
7909 emitcode ("rr", "a");
7912 emitcode ("rr", "a");
7915 emitcode ("anl", "a,#0x01");
7919 emitcode ("mov", "c,acc[%d]", shCount);
7920 emitcode ("clr", "a");
7921 emitcode ("rlc", "a");
7924 emitcode ("swap", "a");
7925 emitcode ("anl", "a,#0x01");
7928 emitcode ("rl", "a");
7931 emitcode ("rl", "a");
7932 emitcode ("anl", "a,#0x01");
7938 freeAsmop (result, NULL, ic, TRUE);
7939 freeAsmop (right, NULL, ic, TRUE);
7940 freeAsmop (left, NULL, ic, TRUE);
7943 /*-----------------------------------------------------------------*/
7944 /* genGetByte - generates code get a single byte */
7945 /*-----------------------------------------------------------------*/
7947 genGetByte (iCode * ic)
7949 operand *left, *right, *result;
7952 D (emitcode (";", "genGetByte"));
7954 left = IC_LEFT (ic);
7955 right = IC_RIGHT (ic);
7956 result = IC_RESULT (ic);
7957 aopOp (left, ic, FALSE);
7958 aopOp (right, ic, FALSE);
7959 aopOp (result, ic, FALSE);
7961 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7963 aopGet (left, offset, FALSE, FALSE),
7966 freeAsmop (result, NULL, ic, TRUE);
7967 freeAsmop (right, NULL, ic, TRUE);
7968 freeAsmop (left, NULL, ic, TRUE);
7971 /*-----------------------------------------------------------------*/
7972 /* genGetWord - generates code get two bytes */
7973 /*-----------------------------------------------------------------*/
7975 genGetWord (iCode * ic)
7977 operand *left, *right, *result;
7980 D (emitcode (";", "genGetWord"));
7982 left = IC_LEFT (ic);
7983 right = IC_RIGHT (ic);
7984 result = IC_RESULT (ic);
7985 aopOp (left, ic, FALSE);
7986 aopOp (right, ic, FALSE);
7987 aopOp (result, ic, FALSE);
7989 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7991 aopGet (left, offset, FALSE, FALSE),
7994 aopGet (left, offset+1, FALSE, FALSE),
7997 freeAsmop (result, NULL, ic, TRUE);
7998 freeAsmop (right, NULL, ic, TRUE);
7999 freeAsmop (left, NULL, ic, TRUE);
8002 /*-----------------------------------------------------------------*/
8003 /* genSwap - generates code to swap nibbles or bytes */
8004 /*-----------------------------------------------------------------*/
8006 genSwap (iCode * ic)
8008 operand *left, *result;
8010 D(emitcode ("; genSwap",""));
8012 left = IC_LEFT (ic);
8013 result = IC_RESULT (ic);
8014 aopOp (left, ic, FALSE);
8015 aopOp (result, ic, FALSE);
8017 switch (AOP_SIZE (left))
8019 case 1: /* swap nibbles in byte */
8020 MOVA (aopGet (left, 0, FALSE, FALSE));
8021 emitcode ("swap", "a");
8022 aopPut (result, "a", 0);
8024 case 2: /* swap bytes in word */
8025 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
8027 MOVA (aopGet (left, 0, FALSE, FALSE));
8028 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8029 aopPut (result, "a", 1);
8031 else if (operandsEqu (left, result))
8034 bool pushedB = FALSE, leftInB = FALSE;
8036 MOVA (aopGet (left, 0, FALSE, FALSE));
8037 if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
8040 emitcode ("mov", "b,a");
8044 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8045 aopPut (result, reg, 1);
8052 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8053 aopPut (result, aopGet (left, 0, FALSE, FALSE), 1);
8057 wassertl(FALSE, "unsupported SWAP operand size");
8060 freeAsmop (result, NULL, ic, TRUE);
8061 freeAsmop (left, NULL, ic, TRUE);
8064 /*-----------------------------------------------------------------*/
8065 /* AccRol - rotate left accumulator by known count */
8066 /*-----------------------------------------------------------------*/
8068 AccRol (int shCount)
8070 shCount &= 0x0007; // shCount : 0..7
8077 emitcode ("rl", "a");
8080 emitcode ("rl", "a");
8081 emitcode ("rl", "a");
8084 emitcode ("swap", "a");
8085 emitcode ("rr", "a");
8088 emitcode ("swap", "a");
8091 emitcode ("swap", "a");
8092 emitcode ("rl", "a");
8095 emitcode ("rr", "a");
8096 emitcode ("rr", "a");
8099 emitcode ("rr", "a");
8104 /*-----------------------------------------------------------------*/
8105 /* AccLsh - left shift accumulator by known count */
8106 /*-----------------------------------------------------------------*/
8108 AccLsh (int shCount)
8113 emitcode ("add", "a,acc");
8114 else if (shCount == 2)
8116 emitcode ("add", "a,acc");
8117 emitcode ("add", "a,acc");
8121 /* rotate left accumulator */
8123 /* and kill the lower order bits */
8124 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
8129 /*-----------------------------------------------------------------*/
8130 /* AccRsh - right shift accumulator by known count */
8131 /*-----------------------------------------------------------------*/
8133 AccRsh (int shCount)
8140 emitcode ("rrc", "a");
8144 /* rotate right accumulator */
8145 AccRol (8 - shCount);
8146 /* and kill the higher order bits */
8147 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8152 /*-----------------------------------------------------------------*/
8153 /* AccSRsh - signed right shift accumulator by known count */
8154 /*-----------------------------------------------------------------*/
8156 AccSRsh (int shCount)
8163 emitcode ("mov", "c,acc.7");
8164 emitcode ("rrc", "a");
8166 else if (shCount == 2)
8168 emitcode ("mov", "c,acc.7");
8169 emitcode ("rrc", "a");
8170 emitcode ("mov", "c,acc.7");
8171 emitcode ("rrc", "a");
8175 tlbl = newiTempLabel (NULL);
8176 /* rotate right accumulator */
8177 AccRol (8 - shCount);
8178 /* and kill the higher order bits */
8179 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8180 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8181 emitcode ("orl", "a,#0x%02x",
8182 (unsigned char) ~SRMask[shCount]);
8188 /*-----------------------------------------------------------------*/
8189 /* shiftR1Left2Result - shift right one byte from left to result */
8190 /*-----------------------------------------------------------------*/
8192 shiftR1Left2Result (operand * left, int offl,
8193 operand * result, int offr,
8194 int shCount, int sign)
8196 MOVA (aopGet (left, offl, FALSE, FALSE));
8197 /* shift right accumulator */
8202 aopPut (result, "a", offr);
8205 /*-----------------------------------------------------------------*/
8206 /* shiftL1Left2Result - shift left one byte from left to result */
8207 /*-----------------------------------------------------------------*/
8209 shiftL1Left2Result (operand * left, int offl,
8210 operand * result, int offr, int shCount)
8213 l = aopGet (left, offl, FALSE, FALSE);
8215 /* shift left accumulator */
8217 aopPut (result, "a", offr);
8220 /*-----------------------------------------------------------------*/
8221 /* movLeft2Result - move byte from left to result */
8222 /*-----------------------------------------------------------------*/
8224 movLeft2Result (operand * left, int offl,
8225 operand * result, int offr, int sign)
8228 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8230 l = aopGet (left, offl, FALSE, FALSE);
8232 if (*l == '@' && (IS_AOP_PREG (result)))
8234 emitcode ("mov", "a,%s", l);
8235 aopPut (result, "a", offr);
8241 aopPut (result, l, offr);
8245 /* MSB sign in acc.7 ! */
8246 if (getDataSize (left) == offl + 1)
8249 aopPut (result, "a", offr);
8256 /*-----------------------------------------------------------------*/
8257 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
8258 /*-----------------------------------------------------------------*/
8262 emitcode ("rrc", "a");
8263 emitcode ("xch", "a,%s", x);
8264 emitcode ("rrc", "a");
8265 emitcode ("xch", "a,%s", x);
8268 /*-----------------------------------------------------------------*/
8269 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
8270 /*-----------------------------------------------------------------*/
8274 emitcode ("xch", "a,%s", x);
8275 emitcode ("rlc", "a");
8276 emitcode ("xch", "a,%s", x);
8277 emitcode ("rlc", "a");
8280 /*-----------------------------------------------------------------*/
8281 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8282 /*-----------------------------------------------------------------*/
8286 emitcode ("xch", "a,%s", x);
8287 emitcode ("add", "a,acc");
8288 emitcode ("xch", "a,%s", x);
8289 emitcode ("rlc", "a");
8292 /*-----------------------------------------------------------------*/
8293 /* AccAXLsh - left shift a:x by known count (0..7) */
8294 /*-----------------------------------------------------------------*/
8296 AccAXLsh (char *x, int shCount)
8311 case 5: // AAAAABBB:CCCCCDDD
8313 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8315 emitcode ("anl", "a,#0x%02x",
8316 SLMask[shCount]); // BBB00000:CCCCCDDD
8318 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8320 AccRol (shCount); // DDDCCCCC:BBB00000
8322 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8324 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8326 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8328 emitcode ("anl", "a,#0x%02x",
8329 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8331 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8333 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8336 case 6: // AAAAAABB:CCCCCCDD
8337 emitcode ("anl", "a,#0x%02x",
8338 SRMask[shCount]); // 000000BB:CCCCCCDD
8339 emitcode ("mov", "c,acc.0"); // c = B
8340 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8342 AccAXRrl1 (x); // BCCCCCCD:D000000B
8343 AccAXRrl1 (x); // BBCCCCCC:DD000000
8345 emitcode("rrc","a");
8346 emitcode("xch","a,%s", x);
8347 emitcode("rrc","a");
8348 emitcode("mov","c,acc.0"); //<< get correct bit
8349 emitcode("xch","a,%s", x);
8351 emitcode("rrc","a");
8352 emitcode("xch","a,%s", x);
8353 emitcode("rrc","a");
8354 emitcode("xch","a,%s", x);
8357 case 7: // a:x <<= 7
8359 emitcode ("anl", "a,#0x%02x",
8360 SRMask[shCount]); // 0000000B:CCCCCCCD
8362 emitcode ("mov", "c,acc.0"); // c = B
8364 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
8366 AccAXRrl1 (x); // BCCCCCCC:D0000000
8374 /*-----------------------------------------------------------------*/
8375 /* AccAXRsh - right shift a:x known count (0..7) */
8376 /*-----------------------------------------------------------------*/
8378 AccAXRsh (char *x, int shCount)
8386 AccAXRrl1 (x); // 0->a:x
8391 AccAXRrl1 (x); // 0->a:x
8394 AccAXRrl1 (x); // 0->a:x
8399 case 5: // AAAAABBB:CCCCCDDD = a:x
8401 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8403 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8405 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8407 emitcode ("anl", "a,#0x%02x",
8408 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8410 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8412 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8414 emitcode ("anl", "a,#0x%02x",
8415 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8417 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8419 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8421 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8424 case 6: // AABBBBBB:CCDDDDDD
8426 emitcode ("mov", "c,acc.7");
8427 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8429 emitcode ("mov", "c,acc.7");
8430 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8432 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8434 emitcode ("anl", "a,#0x%02x",
8435 SRMask[shCount]); // 000000AA:BBBBBBCC
8438 case 7: // ABBBBBBB:CDDDDDDD
8440 emitcode ("mov", "c,acc.7"); // c = A
8442 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8444 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8446 emitcode ("anl", "a,#0x%02x",
8447 SRMask[shCount]); // 0000000A:BBBBBBBC
8455 /*-----------------------------------------------------------------*/
8456 /* AccAXRshS - right shift signed a:x known count (0..7) */
8457 /*-----------------------------------------------------------------*/
8459 AccAXRshS (char *x, int shCount)
8467 emitcode ("mov", "c,acc.7");
8468 AccAXRrl1 (x); // s->a:x
8472 emitcode ("mov", "c,acc.7");
8473 AccAXRrl1 (x); // s->a:x
8475 emitcode ("mov", "c,acc.7");
8476 AccAXRrl1 (x); // s->a:x
8481 case 5: // AAAAABBB:CCCCCDDD = a:x
8483 tlbl = newiTempLabel (NULL);
8484 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8486 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8488 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8490 emitcode ("anl", "a,#0x%02x",
8491 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8493 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8495 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8497 emitcode ("anl", "a,#0x%02x",
8498 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8500 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8502 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8504 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8506 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8507 emitcode ("orl", "a,#0x%02x",
8508 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8511 break; // SSSSAAAA:BBBCCCCC
8513 case 6: // AABBBBBB:CCDDDDDD
8515 tlbl = newiTempLabel (NULL);
8516 emitcode ("mov", "c,acc.7");
8517 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8519 emitcode ("mov", "c,acc.7");
8520 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8522 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8524 emitcode ("anl", "a,#0x%02x",
8525 SRMask[shCount]); // 000000AA:BBBBBBCC
8527 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8528 emitcode ("orl", "a,#0x%02x",
8529 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8533 case 7: // ABBBBBBB:CDDDDDDD
8535 tlbl = newiTempLabel (NULL);
8536 emitcode ("mov", "c,acc.7"); // c = A
8538 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8540 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8542 emitcode ("anl", "a,#0x%02x",
8543 SRMask[shCount]); // 0000000A:BBBBBBBC
8545 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8546 emitcode ("orl", "a,#0x%02x",
8547 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8556 /*-----------------------------------------------------------------*/
8557 /* shiftL2Left2Result - shift left two bytes from left to result */
8558 /*-----------------------------------------------------------------*/
8560 shiftL2Left2Result (operand * left, int offl,
8561 operand * result, int offr, int shCount)
8564 bool pushedB = FALSE;
8567 if (sameRegs (AOP (result), AOP (left)) &&
8568 ((offl + MSB16) == offr))
8570 /* don't crash result[offr] */
8571 MOVA (aopGet (left, offl, FALSE, FALSE));
8572 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8573 usedB = !strncmp(x, "b", 1);
8575 else if (aopGetUsesAcc (result, offr))
8577 movLeft2Result (left, offl, result, offr, 0);
8580 emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8581 MOVA (aopGet (result, offr, FALSE, FALSE));
8582 emitcode ("xch", "a,b");
8587 movLeft2Result (left, offl, result, offr, 0);
8588 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8589 x = aopGet (result, offr, FALSE, FALSE);
8591 /* ax << shCount (x = lsb(result)) */
8592 AccAXLsh (x, shCount);
8595 emitcode ("xch", "a,b");
8596 aopPut (result, "a", offr);
8597 aopPut (result, "b", offr + MSB16);
8602 aopPut (result, "a", offr + MSB16);
8607 /*-----------------------------------------------------------------*/
8608 /* shiftR2Left2Result - shift right two bytes from left to result */
8609 /*-----------------------------------------------------------------*/
8611 shiftR2Left2Result (operand * left, int offl,
8612 operand * result, int offr,
8613 int shCount, int sign)
8616 bool pushedB = FALSE;
8619 if (sameRegs (AOP (result), AOP (left)) &&
8620 ((offl + MSB16) == offr))
8622 /* don't crash result[offr] */
8623 MOVA (aopGet (left, offl, FALSE, FALSE));
8624 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8625 usedB = !strncmp(x, "b", 1);
8627 else if (aopGetUsesAcc (result, offr))
8629 movLeft2Result (left, offl, result, offr, 0);
8632 emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8633 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8638 movLeft2Result (left, offl, result, offr, 0);
8639 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8640 x = aopGet (result, offr, FALSE, FALSE);
8642 /* a:x >> shCount (x = lsb(result)) */
8644 AccAXRshS (x, shCount);
8646 AccAXRsh (x, shCount);
8649 emitcode ("xch", "a,b");
8650 aopPut (result, "a", offr);
8651 emitcode ("xch", "a,b");
8654 if (getDataSize (result) > 1)
8655 aopPut (result, "a", offr + MSB16);
8658 /*-----------------------------------------------------------------*/
8659 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8660 /*-----------------------------------------------------------------*/
8662 shiftLLeftOrResult (operand * left, int offl,
8663 operand * result, int offr, int shCount)
8665 MOVA (aopGet (left, offl, FALSE, FALSE));
8666 /* shift left accumulator */
8668 /* or with result */
8669 if (aopGetUsesAcc (result, offr))
8671 emitcode ("xch", "a,b");
8672 MOVA (aopGet (result, offr, FALSE, FALSE));
8673 emitcode ("orl", "a,b");
8677 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8679 /* back to result */
8680 aopPut (result, "a", offr);
8683 /*-----------------------------------------------------------------*/
8684 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8685 /*-----------------------------------------------------------------*/
8687 shiftRLeftOrResult (operand * left, int offl,
8688 operand * result, int offr, int shCount)
8690 MOVA (aopGet (left, offl, FALSE, FALSE));
8691 /* shift right accumulator */
8693 /* or with result */
8694 if (aopGetUsesAcc(result, offr))
8696 emitcode ("xch", "a,b");
8697 MOVA (aopGet (result, offr, FALSE, FALSE));
8698 emitcode ("orl", "a,b");
8702 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8704 /* back to result */
8705 aopPut (result, "a", offr);
8708 /*-----------------------------------------------------------------*/
8709 /* genlshOne - left shift a one byte quantity by known count */
8710 /*-----------------------------------------------------------------*/
8712 genlshOne (operand * result, operand * left, int shCount)
8714 D (emitcode (";", "genlshOne"));
8716 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8719 /*-----------------------------------------------------------------*/
8720 /* genlshTwo - left shift two bytes by known amount != 0 */
8721 /*-----------------------------------------------------------------*/
8723 genlshTwo (operand * result, operand * left, int shCount)
8727 D (emitcode (";", "genlshTwo"));
8729 size = getDataSize (result);
8731 /* if shCount >= 8 */
8739 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8741 movLeft2Result (left, LSB, result, MSB16, 0);
8743 aopPut (result, zero, LSB);
8746 /* 1 <= shCount <= 7 */
8750 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8752 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8756 /*-----------------------------------------------------------------*/
8757 /* shiftLLong - shift left one long from left to result */
8758 /* offl = LSB or MSB16 */
8759 /*-----------------------------------------------------------------*/
8761 shiftLLong (operand * left, operand * result, int offr)
8764 int size = AOP_SIZE (result);
8766 if (size >= LSB + offr)
8768 l = aopGet (left, LSB, FALSE, FALSE);
8770 emitcode ("add", "a,acc");
8771 if (sameRegs (AOP (left), AOP (result)) &&
8772 size >= MSB16 + offr && offr != LSB)
8773 xch_a_aopGet (left, LSB + offr, FALSE, FALSE);
8775 aopPut (result, "a", LSB + offr);
8778 if (size >= MSB16 + offr)
8780 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8782 l = aopGet (left, MSB16, FALSE, FALSE);
8785 emitcode ("rlc", "a");
8786 if (sameRegs (AOP (left), AOP (result)) &&
8787 size >= MSB24 + offr && offr != LSB)
8788 xch_a_aopGet (left, MSB16 + offr, FALSE, FALSE);
8790 aopPut (result, "a", MSB16 + offr);
8793 if (size >= MSB24 + offr)
8795 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8797 l = aopGet (left, MSB24, FALSE, FALSE);
8800 emitcode ("rlc", "a");
8801 if (sameRegs (AOP (left), AOP (result)) &&
8802 size >= MSB32 + offr && offr != LSB)
8803 xch_a_aopGet (left, MSB24 + offr, FALSE, FALSE);
8805 aopPut (result, "a", MSB24 + offr);
8808 if (size > MSB32 + offr)
8810 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8812 l = aopGet (left, MSB32, FALSE, FALSE);
8815 emitcode ("rlc", "a");
8816 aopPut (result, "a", MSB32 + offr);
8819 aopPut (result, zero, LSB);
8822 /*-----------------------------------------------------------------*/
8823 /* genlshFour - shift four byte by a known amount != 0 */
8824 /*-----------------------------------------------------------------*/
8826 genlshFour (operand * result, operand * left, int shCount)
8830 D (emitcode (";", "genlshFour"));
8832 size = AOP_SIZE (result);
8834 /* if shifting more that 3 bytes */
8839 /* lowest order of left goes to the highest
8840 order of the destination */
8841 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8843 movLeft2Result (left, LSB, result, MSB32, 0);
8844 aopPut (result, zero, LSB);
8845 aopPut (result, zero, MSB16);
8846 aopPut (result, zero, MSB24);
8850 /* more than two bytes */
8851 else if (shCount >= 16)
8853 /* lower order two bytes goes to higher order two bytes */
8855 /* if some more remaining */
8857 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8860 movLeft2Result (left, MSB16, result, MSB32, 0);
8861 movLeft2Result (left, LSB, result, MSB24, 0);
8863 aopPut (result, zero, MSB16);
8864 aopPut (result, zero, LSB);
8868 /* if more than 1 byte */
8869 else if (shCount >= 8)
8871 /* lower order three bytes goes to higher order three bytes */
8876 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8878 movLeft2Result (left, LSB, result, MSB16, 0);
8884 movLeft2Result (left, MSB24, result, MSB32, 0);
8885 movLeft2Result (left, MSB16, result, MSB24, 0);
8886 movLeft2Result (left, LSB, result, MSB16, 0);
8887 aopPut (result, zero, LSB);
8889 else if (shCount == 1)
8890 shiftLLong (left, result, MSB16);
8893 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8894 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8895 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8896 aopPut (result, zero, LSB);
8901 /* 1 <= shCount <= 7 */
8902 else if (shCount <= 2)
8904 shiftLLong (left, result, LSB);
8906 shiftLLong (result, result, LSB);
8908 /* 3 <= shCount <= 7, optimize */
8911 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8912 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8913 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8917 /*-----------------------------------------------------------------*/
8918 /* genLeftShiftLiteral - left shifting by known count */
8919 /*-----------------------------------------------------------------*/
8921 genLeftShiftLiteral (operand * left,
8926 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8929 D (emitcode (";", "genLeftShiftLiteral"));
8931 freeAsmop (right, NULL, ic, TRUE);
8933 aopOp (left, ic, FALSE);
8934 aopOp (result, ic, FALSE);
8936 size = getSize (operandType (result));
8939 emitcode ("; shift left ", "result %d, left %d", size,
8943 /* I suppose that the left size >= result size */
8948 movLeft2Result (left, size, result, size, 0);
8951 else if (shCount >= (size * 8))
8955 aopPut (result, zero, size);
8963 genlshOne (result, left, shCount);
8967 genlshTwo (result, left, shCount);
8971 genlshFour (result, left, shCount);
8974 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8975 "*** ack! mystery literal shift!\n");
8979 freeAsmop (result, NULL, ic, TRUE);
8980 freeAsmop (left, NULL, ic, TRUE);
8983 /*-----------------------------------------------------------------*/
8984 /* genLeftShift - generates code for left shifting */
8985 /*-----------------------------------------------------------------*/
8987 genLeftShift (iCode * ic)
8989 operand *left, *right, *result;
8992 symbol *tlbl, *tlbl1;
8995 D (emitcode (";", "genLeftShift"));
8997 right = IC_RIGHT (ic);
8998 left = IC_LEFT (ic);
8999 result = IC_RESULT (ic);
9001 aopOp (right, ic, FALSE);
9003 /* if the shift count is known then do it
9004 as efficiently as possible */
9005 if (AOP_TYPE (right) == AOP_LIT)
9007 genLeftShiftLiteral (left, right, result, ic);
9011 /* shift count is unknown then we have to form
9012 a loop get the loop count in B : Note: we take
9013 only the lower order byte since shifting
9014 more that 32 bits make no sense anyway, ( the
9015 largest size of an object can be only 32 bits ) */
9018 MOVB (aopGet (right, 0, FALSE, FALSE));
9019 emitcode ("inc", "b");
9020 freeAsmop (right, NULL, ic, TRUE);
9021 aopOp (left, ic, FALSE);
9022 aopOp (result, ic, FALSE);
9024 /* now move the left to the result if they are not the same */
9025 if (!sameRegs (AOP (left), AOP (result)) &&
9026 AOP_SIZE (result) > 1)
9029 size = AOP_SIZE (result);
9033 l = aopGet (left, offset, FALSE, TRUE);
9034 if (*l == '@' && (IS_AOP_PREG (result)))
9037 emitcode ("mov", "a,%s", l);
9038 aopPut (result, "a", offset);
9041 aopPut (result, l, offset);
9046 tlbl = newiTempLabel (NULL);
9047 size = AOP_SIZE (result);
9049 tlbl1 = newiTempLabel (NULL);
9051 /* if it is only one byte then */
9054 symbol *tlbl1 = newiTempLabel (NULL);
9056 l = aopGet (left, 0, FALSE, FALSE);
9058 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9060 emitcode ("add", "a,acc");
9062 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9064 aopPut (result, "a", 0);
9068 reAdjustPreg (AOP (result));
9070 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9072 l = aopGet (result, offset, FALSE, FALSE);
9074 emitcode ("add", "a,acc");
9075 aopPut (result, "a", offset++);
9078 l = aopGet (result, offset, FALSE, FALSE);
9080 emitcode ("rlc", "a");
9081 aopPut (result, "a", offset++);
9083 reAdjustPreg (AOP (result));
9086 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9089 freeAsmop (result, NULL, ic, TRUE);
9090 freeAsmop (left, NULL, ic, TRUE);
9093 /*-----------------------------------------------------------------*/
9094 /* genrshOne - right shift a one byte quantity by known count */
9095 /*-----------------------------------------------------------------*/
9097 genrshOne (operand * result, operand * left,
9098 int shCount, int sign)
9100 D (emitcode (";", "genrshOne"));
9102 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9105 /*-----------------------------------------------------------------*/
9106 /* genrshTwo - right shift two bytes by known amount != 0 */
9107 /*-----------------------------------------------------------------*/
9109 genrshTwo (operand * result, operand * left,
9110 int shCount, int sign)
9112 D (emitcode (";", "genrshTwo"));
9114 /* if shCount >= 8 */
9119 shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
9121 movLeft2Result (left, MSB16, result, LSB, sign);
9122 addSign (result, MSB16, sign);
9125 /* 1 <= shCount <= 7 */
9127 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9130 /*-----------------------------------------------------------------*/
9131 /* shiftRLong - shift right one long from left to result */
9132 /* offl = LSB or MSB16 */
9133 /*-----------------------------------------------------------------*/
9135 shiftRLong (operand * left, int offl,
9136 operand * result, int sign)
9138 bool overlapping = regsInCommon (left, result) || operandsEqu(left, result);
9140 if (overlapping && offl>1)
9142 // we are in big trouble, but this shouldn't happen
9143 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9146 MOVA (aopGet (left, MSB32, FALSE, FALSE));
9153 emitcode ("rlc", "a");
9154 emitcode ("subb", "a,acc");
9155 if (overlapping && sameByte (AOP (left), MSB32, AOP (result), MSB32))
9157 xch_a_aopGet (left, MSB32, FALSE, FALSE);
9161 aopPut (result, "a", MSB32);
9162 MOVA (aopGet (left, MSB32, FALSE, FALSE));
9167 if (aopPutUsesAcc (result, zero, MSB32))
9169 emitcode("xch", "a,b");
9170 aopPut (result, zero, MSB32);
9171 emitcode("xch", "a,b");
9175 aopPut (result, zero, MSB32);
9182 emitcode ("clr", "c");
9186 emitcode ("mov", "c,acc.7");
9189 emitcode ("rrc", "a");
9191 if (overlapping && offl==MSB16 &&
9192 sameByte (AOP (left), MSB24, AOP (result), MSB32-offl))
9194 xch_a_aopGet (left, MSB24, FALSE, FALSE);
9198 aopPut (result, "a", MSB32 - offl);
9199 MOVA (aopGet (left, MSB24, FALSE, FALSE));
9202 emitcode ("rrc", "a");
9203 if (overlapping && offl==MSB16 &&
9204 sameByte (AOP (left), MSB16, AOP (result), MSB24-offl))
9206 xch_a_aopGet (left, MSB16, FALSE, FALSE);
9210 aopPut (result, "a", MSB24 - offl);
9211 MOVA (aopGet (left, MSB16, FALSE, FALSE));
9214 emitcode ("rrc", "a");
9217 aopPut (result, "a", MSB16 - offl);
9222 sameByte (AOP (left), LSB, AOP (result), MSB16-offl))
9224 xch_a_aopGet (left, LSB, FALSE, FALSE);
9228 aopPut (result, "a", MSB16 - offl);
9229 MOVA (aopGet (left, LSB, FALSE, FALSE));
9231 emitcode ("rrc", "a");
9232 aopPut (result, "a", LSB);
9236 /*-----------------------------------------------------------------*/
9237 /* genrshFour - shift four byte by a known amount != 0 */
9238 /*-----------------------------------------------------------------*/
9240 genrshFour (operand * result, operand * left,
9241 int shCount, int sign)
9243 D (emitcode (";", "genrshFour"));
9245 /* if shifting more that 3 bytes */
9250 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9252 movLeft2Result (left, MSB32, result, LSB, sign);
9253 addSign (result, MSB16, sign);
9255 else if (shCount >= 16)
9259 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9262 movLeft2Result (left, MSB24, result, LSB, 0);
9263 movLeft2Result (left, MSB32, result, MSB16, sign);
9265 addSign (result, MSB24, sign);
9267 else if (shCount >= 8)
9272 shiftRLong (left, MSB16, result, sign);
9274 else if (shCount == 0)
9276 movLeft2Result (left, MSB16, result, LSB, 0);
9277 movLeft2Result (left, MSB24, result, MSB16, 0);
9278 movLeft2Result (left, MSB32, result, MSB24, sign);
9279 addSign (result, MSB32, sign);
9283 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9284 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9285 /* the last shift is signed */
9286 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9287 addSign (result, MSB32, sign);
9292 /* 1 <= shCount <= 7 */
9295 shiftRLong (left, LSB, result, sign);
9297 shiftRLong (result, LSB, result, sign);
9301 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9302 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9303 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9308 /*-----------------------------------------------------------------*/
9309 /* genRightShiftLiteral - right shifting by known count */
9310 /*-----------------------------------------------------------------*/
9312 genRightShiftLiteral (operand * left,
9318 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9321 D (emitcode (";", "genRightShiftLiteral"));
9323 freeAsmop (right, NULL, ic, TRUE);
9325 aopOp (left, ic, FALSE);
9326 aopOp (result, ic, FALSE);
9329 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9333 size = getDataSize (left);
9334 /* test the LEFT size !!! */
9336 /* I suppose that the left size >= result size */
9339 size = getDataSize (result);
9341 movLeft2Result (left, size, result, size, 0);
9344 else if (shCount >= (size * 8))
9348 /* get sign in acc.7 */
9349 MOVA (aopGet (left, size - 1, FALSE, FALSE));
9351 addSign (result, LSB, sign);
9358 genrshOne (result, left, shCount, sign);
9362 genrshTwo (result, left, shCount, sign);
9366 genrshFour (result, left, shCount, sign);
9372 freeAsmop (result, NULL, ic, TRUE);
9373 freeAsmop (left, NULL, ic, TRUE);
9376 /*-----------------------------------------------------------------*/
9377 /* genSignedRightShift - right shift of signed number */
9378 /*-----------------------------------------------------------------*/
9380 genSignedRightShift (iCode * ic)
9382 operand *right, *left, *result;
9385 symbol *tlbl, *tlbl1;
9388 D (emitcode (";", "genSignedRightShift"));
9390 /* we do it the hard way put the shift count in b
9391 and loop thru preserving the sign */
9393 right = IC_RIGHT (ic);
9394 left = IC_LEFT (ic);
9395 result = IC_RESULT (ic);
9397 aopOp (right, ic, FALSE);
9400 if (AOP_TYPE (right) == AOP_LIT)
9402 genRightShiftLiteral (left, right, result, ic, 1);
9405 /* shift count is unknown then we have to form
9406 a loop get the loop count in B : Note: we take
9407 only the lower order byte since shifting
9408 more that 32 bits make no sense anyway, ( the
9409 largest size of an object can be only 32 bits ) */
9412 MOVB (aopGet (right, 0, FALSE, FALSE));
9413 emitcode ("inc", "b");
9414 freeAsmop (right, NULL, ic, TRUE);
9415 aopOp (left, ic, FALSE);
9416 aopOp (result, ic, FALSE);
9418 /* now move the left to the result if they are not the
9420 if (!sameRegs (AOP (left), AOP (result)) &&
9421 AOP_SIZE (result) > 1)
9424 size = AOP_SIZE (result);
9428 l = aopGet (left, offset, FALSE, TRUE);
9429 if (*l == '@' && IS_AOP_PREG (result))
9432 emitcode ("mov", "a,%s", l);
9433 aopPut (result, "a", offset);
9436 aopPut (result, l, offset);
9441 /* mov the highest order bit to OVR */
9442 tlbl = newiTempLabel (NULL);
9443 tlbl1 = newiTempLabel (NULL);
9445 size = AOP_SIZE (result);
9447 MOVA (aopGet (left, offset, FALSE, FALSE));
9448 emitcode ("rlc", "a");
9449 emitcode ("mov", "ov,c");
9450 /* if it is only one byte then */
9453 l = aopGet (left, 0, FALSE, FALSE);
9455 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9457 emitcode ("mov", "c,ov");
9458 emitcode ("rrc", "a");
9460 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9462 aopPut (result, "a", 0);
9466 reAdjustPreg (AOP (result));
9467 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9469 emitcode ("mov", "c,ov");
9472 l = aopGet (result, offset, FALSE, FALSE);
9474 emitcode ("rrc", "a");
9475 aopPut (result, "a", offset--);
9477 reAdjustPreg (AOP (result));
9479 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9483 freeAsmop (result, NULL, ic, TRUE);
9484 freeAsmop (left, NULL, ic, TRUE);
9487 /*-----------------------------------------------------------------*/
9488 /* genRightShift - generate code for right shifting */
9489 /*-----------------------------------------------------------------*/
9491 genRightShift (iCode * ic)
9493 operand *right, *left, *result;
9497 symbol *tlbl, *tlbl1;
9500 D (emitcode (";", "genRightShift"));
9502 /* if signed then we do it the hard way preserve the
9503 sign bit moving it inwards */
9504 letype = getSpec (operandType (IC_LEFT (ic)));
9506 if (!SPEC_USIGN (letype))
9508 genSignedRightShift (ic);
9512 /* signed & unsigned types are treated the same : i.e. the
9513 signed is NOT propagated inwards : quoting from the
9514 ANSI - standard : "for E1 >> E2, is equivalent to division
9515 by 2**E2 if unsigned or if it has a non-negative value,
9516 otherwise the result is implementation defined ", MY definition
9517 is that the sign does not get propagated */
9519 right = IC_RIGHT (ic);
9520 left = IC_LEFT (ic);
9521 result = IC_RESULT (ic);
9523 aopOp (right, ic, FALSE);
9525 /* if the shift count is known then do it
9526 as efficiently as possible */
9527 if (AOP_TYPE (right) == AOP_LIT)
9529 genRightShiftLiteral (left, right, result, ic, 0);
9533 /* shift count is unknown then we have to form
9534 a loop get the loop count in B : Note: we take
9535 only the lower order byte since shifting
9536 more that 32 bits make no sense anyway, ( the
9537 largest size of an object can be only 32 bits ) */
9540 MOVB (aopGet (right, 0, FALSE, FALSE));
9541 emitcode ("inc", "b");
9542 freeAsmop (right, NULL, ic, TRUE);
9543 aopOp (left, ic, FALSE);
9544 aopOp (result, ic, FALSE);
9546 /* now move the left to the result if they are not the
9548 if (!sameRegs (AOP (left), AOP (result)) &&
9549 AOP_SIZE (result) > 1)
9551 size = AOP_SIZE (result);
9555 l = aopGet (left, offset, FALSE, TRUE);
9556 if (*l == '@' && IS_AOP_PREG (result))
9559 emitcode ("mov", "a,%s", l);
9560 aopPut (result, "a", offset);
9563 aopPut (result, l, offset);
9568 tlbl = newiTempLabel (NULL);
9569 tlbl1 = newiTempLabel (NULL);
9570 size = AOP_SIZE (result);
9573 /* if it is only one byte then */
9576 l = aopGet (left, 0, FALSE, FALSE);
9578 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9581 emitcode ("rrc", "a");
9583 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9585 aopPut (result, "a", 0);
9589 reAdjustPreg (AOP (result));
9590 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9595 l = aopGet (result, offset, FALSE, FALSE);
9597 emitcode ("rrc", "a");
9598 aopPut (result, "a", offset--);
9600 reAdjustPreg (AOP (result));
9603 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9607 freeAsmop (result, NULL, ic, TRUE);
9608 freeAsmop (left, NULL, ic, TRUE);
9611 /*-----------------------------------------------------------------*/
9612 /* emitPtrByteGet - emits code to get a byte into A through a */
9613 /* pointer register (R0, R1, or DPTR). The */
9614 /* original value of A can be preserved in B. */
9615 /*-----------------------------------------------------------------*/
9617 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9624 emitcode ("mov", "b,a");
9625 emitcode ("mov", "a,@%s", rname);
9630 emitcode ("mov", "b,a");
9631 emitcode ("movx", "a,@%s", rname);
9636 emitcode ("mov", "b,a");
9637 emitcode ("movx", "a,@dptr");
9642 emitcode ("mov", "b,a");
9643 emitcode ("clr", "a");
9644 emitcode ("movc", "a,@a+dptr");
9650 emitcode ("push", "b");
9651 emitcode ("push", "acc");
9653 emitcode ("lcall", "__gptrget");
9655 emitcode ("pop", "b");
9660 /*-----------------------------------------------------------------*/
9661 /* emitPtrByteSet - emits code to set a byte from src through a */
9662 /* pointer register (R0, R1, or DPTR). */
9663 /*-----------------------------------------------------------------*/
9665 emitPtrByteSet (char *rname, int p_type, char *src)
9674 emitcode ("mov", "@%s,a", rname);
9677 emitcode ("mov", "@%s,%s", rname, src);
9682 emitcode ("movx", "@%s,a", rname);
9687 emitcode ("movx", "@dptr,a");
9692 emitcode ("lcall", "__gptrput");
9697 /*-----------------------------------------------------------------*/
9698 /* genUnpackBits - generates code for unpacking bits */
9699 /*-----------------------------------------------------------------*/
9701 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9703 int offset = 0; /* result byte offset */
9704 int rsize; /* result size */
9705 int rlen = 0; /* remaining bitfield length */
9706 sym_link *etype; /* bitfield type information */
9707 int blen; /* bitfield length */
9708 int bstr; /* bitfield starting bit within byte */
9711 D(emitcode ("; genUnpackBits",""));
9713 etype = getSpec (operandType (result));
9714 rsize = getSize (operandType (result));
9715 blen = SPEC_BLEN (etype);
9716 bstr = SPEC_BSTR (etype);
9718 if (ifx && blen <= 8)
9720 emitPtrByteGet (rname, ptype, FALSE);
9723 SNPRINTF (buffer, sizeof(buffer),
9725 genIfxJump (ifx, buffer, NULL, NULL, NULL);
9730 emitcode ("anl", "a,#0x%02x",
9731 (((unsigned char) -1) >> (8 - blen)) << bstr);
9732 genIfxJump (ifx, "a", NULL, NULL, NULL);
9738 /* If the bitfield length is less than a byte */
9741 emitPtrByteGet (rname, ptype, FALSE);
9743 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9744 if (!SPEC_USIGN (etype))
9746 /* signed bitfield */
9747 symbol *tlbl = newiTempLabel (NULL);
9749 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9750 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9753 aopPut (result, "a", offset++);
9757 /* Bit field did not fit in a byte. Copy all
9758 but the partial byte at the end. */
9759 for (rlen=blen;rlen>=8;rlen-=8)
9761 emitPtrByteGet (rname, ptype, FALSE);
9762 aopPut (result, "a", offset++);
9764 emitcode ("inc", "%s", rname);
9767 /* Handle the partial byte at the end */
9770 emitPtrByteGet (rname, ptype, FALSE);
9771 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9772 if (!SPEC_USIGN (etype))
9774 /* signed bitfield */
9775 symbol *tlbl = newiTempLabel (NULL);
9777 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9778 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9781 aopPut (result, "a", offset++);
9789 if (SPEC_USIGN (etype))
9793 /* signed bitfield: sign extension with 0x00 or 0xff */
9794 emitcode ("rlc", "a");
9795 emitcode ("subb", "a,acc");
9801 aopPut (result, source, offset++);
9806 /*-----------------------------------------------------------------*/
9807 /* genDataPointerGet - generates code when ptr offset is known */
9808 /*-----------------------------------------------------------------*/
9810 genDataPointerGet (operand * left,
9816 int size, offset = 0;
9818 D (emitcode (";", "genDataPointerGet"));
9820 aopOp (result, ic, TRUE);
9822 /* get the string representation of the name */
9823 l = aopGet (left, 0, FALSE, TRUE);
9825 size = AOP_SIZE (result);
9830 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
9834 SNPRINTF (buffer, sizeof(buffer), "%s", l);
9836 aopPut (result, buffer, offset++);
9839 freeAsmop (result, NULL, ic, TRUE);
9840 freeAsmop (left, NULL, ic, TRUE);
9843 /*-----------------------------------------------------------------*/
9844 /* genNearPointerGet - emitcode for near pointer fetch */
9845 /*-----------------------------------------------------------------*/
9847 genNearPointerGet (operand * left,
9856 sym_link *rtype, *retype;
9857 sym_link *ltype = operandType (left);
9860 D (emitcode (";", "genNearPointerGet"));
9862 rtype = operandType (result);
9863 retype = getSpec (rtype);
9865 aopOp (left, ic, FALSE);
9867 /* if left is rematerialisable and
9868 result is not bitfield variable type and
9869 the left is pointer to data space i.e
9870 lower 128 bytes of space */
9871 if (AOP_TYPE (left) == AOP_IMMD &&
9872 !IS_BITFIELD (retype) &&
9873 DCL_TYPE (ltype) == POINTER)
9875 genDataPointerGet (left, result, ic);
9879 /* if the value is already in a pointer register
9880 then don't need anything more */
9881 if (!AOP_INPREG (AOP (left)))
9883 if (IS_AOP_PREG (left))
9885 // Aha, it is a pointer, just in disguise.
9886 rname = aopGet (left, 0, FALSE, FALSE);
9889 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9890 __FILE__, __LINE__);
9895 emitcode ("mov", "a%s,%s", rname + 1, rname);
9896 rname++; // skip the '@'.
9901 /* otherwise get a free pointer register */
9903 preg = getFreePtr (ic, &aop, FALSE);
9904 emitcode ("mov", "%s,%s",
9906 aopGet (left, 0, FALSE, TRUE));
9911 rname = aopGet (left, 0, FALSE, FALSE);
9913 //aopOp (result, ic, FALSE);
9914 aopOp (result, ic, result?TRUE:FALSE);
9916 /* if bitfield then unpack the bits */
9917 if (IS_BITFIELD (retype))
9918 genUnpackBits (result, rname, POINTER, ifx);
9921 /* we have can just get the values */
9922 int size = AOP_SIZE (result);
9927 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9930 emitcode ("mov", "a,@%s", rname);
9932 aopPut (result, "a", offset);
9936 SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
9937 aopPut (result, buffer, offset);
9941 emitcode ("inc", "%s", rname);
9945 /* now some housekeeping stuff */
9946 if (aop) /* we had to allocate for this iCode */
9948 if (pi) { /* post increment present */
9949 aopPut (left, rname, 0);
9951 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9955 /* we did not allocate which means left
9956 already in a pointer register, then
9957 if size > 0 && this could be used again
9958 we have to point it back to where it
9960 if ((AOP_SIZE (result) > 1 &&
9961 !OP_SYMBOL (left)->remat &&
9962 (OP_SYMBOL (left)->liveTo > ic->seq ||
9966 int size = AOP_SIZE (result) - 1;
9968 emitcode ("dec", "%s", rname);
9972 if (ifx && !ifx->generated)
9974 genIfxJump (ifx, "a", left, NULL, result);
9978 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9979 freeAsmop (left, NULL, ic, TRUE);
9980 if (pi) pi->generated = 1;
9983 /*-----------------------------------------------------------------*/
9984 /* genPagedPointerGet - emitcode for paged pointer fetch */
9985 /*-----------------------------------------------------------------*/
9987 genPagedPointerGet (operand * left,
9996 sym_link *rtype, *retype;
9998 D (emitcode (";", "genPagedPointerGet"));
10000 rtype = operandType (result);
10001 retype = getSpec (rtype);
10003 aopOp (left, ic, FALSE);
10005 /* if the value is already in a pointer register
10006 then don't need anything more */
10007 if (!AOP_INPREG (AOP (left)))
10009 /* otherwise get a free pointer register */
10010 aop = newAsmop (0);
10011 preg = getFreePtr (ic, &aop, FALSE);
10012 emitcode ("mov", "%s,%s",
10014 aopGet (left, 0, FALSE, TRUE));
10015 rname = preg->name;
10018 rname = aopGet (left, 0, FALSE, FALSE);
10020 aopOp (result, ic, FALSE);
10022 /* if bitfield then unpack the bits */
10023 if (IS_BITFIELD (retype))
10024 genUnpackBits (result, rname, PPOINTER, ifx);
10027 /* we have can just get the values */
10028 int size = AOP_SIZE (result);
10034 emitcode ("movx", "a,@%s", rname);
10036 aopPut (result, "a", offset);
10041 emitcode ("inc", "%s", rname);
10045 /* now some housekeeping stuff */
10046 if (aop) /* we had to allocate for this iCode */
10049 aopPut (left, rname, 0);
10050 freeAsmop (NULL, aop, ic, TRUE);
10054 /* we did not allocate which means left
10055 already in a pointer register, then
10056 if size > 0 && this could be used again
10057 we have to point it back to where it
10059 if ((AOP_SIZE (result) > 1 &&
10060 !OP_SYMBOL (left)->remat &&
10061 (OP_SYMBOL (left)->liveTo > ic->seq ||
10065 int size = AOP_SIZE (result) - 1;
10067 emitcode ("dec", "%s", rname);
10071 if (ifx && !ifx->generated)
10073 genIfxJump (ifx, "a", left, NULL, result);
10077 freeAsmop (result, NULL, ic, TRUE);
10078 freeAsmop (left, NULL, ic, TRUE);
10079 if (pi) pi->generated = 1;
10082 /*--------------------------------------------------------------------*/
10083 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
10084 /*--------------------------------------------------------------------*/
10086 loadDptrFromOperand (operand *op, bool loadBToo)
10088 if (AOP_TYPE (op) != AOP_STR)
10090 /* if this is rematerializable */
10091 if (AOP_TYPE (op) == AOP_IMMD)
10093 emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
10096 if (AOP(op)->aopu.aop_immd.from_cast_remat)
10097 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
10100 wassertl(FALSE, "need pointerCode");
10101 emitcode ("", "; mov b,???");
10102 /* genPointerGet and genPointerSet originally did different
10103 ** things for this case. Both seem wrong.
10104 ** from genPointerGet:
10105 ** emitcode ("mov", "b,#%d", pointerCode (retype));
10106 ** from genPointerSet:
10107 ** emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
10112 else if (AOP_TYPE (op) == AOP_DPTR)
10116 MOVA (aopGet (op, 0, FALSE, FALSE));
10117 emitcode ("push", "acc");
10118 MOVA (aopGet (op, 1, FALSE, FALSE));
10119 emitcode ("push", "acc");
10120 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10121 emitcode ("pop", "dph");
10122 emitcode ("pop", "dpl");
10126 MOVA (aopGet (op, 0, FALSE, FALSE));
10127 emitcode ("push", "acc");
10128 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10129 emitcode ("pop", "dpl");
10133 { /* we need to get it byte by byte */
10134 emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
10135 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10137 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10142 /*-----------------------------------------------------------------*/
10143 /* genFarPointerGet - get value from far space */
10144 /*-----------------------------------------------------------------*/
10146 genFarPointerGet (operand * left,
10147 operand * result, iCode * ic, iCode * pi, iCode * ifx)
10150 sym_link *retype = getSpec (operandType (result));
10152 D (emitcode (";", "genFarPointerGet"));
10154 aopOp (left, ic, FALSE);
10155 loadDptrFromOperand (left, FALSE);
10157 /* so dptr now contains the address */
10158 aopOp (result, ic, FALSE);
10160 /* if bit then unpack */
10161 if (IS_BITFIELD (retype))
10162 genUnpackBits (result, "dptr", FPOINTER, ifx);
10165 size = AOP_SIZE (result);
10170 emitcode ("movx", "a,@dptr");
10172 aopPut (result, "a", offset++);
10174 emitcode ("inc", "dptr");
10178 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10180 aopPut (left, "dpl", 0);
10181 aopPut (left, "dph", 1);
10185 if (ifx && !ifx->generated)
10187 genIfxJump (ifx, "a", left, NULL, result);
10190 freeAsmop (result, NULL, ic, TRUE);
10191 freeAsmop (left, NULL, ic, TRUE);
10194 /*-----------------------------------------------------------------*/
10195 /* genCodePointerGet - get value from code space */
10196 /*-----------------------------------------------------------------*/
10198 genCodePointerGet (operand * left,
10199 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10202 sym_link *retype = getSpec (operandType (result));
10204 D (emitcode (";", "genCodePointerGet"));
10206 aopOp (left, ic, FALSE);
10207 loadDptrFromOperand (left, FALSE);
10209 /* so dptr now contains the address */
10210 aopOp (result, ic, FALSE);
10212 /* if bit then unpack */
10213 if (IS_BITFIELD (retype))
10214 genUnpackBits (result, "dptr", CPOINTER, ifx);
10217 size = AOP_SIZE (result);
10222 emitcode ("clr", "a");
10223 emitcode ("movc", "a,@a+dptr");
10225 aopPut (result, "a", offset++);
10227 emitcode ("inc", "dptr");
10231 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10233 aopPut (left, "dpl", 0);
10234 aopPut (left, "dph", 1);
10238 if (ifx && !ifx->generated)
10240 genIfxJump (ifx, "a", left, NULL, result);
10243 freeAsmop (result, NULL, ic, TRUE);
10244 freeAsmop (left, NULL, ic, TRUE);
10247 /*-----------------------------------------------------------------*/
10248 /* genGenPointerGet - get value from generic pointer space */
10249 /*-----------------------------------------------------------------*/
10251 genGenPointerGet (operand * left,
10252 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10255 sym_link *retype = getSpec (operandType (result));
10257 D (emitcode (";", "genGenPointerGet"));
10259 aopOp (left, ic, FALSE);
10260 loadDptrFromOperand (left, TRUE);
10262 /* so dptr now contains the address */
10263 aopOp (result, ic, FALSE);
10265 /* if bit then unpack */
10266 if (IS_BITFIELD (retype))
10268 genUnpackBits (result, "dptr", GPOINTER, ifx);
10272 size = AOP_SIZE (result);
10277 emitcode ("lcall", "__gptrget");
10279 aopPut (result, "a", offset++);
10281 emitcode ("inc", "dptr");
10285 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10287 aopPut (left, "dpl", 0);
10288 aopPut (left, "dph", 1);
10292 if (ifx && !ifx->generated)
10294 genIfxJump (ifx, "a", left, NULL, result);
10297 freeAsmop (result, NULL, ic, TRUE);
10298 freeAsmop (left, NULL, ic, TRUE);
10301 /*-----------------------------------------------------------------*/
10302 /* genPointerGet - generate code for pointer get */
10303 /*-----------------------------------------------------------------*/
10305 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
10307 operand *left, *result;
10308 sym_link *type, *etype;
10311 D (emitcode (";", "genPointerGet"));
10313 left = IC_LEFT (ic);
10314 result = IC_RESULT (ic);
10316 if (getSize (operandType (result))>1)
10319 /* depending on the type of pointer we need to
10320 move it to the correct pointer register */
10321 type = operandType (left);
10322 etype = getSpec (type);
10323 /* if left is of type of pointer then it is simple */
10324 if (IS_PTR (type) && !IS_FUNC (type->next))
10325 p_type = DCL_TYPE (type);
10328 /* we have to go by the storage class */
10329 p_type = PTR_TYPE (SPEC_OCLS (etype));
10332 /* special case when cast remat */
10333 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10334 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10336 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10337 type = operandType (left);
10338 p_type = DCL_TYPE (type);
10340 /* now that we have the pointer type we assign
10341 the pointer values */
10347 genNearPointerGet (left, result, ic, pi, ifx);
10351 genPagedPointerGet (left, result, ic, pi, ifx);
10355 genFarPointerGet (left, result, ic, pi, ifx);
10359 genCodePointerGet (left, result, ic, pi, ifx);
10363 genGenPointerGet (left, result, ic, pi, ifx);
10369 /*-----------------------------------------------------------------*/
10370 /* genPackBits - generates code for packed bit storage */
10371 /*-----------------------------------------------------------------*/
10373 genPackBits (sym_link * etype,
10375 char *rname, int p_type)
10377 int offset = 0; /* source byte offset */
10378 int rlen = 0; /* remaining bitfield length */
10379 int blen; /* bitfield length */
10380 int bstr; /* bitfield starting bit within byte */
10381 int litval; /* source literal value (if AOP_LIT) */
10382 unsigned char mask; /* bitmask within current byte */
10384 D(emitcode ("; genPackBits",""));
10386 blen = SPEC_BLEN (etype);
10387 bstr = SPEC_BSTR (etype);
10389 /* If the bitfield length is less than a byte */
10392 mask = ((unsigned char) (0xFF << (blen + bstr)) |
10393 (unsigned char) (0xFF >> (8 - bstr)));
10395 if (AOP_TYPE (right) == AOP_LIT)
10397 /* Case with a bitfield length <8 and literal source
10399 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10401 litval &= (~mask) & 0xff;
10402 emitPtrByteGet (rname, p_type, FALSE);
10403 if ((mask|litval)!=0xff)
10404 emitcode ("anl","a,#0x%02x", mask);
10406 emitcode ("orl","a,#0x%02x", litval);
10410 if ((blen==1) && (p_type!=GPOINTER))
10412 /* Case with a bitfield length == 1 and no generic pointer
10414 if (AOP_TYPE (right) == AOP_CRY)
10415 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10418 MOVA (aopGet (right, 0, FALSE, FALSE));
10419 emitcode ("rrc","a");
10421 emitPtrByteGet (rname, p_type, FALSE);
10422 emitcode ("mov","acc.%d,c",bstr);
10427 /* Case with a bitfield length < 8 and arbitrary source
10429 MOVA (aopGet (right, 0, FALSE, FALSE));
10430 /* shift and mask source value */
10432 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10434 pushedB = pushB ();
10435 /* transfer A to B and get next byte */
10436 emitPtrByteGet (rname, p_type, TRUE);
10438 emitcode ("anl", "a,#0x%02x", mask);
10439 emitcode ("orl", "a,b");
10440 if (p_type == GPOINTER)
10441 emitcode ("pop", "b");
10447 emitPtrByteSet (rname, p_type, "a");
10451 /* Bit length is greater than 7 bits. In this case, copy */
10452 /* all except the partial byte at the end */
10453 for (rlen=blen;rlen>=8;rlen-=8)
10455 emitPtrByteSet (rname, p_type,
10456 aopGet (right, offset++, FALSE, TRUE) );
10458 emitcode ("inc", "%s", rname);
10461 /* If there was a partial byte at the end */
10464 mask = (((unsigned char) -1 << rlen) & 0xff);
10466 if (AOP_TYPE (right) == AOP_LIT)
10468 /* Case with partial byte and literal source
10470 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10471 litval >>= (blen-rlen);
10472 litval &= (~mask) & 0xff;
10473 emitPtrByteGet (rname, p_type, FALSE);
10474 if ((mask|litval)!=0xff)
10475 emitcode ("anl","a,#0x%02x", mask);
10477 emitcode ("orl","a,#0x%02x", litval);
10482 /* Case with partial byte and arbitrary source
10484 MOVA (aopGet (right, offset++, FALSE, FALSE));
10485 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10487 pushedB = pushB ();
10488 /* transfer A to B and get next byte */
10489 emitPtrByteGet (rname, p_type, TRUE);
10491 emitcode ("anl", "a,#0x%02x", mask);
10492 emitcode ("orl", "a,b");
10493 if (p_type == GPOINTER)
10494 emitcode ("pop", "b");
10498 emitPtrByteSet (rname, p_type, "a");
10503 /*-----------------------------------------------------------------*/
10504 /* genDataPointerSet - remat pointer to data space */
10505 /*-----------------------------------------------------------------*/
10507 genDataPointerSet (operand * right,
10511 int size, offset = 0;
10512 char *l, buffer[256];
10514 D (emitcode (";", "genDataPointerSet"));
10516 aopOp (right, ic, FALSE);
10518 l = aopGet (result, 0, FALSE, TRUE);
10520 size = AOP_SIZE (right);
10524 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
10526 SNPRINTF (buffer, sizeof(buffer), "%s", l);
10527 emitcode ("mov", "%s,%s", buffer,
10528 aopGet (right, offset++, FALSE, FALSE));
10531 freeAsmop (result, NULL, ic, TRUE);
10532 freeAsmop (right, NULL, ic, TRUE);
10535 /*-----------------------------------------------------------------*/
10536 /* genNearPointerSet - emitcode for near pointer put */
10537 /*-----------------------------------------------------------------*/
10539 genNearPointerSet (operand * right,
10547 sym_link *retype, *letype;
10548 sym_link *ptype = operandType (result);
10550 D (emitcode (";", "genNearPointerSet"));
10552 retype = getSpec (operandType (right));
10553 letype = getSpec (ptype);
10555 aopOp (result, ic, FALSE);
10557 /* if the result is rematerializable &
10558 in data space & not a bit variable */
10559 if (AOP_TYPE (result) == AOP_IMMD &&
10560 DCL_TYPE (ptype) == POINTER &&
10561 !IS_BITVAR (retype) &&
10562 !IS_BITVAR (letype))
10564 genDataPointerSet (right, result, ic);
10568 /* if the value is already in a pointer register
10569 then don't need anything more */
10570 if (!AOP_INPREG (AOP (result)))
10573 //AOP_TYPE (result) == AOP_STK
10574 IS_AOP_PREG(result)
10577 // Aha, it is a pointer, just in disguise.
10578 rname = aopGet (result, 0, FALSE, FALSE);
10581 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10582 __FILE__, __LINE__);
10587 emitcode ("mov", "a%s,%s", rname + 1, rname);
10588 rname++; // skip the '@'.
10593 /* otherwise get a free pointer register */
10594 aop = newAsmop (0);
10595 preg = getFreePtr (ic, &aop, FALSE);
10596 emitcode ("mov", "%s,%s",
10598 aopGet (result, 0, FALSE, TRUE));
10599 rname = preg->name;
10604 rname = aopGet (result, 0, FALSE, FALSE);
10607 aopOp (right, ic, FALSE);
10609 /* if bitfield then unpack the bits */
10610 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10611 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10614 /* we can just get the values */
10615 int size = AOP_SIZE (right);
10620 l = aopGet (right, offset, FALSE, TRUE);
10621 if ((*l == '@') || (strcmp (l, "acc") == 0))
10624 emitcode ("mov", "@%s,a", rname);
10627 emitcode ("mov", "@%s,%s", rname, l);
10629 emitcode ("inc", "%s", rname);
10634 /* now some housekeeping stuff */
10635 if (aop) /* we had to allocate for this iCode */
10638 aopPut (result, rname, 0);
10639 freeAsmop (NULL, aop, ic, TRUE);
10643 /* we did not allocate which means left
10644 already in a pointer register, then
10645 if size > 0 && this could be used again
10646 we have to point it back to where it
10648 if ((AOP_SIZE (right) > 1 &&
10649 !OP_SYMBOL (result)->remat &&
10650 (OP_SYMBOL (result)->liveTo > ic->seq ||
10654 int size = AOP_SIZE (right) - 1;
10656 emitcode ("dec", "%s", rname);
10661 if (pi) pi->generated = 1;
10662 freeAsmop (result, NULL, ic, TRUE);
10663 freeAsmop (right, NULL, ic, TRUE);
10666 /*-----------------------------------------------------------------*/
10667 /* genPagedPointerSet - emitcode for Paged pointer put */
10668 /*-----------------------------------------------------------------*/
10670 genPagedPointerSet (operand * right,
10678 sym_link *retype, *letype;
10680 D (emitcode (";", "genPagedPointerSet"));
10682 retype = getSpec (operandType (right));
10683 letype = getSpec (operandType (result));
10685 aopOp (result, ic, FALSE);
10687 /* if the value is already in a pointer register
10688 then don't need anything more */
10689 if (!AOP_INPREG (AOP (result)))
10691 /* otherwise get a free pointer register */
10692 aop = newAsmop (0);
10693 preg = getFreePtr (ic, &aop, FALSE);
10694 emitcode ("mov", "%s,%s",
10696 aopGet (result, 0, FALSE, TRUE));
10697 rname = preg->name;
10700 rname = aopGet (result, 0, FALSE, FALSE);
10702 aopOp (right, ic, FALSE);
10704 /* if bitfield then unpack the bits */
10705 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10706 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10709 /* we have can just get the values */
10710 int size = AOP_SIZE (right);
10715 l = aopGet (right, offset, FALSE, TRUE);
10717 emitcode ("movx", "@%s,a", rname);
10720 emitcode ("inc", "%s", rname);
10726 /* now some housekeeping stuff */
10727 if (aop) /* we had to allocate for this iCode */
10730 aopPut (result, rname, 0);
10731 freeAsmop (NULL, aop, ic, TRUE);
10735 /* we did not allocate which means left
10736 already in a pointer register, then
10737 if size > 0 && this could be used again
10738 we have to point it back to where it
10740 if (AOP_SIZE (right) > 1 &&
10741 !OP_SYMBOL (result)->remat &&
10742 (OP_SYMBOL (result)->liveTo > ic->seq ||
10745 int size = AOP_SIZE (right) - 1;
10747 emitcode ("dec", "%s", rname);
10752 if (pi) pi->generated = 1;
10753 freeAsmop (result, NULL, ic, TRUE);
10754 freeAsmop (right, NULL, ic, TRUE);
10757 /*-----------------------------------------------------------------*/
10758 /* genFarPointerSet - set value from far space */
10759 /*-----------------------------------------------------------------*/
10761 genFarPointerSet (operand * right,
10762 operand * result, iCode * ic, iCode * pi)
10765 sym_link *retype = getSpec (operandType (right));
10766 sym_link *letype = getSpec (operandType (result));
10768 D(emitcode ("; genFarPointerSet",""));
10770 aopOp (result, ic, FALSE);
10771 loadDptrFromOperand (result, FALSE);
10773 /* so dptr now contains the address */
10774 aopOp (right, ic, FALSE);
10776 /* if bit then unpack */
10777 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10778 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10781 size = AOP_SIZE (right);
10786 char *l = aopGet (right, offset++, FALSE, FALSE);
10788 emitcode ("movx", "@dptr,a");
10790 emitcode ("inc", "dptr");
10793 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10794 aopPut (result, "dpl", 0);
10795 aopPut (result, "dph", 1);
10798 freeAsmop (result, NULL, ic, TRUE);
10799 freeAsmop (right, NULL, ic, TRUE);
10802 /*-----------------------------------------------------------------*/
10803 /* genGenPointerSet - set value from generic pointer space */
10804 /*-----------------------------------------------------------------*/
10806 genGenPointerSet (operand * right,
10807 operand * result, iCode * ic, iCode * pi)
10810 sym_link *retype = getSpec (operandType (right));
10811 sym_link *letype = getSpec (operandType (result));
10813 D (emitcode (";", "genGenPointerSet"));
10815 aopOp (result, ic, FALSE);
10816 loadDptrFromOperand (result, TRUE);
10818 /* so dptr now contains the address */
10819 aopOp (right, ic, FALSE);
10821 /* if bit then unpack */
10822 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10824 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10828 size = AOP_SIZE (right);
10833 char *l = aopGet (right, offset++, FALSE, FALSE);
10835 emitcode ("lcall", "__gptrput");
10837 emitcode ("inc", "dptr");
10841 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10842 aopPut (result, "dpl", 0);
10843 aopPut (result, "dph", 1);
10846 freeAsmop (result, NULL, ic, TRUE);
10847 freeAsmop (right, NULL, ic, TRUE);
10850 /*-----------------------------------------------------------------*/
10851 /* genPointerSet - stores the value into a pointer location */
10852 /*-----------------------------------------------------------------*/
10854 genPointerSet (iCode * ic, iCode *pi)
10856 operand *right, *result;
10857 sym_link *type, *etype;
10860 D (emitcode (";", "genPointerSet"));
10862 right = IC_RIGHT (ic);
10863 result = IC_RESULT (ic);
10865 /* depending on the type of pointer we need to
10866 move it to the correct pointer register */
10867 type = operandType (result);
10868 etype = getSpec (type);
10869 /* if left is of type of pointer then it is simple */
10870 if (IS_PTR (type) && !IS_FUNC (type->next))
10872 p_type = DCL_TYPE (type);
10876 /* we have to go by the storage class */
10877 p_type = PTR_TYPE (SPEC_OCLS (etype));
10880 /* special case when cast remat */
10881 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10882 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10883 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10884 type = operandType (result);
10885 p_type = DCL_TYPE (type);
10888 /* now that we have the pointer type we assign
10889 the pointer values */
10895 genNearPointerSet (right, result, ic, pi);
10899 genPagedPointerSet (right, result, ic, pi);
10903 genFarPointerSet (right, result, ic, pi);
10907 genGenPointerSet (right, result, ic, pi);
10911 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10912 "genPointerSet: illegal pointer type");
10916 /*-----------------------------------------------------------------*/
10917 /* genIfx - generate code for Ifx statement */
10918 /*-----------------------------------------------------------------*/
10920 genIfx (iCode * ic, iCode * popIc)
10922 operand *cond = IC_COND (ic);
10926 D (emitcode (";", "genIfx"));
10928 aopOp (cond, ic, FALSE);
10930 /* get the value into acc */
10931 if (AOP_TYPE (cond) != AOP_CRY)
10938 if (AOP(cond)->aopu.aop_dir)
10939 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10942 /* the result is now in the accumulator or a directly addressable bit */
10943 freeAsmop (cond, NULL, ic, TRUE);
10945 /* if there was something to be popped then do it */
10949 /* if the condition is a bit variable */
10951 genIfxJump(ic, dup, NULL, NULL, NULL);
10952 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10953 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10954 else if (isbit && !IS_ITEMP (cond))
10955 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10957 genIfxJump (ic, "a", NULL, NULL, NULL);
10962 /*-----------------------------------------------------------------*/
10963 /* genAddrOf - generates code for address of */
10964 /*-----------------------------------------------------------------*/
10966 genAddrOf (iCode * ic)
10968 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10971 D (emitcode (";", "genAddrOf"));
10973 aopOp (IC_RESULT (ic), ic, FALSE);
10975 /* if the operand is on the stack then we
10976 need to get the stack offset of this
10980 /* if it has an offset then we need to compute it */
10983 int stack_offset = ((sym->stack < 0) ?
10984 ((char) (sym->stack - _G.nRegsSaved)) :
10985 ((char) sym->stack)) & 0xff;
10986 if ((abs(stack_offset) == 1) &&
10987 !AOP_NEEDSACC(IC_RESULT (ic)) &&
10988 !isOperandVolatile (IC_RESULT (ic), FALSE))
10990 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
10991 if (stack_offset > 0)
10992 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
10994 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
10998 emitcode ("mov", "a,%s", SYM_BP (sym));
10999 emitcode ("add", "a,#0x%02x", stack_offset & 0xff);
11000 aopPut (IC_RESULT (ic), "a", 0);
11005 /* we can just move _bp */
11006 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
11008 /* fill the result with zero */
11009 size = AOP_SIZE (IC_RESULT (ic)) - 1;
11014 aopPut (IC_RESULT (ic), zero, offset++);
11019 /* object not on stack then we need the name */
11020 size = AOP_SIZE (IC_RESULT (ic));
11025 char s[SDCC_NAME_MAX];
11027 sprintf (s, "#(%s >> %d)",
11031 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11032 aopPut (IC_RESULT (ic), s, offset++);
11036 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11040 /*-----------------------------------------------------------------*/
11041 /* genFarFarAssign - assignment when both are in far space */
11042 /*-----------------------------------------------------------------*/
11044 genFarFarAssign (operand * result, operand * right, iCode * ic)
11046 int size = AOP_SIZE (right);
11050 D (emitcode (";", "genFarFarAssign"));
11052 /* first push the right side on to the stack */
11055 l = aopGet (right, offset++, FALSE, FALSE);
11057 emitcode ("push", "acc");
11060 freeAsmop (right, NULL, ic, FALSE);
11061 /* now assign DPTR to result */
11062 aopOp (result, ic, FALSE);
11063 size = AOP_SIZE (result);
11066 emitcode ("pop", "acc");
11067 aopPut (result, "a", --offset);
11069 freeAsmop (result, NULL, ic, FALSE);
11072 /*-----------------------------------------------------------------*/
11073 /* genAssign - generate code for assignment */
11074 /*-----------------------------------------------------------------*/
11076 genAssign (iCode * ic)
11078 operand *result, *right;
11080 unsigned long lit = 0L;
11082 D (emitcode (";", "genAssign"));
11084 result = IC_RESULT (ic);
11085 right = IC_RIGHT (ic);
11087 /* if they are the same */
11088 if (operandsEqu (result, right) &&
11089 !isOperandVolatile (result, FALSE) &&
11090 !isOperandVolatile (right, FALSE))
11093 aopOp (right, ic, FALSE);
11095 /* special case both in far space */
11096 if (AOP_TYPE (right) == AOP_DPTR &&
11097 IS_TRUE_SYMOP (result) &&
11098 isOperandInFarSpace (result))
11100 genFarFarAssign (result, right, ic);
11104 aopOp (result, ic, TRUE);
11106 /* if they are the same registers */
11107 if (sameRegs (AOP (right), AOP (result)) &&
11108 !isOperandVolatile (result, FALSE) &&
11109 !isOperandVolatile (right, FALSE))
11112 /* if the result is a bit */
11113 if (AOP_TYPE (result) == AOP_CRY)
11115 assignBit (result, right);
11119 /* bit variables done */
11121 size = AOP_SIZE (result);
11123 if (AOP_TYPE (right) == AOP_LIT)
11124 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11127 (AOP_TYPE (result) != AOP_REG) &&
11128 (AOP_TYPE (right) == AOP_LIT) &&
11129 !IS_FLOAT (operandType (right)) &&
11132 while ((size) && (lit))
11135 aopGet (right, offset, FALSE, FALSE),
11141 /* And now fill the rest with zeros. */
11144 emitcode ("clr", "a");
11148 aopPut (result, "a", offset);
11157 aopGet (right, offset, FALSE, FALSE),
11164 freeAsmop (result, NULL, ic, TRUE);
11165 freeAsmop (right, NULL, ic, TRUE);
11168 /*-----------------------------------------------------------------*/
11169 /* genJumpTab - generates code for jump table */
11170 /*-----------------------------------------------------------------*/
11172 genJumpTab (iCode * ic)
11174 symbol *jtab,*jtablo,*jtabhi;
11176 unsigned int count;
11178 D (emitcode (";", "genJumpTab"));
11180 count = elementsInSet( IC_JTLABELS (ic) );
11184 /* this algorithm needs 9 cycles and 7 + 3*n bytes
11185 if the switch argument is in a register.
11186 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
11187 /* Peephole may not convert ljmp to sjmp or ret
11188 labelIsReturnOnly & labelInRange must check
11189 currPl->ic->op != JUMPTABLE */
11190 aopOp (IC_JTCOND (ic), ic, FALSE);
11191 /* get the condition into accumulator */
11192 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11194 /* multiply by three */
11195 if (aopGetUsesAcc (IC_JTCOND (ic), 0))
11197 emitcode ("mov", "b,#3");
11198 emitcode ("mul", "ab");
11202 emitcode ("add", "a,acc");
11203 emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
11205 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11207 jtab = newiTempLabel (NULL);
11208 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
11209 emitcode ("jmp", "@a+dptr");
11211 /* now generate the jump labels */
11212 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11213 jtab = setNextItem (IC_JTLABELS (ic)))
11214 emitcode ("ljmp", "%05d$", jtab->key + 100);
11218 /* this algorithm needs 14 cycles and 13 + 2*n bytes
11219 if the switch argument is in a register.
11220 For n>6 this algorithm may be more compact */
11221 jtablo = newiTempLabel (NULL);
11222 jtabhi = newiTempLabel (NULL);
11224 /* get the condition into accumulator.
11225 Using b as temporary storage, if register push/pop is needed */
11226 aopOp (IC_JTCOND (ic), ic, FALSE);
11227 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11228 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
11229 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
11231 // (MB) what if B is in use???
11232 wassertl(!BINUSE, "B was in use");
11233 emitcode ("mov", "b,%s", l);
11236 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11240 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
11241 emitcode ("movc", "a,@a+pc");
11242 emitcode ("push", "acc");
11245 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
11246 emitcode ("movc", "a,@a+pc");
11247 emitcode ("push", "acc");
11251 /* this scales up to n<=255, but needs two more bytes
11252 and changes dptr */
11253 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
11254 emitcode ("movc", "a,@a+dptr");
11255 emitcode ("push", "acc");
11258 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
11259 emitcode ("movc", "a,@a+dptr");
11260 emitcode ("push", "acc");
11263 emitcode ("ret", "");
11265 /* now generate jump table, LSB */
11266 emitLabel (jtablo);
11267 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11268 jtab = setNextItem (IC_JTLABELS (ic)))
11269 emitcode (".db", "%05d$", jtab->key + 100);
11271 /* now generate jump table, MSB */
11272 emitLabel (jtabhi);
11273 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11274 jtab = setNextItem (IC_JTLABELS (ic)))
11275 emitcode (".db", "%05d$>>8", jtab->key + 100);
11279 /*-----------------------------------------------------------------*/
11280 /* genCast - gen code for casting */
11281 /*-----------------------------------------------------------------*/
11283 genCast (iCode * ic)
11285 operand *result = IC_RESULT (ic);
11286 sym_link *ctype = operandType (IC_LEFT (ic));
11287 sym_link *rtype = operandType (IC_RIGHT (ic));
11288 operand *right = IC_RIGHT (ic);
11291 D (emitcode (";", "genCast"));
11293 /* if they are equivalent then do nothing */
11294 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11297 aopOp (right, ic, FALSE);
11298 aopOp (result, ic, FALSE);
11300 /* if the result is a bit (and not a bitfield) */
11301 if (IS_BIT (OP_SYMBOL (result)->type))
11303 assignBit (result, right);
11307 /* if they are the same size : or less */
11308 if (AOP_SIZE (result) <= AOP_SIZE (right))
11311 /* if they are in the same place */
11312 if (sameRegs (AOP (right), AOP (result)))
11315 /* if they in different places then copy */
11316 size = AOP_SIZE (result);
11321 aopGet (right, offset, FALSE, FALSE),
11328 /* if the result is of type pointer */
11329 if (IS_PTR (ctype))
11333 sym_link *type = operandType (right);
11334 sym_link *etype = getSpec (type);
11336 /* pointer to generic pointer */
11337 if (IS_GENPTR (ctype))
11341 p_type = DCL_TYPE (type);
11345 if (SPEC_SCLS(etype)==S_REGISTER) {
11346 // let's assume it is a generic pointer
11349 /* we have to go by the storage class */
11350 p_type = PTR_TYPE (SPEC_OCLS (etype));
11354 /* the first two bytes are known */
11355 size = GPTRSIZE - 1;
11360 aopGet (right, offset, FALSE, FALSE),
11364 /* the last byte depending on type */
11366 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11371 // pointerTypeToGPByte will have bitched.
11375 sprintf(gpValStr, "#0x%x", gpVal);
11376 aopPut (result, gpValStr, GPTRSIZE - 1);
11381 /* just copy the pointers */
11382 size = AOP_SIZE (result);
11387 aopGet (right, offset, FALSE, FALSE),
11394 /* so we now know that the size of destination is greater
11395 than the size of the source */
11396 /* we move to result for the size of source */
11397 size = AOP_SIZE (right);
11402 aopGet (right, offset, FALSE, FALSE),
11407 /* now depending on the sign of the source && destination */
11408 size = AOP_SIZE (result) - AOP_SIZE (right);
11409 /* if unsigned or not an integral type */
11410 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11413 aopPut (result, zero, offset++);
11417 /* we need to extend the sign :{ */
11418 char *l = aopGet (right, AOP_SIZE (right) - 1,
11421 emitcode ("rlc", "a");
11422 emitcode ("subb", "a,acc");
11424 aopPut (result, "a", offset++);
11427 /* we are done hurray !!!! */
11430 freeAsmop (result, NULL, ic, TRUE);
11431 freeAsmop (right, NULL, ic, TRUE);
11434 /*-----------------------------------------------------------------*/
11435 /* genDjnz - generate decrement & jump if not zero instrucion */
11436 /*-----------------------------------------------------------------*/
11438 genDjnz (iCode * ic, iCode * ifx)
11440 symbol *lbl, *lbl1;
11444 /* if the if condition has a false label
11445 then we cannot save */
11446 if (IC_FALSE (ifx))
11449 /* if the minus is not of the form a = a - 1 */
11450 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11451 !IS_OP_LITERAL (IC_RIGHT (ic)))
11454 if (operandLitValue (IC_RIGHT (ic)) != 1)
11457 /* if the size of this greater than one then no
11459 if (getSize (operandType (IC_RESULT (ic))) > 1)
11462 /* otherwise we can save BIG */
11464 D (emitcode (";", "genDjnz"));
11466 lbl = newiTempLabel (NULL);
11467 lbl1 = newiTempLabel (NULL);
11469 aopOp (IC_RESULT (ic), ic, FALSE);
11471 if (AOP_NEEDSACC(IC_RESULT(ic)))
11473 /* If the result is accessed indirectly via
11474 * the accumulator, we must explicitly write
11475 * it back after the decrement.
11477 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11479 if (strcmp(rByte, "a"))
11481 /* Something is hopelessly wrong */
11482 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11483 __FILE__, __LINE__);
11484 /* We can just give up; the generated code will be inefficient,
11485 * but what the hey.
11487 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11490 emitcode ("dec", "%s", rByte);
11491 aopPut (IC_RESULT (ic), rByte, 0);
11492 emitcode ("jnz", "%05d$", lbl->key + 100);
11494 else if (IS_AOP_PREG (IC_RESULT (ic)))
11496 emitcode ("dec", "%s",
11497 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11498 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11499 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11500 ifx->generated = 1;
11501 emitcode ("jnz", "%05d$", lbl->key + 100);
11505 emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11508 emitcode ("sjmp", "%05d$", lbl1->key + 100);
11510 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11513 if (!ifx->generated)
11514 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11515 ifx->generated = 1;
11519 /*-----------------------------------------------------------------*/
11520 /* genReceive - generate code for a receive iCode */
11521 /*-----------------------------------------------------------------*/
11523 genReceive (iCode * ic)
11525 int size = getSize (operandType (IC_RESULT (ic)));
11528 D (emitcode (";", "genReceive"));
11530 if (ic->argreg == 1)
11531 { /* first parameter */
11532 if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11533 isOperandInPagedSpace (IC_RESULT (ic))) &&
11534 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11535 IS_TRUE_SYMOP (IC_RESULT (ic))))
11538 int receivingA = 0;
11541 for (offset = 0; offset<size; offset++)
11542 if (!strcmp (fReturn[offset], "a"))
11547 if (size==1 || getTempRegs(tempRegs, size-1, ic))
11549 for (offset = size-1; offset>0; offset--)
11550 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11551 emitcode("mov","a,%s", fReturn[0]);
11553 aopOp (IC_RESULT (ic), ic, FALSE);
11555 aopPut (IC_RESULT (ic), "a", offset);
11556 for (offset = 1; offset<size; offset++)
11557 aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset);
11563 if (getTempRegs(tempRegs, size, ic))
11565 for (offset = 0; offset<size; offset++)
11566 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11567 aopOp (IC_RESULT (ic), ic, FALSE);
11568 for (offset = 0; offset<size; offset++)
11569 aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset);
11574 offset = fReturnSizeMCS51 - size;
11577 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11578 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11581 aopOp (IC_RESULT (ic), ic, FALSE);
11582 size = AOP_SIZE (IC_RESULT (ic));
11586 emitcode ("pop", "acc");
11587 aopPut (IC_RESULT (ic), "a", offset++);
11593 aopOp (IC_RESULT (ic), ic, FALSE);
11595 assignResultValue (IC_RESULT (ic), NULL);
11598 else if (ic->argreg > 12)
11599 { /* bit parameters */
11600 if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
11602 aopOp (IC_RESULT (ic), ic, FALSE);
11603 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11604 outBitC(IC_RESULT (ic));
11608 { /* other parameters */
11610 aopOp (IC_RESULT (ic), ic, FALSE);
11611 rb1off = ic->argreg;
11614 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
11619 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11622 /*-----------------------------------------------------------------*/
11623 /* genDummyRead - generate code for dummy read of volatiles */
11624 /*-----------------------------------------------------------------*/
11626 genDummyRead (iCode * ic)
11631 D (emitcode(";", "genDummyRead"));
11633 op = IC_RIGHT (ic);
11634 if (op && IS_SYMOP (op))
11636 aopOp (op, ic, FALSE);
11638 /* if the result is a bit */
11639 if (AOP_TYPE (op) == AOP_CRY)
11640 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11643 /* bit variables done */
11645 size = AOP_SIZE (op);
11649 MOVA (aopGet (op, offset, FALSE, FALSE));
11654 freeAsmop (op, NULL, ic, TRUE);
11658 if (op && IS_SYMOP (op))
11660 aopOp (op, ic, FALSE);
11662 /* if the result is a bit */
11663 if (AOP_TYPE (op) == AOP_CRY)
11664 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11667 /* bit variables done */
11669 size = AOP_SIZE (op);
11673 MOVA (aopGet (op, offset, FALSE, FALSE));
11678 freeAsmop (op, NULL, ic, TRUE);
11682 /*-----------------------------------------------------------------*/
11683 /* genCritical - generate code for start of a critical sequence */
11684 /*-----------------------------------------------------------------*/
11686 genCritical (iCode *ic)
11688 symbol *tlbl = newiTempLabel (NULL);
11690 D (emitcode(";", "genCritical"));
11692 if (IC_RESULT (ic))
11694 aopOp (IC_RESULT (ic), ic, TRUE);
11695 aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
11696 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11697 aopPut (IC_RESULT (ic), zero, 0);
11699 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11703 emitcode ("setb", "c");
11704 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11705 emitcode ("clr", "c");
11707 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11711 /*-----------------------------------------------------------------*/
11712 /* genEndCritical - generate code for end of a critical sequence */
11713 /*-----------------------------------------------------------------*/
11715 genEndCritical (iCode *ic)
11717 D(emitcode("; genEndCritical",""));
11721 aopOp (IC_RIGHT (ic), ic, FALSE);
11722 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11724 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11725 emitcode ("mov", "ea,c");
11729 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11730 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11731 emitcode ("rrc", "a");
11732 emitcode ("mov", "ea,c");
11734 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11738 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11739 emitcode ("mov", "ea,c");
11743 /*-----------------------------------------------------------------*/
11744 /* gen51Code - generate code for 8051 based controllers */
11745 /*-----------------------------------------------------------------*/
11747 gen51Code (iCode * lic)
11751 /* int cseq = 0; */
11753 _G.currentFunc = NULL;
11754 lineHead = lineCurr = NULL;
11756 /* print the allocation information */
11757 if (allocInfo && currFunc)
11758 printAllocInfo (currFunc, codeOutBuf);
11759 /* if debug information required */
11760 if (options.debug && currFunc)
11762 debugFile->writeFunction (currFunc, lic);
11764 /* stack pointer name */
11765 if (options.useXstack)
11771 for (ic = lic; ic; ic = ic->next)
11773 _G.current_iCode = ic;
11775 if (ic->lineno && cln != ic->lineno)
11779 debugFile->writeCLine (ic);
11781 if (!options.noCcodeInAsm) {
11782 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
11783 printCLine(ic->filename, ic->lineno));
11788 if (ic->seqPoint && ic->seqPoint != cseq)
11790 emitcode ("", "; sequence point %d", ic->seqPoint);
11791 cseq = ic->seqPoint;
11794 if (options.iCodeInAsm) {
11795 char regsInUse[80];
11800 for (i=0; i<8; i++) {
11801 sprintf (®sInUse[i],
11802 "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11805 strcpy (regsInUse, "--------");
11806 for (i=0; i < 8; i++) {
11807 if (bitVectBitValue (ic->rMask, i))
11809 int offset = regs8051[i].offset;
11810 regsInUse[offset] = offset + '0'; /* show rMask */
11814 iLine = printILine(ic);
11815 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
11818 /* if the result is marked as
11819 spilt and rematerializable or code for
11820 this has already been generated then
11822 if (resultRemat (ic) || ic->generated)
11825 /* depending on the operation */
11845 /* IPOP happens only when trying to restore a
11846 spilt live range, if there is an ifx statement
11847 following this pop then the if statement might
11848 be using some of the registers being popped which
11849 would destory the contents of the register so
11850 we need to check for this condition and handle it */
11852 ic->next->op == IFX &&
11853 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11854 genIfx (ic->next, ic);
11872 genEndFunction (ic);
11892 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11909 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11913 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11920 /* note these two are xlated by algebraic equivalence
11921 in decorateType() in SDCCast.c */
11922 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11923 "got '>=' or '<=' shouldn't have come here");
11927 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11939 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11943 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11947 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11983 genRightShift (ic);
11986 case GET_VALUE_AT_ADDRESS:
11988 hasInc (IC_LEFT (ic), ic,
11989 getSize (operandType (IC_RESULT (ic)))),
11990 ifxForOp (IC_RESULT (ic), ic) );
11994 if (POINTER_SET (ic))
11996 hasInc (IC_RESULT (ic), ic,
11997 getSize (operandType (IC_RIGHT (ic)))));
12023 addSet (&_G.sendSet, ic);
12026 case DUMMY_READ_VOLATILE:
12035 genEndCritical (ic);
12047 _G.current_iCode = NULL;
12049 /* now we are ready to call the
12050 peep hole optimizer */
12051 if (!options.nopeep)
12052 peepHole (&lineHead);
12054 /* now do the actual printing */
12055 printLine (lineHead, codeOutBuf);