1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for 8051
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
27 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
28 Made everything static
29 -------------------------------------------------------------------------*/
31 #define D(x) do if (options.verboseAsm) {x;} while(0)
37 #include "SDCCglobl.h"
41 #include "SDCCpeeph.h"
45 #include "dbuf_string.h"
47 char *aopLiteral (value * val, int offset);
48 char *aopLiteralLong (value * val, int offset, int size);
51 /* this is the down and dirty file with all kinds of
52 kludgy & hacky stuff. This is what it is all about
53 CODE GENERATION for a specific MCU . some of the
54 routines may be reusable, will have to see */
56 static char *zero = "#0x00";
57 static char *one = "#0x01";
61 {"dpl", "dph", "b", "a"};
62 unsigned fReturnSizeMCS51 = 4; /* shared with ralloc.c */
63 char **fReturn = fReturn8051;
64 static char *accUse[] =
67 static unsigned short rbank = -1;
69 #define IS_OP_RUONLY(x) (x && IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
71 #define REG_WITH_INDEX mcs51_regWithIdx
73 #define AOP(op) op->aop
74 #define AOP_TYPE(op) AOP(op)->type
75 #define AOP_SIZE(op) AOP(op)->size
76 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
77 AOP_TYPE(x) == AOP_R0))
79 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
80 AOP_TYPE(x) == AOP_DPTR || \
83 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
84 (x->aopu.aop_reg[0] == REG_WITH_INDEX(R0_IDX) || \
85 x->aopu.aop_reg[0] == REG_WITH_INDEX(R1_IDX) )))
87 #define SYM_BP(sym) (SPEC_OCLS (sym->etype)->paged ? "_bpx" : "_bp")
89 #define R0INB _G.bu.bs.r0InB
90 #define R1INB _G.bu.bs.r1InB
91 #define OPINB _G.bu.bs.OpInB
92 #define BINUSE _G.bu.BInUse
102 short r0InB : 2;//2 so we can see it overflow
103 short r1InB : 2;//2 so we can see it overflow
104 short OpInB : 2;//2 so we can see it overflow
113 iCode *current_iCode;
118 static char *rb1regs[] = {
119 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7",
120 "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7"
123 extern struct dbuf_s *codeOutBuf;
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)));
194 lineCurr->isInline = _G.inLine;
195 lineCurr->isDebug = _G.debugLine;
196 lineCurr->ic = _G.current_iCode;
197 lineCurr->isComment = (*lbp==';');
206 emitLabel (symbol *tlbl)
208 emitcode ("", "%05d$:", tlbl->key + 100);
209 lineCurr->isLabel = 1;
212 /*-----------------------------------------------------------------*/
213 /* mcs51_emitDebuggerSymbol - associate the current code location */
214 /* with a debugger symbol */
215 /*-----------------------------------------------------------------*/
217 mcs51_emitDebuggerSymbol (char * debugSym)
220 emitcode ("", "%s ==.", debugSym);
224 /*-----------------------------------------------------------------*/
225 /* mova - moves specified value into accumulator */
226 /*-----------------------------------------------------------------*/
230 /* do some early peephole optimization */
231 if (!strncmp(x, "a", 2) || !strncmp(x, "acc", 4))
234 /* if it is a literal mov try to get it cheaper */
239 emitcode("mov", "a,%s", x);
242 /*-----------------------------------------------------------------*/
243 /* movb - moves specified value into register b */
244 /*-----------------------------------------------------------------*/
248 /* do some early peephole optimization */
249 if (!strncmp(x, "b", 2))
252 /* if it is a literal mov try to get it cheaper */
255 emitcode("mov","b,%s", rtrackGetLit(x));
259 emitcode("mov","b,%s", x);
262 /*-----------------------------------------------------------------*/
263 /* pushB - saves register B if necessary */
264 /*-----------------------------------------------------------------*/
268 bool pushedB = FALSE;
272 emitcode ("push", "b");
273 // printf("B was in use !\n");
283 /*-----------------------------------------------------------------*/
284 /* popB - restores value of register B if necessary */
285 /*-----------------------------------------------------------------*/
291 emitcode ("pop", "b");
299 /*-----------------------------------------------------------------*/
300 /* pushReg - saves register */
301 /*-----------------------------------------------------------------*/
303 pushReg (int index, bool bits_pushed)
305 regs * reg = REG_WITH_INDEX (index);
306 if (reg->type == REG_BIT)
309 emitcode ("push", "%s", reg->base);
313 emitcode ("push", "%s", reg->dname);
317 /*-----------------------------------------------------------------*/
318 /* popReg - restores register */
319 /*-----------------------------------------------------------------*/
321 popReg (int index, bool bits_popped)
323 regs * reg = REG_WITH_INDEX (index);
324 if (reg->type == REG_BIT)
327 emitcode ("pop", "%s", reg->base);
331 emitcode ("pop", "%s", reg->dname);
335 /*-----------------------------------------------------------------*/
336 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
337 /*-----------------------------------------------------------------*/
339 getFreePtr (iCode * ic, asmop ** aopp, bool result)
344 /* the logic: if r0 & r1 used in the instruction
345 then we are in trouble otherwise */
347 /* first check if r0 & r1 are used by this
348 instruction, in which case we are in trouble */
349 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
350 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
355 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
356 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
358 /* if no usage of r0 then return it */
361 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
362 (*aopp)->type = AOP_R0;
364 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
367 /* if no usage of r1 then return it */
370 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
371 (*aopp)->type = AOP_R1;
373 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R1_IDX);
376 /* now we know they both have usage */
377 /* if r0 not used in this instruction */
380 /* push it if not already pushed */
383 MOVB (REG_WITH_INDEX (R0_IDX)->dname);
386 else if (!_G.r0Pushed)
388 emitcode ("push", "%s",
389 REG_WITH_INDEX (R0_IDX)->dname);
393 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
394 (*aopp)->type = AOP_R0;
396 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
399 /* if r1 not used then */
403 /* push it if not already pushed */
406 MOVB (REG_WITH_INDEX (R1_IDX)->dname);
409 else if (!_G.r1Pushed)
411 emitcode ("push", "%s",
412 REG_WITH_INDEX (R1_IDX)->dname);
416 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
417 (*aopp)->type = AOP_R1;
418 return REG_WITH_INDEX (R1_IDX);
422 /* I said end of world, but not quite end of world yet */
423 /* if this is a result then we can push it on the stack */
426 (*aopp)->type = AOP_STK;
429 /* in the case that result AND left AND right needs a pointer reg
430 we can safely use the result's */
431 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX))
433 (*aopp)->type = AOP_R0;
434 return REG_WITH_INDEX (R0_IDX);
436 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX))
438 (*aopp)->type = AOP_R1;
439 return REG_WITH_INDEX (R1_IDX);
442 /* now this is REALLY the end of the world */
443 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
444 "getFreePtr should never reach here");
449 /*-----------------------------------------------------------------*/
450 /* getTempRegs - initialize an array of pointers to GPR registers */
451 /* that are not in use. Returns 1 if the requested */
452 /* number of registers were available, 0 otherwise. */
453 /*-----------------------------------------------------------------*/
455 getTempRegs(regs **tempRegs, int size, iCode *ic)
462 ic = _G.current_iCode;
468 freeRegs = newBitVect(8);
469 bitVectSetBit (freeRegs, R2_IDX);
470 bitVectSetBit (freeRegs, R3_IDX);
471 bitVectSetBit (freeRegs, R4_IDX);
472 bitVectSetBit (freeRegs, R5_IDX);
473 bitVectSetBit (freeRegs, R6_IDX);
474 bitVectSetBit (freeRegs, R7_IDX);
476 if (IFFUNC_CALLEESAVES(_G.currentFunc->type))
478 bitVect * newfreeRegs;
479 newfreeRegs = bitVectIntersect (freeRegs, _G.currentFunc->regsUsed);
480 freeBitVect(freeRegs);
481 freeRegs = newfreeRegs;
483 freeRegs = bitVectCplAnd (freeRegs, ic->rMask);
486 for (i=0; i<freeRegs->size; i++)
488 if (bitVectBitValue(freeRegs,i))
489 tempRegs[offset++] = REG_WITH_INDEX(i);
492 freeBitVect(freeRegs);
497 freeBitVect(freeRegs);
502 /*-----------------------------------------------------------------*/
503 /* newAsmop - creates a new asmOp */
504 /*-----------------------------------------------------------------*/
506 newAsmop (short type)
510 aop = Safe_calloc (1, sizeof (asmop));
516 /*-----------------------------------------------------------------*/
517 /* pointerCode - returns the code for a pointer type */
518 /*-----------------------------------------------------------------*/
520 pointerCode (sym_link * etype)
523 return PTR_TYPE (SPEC_OCLS (etype));
527 /*-----------------------------------------------------------------*/
528 /* leftRightUseAcc - returns size of accumulator use by operands */
529 /*-----------------------------------------------------------------*/
531 leftRightUseAcc(iCode *ic)
540 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
541 "null iCode pointer");
548 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
551 size = getSize (OP_SYMBOL (op)->type);
556 else if (ic->op == JUMPTABLE)
559 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
562 size = getSize (OP_SYMBOL (op)->type);
570 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
573 size = getSize (OP_SYMBOL (op)->type);
578 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
581 size = getSize (OP_SYMBOL (op)->type);
593 /*-----------------------------------------------------------------*/
594 /* aopForSym - for a true symbol */
595 /*-----------------------------------------------------------------*/
597 aopForSym (iCode * ic, symbol * sym, bool result)
601 bool accuse = leftRightUseAcc (ic) || _G.accInUse;
603 wassertl (ic != NULL, "Got a null iCode");
604 wassertl (sym != NULL, "Got a null symbol");
606 space = SPEC_OCLS (sym->etype);
608 /* if already has one */
611 sym->aop->allocated++;
615 /* assign depending on the storage class */
616 /* if it is on the stack or indirectly addressable */
617 /* space we need to assign either r0 or r1 to it */
618 if (sym->onStack || sym->iaccess)
620 sym->aop = aop = newAsmop (0);
621 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
622 aop->size = getSize (sym->type);
624 /* now assign the address of the variable to
625 the pointer register */
626 if (aop->type != AOP_STK)
630 signed char offset = ((sym->stack < 0) ?
631 ((signed char) (sym->stack - _G.nRegsSaved)) :
632 ((signed char) sym->stack)) & 0xff;
634 if ((abs(offset) <= 3) ||
635 (accuse && (abs(offset) <= 7)))
637 emitcode ("mov", "%s,%s",
638 aop->aopu.aop_ptr->name, SYM_BP (sym));
641 emitcode ("dec", aop->aopu.aop_ptr->name);
646 emitcode ("inc", aop->aopu.aop_ptr->name);
653 emitcode ("push", "acc");
654 emitcode ("mov", "a,%s", SYM_BP (sym));
655 emitcode ("add", "a,#0x%02x", offset & 0xff);
656 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
658 emitcode ("pop", "acc");
663 emitcode ("mov", "%s,#%s",
664 aop->aopu.aop_ptr->name,
667 aop->paged = space->paged;
670 aop->aopu.aop_stk = sym->stack;
674 /* if in bit space */
675 if (IN_BITSPACE (space))
677 sym->aop = aop = newAsmop (AOP_CRY);
678 aop->aopu.aop_dir = sym->rname;
679 aop->size = getSize (sym->type);
682 /* if it is in direct space */
683 if (IN_DIRSPACE (space))
685 //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
686 //printTypeChainRaw(sym->type, NULL);
687 //printf("space = %s\n", space ? space->sname : "NULL");
688 sym->aop = aop = newAsmop (AOP_DIR);
689 aop->aopu.aop_dir = sym->rname;
690 aop->size = getSize (sym->type);
694 /* special case for a function */
695 if (IS_FUNC (sym->type))
697 sym->aop = aop = newAsmop (AOP_IMMD);
698 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
699 aop->size = getSize (sym->type);
703 /* only remaining is far space */
704 /* in which case DPTR gets the address */
705 sym->aop = aop = newAsmop (AOP_DPTR);
706 emitcode ("mov", "dptr,#%s", sym->rname);
707 aop->size = getSize (sym->type);
709 /* if it is in code space */
710 if (IN_CODESPACE (space))
716 /*-----------------------------------------------------------------*/
717 /* aopForRemat - rematerialzes an object */
718 /*-----------------------------------------------------------------*/
720 aopForRemat (symbol * sym)
722 iCode *ic = sym->rematiCode;
723 asmop *aop = newAsmop (AOP_IMMD);
730 val += (int) operandLitValue (IC_RIGHT (ic));
731 else if (ic->op == '-')
732 val -= (int) operandLitValue (IC_RIGHT (ic));
733 else if (IS_CAST_ICODE(ic)) {
734 sym_link *from_type = operandType(IC_RIGHT(ic));
735 aop->aopu.aop_immd.from_cast_remat = 1;
736 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
737 ptr_type = pointerTypeToGPByte (DCL_TYPE(from_type), NULL, NULL);
741 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
746 SNPRINTF (buffer, sizeof(buffer),
748 OP_SYMBOL (IC_LEFT (ic))->rname,
749 val >= 0 ? '+' : '-',
754 strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
757 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
758 /* set immd2 field if required */
759 if (aop->aopu.aop_immd.from_cast_remat)
761 SNPRINTF (buffer, sizeof(buffer), "#0x%02x", ptr_type);
762 aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
768 /*-----------------------------------------------------------------*/
769 /* regsInCommon - two operands have some registers in common */
770 /*-----------------------------------------------------------------*/
772 regsInCommon (operand * op1, operand * op2)
777 /* if they have registers in common */
778 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
781 sym1 = OP_SYMBOL (op1);
782 sym2 = OP_SYMBOL (op2);
784 if (sym1->nRegs == 0 || sym2->nRegs == 0)
787 for (i = 0; i < sym1->nRegs; i++)
793 for (j = 0; j < sym2->nRegs; j++)
798 if (sym2->regs[j] == sym1->regs[i])
806 /*-----------------------------------------------------------------*/
807 /* operandsEqu - equivalent */
808 /*-----------------------------------------------------------------*/
810 operandsEqu (operand * op1, operand * op2)
814 /* if they're not symbols */
815 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
818 sym1 = OP_SYMBOL (op1);
819 sym2 = OP_SYMBOL (op2);
821 /* if both are itemps & one is spilt
822 and the other is not then false */
823 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
824 sym1->isspilt != sym2->isspilt)
827 /* if they are the same */
831 /* if they have the same rname */
832 if (sym1->rname[0] && sym2->rname[0] &&
833 strcmp (sym1->rname, sym2->rname) == 0 &&
834 !(IS_PARM (op2) && IS_ITEMP (op1)))
837 /* if left is a tmp & right is not */
838 if (IS_ITEMP (op1) &&
841 (sym1->usl.spillLoc == sym2))
844 if (IS_ITEMP (op2) &&
848 (sym2->usl.spillLoc == sym1))
854 /*-----------------------------------------------------------------*/
855 /* sameByte - two asmops have the same address at given offsets */
856 /*-----------------------------------------------------------------*/
858 sameByte (asmop * aop1, int off1, asmop * aop2, int off2)
860 if (aop1 == aop2 && off1 == off2)
863 if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
866 if (aop1->type != aop2->type)
869 if (aop1->aopu.aop_reg[off1] != aop2->aopu.aop_reg[off2])
875 /*-----------------------------------------------------------------*/
876 /* sameRegs - two asmops have the same registers */
877 /*-----------------------------------------------------------------*/
879 sameRegs (asmop * aop1, asmop * aop2)
886 if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
889 if (aop1->type != aop2->type)
892 if (aop1->size != aop2->size)
895 for (i = 0; i < aop1->size; i++)
896 if (aop1->aopu.aop_reg[i] != aop2->aopu.aop_reg[i])
902 /*-----------------------------------------------------------------*/
903 /* aopOp - allocates an asmop for an operand : */
904 /*-----------------------------------------------------------------*/
906 aopOp (operand * op, iCode * ic, bool result)
915 /* if this a literal */
916 if (IS_OP_LITERAL (op))
918 op->aop = aop = newAsmop (AOP_LIT);
919 aop->aopu.aop_lit = op->operand.valOperand;
920 aop->size = getSize (operandType (op));
924 /* if already has a asmop then continue */
927 op->aop->allocated++;
931 /* if the underlying symbol has a aop */
932 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
934 op->aop = OP_SYMBOL (op)->aop;
935 op->aop->allocated++;
939 /* if this is a true symbol */
940 if (IS_TRUE_SYMOP (op))
942 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
946 /* this is a temporary : this has
952 e) can be a return use only */
954 sym = OP_SYMBOL (op);
956 /* if the type is a conditional */
957 if (sym->regType == REG_CND)
959 sym->aop = op->aop = aop = newAsmop (AOP_CRY);
960 aop->size = sym->ruonly ? 1 : 0;
964 /* if it is spilt then two situations
966 b) has a spill location */
967 if (sym->isspilt || sym->nRegs == 0)
970 /* rematerialize it NOW */
973 sym->aop = op->aop = aop = aopForRemat (sym);
974 aop->size = getSize (sym->type);
981 sym->aop = op->aop = aop = newAsmop (AOP_ACC);
982 aop->size = getSize (sym->type);
983 for (i = 0; i < 2; i++)
984 aop->aopu.aop_str[i] = accUse[i];
992 sym->aop = op->aop = aop = newAsmop (AOP_STR);
993 aop->size = getSize (sym->type);
994 for (i = 0; i < fReturnSizeMCS51; i++)
995 aop->aopu.aop_str[i] = fReturn[i];
999 if (sym->usl.spillLoc)
1001 asmop *oldAsmOp = NULL;
1003 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1005 /* force a new aop if sizes differ */
1006 oldAsmOp = sym->usl.spillLoc->aop;
1007 sym->usl.spillLoc->aop = NULL;
1009 sym->aop = op->aop = aop =
1010 aopForSym (ic, sym->usl.spillLoc, result);
1011 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1013 /* Don't reuse the new aop, go with the last one */
1014 sym->usl.spillLoc->aop = oldAsmOp;
1016 aop->size = getSize (sym->type);
1020 /* else must be a dummy iTemp */
1021 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1022 aop->size = getSize (sym->type);
1026 /* if the type is a bit register */
1027 if (sym->regType == REG_BIT)
1029 sym->aop = op->aop = aop = newAsmop (AOP_CRY);
1030 aop->size = sym->nRegs;//1???
1031 aop->aopu.aop_reg[0] = sym->regs[0];
1032 aop->aopu.aop_dir = sym->regs[0]->name;
1036 /* must be in a register */
1037 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1038 aop->size = sym->nRegs;
1039 for (i = 0; i < sym->nRegs; i++)
1040 aop->aopu.aop_reg[i] = sym->regs[i];
1043 /*-----------------------------------------------------------------*/
1044 /* freeAsmop - free up the asmop given to an operand */
1045 /*----------------------------------------------------------------*/
1047 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1064 /* depending on the asmop type only three cases need work
1065 AOP_R0, AOP_R1 & AOP_STK */
1071 emitcode ("mov", "r0,b");
1074 else if (_G.r0Pushed)
1078 emitcode ("pop", "ar0");
1082 bitVectUnSetBit (ic->rUsed, R0_IDX);
1088 emitcode ("mov", "r1,b");
1091 else if (_G.r1Pushed)
1095 emitcode ("pop", "ar1");
1099 bitVectUnSetBit (ic->rUsed, R1_IDX);
1105 int stk = aop->aopu.aop_stk + aop->size - 1;
1106 bitVectUnSetBit (ic->rUsed, R0_IDX);
1107 bitVectUnSetBit (ic->rUsed, R1_IDX);
1109 getFreePtr (ic, &aop, FALSE);
1113 emitcode ("mov", "a,_bp");
1114 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1115 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1119 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1124 emitcode ("pop", "acc");
1125 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1128 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1131 freeAsmop (op, NULL, ic, TRUE);
1134 emitcode ("pop", "ar1");
1139 emitcode ("pop", "ar0");
1147 /* all other cases just dealloc */
1153 OP_SYMBOL (op)->aop = NULL;
1154 /* if the symbol has a spill */
1156 SPIL_LOC (op)->aop = NULL;
1161 /*------------------------------------------------------------------*/
1162 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
1163 /* pop r0 or r1 off stack if pushed */
1164 /*------------------------------------------------------------------*/
1166 freeForBranchAsmop (operand * op)
1178 if (!aop->allocated)
1186 emitcode ("mov", "r0,b");
1188 else if (_G.r0Pushed)
1190 emitcode ("pop", "ar0");
1197 emitcode ("mov", "r1,b");
1199 else if (_G.r1Pushed)
1201 emitcode ("pop", "ar1");
1208 int stk = aop->aopu.aop_stk + aop->size - 1;
1210 emitcode ("mov", "b,r0");
1213 emitcode ("mov", "a,_bp");
1214 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1215 emitcode ("mov", "r0,a");
1219 emitcode ("mov", "r0,_bp");
1224 emitcode ("pop", "acc");
1225 emitcode ("mov", "@r0,a");
1228 emitcode ("dec", "r0");
1230 emitcode ("mov", "r0,b");
1236 /*-----------------------------------------------------------------*/
1237 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
1238 /* clobber the accumulator */
1239 /*-----------------------------------------------------------------*/
1241 aopGetUsesAcc (operand * oper, int offset)
1243 asmop * aop = AOP (oper);
1245 if (offset > (aop->size - 1))
1263 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1274 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1280 /* Error case --- will have been caught already */
1286 /*-------------------------------------------------------------------*/
1287 /* aopGet - for fetching value of the aop */
1288 /*-------------------------------------------------------------------*/
1290 aopGet (operand * oper, int offset, bool bit16, bool dname)
1292 asmop * aop = AOP (oper);
1294 /* offset is greater than
1296 if (offset > (aop->size - 1) &&
1297 aop->type != AOP_LIT)
1300 /* depending on type */
1308 /* if we need to increment it */
1309 while (offset > aop->coff)
1311 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1315 while (offset < aop->coff)
1317 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1324 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1325 return (dname ? "acc" : "a");
1327 SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1328 return Safe_strdup(buffer);
1331 if (aop->code && aop->coff==0 && offset>=1) {
1332 emitcode ("mov", "a,#0x%02x", offset);
1333 emitcode ("movc", "a,@a+dptr");
1334 return (dname ? "acc" : "a");
1337 while (offset > aop->coff)
1339 emitcode ("inc", "dptr");
1343 while (offset < aop->coff)
1345 emitcode ("lcall", "__decdptr");
1352 emitcode ("clr", "a");
1353 emitcode ("movc", "a,@a+dptr");
1357 emitcode ("movx", "a,@dptr");
1359 return (dname ? "acc" : "a");
1362 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1364 SNPRINTF(buffer, sizeof(buffer),
1365 "%s",aop->aopu.aop_immd.aop_immd2);
1369 SNPRINTF(buffer, sizeof(buffer),
1370 "#%s", aop->aopu.aop_immd.aop_immd1);
1374 SNPRINTF (buffer, sizeof(buffer),
1376 aop->aopu.aop_immd.aop_immd1,
1381 SNPRINTF (buffer, sizeof(buffer),
1383 aop->aopu.aop_immd.aop_immd1);
1385 return Safe_strdup(buffer);
1388 if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
1390 SNPRINTF (buffer, sizeof(buffer),
1392 aop->aopu.aop_dir, offset * 8);
1396 SNPRINTF (buffer, sizeof(buffer),
1403 SNPRINTF (buffer, sizeof(buffer),
1408 return Safe_strdup(buffer);
1412 return aop->aopu.aop_reg[offset]->dname;
1414 return aop->aopu.aop_reg[offset]->name;
1417 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1418 emitcode ("clr", "a");
1419 emitcode ("rlc", "a");
1420 return (dname ? "acc" : "a");
1423 if (!offset && dname)
1425 return aop->aopu.aop_str[offset];
1428 return aopLiteral (aop->aopu.aop_lit, offset);
1432 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1436 return aop->aopu.aop_str[offset];
1440 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1441 "aopget got unsupported aop->type");
1445 /*-----------------------------------------------------------------*/
1446 /* aopPutUsesAcc - indicates ahead of time whether aopPut() will */
1447 /* clobber the accumulator */
1448 /*-----------------------------------------------------------------*/
1450 aopPutUsesAcc (operand * oper, const char *s, int offset)
1452 asmop * aop = AOP (oper);
1454 if (offset > (aop->size - 1))
1464 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1470 return ((aop->paged) || (*s == '@'));
1474 return (!aop->aopu.aop_dir || strcmp(s, aop->aopu.aop_dir));
1482 /* Error case --- will have been caught already */
1488 /*-----------------------------------------------------------------*/
1489 /* aopPut - puts a string for a aop and indicates if acc is in use */
1490 /*-----------------------------------------------------------------*/
1492 aopPut (operand * result, const char *s, int offset)
1494 bool bvolatile = isOperandVolatile (result, FALSE);
1495 bool accuse = FALSE;
1496 asmop * aop = AOP (result);
1497 const char *d = NULL;
1499 if (aop->size && offset > (aop->size - 1))
1501 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1502 "aopPut got offset > aop->size");
1506 /* will assign value to value */
1507 /* depending on where it is ofcourse */
1511 MOVA (s); /* read s in case it was volatile */
1516 if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1518 SNPRINTF (buffer, sizeof(buffer),
1520 aop->aopu.aop_dir, offset * 8);
1524 SNPRINTF (buffer, sizeof(buffer),
1526 aop->aopu.aop_dir, offset);
1530 SNPRINTF (buffer, sizeof(buffer),
1535 if (strcmp (buffer, s) || bvolatile)
1537 emitcode ("mov", "%s,%s", buffer, s);
1539 if (!strcmp (buffer, "acc"))
1546 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1547 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1550 strcmp (s, "r0") == 0 ||
1551 strcmp (s, "r1") == 0 ||
1552 strcmp (s, "r2") == 0 ||
1553 strcmp (s, "r3") == 0 ||
1554 strcmp (s, "r4") == 0 ||
1555 strcmp (s, "r5") == 0 ||
1556 strcmp (s, "r6") == 0 ||
1557 strcmp (s, "r7") == 0)
1559 emitcode ("mov", "%s,%s",
1560 aop->aopu.aop_reg[offset]->dname, s);
1564 emitcode ("mov", "%s,%s",
1565 aop->aopu.aop_reg[offset]->name, s);
1573 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1574 "aopPut writing to code space");
1578 while (offset > aop->coff)
1581 emitcode ("inc", "dptr");
1584 while (offset < aop->coff)
1587 emitcode ("lcall", "__decdptr");
1592 /* if not in accumulator */
1595 emitcode ("movx", "@dptr,a");
1600 while (offset > aop->coff)
1603 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1605 while (offset < aop->coff)
1608 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1615 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1620 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1622 else if (strcmp (s, "r0") == 0 ||
1623 strcmp (s, "r1") == 0 ||
1624 strcmp (s, "r2") == 0 ||
1625 strcmp (s, "r3") == 0 ||
1626 strcmp (s, "r4") == 0 ||
1627 strcmp (s, "r5") == 0 ||
1628 strcmp (s, "r6") == 0 ||
1629 strcmp (s, "r7") == 0)
1632 SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1633 emitcode ("mov", "@%s,%s",
1634 aop->aopu.aop_ptr->name, buffer);
1638 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1643 if (strcmp (s, "a") == 0)
1645 emitcode ("push", "acc");
1650 emitcode ("push", "acc");
1652 else if (strcmp (s, "r0") == 0 ||
1653 strcmp (s, "r1") == 0 ||
1654 strcmp (s, "r2") == 0 ||
1655 strcmp (s, "r3") == 0 ||
1656 strcmp (s, "r4") == 0 ||
1657 strcmp (s, "r5") == 0 ||
1658 strcmp (s, "r6") == 0 ||
1659 strcmp (s, "r7") == 0)
1662 SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1663 emitcode ("push", buffer);
1667 emitcode ("push", s);
1673 // destination is carry for return-use-only
1674 d = (IS_OP_RUONLY (result)) ? "c" : aop->aopu.aop_dir;
1675 // source is no literal and not in carry
1676 if ((s != zero) && (s != one) && strcmp (s, "c"))
1679 /* set C, if a >= 1 */
1680 emitcode ("add", "a,#0xff");
1683 // now source is zero, one or carry
1685 /* if result no bit variable */
1688 if (!strcmp (s, "c"))
1690 /* inefficient: move carry into A and use jz/jnz */
1691 emitcode ("clr", "a");
1692 emitcode ("rlc", "a");
1702 emitcode ("clr", "%s", d);
1704 emitcode ("setb", "%s", d);
1705 else if (strcmp (s, d))
1706 emitcode ("mov", "%s,c", d);
1711 if (strcmp (aop->aopu.aop_str[offset], s) || bvolatile)
1712 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1718 if (!offset && (strcmp (s, "acc") == 0) && !bvolatile)
1721 if (strcmp (aop->aopu.aop_str[offset], s) && !bvolatile)
1722 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1726 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1727 "aopPut got unsupported aop->type");
1736 /*-----------------------------------------------------------------*/
1737 /* pointToEnd :- points to the last byte of the operand */
1738 /*-----------------------------------------------------------------*/
1740 pointToEnd (asmop * aop)
1746 aop->coff = count = (aop->size - 1);
1752 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1756 emitcode ("inc", "dptr");
1763 /*-----------------------------------------------------------------*/
1764 /* reAdjustPreg - points a register back to where it should */
1765 /*-----------------------------------------------------------------*/
1767 reAdjustPreg (asmop * aop)
1769 if ((aop->coff==0) || (aop->size <= 1))
1777 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1782 emitcode ("lcall", "__decdptr");
1789 /*-----------------------------------------------------------------*/
1790 /* opIsGptr: returns non-zero if the passed operand is */
1791 /* a generic pointer type. */
1792 /*-----------------------------------------------------------------*/
1794 opIsGptr (operand * op)
1796 sym_link *type = operandType (op);
1798 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1805 /*-----------------------------------------------------------------*/
1806 /* getDataSize - get the operand data size */
1807 /*-----------------------------------------------------------------*/
1809 getDataSize (operand * op)
1812 size = AOP_SIZE (op);
1813 if (size == GPTRSIZE)
1815 sym_link *type = operandType (op);
1816 if (IS_GENPTR (type))
1818 /* generic pointer; arithmetic operations
1819 * should ignore the high byte (pointer type).
1827 /*-----------------------------------------------------------------*/
1828 /* outAcc - output Acc */
1829 /*-----------------------------------------------------------------*/
1831 outAcc (operand * result)
1834 size = getDataSize (result);
1837 aopPut (result, "a", 0);
1840 /* unsigned or positive */
1843 aopPut (result, zero, offset++);
1848 /*-----------------------------------------------------------------*/
1849 /* outBitC - output a bit C */
1850 /*-----------------------------------------------------------------*/
1852 outBitC (operand * result)
1854 /* if the result is bit */
1855 if (AOP_TYPE (result) == AOP_CRY)
1857 if (!OP_SYMBOL (result)->ruonly)
1858 aopPut (result, "c", 0);
1862 emitcode ("clr", "a");
1863 emitcode ("rlc", "a");
1868 /*-----------------------------------------------------------------*/
1869 /* toBoolean - emit code for orl a,operator(sizeop) */
1870 /*-----------------------------------------------------------------*/
1872 toBoolean (operand * oper)
1874 int size = AOP_SIZE (oper) - 1;
1876 bool AccUsed = FALSE;
1879 while (!AccUsed && size--)
1881 AccUsed |= aopGetUsesAcc(oper, offset++);
1884 size = AOP_SIZE (oper) - 1;
1886 MOVA (aopGet (oper, 0, FALSE, FALSE));
1887 if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1890 emitcode("mov", "b,a");
1893 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1894 emitcode ("orl", "b,a");
1896 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1897 emitcode ("orl", "a,b");
1904 emitcode ("orl", "a,%s",
1905 aopGet (oper, offset++, FALSE, FALSE));
1910 /*-----------------------------------------------------------------*/
1911 /* toCarry - make boolean and move into carry */
1912 /*-----------------------------------------------------------------*/
1914 toCarry (operand * oper)
1916 /* if the operand is a literal then
1917 we know what the value is */
1918 if (AOP_TYPE (oper) == AOP_LIT)
1920 if ((int) operandLitValue (oper))
1925 else if (AOP_TYPE (oper) == AOP_CRY)
1927 emitcode ("mov", "c,%s", oper->aop->aopu.aop_dir);
1931 /* or the operand into a */
1933 /* set C, if a >= 1 */
1934 emitcode ("add", "a,#0xff");
1938 /*-----------------------------------------------------------------*/
1939 /* assignBit - assign operand to bit operand */
1940 /*-----------------------------------------------------------------*/
1942 assignBit (operand * result, operand * right)
1944 /* if the right side is a literal then
1945 we know what the value is */
1946 if (AOP_TYPE (right) == AOP_LIT)
1948 if ((int) operandLitValue (right))
1949 aopPut (result, one, 0);
1951 aopPut (result, zero, 0);
1956 aopPut (result, "c", 0);
1961 /*-------------------------------------------------------------------*/
1962 /* xch_a_aopGet - for exchanging acc with value of the aop */
1963 /*-------------------------------------------------------------------*/
1965 xch_a_aopGet (operand * oper, int offset, bool bit16, bool dname)
1969 if (aopGetUsesAcc (oper, offset))
1971 emitcode("mov", "b,a");
1972 MOVA (aopGet (oper, offset, bit16, dname));
1973 emitcode("xch", "a,b");
1974 aopPut (oper, "a", offset);
1975 emitcode("xch", "a,b");
1980 l = aopGet (oper, offset, bit16, dname);
1981 emitcode("xch", "a,%s", l);
1987 /*-----------------------------------------------------------------*/
1988 /* genNot - generate code for ! operation */
1989 /*-----------------------------------------------------------------*/
1995 D (emitcode (";", "genNot"));
1997 /* assign asmOps to operand & result */
1998 aopOp (IC_LEFT (ic), ic, FALSE);
1999 aopOp (IC_RESULT (ic), ic, TRUE);
2001 /* if in bit space then a special case */
2002 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2004 /* if left==result then cpl bit */
2005 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2007 emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2011 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2012 emitcode ("cpl", "c");
2013 outBitC (IC_RESULT (ic));
2018 toBoolean (IC_LEFT (ic));
2020 /* set C, if a == 0 */
2021 tlbl = newiTempLabel (NULL);
2022 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
2024 outBitC (IC_RESULT (ic));
2027 /* release the aops */
2028 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2029 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2033 /*-----------------------------------------------------------------*/
2034 /* genCpl - generate code for complement */
2035 /*-----------------------------------------------------------------*/
2042 sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
2044 D(emitcode (";", "genCpl"));
2046 /* assign asmOps to operand & result */
2047 aopOp (IC_LEFT (ic), ic, FALSE);
2048 aopOp (IC_RESULT (ic), ic, TRUE);
2050 /* special case if in bit space */
2051 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2055 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
2056 (SPEC_USIGN (letype) && IS_CHAR (letype)))
2058 /* promotion rules are responsible for this strange result:
2059 bit -> int -> ~int -> bit
2060 uchar -> int -> ~int -> bit
2062 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
2066 tlbl=newiTempLabel(NULL);
2067 l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
2068 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
2069 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
2070 IS_AOP_PREG (IC_LEFT (ic)))
2072 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
2077 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
2080 outBitC (IC_RESULT(ic));
2084 size = AOP_SIZE (IC_RESULT (ic));
2087 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2089 emitcode ("cpl", "a");
2090 aopPut (IC_RESULT (ic), "a", offset++);
2095 /* release the aops */
2096 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2097 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2100 /*-----------------------------------------------------------------*/
2101 /* genUminusFloat - unary minus for floating points */
2102 /*-----------------------------------------------------------------*/
2104 genUminusFloat (operand * op, operand * result)
2106 int size, offset = 0;
2109 D (emitcode (";", "genUminusFloat"));
2111 /* for this we just copy and then flip the bit */
2113 size = AOP_SIZE (op) - 1;
2118 aopGet (op, offset, FALSE, FALSE),
2123 l = aopGet (op, offset, FALSE, FALSE);
2126 emitcode ("cpl", "acc.7");
2127 aopPut (result, "a", offset);
2130 /*-----------------------------------------------------------------*/
2131 /* genUminus - unary minus code generation */
2132 /*-----------------------------------------------------------------*/
2134 genUminus (iCode * ic)
2139 D (emitcode (";", "genUminus"));
2142 aopOp (IC_LEFT (ic), ic, FALSE);
2143 aopOp (IC_RESULT (ic), ic, TRUE);
2145 /* if both in bit space then special
2147 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2148 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2151 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2152 emitcode ("cpl", "c");
2153 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2157 optype = operandType (IC_LEFT (ic));
2159 /* if float then do float stuff */
2160 if (IS_FLOAT (optype))
2162 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2166 /* otherwise subtract from zero */
2167 size = AOP_SIZE (IC_LEFT (ic));
2171 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2172 if (!strcmp (l, "a"))
2176 emitcode ("cpl", "a");
2177 emitcode ("addc", "a,#0");
2183 emitcode ("clr", "a");
2184 emitcode ("subb", "a,%s", l);
2186 aopPut (IC_RESULT (ic), "a", offset++);
2189 /* if any remaining bytes in the result */
2190 /* we just need to propagate the sign */
2191 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2193 emitcode ("rlc", "a");
2194 emitcode ("subb", "a,acc");
2196 aopPut (IC_RESULT (ic), "a", offset++);
2200 /* release the aops */
2201 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2202 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2205 /*-----------------------------------------------------------------*/
2206 /* saveRegisters - will look for a call and save the registers */
2207 /*-----------------------------------------------------------------*/
2209 saveRegisters (iCode * lic)
2216 for (ic = lic; ic; ic = ic->next)
2217 if (ic->op == CALL || ic->op == PCALL)
2222 fprintf (stderr, "found parameter push with no function call\n");
2226 /* if the registers have been saved already or don't need to be then
2230 if (IS_SYMOP(IC_LEFT(ic)) &&
2231 (IFFUNC_CALLEESAVES (OP_SYMBOL (IC_LEFT (ic))->type) ||
2232 IFFUNC_ISNAKED (OP_SYM_TYPE (IC_LEFT (ic)))))
2235 /* save the registers in use at this time but skip the
2236 ones for the result */
2237 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2238 mcs51_rUmaskForOp (IC_RESULT(ic)));
2241 if (options.useXstack)
2243 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2244 int nBits = bitVectnBitsOn (rsavebits);
2245 int count = bitVectnBitsOn (rsave);
2249 count = count - nBits + 1;
2250 /* remove all but the first bits as they are pushed all at once */
2251 rsave = bitVectCplAnd (rsave, rsavebits);
2252 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2254 freeBitVect (rsavebits);
2258 regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2259 if (reg->type == REG_BIT)
2261 emitcode ("mov", "a,%s", reg->base);
2265 emitcode ("mov", "a,%s", reg->name);
2267 emitcode ("mov", "r0,%s", spname);
2268 emitcode ("inc", "%s", spname);// allocate before use
2269 emitcode ("movx", "@r0,a");
2270 if (bitVectBitValue (rsave, R0_IDX))
2271 emitcode ("mov", "r0,a");
2273 else if (count != 0)
2275 if (bitVectBitValue (rsave, R0_IDX))
2277 emitcode ("push", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2279 emitcode ("mov", "r0,%s", spname);
2281 emitcode ("add", "a,#%d", count);
2282 emitcode ("mov", "%s,a", spname);
2283 for (i = 0; i < mcs51_nRegs; i++)
2285 if (bitVectBitValue (rsave, i))
2287 regs * reg = REG_WITH_INDEX (i);
2290 emitcode ("pop", "acc");
2291 emitcode ("push", "acc");
2293 else if (reg->type == REG_BIT)
2295 emitcode ("mov", "a,%s", reg->base);
2299 emitcode ("mov", "a,%s", reg->name);
2301 emitcode ("movx", "@r0,a");
2304 emitcode ("inc", "r0");
2308 if (bitVectBitValue (rsave, R0_IDX))
2310 emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2316 bool bits_pushed = FALSE;
2317 for (i = 0; i < mcs51_nRegs; i++)
2319 if (bitVectBitValue (rsave, i))
2321 bits_pushed = pushReg (i, bits_pushed);
2325 freeBitVect (rsave);
2328 /*-----------------------------------------------------------------*/
2329 /* unsaveRegisters - pop the pushed registers */
2330 /*-----------------------------------------------------------------*/
2332 unsaveRegisters (iCode * ic)
2337 /* restore the registers in use at this time but skip the
2338 ones for the result */
2339 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2340 mcs51_rUmaskForOp (IC_RESULT(ic)));
2342 if (options.useXstack)
2344 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2345 int nBits = bitVectnBitsOn (rsavebits);
2346 int count = bitVectnBitsOn (rsave);
2350 count = count - nBits + 1;
2351 /* remove all but the first bits as they are popped all at once */
2352 rsave = bitVectCplAnd (rsave, rsavebits);
2353 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2355 freeBitVect (rsavebits);
2359 regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2360 emitcode ("mov", "r0,%s", spname);
2361 emitcode ("dec", "r0");
2362 emitcode ("movx", "a,@r0");
2363 if (reg->type == REG_BIT)
2365 emitcode ("mov", "%s,a", reg->base);
2369 emitcode ("mov", "%s,a", reg->name);
2371 emitcode ("dec", "%s", spname);
2373 else if (count != 0)
2375 emitcode ("mov", "r0,%s", spname);
2376 for (i = mcs51_nRegs; i >= 0; i--)
2378 if (bitVectBitValue (rsave, i))
2380 regs * reg = REG_WITH_INDEX (i);
2381 emitcode ("dec", "r0");
2382 emitcode ("movx", "a,@r0");
2385 emitcode ("push", "acc");
2387 else if (reg->type == REG_BIT)
2389 emitcode ("mov", "%s,a", reg->base);
2393 emitcode ("mov", "%s,a", reg->name);
2397 emitcode ("mov", "%s,r0", spname);
2398 if (bitVectBitValue (rsave, R0_IDX))
2400 emitcode ("pop", "ar0");
2406 bool bits_popped = FALSE;
2407 for (i = mcs51_nRegs; i >= 0; i--)
2409 if (bitVectBitValue (rsave, i))
2411 bits_popped = popReg (i, bits_popped);
2415 freeBitVect (rsave);
2419 /*-----------------------------------------------------------------*/
2421 /*-----------------------------------------------------------------*/
2423 pushSide (operand * oper, int size)
2428 char *l = aopGet (oper, offset++, FALSE, TRUE);
2429 if (AOP_TYPE (oper) != AOP_REG &&
2430 AOP_TYPE (oper) != AOP_DIR &&
2434 emitcode ("push", "acc");
2438 emitcode ("push", "%s", l);
2443 /*-----------------------------------------------------------------*/
2444 /* assignResultValue - also indicates if acc is in use afterwards */
2445 /*-----------------------------------------------------------------*/
2447 assignResultValue (operand * oper, operand * func)
2450 int size = AOP_SIZE (oper);
2451 bool accuse = FALSE;
2452 bool pushedA = FALSE;
2454 if (func && IS_BIT (OP_SYM_ETYPE (func)))
2460 if ((size > 3) && aopPutUsesAcc (oper, fReturn[offset], offset))
2462 emitcode ("push", "acc");
2467 if ((offset == 3) && pushedA)
2468 emitcode ("pop", "acc");
2469 accuse |= aopPut (oper, fReturn[offset], offset);
2476 /*-----------------------------------------------------------------*/
2477 /* genXpush - pushes onto the external stack */
2478 /*-----------------------------------------------------------------*/
2480 genXpush (iCode * ic)
2482 asmop *aop = newAsmop (0);
2484 int size, offset = 0;
2486 D (emitcode (";", "genXpush"));
2488 aopOp (IC_LEFT (ic), ic, FALSE);
2489 r = getFreePtr (ic, &aop, FALSE);
2491 size = AOP_SIZE (IC_LEFT (ic));
2495 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2496 emitcode ("mov", "%s,%s", r->name, spname);
2497 emitcode ("inc", "%s", spname); // allocate space first
2498 emitcode ("movx", "@%s,a", r->name);
2502 // allocate space first
2503 emitcode ("mov", "%s,%s", r->name, spname);
2505 emitcode ("add", "a,#%d", size);
2506 emitcode ("mov", "%s,a", spname);
2510 MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2511 emitcode ("movx", "@%s,a", r->name);
2512 emitcode ("inc", "%s", r->name);
2516 freeAsmop (NULL, aop, ic, TRUE);
2517 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2520 /*-----------------------------------------------------------------*/
2521 /* genIpush - generate code for pushing this gets a little complex */
2522 /*-----------------------------------------------------------------*/
2524 genIpush (iCode * ic)
2526 int size, offset = 0;
2530 D (emitcode (";", "genIpush"));
2532 /* if this is not a parm push : ie. it is spill push
2533 and spill push is always done on the local stack */
2537 /* and the item is spilt then do nothing */
2538 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2541 aopOp (IC_LEFT (ic), ic, FALSE);
2542 size = AOP_SIZE (IC_LEFT (ic));
2543 /* push it on the stack */
2546 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2552 emitcode ("push", "%s", l);
2557 /* this is a parameter push: in this case we call
2558 the routine to find the call and save those
2559 registers that need to be saved */
2562 /* if use external stack then call the external
2563 stack pushing routine */
2564 if (options.useXstack)
2570 /* then do the push */
2571 aopOp (IC_LEFT (ic), ic, FALSE);
2573 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2574 size = AOP_SIZE (IC_LEFT (ic));
2578 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2579 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2580 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR)
2582 if (strcmp (l, prev) || *l == '@')
2584 emitcode ("push", "acc");
2588 emitcode ("push", "%s", l);
2593 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2596 /*-----------------------------------------------------------------*/
2597 /* genIpop - recover the registers: can happen only for spilling */
2598 /*-----------------------------------------------------------------*/
2600 genIpop (iCode * ic)
2604 D (emitcode (";", "genIpop"));
2606 /* if the temp was not pushed then */
2607 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2610 aopOp (IC_LEFT (ic), ic, FALSE);
2611 size = AOP_SIZE (IC_LEFT (ic));
2612 offset = (size - 1);
2615 emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2619 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2622 /*-----------------------------------------------------------------*/
2623 /* saveRBank - saves an entire register bank on the stack */
2624 /*-----------------------------------------------------------------*/
2626 saveRBank (int bank, iCode * ic, bool pushPsw)
2629 int count = 8 + (pushPsw ? 1 : 0);
2633 if (options.useXstack)
2637 /* Assume r0 is available for use. */
2638 r = REG_WITH_INDEX (R0_IDX);
2643 r = getFreePtr (ic, &aop, FALSE);
2645 // allocate space first
2646 emitcode ("mov", "%s,%s", r->name, spname);
2648 emitcode ("add", "a,#%d", count);
2649 emitcode ("mov", "%s,a", spname);
2652 for (i = 0; i < 8; i++)
2654 if (options.useXstack)
2656 emitcode ("mov", "a,(%s+%d)",
2657 regs8051[i].base, 8 * bank + regs8051[i].offset);
2658 emitcode ("movx", "@%s,a", r->name);
2660 emitcode ("inc", "%s", r->name);
2663 emitcode ("push", "(%s+%d)",
2664 regs8051[i].base, 8 * bank + regs8051[i].offset);
2669 if (options.useXstack)
2671 emitcode ("mov", "a,psw");
2672 emitcode ("movx", "@%s,a", r->name);
2676 emitcode ("push", "psw");
2679 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2684 freeAsmop (NULL, aop, ic, TRUE);
2693 /*-----------------------------------------------------------------*/
2694 /* unsaveRBank - restores the register bank from stack */
2695 /*-----------------------------------------------------------------*/
2697 unsaveRBank (int bank, iCode * ic, bool popPsw)
2703 if (options.useXstack)
2707 /* Assume r0 is available for use. */
2708 r = REG_WITH_INDEX (R0_IDX);;
2713 r = getFreePtr (ic, &aop, FALSE);
2715 emitcode ("mov", "%s,%s", r->name, spname);
2720 if (options.useXstack)
2722 emitcode ("dec", "%s", r->name);
2723 emitcode ("movx", "a,@%s", r->name);
2724 emitcode ("mov", "psw,a");
2728 emitcode ("pop", "psw");
2732 for (i = 7; i >= 0; i--)
2734 if (options.useXstack)
2736 emitcode ("dec", "%s", r->name);
2737 emitcode ("movx", "a,@%s", r->name);
2738 emitcode ("mov", "(%s+%d),a",
2739 regs8051[i].base, 8 * bank + regs8051[i].offset);
2743 emitcode ("pop", "(%s+%d)",
2744 regs8051[i].base, 8 * bank + regs8051[i].offset);
2748 if (options.useXstack)
2750 emitcode ("mov", "%s,%s", spname, r->name);
2755 freeAsmop (NULL, aop, ic, TRUE);
2759 /*-----------------------------------------------------------------*/
2760 /* genSend - gen code for SEND */
2761 /*-----------------------------------------------------------------*/
2762 static void genSend(set *sendSet)
2767 /* first we do all bit parameters */
2768 for (sic = setFirstItem (sendSet); sic;
2769 sic = setNextItem (sendSet))
2771 if (sic->argreg > 12)
2773 int bit = sic->argreg-13;
2775 aopOp (IC_LEFT (sic), sic, FALSE);
2777 /* if left is a literal then
2778 we know what the value is */
2779 if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2781 if (((int) operandLitValue (IC_LEFT (sic))))
2782 emitcode ("setb", "b[%d]", bit);
2784 emitcode ("clr", "b[%d]", bit);
2789 toCarry (IC_LEFT (sic));
2790 emitcode ("mov", "b[%d],c", bit);
2795 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2801 saveRegisters (setFirstItem (sendSet));
2802 emitcode ("mov", "bits,b");
2805 /* then we do all other parameters */
2806 for (sic = setFirstItem (sendSet); sic;
2807 sic = setNextItem (sendSet))
2809 if (sic->argreg <= 12)
2811 int size, offset = 0;
2812 aopOp (IC_LEFT (sic), sic, FALSE);
2813 size = AOP_SIZE (IC_LEFT (sic));
2815 if (sic->argreg == 1)
2819 char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2820 if (strcmp (l, fReturn[offset]))
2822 emitcode ("mov", "%s,%s", fReturn[offset], l);
2831 emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2832 aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2836 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2841 /*-----------------------------------------------------------------*/
2842 /* selectRegBank - emit code to select the register bank */
2843 /*-----------------------------------------------------------------*/
2845 selectRegBank (short bank, bool keepFlags)
2847 /* if f.e. result is in carry */
2850 emitcode ("anl", "psw,#0xE7");
2852 emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2856 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2860 /*-----------------------------------------------------------------*/
2861 /* genCall - generates a call statement */
2862 /*-----------------------------------------------------------------*/
2864 genCall (iCode * ic)
2868 // bool restoreBank = FALSE;
2869 bool swapBanks = FALSE;
2870 bool accuse = FALSE;
2871 bool accPushed = FALSE;
2872 bool resultInF0 = FALSE;
2873 bool assignResultGenerated = FALSE;
2875 D (emitcode (";", "genCall"));
2877 dtype = operandType (IC_LEFT (ic));
2878 etype = getSpec(dtype);
2879 /* if send set is not empty then assign */
2882 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2883 genSend(reverseSet(_G.sendSet));
2885 genSend(_G.sendSet);
2890 /* if we are calling a not _naked function that is not using
2891 the same register bank then we need to save the
2892 destination registers on the stack */
2893 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2894 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2895 !IFFUNC_ISISR (dtype))
2900 /* if caller saves & we have not saved then */
2906 emitcode ("mov", "psw,#0x%02x",
2907 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2911 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2913 if (IFFUNC_CALLEESAVES(dtype))
2915 werror (E_BANKED_WITH_CALLEESAVES);
2919 char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2920 OP_SYMBOL (IC_LEFT (ic))->rname :
2921 OP_SYMBOL (IC_LEFT (ic))->name);
2923 emitcode ("mov", "r0,#%s", l);
2924 emitcode ("mov", "r1,#(%s >> 8)", l);
2925 emitcode ("mov", "r2,#(%s >> 16)", l);
2926 emitcode ("lcall", "__sdcc_banked_call");
2931 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2932 OP_SYMBOL (IC_LEFT (ic))->rname :
2933 OP_SYMBOL (IC_LEFT (ic))->name));
2938 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2941 /* if we need assign a result value */
2942 if ((IS_ITEMP (IC_RESULT (ic)) &&
2943 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2944 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2945 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2946 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2947 IS_TRUE_SYMOP (IC_RESULT (ic)))
2951 aopOp (IC_RESULT (ic), ic, FALSE);
2954 accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2955 assignResultGenerated = TRUE;
2957 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2960 /* adjust the stack for parameters if required */
2964 if (ic->parmBytes > 3)
2968 emitcode ("push", "acc");
2971 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2972 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2973 !assignResultGenerated)
2975 emitcode ("mov", "F0,c");
2979 emitcode ("mov", "a,%s", spname);
2980 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2981 emitcode ("mov", "%s,a", spname);
2983 /* unsaveRegisters from xstack needs acc, but */
2984 /* unsaveRegisters from stack needs this popped */
2985 if (accPushed && !options.useXstack)
2987 emitcode ("pop", "acc");
2992 for (i = 0; i < ic->parmBytes; i++)
2993 emitcode ("dec", "%s", spname);
2996 /* if we had saved some registers then unsave them */
2997 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2999 if (accuse && !accPushed && options.useXstack)
3001 /* xstack needs acc, but doesn't touch normal stack */
3002 emitcode ("push", "acc");
3005 unsaveRegisters (ic);
3008 // /* if register bank was saved then pop them */
3010 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
3012 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
3015 emitcode ("mov", "c,F0");
3017 aopOp (IC_RESULT (ic), ic, FALSE);
3018 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3019 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3023 emitcode ("pop", "acc");
3026 /*-----------------------------------------------------------------*/
3027 /* genPcall - generates a call by pointer statement */
3028 /*-----------------------------------------------------------------*/
3030 genPcall (iCode * ic)
3034 symbol *rlbl = newiTempLabel (NULL);
3035 // bool restoreBank=FALSE;
3036 bool swapBanks = FALSE;
3037 bool resultInF0 = FALSE;
3039 D (emitcode (";", "genPcall"));
3041 dtype = operandType (IC_LEFT (ic))->next;
3042 etype = getSpec(dtype);
3043 /* if caller saves & we have not saved then */
3047 /* if we are calling a not _naked function that is not using
3048 the same register bank then we need to save the
3049 destination registers on the stack */
3050 if (currFunc && dtype && !IFFUNC_ISNAKED (dtype) &&
3051 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
3052 !IFFUNC_ISISR (dtype))
3054 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3055 // restoreBank=TRUE;
3057 // need caution message to user here
3060 if (IS_LITERAL (etype))
3062 /* if send set is not empty then assign */
3065 genSend(reverseSet(_G.sendSet));
3071 emitcode ("mov", "psw,#0x%02x",
3072 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3075 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT (getSpec(dtype)))
3077 if (IFFUNC_CALLEESAVES (dtype))
3079 werror (E_BANKED_WITH_CALLEESAVES);
3083 char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
3085 emitcode ("mov", "r0,#%s", l);
3086 emitcode ("mov", "r1,#(%s >> 8)", l);
3087 emitcode ("mov", "r2,#(%s >> 16)", l);
3088 emitcode ("lcall", "__sdcc_banked_call");
3093 emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
3098 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT (getSpec(dtype)))
3100 if (IFFUNC_CALLEESAVES (dtype))
3102 werror (E_BANKED_WITH_CALLEESAVES);
3106 aopOp (IC_LEFT (ic), ic, FALSE);
3110 /* what if aopGet needs r0 or r1 ??? */
3111 emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3112 emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3113 emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3117 int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
3118 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3119 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3120 emitcode ("mov", "0x%02x,%s", reg, aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3123 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3125 /* if send set is not empty then assign */
3128 genSend(reverseSet(_G.sendSet));
3134 emitcode ("mov", "psw,#0x%02x",
3135 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3139 emitcode ("lcall", "__sdcc_banked_call");
3142 else if (_G.sendSet)
3144 /* push the return address on to the stack */
3145 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
3146 emitcode ("push", "acc");
3147 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
3148 emitcode ("push", "acc");
3150 /* now push the calling address */
3151 aopOp (IC_LEFT (ic), ic, FALSE);
3153 pushSide (IC_LEFT (ic), FPTRSIZE);
3155 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3157 /* if send set is not empty the assign */
3160 genSend(reverseSet(_G.sendSet));
3166 emitcode ("mov", "psw,#0x%02x",
3167 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3171 emitcode ("ret", "");
3174 else /* the send set is empty */
3177 /* now get the calling address into dptr */
3178 aopOp (IC_LEFT (ic), ic, FALSE);
3180 l = aopGet (IC_LEFT (ic), 0, FALSE, FALSE);
3181 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3183 emitcode ("mov", "r0,%s", l);
3184 l = aopGet (IC_LEFT (ic), 1, FALSE, FALSE);
3185 emitcode ("mov", "dph,%s", l);
3186 emitcode ("mov", "dpl,r0");
3190 emitcode ("mov", "dpl,%s", l);
3191 l = aopGet (IC_LEFT (ic), 1, FALSE, FALSE);
3192 emitcode ("mov", "dph,%s", l);
3195 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3199 emitcode ("mov", "psw,#0x%02x",
3200 ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3204 emitcode ("lcall", "__sdcc_call_dptr");
3209 selectRegBank (FUNC_REGBANK (currFunc->type), IS_BIT (etype));
3212 /* if we need assign a result value */
3213 if ((IS_ITEMP (IC_RESULT (ic)) &&
3214 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3215 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3216 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3217 IS_TRUE_SYMOP (IC_RESULT (ic)))
3221 aopOp (IC_RESULT (ic), ic, FALSE);
3224 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3226 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3229 /* adjust the stack for parameters if required */
3233 if (ic->parmBytes > 3)
3235 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3236 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3238 emitcode ("mov", "F0,c");
3242 emitcode ("mov", "a,%s", spname);
3243 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3244 emitcode ("mov", "%s,a", spname);
3247 for (i = 0; i < ic->parmBytes; i++)
3248 emitcode ("dec", "%s", spname);
3251 // /* if register bank was saved then unsave them */
3253 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3255 /* if we had saved some registers then unsave them */
3256 if (ic->regsSaved && !IFFUNC_CALLEESAVES (dtype))
3257 unsaveRegisters (ic);
3259 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3262 emitcode ("mov", "c,F0");
3264 aopOp (IC_RESULT (ic), ic, FALSE);
3265 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3266 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3270 /*-----------------------------------------------------------------*/
3271 /* resultRemat - result is rematerializable */
3272 /*-----------------------------------------------------------------*/
3274 resultRemat (iCode * ic)
3276 if (SKIP_IC (ic) || ic->op == IFX)
3279 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3281 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3282 if (sym->remat && !POINTER_SET (ic))
3289 /*-----------------------------------------------------------------*/
3290 /* inExcludeList - return 1 if the string is in exclude Reg list */
3291 /*-----------------------------------------------------------------*/
3293 regsCmp(void *p1, void *p2)
3295 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3299 inExcludeList (char *s)
3301 const char *p = setFirstItem(options.excludeRegsSet);
3303 if (p == NULL || STRCASECMP(p, "none") == 0)
3307 return isinSetWith(options.excludeRegsSet, s, regsCmp);
3310 /*-----------------------------------------------------------------*/
3311 /* genFunction - generated code for function entry */
3312 /*-----------------------------------------------------------------*/
3314 genFunction (iCode * ic)
3316 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3318 bool switchedPSW = FALSE;
3319 int calleesaves_saved_register = -1;
3320 int stackAdjust = sym->stack;
3321 int accIsFree = sym->recvSize < 4;
3322 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3323 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3326 /* create the function header */
3327 emitcode (";", "-----------------------------------------");
3328 emitcode (";", " function %s", sym->name);
3329 emitcode (";", "-----------------------------------------");
3331 emitcode ("", "%s:", sym->rname);
3332 lineCurr->isLabel = 1;
3333 ftype = operandType (IC_LEFT (ic));
3334 _G.currentFunc = sym;
3336 if (IFFUNC_ISNAKED(ftype))
3338 emitcode(";", "naked function: no prologue.");
3342 /* here we need to generate the equates for the
3343 register bank if required */
3344 if (FUNC_REGBANK (ftype) != rbank)
3348 rbank = FUNC_REGBANK (ftype);
3349 for (i = 0; i < mcs51_nRegs; i++)
3351 if (regs8051[i].type != REG_BIT)
3353 if (strcmp (regs8051[i].base, "0") == 0)
3354 emitcode ("", "%s = 0x%02x",
3356 8 * rbank + regs8051[i].offset);
3358 emitcode ("", "%s = %s + 0x%02x",
3361 8 * rbank + regs8051[i].offset);
3366 /* if this is an interrupt service routine then
3367 save acc, b, dpl, dph */
3368 if (IFFUNC_ISISR (sym->type))
3372 rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), sym->regsUsed);
3373 if (IFFUNC_HASFCALL(sym->type) || !bitVectIsZero (rsavebits))
3375 emitcode ("push", "bits");
3378 freeBitVect (rsavebits);
3380 if (!inExcludeList ("acc"))
3381 emitcode ("push", "acc");
3382 if (!inExcludeList ("b"))
3383 emitcode ("push", "b");
3384 if (!inExcludeList ("dpl"))
3385 emitcode ("push", "dpl");
3386 if (!inExcludeList ("dph"))
3387 emitcode ("push", "dph");
3388 /* if this isr has no bank i.e. is going to
3389 run with bank 0 , then we need to save more
3391 if (!FUNC_REGBANK (sym->type))
3395 /* if this function does not call any other
3396 function then we can be economical and
3397 save only those registers that are used */
3398 if (!IFFUNC_HASFCALL(sym->type))
3400 /* if any registers used */
3403 /* save the registers used */
3404 for (i = 0; i < sym->regsUsed->size; i++)
3406 if (bitVectBitValue (sym->regsUsed, i))
3413 /* this function has a function call. We cannot
3414 determine register usage so we will have to push the
3416 saveRBank (0, ic, FALSE);
3417 if (options.parms_in_bank1) {
3418 for (i=0; i < 8 ; i++ ) {
3419 emitcode ("push","%s",rb1regs[i]);
3426 /* This ISR uses a non-zero bank.
3428 * We assume that the bank is available for our
3431 * However, if this ISR calls a function which uses some
3432 * other bank, we must save that bank entirely.
3434 unsigned long banksToSave = 0;
3436 if (IFFUNC_HASFCALL(sym->type))
3439 #define MAX_REGISTER_BANKS 4
3444 for (i = ic; i; i = i->next)
3446 if (i->op == ENDFUNCTION)
3448 /* we got to the end OK. */
3456 dtype = operandType (IC_LEFT(i));
3458 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3460 /* Mark this bank for saving. */
3461 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3463 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3467 banksToSave |= (1 << FUNC_REGBANK(dtype));
3470 /* And note that we don't need to do it in
3478 /* This is a mess; we have no idea what
3479 * register bank the called function might
3482 * The only thing I can think of to do is
3483 * throw a warning and hope.
3485 werror(W_FUNCPTR_IN_USING_ISR);
3489 if (banksToSave && options.useXstack)
3491 /* Since we aren't passing it an ic,
3492 * saveRBank will assume r0 is available to abuse.
3494 * So switch to our (trashable) bank now, so
3495 * the caller's R0 isn't trashed.
3497 emitcode ("push", "psw");
3498 emitcode ("mov", "psw,#0x%02x",
3499 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3503 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3505 if (banksToSave & (1 << ix))
3507 saveRBank(ix, NULL, FALSE);
3511 // TODO: this needs a closer look
3512 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3515 /* Set the register bank to the desired value if nothing else */
3516 /* has done so yet. */
3519 emitcode ("push", "psw");
3520 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3525 /* This is a non-ISR function. The caller has already switched register */
3526 /* banks, if necessary, so just handle the callee-saves option. */
3528 /* if callee-save to be used for this function
3529 then save the registers being used in this function */
3530 if (IFFUNC_CALLEESAVES(sym->type))
3534 /* if any registers used */
3537 bool bits_pushed = FALSE;
3538 /* save the registers used */
3539 for (i = 0; i < sym->regsUsed->size; i++)
3541 if (bitVectBitValue (sym->regsUsed, i))
3543 /* remember one saved register for later usage */
3544 if (calleesaves_saved_register < 0)
3545 calleesaves_saved_register = i;
3546 bits_pushed = pushReg (i, bits_pushed);
3556 if (options.useXstack)
3558 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3560 emitcode ("mov", "r0,%s", spname);
3561 emitcode ("inc", "%s", spname);
3562 emitcode ("xch", "a,_bpx");
3563 emitcode ("movx", "@r0,a");
3564 emitcode ("inc", "r0");
3565 emitcode ("mov", "a,r0");
3566 emitcode ("xch", "a,_bpx");
3570 emitcode ("push", "_bp"); /* save the callers stack */
3571 emitcode ("mov", "_bp,sp");
3576 if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3578 /* set up the stack */
3579 emitcode ("push", "_bp"); /* save the callers stack */
3580 emitcode ("mov", "_bp,sp");
3585 /* For some cases it is worthwhile to perform a RECEIVE iCode */
3586 /* before setting up the stack frame completely. */
3587 if (ric && ric->argreg == 1 && IC_RESULT (ric))
3589 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3593 if (rsym && rsym->regType == REG_CND)
3595 if (rsym && (rsym->accuse || rsym->ruonly))
3597 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3598 rsym = rsym->usl.spillLoc;
3601 /* If the RECEIVE operand immediately spills to the first entry on the */
3602 /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3603 /* rather than the usual @r0/r1 machinations. */
3604 if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3608 _G.current_iCode = ric;
3609 D(emitcode (";", "genReceive"));
3610 for (ofs=0; ofs < sym->recvSize; ofs++)
3612 if (!strcmp (fReturn[ofs], "a"))
3613 emitcode ("push", "acc");
3615 emitcode ("push", fReturn[ofs]);
3617 stackAdjust -= sym->recvSize;
3620 assert (stackAdjust>=0);
3623 _G.current_iCode = ic;
3627 /* If the RECEIVE operand is 4 registers, we can do the moves now */
3628 /* to free up the accumulator. */
3629 else if (rsym && rsym->nRegs && sym->recvSize == 4)
3633 _G.current_iCode = ric;
3634 D(emitcode (";", "genReceive"));
3635 for (ofs=0; ofs < sym->recvSize; ofs++)
3637 emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3639 _G.current_iCode = ic;
3645 /* adjust the stack for the function */
3648 int i = stackAdjust;
3650 werror (W_STACK_OVERFLOW, sym->name);
3652 if (i > 3 && accIsFree)
3654 emitcode ("mov", "a,sp");
3655 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3656 emitcode ("mov", "sp,a");
3660 /* The accumulator is not free, so we will need another register */
3661 /* to clobber. No need to worry about a possible conflict with */
3662 /* the above early RECEIVE optimizations since they would have */
3663 /* freed the accumulator if they were generated. */
3665 if (IFFUNC_CALLEESAVES(sym->type))
3667 /* if it's a callee-saves function we need a saved register */
3668 if (calleesaves_saved_register >= 0)
3670 emitcode ("mov", "%s,a", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3671 emitcode ("mov", "a,sp");
3672 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3673 emitcode ("mov", "sp,a");
3674 emitcode ("mov", "a,%s", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3677 /* do it the hard way */
3679 emitcode ("inc", "sp");
3683 /* not callee-saves, we can clobber r0 */
3684 emitcode ("mov", "r0,a");
3685 emitcode ("mov", "a,sp");
3686 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3687 emitcode ("mov", "sp,a");
3688 emitcode ("mov", "a,r0");
3693 emitcode ("inc", "sp");
3698 char i = ((char) sym->xstack & 0xff);
3700 if (i > 3 && accIsFree)
3702 emitcode ("mov", "a,_spx");
3703 emitcode ("add", "a,#0x%02x", i & 0xff);
3704 emitcode ("mov", "_spx,a");
3708 emitcode ("push", "acc");
3709 emitcode ("mov", "a,_spx");
3710 emitcode ("add", "a,#0x%02x", i & 0xff);
3711 emitcode ("mov", "_spx,a");
3712 emitcode ("pop", "acc");
3717 emitcode ("inc", "_spx");
3721 /* if critical function then turn interrupts off */
3722 if (IFFUNC_ISCRITICAL (ftype))
3724 symbol *tlbl = newiTempLabel (NULL);
3725 emitcode ("setb", "c");
3726 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3727 emitcode ("clr", "c");
3729 emitcode ("push", "psw"); /* save old ea via c in psw */
3733 /*-----------------------------------------------------------------*/
3734 /* genEndFunction - generates epilogue for functions */
3735 /*-----------------------------------------------------------------*/
3737 genEndFunction (iCode * ic)
3739 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3740 lineNode *lnp = lineCurr;
3742 bitVect *regsUsedPrologue;
3743 bitVect *regsUnneeded;
3746 _G.currentFunc = NULL;
3747 if (IFFUNC_ISNAKED(sym->type))
3749 emitcode(";", "naked function: no epilogue.");
3750 if (options.debug && currFunc)
3751 debugFile->writeEndFunction (currFunc, ic, 0);
3755 if (IFFUNC_ISCRITICAL (sym->type))
3757 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3759 emitcode ("rlc", "a"); /* save c in a */
3760 emitcode ("pop", "psw"); /* restore ea via c in psw */
3761 emitcode ("mov", "ea,c");
3762 emitcode ("rrc", "a"); /* restore c from a */
3766 emitcode ("pop", "psw"); /* restore ea via c in psw */
3767 emitcode ("mov", "ea,c");
3771 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3773 if (options.useXstack)
3777 emitcode ("mov", "sp,_bp");
3778 emitcode ("pop", "_bp");
3780 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3782 emitcode ("xch", "a,_bpx");
3783 emitcode ("mov", "r0,a");
3784 emitcode ("dec", "r0");
3785 emitcode ("movx", "a,@r0");
3786 emitcode ("xch", "a,_bpx");
3787 emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3790 else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3793 emitcode ("mov", "sp,_bp");
3794 emitcode ("pop", "_bp");
3798 /* restore the register bank */
3799 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3801 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3802 || !options.useXstack)
3804 /* Special case of ISR using non-zero bank with useXstack
3807 emitcode ("pop", "psw");
3811 if (IFFUNC_ISISR (sym->type))
3815 /* now we need to restore the registers */
3816 /* if this isr has no bank i.e. is going to
3817 run with bank 0 , then we need to save more
3819 if (!FUNC_REGBANK (sym->type))
3822 /* if this function does not call any other
3823 function then we can be economical and
3824 save only those registers that are used */
3825 if (!IFFUNC_HASFCALL(sym->type))
3827 /* if any registers used */
3830 /* save the registers used */
3831 for (i = sym->regsUsed->size; i >= 0; i--)
3833 if (bitVectBitValue (sym->regsUsed, i))
3840 if (options.parms_in_bank1) {
3841 for (i = 7 ; i >= 0 ; i-- ) {
3842 emitcode ("pop","%s",rb1regs[i]);
3845 /* this function has a function call. We cannot
3846 determine register usage so we will have to pop the
3848 unsaveRBank (0, ic, FALSE);
3853 /* This ISR uses a non-zero bank.
3855 * Restore any register banks saved by genFunction
3858 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3861 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3863 if (savedBanks & (1 << ix))
3865 unsaveRBank(ix, NULL, FALSE);
3869 if (options.useXstack)
3871 /* Restore bank AFTER calling unsaveRBank,
3872 * since it can trash r0.
3874 emitcode ("pop", "psw");
3878 if (!inExcludeList ("dph"))
3879 emitcode ("pop", "dph");
3880 if (!inExcludeList ("dpl"))
3881 emitcode ("pop", "dpl");
3882 if (!inExcludeList ("b"))
3883 emitcode ("pop", "b");
3884 if (!inExcludeList ("acc"))
3885 emitcode ("pop", "acc");
3887 rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), sym->regsUsed);
3888 if (IFFUNC_HASFCALL(sym->type) || !bitVectIsZero (rsavebits))
3889 emitcode ("pop", "bits");
3890 freeBitVect (rsavebits);
3892 /* if debug then send end of function */
3893 if (options.debug && currFunc)
3895 debugFile->writeEndFunction (currFunc, ic, 1);
3898 emitcode ("reti", "");
3902 if (IFFUNC_CALLEESAVES(sym->type))
3906 /* if any registers used */
3909 /* save the registers used */
3910 for (i = sym->regsUsed->size; i >= 0; i--)
3912 if (bitVectBitValue (sym->regsUsed, i) ||
3913 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3914 emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
3917 else if (mcs51_ptrRegReq)
3919 emitcode ("pop", "%s", REG_WITH_INDEX (R1_IDX)->dname);
3920 emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
3925 /* if debug then send end of function */
3926 if (options.debug && currFunc)
3928 debugFile->writeEndFunction (currFunc, ic, 1);
3931 if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3933 emitcode ("ljmp", "__sdcc_banked_ret");
3937 emitcode ("ret", "");
3941 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3944 /* If this was an interrupt handler using bank 0 that called another */
3945 /* function, then all registers must be saved; nothing to optimized. */
3946 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3947 && !FUNC_REGBANK(sym->type))
3950 /* There are no push/pops to optimize if not callee-saves or ISR */
3951 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3954 /* If there were stack parameters, we cannot optimize without also */
3955 /* fixing all of the stack offsets; this is too dificult to consider. */
3956 if (FUNC_HASSTACKPARM(sym->type))
3959 /* Compute the registers actually used */
3960 regsUsed = newBitVect (mcs51_nRegs);
3961 regsUsedPrologue = newBitVect (mcs51_nRegs);
3964 if (lnp->ic && lnp->ic->op == FUNCTION)
3965 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3967 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3969 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3970 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3977 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3978 && !bitVectBitValue (regsUsed, CND_IDX))
3980 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3981 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3982 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3983 bitVectUnSetBit (regsUsed, CND_IDX);
3986 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3988 /* If this was an interrupt handler that called another function */
3989 /* function, then assume A, B, DPH, & DPL may be modified by it. */
3990 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3992 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3993 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3994 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3995 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3996 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3999 /* Remove the unneeded push/pops */
4000 regsUnneeded = newBitVect (mcs51_nRegs);
4003 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
4005 if (!strncmp(lnp->line, "push", 4))
4007 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
4008 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4010 connectLine (lnp->prev, lnp->next);
4011 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4014 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
4016 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
4017 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4019 connectLine (lnp->prev, lnp->next);
4020 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4027 for (idx = 0; idx < regsUnneeded->size; idx++)
4028 if (bitVectBitValue (regsUnneeded, idx))
4029 emitcode (";", "eliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
4031 freeBitVect (regsUnneeded);
4032 freeBitVect (regsUsed);
4033 freeBitVect (regsUsedPrologue);
4036 /*-----------------------------------------------------------------*/
4037 /* genRet - generate code for return statement */
4038 /*-----------------------------------------------------------------*/
4042 int size, offset = 0, pushed = 0;
4044 D (emitcode (";", "genRet"));
4046 /* if we have no return value then
4047 just generate the "ret" */
4051 /* we have something to return then
4052 move the return value into place */
4053 aopOp (IC_LEFT (ic), ic, FALSE);
4054 size = AOP_SIZE (IC_LEFT (ic));
4056 if (IS_BIT(_G.currentFunc->etype))
4058 if (!(IS_SYMOP (IC_LEFT (ic)) && OP_SYMBOL (IC_LEFT (ic))->ruonly))
4059 toCarry (IC_LEFT (ic));
4066 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
4069 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
4070 emitcode ("push", "%s", l);
4075 l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
4076 if (strcmp (fReturn[offset], l))
4077 emitcode ("mov", "%s,%s", fReturn[offset++], l);
4084 if (strcmp (fReturn[pushed], "a"))
4085 emitcode ("pop", fReturn[pushed]);
4087 emitcode ("pop", "acc");
4090 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
4093 /* generate a jump to the return label
4094 if the next is not the return statement */
4095 if (!(ic->next && ic->next->op == LABEL &&
4096 IC_LABEL (ic->next) == returnLabel))
4098 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
4102 /*-----------------------------------------------------------------*/
4103 /* genLabel - generates a label */
4104 /*-----------------------------------------------------------------*/
4106 genLabel (iCode * ic)
4108 /* special case never generate */
4109 if (IC_LABEL (ic) == entryLabel)
4112 emitLabel (IC_LABEL (ic));
4115 /*-----------------------------------------------------------------*/
4116 /* genGoto - generates a ljmp */
4117 /*-----------------------------------------------------------------*/
4119 genGoto (iCode * ic)
4121 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
4124 /*-----------------------------------------------------------------*/
4125 /* findLabelBackwards: walks back through the iCode chain looking */
4126 /* for the given label. Returns number of iCode instructions */
4127 /* between that label and given ic. */
4128 /* Returns zero if label not found. */
4129 /*-----------------------------------------------------------------*/
4131 findLabelBackwards (iCode * ic, int key)
4140 /* If we have any pushes or pops, we cannot predict the distance.
4141 I don't like this at all, this should be dealt with in the
4143 if (ic->op == IPUSH || ic->op == IPOP) {
4147 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4156 /*-----------------------------------------------------------------*/
4157 /* genPlusIncr :- does addition with increment if possible */
4158 /*-----------------------------------------------------------------*/
4160 genPlusIncr (iCode * ic)
4162 unsigned int icount;
4163 unsigned int size = getDataSize (IC_RESULT (ic));
4165 /* will try to generate an increment */
4166 /* if the right side is not a literal
4168 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4171 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4173 D(emitcode (";","genPlusIncr"));
4175 /* if increment >=16 bits in register or direct space */
4176 if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG ||
4177 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4178 (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4179 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4180 !isOperandVolatile (IC_RESULT (ic), FALSE) &&
4188 /* If the next instruction is a goto and the goto target
4189 * is < 10 instructions previous to this, we can generate
4190 * jumps straight to that target.
4192 if (ic->next && ic->next->op == GOTO
4193 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4194 && labelRange <= 10)
4196 D (emitcode (";", "tail increment optimized (range %d)", labelRange));
4197 tlbl = IC_LABEL (ic->next);
4202 tlbl = newiTempLabel (NULL);
4205 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4206 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4207 IS_AOP_PREG (IC_RESULT (ic)))
4208 emitcode ("cjne", "%s,#0x00,%05d$",
4209 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4213 emitcode ("clr", "a");
4214 emitcode ("cjne", "a,%s,%05d$",
4215 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4219 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4222 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4223 IS_AOP_PREG (IC_RESULT (ic)))
4224 emitcode ("cjne", "%s,#0x00,%05d$",
4225 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4228 emitcode ("cjne", "a,%s,%05d$",
4229 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4232 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4236 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4237 IS_AOP_PREG (IC_RESULT (ic)))
4238 emitcode ("cjne", "%s,#0x00,%05d$",
4239 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4243 emitcode ("cjne", "a,%s,%05d$",
4244 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4247 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4257 /* if result is dptr */
4258 if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
4259 (AOP_SIZE (IC_RESULT (ic)) == 2) &&
4260 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
4261 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
4263 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4269 if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
4272 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0);
4273 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1);
4275 emitcode ("inc", "dptr");
4280 /* if the literal value of the right hand side
4281 is greater than 4 then it is not worth it */
4285 /* if the sizes are greater than 1 then we cannot */
4286 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4287 AOP_SIZE (IC_LEFT (ic)) > 1)
4290 /* we can if the aops of the left & result match or
4291 if they are in registers and the registers are the
4293 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4297 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4298 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4299 aopPut (IC_RESULT (ic), "a", 0);
4305 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4314 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4315 emitcode ("inc", "a");
4316 aopPut (IC_RESULT (ic), "a", 0);
4323 /*-----------------------------------------------------------------*/
4324 /* outBitAcc - output a bit in acc */
4325 /*-----------------------------------------------------------------*/
4327 outBitAcc (operand * result)
4329 symbol *tlbl = newiTempLabel (NULL);
4330 /* if the result is a bit */
4331 if (AOP_TYPE (result) == AOP_CRY)
4333 aopPut (result, "a", 0);
4337 emitcode ("jz", "%05d$", tlbl->key + 100);
4338 emitcode ("mov", "a,%s", one);
4344 /*-----------------------------------------------------------------*/
4345 /* genPlusBits - generates code for addition of two bits */
4346 /*-----------------------------------------------------------------*/
4348 genPlusBits (iCode * ic)
4350 D (emitcode (";", "genPlusBits"));
4352 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4353 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4355 symbol *lbl = newiTempLabel (NULL);
4356 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4357 emitcode ("cpl", "c");
4359 outBitC (IC_RESULT (ic));
4363 emitcode ("clr", "a");
4364 emitcode ("rlc", "a");
4365 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4366 emitcode ("addc", "a,%s", zero);
4367 outAcc (IC_RESULT (ic));
4372 /* This is the original version of this code.
4374 * This is being kept around for reference,
4375 * because I am not entirely sure I got it right...
4378 adjustArithmeticResult (iCode * ic)
4380 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4381 AOP_SIZE (IC_LEFT (ic)) == 3 &&
4382 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4383 aopPut (IC_RESULT (ic),
4384 aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4387 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4388 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4389 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4390 aopPut (IC_RESULT (ic),
4391 aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4394 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4395 AOP_SIZE (IC_LEFT (ic)) < 3 &&
4396 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4397 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4398 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4401 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4402 aopPut (IC_RESULT (ic), buffer, 2);
4406 /* This is the pure and virtuous version of this code.
4407 * I'm pretty certain it's right, but not enough to toss the old
4411 adjustArithmeticResult (iCode * ic)
4413 if (opIsGptr (IC_RESULT (ic)) &&
4414 opIsGptr (IC_LEFT (ic)) &&
4415 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4417 aopPut (IC_RESULT (ic),
4418 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4422 if (opIsGptr (IC_RESULT (ic)) &&
4423 opIsGptr (IC_RIGHT (ic)) &&
4424 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4426 aopPut (IC_RESULT (ic),
4427 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4431 if (opIsGptr (IC_RESULT (ic)) &&
4432 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4433 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4434 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4435 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4438 SNPRINTF (buffer, sizeof(buffer),
4439 "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4440 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4445 /*-----------------------------------------------------------------*/
4446 /* genPlus - generates code for addition */
4447 /*-----------------------------------------------------------------*/
4449 genPlus (iCode * ic)
4451 int size, offset = 0;
4454 bool swappedLR = FALSE;
4455 operand *leftOp, *rightOp;
4458 D (emitcode (";", "genPlus"));
4460 /* special cases :- */
4462 aopOp (IC_LEFT (ic), ic, FALSE);
4463 aopOp (IC_RIGHT (ic), ic, FALSE);
4464 aopOp (IC_RESULT (ic), ic, TRUE);
4466 /* if literal, literal on the right or
4467 if left requires ACC or right is already
4469 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4470 (AOP_NEEDSACC (IC_LEFT (ic))) ||
4471 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4473 operand *t = IC_RIGHT (ic);
4474 IC_RIGHT (ic) = IC_LEFT (ic);
4479 /* if both left & right are in bit
4481 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4482 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4488 /* if left in bit space & right literal */
4489 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4490 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4492 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4493 /* if result in bit space */
4494 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4496 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4497 emitcode ("cpl", "c");
4498 outBitC (IC_RESULT (ic));
4502 size = getDataSize (IC_RESULT (ic));
4505 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4506 emitcode ("addc", "a,%s", zero);
4507 aopPut (IC_RESULT (ic), "a", offset++);
4513 /* if I can do an increment instead
4514 of add then GOOD for ME */
4515 if (genPlusIncr (ic) == TRUE)
4518 size = getDataSize (IC_RESULT (ic));
4519 leftOp = IC_LEFT(ic);
4520 rightOp = IC_RIGHT(ic);
4523 /* if this is an add for an array access
4524 at a 256 byte boundary */
4526 && AOP_TYPE (op) == AOP_IMMD
4528 && IS_SPEC (OP_SYM_ETYPE (op))
4529 && SPEC_ABSA (OP_SYM_ETYPE (op))
4530 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4533 D(emitcode (";", "genPlus aligned array"));
4534 aopPut (IC_RESULT (ic),
4535 aopGet (rightOp, 0, FALSE, FALSE),
4538 if( 1 == getDataSize (IC_RIGHT (ic)) )
4540 aopPut (IC_RESULT (ic),
4541 aopGet (leftOp, 1, FALSE, FALSE),
4546 MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4547 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4548 aopPut (IC_RESULT (ic), "a", 1);
4553 /* if the lower bytes of a literal are zero skip the addition */
4554 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4556 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4557 (skip_bytes+1 < size))
4562 D(emitcode (";", "genPlus shortcut"));
4567 if( offset >= skip_bytes )
4569 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4572 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4574 emitcode("xch", "a,b");
4575 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4576 emitcode (add, "a,b");
4579 else if (aopGetUsesAcc (leftOp, offset))
4581 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4582 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4586 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4587 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4589 aopPut (IC_RESULT (ic), "a", offset);
4590 add = "addc"; /* further adds must propagate carry */
4594 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4595 isOperandVolatile (IC_RESULT (ic), FALSE))
4598 aopPut (IC_RESULT (ic),
4599 aopGet (leftOp, offset, FALSE, FALSE),
4606 adjustArithmeticResult (ic);
4609 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4612 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4613 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4617 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4618 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4622 /*-----------------------------------------------------------------*/
4623 /* genMinusDec :- does subtraction with decrement if possible */
4624 /*-----------------------------------------------------------------*/
4626 genMinusDec (iCode * ic)
4628 unsigned int icount;
4629 unsigned int size = getDataSize (IC_RESULT (ic));
4631 /* will try to generate an increment */
4632 /* if the right side is not a literal
4634 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4637 /* if the literal value of the right hand side
4638 is greater than 4 then it is not worth it */
4639 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4642 D (emitcode (";", "genMinusDec"));
4644 /* if decrement >=16 bits in register or direct space */
4645 if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG ||
4646 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4647 (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4648 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4656 /* If the next instruction is a goto and the goto target
4657 * is <= 10 instructions previous to this, we can generate
4658 * jumps straight to that target.
4660 if (ic->next && ic->next->op == GOTO
4661 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4662 && labelRange <= 10)
4664 D (emitcode (";", "tail decrement optimized (range %d)", labelRange));
4665 tlbl = IC_LABEL (ic->next);
4670 tlbl = newiTempLabel (NULL);
4674 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4675 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4676 IS_AOP_PREG (IC_RESULT (ic)))
4677 emitcode ("cjne", "%s,#0xff,%05d$"
4678 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4682 emitcode ("mov", "a,#0xff");
4683 emitcode ("cjne", "a,%s,%05d$"
4684 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4687 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4690 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4691 IS_AOP_PREG (IC_RESULT (ic)))
4692 emitcode ("cjne", "%s,#0xff,%05d$"
4693 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4697 emitcode ("cjne", "a,%s,%05d$"
4698 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4701 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4705 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4706 IS_AOP_PREG (IC_RESULT (ic)))
4707 emitcode ("cjne", "%s,#0xff,%05d$"
4708 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4712 emitcode ("cjne", "a,%s,%05d$"
4713 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4716 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4725 /* if the sizes are greater than 1 then we cannot */
4726 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4727 AOP_SIZE (IC_LEFT (ic)) > 1)
4730 /* we can if the aops of the left & result match or
4731 if they are in registers and the registers are the
4733 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4737 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4739 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4744 l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
4749 emitcode ("dec", "%s", l);
4752 if (AOP_NEEDSACC (IC_RESULT (ic)))
4753 aopPut (IC_RESULT (ic), "a", 0);
4760 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4761 emitcode ("dec", "a");
4762 aopPut (IC_RESULT (ic), "a", 0);
4769 /*-----------------------------------------------------------------*/
4770 /* addSign - complete with sign */
4771 /*-----------------------------------------------------------------*/
4773 addSign (operand * result, int offset, int sign)
4775 int size = (getDataSize (result) - offset);
4780 emitcode ("rlc", "a");
4781 emitcode ("subb", "a,acc");
4784 aopPut (result, "a", offset++);
4791 aopPut (result, zero, offset++);
4797 /*-----------------------------------------------------------------*/
4798 /* genMinusBits - generates code for subtraction of two bits */
4799 /*-----------------------------------------------------------------*/
4801 genMinusBits (iCode * ic)
4803 symbol *lbl = newiTempLabel (NULL);
4805 D (emitcode (";", "genMinusBits"));
4807 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4809 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4810 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4811 emitcode ("cpl", "c");
4813 outBitC (IC_RESULT (ic));
4817 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4818 emitcode ("subb", "a,acc");
4819 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4820 emitcode ("inc", "a");
4822 aopPut (IC_RESULT (ic), "a", 0);
4823 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4827 /*-----------------------------------------------------------------*/
4828 /* genMinus - generates code for subtraction */
4829 /*-----------------------------------------------------------------*/
4831 genMinus (iCode * ic)
4833 int size, offset = 0;
4835 D (emitcode (";", "genMinus"));
4837 aopOp (IC_LEFT (ic), ic, FALSE);
4838 aopOp (IC_RIGHT (ic), ic, FALSE);
4839 aopOp (IC_RESULT (ic), ic, TRUE);
4841 /* special cases :- */
4842 /* if both left & right are in bit space */
4843 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4844 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4850 /* if I can do an decrement instead
4851 of subtract then GOOD for ME */
4852 if (genMinusDec (ic) == TRUE)
4855 size = getDataSize (IC_RESULT (ic));
4857 /* if literal, add a,#-lit, else normal subb */
4858 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4860 unsigned long lit = 0L;
4861 bool useCarry = FALSE;
4863 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4868 if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4870 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4871 if (!offset && !size && lit== (unsigned long) -1)
4873 emitcode ("dec", "a");
4877 /* first add without previous c */
4878 emitcode ("add", "a,#0x%02x",
4879 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4884 emitcode ("addc", "a,#0x%02x",
4885 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4887 aopPut (IC_RESULT (ic), "a", offset++);
4891 /* no need to add zeroes */
4892 if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4894 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4903 operand *leftOp, *rightOp;
4905 leftOp = IC_LEFT(ic);
4906 rightOp = IC_RIGHT(ic);
4910 if (aopGetUsesAcc(rightOp, offset)) {
4911 if (aopGetUsesAcc(leftOp, offset)) {
4914 MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4916 emitcode ("mov", "b,a");
4919 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4920 emitcode ("subb", "a,b");
4923 /* reverse subtraction with 2's complement */
4925 emitcode( "setb", "c");
4927 emitcode( "cpl", "c");
4928 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4929 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4930 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4931 emitcode("cpl", "a");
4932 if (size) /* skip if last byte */
4933 emitcode( "cpl", "c");
4936 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4939 emitcode ("subb", "a,%s",
4940 aopGet(rightOp, offset, FALSE, TRUE));
4943 aopPut (IC_RESULT (ic), "a", offset++);
4947 adjustArithmeticResult (ic);
4950 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4951 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4952 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4956 /*-----------------------------------------------------------------*/
4957 /* genMultbits :- multiplication of bits */
4958 /*-----------------------------------------------------------------*/
4960 genMultbits (operand * left,
4964 D (emitcode (";", "genMultbits"));
4966 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4967 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4971 /*-----------------------------------------------------------------*/
4972 /* genMultOneByte : 8*8=8/16 bit multiplication */
4973 /*-----------------------------------------------------------------*/
4975 genMultOneByte (operand * left,
4980 int size = AOP_SIZE (result);
4981 bool runtimeSign, compiletimeSign;
4982 bool lUnsigned, rUnsigned, pushedB;
4984 D (emitcode (";", "genMultOneByte"));
4986 if (size < 1 || size > 2)
4988 /* this should never happen */
4989 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4990 AOP_SIZE(result), __FILE__, lineno);
4994 /* (if two literals: the value is computed before) */
4995 /* if one literal, literal on the right */
4996 if (AOP_TYPE (left) == AOP_LIT)
5001 /* emitcode (";", "swapped left and right"); */
5003 /* if no literal, unsigned on the right: shorter code */
5004 if ( AOP_TYPE (right) != AOP_LIT
5005 && SPEC_USIGN (getSpec (operandType (left))))
5012 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5013 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5017 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
5018 no need to take care about the signedness! */
5019 || (lUnsigned && rUnsigned))
5021 /* just an unsigned 8 * 8 = 8 multiply
5023 /* emitcode (";","unsigned"); */
5024 /* TODO: check for accumulator clash between left & right aops? */
5026 if (AOP_TYPE (right) == AOP_LIT)
5028 /* moving to accumulator first helps peepholes */
5029 MOVA (aopGet (left, 0, FALSE, FALSE));
5030 MOVB (aopGet (right, 0, FALSE, FALSE));
5034 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5035 MOVA (aopGet (left, 0, FALSE, FALSE));
5038 emitcode ("mul", "ab");
5039 aopPut (result, "a", 0);
5041 aopPut (result, "b", 1);
5047 /* we have to do a signed multiply */
5048 /* emitcode (";", "signed"); */
5050 /* now sign adjust for both left & right */
5052 /* let's see what's needed: */
5053 /* apply negative sign during runtime */
5054 runtimeSign = FALSE;
5055 /* negative sign from literals */
5056 compiletimeSign = FALSE;
5060 if (AOP_TYPE(left) == AOP_LIT)
5062 /* signed literal */
5063 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5065 compiletimeSign = TRUE;
5068 /* signed but not literal */
5074 if (AOP_TYPE(right) == AOP_LIT)
5076 /* signed literal */
5077 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5079 compiletimeSign ^= TRUE;
5082 /* signed but not literal */
5086 /* initialize F0, which stores the runtime sign */
5089 if (compiletimeSign)
5090 emitcode ("setb", "F0"); /* set sign flag */
5092 emitcode ("clr", "F0"); /* reset sign flag */
5095 /* save the signs of the operands */
5096 if (AOP_TYPE(right) == AOP_LIT)
5098 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5100 if (!rUnsigned && val < 0)
5101 emitcode ("mov", "b,#0x%02x", -val);
5103 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5105 else /* ! literal */
5107 if (rUnsigned) /* emitcode (";", "signed"); */
5108 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5111 MOVA (aopGet (right, 0, FALSE, FALSE));
5112 lbl = newiTempLabel (NULL);
5113 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5114 emitcode ("cpl", "F0"); /* complement sign flag */
5115 emitcode ("cpl", "a"); /* 2's complement */
5116 emitcode ("inc", "a");
5118 emitcode ("mov", "b,a");
5122 if (AOP_TYPE(left) == AOP_LIT)
5124 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5126 if (!lUnsigned && val < 0)
5127 emitcode ("mov", "a,#0x%02x", -val);
5129 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5131 else /* ! literal */
5133 MOVA (aopGet (left, 0, FALSE, FALSE));
5137 lbl = newiTempLabel (NULL);
5138 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5139 emitcode ("cpl", "F0"); /* complement sign flag */
5140 emitcode ("cpl", "a"); /* 2's complement */
5141 emitcode ("inc", "a");
5146 /* now the multiplication */
5147 emitcode ("mul", "ab");
5148 if (runtimeSign || compiletimeSign)
5150 lbl = newiTempLabel (NULL);
5152 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5153 emitcode ("cpl", "a"); /* lsb 2's complement */
5155 emitcode ("inc", "a"); /* inc doesn't set carry flag */
5158 emitcode ("add", "a,#1"); /* this sets carry flag */
5159 emitcode ("xch", "a,b");
5160 emitcode ("cpl", "a"); /* msb 2's complement */
5161 emitcode ("addc", "a,#0");
5162 emitcode ("xch", "a,b");
5166 aopPut (result, "a", 0);
5168 aopPut (result, "b", 1);
5173 /*-----------------------------------------------------------------*/
5174 /* genMult - generates code for multiplication */
5175 /*-----------------------------------------------------------------*/
5177 genMult (iCode * ic)
5179 operand *left = IC_LEFT (ic);
5180 operand *right = IC_RIGHT (ic);
5181 operand *result = IC_RESULT (ic);
5183 D (emitcode (";", "genMult"));
5185 /* assign the asmops */
5186 aopOp (left, ic, FALSE);
5187 aopOp (right, ic, FALSE);
5188 aopOp (result, ic, TRUE);
5190 /* special cases first */
5192 if (AOP_TYPE (left) == AOP_CRY &&
5193 AOP_TYPE (right) == AOP_CRY)
5195 genMultbits (left, right, result);
5199 /* if both are of size == 1 */
5200 #if 0 // one of them can be a sloc shared with the result
5201 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
5203 if (getSize(operandType(left)) == 1 &&
5204 getSize(operandType(right)) == 1)
5207 genMultOneByte (left, right, result);
5211 /* should have been converted to function call */
5212 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
5213 getSize(OP_SYMBOL(right)->type));
5217 freeAsmop (result, NULL, ic, TRUE);
5218 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5219 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5222 /*-----------------------------------------------------------------*/
5223 /* genDivbits :- division of bits */
5224 /*-----------------------------------------------------------------*/
5226 genDivbits (operand * left,
5233 D(emitcode (";", "genDivbits"));
5237 /* the result must be bit */
5238 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5239 l = aopGet (left, 0, FALSE, FALSE);
5243 emitcode ("div", "ab");
5244 emitcode ("rrc", "a");
5248 aopPut (result, "c", 0);
5251 /*-----------------------------------------------------------------*/
5252 /* genDivOneByte : 8 bit division */
5253 /*-----------------------------------------------------------------*/
5255 genDivOneByte (operand * left,
5259 bool lUnsigned, rUnsigned, pushedB;
5260 bool runtimeSign, compiletimeSign;
5261 bool accuse = FALSE;
5262 bool pushedA = FALSE;
5266 D(emitcode (";", "genDivOneByte"));
5268 /* Why is it necessary that genDivOneByte() can return an int result?
5271 volatile unsigned char uc;
5272 volatile signed char sc1, sc2;
5285 In all cases a one byte result would overflow, the following cast to int
5286 would return the wrong result.
5288 Two possible solution:
5289 a) cast operands to int, if ((unsigned) / (signed)) or
5290 ((signed) / (signed))
5291 b) return an 16 bit signed int; this is what we're doing here!
5294 size = AOP_SIZE (result) - 1;
5296 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5297 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5301 /* signed or unsigned */
5302 if (lUnsigned && rUnsigned)
5304 /* unsigned is easy */
5305 MOVB (aopGet (right, 0, FALSE, FALSE));
5306 MOVA (aopGet (left, 0, FALSE, FALSE));
5307 emitcode ("div", "ab");
5308 aopPut (result, "a", 0);
5310 aopPut (result, zero, offset++);
5316 /* signed is a little bit more difficult */
5318 /* now sign adjust for both left & right */
5320 /* let's see what's needed: */
5321 /* apply negative sign during runtime */
5322 runtimeSign = FALSE;
5323 /* negative sign from literals */
5324 compiletimeSign = FALSE;
5328 if (AOP_TYPE(left) == AOP_LIT)
5330 /* signed literal */
5331 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5333 compiletimeSign = TRUE;
5336 /* signed but not literal */
5342 if (AOP_TYPE(right) == AOP_LIT)
5344 /* signed literal */
5345 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5347 compiletimeSign ^= TRUE;
5350 /* signed but not literal */
5354 /* initialize F0, which stores the runtime sign */
5357 if (compiletimeSign)
5358 emitcode ("setb", "F0"); /* set sign flag */
5360 emitcode ("clr", "F0"); /* reset sign flag */
5363 /* save the signs of the operands */
5364 if (AOP_TYPE(right) == AOP_LIT)
5366 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5368 if (!rUnsigned && val < 0)
5369 emitcode ("mov", "b,#0x%02x", -val);
5371 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5373 else /* ! literal */
5376 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5379 MOVA (aopGet (right, 0, FALSE, FALSE));
5380 lbl = newiTempLabel (NULL);
5381 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5382 emitcode ("cpl", "F0"); /* complement sign flag */
5383 emitcode ("cpl", "a"); /* 2's complement */
5384 emitcode ("inc", "a");
5386 emitcode ("mov", "b,a");
5390 if (AOP_TYPE(left) == AOP_LIT)
5392 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5394 if (!lUnsigned && val < 0)
5395 emitcode ("mov", "a,#0x%02x", -val);
5397 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5399 else /* ! literal */
5401 MOVA (aopGet (left, 0, FALSE, FALSE));
5405 lbl = newiTempLabel (NULL);
5406 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5407 emitcode ("cpl", "F0"); /* complement sign flag */
5408 emitcode ("cpl", "a"); /* 2's complement */
5409 emitcode ("inc", "a");
5414 /* now the division */
5415 emitcode ("div", "ab");
5417 if (runtimeSign || compiletimeSign)
5419 lbl = newiTempLabel (NULL);
5421 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5422 emitcode ("cpl", "a"); /* lsb 2's complement */
5423 emitcode ("inc", "a");
5426 accuse = aopPut (result, "a", 0);
5429 /* msb is 0x00 or 0xff depending on the sign */
5434 emitcode ("push", "acc");
5437 emitcode ("mov", "c,F0");
5438 emitcode ("subb", "a,acc");
5440 aopPut (result, "a", offset++);
5442 else /* compiletimeSign */
5444 if (aopPutUsesAcc (result, "#0xFF", offset))
5446 emitcode ("push", "acc");
5450 aopPut (result, "#0xff", offset++);
5456 aopPut (result, "a", 0);
5458 aopPut (result, zero, offset++);
5462 emitcode ("pop", "acc");
5466 /*-----------------------------------------------------------------*/
5467 /* genDiv - generates code for division */
5468 /*-----------------------------------------------------------------*/
5472 operand *left = IC_LEFT (ic);
5473 operand *right = IC_RIGHT (ic);
5474 operand *result = IC_RESULT (ic);
5476 D (emitcode (";", "genDiv"));
5478 /* assign the asmops */
5479 aopOp (left, ic, FALSE);
5480 aopOp (right, ic, FALSE);
5481 aopOp (result, ic, TRUE);
5483 /* special cases first */
5485 if (AOP_TYPE (left) == AOP_CRY &&
5486 AOP_TYPE (right) == AOP_CRY)
5488 genDivbits (left, right, result);
5492 /* if both are of size == 1 */
5493 if (AOP_SIZE (left) == 1 &&
5494 AOP_SIZE (right) == 1)
5496 genDivOneByte (left, right, result);
5500 /* should have been converted to function call */
5503 freeAsmop (result, NULL, ic, TRUE);
5504 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5505 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5508 /*-----------------------------------------------------------------*/
5509 /* genModbits :- modulus of bits */
5510 /*-----------------------------------------------------------------*/
5512 genModbits (operand * left,
5519 D (emitcode (";", "genModbits"));
5523 /* the result must be bit */
5524 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5525 l = aopGet (left, 0, FALSE, FALSE);
5529 emitcode ("div", "ab");
5530 emitcode ("mov", "a,b");
5531 emitcode ("rrc", "a");
5535 aopPut (result, "c", 0);
5538 /*-----------------------------------------------------------------*/
5539 /* genModOneByte : 8 bit modulus */
5540 /*-----------------------------------------------------------------*/
5542 genModOneByte (operand * left,
5546 bool lUnsigned, rUnsigned, pushedB;
5547 bool runtimeSign, compiletimeSign;
5551 D (emitcode (";", "genModOneByte"));
5553 size = AOP_SIZE (result) - 1;
5555 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5556 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5558 /* if right is a literal, check it for 2^n */
5559 if (AOP_TYPE(right) == AOP_LIT)
5561 unsigned char val = abs((int) operandLitValue(right));
5562 symbol *lbl2 = NULL;
5566 case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5575 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5576 "modulus of unsigned char by 2^n literal shouldn't be processed here");
5577 /* because iCode should have been changed to genAnd */
5578 /* see file "SDCCopt.c", function "convertToFcall()" */
5580 MOVA (aopGet (left, 0, FALSE, FALSE));
5581 emitcode ("mov", "c,acc.7");
5582 emitcode ("anl", "a,#0x%02x", val - 1);
5583 lbl = newiTempLabel (NULL);
5584 emitcode ("jz", "%05d$", (lbl->key + 100));
5585 emitcode ("jnc", "%05d$", (lbl->key + 100));
5586 emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5592 aopPut (result, "a", 0);
5594 aopPut (result, "#0xff", offs2++);
5595 lbl2 = newiTempLabel (NULL);
5596 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5599 aopPut (result, "a", 0);
5601 aopPut (result, zero, offset++);
5615 /* signed or unsigned */
5616 if (lUnsigned && rUnsigned)
5618 /* unsigned is easy */
5619 MOVB (aopGet (right, 0, FALSE, FALSE));
5620 MOVA (aopGet (left, 0, FALSE, FALSE));
5621 emitcode ("div", "ab");
5622 aopPut (result, "b", 0);
5624 aopPut (result, zero, offset++);
5630 /* signed is a little bit more difficult */
5632 /* now sign adjust for both left & right */
5634 /* modulus: sign of the right operand has no influence on the result! */
5635 if (AOP_TYPE(right) == AOP_LIT)
5637 signed char val = (char) operandLitValue(right);
5639 if (!rUnsigned && val < 0)
5640 emitcode ("mov", "b,#0x%02x", -val);
5642 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5644 else /* not literal */
5647 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5650 MOVA (aopGet (right, 0, FALSE, FALSE));
5651 lbl = newiTempLabel (NULL);
5652 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5653 emitcode ("cpl", "a"); /* 2's complement */
5654 emitcode ("inc", "a");
5656 emitcode ("mov", "b,a");
5660 /* let's see what's needed: */
5661 /* apply negative sign during runtime */
5662 runtimeSign = FALSE;
5663 /* negative sign from literals */
5664 compiletimeSign = FALSE;
5666 /* sign adjust left side */
5667 if (AOP_TYPE(left) == AOP_LIT)
5669 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5671 if (!lUnsigned && val < 0)
5673 compiletimeSign = TRUE; /* set sign flag */
5674 emitcode ("mov", "a,#0x%02x", -val);
5677 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5679 else /* ! literal */
5681 MOVA (aopGet (left, 0, FALSE, FALSE));
5686 emitcode ("clr", "F0"); /* clear sign flag */
5688 lbl = newiTempLabel (NULL);
5689 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5690 emitcode ("setb", "F0"); /* set sign flag */
5691 emitcode ("cpl", "a"); /* 2's complement */
5692 emitcode ("inc", "a");
5697 /* now the modulus */
5698 emitcode ("div", "ab");
5700 if (runtimeSign || compiletimeSign)
5702 emitcode ("mov", "a,b");
5703 lbl = newiTempLabel (NULL);
5705 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5706 emitcode ("cpl", "a"); /* 2's complement */
5707 emitcode ("inc", "a");
5710 aopPut (result, "a", 0);
5713 /* msb is 0x00 or 0xff depending on the sign */
5716 emitcode ("mov", "c,F0");
5717 emitcode ("subb", "a,acc");
5719 aopPut (result, "a", offset++);
5721 else /* compiletimeSign */
5723 aopPut (result, "#0xff", offset++);
5728 aopPut (result, "b", 0);
5730 aopPut (result, zero, offset++);
5736 /*-----------------------------------------------------------------*/
5737 /* genMod - generates code for division */
5738 /*-----------------------------------------------------------------*/
5742 operand *left = IC_LEFT (ic);
5743 operand *right = IC_RIGHT (ic);
5744 operand *result = IC_RESULT (ic);
5746 D (emitcode (";", "genMod"));
5748 /* assign the asmops */
5749 aopOp (left, ic, FALSE);
5750 aopOp (right, ic, FALSE);
5751 aopOp (result, ic, TRUE);
5753 /* special cases first */
5755 if (AOP_TYPE (left) == AOP_CRY &&
5756 AOP_TYPE (right) == AOP_CRY)
5758 genModbits (left, right, result);
5762 /* if both are of size == 1 */
5763 if (AOP_SIZE (left) == 1 &&
5764 AOP_SIZE (right) == 1)
5766 genModOneByte (left, right, result);
5770 /* should have been converted to function call */
5774 freeAsmop (result, NULL, ic, TRUE);
5775 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5776 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5779 /*-----------------------------------------------------------------*/
5780 /* genIfxJump :- will create a jump depending on the ifx */
5781 /*-----------------------------------------------------------------*/
5783 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5786 symbol *tlbl = newiTempLabel (NULL);
5789 D (emitcode (";", "genIfxJump"));
5791 /* if true label then we jump if condition
5795 jlbl = IC_TRUE (ic);
5796 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5797 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5801 /* false label is present */
5802 jlbl = IC_FALSE (ic);
5803 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5804 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5806 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5807 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5809 emitcode (inst, "%05d$", tlbl->key + 100);
5810 freeForBranchAsmop (result);
5811 freeForBranchAsmop (right);
5812 freeForBranchAsmop (left);
5813 emitcode ("ljmp", "%05d$", jlbl->key + 100);
5816 /* mark the icode as generated */
5820 /*-----------------------------------------------------------------*/
5821 /* genCmp :- greater or less than comparison */
5822 /*-----------------------------------------------------------------*/
5824 genCmp (operand * left, operand * right,
5825 operand * result, iCode * ifx, int sign, iCode *ic)
5827 int size, offset = 0;
5828 unsigned long lit = 0L;
5831 D (emitcode (";", "genCmp"));
5833 /* if left & right are bit variables */
5834 if (AOP_TYPE (left) == AOP_CRY &&
5835 AOP_TYPE (right) == AOP_CRY)
5837 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5838 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5842 /* subtract right from left if at the
5843 end the carry flag is set then we know that
5844 left is greater than right */
5845 size = max (AOP_SIZE (left), AOP_SIZE (right));
5847 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5848 if ((size == 1) && !sign &&
5849 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5851 symbol *lbl = newiTempLabel (NULL);
5852 emitcode ("cjne", "%s,%s,%05d$",
5853 aopGet (left, offset, FALSE, FALSE),
5854 aopGet (right, offset, FALSE, FALSE),
5860 if (AOP_TYPE (right) == AOP_LIT)
5862 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5863 /* optimize if(x < 0) or if(x >= 0) */
5872 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5873 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5875 genIfxJump (ifx, "acc.7", left, right, result);
5876 freeAsmop (right, NULL, ic, TRUE);
5877 freeAsmop (left, NULL, ic, TRUE);
5883 emitcode ("rlc", "a");
5890 int bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5891 while (size && (bytelit == 0))
5894 bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5900 MOVA (aopGet (left, offset, FALSE, FALSE));
5901 if (sign && size == 0)
5903 emitcode ("xrl", "a,#0x80");
5904 emitcode ("subb", "a,#0x%02x",
5905 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5909 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5919 bool pushedB = FALSE;
5920 rightInB = aopGetUsesAcc(right, offset);
5924 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5926 MOVA (aopGet (left, offset, FALSE, FALSE));
5927 if (sign && size == 0)
5929 emitcode ("xrl", "a,#0x80");
5934 MOVB (aopGet (right, offset, FALSE, FALSE));
5936 emitcode ("xrl", "b,#0x80");
5937 emitcode ("subb", "a,b");
5942 emitcode ("subb", "a,b");
5944 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5954 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5955 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5956 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5962 /* if the result is used in the next
5963 ifx conditional branch then generate
5964 code a little differently */
5967 genIfxJump (ifx, "c", NULL, NULL, result);
5973 /* leave the result in acc */
5977 /*-----------------------------------------------------------------*/
5978 /* genCmpGt :- greater than comparison */
5979 /*-----------------------------------------------------------------*/
5981 genCmpGt (iCode * ic, iCode * ifx)
5983 operand *left, *right, *result;
5984 sym_link *letype, *retype;
5987 D (emitcode (";", "genCmpGt"));
5989 left = IC_LEFT (ic);
5990 right = IC_RIGHT (ic);
5991 result = IC_RESULT (ic);
5993 letype = getSpec (operandType (left));
5994 retype = getSpec (operandType (right));
5995 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5996 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5997 /* assign the asmops */
5998 aopOp (result, ic, TRUE);
5999 aopOp (left, ic, FALSE);
6000 aopOp (right, ic, FALSE);
6002 genCmp (right, left, result, ifx, sign, ic);
6004 freeAsmop (result, NULL, ic, TRUE);
6007 /*-----------------------------------------------------------------*/
6008 /* genCmpLt - less than comparisons */
6009 /*-----------------------------------------------------------------*/
6011 genCmpLt (iCode * ic, iCode * ifx)
6013 operand *left, *right, *result;
6014 sym_link *letype, *retype;
6017 D (emitcode (";", "genCmpLt"));
6019 left = IC_LEFT (ic);
6020 right = IC_RIGHT (ic);
6021 result = IC_RESULT (ic);
6023 letype = getSpec (operandType (left));
6024 retype = getSpec (operandType (right));
6025 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
6026 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
6027 /* assign the asmops */
6028 aopOp (result, ic, TRUE);
6029 aopOp (left, ic, FALSE);
6030 aopOp (right, ic, FALSE);
6032 genCmp (left, right, result, ifx, sign, ic);
6034 freeAsmop (result, NULL, ic, TRUE);
6037 /*-----------------------------------------------------------------*/
6038 /* gencjneshort - compare and jump if not equal */
6039 /*-----------------------------------------------------------------*/
6041 gencjneshort (operand * left, operand * right, symbol * lbl)
6043 int size = max (AOP_SIZE (left), AOP_SIZE (right));
6045 unsigned long lit = 0L;
6047 D (emitcode (";", "gencjneshort"));
6049 /* if the left side is a literal or
6050 if the right is in a pointer register and left
6052 if ((AOP_TYPE (left) == AOP_LIT) ||
6053 (AOP_TYPE (left) == AOP_IMMD) ||
6054 (AOP_TYPE (left) == AOP_DIR) ||
6055 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6062 if (AOP_TYPE (right) == AOP_LIT)
6063 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6065 /* if the right side is a literal then anything goes */
6066 if (AOP_TYPE (right) == AOP_LIT &&
6067 AOP_TYPE (left) != AOP_DIR &&
6068 AOP_TYPE (left) != AOP_IMMD)
6072 emitcode ("cjne", "%s,%s,%05d$",
6073 aopGet (left, offset, FALSE, FALSE),
6074 aopGet (right, offset, FALSE, FALSE),
6080 /* if the right side is in a register or in direct space or
6081 if the left is a pointer register & right is not */
6082 else if (AOP_TYPE (right) == AOP_REG ||
6083 AOP_TYPE (right) == AOP_DIR ||
6084 AOP_TYPE (right) == AOP_LIT ||
6085 AOP_TYPE (right) == AOP_IMMD ||
6086 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6087 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6091 MOVA (aopGet (left, offset, FALSE, FALSE));
6092 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6093 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6094 emitcode ("jnz", "%05d$", lbl->key + 100);
6096 emitcode ("cjne", "a,%s,%05d$",
6097 aopGet (right, offset, FALSE, TRUE),
6104 /* right is a pointer reg need both a & b */
6107 //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
6108 wassertl(!BINUSE, "B was in use");
6109 MOVB (aopGet (left, offset, FALSE, FALSE));
6110 MOVA (aopGet (right, offset, FALSE, FALSE));
6111 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
6117 /*-----------------------------------------------------------------*/
6118 /* gencjne - compare and jump if not equal */
6119 /*-----------------------------------------------------------------*/
6121 gencjne (operand * left, operand * right, symbol * lbl)
6123 symbol *tlbl = newiTempLabel (NULL);
6125 D (emitcode (";", "gencjne"));
6127 gencjneshort (left, right, lbl);
6129 emitcode ("mov", "a,%s", one);
6130 emitcode ("sjmp", "%05d$", tlbl->key + 100);
6132 emitcode ("clr", "a");
6136 /*-----------------------------------------------------------------*/
6137 /* genCmpEq - generates code for equal to */
6138 /*-----------------------------------------------------------------*/
6140 genCmpEq (iCode * ic, iCode * ifx)
6142 bool swappedLR = FALSE;
6143 operand *left, *right, *result;
6145 D (emitcode (";", "genCmpEq"));
6147 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6148 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6149 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6151 /* if literal, literal on the right or
6152 if the right is in a pointer register and left
6154 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6155 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6157 operand *t = IC_RIGHT (ic);
6158 IC_RIGHT (ic) = IC_LEFT (ic);
6163 if (ifx && !AOP_SIZE (result))
6166 /* if they are both bit variables */
6167 if (AOP_TYPE (left) == AOP_CRY &&
6168 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6170 if (AOP_TYPE (right) == AOP_LIT)
6172 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6175 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6176 emitcode ("cpl", "c");
6180 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6184 emitcode ("clr", "c");
6186 /* AOP_TYPE(right) == AOP_CRY */
6190 symbol *lbl = newiTempLabel (NULL);
6191 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6192 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6193 emitcode ("cpl", "c");
6196 /* if true label then we jump if condition
6198 tlbl = newiTempLabel (NULL);
6201 emitcode ("jnc", "%05d$", tlbl->key + 100);
6202 freeForBranchAsmop (result);
6203 freeForBranchAsmop (right);
6204 freeForBranchAsmop (left);
6205 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6209 emitcode ("jc", "%05d$", tlbl->key + 100);
6210 freeForBranchAsmop (result);
6211 freeForBranchAsmop (right);
6212 freeForBranchAsmop (left);
6213 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6219 tlbl = newiTempLabel (NULL);
6220 gencjneshort (left, right, tlbl);
6223 freeForBranchAsmop (result);
6224 freeForBranchAsmop (right);
6225 freeForBranchAsmop (left);
6226 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6231 symbol *lbl = newiTempLabel (NULL);
6232 emitcode ("sjmp", "%05d$", lbl->key + 100);
6234 freeForBranchAsmop (result);
6235 freeForBranchAsmop (right);
6236 freeForBranchAsmop (left);
6237 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6241 /* mark the icode as generated */
6246 /* if they are both bit variables */
6247 if (AOP_TYPE (left) == AOP_CRY &&
6248 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6250 if (AOP_TYPE (right) == AOP_LIT)
6252 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6255 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6256 emitcode ("cpl", "c");
6260 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6264 emitcode ("clr", "c");
6266 /* AOP_TYPE(right) == AOP_CRY */
6270 symbol *lbl = newiTempLabel (NULL);
6271 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6272 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6273 emitcode ("cpl", "c");
6277 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6284 genIfxJump (ifx, "c", left, right, result);
6287 /* if the result is used in an arithmetic operation
6288 then put the result in place */
6293 gencjne (left, right, newiTempLabel (NULL));
6294 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6296 aopPut (result, "a", 0);
6301 genIfxJump (ifx, "a", left, right, result);
6304 /* if the result is used in an arithmetic operation
6305 then put the result in place */
6306 if (AOP_TYPE (result) != AOP_CRY)
6308 /* leave the result in acc */
6312 freeAsmop (result, NULL, ic, TRUE);
6315 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6316 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6320 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6321 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6325 /*-----------------------------------------------------------------*/
6326 /* ifxForOp - returns the icode containing the ifx for operand */
6327 /*-----------------------------------------------------------------*/
6329 ifxForOp (operand * op, iCode * ic)
6331 /* if true symbol then needs to be assigned */
6332 if (IS_TRUE_SYMOP (op))
6335 /* if this has register type condition and
6336 the next instruction is ifx with the same operand
6337 and live to of the operand is upto the ifx only then */
6339 ic->next->op == IFX &&
6340 IC_COND (ic->next)->key == op->key &&
6341 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6347 /*-----------------------------------------------------------------*/
6348 /* hasInc - operand is incremented before any other use */
6349 /*-----------------------------------------------------------------*/
6351 hasInc (operand *op, iCode *ic, int osize)
6353 sym_link *type = operandType(op);
6354 sym_link *retype = getSpec (type);
6355 iCode *lic = ic->next;
6358 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6359 if (!IS_SYMOP(op)) return NULL;
6361 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6362 if (IS_AGGREGATE(type->next)) return NULL;
6363 if (osize != (isize = getSize(type->next))) return NULL;
6366 /* if operand of the form op = op + <sizeof *op> */
6367 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6368 isOperandEqual(IC_RESULT(lic),op) &&
6369 isOperandLiteral(IC_RIGHT(lic)) &&
6370 operandLitValue(IC_RIGHT(lic)) == isize) {
6373 /* if the operand used or deffed */
6374 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6377 /* if GOTO or IFX */
6378 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6384 /*-----------------------------------------------------------------*/
6385 /* genAndOp - for && operation */
6386 /*-----------------------------------------------------------------*/
6388 genAndOp (iCode * ic)
6390 operand *left, *right, *result;
6393 D (emitcode (";", "genAndOp"));
6395 /* note here that && operations that are in an
6396 if statement are taken away by backPatchLabels
6397 only those used in arthmetic operations remain */
6398 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6399 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6400 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6402 /* if both are bit variables */
6403 if (AOP_TYPE (left) == AOP_CRY &&
6404 AOP_TYPE (right) == AOP_CRY)
6406 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6407 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6412 tlbl = newiTempLabel (NULL);
6414 emitcode ("jz", "%05d$", tlbl->key + 100);
6420 freeAsmop (result, NULL, ic, TRUE);
6421 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6422 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6426 /*-----------------------------------------------------------------*/
6427 /* genOrOp - for || operation */
6428 /*-----------------------------------------------------------------*/
6430 genOrOp (iCode * ic)
6432 operand *left, *right, *result;
6435 D (emitcode (";", "genOrOp"));
6437 /* note here that || operations that are in an
6438 if statement are taken away by backPatchLabels
6439 only those used in arthmetic operations remain */
6440 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6441 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6442 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6444 /* if both are bit variables */
6445 if (AOP_TYPE (left) == AOP_CRY &&
6446 AOP_TYPE (right) == AOP_CRY)
6448 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6449 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6454 tlbl = newiTempLabel (NULL);
6456 emitcode ("jnz", "%05d$", tlbl->key + 100);
6462 freeAsmop (result, NULL, ic, TRUE);
6463 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6464 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6467 /*-----------------------------------------------------------------*/
6468 /* isLiteralBit - test if lit == 2^n */
6469 /*-----------------------------------------------------------------*/
6471 isLiteralBit (unsigned long lit)
6473 unsigned long pw[32] =
6474 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6475 0x100L, 0x200L, 0x400L, 0x800L,
6476 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6477 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6478 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6479 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6480 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6483 for (idx = 0; idx < 32; idx++)
6489 /*-----------------------------------------------------------------*/
6490 /* continueIfTrue - */
6491 /*-----------------------------------------------------------------*/
6493 continueIfTrue (iCode * ic)
6496 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6500 /*-----------------------------------------------------------------*/
6502 /*-----------------------------------------------------------------*/
6504 jumpIfTrue (iCode * ic)
6507 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6511 /*-----------------------------------------------------------------*/
6512 /* jmpTrueOrFalse - */
6513 /*-----------------------------------------------------------------*/
6515 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6517 // ugly but optimized by peephole
6520 symbol *nlbl = newiTempLabel (NULL);
6521 emitcode ("sjmp", "%05d$", nlbl->key + 100);
6523 freeForBranchAsmop (result);
6524 freeForBranchAsmop (right);
6525 freeForBranchAsmop (left);
6526 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6531 freeForBranchAsmop (result);
6532 freeForBranchAsmop (right);
6533 freeForBranchAsmop (left);
6534 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6540 /*-----------------------------------------------------------------*/
6541 /* genAnd - code for and */
6542 /*-----------------------------------------------------------------*/
6544 genAnd (iCode * ic, iCode * ifx)
6546 operand *left, *right, *result;
6547 int size, offset = 0;
6548 unsigned long lit = 0L;
6552 D (emitcode (";", "genAnd"));
6554 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6555 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6556 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6559 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
6561 AOP_TYPE (left), AOP_TYPE (right));
6562 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
6564 AOP_SIZE (left), AOP_SIZE (right));
6567 /* if left is a literal & right is not then exchange them */
6568 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6569 AOP_NEEDSACC (left))
6571 operand *tmp = right;
6576 /* if result = right then exchange left and right */
6577 if (sameRegs (AOP (result), AOP (right)))
6579 operand *tmp = right;
6584 /* if right is bit then exchange them */
6585 if (AOP_TYPE (right) == AOP_CRY &&
6586 AOP_TYPE (left) != AOP_CRY)
6588 operand *tmp = right;
6592 if (AOP_TYPE (right) == AOP_LIT)
6593 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6595 size = AOP_SIZE (result);
6598 // result = bit & yy;
6599 if (AOP_TYPE (left) == AOP_CRY)
6601 // c = bit & literal;
6602 if (AOP_TYPE (right) == AOP_LIT)
6606 if (size && sameRegs (AOP (result), AOP (left)))
6609 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6614 if (size && (AOP_TYPE (result) == AOP_CRY))
6616 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6619 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6624 emitcode ("clr", "c");
6629 if (AOP_TYPE (right) == AOP_CRY)
6632 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6633 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6638 MOVA (aopGet (right, 0, FALSE, FALSE));
6640 emitcode ("rrc", "a");
6641 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6649 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6650 genIfxJump (ifx, "c", left, right, result);
6654 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6655 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6656 if ((AOP_TYPE (right) == AOP_LIT) &&
6657 (AOP_TYPE (result) == AOP_CRY) &&
6658 (AOP_TYPE (left) != AOP_CRY))
6660 int posbit = isLiteralBit (lit);
6665 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6669 switch (posbit & 0x07)
6671 case 0: emitcode ("rrc", "a");
6673 case 7: emitcode ("rlc", "a");
6675 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6684 SNPRINTF (buffer, sizeof(buffer),
6685 "acc.%d", posbit & 0x07);
6686 genIfxJump (ifx, buffer, left, right, result);
6689 {// what is this case? just found it in ds390/gen.c
6690 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6697 symbol *tlbl = newiTempLabel (NULL);
6698 int sizel = AOP_SIZE (left);
6700 emitcode ("setb", "c");
6703 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6705 MOVA (aopGet (left, offset, FALSE, FALSE));
6707 if ((posbit = isLiteralBit (bytelit)) != 0)
6708 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6711 if (bytelit != 0x0FFL)
6712 emitcode ("anl", "a,%s",
6713 aopGet (right, offset, FALSE, TRUE));
6714 emitcode ("jnz", "%05d$", tlbl->key + 100);
6719 // bit = left & literal
6722 emitcode ("clr", "c");
6725 // if(left & literal)
6729 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6739 /* if left is same as result */
6740 if (sameRegs (AOP (result), AOP (left)))
6742 for (; size--; offset++)
6744 if (AOP_TYPE (right) == AOP_LIT)
6746 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6747 if (bytelit == 0x0FF)
6749 /* dummy read of volatile operand */
6750 if (isOperandVolatile (left, FALSE))
6751 MOVA (aopGet (left, offset, FALSE, FALSE));
6755 else if (bytelit == 0)
6757 aopPut (result, zero, offset);
6759 else if (IS_AOP_PREG (result))
6761 MOVA (aopGet (left, offset, FALSE, TRUE));
6762 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6763 aopPut (result, "a", offset);
6766 emitcode ("anl", "%s,%s",
6767 aopGet (left, offset, FALSE, TRUE),
6768 aopGet (right, offset, FALSE, FALSE));
6772 if (AOP_TYPE (left) == AOP_ACC)
6775 emitcode("mov", "a,b");
6776 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6778 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6780 MOVB (aopGet (left, offset, FALSE, FALSE));
6781 MOVA (aopGet (right, offset, FALSE, FALSE));
6782 emitcode ("anl", "a,b");
6783 aopPut (result, "a", offset);
6785 else if (aopGetUsesAcc (left, offset))
6787 MOVA (aopGet (left, offset, FALSE, FALSE));
6788 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6789 aopPut (result, "a", offset);
6793 MOVA (aopGet (right, offset, FALSE, FALSE));
6794 if (IS_AOP_PREG (result))
6796 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6797 aopPut (result, "a", offset);
6800 emitcode ("anl", "%s,a", aopGet (left, offset, FALSE, TRUE));
6807 // left & result in different registers
6808 if (AOP_TYPE (result) == AOP_CRY)
6811 // if(size), result in bit
6812 // if(!size && ifx), conditional oper: if(left & right)
6813 symbol *tlbl = newiTempLabel (NULL);
6814 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6816 emitcode ("setb", "c");
6819 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6820 && AOP_TYPE(left)==AOP_ACC)
6823 emitcode("mov", "a,b");
6824 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6826 else if (AOP_TYPE(left)==AOP_ACC)
6830 bool pushedB = pushB ();
6831 emitcode("mov", "b,a");
6832 MOVA (aopGet (right, offset, FALSE, FALSE));
6833 emitcode("anl", "a,b");
6838 MOVA (aopGet (right, offset, FALSE, FALSE));
6839 emitcode("anl", "a,b");
6842 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6844 MOVB (aopGet (left, offset, FALSE, FALSE));
6845 MOVA (aopGet (right, offset, FALSE, FALSE));
6846 emitcode ("anl", "a,b");
6848 else if (aopGetUsesAcc (left, offset))
6850 MOVA (aopGet (left, offset, FALSE, FALSE));
6851 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6855 MOVA (aopGet (right, offset, FALSE, FALSE));
6856 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6859 emitcode ("jnz", "%05d$", tlbl->key + 100);
6869 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6875 for (; (size--); offset++)
6878 // result = left & right
6879 if (AOP_TYPE (right) == AOP_LIT)
6881 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6882 if (bytelit == 0x0FF)
6885 aopGet (left, offset, FALSE, FALSE),
6889 else if (bytelit == 0)
6891 /* dummy read of volatile operand */
6892 if (isOperandVolatile (left, FALSE))
6893 MOVA (aopGet (left, offset, FALSE, FALSE));
6894 aopPut (result, zero, offset);
6897 else if (AOP_TYPE (left) == AOP_ACC)
6901 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6902 aopPut (result, "a", offset);
6907 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6908 aopPut (result, "b", offset);
6913 // faster than result <- left, anl result,right
6914 // and better if result is SFR
6915 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6916 && AOP_TYPE(left)==AOP_ACC)
6919 emitcode("mov", "a,b");
6920 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6922 else if (AOP_TYPE(left)==AOP_ACC)
6926 bool pushedB = pushB ();
6927 emitcode("mov", "b,a");
6928 MOVA (aopGet (right, offset, FALSE, FALSE));
6929 emitcode("anl", "a,b");
6934 MOVA (aopGet (right, offset, FALSE, FALSE));
6935 emitcode("anl", "a,b");
6938 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6940 MOVB (aopGet (left, offset, FALSE, FALSE));
6941 MOVA (aopGet (right, offset, FALSE, FALSE));
6942 emitcode ("anl", "a,b");
6944 else if (aopGetUsesAcc (left, offset))
6946 MOVA (aopGet (left, offset, FALSE, FALSE));
6947 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6951 MOVA (aopGet (right, offset, FALSE, FALSE));
6952 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6954 aopPut (result, "a", offset);
6960 freeAsmop (result, NULL, ic, TRUE);
6961 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6962 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6965 /*-----------------------------------------------------------------*/
6966 /* genOr - code for or */
6967 /*-----------------------------------------------------------------*/
6969 genOr (iCode * ic, iCode * ifx)
6971 operand *left, *right, *result;
6972 int size, offset = 0;
6973 unsigned long lit = 0L;
6976 D (emitcode (";", "genOr"));
6978 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6979 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6980 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6983 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
6985 AOP_TYPE (left), AOP_TYPE (right));
6986 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
6988 AOP_SIZE (left), AOP_SIZE (right));
6991 /* if left is a literal & right is not then exchange them */
6992 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6993 AOP_NEEDSACC (left))
6995 operand *tmp = right;
7000 /* if result = right then exchange them */
7001 if (sameRegs (AOP (result), AOP (right)))
7003 operand *tmp = right;
7008 /* if right is bit then exchange them */
7009 if (AOP_TYPE (right) == AOP_CRY &&
7010 AOP_TYPE (left) != AOP_CRY)
7012 operand *tmp = right;
7016 if (AOP_TYPE (right) == AOP_LIT)
7017 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7019 size = AOP_SIZE (result);
7023 if (AOP_TYPE (left) == AOP_CRY)
7025 if (AOP_TYPE (right) == AOP_LIT)
7027 // c = bit | literal;
7030 // lit != 0 => result = 1
7031 if (AOP_TYPE (result) == AOP_CRY)
7034 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7036 continueIfTrue (ifx);
7039 emitcode ("setb", "c");
7043 // lit == 0 => result = left
7044 if (size && sameRegs (AOP (result), AOP (left)))
7046 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7051 if (AOP_TYPE (right) == AOP_CRY)
7054 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7055 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7060 symbol *tlbl = newiTempLabel (NULL);
7061 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
7062 emitcode ("setb", "c");
7063 emitcode ("jb", "%s,%05d$",
7064 AOP (left)->aopu.aop_dir, tlbl->key + 100);
7066 emitcode ("jnz", "%05d$", tlbl->key + 100);
7067 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7069 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7084 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7085 genIfxJump (ifx, "c", left, right, result);
7089 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7090 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7091 if ((AOP_TYPE (right) == AOP_LIT) &&
7092 (AOP_TYPE (result) == AOP_CRY) &&
7093 (AOP_TYPE (left) != AOP_CRY))
7099 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7101 continueIfTrue (ifx);
7106 // lit = 0, result = boolean(left)
7108 emitcode ("setb", "c");
7112 symbol *tlbl = newiTempLabel (NULL);
7113 emitcode ("jnz", "%05d$", tlbl->key + 100);
7119 genIfxJump (ifx, "a", left, right, result);
7127 /* if left is same as result */
7128 if (sameRegs (AOP (result), AOP (left)))
7130 for (; size--; offset++)
7132 if (AOP_TYPE (right) == AOP_LIT)
7134 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7137 /* dummy read of volatile operand */
7138 if (isOperandVolatile (left, FALSE))
7139 MOVA (aopGet (left, offset, FALSE, FALSE));
7143 else if (bytelit == 0x0FF)
7145 aopPut (result, "#0xFF", offset);
7147 else if (IS_AOP_PREG (left))
7149 MOVA (aopGet (left, offset, FALSE, TRUE));
7150 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7151 aopPut (result, "a", offset);
7155 emitcode ("orl", "%s,%s",
7156 aopGet (left, offset, FALSE, TRUE),
7157 aopGet (right, offset, FALSE, FALSE));
7162 if (AOP_TYPE (left) == AOP_ACC)
7165 emitcode("mov", "a,b");
7166 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7168 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7170 MOVB (aopGet (left, offset, FALSE, FALSE));
7171 MOVA (aopGet (right, offset, FALSE, FALSE));
7172 emitcode ("orl", "a,b");
7173 aopPut (result, "a", offset);
7175 else if (aopGetUsesAcc (left, offset))
7177 MOVA (aopGet (left, offset, FALSE, FALSE));
7178 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7179 aopPut (result, "a", offset);
7183 MOVA (aopGet (right, offset, FALSE, FALSE));
7184 if (IS_AOP_PREG (left))
7186 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7187 aopPut (result, "a", offset);
7191 emitcode ("orl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7199 // left & result in different registers
7200 if (AOP_TYPE (result) == AOP_CRY)
7203 // if(size), result in bit
7204 // if(!size && ifx), conditional oper: if(left | right)
7205 symbol *tlbl = newiTempLabel (NULL);
7206 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7208 emitcode ("setb", "c");
7211 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7212 && AOP_TYPE(left)==AOP_ACC)
7215 emitcode("mov", "a,b");
7216 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7218 else if (AOP_TYPE(left)==AOP_ACC)
7222 bool pushedB = pushB ();
7223 emitcode("mov", "b,a");
7224 MOVA (aopGet (right, offset, FALSE, FALSE));
7225 emitcode("orl", "a,b");
7230 MOVA (aopGet (right, offset, FALSE, FALSE));
7231 emitcode("orl", "a,b");
7234 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7236 MOVB (aopGet (left, offset, FALSE, FALSE));
7237 MOVA (aopGet (right, offset, FALSE, FALSE));
7238 emitcode ("orl", "a,b");
7240 else if (aopGetUsesAcc (left, offset))
7242 MOVA (aopGet (left, offset, FALSE, FALSE));
7243 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7247 MOVA (aopGet (right, offset, FALSE, FALSE));
7248 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7251 emitcode ("jnz", "%05d$", tlbl->key + 100);
7261 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7267 for (; (size--); offset++)
7270 // result = left | right
7271 if (AOP_TYPE (right) == AOP_LIT)
7273 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7277 aopGet (left, offset, FALSE, FALSE),
7281 else if (bytelit == 0x0FF)
7283 /* dummy read of volatile operand */
7284 if (isOperandVolatile (left, FALSE))
7285 MOVA (aopGet (left, offset, FALSE, FALSE));
7286 aopPut (result, "#0xFF", offset);
7290 // faster than result <- left, orl result,right
7291 // and better if result is SFR
7292 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7293 && AOP_TYPE(left)==AOP_ACC)
7296 emitcode("mov", "a,b");
7297 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7299 else if (AOP_TYPE(left)==AOP_ACC)
7303 bool pushedB = pushB ();
7304 emitcode("mov", "b,a");
7305 MOVA (aopGet (right, offset, FALSE, FALSE));
7306 emitcode("orl", "a,b");
7311 MOVA (aopGet (right, offset, FALSE, FALSE));
7312 emitcode("orl", "a,b");
7315 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7317 MOVB (aopGet (left, offset, FALSE, FALSE));
7318 MOVA (aopGet (right, offset, FALSE, FALSE));
7319 emitcode ("orl", "a,b");
7321 else if (aopGetUsesAcc (left, offset))
7323 MOVA (aopGet (left, offset, FALSE, FALSE));
7324 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7328 MOVA (aopGet (right, offset, FALSE, FALSE));
7329 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7331 aopPut (result, "a", offset);
7337 freeAsmop (result, NULL, ic, TRUE);
7338 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7339 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7342 /*-----------------------------------------------------------------*/
7343 /* genXor - code for xclusive or */
7344 /*-----------------------------------------------------------------*/
7346 genXor (iCode * ic, iCode * ifx)
7348 operand *left, *right, *result;
7349 int size, offset = 0;
7350 unsigned long lit = 0L;
7353 D (emitcode (";", "genXor"));
7355 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7356 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7357 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7360 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
7362 AOP_TYPE (left), AOP_TYPE (right));
7363 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
7365 AOP_SIZE (left), AOP_SIZE (right));
7368 /* if left is a literal & right is not ||
7369 if left needs acc & right does not */
7370 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7371 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7373 operand *tmp = right;
7378 /* if result = right then exchange them */
7379 if (sameRegs (AOP (result), AOP (right)))
7381 operand *tmp = right;
7386 /* if right is bit then exchange them */
7387 if (AOP_TYPE (right) == AOP_CRY &&
7388 AOP_TYPE (left) != AOP_CRY)
7390 operand *tmp = right;
7395 if (AOP_TYPE (right) == AOP_LIT)
7396 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7398 size = AOP_SIZE (result);
7402 if (AOP_TYPE (left) == AOP_CRY)
7404 if (AOP_TYPE (right) == AOP_LIT)
7406 // c = bit & literal;
7409 // lit>>1 != 0 => result = 1
7410 if (AOP_TYPE (result) == AOP_CRY)
7413 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7415 continueIfTrue (ifx);
7418 emitcode ("setb", "c");
7425 // lit == 0, result = left
7426 if (size && sameRegs (AOP (result), AOP (left)))
7428 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7432 // lit == 1, result = not(left)
7433 if (size && sameRegs (AOP (result), AOP (left)))
7435 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7440 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7441 emitcode ("cpl", "c");
7449 symbol *tlbl = newiTempLabel (NULL);
7450 if (AOP_TYPE (right) == AOP_CRY)
7453 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7457 int sizer = AOP_SIZE (right);
7459 // if val>>1 != 0, result = 1
7460 emitcode ("setb", "c");
7463 MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
7465 // test the msb of the lsb
7466 emitcode ("anl", "a,#0xfe");
7467 emitcode ("jnz", "%05d$", tlbl->key + 100);
7471 emitcode ("rrc", "a");
7473 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7474 emitcode ("cpl", "c");
7482 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7483 genIfxJump (ifx, "c", left, right, result);
7487 /* if left is same as result */
7488 if (sameRegs (AOP (result), AOP (left)))
7490 for (; size--; offset++)
7492 if (AOP_TYPE (right) == AOP_LIT)
7494 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7497 /* dummy read of volatile operand */
7498 if (isOperandVolatile (left, FALSE))
7499 MOVA (aopGet (left, offset, FALSE, FALSE));
7503 else if (IS_AOP_PREG (left))
7505 MOVA (aopGet (left, offset, FALSE, TRUE));
7506 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7507 aopPut (result, "a", offset);
7511 emitcode ("xrl", "%s,%s",
7512 aopGet (left, offset, FALSE, TRUE),
7513 aopGet (right, offset, FALSE, FALSE));
7518 if (AOP_TYPE (left) == AOP_ACC)
7521 emitcode("mov", "a,b");
7522 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7524 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7526 MOVB (aopGet (left, offset, FALSE, FALSE));
7527 MOVA (aopGet (right, offset, FALSE, FALSE));
7528 emitcode ("xrl", "a,b");
7529 aopPut (result, "a", offset);
7531 else if (aopGetUsesAcc (left, offset))
7533 MOVA (aopGet (left, offset, FALSE, FALSE));
7534 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7535 aopPut (result, "a", offset);
7539 MOVA (aopGet (right, offset, FALSE, FALSE));
7540 if (IS_AOP_PREG (left))
7542 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7543 aopPut (result, "a", offset);
7546 emitcode ("xrl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7553 // left & result in different registers
7554 if (AOP_TYPE (result) == AOP_CRY)
7557 // if(size), result in bit
7558 // if(!size && ifx), conditional oper: if(left ^ right)
7559 symbol *tlbl = newiTempLabel (NULL);
7560 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7563 emitcode ("setb", "c");
7566 if ((AOP_TYPE (right) == AOP_LIT) &&
7567 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7569 MOVA (aopGet (left, offset, FALSE, FALSE));
7571 else if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7572 && AOP_TYPE(left)==AOP_ACC)
7575 emitcode("mov", "a,b");
7576 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7578 else if (AOP_TYPE(left)==AOP_ACC)
7582 bool pushedB = pushB ();
7583 emitcode("mov", "b,a");
7584 MOVA (aopGet (right, offset, FALSE, FALSE));
7585 emitcode("xrl", "a,b");
7590 MOVA (aopGet (right, offset, FALSE, FALSE));
7591 emitcode("xrl", "a,b");
7594 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7596 MOVB (aopGet (left, offset, FALSE, FALSE));
7597 MOVA (aopGet (right, offset, FALSE, FALSE));
7598 emitcode ("xrl", "a,b");
7600 else if (aopGetUsesAcc (left, offset))
7602 MOVA (aopGet (left, offset, FALSE, FALSE));
7603 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7607 MOVA (aopGet (right, offset, FALSE, FALSE));
7608 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7611 emitcode ("jnz", "%05d$", tlbl->key + 100);
7621 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7625 for (; (size--); offset++)
7628 // result = left ^ right
7629 if (AOP_TYPE (right) == AOP_LIT)
7631 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7635 aopGet (left, offset, FALSE, FALSE),
7640 // faster than result <- left, xrl result,right
7641 // and better if result is SFR
7642 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7643 && AOP_TYPE(left)==AOP_ACC)
7646 emitcode("mov", "a,b");
7647 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7649 else if (AOP_TYPE(left)==AOP_ACC)
7653 bool pushedB = pushB ();
7654 emitcode("mov", "b,a");
7655 MOVA (aopGet (right, offset, FALSE, FALSE));
7656 emitcode("xrl", "a,b");
7661 MOVA (aopGet (right, offset, FALSE, FALSE));
7662 emitcode("xrl", "a,b");
7665 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7667 MOVB (aopGet (left, offset, FALSE, FALSE));
7668 MOVA (aopGet (right, offset, FALSE, FALSE));
7669 emitcode ("xrl", "a,b");
7671 else if (aopGetUsesAcc (left, offset))
7673 MOVA (aopGet (left, offset, FALSE, FALSE));
7674 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7678 MOVA (aopGet (right, offset, FALSE, FALSE));
7679 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7681 aopPut (result, "a", offset);
7687 freeAsmop (result, NULL, ic, TRUE);
7688 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7689 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7692 /*-----------------------------------------------------------------*/
7693 /* genInline - write the inline code out */
7694 /*-----------------------------------------------------------------*/
7696 genInline (iCode * ic)
7698 char *buffer, *bp, *bp1;
7700 D (emitcode (";", "genInline"));
7702 _G.inLine += (!options.asmpeep);
7704 buffer = bp = bp1 = Safe_strdup(IC_INLINE(ic));
7706 /* emit each line as a code */
7717 /* Add \n for labels, not dirs such as c:\mydir */
7718 if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
7732 /* emitcode("",buffer); */
7733 _G.inLine -= (!options.asmpeep);
7736 /*-----------------------------------------------------------------*/
7737 /* genRRC - rotate right with carry */
7738 /*-----------------------------------------------------------------*/
7742 operand *left, *result;
7746 D (emitcode (";", "genRRC"));
7748 /* rotate right with carry */
7749 left = IC_LEFT (ic);
7750 result = IC_RESULT (ic);
7751 aopOp (left, ic, FALSE);
7752 aopOp (result, ic, FALSE);
7754 /* move it to the result */
7755 size = AOP_SIZE (result);
7757 if (size == 1) { /* special case for 1 byte */
7758 l = aopGet (left, offset, FALSE, FALSE);
7760 emitcode ("rr", "a");
7763 /* no need to clear carry, bit7 will be written later */
7766 l = aopGet (left, offset, FALSE, FALSE);
7768 emitcode ("rrc", "a");
7769 if (AOP_SIZE (result) > 1)
7770 aopPut (result, "a", offset--);
7772 /* now we need to put the carry into the
7773 highest order byte of the result */
7774 if (AOP_SIZE (result) > 1)
7776 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7779 emitcode ("mov", "acc.7,c");
7781 aopPut (result, "a", AOP_SIZE (result) - 1);
7782 freeAsmop (result, NULL, ic, TRUE);
7783 freeAsmop (left, NULL, ic, TRUE);
7786 /*-----------------------------------------------------------------*/
7787 /* genRLC - generate code for rotate left with carry */
7788 /*-----------------------------------------------------------------*/
7792 operand *left, *result;
7796 D (emitcode (";", "genRLC"));
7798 /* rotate right with carry */
7799 left = IC_LEFT (ic);
7800 result = IC_RESULT (ic);
7801 aopOp (left, ic, FALSE);
7802 aopOp (result, ic, FALSE);
7804 /* move it to the result */
7805 size = AOP_SIZE (result);
7809 l = aopGet (left, offset, FALSE, FALSE);
7811 if (size == 0) { /* special case for 1 byte */
7815 emitcode("rlc","a"); /* bit0 will be written later */
7816 if (AOP_SIZE (result) > 1)
7818 aopPut (result, "a", offset++);
7823 l = aopGet (left, offset, FALSE, FALSE);
7825 emitcode ("rlc", "a");
7826 if (AOP_SIZE (result) > 1)
7827 aopPut (result, "a", offset++);
7830 /* now we need to put the carry into the
7831 highest order byte of the result */
7832 if (AOP_SIZE (result) > 1)
7834 l = aopGet (result, 0, FALSE, FALSE);
7837 emitcode ("mov", "acc.0,c");
7839 aopPut (result, "a", 0);
7840 freeAsmop (result, NULL, ic, TRUE);
7841 freeAsmop (left, NULL, ic, TRUE);
7844 /*-----------------------------------------------------------------*/
7845 /* genGetHbit - generates code get highest order bit */
7846 /*-----------------------------------------------------------------*/
7848 genGetHbit (iCode * ic)
7850 operand *left, *result;
7852 D (emitcode (";", "genGetHbit"));
7854 left = IC_LEFT (ic);
7855 result = IC_RESULT (ic);
7856 aopOp (left, ic, FALSE);
7857 aopOp (result, ic, FALSE);
7859 /* get the highest order byte into a */
7860 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7861 if (AOP_TYPE (result) == AOP_CRY)
7863 emitcode ("rlc", "a");
7868 emitcode ("rl", "a");
7869 emitcode ("anl", "a,#0x01");
7873 freeAsmop (result, NULL, ic, TRUE);
7874 freeAsmop (left, NULL, ic, TRUE);
7877 /*-----------------------------------------------------------------*/
7878 /* genGetAbit - generates code get a single bit */
7879 /*-----------------------------------------------------------------*/
7881 genGetAbit (iCode * ic)
7883 operand *left, *right, *result;
7886 D (emitcode (";", "genGetAbit"));
7888 left = IC_LEFT (ic);
7889 right = IC_RIGHT (ic);
7890 result = IC_RESULT (ic);
7891 aopOp (left, ic, FALSE);
7892 aopOp (right, ic, FALSE);
7893 aopOp (result, ic, FALSE);
7895 shCount = (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7897 /* get the needed byte into a */
7898 MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7900 if (AOP_TYPE (result) == AOP_CRY)
7903 emitcode ("rlc", "a");
7904 else if ((shCount) == 0)
7905 emitcode ("rrc", "a");
7907 emitcode ("mov", "c,acc[%d]", shCount);
7915 emitcode ("rr", "a");
7918 emitcode ("rr", "a");
7921 emitcode ("anl", "a,#0x01");
7925 emitcode ("mov", "c,acc[%d]", shCount);
7926 emitcode ("clr", "a");
7927 emitcode ("rlc", "a");
7930 emitcode ("swap", "a");
7931 emitcode ("anl", "a,#0x01");
7934 emitcode ("rl", "a");
7937 emitcode ("rl", "a");
7938 emitcode ("anl", "a,#0x01");
7944 freeAsmop (result, NULL, ic, TRUE);
7945 freeAsmop (right, NULL, ic, TRUE);
7946 freeAsmop (left, NULL, ic, TRUE);
7949 /*-----------------------------------------------------------------*/
7950 /* genGetByte - generates code get a single byte */
7951 /*-----------------------------------------------------------------*/
7953 genGetByte (iCode * ic)
7955 operand *left, *right, *result;
7958 D (emitcode (";", "genGetByte"));
7960 left = IC_LEFT (ic);
7961 right = IC_RIGHT (ic);
7962 result = IC_RESULT (ic);
7963 aopOp (left, ic, FALSE);
7964 aopOp (right, ic, FALSE);
7965 aopOp (result, ic, FALSE);
7967 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7969 aopGet (left, offset, FALSE, FALSE),
7972 freeAsmop (result, NULL, ic, TRUE);
7973 freeAsmop (right, NULL, ic, TRUE);
7974 freeAsmop (left, NULL, ic, TRUE);
7977 /*-----------------------------------------------------------------*/
7978 /* genGetWord - generates code get two bytes */
7979 /*-----------------------------------------------------------------*/
7981 genGetWord (iCode * ic)
7983 operand *left, *right, *result;
7986 D (emitcode (";", "genGetWord"));
7988 left = IC_LEFT (ic);
7989 right = IC_RIGHT (ic);
7990 result = IC_RESULT (ic);
7991 aopOp (left, ic, FALSE);
7992 aopOp (right, ic, FALSE);
7993 aopOp (result, ic, FALSE);
7995 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7997 aopGet (left, offset, FALSE, FALSE),
8000 aopGet (left, offset+1, FALSE, FALSE),
8003 freeAsmop (result, NULL, ic, TRUE);
8004 freeAsmop (right, NULL, ic, TRUE);
8005 freeAsmop (left, NULL, ic, TRUE);
8008 /*-----------------------------------------------------------------*/
8009 /* genSwap - generates code to swap nibbles or bytes */
8010 /*-----------------------------------------------------------------*/
8012 genSwap (iCode * ic)
8014 operand *left, *result;
8016 D(emitcode (";", "genSwap"));
8018 left = IC_LEFT (ic);
8019 result = IC_RESULT (ic);
8020 aopOp (left, ic, FALSE);
8021 aopOp (result, ic, FALSE);
8023 switch (AOP_SIZE (left))
8025 case 1: /* swap nibbles in byte */
8026 MOVA (aopGet (left, 0, FALSE, FALSE));
8027 emitcode ("swap", "a");
8028 aopPut (result, "a", 0);
8030 case 2: /* swap bytes in word */
8031 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
8033 MOVA (aopGet (left, 0, FALSE, FALSE));
8034 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8035 aopPut (result, "a", 1);
8037 else if (operandsEqu (left, result))
8040 bool pushedB = FALSE, leftInB = FALSE;
8042 MOVA (aopGet (left, 0, FALSE, FALSE));
8043 if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
8046 emitcode ("mov", "b,a");
8050 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8051 aopPut (result, reg, 1);
8058 aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8059 aopPut (result, aopGet (left, 0, FALSE, FALSE), 1);
8063 wassertl(FALSE, "unsupported SWAP operand size");
8066 freeAsmop (result, NULL, ic, TRUE);
8067 freeAsmop (left, NULL, ic, TRUE);
8070 /*-----------------------------------------------------------------*/
8071 /* AccRol - rotate left accumulator by known count */
8072 /*-----------------------------------------------------------------*/
8074 AccRol (int shCount)
8076 shCount &= 0x0007; // shCount : 0..7
8083 emitcode ("rl", "a");
8086 emitcode ("rl", "a");
8087 emitcode ("rl", "a");
8090 emitcode ("swap", "a");
8091 emitcode ("rr", "a");
8094 emitcode ("swap", "a");
8097 emitcode ("swap", "a");
8098 emitcode ("rl", "a");
8101 emitcode ("rr", "a");
8102 emitcode ("rr", "a");
8105 emitcode ("rr", "a");
8110 /*-----------------------------------------------------------------*/
8111 /* AccLsh - left shift accumulator by known count */
8112 /*-----------------------------------------------------------------*/
8114 AccLsh (int shCount)
8119 emitcode ("add", "a,acc");
8120 else if (shCount == 2)
8122 emitcode ("add", "a,acc");
8123 emitcode ("add", "a,acc");
8127 /* rotate left accumulator */
8129 /* and kill the lower order bits */
8130 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
8135 /*-----------------------------------------------------------------*/
8136 /* AccRsh - right shift accumulator by known count */
8137 /*-----------------------------------------------------------------*/
8139 AccRsh (int shCount)
8146 emitcode ("rrc", "a");
8150 /* rotate right accumulator */
8151 AccRol (8 - shCount);
8152 /* and kill the higher order bits */
8153 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8158 /*-----------------------------------------------------------------*/
8159 /* AccSRsh - signed right shift accumulator by known count */
8160 /*-----------------------------------------------------------------*/
8162 AccSRsh (int shCount)
8169 emitcode ("mov", "c,acc.7");
8170 emitcode ("rrc", "a");
8172 else if (shCount == 2)
8174 emitcode ("mov", "c,acc.7");
8175 emitcode ("rrc", "a");
8176 emitcode ("mov", "c,acc.7");
8177 emitcode ("rrc", "a");
8181 tlbl = newiTempLabel (NULL);
8182 /* rotate right accumulator */
8183 AccRol (8 - shCount);
8184 /* and kill the higher order bits */
8185 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8186 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8187 emitcode ("orl", "a,#0x%02x",
8188 (unsigned char) ~SRMask[shCount]);
8194 /*-----------------------------------------------------------------*/
8195 /* shiftR1Left2Result - shift right one byte from left to result */
8196 /*-----------------------------------------------------------------*/
8198 shiftR1Left2Result (operand * left, int offl,
8199 operand * result, int offr,
8200 int shCount, int sign)
8202 MOVA (aopGet (left, offl, FALSE, FALSE));
8203 /* shift right accumulator */
8208 aopPut (result, "a", offr);
8211 /*-----------------------------------------------------------------*/
8212 /* shiftL1Left2Result - shift left one byte from left to result */
8213 /*-----------------------------------------------------------------*/
8215 shiftL1Left2Result (operand * left, int offl,
8216 operand * result, int offr, int shCount)
8219 l = aopGet (left, offl, FALSE, FALSE);
8221 /* shift left accumulator */
8223 aopPut (result, "a", offr);
8226 /*-----------------------------------------------------------------*/
8227 /* movLeft2Result - move byte from left to result */
8228 /*-----------------------------------------------------------------*/
8230 movLeft2Result (operand * left, int offl,
8231 operand * result, int offr, int sign)
8234 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8236 l = aopGet (left, offl, FALSE, FALSE);
8238 if (*l == '@' && (IS_AOP_PREG (result)))
8240 emitcode ("mov", "a,%s", l);
8241 aopPut (result, "a", offr);
8247 aopPut (result, l, offr);
8251 /* MSB sign in acc.7 ! */
8252 if (getDataSize (left) == offl + 1)
8255 aopPut (result, "a", offr);
8262 /*-----------------------------------------------------------------*/
8263 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
8264 /*-----------------------------------------------------------------*/
8268 emitcode ("rrc", "a");
8269 emitcode ("xch", "a,%s", x);
8270 emitcode ("rrc", "a");
8271 emitcode ("xch", "a,%s", x);
8274 /*-----------------------------------------------------------------*/
8275 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
8276 /*-----------------------------------------------------------------*/
8280 emitcode ("xch", "a,%s", x);
8281 emitcode ("rlc", "a");
8282 emitcode ("xch", "a,%s", x);
8283 emitcode ("rlc", "a");
8286 /*-----------------------------------------------------------------*/
8287 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8288 /*-----------------------------------------------------------------*/
8292 emitcode ("xch", "a,%s", x);
8293 emitcode ("add", "a,acc");
8294 emitcode ("xch", "a,%s", x);
8295 emitcode ("rlc", "a");
8298 /*-----------------------------------------------------------------*/
8299 /* AccAXLsh - left shift a:x by known count (0..7) */
8300 /*-----------------------------------------------------------------*/
8302 AccAXLsh (char *x, int shCount)
8317 case 5: // AAAAABBB:CCCCCDDD
8319 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8321 emitcode ("anl", "a,#0x%02x",
8322 SLMask[shCount]); // BBB00000:CCCCCDDD
8324 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8326 AccRol (shCount); // DDDCCCCC:BBB00000
8328 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8330 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8332 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8334 emitcode ("anl", "a,#0x%02x",
8335 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8337 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8339 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8342 case 6: // AAAAAABB:CCCCCCDD
8343 emitcode ("anl", "a,#0x%02x",
8344 SRMask[shCount]); // 000000BB:CCCCCCDD
8345 emitcode ("mov", "c,acc.0"); // c = B
8346 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8348 AccAXRrl1 (x); // BCCCCCCD:D000000B
8349 AccAXRrl1 (x); // BBCCCCCC:DD000000
8351 emitcode("rrc","a");
8352 emitcode("xch","a,%s", x);
8353 emitcode("rrc","a");
8354 emitcode("mov","c,acc.0"); //<< get correct bit
8355 emitcode("xch","a,%s", x);
8357 emitcode("rrc","a");
8358 emitcode("xch","a,%s", x);
8359 emitcode("rrc","a");
8360 emitcode("xch","a,%s", x);
8363 case 7: // a:x <<= 7
8365 emitcode ("anl", "a,#0x%02x",
8366 SRMask[shCount]); // 0000000B:CCCCCCCD
8368 emitcode ("mov", "c,acc.0"); // c = B
8370 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
8372 AccAXRrl1 (x); // BCCCCCCC:D0000000
8380 /*-----------------------------------------------------------------*/
8381 /* AccAXRsh - right shift a:x known count (0..7) */
8382 /*-----------------------------------------------------------------*/
8384 AccAXRsh (char *x, int shCount)
8392 AccAXRrl1 (x); // 0->a:x
8397 AccAXRrl1 (x); // 0->a:x
8400 AccAXRrl1 (x); // 0->a:x
8405 case 5: // AAAAABBB:CCCCCDDD = a:x
8407 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8409 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8411 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8413 emitcode ("anl", "a,#0x%02x",
8414 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8416 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8418 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8420 emitcode ("anl", "a,#0x%02x",
8421 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8423 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8425 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8427 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8430 case 6: // AABBBBBB:CCDDDDDD
8432 emitcode ("mov", "c,acc.7");
8433 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8435 emitcode ("mov", "c,acc.7");
8436 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8438 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8440 emitcode ("anl", "a,#0x%02x",
8441 SRMask[shCount]); // 000000AA:BBBBBBCC
8444 case 7: // ABBBBBBB:CDDDDDDD
8446 emitcode ("mov", "c,acc.7"); // c = A
8448 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8450 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8452 emitcode ("anl", "a,#0x%02x",
8453 SRMask[shCount]); // 0000000A:BBBBBBBC
8461 /*-----------------------------------------------------------------*/
8462 /* AccAXRshS - right shift signed a:x known count (0..7) */
8463 /*-----------------------------------------------------------------*/
8465 AccAXRshS (char *x, int shCount)
8473 emitcode ("mov", "c,acc.7");
8474 AccAXRrl1 (x); // s->a:x
8478 emitcode ("mov", "c,acc.7");
8479 AccAXRrl1 (x); // s->a:x
8481 emitcode ("mov", "c,acc.7");
8482 AccAXRrl1 (x); // s->a:x
8487 case 5: // AAAAABBB:CCCCCDDD = a:x
8489 tlbl = newiTempLabel (NULL);
8490 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8492 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8494 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8496 emitcode ("anl", "a,#0x%02x",
8497 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8499 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8501 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8503 emitcode ("anl", "a,#0x%02x",
8504 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8506 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8508 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8510 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8512 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8513 emitcode ("orl", "a,#0x%02x",
8514 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8517 break; // SSSSAAAA:BBBCCCCC
8519 case 6: // AABBBBBB:CCDDDDDD
8521 tlbl = newiTempLabel (NULL);
8522 emitcode ("mov", "c,acc.7");
8523 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8525 emitcode ("mov", "c,acc.7");
8526 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8528 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8530 emitcode ("anl", "a,#0x%02x",
8531 SRMask[shCount]); // 000000AA:BBBBBBCC
8533 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8534 emitcode ("orl", "a,#0x%02x",
8535 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8539 case 7: // ABBBBBBB:CDDDDDDD
8541 tlbl = newiTempLabel (NULL);
8542 emitcode ("mov", "c,acc.7"); // c = A
8544 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8546 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8548 emitcode ("anl", "a,#0x%02x",
8549 SRMask[shCount]); // 0000000A:BBBBBBBC
8551 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8552 emitcode ("orl", "a,#0x%02x",
8553 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8562 /*-----------------------------------------------------------------*/
8563 /* shiftL2Left2Result - shift left two bytes from left to result */
8564 /*-----------------------------------------------------------------*/
8566 shiftL2Left2Result (operand * left, int offl,
8567 operand * result, int offr, int shCount)
8570 bool pushedB = FALSE;
8573 if (sameRegs (AOP (result), AOP (left)) &&
8574 ((offl + MSB16) == offr))
8576 /* don't crash result[offr] */
8577 MOVA (aopGet (left, offl, FALSE, FALSE));
8578 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8579 usedB = !strncmp(x, "b", 1);
8581 else if (aopGetUsesAcc (result, offr))
8583 movLeft2Result (left, offl, result, offr, 0);
8586 emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8587 MOVA (aopGet (result, offr, FALSE, FALSE));
8588 emitcode ("xch", "a,b");
8593 movLeft2Result (left, offl, result, offr, 0);
8594 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8595 x = aopGet (result, offr, FALSE, FALSE);
8597 /* ax << shCount (x = lsb(result)) */
8598 AccAXLsh (x, shCount);
8601 emitcode ("xch", "a,b");
8602 aopPut (result, "a", offr);
8603 aopPut (result, "b", offr + MSB16);
8608 aopPut (result, "a", offr + MSB16);
8613 /*-----------------------------------------------------------------*/
8614 /* shiftR2Left2Result - shift right two bytes from left to result */
8615 /*-----------------------------------------------------------------*/
8617 shiftR2Left2Result (operand * left, int offl,
8618 operand * result, int offr,
8619 int shCount, int sign)
8622 bool pushedB = FALSE;
8625 if (sameRegs (AOP (result), AOP (left)) &&
8626 ((offl + MSB16) == offr))
8628 /* don't crash result[offr] */
8629 MOVA (aopGet (left, offl, FALSE, FALSE));
8630 x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8631 usedB = !strncmp(x, "b", 1);
8633 else if (aopGetUsesAcc (result, offr))
8635 movLeft2Result (left, offl, result, offr, 0);
8638 emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8639 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8644 movLeft2Result (left, offl, result, offr, 0);
8645 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8646 x = aopGet (result, offr, FALSE, FALSE);
8648 /* a:x >> shCount (x = lsb(result)) */
8650 AccAXRshS (x, shCount);
8652 AccAXRsh (x, shCount);
8655 emitcode ("xch", "a,b");
8656 aopPut (result, "a", offr);
8657 emitcode ("xch", "a,b");
8660 if (getDataSize (result) > 1)
8661 aopPut (result, "a", offr + MSB16);
8664 /*-----------------------------------------------------------------*/
8665 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8666 /*-----------------------------------------------------------------*/
8668 shiftLLeftOrResult (operand * left, int offl,
8669 operand * result, int offr, int shCount)
8671 MOVA (aopGet (left, offl, FALSE, FALSE));
8672 /* shift left accumulator */
8674 /* or with result */
8675 if (aopGetUsesAcc (result, offr))
8677 emitcode ("xch", "a,b");
8678 MOVA (aopGet (result, offr, FALSE, FALSE));
8679 emitcode ("orl", "a,b");
8683 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8685 /* back to result */
8686 aopPut (result, "a", offr);
8689 /*-----------------------------------------------------------------*/
8690 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8691 /*-----------------------------------------------------------------*/
8693 shiftRLeftOrResult (operand * left, int offl,
8694 operand * result, int offr, int shCount)
8696 MOVA (aopGet (left, offl, FALSE, FALSE));
8697 /* shift right accumulator */
8699 /* or with result */
8700 if (aopGetUsesAcc(result, offr))
8702 emitcode ("xch", "a,b");
8703 MOVA (aopGet (result, offr, FALSE, FALSE));
8704 emitcode ("orl", "a,b");
8708 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8710 /* back to result */
8711 aopPut (result, "a", offr);
8714 /*-----------------------------------------------------------------*/
8715 /* genlshOne - left shift a one byte quantity by known count */
8716 /*-----------------------------------------------------------------*/
8718 genlshOne (operand * result, operand * left, int shCount)
8720 D (emitcode (";", "genlshOne"));
8722 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8725 /*-----------------------------------------------------------------*/
8726 /* genlshTwo - left shift two bytes by known amount != 0 */
8727 /*-----------------------------------------------------------------*/
8729 genlshTwo (operand * result, operand * left, int shCount)
8733 D (emitcode (";", "genlshTwo"));
8735 size = getDataSize (result);
8737 /* if shCount >= 8 */
8745 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8747 movLeft2Result (left, LSB, result, MSB16, 0);
8749 aopPut (result, zero, LSB);
8752 /* 1 <= shCount <= 7 */
8756 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8758 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8762 /*-----------------------------------------------------------------*/
8763 /* shiftLLong - shift left one long from left to result */
8764 /* offl = LSB or MSB16 */
8765 /*-----------------------------------------------------------------*/
8767 shiftLLong (operand * left, operand * result, int offr)
8770 int size = AOP_SIZE (result);
8772 if (size >= LSB + offr)
8774 l = aopGet (left, LSB, FALSE, FALSE);
8776 emitcode ("add", "a,acc");
8777 if (sameRegs (AOP (left), AOP (result)) &&
8778 size >= MSB16 + offr && offr != LSB)
8779 xch_a_aopGet (left, LSB + offr, FALSE, FALSE);
8781 aopPut (result, "a", LSB + offr);
8784 if (size >= MSB16 + offr)
8786 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8788 l = aopGet (left, MSB16, FALSE, FALSE);
8791 emitcode ("rlc", "a");
8792 if (sameRegs (AOP (left), AOP (result)) &&
8793 size >= MSB24 + offr && offr != LSB)
8794 xch_a_aopGet (left, MSB16 + offr, FALSE, FALSE);
8796 aopPut (result, "a", MSB16 + offr);
8799 if (size >= MSB24 + offr)
8801 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8803 l = aopGet (left, MSB24, FALSE, FALSE);
8806 emitcode ("rlc", "a");
8807 if (sameRegs (AOP (left), AOP (result)) &&
8808 size >= MSB32 + offr && offr != LSB)
8809 xch_a_aopGet (left, MSB24 + offr, FALSE, FALSE);
8811 aopPut (result, "a", MSB24 + offr);
8814 if (size > MSB32 + offr)
8816 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8818 l = aopGet (left, MSB32, FALSE, FALSE);
8821 emitcode ("rlc", "a");
8822 aopPut (result, "a", MSB32 + offr);
8825 aopPut (result, zero, LSB);
8828 /*-----------------------------------------------------------------*/
8829 /* genlshFour - shift four byte by a known amount != 0 */
8830 /*-----------------------------------------------------------------*/
8832 genlshFour (operand * result, operand * left, int shCount)
8836 D (emitcode (";", "genlshFour"));
8838 size = AOP_SIZE (result);
8840 /* if shifting more that 3 bytes */
8845 /* lowest order of left goes to the highest
8846 order of the destination */
8847 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8849 movLeft2Result (left, LSB, result, MSB32, 0);
8850 aopPut (result, zero, LSB);
8851 aopPut (result, zero, MSB16);
8852 aopPut (result, zero, MSB24);
8856 /* more than two bytes */
8857 else if (shCount >= 16)
8859 /* lower order two bytes goes to higher order two bytes */
8861 /* if some more remaining */
8863 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8866 movLeft2Result (left, MSB16, result, MSB32, 0);
8867 movLeft2Result (left, LSB, result, MSB24, 0);
8869 aopPut (result, zero, MSB16);
8870 aopPut (result, zero, LSB);
8874 /* if more than 1 byte */
8875 else if (shCount >= 8)
8877 /* lower order three bytes goes to higher order three bytes */
8882 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8884 movLeft2Result (left, LSB, result, MSB16, 0);
8890 movLeft2Result (left, MSB24, result, MSB32, 0);
8891 movLeft2Result (left, MSB16, result, MSB24, 0);
8892 movLeft2Result (left, LSB, result, MSB16, 0);
8893 aopPut (result, zero, LSB);
8895 else if (shCount == 1)
8896 shiftLLong (left, result, MSB16);
8899 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8900 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8901 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8902 aopPut (result, zero, LSB);
8907 /* 1 <= shCount <= 7 */
8908 else if (shCount <= 2)
8910 shiftLLong (left, result, LSB);
8912 shiftLLong (result, result, LSB);
8914 /* 3 <= shCount <= 7, optimize */
8917 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8918 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8919 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8923 /*-----------------------------------------------------------------*/
8924 /* genLeftShiftLiteral - left shifting by known count */
8925 /*-----------------------------------------------------------------*/
8927 genLeftShiftLiteral (operand * left,
8932 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8935 D (emitcode (";", "genLeftShiftLiteral"));
8937 freeAsmop (right, NULL, ic, TRUE);
8939 aopOp (left, ic, FALSE);
8940 aopOp (result, ic, FALSE);
8942 size = getSize (operandType (result));
8945 emitcode ("; shift left ", "result %d, left %d", size,
8949 /* I suppose that the left size >= result size */
8954 movLeft2Result (left, size, result, size, 0);
8957 else if (shCount >= (size * 8))
8961 aopPut (result, zero, size);
8969 genlshOne (result, left, shCount);
8973 genlshTwo (result, left, shCount);
8977 genlshFour (result, left, shCount);
8980 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8981 "*** ack! mystery literal shift!\n");
8985 freeAsmop (result, NULL, ic, TRUE);
8986 freeAsmop (left, NULL, ic, TRUE);
8989 /*-----------------------------------------------------------------*/
8990 /* genLeftShift - generates code for left shifting */
8991 /*-----------------------------------------------------------------*/
8993 genLeftShift (iCode * ic)
8995 operand *left, *right, *result;
8998 symbol *tlbl, *tlbl1;
9001 D (emitcode (";", "genLeftShift"));
9003 right = IC_RIGHT (ic);
9004 left = IC_LEFT (ic);
9005 result = IC_RESULT (ic);
9007 aopOp (right, ic, FALSE);
9009 /* if the shift count is known then do it
9010 as efficiently as possible */
9011 if (AOP_TYPE (right) == AOP_LIT)
9013 genLeftShiftLiteral (left, right, result, ic);
9017 /* shift count is unknown then we have to form
9018 a loop get the loop count in B : Note: we take
9019 only the lower order byte since shifting
9020 more that 32 bits make no sense anyway, ( the
9021 largest size of an object can be only 32 bits ) */
9024 MOVB (aopGet (right, 0, FALSE, FALSE));
9025 emitcode ("inc", "b");
9026 freeAsmop (right, NULL, ic, TRUE);
9027 aopOp (left, ic, FALSE);
9028 aopOp (result, ic, FALSE);
9030 /* now move the left to the result if they are not the same */
9031 if (!sameRegs (AOP (left), AOP (result)) &&
9032 AOP_SIZE (result) > 1)
9035 size = AOP_SIZE (result);
9039 l = aopGet (left, offset, FALSE, TRUE);
9040 if (*l == '@' && (IS_AOP_PREG (result)))
9043 emitcode ("mov", "a,%s", l);
9044 aopPut (result, "a", offset);
9047 aopPut (result, l, offset);
9052 tlbl = newiTempLabel (NULL);
9053 size = AOP_SIZE (result);
9055 tlbl1 = newiTempLabel (NULL);
9057 /* if it is only one byte then */
9060 symbol *tlbl1 = newiTempLabel (NULL);
9062 l = aopGet (left, 0, FALSE, FALSE);
9064 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9066 emitcode ("add", "a,acc");
9068 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9070 aopPut (result, "a", 0);
9074 reAdjustPreg (AOP (result));
9076 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9078 l = aopGet (result, offset, FALSE, FALSE);
9080 emitcode ("add", "a,acc");
9081 aopPut (result, "a", offset++);
9084 l = aopGet (result, offset, FALSE, FALSE);
9086 emitcode ("rlc", "a");
9087 aopPut (result, "a", offset++);
9089 reAdjustPreg (AOP (result));
9092 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9095 freeAsmop (result, NULL, ic, TRUE);
9096 freeAsmop (left, NULL, ic, TRUE);
9099 /*-----------------------------------------------------------------*/
9100 /* genrshOne - right shift a one byte quantity by known count */
9101 /*-----------------------------------------------------------------*/
9103 genrshOne (operand * result, operand * left,
9104 int shCount, int sign)
9106 D (emitcode (";", "genrshOne"));
9108 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9111 /*-----------------------------------------------------------------*/
9112 /* genrshTwo - right shift two bytes by known amount != 0 */
9113 /*-----------------------------------------------------------------*/
9115 genrshTwo (operand * result, operand * left,
9116 int shCount, int sign)
9118 D (emitcode (";", "genrshTwo"));
9120 /* if shCount >= 8 */
9125 shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
9127 movLeft2Result (left, MSB16, result, LSB, sign);
9128 addSign (result, MSB16, sign);
9131 /* 1 <= shCount <= 7 */
9133 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9136 /*-----------------------------------------------------------------*/
9137 /* shiftRLong - shift right one long from left to result */
9138 /* offl = LSB or MSB16 */
9139 /*-----------------------------------------------------------------*/
9141 shiftRLong (operand * left, int offl,
9142 operand * result, int sign)
9144 bool overlapping = regsInCommon (left, result) || operandsEqu(left, result);
9146 if (overlapping && offl>1)
9148 // we are in big trouble, but this shouldn't happen
9149 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9152 MOVA (aopGet (left, MSB32, FALSE, FALSE));
9159 emitcode ("rlc", "a");
9160 emitcode ("subb", "a,acc");
9161 if (overlapping && sameByte (AOP (left), MSB32, AOP (result), MSB32))
9163 xch_a_aopGet (left, MSB32, FALSE, FALSE);
9167 aopPut (result, "a", MSB32);
9168 MOVA (aopGet (left, MSB32, FALSE, FALSE));
9173 if (aopPutUsesAcc (result, zero, MSB32))
9175 emitcode("xch", "a,b");
9176 aopPut (result, zero, MSB32);
9177 emitcode("xch", "a,b");
9181 aopPut (result, zero, MSB32);
9188 emitcode ("clr", "c");
9192 emitcode ("mov", "c,acc.7");
9195 emitcode ("rrc", "a");
9197 if (overlapping && offl==MSB16 &&
9198 sameByte (AOP (left), MSB24, AOP (result), MSB32-offl))
9200 xch_a_aopGet (left, MSB24, FALSE, FALSE);
9204 aopPut (result, "a", MSB32 - offl);
9205 MOVA (aopGet (left, MSB24, FALSE, FALSE));
9208 emitcode ("rrc", "a");
9209 if (overlapping && offl==MSB16 &&
9210 sameByte (AOP (left), MSB16, AOP (result), MSB24-offl))
9212 xch_a_aopGet (left, MSB16, FALSE, FALSE);
9216 aopPut (result, "a", MSB24 - offl);
9217 MOVA (aopGet (left, MSB16, FALSE, FALSE));
9220 emitcode ("rrc", "a");
9223 aopPut (result, "a", MSB16 - offl);
9228 sameByte (AOP (left), LSB, AOP (result), MSB16-offl))
9230 xch_a_aopGet (left, LSB, FALSE, FALSE);
9234 aopPut (result, "a", MSB16 - offl);
9235 MOVA (aopGet (left, LSB, FALSE, FALSE));
9237 emitcode ("rrc", "a");
9238 aopPut (result, "a", LSB);
9242 /*-----------------------------------------------------------------*/
9243 /* genrshFour - shift four byte by a known amount != 0 */
9244 /*-----------------------------------------------------------------*/
9246 genrshFour (operand * result, operand * left,
9247 int shCount, int sign)
9249 D (emitcode (";", "genrshFour"));
9251 /* if shifting more that 3 bytes */
9256 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9258 movLeft2Result (left, MSB32, result, LSB, sign);
9259 addSign (result, MSB16, sign);
9261 else if (shCount >= 16)
9265 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9268 movLeft2Result (left, MSB24, result, LSB, 0);
9269 movLeft2Result (left, MSB32, result, MSB16, sign);
9271 addSign (result, MSB24, sign);
9273 else if (shCount >= 8)
9278 shiftRLong (left, MSB16, result, sign);
9280 else if (shCount == 0)
9282 movLeft2Result (left, MSB16, result, LSB, 0);
9283 movLeft2Result (left, MSB24, result, MSB16, 0);
9284 movLeft2Result (left, MSB32, result, MSB24, sign);
9285 addSign (result, MSB32, sign);
9289 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9290 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9291 /* the last shift is signed */
9292 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9293 addSign (result, MSB32, sign);
9298 /* 1 <= shCount <= 7 */
9301 shiftRLong (left, LSB, result, sign);
9303 shiftRLong (result, LSB, result, sign);
9307 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9308 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9309 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9314 /*-----------------------------------------------------------------*/
9315 /* genRightShiftLiteral - right shifting by known count */
9316 /*-----------------------------------------------------------------*/
9318 genRightShiftLiteral (operand * left,
9324 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9327 D (emitcode (";", "genRightShiftLiteral"));
9329 freeAsmop (right, NULL, ic, TRUE);
9331 aopOp (left, ic, FALSE);
9332 aopOp (result, ic, FALSE);
9335 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9339 size = getDataSize (left);
9340 /* test the LEFT size !!! */
9342 /* I suppose that the left size >= result size */
9345 size = getDataSize (result);
9347 movLeft2Result (left, size, result, size, 0);
9350 else if (shCount >= (size * 8))
9354 /* get sign in acc.7 */
9355 MOVA (aopGet (left, size - 1, FALSE, FALSE));
9357 addSign (result, LSB, sign);
9364 genrshOne (result, left, shCount, sign);
9368 genrshTwo (result, left, shCount, sign);
9372 genrshFour (result, left, shCount, sign);
9378 freeAsmop (result, NULL, ic, TRUE);
9379 freeAsmop (left, NULL, ic, TRUE);
9382 /*-----------------------------------------------------------------*/
9383 /* genSignedRightShift - right shift of signed number */
9384 /*-----------------------------------------------------------------*/
9386 genSignedRightShift (iCode * ic)
9388 operand *right, *left, *result;
9391 symbol *tlbl, *tlbl1;
9394 D (emitcode (";", "genSignedRightShift"));
9396 /* we do it the hard way put the shift count in b
9397 and loop thru preserving the sign */
9399 right = IC_RIGHT (ic);
9400 left = IC_LEFT (ic);
9401 result = IC_RESULT (ic);
9403 aopOp (right, ic, FALSE);
9406 if (AOP_TYPE (right) == AOP_LIT)
9408 genRightShiftLiteral (left, right, result, ic, 1);
9411 /* shift count is unknown then we have to form
9412 a loop get the loop count in B : Note: we take
9413 only the lower order byte since shifting
9414 more that 32 bits make no sense anyway, ( the
9415 largest size of an object can be only 32 bits ) */
9418 MOVB (aopGet (right, 0, FALSE, FALSE));
9419 emitcode ("inc", "b");
9420 freeAsmop (right, NULL, ic, TRUE);
9421 aopOp (left, ic, FALSE);
9422 aopOp (result, ic, FALSE);
9424 /* now move the left to the result if they are not the
9426 if (!sameRegs (AOP (left), AOP (result)) &&
9427 AOP_SIZE (result) > 1)
9430 size = AOP_SIZE (result);
9434 l = aopGet (left, offset, FALSE, TRUE);
9435 if (*l == '@' && IS_AOP_PREG (result))
9438 emitcode ("mov", "a,%s", l);
9439 aopPut (result, "a", offset);
9442 aopPut (result, l, offset);
9447 /* mov the highest order bit to OVR */
9448 tlbl = newiTempLabel (NULL);
9449 tlbl1 = newiTempLabel (NULL);
9451 size = AOP_SIZE (result);
9453 MOVA (aopGet (left, offset, FALSE, FALSE));
9454 emitcode ("rlc", "a");
9455 emitcode ("mov", "ov,c");
9456 /* if it is only one byte then */
9459 l = aopGet (left, 0, FALSE, FALSE);
9461 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9463 emitcode ("mov", "c,ov");
9464 emitcode ("rrc", "a");
9466 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9468 aopPut (result, "a", 0);
9472 reAdjustPreg (AOP (result));
9473 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9475 emitcode ("mov", "c,ov");
9478 l = aopGet (result, offset, FALSE, FALSE);
9480 emitcode ("rrc", "a");
9481 aopPut (result, "a", offset--);
9483 reAdjustPreg (AOP (result));
9485 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9489 freeAsmop (result, NULL, ic, TRUE);
9490 freeAsmop (left, NULL, ic, TRUE);
9493 /*-----------------------------------------------------------------*/
9494 /* genRightShift - generate code for right shifting */
9495 /*-----------------------------------------------------------------*/
9497 genRightShift (iCode * ic)
9499 operand *right, *left, *result;
9503 symbol *tlbl, *tlbl1;
9506 D (emitcode (";", "genRightShift"));
9508 /* if signed then we do it the hard way preserve the
9509 sign bit moving it inwards */
9510 letype = getSpec (operandType (IC_LEFT (ic)));
9512 if (!SPEC_USIGN (letype))
9514 genSignedRightShift (ic);
9518 /* signed & unsigned types are treated the same : i.e. the
9519 signed is NOT propagated inwards : quoting from the
9520 ANSI - standard : "for E1 >> E2, is equivalent to division
9521 by 2**E2 if unsigned or if it has a non-negative value,
9522 otherwise the result is implementation defined ", MY definition
9523 is that the sign does not get propagated */
9525 right = IC_RIGHT (ic);
9526 left = IC_LEFT (ic);
9527 result = IC_RESULT (ic);
9529 aopOp (right, ic, FALSE);
9531 /* if the shift count is known then do it
9532 as efficiently as possible */
9533 if (AOP_TYPE (right) == AOP_LIT)
9535 genRightShiftLiteral (left, right, result, ic, 0);
9539 /* shift count is unknown then we have to form
9540 a loop get the loop count in B : Note: we take
9541 only the lower order byte since shifting
9542 more that 32 bits make no sense anyway, ( the
9543 largest size of an object can be only 32 bits ) */
9546 MOVB (aopGet (right, 0, FALSE, FALSE));
9547 emitcode ("inc", "b");
9548 freeAsmop (right, NULL, ic, TRUE);
9549 aopOp (left, ic, FALSE);
9550 aopOp (result, ic, FALSE);
9552 /* now move the left to the result if they are not the
9554 if (!sameRegs (AOP (left), AOP (result)) &&
9555 AOP_SIZE (result) > 1)
9557 size = AOP_SIZE (result);
9561 l = aopGet (left, offset, FALSE, TRUE);
9562 if (*l == '@' && IS_AOP_PREG (result))
9565 emitcode ("mov", "a,%s", l);
9566 aopPut (result, "a", offset);
9569 aopPut (result, l, offset);
9574 tlbl = newiTempLabel (NULL);
9575 tlbl1 = newiTempLabel (NULL);
9576 size = AOP_SIZE (result);
9579 /* if it is only one byte then */
9582 l = aopGet (left, 0, FALSE, FALSE);
9584 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9587 emitcode ("rrc", "a");
9589 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9591 aopPut (result, "a", 0);
9595 reAdjustPreg (AOP (result));
9596 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9601 l = aopGet (result, offset, FALSE, FALSE);
9603 emitcode ("rrc", "a");
9604 aopPut (result, "a", offset--);
9606 reAdjustPreg (AOP (result));
9609 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9613 freeAsmop (result, NULL, ic, TRUE);
9614 freeAsmop (left, NULL, ic, TRUE);
9617 /*-----------------------------------------------------------------*/
9618 /* emitPtrByteGet - emits code to get a byte into A through a */
9619 /* pointer register (R0, R1, or DPTR). The */
9620 /* original value of A can be preserved in B. */
9621 /*-----------------------------------------------------------------*/
9623 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9630 emitcode ("mov", "b,a");
9631 emitcode ("mov", "a,@%s", rname);
9636 emitcode ("mov", "b,a");
9637 emitcode ("movx", "a,@%s", rname);
9642 emitcode ("mov", "b,a");
9643 emitcode ("movx", "a,@dptr");
9648 emitcode ("mov", "b,a");
9649 emitcode ("clr", "a");
9650 emitcode ("movc", "a,@a+dptr");
9656 emitcode ("push", "b");
9657 emitcode ("push", "acc");
9659 emitcode ("lcall", "__gptrget");
9661 emitcode ("pop", "b");
9666 /*-----------------------------------------------------------------*/
9667 /* emitPtrByteSet - emits code to set a byte from src through a */
9668 /* pointer register (R0, R1, or DPTR). */
9669 /*-----------------------------------------------------------------*/
9671 emitPtrByteSet (char *rname, int p_type, char *src)
9680 emitcode ("mov", "@%s,a", rname);
9683 emitcode ("mov", "@%s,%s", rname, src);
9688 emitcode ("movx", "@%s,a", rname);
9693 emitcode ("movx", "@dptr,a");
9698 emitcode ("lcall", "__gptrput");
9703 /*-----------------------------------------------------------------*/
9704 /* genUnpackBits - generates code for unpacking bits */
9705 /*-----------------------------------------------------------------*/
9707 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9709 int offset = 0; /* result byte offset */
9710 int rsize; /* result size */
9711 int rlen = 0; /* remaining bitfield length */
9712 sym_link *etype; /* bitfield type information */
9713 int blen; /* bitfield length */
9714 int bstr; /* bitfield starting bit within byte */
9717 D(emitcode (";", "genUnpackBits"));
9719 etype = getSpec (operandType (result));
9720 rsize = getSize (operandType (result));
9721 blen = SPEC_BLEN (etype);
9722 bstr = SPEC_BSTR (etype);
9724 if (ifx && blen <= 8)
9726 emitPtrByteGet (rname, ptype, FALSE);
9729 SNPRINTF (buffer, sizeof(buffer),
9731 genIfxJump (ifx, buffer, NULL, NULL, NULL);
9736 emitcode ("anl", "a,#0x%02x",
9737 (((unsigned char) -1) >> (8 - blen)) << bstr);
9738 genIfxJump (ifx, "a", NULL, NULL, NULL);
9744 /* If the bitfield length is less than a byte */
9747 emitPtrByteGet (rname, ptype, FALSE);
9749 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9750 if (!SPEC_USIGN (etype))
9752 /* signed bitfield */
9753 symbol *tlbl = newiTempLabel (NULL);
9755 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9756 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9759 aopPut (result, "a", offset++);
9763 /* Bit field did not fit in a byte. Copy all
9764 but the partial byte at the end. */
9765 for (rlen=blen;rlen>=8;rlen-=8)
9767 emitPtrByteGet (rname, ptype, FALSE);
9768 aopPut (result, "a", offset++);
9770 emitcode ("inc", "%s", rname);
9773 /* Handle the partial byte at the end */
9776 emitPtrByteGet (rname, ptype, FALSE);
9777 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9778 if (!SPEC_USIGN (etype))
9780 /* signed bitfield */
9781 symbol *tlbl = newiTempLabel (NULL);
9783 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9784 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9787 aopPut (result, "a", offset++);
9795 if (SPEC_USIGN (etype))
9799 /* signed bitfield: sign extension with 0x00 or 0xff */
9800 emitcode ("rlc", "a");
9801 emitcode ("subb", "a,acc");
9807 aopPut (result, source, offset++);
9812 /*-----------------------------------------------------------------*/
9813 /* genDataPointerGet - generates code when ptr offset is known */
9814 /*-----------------------------------------------------------------*/
9816 genDataPointerGet (operand * left,
9822 int size, offset = 0;
9824 D (emitcode (";", "genDataPointerGet"));
9826 aopOp (result, ic, TRUE);
9828 /* get the string representation of the name */
9829 l = aopGet (left, 0, FALSE, TRUE);
9831 size = AOP_SIZE (result);
9836 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
9840 SNPRINTF (buffer, sizeof(buffer), "%s", l);
9842 aopPut (result, buffer, offset++);
9845 freeAsmop (result, NULL, ic, TRUE);
9846 freeAsmop (left, NULL, ic, TRUE);
9849 /*-----------------------------------------------------------------*/
9850 /* genNearPointerGet - emitcode for near pointer fetch */
9851 /*-----------------------------------------------------------------*/
9853 genNearPointerGet (operand * left,
9862 sym_link *rtype, *retype;
9863 sym_link *ltype = operandType (left);
9866 D (emitcode (";", "genNearPointerGet"));
9868 rtype = operandType (result);
9869 retype = getSpec (rtype);
9871 aopOp (left, ic, FALSE);
9873 /* if left is rematerialisable and
9874 result is not bitfield variable type and
9875 the left is pointer to data space i.e
9876 lower 128 bytes of space */
9877 if (AOP_TYPE (left) == AOP_IMMD &&
9878 !IS_BITFIELD (retype) &&
9879 DCL_TYPE (ltype) == POINTER)
9881 genDataPointerGet (left, result, ic);
9885 /* if the value is already in a pointer register
9886 then don't need anything more */
9887 if (!AOP_INPREG (AOP (left)))
9889 if (IS_AOP_PREG (left))
9891 // Aha, it is a pointer, just in disguise.
9892 rname = aopGet (left, 0, FALSE, FALSE);
9895 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9896 __FILE__, __LINE__);
9901 emitcode ("mov", "a%s,%s", rname + 1, rname);
9902 rname++; // skip the '@'.
9907 /* otherwise get a free pointer register */
9909 preg = getFreePtr (ic, &aop, FALSE);
9910 emitcode ("mov", "%s,%s",
9912 aopGet (left, 0, FALSE, TRUE));
9917 rname = aopGet (left, 0, FALSE, FALSE);
9919 //aopOp (result, ic, FALSE);
9920 aopOp (result, ic, result?TRUE:FALSE);
9922 /* if bitfield then unpack the bits */
9923 if (IS_BITFIELD (retype))
9924 genUnpackBits (result, rname, POINTER, ifx);
9927 /* we have can just get the values */
9928 int size = AOP_SIZE (result);
9933 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9936 emitcode ("mov", "a,@%s", rname);
9938 aopPut (result, "a", offset);
9942 SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
9943 aopPut (result, buffer, offset);
9947 emitcode ("inc", "%s", rname);
9951 /* now some housekeeping stuff */
9952 if (aop) /* we had to allocate for this iCode */
9954 if (pi) { /* post increment present */
9955 aopPut (left, rname, 0);
9957 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9961 /* we did not allocate which means left
9962 already in a pointer register, then
9963 if size > 0 && this could be used again
9964 we have to point it back to where it
9966 if ((AOP_SIZE (result) > 1 &&
9967 !OP_SYMBOL (left)->remat &&
9968 (OP_SYMBOL (left)->liveTo > ic->seq ||
9972 int size = AOP_SIZE (result) - 1;
9974 emitcode ("dec", "%s", rname);
9978 if (ifx && !ifx->generated)
9980 genIfxJump (ifx, "a", left, NULL, result);
9984 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9985 freeAsmop (left, NULL, ic, TRUE);
9986 if (pi) pi->generated = 1;
9989 /*-----------------------------------------------------------------*/
9990 /* genPagedPointerGet - emitcode for paged pointer fetch */
9991 /*-----------------------------------------------------------------*/
9993 genPagedPointerGet (operand * left,
10002 sym_link *rtype, *retype;
10004 D (emitcode (";", "genPagedPointerGet"));
10006 rtype = operandType (result);
10007 retype = getSpec (rtype);
10009 aopOp (left, ic, FALSE);
10011 /* if the value is already in a pointer register
10012 then don't need anything more */
10013 if (!AOP_INPREG (AOP (left)))
10015 /* otherwise get a free pointer register */
10016 aop = newAsmop (0);
10017 preg = getFreePtr (ic, &aop, FALSE);
10018 emitcode ("mov", "%s,%s",
10020 aopGet (left, 0, FALSE, TRUE));
10021 rname = preg->name;
10024 rname = aopGet (left, 0, FALSE, FALSE);
10026 aopOp (result, ic, FALSE);
10028 /* if bitfield then unpack the bits */
10029 if (IS_BITFIELD (retype))
10030 genUnpackBits (result, rname, PPOINTER, ifx);
10033 /* we have can just get the values */
10034 int size = AOP_SIZE (result);
10040 emitcode ("movx", "a,@%s", rname);
10042 aopPut (result, "a", offset);
10047 emitcode ("inc", "%s", rname);
10051 /* now some housekeeping stuff */
10052 if (aop) /* we had to allocate for this iCode */
10055 aopPut (left, rname, 0);
10056 freeAsmop (NULL, aop, ic, TRUE);
10060 /* we did not allocate which means left
10061 already in a pointer register, then
10062 if size > 0 && this could be used again
10063 we have to point it back to where it
10065 if ((AOP_SIZE (result) > 1 &&
10066 !OP_SYMBOL (left)->remat &&
10067 (OP_SYMBOL (left)->liveTo > ic->seq ||
10071 int size = AOP_SIZE (result) - 1;
10073 emitcode ("dec", "%s", rname);
10077 if (ifx && !ifx->generated)
10079 genIfxJump (ifx, "a", left, NULL, result);
10083 freeAsmop (result, NULL, ic, TRUE);
10084 freeAsmop (left, NULL, ic, TRUE);
10085 if (pi) pi->generated = 1;
10088 /*--------------------------------------------------------------------*/
10089 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
10090 /*--------------------------------------------------------------------*/
10092 loadDptrFromOperand (operand *op, bool loadBToo)
10094 if (AOP_TYPE (op) != AOP_STR)
10096 /* if this is rematerializable */
10097 if (AOP_TYPE (op) == AOP_IMMD)
10099 emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
10102 if (AOP(op)->aopu.aop_immd.from_cast_remat)
10103 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
10106 wassertl(FALSE, "need pointerCode");
10107 emitcode (";", "mov b,???");
10108 /* genPointerGet and genPointerSet originally did different
10109 ** things for this case. Both seem wrong.
10110 ** from genPointerGet:
10111 ** emitcode ("mov", "b,#%d", pointerCode (retype));
10112 ** from genPointerSet:
10113 ** emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
10118 else if (AOP_TYPE (op) == AOP_DPTR)
10122 MOVA (aopGet (op, 0, FALSE, FALSE));
10123 emitcode ("push", "acc");
10124 MOVA (aopGet (op, 1, FALSE, FALSE));
10125 emitcode ("push", "acc");
10126 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10127 emitcode ("pop", "dph");
10128 emitcode ("pop", "dpl");
10132 MOVA (aopGet (op, 0, FALSE, FALSE));
10133 emitcode ("push", "acc");
10134 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10135 emitcode ("pop", "dpl");
10139 { /* we need to get it byte by byte */
10140 emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
10141 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10143 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10148 /*-----------------------------------------------------------------*/
10149 /* genFarPointerGet - get value from far space */
10150 /*-----------------------------------------------------------------*/
10152 genFarPointerGet (operand * left,
10153 operand * result, iCode * ic, iCode * pi, iCode * ifx)
10156 sym_link *retype = getSpec (operandType (result));
10158 D (emitcode (";", "genFarPointerGet"));
10160 aopOp (left, ic, FALSE);
10161 loadDptrFromOperand (left, FALSE);
10163 /* so dptr now contains the address */
10164 aopOp (result, ic, FALSE);
10166 /* if bit then unpack */
10167 if (IS_BITFIELD (retype))
10168 genUnpackBits (result, "dptr", FPOINTER, ifx);
10171 size = AOP_SIZE (result);
10176 emitcode ("movx", "a,@dptr");
10178 aopPut (result, "a", offset++);
10180 emitcode ("inc", "dptr");
10184 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10186 aopPut (left, "dpl", 0);
10187 aopPut (left, "dph", 1);
10191 if (ifx && !ifx->generated)
10193 genIfxJump (ifx, "a", left, NULL, result);
10196 freeAsmop (result, NULL, ic, TRUE);
10197 freeAsmop (left, NULL, ic, TRUE);
10200 /*-----------------------------------------------------------------*/
10201 /* genCodePointerGet - get value from code space */
10202 /*-----------------------------------------------------------------*/
10204 genCodePointerGet (operand * left,
10205 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10208 sym_link *retype = getSpec (operandType (result));
10210 D (emitcode (";", "genCodePointerGet"));
10212 aopOp (left, ic, FALSE);
10213 loadDptrFromOperand (left, FALSE);
10215 /* so dptr now contains the address */
10216 aopOp (result, ic, FALSE);
10218 /* if bit then unpack */
10219 if (IS_BITFIELD (retype))
10220 genUnpackBits (result, "dptr", CPOINTER, ifx);
10223 size = AOP_SIZE (result);
10228 emitcode ("clr", "a");
10229 emitcode ("movc", "a,@a+dptr");
10231 aopPut (result, "a", offset++);
10233 emitcode ("inc", "dptr");
10237 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10239 aopPut (left, "dpl", 0);
10240 aopPut (left, "dph", 1);
10244 if (ifx && !ifx->generated)
10246 genIfxJump (ifx, "a", left, NULL, result);
10249 freeAsmop (result, NULL, ic, TRUE);
10250 freeAsmop (left, NULL, ic, TRUE);
10253 /*-----------------------------------------------------------------*/
10254 /* genGenPointerGet - get value from generic pointer space */
10255 /*-----------------------------------------------------------------*/
10257 genGenPointerGet (operand * left,
10258 operand * result, iCode * ic, iCode *pi, iCode *ifx)
10261 sym_link *retype = getSpec (operandType (result));
10263 D (emitcode (";", "genGenPointerGet"));
10265 aopOp (left, ic, FALSE);
10266 loadDptrFromOperand (left, TRUE);
10268 /* so dptr now contains the address */
10269 aopOp (result, ic, FALSE);
10271 /* if bit then unpack */
10272 if (IS_BITFIELD (retype))
10274 genUnpackBits (result, "dptr", GPOINTER, ifx);
10278 size = AOP_SIZE (result);
10283 emitcode ("lcall", "__gptrget");
10285 aopPut (result, "a", offset++);
10287 emitcode ("inc", "dptr");
10291 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10293 aopPut (left, "dpl", 0);
10294 aopPut (left, "dph", 1);
10298 if (ifx && !ifx->generated)
10300 genIfxJump (ifx, "a", left, NULL, result);
10303 freeAsmop (result, NULL, ic, TRUE);
10304 freeAsmop (left, NULL, ic, TRUE);
10307 /*-----------------------------------------------------------------*/
10308 /* genPointerGet - generate code for pointer get */
10309 /*-----------------------------------------------------------------*/
10311 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
10313 operand *left, *result;
10314 sym_link *type, *etype;
10317 D (emitcode (";", "genPointerGet"));
10319 left = IC_LEFT (ic);
10320 result = IC_RESULT (ic);
10322 if (getSize (operandType (result))>1)
10325 /* depending on the type of pointer we need to
10326 move it to the correct pointer register */
10327 type = operandType (left);
10328 etype = getSpec (type);
10329 /* if left is of type of pointer then it is simple */
10330 if (IS_PTR (type) && !IS_FUNC (type->next))
10331 p_type = DCL_TYPE (type);
10334 /* we have to go by the storage class */
10335 p_type = PTR_TYPE (SPEC_OCLS (etype));
10338 /* special case when cast remat */
10339 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10340 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10342 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10343 type = operandType (left);
10344 p_type = DCL_TYPE (type);
10346 /* now that we have the pointer type we assign
10347 the pointer values */
10353 genNearPointerGet (left, result, ic, pi, ifx);
10357 genPagedPointerGet (left, result, ic, pi, ifx);
10361 genFarPointerGet (left, result, ic, pi, ifx);
10365 genCodePointerGet (left, result, ic, pi, ifx);
10369 genGenPointerGet (left, result, ic, pi, ifx);
10375 /*-----------------------------------------------------------------*/
10376 /* genPackBits - generates code for packed bit storage */
10377 /*-----------------------------------------------------------------*/
10379 genPackBits (sym_link * etype,
10381 char *rname, int p_type)
10383 int offset = 0; /* source byte offset */
10384 int rlen = 0; /* remaining bitfield length */
10385 int blen; /* bitfield length */
10386 int bstr; /* bitfield starting bit within byte */
10387 int litval; /* source literal value (if AOP_LIT) */
10388 unsigned char mask; /* bitmask within current byte */
10390 D(emitcode (";", "genPackBits"));
10392 blen = SPEC_BLEN (etype);
10393 bstr = SPEC_BSTR (etype);
10395 /* If the bitfield length is less than a byte */
10398 mask = ((unsigned char) (0xFF << (blen + bstr)) |
10399 (unsigned char) (0xFF >> (8 - bstr)));
10401 if (AOP_TYPE (right) == AOP_LIT)
10403 /* Case with a bitfield length <8 and literal source
10405 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10407 litval &= (~mask) & 0xff;
10408 emitPtrByteGet (rname, p_type, FALSE);
10409 if ((mask|litval)!=0xff)
10410 emitcode ("anl","a,#0x%02x", mask);
10412 emitcode ("orl","a,#0x%02x", litval);
10416 if ((blen==1) && (p_type!=GPOINTER))
10418 /* Case with a bitfield length == 1 and no generic pointer
10420 if (AOP_TYPE (right) == AOP_CRY)
10421 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10424 MOVA (aopGet (right, 0, FALSE, FALSE));
10425 emitcode ("rrc","a");
10427 emitPtrByteGet (rname, p_type, FALSE);
10428 emitcode ("mov","acc.%d,c",bstr);
10433 /* Case with a bitfield length < 8 and arbitrary source
10435 MOVA (aopGet (right, 0, FALSE, FALSE));
10436 /* shift and mask source value */
10438 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10440 pushedB = pushB ();
10441 /* transfer A to B and get next byte */
10442 emitPtrByteGet (rname, p_type, TRUE);
10444 emitcode ("anl", "a,#0x%02x", mask);
10445 emitcode ("orl", "a,b");
10446 if (p_type == GPOINTER)
10447 emitcode ("pop", "b");
10453 emitPtrByteSet (rname, p_type, "a");
10457 /* Bit length is greater than 7 bits. In this case, copy */
10458 /* all except the partial byte at the end */
10459 for (rlen=blen;rlen>=8;rlen-=8)
10461 emitPtrByteSet (rname, p_type,
10462 aopGet (right, offset++, FALSE, TRUE) );
10464 emitcode ("inc", "%s", rname);
10467 /* If there was a partial byte at the end */
10470 mask = (((unsigned char) -1 << rlen) & 0xff);
10472 if (AOP_TYPE (right) == AOP_LIT)
10474 /* Case with partial byte and literal source
10476 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10477 litval >>= (blen-rlen);
10478 litval &= (~mask) & 0xff;
10479 emitPtrByteGet (rname, p_type, FALSE);
10480 if ((mask|litval)!=0xff)
10481 emitcode ("anl","a,#0x%02x", mask);
10483 emitcode ("orl","a,#0x%02x", litval);
10488 /* Case with partial byte and arbitrary source
10490 MOVA (aopGet (right, offset++, FALSE, FALSE));
10491 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10493 pushedB = pushB ();
10494 /* transfer A to B and get next byte */
10495 emitPtrByteGet (rname, p_type, TRUE);
10497 emitcode ("anl", "a,#0x%02x", mask);
10498 emitcode ("orl", "a,b");
10499 if (p_type == GPOINTER)
10500 emitcode ("pop", "b");
10504 emitPtrByteSet (rname, p_type, "a");
10509 /*-----------------------------------------------------------------*/
10510 /* genDataPointerSet - remat pointer to data space */
10511 /*-----------------------------------------------------------------*/
10513 genDataPointerSet (operand * right,
10517 int size, offset = 0;
10518 char *l, buffer[256];
10520 D (emitcode (";", "genDataPointerSet"));
10522 aopOp (right, ic, FALSE);
10524 l = aopGet (result, 0, FALSE, TRUE);
10526 size = AOP_SIZE (right);
10530 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
10532 SNPRINTF (buffer, sizeof(buffer), "%s", l);
10533 emitcode ("mov", "%s,%s", buffer,
10534 aopGet (right, offset++, FALSE, FALSE));
10537 freeAsmop (result, NULL, ic, TRUE);
10538 freeAsmop (right, NULL, ic, TRUE);
10541 /*-----------------------------------------------------------------*/
10542 /* genNearPointerSet - emitcode for near pointer put */
10543 /*-----------------------------------------------------------------*/
10545 genNearPointerSet (operand * right,
10553 sym_link *retype, *letype;
10554 sym_link *ptype = operandType (result);
10556 D (emitcode (";", "genNearPointerSet"));
10558 retype = getSpec (operandType (right));
10559 letype = getSpec (ptype);
10561 aopOp (result, ic, FALSE);
10563 /* if the result is rematerializable &
10564 in data space & not a bit variable */
10565 if (AOP_TYPE (result) == AOP_IMMD &&
10566 DCL_TYPE (ptype) == POINTER &&
10567 !IS_BITVAR (retype) &&
10568 !IS_BITVAR (letype))
10570 genDataPointerSet (right, result, ic);
10574 /* if the value is already in a pointer register
10575 then don't need anything more */
10576 if (!AOP_INPREG (AOP (result)))
10579 //AOP_TYPE (result) == AOP_STK
10580 IS_AOP_PREG(result)
10583 // Aha, it is a pointer, just in disguise.
10584 rname = aopGet (result, 0, FALSE, FALSE);
10587 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10588 __FILE__, __LINE__);
10593 emitcode ("mov", "a%s,%s", rname + 1, rname);
10594 rname++; // skip the '@'.
10599 /* otherwise get a free pointer register */
10600 aop = newAsmop (0);
10601 preg = getFreePtr (ic, &aop, FALSE);
10602 emitcode ("mov", "%s,%s",
10604 aopGet (result, 0, FALSE, TRUE));
10605 rname = preg->name;
10610 rname = aopGet (result, 0, FALSE, FALSE);
10613 aopOp (right, ic, FALSE);
10615 /* if bitfield then unpack the bits */
10616 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10617 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10620 /* we can just get the values */
10621 int size = AOP_SIZE (right);
10626 l = aopGet (right, offset, FALSE, TRUE);
10627 if ((*l == '@') || (strcmp (l, "acc") == 0))
10630 emitcode ("mov", "@%s,a", rname);
10633 emitcode ("mov", "@%s,%s", rname, l);
10635 emitcode ("inc", "%s", rname);
10640 /* now some housekeeping stuff */
10641 if (aop) /* we had to allocate for this iCode */
10644 aopPut (result, rname, 0);
10645 freeAsmop (NULL, aop, ic, TRUE);
10649 /* we did not allocate which means left
10650 already in a pointer register, then
10651 if size > 0 && this could be used again
10652 we have to point it back to where it
10654 if ((AOP_SIZE (right) > 1 &&
10655 !OP_SYMBOL (result)->remat &&
10656 (OP_SYMBOL (result)->liveTo > ic->seq ||
10660 int size = AOP_SIZE (right) - 1;
10662 emitcode ("dec", "%s", rname);
10667 if (pi) pi->generated = 1;
10668 freeAsmop (result, NULL, ic, TRUE);
10669 freeAsmop (right, NULL, ic, TRUE);
10672 /*-----------------------------------------------------------------*/
10673 /* genPagedPointerSet - emitcode for Paged pointer put */
10674 /*-----------------------------------------------------------------*/
10676 genPagedPointerSet (operand * right,
10684 sym_link *retype, *letype;
10686 D (emitcode (";", "genPagedPointerSet"));
10688 retype = getSpec (operandType (right));
10689 letype = getSpec (operandType (result));
10691 aopOp (result, ic, FALSE);
10693 /* if the value is already in a pointer register
10694 then don't need anything more */
10695 if (!AOP_INPREG (AOP (result)))
10697 /* otherwise get a free pointer register */
10698 aop = newAsmop (0);
10699 preg = getFreePtr (ic, &aop, FALSE);
10700 emitcode ("mov", "%s,%s",
10702 aopGet (result, 0, FALSE, TRUE));
10703 rname = preg->name;
10706 rname = aopGet (result, 0, FALSE, FALSE);
10708 aopOp (right, ic, FALSE);
10710 /* if bitfield then unpack the bits */
10711 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10712 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10715 /* we have can just get the values */
10716 int size = AOP_SIZE (right);
10721 l = aopGet (right, offset, FALSE, TRUE);
10723 emitcode ("movx", "@%s,a", rname);
10726 emitcode ("inc", "%s", rname);
10732 /* now some housekeeping stuff */
10733 if (aop) /* we had to allocate for this iCode */
10736 aopPut (result, rname, 0);
10737 freeAsmop (NULL, aop, ic, TRUE);
10741 /* we did not allocate which means left
10742 already in a pointer register, then
10743 if size > 0 && this could be used again
10744 we have to point it back to where it
10746 if (AOP_SIZE (right) > 1 &&
10747 !OP_SYMBOL (result)->remat &&
10748 (OP_SYMBOL (result)->liveTo > ic->seq ||
10751 int size = AOP_SIZE (right) - 1;
10753 emitcode ("dec", "%s", rname);
10758 if (pi) pi->generated = 1;
10759 freeAsmop (result, NULL, ic, TRUE);
10760 freeAsmop (right, NULL, ic, TRUE);
10763 /*-----------------------------------------------------------------*/
10764 /* genFarPointerSet - set value from far space */
10765 /*-----------------------------------------------------------------*/
10767 genFarPointerSet (operand * right,
10768 operand * result, iCode * ic, iCode * pi)
10771 sym_link *retype = getSpec (operandType (right));
10772 sym_link *letype = getSpec (operandType (result));
10774 D(emitcode (";", "genFarPointerSet"));
10776 aopOp (result, ic, FALSE);
10777 loadDptrFromOperand (result, FALSE);
10779 /* so dptr now contains the address */
10780 aopOp (right, ic, FALSE);
10782 /* if bit then unpack */
10783 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10784 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10787 size = AOP_SIZE (right);
10792 char *l = aopGet (right, offset++, FALSE, FALSE);
10794 emitcode ("movx", "@dptr,a");
10796 emitcode ("inc", "dptr");
10799 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10800 aopPut (result, "dpl", 0);
10801 aopPut (result, "dph", 1);
10804 freeAsmop (result, NULL, ic, TRUE);
10805 freeAsmop (right, NULL, ic, TRUE);
10808 /*-----------------------------------------------------------------*/
10809 /* genGenPointerSet - set value from generic pointer space */
10810 /*-----------------------------------------------------------------*/
10812 genGenPointerSet (operand * right,
10813 operand * result, iCode * ic, iCode * pi)
10816 sym_link *retype = getSpec (operandType (right));
10817 sym_link *letype = getSpec (operandType (result));
10819 D (emitcode (";", "genGenPointerSet"));
10821 aopOp (result, ic, FALSE);
10822 loadDptrFromOperand (result, TRUE);
10824 /* so dptr now contains the address */
10825 aopOp (right, ic, FALSE);
10827 /* if bit then unpack */
10828 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10830 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10834 size = AOP_SIZE (right);
10839 char *l = aopGet (right, offset++, FALSE, FALSE);
10841 emitcode ("lcall", "__gptrput");
10843 emitcode ("inc", "dptr");
10847 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10848 aopPut (result, "dpl", 0);
10849 aopPut (result, "dph", 1);
10852 freeAsmop (result, NULL, ic, TRUE);
10853 freeAsmop (right, NULL, ic, TRUE);
10856 /*-----------------------------------------------------------------*/
10857 /* genPointerSet - stores the value into a pointer location */
10858 /*-----------------------------------------------------------------*/
10860 genPointerSet (iCode * ic, iCode *pi)
10862 operand *right, *result;
10863 sym_link *type, *etype;
10866 D (emitcode (";", "genPointerSet"));
10868 right = IC_RIGHT (ic);
10869 result = IC_RESULT (ic);
10871 /* depending on the type of pointer we need to
10872 move it to the correct pointer register */
10873 type = operandType (result);
10874 etype = getSpec (type);
10875 /* if left is of type of pointer then it is simple */
10876 if (IS_PTR (type) && !IS_FUNC (type->next))
10878 p_type = DCL_TYPE (type);
10882 /* we have to go by the storage class */
10883 p_type = PTR_TYPE (SPEC_OCLS (etype));
10886 /* special case when cast remat */
10887 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10888 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10889 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10890 type = operandType (result);
10891 p_type = DCL_TYPE (type);
10894 /* now that we have the pointer type we assign
10895 the pointer values */
10901 genNearPointerSet (right, result, ic, pi);
10905 genPagedPointerSet (right, result, ic, pi);
10909 genFarPointerSet (right, result, ic, pi);
10913 genGenPointerSet (right, result, ic, pi);
10917 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10918 "genPointerSet: illegal pointer type");
10922 /*-----------------------------------------------------------------*/
10923 /* genIfx - generate code for Ifx statement */
10924 /*-----------------------------------------------------------------*/
10926 genIfx (iCode * ic, iCode * popIc)
10928 operand *cond = IC_COND (ic);
10932 D (emitcode (";", "genIfx"));
10934 aopOp (cond, ic, FALSE);
10936 /* get the value into acc */
10937 if (AOP_TYPE (cond) != AOP_CRY)
10944 if (AOP(cond)->aopu.aop_dir)
10945 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10948 /* the result is now in the accumulator or a directly addressable bit */
10949 freeAsmop (cond, NULL, ic, TRUE);
10951 /* if there was something to be popped then do it */
10955 /* if the condition is a bit variable */
10957 genIfxJump(ic, dup, NULL, NULL, NULL);
10958 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10959 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10960 else if (isbit && !IS_ITEMP (cond))
10961 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10963 genIfxJump (ic, "a", NULL, NULL, NULL);
10968 /*-----------------------------------------------------------------*/
10969 /* genAddrOf - generates code for address of */
10970 /*-----------------------------------------------------------------*/
10972 genAddrOf (iCode * ic)
10974 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10977 D (emitcode (";", "genAddrOf"));
10979 aopOp (IC_RESULT (ic), ic, FALSE);
10981 /* if the operand is on the stack then we
10982 need to get the stack offset of this
10986 /* if it has an offset then we need to compute it */
10989 int stack_offset = ((sym->stack < 0) ?
10990 ((char) (sym->stack - _G.nRegsSaved)) :
10991 ((char) sym->stack)) & 0xff;
10992 if ((abs(stack_offset) == 1) &&
10993 !AOP_NEEDSACC(IC_RESULT (ic)) &&
10994 !isOperandVolatile (IC_RESULT (ic), FALSE))
10996 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
10997 if (stack_offset > 0)
10998 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
11000 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
11004 emitcode ("mov", "a,%s", SYM_BP (sym));
11005 emitcode ("add", "a,#0x%02x", stack_offset & 0xff);
11006 aopPut (IC_RESULT (ic), "a", 0);
11011 /* we can just move _bp */
11012 aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
11014 /* fill the result with zero */
11015 size = AOP_SIZE (IC_RESULT (ic)) - 1;
11020 aopPut (IC_RESULT (ic), zero, offset++);
11025 /* object not on stack then we need the name */
11026 size = AOP_SIZE (IC_RESULT (ic));
11031 char s[SDCC_NAME_MAX];
11033 sprintf (s, "#(%s >> %d)",
11037 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11038 aopPut (IC_RESULT (ic), s, offset++);
11042 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11046 /*-----------------------------------------------------------------*/
11047 /* genFarFarAssign - assignment when both are in far space */
11048 /*-----------------------------------------------------------------*/
11050 genFarFarAssign (operand * result, operand * right, iCode * ic)
11052 int size = AOP_SIZE (right);
11056 D (emitcode (";", "genFarFarAssign"));
11058 /* first push the right side on to the stack */
11061 l = aopGet (right, offset++, FALSE, FALSE);
11063 emitcode ("push", "acc");
11066 freeAsmop (right, NULL, ic, FALSE);
11067 /* now assign DPTR to result */
11068 aopOp (result, ic, FALSE);
11069 size = AOP_SIZE (result);
11072 emitcode ("pop", "acc");
11073 aopPut (result, "a", --offset);
11075 freeAsmop (result, NULL, ic, FALSE);
11078 /*-----------------------------------------------------------------*/
11079 /* genAssign - generate code for assignment */
11080 /*-----------------------------------------------------------------*/
11082 genAssign (iCode * ic)
11084 operand *result, *right;
11086 unsigned long lit = 0L;
11088 D (emitcode (";", "genAssign"));
11090 result = IC_RESULT (ic);
11091 right = IC_RIGHT (ic);
11093 /* if they are the same */
11094 if (operandsEqu (result, right) &&
11095 !isOperandVolatile (result, FALSE) &&
11096 !isOperandVolatile (right, FALSE))
11099 aopOp (right, ic, FALSE);
11101 /* special case both in far space */
11102 if (AOP_TYPE (right) == AOP_DPTR &&
11103 IS_TRUE_SYMOP (result) &&
11104 isOperandInFarSpace (result))
11106 genFarFarAssign (result, right, ic);
11110 aopOp (result, ic, TRUE);
11112 /* if they are the same registers */
11113 if (sameRegs (AOP (right), AOP (result)) &&
11114 !isOperandVolatile (result, FALSE) &&
11115 !isOperandVolatile (right, FALSE))
11118 /* if the result is a bit */
11119 if (AOP_TYPE (result) == AOP_CRY)
11121 assignBit (result, right);
11125 /* bit variables done */
11127 size = AOP_SIZE (result);
11129 if (AOP_TYPE (right) == AOP_LIT)
11130 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11133 (AOP_TYPE (result) != AOP_REG) &&
11134 (AOP_TYPE (right) == AOP_LIT) &&
11135 !IS_FLOAT (operandType (right)) &&
11138 while ((size) && (lit))
11141 aopGet (right, offset, FALSE, FALSE),
11147 /* And now fill the rest with zeros. */
11150 emitcode ("clr", "a");
11154 aopPut (result, "a", offset);
11163 aopGet (right, offset, FALSE, FALSE),
11170 freeAsmop (result, NULL, ic, TRUE);
11171 freeAsmop (right, NULL, ic, TRUE);
11174 /*-----------------------------------------------------------------*/
11175 /* genJumpTab - generates code for jump table */
11176 /*-----------------------------------------------------------------*/
11178 genJumpTab (iCode * ic)
11180 symbol *jtab,*jtablo,*jtabhi;
11182 unsigned int count;
11184 D (emitcode (";", "genJumpTab"));
11186 count = elementsInSet( IC_JTLABELS (ic) );
11190 /* this algorithm needs 9 cycles and 7 + 3*n bytes
11191 if the switch argument is in a register.
11192 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
11193 /* Peephole may not convert ljmp to sjmp or ret
11194 labelIsReturnOnly & labelInRange must check
11195 currPl->ic->op != JUMPTABLE */
11196 aopOp (IC_JTCOND (ic), ic, FALSE);
11197 /* get the condition into accumulator */
11198 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11200 /* multiply by three */
11201 if (aopGetUsesAcc (IC_JTCOND (ic), 0))
11203 emitcode ("mov", "b,#3");
11204 emitcode ("mul", "ab");
11208 emitcode ("add", "a,acc");
11209 emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
11211 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11213 jtab = newiTempLabel (NULL);
11214 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
11215 emitcode ("jmp", "@a+dptr");
11217 /* now generate the jump labels */
11218 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11219 jtab = setNextItem (IC_JTLABELS (ic)))
11220 emitcode ("ljmp", "%05d$", jtab->key + 100);
11224 /* this algorithm needs 14 cycles and 13 + 2*n bytes
11225 if the switch argument is in a register.
11226 For n>6 this algorithm may be more compact */
11227 jtablo = newiTempLabel (NULL);
11228 jtabhi = newiTempLabel (NULL);
11230 /* get the condition into accumulator.
11231 Using b as temporary storage, if register push/pop is needed */
11232 aopOp (IC_JTCOND (ic), ic, FALSE);
11233 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11234 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
11235 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
11237 // (MB) what if B is in use???
11238 wassertl(!BINUSE, "B was in use");
11239 emitcode ("mov", "b,%s", l);
11242 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11246 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
11247 emitcode ("movc", "a,@a+pc");
11248 emitcode ("push", "acc");
11251 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
11252 emitcode ("movc", "a,@a+pc");
11253 emitcode ("push", "acc");
11257 /* this scales up to n<=255, but needs two more bytes
11258 and changes dptr */
11259 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
11260 emitcode ("movc", "a,@a+dptr");
11261 emitcode ("push", "acc");
11264 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
11265 emitcode ("movc", "a,@a+dptr");
11266 emitcode ("push", "acc");
11269 emitcode ("ret", "");
11271 /* now generate jump table, LSB */
11272 emitLabel (jtablo);
11273 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11274 jtab = setNextItem (IC_JTLABELS (ic)))
11275 emitcode (".db", "%05d$", jtab->key + 100);
11277 /* now generate jump table, MSB */
11278 emitLabel (jtabhi);
11279 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11280 jtab = setNextItem (IC_JTLABELS (ic)))
11281 emitcode (".db", "%05d$>>8", jtab->key + 100);
11285 /*-----------------------------------------------------------------*/
11286 /* genCast - gen code for casting */
11287 /*-----------------------------------------------------------------*/
11289 genCast (iCode * ic)
11291 operand *result = IC_RESULT (ic);
11292 sym_link *ctype = operandType (IC_LEFT (ic));
11293 sym_link *rtype = operandType (IC_RIGHT (ic));
11294 operand *right = IC_RIGHT (ic);
11297 D (emitcode (";", "genCast"));
11299 /* if they are equivalent then do nothing */
11300 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11303 aopOp (right, ic, FALSE);
11304 aopOp (result, ic, FALSE);
11306 /* if the result is a bit (and not a bitfield) */
11307 if (IS_BIT (OP_SYMBOL (result)->type))
11309 assignBit (result, right);
11313 /* if they are the same size : or less */
11314 if (AOP_SIZE (result) <= AOP_SIZE (right))
11317 /* if they are in the same place */
11318 if (sameRegs (AOP (right), AOP (result)))
11321 /* if they in different places then copy */
11322 size = AOP_SIZE (result);
11327 aopGet (right, offset, FALSE, FALSE),
11334 /* if the result is of type pointer */
11335 if (IS_PTR (ctype))
11339 sym_link *type = operandType (right);
11340 sym_link *etype = getSpec (type);
11342 /* pointer to generic pointer */
11343 if (IS_GENPTR (ctype))
11347 p_type = DCL_TYPE (type);
11351 if (SPEC_SCLS(etype)==S_REGISTER) {
11352 // let's assume it is a generic pointer
11355 /* we have to go by the storage class */
11356 p_type = PTR_TYPE (SPEC_OCLS (etype));
11360 /* the first two bytes are known */
11361 size = GPTRSIZE - 1;
11366 aopGet (right, offset, FALSE, FALSE),
11370 /* the last byte depending on type */
11372 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11377 // pointerTypeToGPByte will have bitched.
11381 sprintf(gpValStr, "#0x%x", gpVal);
11382 aopPut (result, gpValStr, GPTRSIZE - 1);
11387 /* just copy the pointers */
11388 size = AOP_SIZE (result);
11393 aopGet (right, offset, FALSE, FALSE),
11400 /* so we now know that the size of destination is greater
11401 than the size of the source */
11402 /* we move to result for the size of source */
11403 size = AOP_SIZE (right);
11408 aopGet (right, offset, FALSE, FALSE),
11413 /* now depending on the sign of the source && destination */
11414 size = AOP_SIZE (result) - AOP_SIZE (right);
11415 /* if unsigned or not an integral type */
11416 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11419 aopPut (result, zero, offset++);
11423 /* we need to extend the sign :{ */
11424 char *l = aopGet (right, AOP_SIZE (right) - 1,
11427 emitcode ("rlc", "a");
11428 emitcode ("subb", "a,acc");
11430 aopPut (result, "a", offset++);
11433 /* we are done hurray !!!! */
11436 freeAsmop (result, NULL, ic, TRUE);
11437 freeAsmop (right, NULL, ic, TRUE);
11440 /*-----------------------------------------------------------------*/
11441 /* genDjnz - generate decrement & jump if not zero instrucion */
11442 /*-----------------------------------------------------------------*/
11444 genDjnz (iCode * ic, iCode * ifx)
11446 symbol *lbl, *lbl1;
11450 /* if the if condition has a false label
11451 then we cannot save */
11452 if (IC_FALSE (ifx))
11455 /* if the minus is not of the form a = a - 1 */
11456 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11457 !IS_OP_LITERAL (IC_RIGHT (ic)))
11460 if (operandLitValue (IC_RIGHT (ic)) != 1)
11463 /* if the size of this greater than one then no
11465 if (getSize (operandType (IC_RESULT (ic))) > 1)
11468 /* otherwise we can save BIG */
11470 D (emitcode (";", "genDjnz"));
11472 lbl = newiTempLabel (NULL);
11473 lbl1 = newiTempLabel (NULL);
11475 aopOp (IC_RESULT (ic), ic, FALSE);
11477 if (AOP_NEEDSACC(IC_RESULT(ic)))
11479 /* If the result is accessed indirectly via
11480 * the accumulator, we must explicitly write
11481 * it back after the decrement.
11483 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11485 if (strcmp(rByte, "a"))
11487 /* Something is hopelessly wrong */
11488 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11489 __FILE__, __LINE__);
11490 /* We can just give up; the generated code will be inefficient,
11491 * but what the hey.
11493 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11496 emitcode ("dec", "%s", rByte);
11497 aopPut (IC_RESULT (ic), rByte, 0);
11498 emitcode ("jnz", "%05d$", lbl->key + 100);
11500 else if (IS_AOP_PREG (IC_RESULT (ic)))
11502 emitcode ("dec", "%s",
11503 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11504 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11505 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11506 ifx->generated = 1;
11507 emitcode ("jnz", "%05d$", lbl->key + 100);
11511 emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11514 emitcode ("sjmp", "%05d$", lbl1->key + 100);
11516 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11519 if (!ifx->generated)
11520 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11521 ifx->generated = 1;
11525 /*-----------------------------------------------------------------*/
11526 /* genReceive - generate code for a receive iCode */
11527 /*-----------------------------------------------------------------*/
11529 genReceive (iCode * ic)
11531 int size = getSize (operandType (IC_RESULT (ic)));
11534 D (emitcode (";", "genReceive"));
11536 if (ic->argreg == 1)
11537 { /* first parameter */
11538 if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11539 isOperandInPagedSpace (IC_RESULT (ic))) &&
11540 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11541 IS_TRUE_SYMOP (IC_RESULT (ic))))
11544 int receivingA = 0;
11547 for (offset = 0; offset<size; offset++)
11548 if (!strcmp (fReturn[offset], "a"))
11553 if (size==1 || getTempRegs(tempRegs, size-1, ic))
11555 for (offset = size-1; offset>0; offset--)
11556 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11557 emitcode("mov","a,%s", fReturn[0]);
11559 aopOp (IC_RESULT (ic), ic, FALSE);
11561 aopPut (IC_RESULT (ic), "a", offset);
11562 for (offset = 1; offset<size; offset++)
11563 aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset);
11569 if (getTempRegs(tempRegs, size, ic))
11571 for (offset = 0; offset<size; offset++)
11572 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11573 aopOp (IC_RESULT (ic), ic, FALSE);
11574 for (offset = 0; offset<size; offset++)
11575 aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset);
11580 offset = fReturnSizeMCS51 - size;
11583 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11584 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11587 aopOp (IC_RESULT (ic), ic, FALSE);
11588 size = AOP_SIZE (IC_RESULT (ic));
11592 emitcode ("pop", "acc");
11593 aopPut (IC_RESULT (ic), "a", offset++);
11599 aopOp (IC_RESULT (ic), ic, FALSE);
11601 assignResultValue (IC_RESULT (ic), NULL);
11604 else if (ic->argreg > 12)
11605 { /* bit parameters */
11606 if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
11608 aopOp (IC_RESULT (ic), ic, FALSE);
11609 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11610 outBitC(IC_RESULT (ic));
11614 { /* other parameters */
11616 aopOp (IC_RESULT (ic), ic, FALSE);
11617 rb1off = ic->argreg;
11620 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
11625 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11628 /*-----------------------------------------------------------------*/
11629 /* genDummyRead - generate code for dummy read of volatiles */
11630 /*-----------------------------------------------------------------*/
11632 genDummyRead (iCode * ic)
11637 D (emitcode(";", "genDummyRead"));
11639 op = IC_RIGHT (ic);
11640 if (op && IS_SYMOP (op))
11642 aopOp (op, ic, FALSE);
11644 /* if the result is a bit */
11645 if (AOP_TYPE (op) == AOP_CRY)
11646 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11649 /* bit variables done */
11651 size = AOP_SIZE (op);
11655 MOVA (aopGet (op, offset, FALSE, FALSE));
11660 freeAsmop (op, NULL, ic, TRUE);
11664 if (op && IS_SYMOP (op))
11666 aopOp (op, ic, FALSE);
11668 /* if the result is a bit */
11669 if (AOP_TYPE (op) == AOP_CRY)
11670 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11673 /* bit variables done */
11675 size = AOP_SIZE (op);
11679 MOVA (aopGet (op, offset, FALSE, FALSE));
11684 freeAsmop (op, NULL, ic, TRUE);
11688 /*-----------------------------------------------------------------*/
11689 /* genCritical - generate code for start of a critical sequence */
11690 /*-----------------------------------------------------------------*/
11692 genCritical (iCode *ic)
11694 symbol *tlbl = newiTempLabel (NULL);
11696 D (emitcode(";", "genCritical"));
11698 if (IC_RESULT (ic))
11700 aopOp (IC_RESULT (ic), ic, TRUE);
11701 aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
11702 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11703 aopPut (IC_RESULT (ic), zero, 0);
11705 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11709 emitcode ("setb", "c");
11710 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11711 emitcode ("clr", "c");
11713 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11717 /*-----------------------------------------------------------------*/
11718 /* genEndCritical - generate code for end of a critical sequence */
11719 /*-----------------------------------------------------------------*/
11721 genEndCritical (iCode *ic)
11723 D(emitcode(";", "genEndCritical"));
11727 aopOp (IC_RIGHT (ic), ic, FALSE);
11728 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11730 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11731 emitcode ("mov", "ea,c");
11735 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11736 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11737 emitcode ("rrc", "a");
11738 emitcode ("mov", "ea,c");
11740 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11744 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11745 emitcode ("mov", "ea,c");
11749 /*-----------------------------------------------------------------*/
11750 /* gen51Code - generate code for 8051 based controllers */
11751 /*-----------------------------------------------------------------*/
11753 gen51Code (iCode * lic)
11757 /* int cseq = 0; */
11759 _G.currentFunc = NULL;
11760 lineHead = lineCurr = NULL;
11762 /* print the allocation information */
11763 if (allocInfo && currFunc)
11764 printAllocInfo (currFunc, codeOutBuf);
11765 /* if debug information required */
11766 if (options.debug && currFunc)
11768 debugFile->writeFunction (currFunc, lic);
11770 /* stack pointer name */
11771 if (options.useXstack)
11777 for (ic = lic; ic; ic = ic->next)
11779 _G.current_iCode = ic;
11781 if (ic->lineno && cln != ic->lineno)
11785 debugFile->writeCLine (ic);
11787 if (!options.noCcodeInAsm) {
11788 emitcode (";", "%s:%d: %s", ic->filename, ic->lineno,
11789 printCLine(ic->filename, ic->lineno));
11794 if (ic->seqPoint && ic->seqPoint != cseq)
11796 emitcode (";", "sequence point %d", ic->seqPoint);
11797 cseq = ic->seqPoint;
11800 if (options.iCodeInAsm) {
11801 char regsInUse[80];
11806 for (i=0; i<8; i++) {
11807 sprintf (®sInUse[i],
11808 "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11811 strcpy (regsInUse, "--------");
11812 for (i=0; i < 8; i++) {
11813 if (bitVectBitValue (ic->rMask, i))
11815 int offset = regs8051[i].offset;
11816 regsInUse[offset] = offset + '0'; /* show rMask */
11820 iLine = printILine(ic);
11821 emitcode(";", "[%s] ic:%d: %s", regsInUse, ic->seq, iLine);
11824 /* if the result is marked as
11825 spilt and rematerializable or code for
11826 this has already been generated then
11828 if (resultRemat (ic) || ic->generated)
11831 /* depending on the operation */
11851 /* IPOP happens only when trying to restore a
11852 spilt live range, if there is an ifx statement
11853 following this pop then the if statement might
11854 be using some of the registers being popped which
11855 would destory the contents of the register so
11856 we need to check for this condition and handle it */
11858 ic->next->op == IFX &&
11859 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11860 genIfx (ic->next, ic);
11878 genEndFunction (ic);
11898 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11915 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11919 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11926 /* note these two are xlated by algebraic equivalence
11927 in decorateType() in SDCCast.c */
11928 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11929 "got '>=' or '<=' shouldn't have come here");
11933 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11945 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11949 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11953 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11989 genRightShift (ic);
11992 case GET_VALUE_AT_ADDRESS:
11994 hasInc (IC_LEFT (ic), ic,
11995 getSize (operandType (IC_RESULT (ic)))),
11996 ifxForOp (IC_RESULT (ic), ic) );
12000 if (POINTER_SET (ic))
12002 hasInc (IC_RESULT (ic), ic,
12003 getSize (operandType (IC_RIGHT (ic)))));
12029 addSet (&_G.sendSet, ic);
12032 case DUMMY_READ_VOLATILE:
12041 genEndCritical (ic);
12053 _G.current_iCode = NULL;
12055 /* now we are ready to call the
12056 peep hole optimizer */
12057 if (!options.nopeep)
12058 peepHole (&lineHead);
12060 /* now do the actual printing */
12061 printLine (lineHead, codeOutBuf);