1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for DS80C390
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)
7 DS390 adaptation by Kevin Vigor <kevin@vigor.nu>
9 This program is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 2, or (at your option) any
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 In other words, you are welcome to use, share and improve this program.
24 You are forbidden to forbid anyone else to use, share and improve
25 what you give them. Help stamp out software-hoarding!
26 -------------------------------------------------------------------------*/
35 #include "SDCCglobl.h"
37 #include "dbuf_string.h"
44 #define BETTER_LITERAL_SHIFT
46 char *aopLiteral (value * val, int offset);
49 /* this is the down and dirty file with all kinds of
50 kludgy & hacky stuff. This is what it is all about
51 CODE GENERATION for a specific MCU . some of the
52 routines may be reusable, will have to see */
54 static char *zero = "#0";
55 static char *one = "#1";
58 #define TR_DPTR(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_DPTR1 %s ", s); }
59 #define TR_AP(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_AP %s ", s); }
61 unsigned fReturnSizeDS390 = 5;
62 static char *fReturn24[] =
63 {"dpl", "dph", "dpx", "b", "a"};
64 static char *fReturn16[] =
65 {"dpl", "dph", "b", "a"};
66 static char **fReturn = fReturn24;
67 static char *accUse[] =
69 static char *dptrn[2][3];
70 static char *javaRet[] = { "r0","r1","r2","r3"};
71 static short rbank = -1;
73 #define REG_WITH_INDEX ds390_regWithIdx
75 #define AOP(op) op->aop
76 #define AOP_TYPE(op) AOP(op)->type
77 #define AOP_SIZE(op) AOP(op)->size
78 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
79 AOP_TYPE(x) == AOP_R0))
81 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
82 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
85 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
86 (x->aopu.aop_reg[0] == REG_WITH_INDEX(R0_IDX) || \
87 x->aopu.aop_reg[0] == REG_WITH_INDEX(R1_IDX) )))
88 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
89 #define AOP_USESDPTR(x) ((AOP_TYPE(x) == AOP_DPTR) || (AOP_TYPE(x) == AOP_STR))
90 #define AOP_USESDPTR2(x) ((AOP_TYPE(x) == AOP_DPTR2) || (AOP_TYPE(x) == AOP_DPTRn))
92 // The following two macros can be used even if the aop has not yet been aopOp'd.
93 #define AOP_IS_STR(x) (IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
94 #define AOP_IS_DPTRn(x) (IS_SYMOP(x) && OP_SYMBOL(x)->dptr)
96 /* Workaround for DS80C390 bug: div ab may return bogus results
97 * if A is accessed in instruction immediately before the div.
99 * Will be fixed in B4 rev of processor, Dallas claims.
102 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
103 if (!AOP_NEEDSACC(RIGHT)) \
105 /* We can load A first, then B, since \
106 * B (the RIGHT operand) won't clobber A, \
107 * thus avoiding touching A right before the div. \
109 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
110 L = aopGet(LEFT,0,FALSE,FALSE,NULL); \
112 L = aopGet(RIGHT,0,FALSE,FALSE,"b"); \
117 /* Just stuff in a nop after loading A. */ \
118 emitcode("mov","b,%s",aopGet(RIGHT,0,FALSE,FALSE,NULL));\
119 L = aopGet(LEFT,0,FALSE,FALSE,NULL); \
121 emitcode("nop", "; workaround for DS80C390 div bug."); \
124 #define R0INB _G.bu.bs.r0InB
125 #define R1INB _G.bu.bs.r1InB
126 #define OPINB _G.bu.bs.OpInB
127 #define BINUSE _G.bu.BInUse
137 short r0InB : 2;//2 so we can see it overflow
138 short r1InB : 2;//2 so we can see it overflow
139 short OpInB : 2;//2 so we can see it overflow
150 iCode *current_iCode;
155 static char *rb1regs[] = {
156 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7",
157 "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7"
160 static void saveRBank (int, iCode *, bool);
162 #define RESULTONSTACK(x) \
163 (IC_RESULT(x) && IC_RESULT(x)->aop && \
164 IC_RESULT(x)->aop->type == AOP_STK )
166 #define MOVA(x) mova(x) /* use function to avoid multiple eval */
167 #define MOVB(x) movb(x)
169 #define CLRC emitcode("clr","c")
170 #define SETC emitcode("setb","c")
172 // A scratch register which will be used to hold
173 // result bytes from operands in far space via DPTR2.
174 #define DP2_RESULT_REG "_ap"
176 static lineNode *lineHead = NULL;
177 static lineNode *lineCurr = NULL;
179 static unsigned char SLMask[] =
180 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
181 0xE0, 0xC0, 0x80, 0x00};
182 static unsigned char SRMask[] =
183 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
184 0x07, 0x03, 0x01, 0x00};
190 #define PROTECT_SP {if (options.protect_sp_update) { \
191 symbol *lbl = newiTempLabel(NULL); \
192 emitcode ("setb","F1"); \
193 emitcode ("jbc","EA,!tlabel",lbl->key+100); \
194 emitcode ("clr","F1"); \
197 #define UNPROTECT_SP { if (options.protect_sp_update) { \
198 emitcode ("mov","EA,F1"); \
201 static int _currentDPS; /* Current processor DPS. */
202 static int _desiredDPS; /* DPS value compiler thinks we should be using. */
203 static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */
205 /*-----------------------------------------------------------------*/
206 /* emitcode - writes the code into a file : for now it is simple */
207 /*-----------------------------------------------------------------*/
209 emitcode (const char *inst, const char *fmt,...)
213 const char *lbp, *lb;
215 dbuf_init (&dbuf, INITIAL_INLINEASM);
221 dbuf_append_str (&dbuf, inst);
225 dbuf_append_char (&dbuf, '\t');
226 dbuf_tvprintf (&dbuf, fmt, ap);
231 dbuf_tvprintf (&dbuf, fmt, ap);
234 lbp = lb = dbuf_c_str(&dbuf);
236 while (isspace ((unsigned char)*lbp))
243 lineCurr = (lineCurr ?
244 connectLine (lineCurr, newLineNode (lb)) :
245 (lineHead = newLineNode (lb)));
248 lineCurr->isInline = _G.inLine;
249 lineCurr->isDebug = _G.debugLine;
250 lineCurr->ic = _G.current_iCode;
251 lineCurr->aln = ds390newAsmLineNode(_currentDPS);
252 lineCurr->isComment = (*lbp == ';');
259 emitLabel (symbol *tlbl)
261 emitcode ("", "!tlabeldef", tlbl->key + 100);
262 lineCurr->isLabel = 1;
265 /*-----------------------------------------------------------------*/
266 /* ds390_emitDebuggerSymbol - associate the current code location */
267 /* with a debugger symbol */
268 /*-----------------------------------------------------------------*/
270 ds390_emitDebuggerSymbol (char * debugSym)
273 emitcode ("", "%s ==.", debugSym);
277 /*-----------------------------------------------------------------*/
278 /* mova - moves specified value into accumulator */
279 /*-----------------------------------------------------------------*/
283 /* do some early peephole optimization */
284 if (!strncmp(x, "a", 2) || !strncmp(x, "acc", 4))
287 emitcode("mov", "a,%s", x);
290 /*-----------------------------------------------------------------*/
291 /* movb - moves specified value into register b */
292 /*-----------------------------------------------------------------*/
296 /* do some early peephole optimization */
297 if (!strncmp(x, "b", 2))
300 emitcode("mov","b,%s", x);
303 /*-----------------------------------------------------------------*/
304 /* movc - moves specified value into the carry */
305 /*-----------------------------------------------------------------*/
313 else if (strcmp (s, "c"))
314 {/* it's not in carry already */
316 /* set C, if a >= 1 */
317 emitcode ("add", "a,#0xff");
321 /*-----------------------------------------------------------------*/
322 /* pushB - saves register B if necessary */
323 /*-----------------------------------------------------------------*/
327 bool pushedB = FALSE;
331 emitcode ("push", "b");
332 // printf("B was in use !\n");
342 /*-----------------------------------------------------------------*/
343 /* popB - restores value of register B if necessary */
344 /*-----------------------------------------------------------------*/
350 emitcode ("pop", "b");
358 /*-----------------------------------------------------------------*/
359 /* pushReg - saves register */
360 /*-----------------------------------------------------------------*/
362 pushReg (int index, bool bits_pushed)
364 regs * reg = REG_WITH_INDEX (index);
365 if (reg->type == REG_BIT)
368 emitcode ("push", "%s", reg->base);
372 emitcode ("push", "%s", reg->dname);
376 /*-----------------------------------------------------------------*/
377 /* popReg - restores register */
378 /*-----------------------------------------------------------------*/
380 popReg (int index, bool bits_popped)
382 regs * reg = REG_WITH_INDEX (index);
383 if (reg->type == REG_BIT)
386 emitcode ("pop", "%s", reg->base);
390 emitcode ("pop", "%s", reg->dname);
394 /*-----------------------------------------------------------------*/
395 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
396 /*-----------------------------------------------------------------*/
398 getFreePtr (iCode * ic, asmop ** aopp, bool result)
403 /* the logic: if r0 & r1 used in the instruction
404 then we are in trouble otherwise */
406 /* first check if r0 & r1 are used by this
407 instruction, in which case we are in trouble */
408 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
409 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
414 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
415 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
417 /* if no usage of r0 then return it */
420 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
421 (*aopp)->type = AOP_R0;
423 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
426 /* if no usage of r1 then return it */
429 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
430 (*aopp)->type = AOP_R1;
432 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R1_IDX);
435 /* now we know they both have usage */
436 /* if r0 not used in this instruction */
439 /* push it if not already pushed */
442 emitcode ("push", "%s",
443 REG_WITH_INDEX (R0_IDX)->dname);
447 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
448 (*aopp)->type = AOP_R0;
450 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
453 /* if r1 not used then */
457 /* push it if not already pushed */
460 emitcode ("push", "%s",
461 REG_WITH_INDEX (R1_IDX)->dname);
465 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
466 (*aopp)->type = AOP_R1;
467 return REG_WITH_INDEX (R1_IDX);
471 /* I said end of world, but not quite end of world yet */
472 /* if this is a result then we can push it on the stack */
475 (*aopp)->type = AOP_STK;
479 /* now this is REALLY the end of the world */
480 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
481 "getFreePtr should never reach here");
484 return NULL; // notreached, but makes compiler happy.
488 /*-----------------------------------------------------------------*/
489 /* genSetDPTR: generate code to select which DPTR is in use (zero */
490 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */
491 /* alternate DPTR (DPL1/DPH1/DPX1). */
492 /*-----------------------------------------------------------------*/
497 /* If we are doing lazy evaluation, simply note the desired
498 * change, but don't emit any code yet.
508 emitcode ("mov", "dps,#0");
513 emitcode ("mov", "dps,#1");
517 /*------------------------------------------------------------------*/
518 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
520 /* Any code that operates on DPTR (NB: not on the individual */
521 /* components, like DPH) *must* call _flushLazyDPS() before using */
522 /* DPTR within a lazy DPS evaluation block. */
524 /* Note that aopPut and aopGet already contain the proper calls to */
525 /* _flushLazyDPS, so it is safe to use these calls within a lazy */
526 /* DPS evaluation block. */
528 /* Also, _flushLazyDPS must be called before any flow control */
529 /* operations that could potentially branch out of the block. */
531 /* Lazy DPS evaluation is simply an optimization (though an */
532 /* important one), so if in doubt, leave it out. */
533 /*------------------------------------------------------------------*/
535 _startLazyDPSEvaluation (void)
539 #ifdef BETTER_LITERAL_SHIFT
546 /*------------------------------------------------------------------*/
547 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
548 /* desired one. Call before using DPTR within a lazy DPS evaluation */
550 /*------------------------------------------------------------------*/
560 if (_desiredDPS != _currentDPS)
564 emitcode ("inc", "dps");
568 emitcode ("dec", "dps");
570 _currentDPS = _desiredDPS;
574 /*-----------------------------------------------------------------*/
575 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
577 /* Forces us back to the safe state (standard DPTR selected). */
578 /*-----------------------------------------------------------------*/
580 _endLazyDPSEvaluation (void)
582 #ifdef BETTER_LITERAL_SHIFT
600 /*-----------------------------------------------------------------*/
601 /* newAsmop - creates a new asmOp */
602 /*-----------------------------------------------------------------*/
604 newAsmop (short type)
608 aop = Safe_calloc (1, sizeof (asmop));
614 /*-----------------------------------------------------------------*/
615 /* pointerCode - returns the code for a pointer type */
616 /*-----------------------------------------------------------------*/
618 pointerCode (sym_link * etype)
621 return PTR_TYPE (SPEC_OCLS (etype));
625 /*-----------------------------------------------------------------*/
626 /* leftRightUseAcc - returns size of accumulator use by operands */
627 /*-----------------------------------------------------------------*/
629 leftRightUseAcc(iCode *ic)
638 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
639 "null iCode pointer");
646 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
649 size = getSize (OP_SYMBOL (op)->type);
654 else if (ic->op == JUMPTABLE)
657 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
660 size = getSize (OP_SYMBOL (op)->type);
668 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
671 size = getSize (OP_SYMBOL (op)->type);
676 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
679 size = getSize (OP_SYMBOL (op)->type);
691 /*-----------------------------------------------------------------*/
692 /* aopForSym - for a true symbol */
693 /*-----------------------------------------------------------------*/
695 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
699 bool accuse = leftRightUseAcc (ic) || _G.accInUse;
700 char *dpl = useDP2 ? "dpl1" : "dpl";
701 char *dph = useDP2 ? "dph1" : "dph";
702 char *dpx = useDP2 ? "dpx1" : "dpx";
704 wassertl (ic != NULL, "Got a null iCode");
705 wassertl (sym != NULL, "Got a null symbol");
707 space = SPEC_OCLS (sym->etype);
709 /* if already has one */
712 if ((sym->aop->type == AOP_DPTR && useDP2)
713 || (sym->aop->type == AOP_DPTR2 && !useDP2))
717 sym->aop->allocated++;
722 /* assign depending on the storage class */
723 /* if it is on the stack or indirectly addressable */
724 /* space we need to assign either r0 or r1 to it */
725 if ((sym->onStack && !options.stack10bit) || sym->iaccess)
727 sym->aop = aop = newAsmop (0);
728 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
729 aop->size = getSize (sym->type);
731 /* now assign the address of the variable to
732 the pointer register */
733 if (aop->type != AOP_STK)
737 signed char offset = ((sym->stack < 0) ?
738 ((signed char) (sym->stack - _G.nRegsSaved)) :
739 ((signed char) sym->stack)) & 0xff;
741 if ((abs(offset) <= 3) ||
742 (accuse && (abs(offset) <= 7)))
744 emitcode ("mov", "%s,_bp",
745 aop->aopu.aop_ptr->name);
748 emitcode ("dec", aop->aopu.aop_ptr->name);
753 emitcode ("inc", aop->aopu.aop_ptr->name);
760 emitcode ("push", "acc");
761 emitcode ("mov", "a,_bp");
762 emitcode ("add", "a,#!constbyte", offset);
763 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
765 emitcode ("pop", "acc");
770 emitcode ("mov", "%s,#%s",
771 aop->aopu.aop_ptr->name,
774 aop->paged = space->paged;
777 aop->aopu.aop_stk = sym->stack;
781 if (sym->onStack && options.stack10bit)
783 short stack_val = -((sym->stack < 0) ?
784 ((short) (sym->stack - _G.nRegsSaved)) :
785 ((short) sym->stack)) ;
787 emitcode ("push",dpl);
788 emitcode ("push",dph);
789 emitcode ("push",dpx);
791 /* It's on the 10 bit stack, which is located in
794 if (stack_val < 0 && stack_val > -5)
795 { /* between -5 & -1 */
796 if (options.model == MODEL_FLAT24)
798 emitcode ("mov", "%s,#!constbyte", dpx,
799 (options.stack_loc >> 16) & 0xff);
801 emitcode ("mov", "%s,_bpx+1", dph);
802 emitcode ("mov", "%s,_bpx", dpl);
804 emitcode ("mov","dps,#1");
806 stack_val = -stack_val;
807 while (stack_val--) {
808 emitcode ("inc","dptr");
811 emitcode("mov","dps,#0");
817 emitcode ("push", "acc");
819 emitcode ("mov", "a,_bpx");
820 emitcode ("clr","c");
821 emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
822 emitcode ("mov","%s,a", dpl);
823 emitcode ("mov","a,_bpx+1");
824 emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
825 emitcode ("mov", "%s,a", dph);
826 if (options.model == MODEL_FLAT24)
828 emitcode ("mov", "%s,#!constbyte", dpx,
829 (options.stack_loc >> 16) & 0xff);
833 emitcode ("pop", "acc");
835 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
836 aop->size = getSize (sym->type);
840 /* if in bit space */
841 if (IN_BITSPACE (space))
843 sym->aop = aop = newAsmop (AOP_CRY);
844 aop->aopu.aop_dir = sym->rname;
845 aop->size = getSize (sym->type);
848 /* if it is in direct space */
849 if (IN_DIRSPACE (space))
851 sym->aop = aop = newAsmop (AOP_DIR);
852 aop->aopu.aop_dir = sym->rname;
853 aop->size = getSize (sym->type);
857 /* special case for a function */
858 if (IS_FUNC (sym->type) && !(sym->isitmp))
860 sym->aop = aop = newAsmop (AOP_IMMD);
861 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
862 aop->size = FPTRSIZE;
866 /* only remaining is far space */
867 /* in which case DPTR gets the address */
868 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
873 emitcode ("mov", "dptr,#%s", sym->rname);
878 emitcode ("mov", "dptr,#%s", sym->rname);
880 aop->size = getSize (sym->type);
882 /* if it is in code space */
883 if (IN_CODESPACE (space))
889 /*-----------------------------------------------------------------*/
890 /* aopForRemat - rematerialzes an object */
891 /*-----------------------------------------------------------------*/
893 aopForRemat (symbol * sym)
895 iCode *ic = sym->rematiCode;
896 asmop *aop = newAsmop (AOP_IMMD);
903 val += (int) operandLitValue (IC_RIGHT (ic));
904 else if (ic->op == '-')
905 val -= (int) operandLitValue (IC_RIGHT (ic));
906 else if (IS_CAST_ICODE(ic)) {
907 sym_link *from_type = operandType(IC_RIGHT(ic));
908 aop->aopu.aop_immd.from_cast_remat = 1;
909 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
910 ptr_type = pointerTypeToGPByte (DCL_TYPE(from_type), NULL, NULL);
914 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
919 SNPRINTF (buffer, sizeof(buffer),
921 OP_SYMBOL (IC_LEFT (ic))->rname,
922 val >= 0 ? '+' : '-',
923 abs (val) & 0xffffff);
927 if (IS_ASSIGN_ICODE(ic) && isOperandLiteral(IC_RIGHT(ic)))
929 SNPRINTF(buffer, sizeof(buffer),
930 "0x%x",(int) operandLitValue (IC_RIGHT (ic)));
934 strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
938 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
939 /* set immd2 field if required */
940 if (aop->aopu.aop_immd.from_cast_remat)
942 tsprintf(buffer, sizeof(buffer), "#!constbyte",ptr_type);
943 aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
949 /*-----------------------------------------------------------------*/
950 /* aopHasRegs - returns true if aop has regs between from-to */
951 /*-----------------------------------------------------------------*/
952 static int aopHasRegs(asmop *aop, int from, int to)
956 if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
958 for (; size < aop->size ; size++) {
960 for (reg = from ; reg <= to ; reg++)
961 if (aop->aopu.aop_reg[size] == REG_WITH_INDEX(reg)) return 1;
966 /*-----------------------------------------------------------------*/
967 /* regsInCommon - two operands have some registers in common */
968 /*-----------------------------------------------------------------*/
970 regsInCommon (operand * op1, operand * op2)
975 /* if they have registers in common */
976 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
979 sym1 = OP_SYMBOL (op1);
980 sym2 = OP_SYMBOL (op2);
982 if (sym1->nRegs == 0 || sym2->nRegs == 0)
985 for (i = 0; i < sym1->nRegs; i++)
991 for (j = 0; j < sym2->nRegs; j++)
996 if (sym2->regs[j] == sym1->regs[i])
1004 /*-----------------------------------------------------------------*/
1005 /* operandsEqu - equivalent */
1006 /*-----------------------------------------------------------------*/
1008 operandsEqu (operand * op1, operand * op2)
1010 symbol *sym1, *sym2;
1012 /* if they're not symbols */
1013 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
1016 sym1 = OP_SYMBOL (op1);
1017 sym2 = OP_SYMBOL (op2);
1019 /* if both are itemps & one is spilt
1020 and the other is not then false */
1021 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
1022 sym1->isspilt != sym2->isspilt)
1025 /* if they are the same */
1029 /* if they have the same rname */
1030 if (sym1->rname[0] && sym2->rname[0] &&
1031 strcmp (sym1->rname, sym2->rname) == 0 &&
1032 !(IS_PARM (op2) && IS_ITEMP (op1)))
1035 /* if left is a tmp & right is not */
1036 if (IS_ITEMP (op1) &&
1039 (sym1->usl.spillLoc == sym2))
1042 if (IS_ITEMP (op2) &&
1046 (sym2->usl.spillLoc == sym1))
1049 /* are they spilt to the same location */
1050 if (IS_ITEMP (op2) &&
1054 (sym1->usl.spillLoc == sym2->usl.spillLoc))
1060 /*-----------------------------------------------------------------*/
1061 /* sameRegs - two asmops have the same registers */
1062 /*-----------------------------------------------------------------*/
1064 sameRegs (asmop * aop1, asmop * aop2)
1070 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
1077 if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
1080 if (aop1->type != aop2->type)
1083 if (aop1->size != aop2->size)
1086 for (i = 0; i < aop1->size; i++)
1087 if (aop1->aopu.aop_reg[i] != aop2->aopu.aop_reg[i])
1093 /*-----------------------------------------------------------------*/
1094 /* aopOp - allocates an asmop for an operand : */
1095 /*-----------------------------------------------------------------*/
1097 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
1106 /* if this a literal */
1107 if (IS_OP_LITERAL (op))
1109 op->aop = aop = newAsmop (AOP_LIT);
1110 aop->aopu.aop_lit = op->operand.valOperand;
1111 aop->size = getSize (operandType (op));
1115 /* if already has a asmop then continue */
1118 if ((op->aop->type == AOP_DPTR && useDP2)
1119 || (op->aop->type == AOP_DPTR2 && !useDP2))
1123 op->aop->allocated++;
1128 /* if the underlying symbol has a aop */
1129 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
1131 op->aop = OP_SYMBOL (op)->aop;
1132 if ((op->aop->type == AOP_DPTR && useDP2)
1133 || (op->aop->type == AOP_DPTR2 && !useDP2))
1137 op->aop->allocated++;
1142 /* if this is a true symbol */
1143 if (IS_TRUE_SYMOP (op))
1145 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
1149 /* this is a temporary : this has
1155 e) can be a return use only */
1157 sym = OP_SYMBOL (op);
1159 /* if the type is a conditional */
1160 if (sym->regType == REG_CND)
1162 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
1167 /* if it is spilt then two situations
1169 b) has a spill location */
1170 if (sym->isspilt || sym->nRegs == 0)
1173 /* rematerialize it NOW */
1176 sym->aop = op->aop = aop =
1178 aop->size = getSize (sym->type);
1185 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
1186 aop->size = getSize (sym->type);
1187 for (i = 0; i < 2; i++)
1188 aop->aopu.aop_str[i] = accUse[i];
1198 /* a AOP_STR uses DPTR, but DPTR is already in use;
1201 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
1204 aop = op->aop = sym->aop = newAsmop (AOP_STR);
1205 aop->size = getSize (sym->type);
1206 for (i = 0; i < fReturnSizeDS390; i++)
1207 aop->aopu.aop_str[i] = fReturn[i];
1211 if (sym->dptr) { /* has been allocated to a DPTRn */
1212 aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
1213 aop->size = getSize (sym->type);
1214 aop->aopu.dptr = sym->dptr;
1218 if (sym->usl.spillLoc)
1220 asmop *oldAsmOp = NULL;
1222 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1224 /* force a new aop if sizes differ */
1225 oldAsmOp = sym->usl.spillLoc->aop;
1226 sym->usl.spillLoc->aop = NULL;
1228 sym->aop = op->aop = aop =
1229 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
1230 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1232 /* Don't reuse the new aop, go with the last one */
1233 sym->usl.spillLoc->aop = oldAsmOp;
1235 aop->size = getSize (sym->type);
1239 /* else must be a dummy iTemp */
1240 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1241 aop->size = getSize (sym->type);
1245 /* if the type is a bit register */
1246 if (sym->regType == REG_BIT)
1248 sym->aop = op->aop = aop = newAsmop (AOP_CRY);
1249 aop->size = sym->nRegs;//1???
1250 aop->aopu.aop_reg[0] = sym->regs[0];
1251 aop->aopu.aop_dir = sym->regs[0]->name;
1255 /* must be in a register */
1256 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1257 aop->size = sym->nRegs;
1258 for (i = 0; i < sym->nRegs; i++)
1259 aop->aopu.aop_reg[i] = sym->regs[i];
1262 /*-----------------------------------------------------------------*/
1263 /* freeAsmop - free up the asmop given to an operand */
1264 /*----------------------------------------------------------------*/
1266 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1283 /* depending on the asmop type only three cases need work
1284 AOP_R0, AOP_R1 & AOP_STK */
1292 emitcode ("pop", "ar0");
1296 bitVectUnSetBit (ic->rUsed, R0_IDX);
1304 emitcode ("pop", "ar1");
1308 bitVectUnSetBit (ic->rUsed, R1_IDX);
1314 int stk = aop->aopu.aop_stk + aop->size;
1315 bitVectUnSetBit (ic->rUsed, R0_IDX);
1316 bitVectUnSetBit (ic->rUsed, R1_IDX);
1318 getFreePtr (ic, &aop, FALSE);
1320 if (options.stack10bit)
1322 /* I'm not sure what to do here yet... */
1325 "*** Warning: probably generating bad code for "
1326 "10 bit stack mode.\n");
1331 emitcode ("mov", "a,_bp");
1332 emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
1333 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1337 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1342 emitcode ("pop", "acc");
1343 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1346 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1349 freeAsmop (op, NULL, ic, TRUE);
1352 emitcode ("pop", "ar1");
1357 emitcode ("pop", "ar0");
1362 if (_G.dptr1InUse) {
1363 emitcode ("pop","dpx1");
1364 emitcode ("pop","dph1");
1365 emitcode ("pop","dpl1");
1370 emitcode ("pop","dpx");
1371 emitcode ("pop","dph");
1372 emitcode ("pop","dpl");
1378 /* all other cases just dealloc */
1384 OP_SYMBOL (op)->aop = NULL;
1385 /* if the symbol has a spill */
1387 SPIL_LOC (op)->aop = NULL;
1392 #define DEFAULT_ACC_WARNING 0
1393 static int saveAccWarn = DEFAULT_ACC_WARNING;
1396 /*-----------------------------------------------------------------*/
1397 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
1398 /* clobber the accumulator */
1399 /*-----------------------------------------------------------------*/
1401 aopGetUsesAcc (operand * oper, int offset)
1403 asmop * aop = AOP (oper);
1405 if (offset > (aop->size - 1))
1425 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1436 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1442 /* Error case --- will have been caught already */
1448 /*-------------------------------------------------------------------*/
1449 /* aopGet - for fetching value of the aop */
1451 /* Set saveAcc to NULL if you are sure it is OK to clobber the value */
1452 /* in the accumulator. Set it to the name of a free register */
1453 /* if acc must be preserved; the register will be used to preserve */
1454 /* acc temporarily and to return the result byte. */
1455 /*-------------------------------------------------------------------*/
1457 aopGet (operand * oper,
1463 asmop * aop = AOP (oper);
1465 /* offset is greater than
1467 if (offset > (aop->size - 1) &&
1468 aop->type != AOP_LIT)
1471 /* depending on type */
1479 /* if we need to increment it */
1480 while (offset > aop->coff)
1482 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1486 while (offset < aop->coff)
1488 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1495 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1496 return (dname ? "acc" : "a");
1498 SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1499 return Safe_strdup(buffer);
1502 assert(offset <= 3);
1503 return dptrn[aop->aopu.dptr][offset];
1508 if (aop->type == AOP_DPTR2)
1516 // if (aop->type != AOP_DPTR2)
1518 // if (saveAccWarn) { fprintf(stderr, "saveAcc for DPTR...\n"); }
1519 // emitcode(";", "spanky: saveAcc for DPTR");
1522 emitcode ("xch", "a, %s", saveAcc);
1527 while (offset > aop->coff)
1529 emitcode ("inc", "dptr");
1533 while (offset < aop->coff)
1535 emitcode ("lcall", "__decdptr");
1542 emitcode ("clr", "a");
1543 emitcode ("movc", "a,@a+dptr");
1547 emitcode ("movx", "a,@dptr");
1550 if (aop->type == AOP_DPTR2)
1558 emitcode ("xch", "a, %s", saveAcc);
1559 // if (strcmp(saveAcc, "_ap"))
1561 // emitcode(";", "spiffy: non _ap return from aopGet.");
1566 return (dname ? "acc" : "a");
1569 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1571 SNPRINTF(buffer, sizeof(buffer),
1572 "%s",aop->aopu.aop_immd.aop_immd2);
1576 SNPRINTF(buffer, sizeof(buffer),
1577 "#%s", aop->aopu.aop_immd.aop_immd1);
1583 tsprintf(buffer, sizeof(buffer),
1584 "#!his",aop->aopu.aop_immd.aop_immd1);
1587 tsprintf(buffer, sizeof(buffer),
1588 "#!hihis",aop->aopu.aop_immd.aop_immd1);
1591 tsprintf(buffer, sizeof(buffer),
1592 "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1594 default: /* should not need this (just in case) */
1595 SNPRINTF (buffer, sizeof(buffer),
1597 aop->aopu.aop_immd.aop_immd1,
1603 SNPRINTF (buffer, sizeof(buffer),
1605 aop->aopu.aop_immd.aop_immd1);
1607 return Safe_strdup(buffer);
1610 if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
1612 SNPRINTF (buffer, sizeof(buffer),
1614 aop->aopu.aop_dir, offset * 8);
1618 SNPRINTF (buffer, sizeof(buffer),
1625 SNPRINTF (buffer, sizeof(buffer),
1630 return Safe_strdup(buffer);
1634 return aop->aopu.aop_reg[offset]->dname;
1636 return aop->aopu.aop_reg[offset]->name;
1639 emitcode ("clr", "a");
1640 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1641 emitcode ("rlc", "a");
1642 return (dname ? "acc" : "a");
1645 if (!offset && dname)
1647 return aop->aopu.aop_str[offset];
1650 return aopLiteral (aop->aopu.aop_lit, offset);
1654 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1658 return aop->aopu.aop_str[offset];
1662 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1663 "aopget got unsupported aop->type");
1666 return NULL; // not reached, but makes compiler happy.
1669 /*-----------------------------------------------------------------*/
1670 /* aopPut - puts a string for a aop and indicates if acc is in use */
1671 /*-----------------------------------------------------------------*/
1673 aopPut (operand * result, const char *s, int offset)
1675 bool bvolatile = isOperandVolatile (result, FALSE);
1676 bool accuse = FALSE;
1677 asmop * aop = AOP (result);
1679 if (aop->size && offset > (aop->size - 1))
1681 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1682 "aopPut got offset > aop->size");
1686 /* will assign value to value */
1687 /* depending on where it is ofcourse */
1691 MOVA (s); /* read s in case it was volatile */
1696 if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1698 SNPRINTF (buffer, sizeof(buffer),
1700 aop->aopu.aop_dir, offset * 8);
1704 SNPRINTF (buffer, sizeof(buffer),
1706 aop->aopu.aop_dir, offset);
1710 SNPRINTF (buffer, sizeof(buffer),
1715 if (strcmp (buffer, s) || bvolatile)
1717 emitcode ("mov", "%s,%s", buffer, s);
1719 if (!strcmp (buffer, "acc"))
1726 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1727 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1730 strcmp (s, "r0") == 0 ||
1731 strcmp (s, "r1") == 0 ||
1732 strcmp (s, "r2") == 0 ||
1733 strcmp (s, "r3") == 0 ||
1734 strcmp (s, "r4") == 0 ||
1735 strcmp (s, "r5") == 0 ||
1736 strcmp (s, "r6") == 0 ||
1737 strcmp (s, "r7") == 0)
1739 emitcode ("mov", "%s,%s",
1740 aop->aopu.aop_reg[offset]->dname, s);
1744 emitcode ("mov", "%s,%s",
1745 aop->aopu.aop_reg[offset]->name, s);
1751 emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1757 if (aop->type == AOP_DPTR2)
1765 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1766 "aopPut writing to code space");
1770 while (offset > aop->coff)
1773 emitcode ("inc", "dptr");
1776 while (offset < aop->coff)
1779 emitcode ("lcall", "__decdptr");
1784 /* if not in accumulator */
1787 emitcode ("movx", "@dptr,a");
1789 if (aop->type == AOP_DPTR2)
1797 while (offset > aop->coff)
1800 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1802 while (offset < aop->coff)
1805 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1812 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1817 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1819 else if (strcmp (s, "r0") == 0 ||
1820 strcmp (s, "r1") == 0 ||
1821 strcmp (s, "r2") == 0 ||
1822 strcmp (s, "r3") == 0 ||
1823 strcmp (s, "r4") == 0 ||
1824 strcmp (s, "r5") == 0 ||
1825 strcmp (s, "r6") == 0 ||
1826 strcmp (s, "r7") == 0)
1829 SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1830 emitcode ("mov", "@%s,%s",
1831 aop->aopu.aop_ptr->name, buffer);
1835 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1840 if (strcmp (s, "a") == 0)
1841 emitcode ("push", "acc");
1845 emitcode ("push", "acc");
1847 emitcode ("push", s);
1853 /* if not bit variable */
1854 if (!aop->aopu.aop_dir)
1856 /* inefficient: move carry into A and use jz/jnz */
1857 emitcode ("clr", "a");
1858 emitcode ("rlc", "a");
1864 emitcode ("clr", "%s", aop->aopu.aop_dir);
1866 emitcode ("setb", "%s", aop->aopu.aop_dir);
1867 else if (!strcmp (s, "c"))
1868 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1869 else if (strcmp (s, aop->aopu.aop_dir))
1872 /* set C, if a >= 1 */
1873 emitcode ("add", "a,#!constbyte",0xff);
1874 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1881 if (strcmp (aop->aopu.aop_str[offset], s) || bvolatile)
1882 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1888 if (!offset && (strcmp (s, "acc") == 0) && !bvolatile)
1891 if (strcmp (aop->aopu.aop_str[offset], s) && !bvolatile)
1892 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1896 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1897 "aopPut got unsupported aop->type");
1905 /*--------------------------------------------------------------------*/
1906 /* reAdjustPreg - points a register back to where it should (coff==0) */
1907 /*--------------------------------------------------------------------*/
1909 reAdjustPreg (asmop * aop)
1911 if ((aop->coff==0) || (aop->size <= 1))
1919 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1923 if (aop->type == AOP_DPTR2)
1930 emitcode ("lcall", "__decdptr");
1933 if (aop->type == AOP_DPTR2)
1942 /*-----------------------------------------------------------------*/
1943 /* opIsGptr: returns non-zero if the passed operand is */
1944 /* a generic pointer type. */
1945 /*-----------------------------------------------------------------*/
1947 opIsGptr (operand * op)
1949 sym_link *type = operandType (op);
1951 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1958 /*-----------------------------------------------------------------*/
1959 /* getDataSize - get the operand data size */
1960 /*-----------------------------------------------------------------*/
1962 getDataSize (operand * op)
1965 size = AOP_SIZE (op);
1966 if (size == GPTRSIZE)
1968 sym_link *type = operandType (op);
1969 if (IS_GENPTR (type))
1971 /* generic pointer; arithmetic operations
1972 * should ignore the high byte (pointer type).
1980 /*-----------------------------------------------------------------*/
1981 /* outAcc - output Acc */
1982 /*-----------------------------------------------------------------*/
1984 outAcc (operand * result)
1987 size = getDataSize (result);
1990 aopPut (result, "a", 0);
1993 /* unsigned or positive */
1996 aopPut (result, zero, offset++);
2001 /*-----------------------------------------------------------------*/
2002 /* outBitC - output a bit C */
2003 /*-----------------------------------------------------------------*/
2005 outBitC (operand * result)
2007 /* if the result is bit */
2008 if (AOP_TYPE (result) == AOP_CRY)
2010 aopPut (result, "c", 0);
2014 emitcode ("clr", "a");
2015 emitcode ("rlc", "a");
2020 /*-----------------------------------------------------------------*/
2021 /* toBoolean - emit code for orl a,operator(sizeop) */
2022 /*-----------------------------------------------------------------*/
2024 toBoolean (operand * oper)
2026 int size = AOP_SIZE (oper) - 1;
2030 /* The generic part of a generic pointer should
2031 * not participate in it's truth value.
2033 * i.e. 0x10000000 is zero.
2035 if (opIsGptr (oper))
2037 D (emitcode (";", "toBoolean: generic ptr special case."));
2041 _startLazyDPSEvaluation ();
2042 MOVA (aopGet (oper, 0, FALSE, FALSE, NULL));
2043 if (AOP_NEEDSACC (oper) && size && (AOP (oper)->type != AOP_ACC))
2046 emitcode("mov", "b,a");
2049 MOVA (aopGet (oper, offset++, FALSE, FALSE, NULL));
2050 emitcode ("orl", "b,a");
2052 MOVA (aopGet (oper, offset++, FALSE, FALSE, NULL));
2053 emitcode ("orl", "a,b");
2060 emitcode ("orl", "a,%s",
2061 aopGet (oper, offset++, FALSE, FALSE, NULL));
2064 _endLazyDPSEvaluation ();
2068 /*-----------------------------------------------------------------*/
2069 /* genNot - generate code for ! operation */
2070 /*-----------------------------------------------------------------*/
2076 D (emitcode (";", "genNot"));
2078 /* assign asmOps to operand & result */
2079 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2080 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
2082 /* if in bit space then a special case */
2083 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2085 /* if left==result then cpl bit */
2086 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2088 emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2092 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2093 emitcode ("cpl", "c");
2094 outBitC (IC_RESULT (ic));
2099 toBoolean (IC_LEFT (ic));
2101 /* set C, if a == 0 */
2102 tlbl = newiTempLabel (NULL);
2103 emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
2105 outBitC (IC_RESULT (ic));
2108 /* release the aops */
2109 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2110 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2114 /*-----------------------------------------------------------------*/
2115 /* genCpl - generate code for complement */
2116 /*-----------------------------------------------------------------*/
2123 sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
2125 D(emitcode (";", "genCpl"));
2127 /* assign asmOps to operand & result */
2128 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2129 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
2131 /* special case if in bit space */
2132 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2136 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
2137 (SPEC_USIGN (letype) && IS_CHAR (letype)))
2139 /* promotion rules are responsible for this strange result:
2140 bit -> int -> ~int -> bit
2141 uchar -> int -> ~int -> bit
2143 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
2147 tlbl=newiTempLabel(NULL);
2148 l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE, NULL);
2149 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
2150 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
2151 IS_AOP_PREG (IC_LEFT (ic)))
2153 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
2158 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
2161 outBitC (IC_RESULT(ic));
2165 size = AOP_SIZE (IC_RESULT (ic));
2166 _startLazyDPSEvaluation ();
2169 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL);
2171 emitcode ("cpl", "a");
2172 aopPut (IC_RESULT (ic), "a", offset++);
2174 _endLazyDPSEvaluation ();
2178 /* release the aops */
2179 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2180 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2183 /*-----------------------------------------------------------------*/
2184 /* genUminusFloat - unary minus for floating points */
2185 /*-----------------------------------------------------------------*/
2187 genUminusFloat (operand * op, operand * result)
2189 int size, offset = 0;
2192 D (emitcode (";", "genUminusFloat"));
2194 /* for this we just copy and then flip the bit */
2196 _startLazyDPSEvaluation ();
2197 size = AOP_SIZE (op) - 1;
2202 aopGet (op, offset, FALSE, FALSE, NULL),
2207 l = aopGet (op, offset, FALSE, FALSE, NULL);
2210 emitcode ("cpl", "acc.7");
2211 aopPut (result, "a", offset);
2212 _endLazyDPSEvaluation ();
2215 /*-----------------------------------------------------------------*/
2216 /* genUminus - unary minus code generation */
2217 /*-----------------------------------------------------------------*/
2219 genUminus (iCode * ic)
2224 D (emitcode (";", "genUminus"));
2227 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2228 aopOp (IC_RESULT (ic), ic, TRUE, (AOP_TYPE(IC_LEFT (ic)) == AOP_DPTR));
2230 /* if both in bit space then special
2232 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2233 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2236 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2237 emitcode ("cpl", "c");
2238 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2242 optype = operandType (IC_LEFT (ic));
2244 /* if float then do float stuff */
2245 if (IS_FLOAT (optype))
2247 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2251 /* otherwise subtract from zero */
2252 size = AOP_SIZE (IC_LEFT (ic));
2254 _startLazyDPSEvaluation ();
2257 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL);
2258 if (!strcmp (l, "a"))
2262 emitcode ("cpl", "a");
2263 emitcode ("addc", "a,#0");
2269 emitcode ("clr", "a");
2270 emitcode ("subb", "a,%s", l);
2272 aopPut (IC_RESULT (ic), "a", offset++);
2274 _endLazyDPSEvaluation ();
2276 /* if any remaining bytes in the result */
2277 /* we just need to propagate the sign */
2278 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2280 emitcode ("rlc", "a");
2281 emitcode ("subb", "a,acc");
2283 aopPut (IC_RESULT (ic), "a", offset++);
2287 /* release the aops */
2288 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2289 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2292 /*-----------------------------------------------------------------*/
2293 /* savermask - saves registers in the mask */
2294 /*-----------------------------------------------------------------*/
2295 static void savermask(bitVect *rs_mask)
2299 if (options.useXstack)
2301 if (bitVectBitValue (rs_mask, R0_IDX))
2302 emitcode ("mov", "b,r0");
2303 emitcode ("mov", "r0,%s", spname);
2304 for (i = 0; i < ds390_nRegs; i++)
2306 if (bitVectBitValue (rs_mask, i))
2309 emitcode ("mov", "a,b");
2311 emitcode ("mov", "a,%s", REG_WITH_INDEX (i)->name);
2312 emitcode ("movx", "@r0,a");
2313 emitcode ("inc", "r0");
2316 emitcode ("mov", "%s,r0", spname);
2317 if (bitVectBitValue (rs_mask, R0_IDX))
2318 emitcode ("mov", "r0,b");
2322 bool bits_pushed = FALSE;
2323 for (i = 0; i < ds390_nRegs; i++)
2325 if (bitVectBitValue (rs_mask, i))
2327 bits_pushed = pushReg (i, bits_pushed);
2333 /*-----------------------------------------------------------------*/
2334 /* saveRegisters - will look for a call and save the registers */
2335 /*-----------------------------------------------------------------*/
2337 saveRegisters (iCode * lic)
2343 for (ic = lic; ic; ic = ic->next)
2344 if (ic->op == CALL || ic->op == PCALL)
2349 fprintf (stderr, "found parameter push with no function call\n");
2353 /* if the registers have been saved already or don't need to be then
2356 || (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))) && !TARGET_IS_DS400) )
2359 /* special case if DPTR alive across a function call then must save it
2360 even though callee saves */
2361 if (IS_SYMOP(IC_LEFT(ic)) &&
2362 IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type))
2365 rsave = newBitVect(ic->rMask->size);
2366 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2367 if (bitVectBitValue(ic->rMask,i))
2368 rsave = bitVectSetBit(rsave,i);
2370 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2374 /* save the registers in use at this time but skip the
2375 ones for the result */
2376 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2377 ds390_rUmaskForOp (IC_RESULT(ic)));
2383 /*-----------------------------------------------------------------*/
2384 /* usavermask - restore registers with mask */
2385 /*-----------------------------------------------------------------*/
2386 static void unsavermask(bitVect *rs_mask)
2390 if (options.useXstack)
2392 emitcode ("mov", "r0,%s", spname);
2393 for (i = ds390_nRegs; i >= 0; i--)
2395 if (bitVectBitValue (rs_mask, i))
2397 regs * reg = REG_WITH_INDEX (i);
2398 emitcode ("dec", "r0");
2399 emitcode ("movx", "a,@r0");
2402 emitcode ("push", "acc");
2406 emitcode ("mov", "%s,a", reg->name);
2410 emitcode ("mov", "%s,r0", spname);
2411 if (bitVectBitValue (rs_mask, R0_IDX))
2413 emitcode ("pop", "ar0");
2418 bool bits_popped = FALSE;
2419 for (i = ds390_nRegs; i >= 0; i--)
2421 if (bitVectBitValue (rs_mask, i))
2423 bits_popped = popReg (i, bits_popped);
2429 /*-----------------------------------------------------------------*/
2430 /* unsaveRegisters - pop the pushed registers */
2431 /*-----------------------------------------------------------------*/
2433 unsaveRegisters (iCode * ic)
2437 if (IS_SYMOP(IC_LEFT (ic)) &&
2438 IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2440 rsave = newBitVect(ic->rMask->size);
2441 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2442 if (bitVectBitValue(ic->rMask,i))
2443 rsave = bitVectSetBit(rsave,i);
2445 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2447 /* restore the registers in use at this time but skip the
2448 ones for the result */
2449 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2450 ds390_rUmaskForOp (IC_RESULT(ic)));
2456 /*-----------------------------------------------------------------*/
2458 /*-----------------------------------------------------------------*/
2460 pushSide (operand * oper, int size)
2463 _startLazyDPSEvaluation ();
2466 char *l = aopGet (oper, offset++, FALSE, TRUE, NULL);
2467 if (AOP_TYPE (oper) != AOP_REG &&
2468 AOP_TYPE (oper) != AOP_DIR &&
2472 emitcode ("push", "acc");
2476 emitcode ("push", "%s", l);
2479 _endLazyDPSEvaluation ();
2482 /*-----------------------------------------------------------------*/
2483 /* assignResultValue - also indicates if acc is in use afterwards */
2484 /*-----------------------------------------------------------------*/
2486 assignResultValue (operand * oper, operand * func)
2489 unsigned size = AOP_SIZE (oper);
2490 bool accuse = FALSE;
2491 bool pushedA = FALSE;
2493 if (func && IS_BIT (OP_SYM_ETYPE (func)))
2499 if (size == fReturnSizeDS390)
2501 /* I don't think this case can ever happen... */
2502 /* ACC is the last part of this. If writing the result
2503 * uses ACC, we must preserve it.
2505 if (AOP_NEEDSACC(oper))
2507 emitcode(";", "assignResultValue special case for ACC.");
2508 emitcode("push", "acc");
2514 _startLazyDPSEvaluation ();
2517 accuse |= aopPut (oper, fReturn[offset], offset);
2520 _endLazyDPSEvaluation ();
2524 emitcode ("pop", "acc");
2525 accuse |= aopPut (oper, "a", offset);
2531 /*-----------------------------------------------------------------*/
2532 /* genXpush - pushes onto the external stack */
2533 /*-----------------------------------------------------------------*/
2535 genXpush (iCode * ic)
2537 asmop *aop = newAsmop (0);
2539 int size, offset = 0;
2541 D (emitcode (";", "genXpush"));
2543 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2544 r = getFreePtr (ic, &aop, FALSE);
2546 size = AOP_SIZE (IC_LEFT (ic));
2550 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
2551 emitcode ("mov", "%s,_spx", r->name);
2552 emitcode ("inc", "_spx"); // allocate space first
2553 emitcode ("movx", "@%s,a", r->name);
2557 // allocate space first
2558 emitcode ("mov", "%s,_spx", r->name);
2560 emitcode ("add", "a,#%d", size);
2561 emitcode ("mov", "_spx,a");
2563 _startLazyDPSEvaluation ();
2566 MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE, NULL));
2567 emitcode ("movx", "@%s,a", r->name);
2568 emitcode ("inc", "%s", r->name);
2570 _endLazyDPSEvaluation ();
2573 freeAsmop (NULL, aop, ic, TRUE);
2574 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2577 /*-----------------------------------------------------------------*/
2578 /* genIpush - generate code for pushing this gets a little complex */
2579 /*-----------------------------------------------------------------*/
2581 genIpush (iCode * ic)
2583 int size, offset = 0;
2587 D (emitcode (";", "genIpush"));
2589 /* if this is not a parm push : ie. it is spill push
2590 and spill push is always done on the local stack */
2594 /* and the item is spilt then do nothing */
2595 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2598 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2599 size = AOP_SIZE (IC_LEFT (ic));
2600 /* push it on the stack */
2601 _startLazyDPSEvaluation ();
2604 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE, NULL);
2610 emitcode ("push", "%s", l);
2612 _endLazyDPSEvaluation ();
2616 /* this is a parameter push: in this case we call
2617 the routine to find the call and save those
2618 registers that need to be saved */
2621 /* if use external stack then call the external
2622 stack pushing routine */
2623 if (options.useXstack)
2629 /* then do the push */
2630 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2632 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2633 size = AOP_SIZE (IC_LEFT (ic));
2635 _startLazyDPSEvaluation ();
2638 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE, NULL);
2639 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2640 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2643 if (strcmp (l, prev) || *l == '@')
2645 emitcode ("push", "acc");
2649 emitcode ("push", "%s", l);
2653 _endLazyDPSEvaluation ();
2655 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2658 /*-----------------------------------------------------------------*/
2659 /* genIpop - recover the registers: can happen only for spilling */
2660 /*-----------------------------------------------------------------*/
2662 genIpop (iCode * ic)
2666 D (emitcode (";", "genIpop"));
2668 /* if the temp was not pushed then */
2669 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2672 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2673 size = AOP_SIZE (IC_LEFT (ic));
2674 offset = (size - 1);
2675 _startLazyDPSEvaluation ();
2678 emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2679 FALSE, TRUE, NULL));
2681 _endLazyDPSEvaluation ();
2683 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2686 /*-----------------------------------------------------------------*/
2687 /* saveRBank - saves an entire register bank on the stack */
2688 /*-----------------------------------------------------------------*/
2690 saveRBank (int bank, iCode * ic, bool pushPsw)
2693 int count = 8 + (ds390_nBitRegs/8) + (pushPsw ? 1 : 0);
2697 if (options.useXstack)
2701 /* Assume r0 is available for use. */
2702 r = REG_WITH_INDEX (R0_IDX);;
2707 r = getFreePtr (ic, &aop, FALSE);
2709 // allocate space first
2710 emitcode ("mov", "%s,_spx", r->name);
2712 emitcode ("add", "a,#%d", count);
2713 emitcode ("mov", "_spx,a");
2716 for (i = 0; i < 8; i++) /* only R0-R7 needs saving */
2718 if (options.useXstack)
2720 emitcode ("mov", "a,(%s+%d)",
2721 regs390[i].base, 8 * bank + regs390[i].offset);
2722 emitcode ("movx", "@%s,a", r->name);
2724 emitcode ("inc", "%s", r->name);
2727 emitcode ("push", "(%s+%d)",
2728 regs390[i].base, 8 * bank + regs390[i].offset);
2731 if (ds390_nBitRegs > 0)
2733 if (options.useXstack)
2735 emitcode ("mov", "a,bits");
2736 emitcode ("movx", "@%s,a", r->name);
2738 emitcode ("inc", "%s", r->name);
2742 emitcode ("push", "bits");
2749 if (options.useXstack)
2751 emitcode ("mov", "a,psw");
2752 emitcode ("movx", "@%s,a", r->name);
2756 emitcode ("push", "psw");
2759 emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2764 freeAsmop (NULL, aop, ic, TRUE);
2773 /*-----------------------------------------------------------------*/
2774 /* unsaveRBank - restores the register bank from stack */
2775 /*-----------------------------------------------------------------*/
2777 unsaveRBank (int bank, iCode * ic, bool popPsw)
2783 if (options.useXstack)
2787 /* Assume r0 is available for use. */
2788 r = REG_WITH_INDEX (R0_IDX);;
2793 r = getFreePtr (ic, &aop, FALSE);
2795 emitcode ("mov", "%s,_spx", r->name);
2800 if (options.useXstack)
2802 emitcode ("dec", "%s", r->name);
2803 emitcode ("movx", "a,@%s", r->name);
2804 emitcode ("mov", "psw,a");
2808 emitcode ("pop", "psw");
2812 if (ds390_nBitRegs > 0)
2814 if (options.useXstack)
2816 emitcode ("dec", "%s", r->name);
2817 emitcode ("movx", "a,@%s", r->name);
2818 emitcode ("mov", "bits,a");
2822 emitcode ("pop", "bits");
2826 for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2828 if (options.useXstack)
2830 emitcode ("dec", "%s", r->name);
2831 emitcode ("movx", "a,@%s", r->name);
2832 emitcode ("mov", "(%s+%d),a",
2833 regs390[i].base, 8 * bank + regs390[i].offset);
2837 emitcode ("pop", "(%s+%d)",
2838 regs390[i].base, 8 * bank + regs390[i].offset);
2842 if (options.useXstack)
2844 emitcode ("mov", "_spx,%s", r->name);
2849 freeAsmop (NULL, aop, ic, TRUE);
2853 /*-----------------------------------------------------------------*/
2854 /* genSend - gen code for SEND */
2855 /*-----------------------------------------------------------------*/
2856 static void genSend(set *sendSet)
2861 static int rb1_count = 0;
2863 /* first we do all bit parameters */
2864 for (sic = setFirstItem (sendSet); sic;
2865 sic = setNextItem (sendSet))
2867 if (sic->argreg > 12)
2869 int bit = sic->argreg-13;
2871 aopOp (IC_LEFT (sic), sic, FALSE,
2872 (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2874 /* if left is a literal then
2875 we know what the value is */
2876 if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2878 if (((int) operandLitValue (IC_LEFT (sic))))
2879 emitcode ("setb", "b[%d]", bit);
2881 emitcode ("clr", "b[%d]", bit);
2883 else if (AOP_TYPE (IC_LEFT (sic)) == AOP_CRY)
2885 char *l = AOP (IC_LEFT (sic))->aopu.aop_dir;
2886 if (strcmp (l, "c"))
2887 emitcode ("mov", "c,%s", l);
2888 emitcode ("mov", "b[%d],c", bit);
2893 toBoolean (IC_LEFT (sic));
2894 /* set C, if a >= 1 */
2895 emitcode ("add", "a,#0xff");
2896 emitcode ("mov", "b[%d],c", bit);
2901 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2907 saveRegisters (setFirstItem (sendSet));
2908 emitcode ("mov", "bits,b");
2911 /* then we do all other parameters */
2912 for (sic = setFirstItem (sendSet); sic;
2913 sic = setNextItem (sendSet))
2915 if (sic->argreg <= 12)
2917 int size, offset = 0;
2919 size = getSize (operandType (IC_LEFT (sic)));
2920 D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2921 if (sendCount == 0) { /* first parameter */
2922 // we know that dpl(hxb) is the result, so
2924 _startLazyDPSEvaluation ();
2926 aopOp (IC_LEFT (sic), sic, FALSE,
2927 (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2929 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2933 char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE, NULL);
2934 if (strcmp (l, fReturn[offset]))
2936 emitcode ("mov", "%s,%s", fReturn[offset], l);
2940 _endLazyDPSEvaluation ();
2941 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2943 } else { /* if more parameter in registers */
2944 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2946 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (IC_LEFT (sic), offset++,
2947 FALSE, FALSE, NULL));
2949 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2957 adjustEsp(const char *reg)
2959 emitcode ("anl","%s,#3", reg);
2960 if (TARGET_IS_DS400)
2962 emitcode ("orl","%s,#!constbyte",
2964 (options.stack_loc >> 8) & 0xff);
2968 /*-----------------------------------------------------------------*/
2969 /* selectRegBank - emit code to select the register bank */
2970 /*-----------------------------------------------------------------*/
2972 selectRegBank (short bank, bool keepFlags)
2974 /* if f.e. result is in carry */
2977 emitcode ("anl", "psw,#0xE7");
2979 emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2983 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2987 /*-----------------------------------------------------------------*/
2988 /* genCall - generates a call statement */
2989 /*-----------------------------------------------------------------*/
2991 genCall (iCode * ic)
2995 bool restoreBank = FALSE;
2996 bool swapBanks = FALSE;
2997 bool accuse = FALSE;
2998 bool accPushed = FALSE;
2999 bool resultInF0 = FALSE;
3000 bool assignResultGenerated = FALSE;
3002 D (emitcode (";", "genCall"));
3004 /* if we are calling a not _naked function that is not using
3005 the same register bank then we need to save the
3006 destination registers on the stack */
3007 dtype = operandType (IC_LEFT (ic));
3008 etype = getSpec(dtype);
3009 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
3010 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
3011 IFFUNC_ISISR (currFunc->type))
3015 /* This is unexpected; the bank should have been saved in
3018 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
3024 /* if caller saves & we have not saved then */
3028 /* if send set is not empty then assign */
3029 /* We've saved all the registers we care about;
3030 * therefore, we may clobber any register not used
3031 * in the calling convention (i.e. anything not in
3036 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
3037 genSend(reverseSet(_G.sendSet));
3039 genSend(_G.sendSet);
3046 emitcode ("mov", "psw,#!constbyte",
3047 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3051 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
3052 OP_SYMBOL (IC_LEFT (ic))->rname :
3053 OP_SYMBOL (IC_LEFT (ic))->name));
3057 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
3060 /* if we need assign a result value */
3061 if ((IS_ITEMP (IC_RESULT (ic)) &&
3062 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3063 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3064 OP_SYMBOL (IC_RESULT (ic))->accuse ||
3065 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3066 IS_TRUE_SYMOP (IC_RESULT (ic)))
3068 if (isOperandInFarSpace (IC_RESULT (ic))
3069 && getSize (operandType (IC_RESULT (ic))) <= 2)
3071 int size = getSize (operandType (IC_RESULT (ic)));
3072 bool pushedB = FALSE;
3074 /* Special case for 1 or 2 byte return in far space. */
3079 emitcode ("mov", "b,%s", fReturn[1]);
3083 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
3088 aopPut (IC_RESULT (ic), "a", 0);
3092 aopPut (IC_RESULT (ic), "b", 1);
3094 assignResultGenerated = TRUE;
3095 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3099 bool pushedB = pushB ();
3100 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
3103 accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3104 assignResultGenerated = TRUE;
3105 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3109 /* adjust the stack for parameters if required */
3113 if (options.stack10bit) {
3114 if (ic->parmBytes <= 10) {
3115 emitcode(";","stack adjustment for parms");
3116 for (i=0; i < ic->parmBytes ; i++) {
3117 emitcode("pop","acc");
3121 emitcode ("clr","c");
3122 emitcode ("mov","a,sp");
3123 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
3124 emitcode ("mov","sp,a");
3125 emitcode ("mov","a,esp");
3127 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
3128 emitcode ("mov","esp,a");
3132 if (ic->parmBytes > 3)
3136 emitcode ("push", "acc");
3139 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3140 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3141 !assignResultGenerated)
3143 emitcode ("mov", "F0,c");
3147 emitcode ("mov", "a,%s", spname);
3148 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
3149 emitcode ("mov", "%s,a", spname);
3151 /* unsaveRegisters from xstack needs acc, but */
3152 /* unsaveRegisters from stack needs this popped */
3153 if (accPushed && !options.useXstack)
3155 emitcode ("pop", "acc");
3160 for (i = 0; i < ic->parmBytes; i++)
3161 emitcode ("dec", "%s", spname);
3165 /* if we had saved some registers then unsave them */
3166 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3168 if (accuse && !accPushed && options.useXstack)
3170 /* xstack needs acc, but doesn't touch normal stack */
3171 emitcode ("push", "acc");
3174 unsaveRegisters (ic);
3177 /* if register bank was saved then pop them */
3179 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
3181 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
3184 emitcode ("mov", "c,F0");
3186 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
3187 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3188 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3192 emitcode ("pop", "acc");
3195 /*-----------------------------------------------------------------*/
3196 /* genPcall - generates a call by pointer statement */
3197 /*-----------------------------------------------------------------*/
3199 genPcall (iCode * ic)
3203 symbol *rlbl = newiTempLabel (NULL);
3204 bool restoreBank=FALSE;
3205 bool resultInF0 = FALSE;
3207 D (emitcode (";", "genPcall"));
3209 dtype = operandType (IC_LEFT (ic))->next;
3210 etype = getSpec(dtype);
3211 /* if caller saves & we have not saved then */
3215 /* if we are calling a not _naked function that is not using
3216 the same register bank then we need to save the
3217 destination registers on the stack */
3218 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
3219 IFFUNC_ISISR (currFunc->type) &&
3220 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
3221 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3225 /* push the return address on to the stack */
3226 emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
3227 emitcode ("push", "acc");
3228 emitcode ("mov", "a,#!hil", (rlbl->key + 100));
3229 emitcode ("push", "acc");
3231 if (options.model == MODEL_FLAT24)
3233 emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
3234 emitcode ("push", "acc");
3237 /* now push the calling address */
3238 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3240 pushSide (IC_LEFT (ic), FPTRSIZE);
3242 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3244 /* if send set is not empty the assign */
3247 genSend(reverseSet(_G.sendSet));
3252 emitcode ("ret", "");
3256 /* if we need assign a result value */
3257 if ((IS_ITEMP (IC_RESULT (ic)) &&
3258 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3259 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3260 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3261 IS_TRUE_SYMOP (IC_RESULT (ic)))
3265 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
3268 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3270 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3273 /* adjust the stack for parameters if required */
3277 if (options.stack10bit) {
3278 if (ic->parmBytes <= 10) {
3279 emitcode(";","stack adjustment for parms");
3280 for (i=0; i < ic->parmBytes ; i++) {
3281 emitcode("pop","acc");
3284 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3285 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3287 emitcode ("mov", "F0,c");
3292 emitcode ("clr","c");
3293 emitcode ("mov","a,sp");
3294 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
3295 emitcode ("mov","sp,a");
3296 emitcode ("mov","a,esp");
3298 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
3299 emitcode ("mov","esp,a");
3303 if (ic->parmBytes > 3) {
3304 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3305 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3307 emitcode ("mov", "F0,c");
3311 emitcode ("mov", "a,%s", spname);
3312 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
3313 emitcode ("mov", "%s,a", spname);
3316 for (i = 0; i < ic->parmBytes; i++)
3317 emitcode ("dec", "%s", spname);
3320 /* if register bank was saved then unsave them */
3322 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3324 /* if we had saved some registers then unsave them */
3326 unsaveRegisters (ic);
3328 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3331 emitcode ("mov", "c,F0");
3333 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
3334 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3335 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3339 /*-----------------------------------------------------------------*/
3340 /* resultRemat - result is rematerializable */
3341 /*-----------------------------------------------------------------*/
3343 resultRemat (iCode * ic)
3345 if (SKIP_IC (ic) || ic->op == IFX)
3348 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3350 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3351 if (sym->remat && !POINTER_SET (ic))
3358 #if defined(__BORLANDC__) || defined(_MSC_VER)
3359 #define STRCASECMP stricmp
3361 #define STRCASECMP strcasecmp
3364 /*-----------------------------------------------------------------*/
3365 /* inExcludeList - return 1 if the string is in exclude Reg list */
3366 /*-----------------------------------------------------------------*/
3368 regsCmp(void *p1, void *p2)
3370 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3374 inExcludeList (char *s)
3376 const char *p = setFirstItem(options.excludeRegsSet);
3378 if (p == NULL || STRCASECMP(p, "none") == 0)
3382 return isinSetWith(options.excludeRegsSet, s, regsCmp);
3385 /*-----------------------------------------------------------------*/
3386 /* genFunction - generated code for function entry */
3387 /*-----------------------------------------------------------------*/
3389 genFunction (iCode * ic)
3391 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3393 bool switchedPSW = FALSE;
3394 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3396 D (emitcode (";", "genFunction"));
3399 /* create the function header */
3400 emitcode (";", "-----------------------------------------");
3401 emitcode (";", " function %s", sym->name);
3402 emitcode (";", "-----------------------------------------");
3404 emitcode ("", "%s:", sym->rname);
3405 lineCurr->isLabel = 1;
3406 ftype = operandType (IC_LEFT (ic));
3407 _G.currentFunc = sym;
3409 if (IFFUNC_ISNAKED(ftype))
3411 emitcode(";", "naked function: no prologue.");
3415 if (options.stack_probe)
3416 emitcode ("lcall","__stack_probe");
3418 /* here we need to generate the equates for the
3419 register bank if required */
3420 if (FUNC_REGBANK (ftype) != rbank)
3424 rbank = FUNC_REGBANK (ftype);
3425 for (i = 0; i < ds390_nRegs; i++)
3427 if (regs390[i].print) {
3428 if (strcmp (regs390[i].base, "0") == 0)
3429 emitcode ("", "%s !equ !constbyte",
3431 8 * rbank + regs390[i].offset);
3433 emitcode ("", "%s !equ %s + !constbyte",
3436 8 * rbank + regs390[i].offset);
3441 /* if this is an interrupt service routine then
3442 save acc, b, dpl, dph */
3443 if (IFFUNC_ISISR (sym->type))
3445 if (!inExcludeList ("acc"))
3446 emitcode ("push", "acc");
3447 if (!inExcludeList ("b"))
3448 emitcode ("push", "b");
3449 if (!inExcludeList ("dpl"))
3450 emitcode ("push", "dpl");
3451 if (!inExcludeList ("dph"))
3452 emitcode ("push", "dph");
3453 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3455 emitcode ("push", "dpx");
3456 /* Make sure we're using standard DPTR */
3457 emitcode ("push", "dps");
3458 emitcode ("mov", "dps,#0");
3459 if (options.stack10bit)
3461 /* This ISR could conceivably use DPTR2. Better save it. */
3462 emitcode ("push", "dpl1");
3463 emitcode ("push", "dph1");
3464 emitcode ("push", "dpx1");
3465 emitcode ("push", DP2_RESULT_REG);
3468 /* if this isr has no bank i.e. is going to
3469 run with bank 0 , then we need to save more
3471 if (!FUNC_REGBANK (sym->type))
3475 /* if this function does not call any other
3476 function then we can be economical and
3477 save only those registers that are used */
3478 if (!IFFUNC_HASFCALL(sym->type))
3480 /* if any registers used */
3483 bool bits_pushed = FALSE;
3484 /* save the registers used */
3485 for (i = 0; i < sym->regsUsed->size; i++)
3487 if (bitVectBitValue (sym->regsUsed, i))
3488 bits_pushed = pushReg (i, bits_pushed);
3494 /* this function has a function call. We cannot
3495 determine register usage so we will have to push the
3497 saveRBank (0, ic, FALSE);
3498 if (options.parms_in_bank1) {
3499 for (i=0; i < 8 ; i++ ) {
3500 emitcode ("push","%s",rb1regs[i]);
3507 /* This ISR uses a non-zero bank.
3509 * We assume that the bank is available for our
3512 * However, if this ISR calls a function which uses some
3513 * other bank, we must save that bank entirely.
3515 unsigned long banksToSave = 0;
3517 if (IFFUNC_HASFCALL(sym->type))
3520 #define MAX_REGISTER_BANKS 4
3525 for (i = ic; i; i = i->next)
3527 if (i->op == ENDFUNCTION)
3529 /* we got to the end OK. */
3537 dtype = operandType (IC_LEFT(i));
3539 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3541 /* Mark this bank for saving. */
3542 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3544 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3548 banksToSave |= (1 << FUNC_REGBANK(dtype));
3551 /* And note that we don't need to do it in
3559 /* This is a mess; we have no idea what
3560 * register bank the called function might
3563 * The only thing I can think of to do is
3564 * throw a warning and hope.
3566 werror(W_FUNCPTR_IN_USING_ISR);
3570 if (banksToSave && options.useXstack)
3572 /* Since we aren't passing it an ic,
3573 * saveRBank will assume r0 is available to abuse.
3575 * So switch to our (trashable) bank now, so
3576 * the caller's R0 isn't trashed.
3578 emitcode ("push", "psw");
3579 emitcode ("mov", "psw,#!constbyte",
3580 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3584 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3586 if (banksToSave & (1 << ix))
3588 saveRBank(ix, NULL, FALSE);
3592 // TODO: this needs a closer look
3593 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3598 /* if callee-save to be used for this function
3599 then save the registers being used in this function */
3600 if (IFFUNC_CALLEESAVES(sym->type))
3604 /* if any registers used */
3607 bool bits_pushed = FALSE;
3608 /* save the registers used */
3609 for (i = 0; i < sym->regsUsed->size; i++)
3611 if (bitVectBitValue (sym->regsUsed, i))
3613 bits_pushed = pushReg (i, bits_pushed);
3621 /* set the register bank to the desired value */
3622 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3625 emitcode ("push", "psw");
3626 emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3630 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3631 if (options.stack10bit) {
3632 emitcode ("push","_bpx");
3633 emitcode ("push","_bpx+1");
3634 emitcode ("mov","_bpx,%s",spname);
3635 emitcode ("mov","_bpx+1,esp");
3636 adjustEsp("_bpx+1");
3638 if (options.useXstack)
3640 emitcode ("mov", "r0,%s", spname);
3641 emitcode ("mov", "a,_bp");
3642 emitcode ("movx", "@r0,a");
3643 emitcode ("inc", "%s", spname);
3645 /* set up the stack */
3646 emitcode ("push", "_bp"); /* save the callers stack */
3648 emitcode ("mov", "_bp,%s", spname);
3652 /* adjust the stack for the function */
3655 if (options.stack10bit) {
3656 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
3657 assert (sym->recvSize <= 4);
3658 if (sym->stack <= 8) {
3659 while (i--) emitcode ("push","acc");
3662 emitcode ("mov","a,sp");
3663 emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3664 emitcode ("mov","sp,a");
3665 emitcode ("mov","a,esp");
3667 emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3668 emitcode ("mov","esp,a");
3673 werror (W_STACK_OVERFLOW, sym->name);
3675 if (i > 3 && sym->recvSize < 4) {
3677 emitcode ("mov", "a,sp");
3678 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3679 emitcode ("mov", "sp,a");
3683 emitcode ("inc", "sp");
3690 emitcode ("mov", "a,_spx");
3691 emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3692 emitcode ("mov", "_spx,a");
3695 /* if critical function then turn interrupts off */
3696 if (IFFUNC_ISCRITICAL (ftype))
3698 symbol *tlbl = newiTempLabel (NULL);
3699 emitcode ("setb", "c");
3700 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3701 emitcode ("clr", "c");
3703 emitcode ("push", "psw"); /* save old ea via c in psw */
3707 /*-----------------------------------------------------------------*/
3708 /* genEndFunction - generates epilogue for functions */
3709 /*-----------------------------------------------------------------*/
3711 genEndFunction (iCode * ic)
3713 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3714 lineNode *lnp = lineCurr;
3716 bitVect *regsUsedPrologue;
3717 bitVect *regsUnneeded;
3720 D (emitcode (";", "genEndFunction"));
3722 _G.currentFunc = NULL;
3723 if (IFFUNC_ISNAKED(sym->type))
3725 emitcode(";", "naked function: no epilogue.");
3726 if (options.debug && currFunc)
3727 debugFile->writeEndFunction (currFunc, ic, 0);
3731 if (IFFUNC_ISCRITICAL (sym->type))
3733 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3735 emitcode ("rlc", "a"); /* save c in a */
3736 emitcode ("pop", "psw"); /* restore ea via c in psw */
3737 emitcode ("mov", "ea,c");
3738 emitcode ("rrc", "a"); /* restore c from a */
3742 emitcode ("pop", "psw"); /* restore ea via c in psw */
3743 emitcode ("mov", "ea,c");
3747 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3748 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3750 if (options.stack10bit) {
3752 emitcode ("mov", "sp,_bpx", spname);
3753 emitcode ("mov", "esp,_bpx+1", spname);
3756 emitcode ("mov", "%s,_bp", spname);
3760 /* if use external stack but some variables were
3761 added to the local stack then decrement the
3763 if (options.useXstack && sym->stack) {
3764 emitcode ("mov", "a,sp");
3765 emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3766 emitcode ("mov", "sp,a");
3770 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3771 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3773 if (options.useXstack) {
3774 emitcode ("mov", "r0,%s", spname);
3775 emitcode ("movx", "a,@r0");
3776 emitcode ("mov", "_bp,a");
3777 emitcode ("dec", "%s", spname);
3779 if (options.stack10bit) {
3780 emitcode ("pop", "_bpx+1");
3781 emitcode ("pop", "_bpx");
3783 emitcode ("pop", "_bp");
3788 /* restore the register bank */
3789 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3791 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3792 || !options.useXstack)
3794 /* Special case of ISR using non-zero bank with useXstack
3797 emitcode ("pop", "psw");
3801 if (IFFUNC_ISISR (sym->type))
3804 /* now we need to restore the registers */
3805 /* if this isr has no bank i.e. is going to
3806 run with bank 0 , then we need to save more
3808 if (!FUNC_REGBANK (sym->type))
3811 /* if this function does not call any other
3812 function then we can be economical and
3813 save only those registers that are used */
3814 if (!IFFUNC_HASFCALL(sym->type))
3816 /* if any registers used */
3819 bool bits_popped = FALSE;
3820 /* save the registers used */
3821 for (i = sym->regsUsed->size; i >= 0; i--)
3823 if (bitVectBitValue (sym->regsUsed, i))
3824 bits_popped = popReg (i, bits_popped);
3830 /* this function has a function call. We cannot
3831 determine register usage so we will have to pop the
3833 if (options.parms_in_bank1) {
3834 for (i = 7 ; i >= 0 ; i-- ) {
3835 emitcode ("pop","%s",rb1regs[i]);
3838 unsaveRBank (0, ic, FALSE);
3843 /* This ISR uses a non-zero bank.
3845 * Restore any register banks saved by genFunction
3848 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3851 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3853 if (savedBanks & (1 << ix))
3855 unsaveRBank(ix, NULL, FALSE);
3859 if (options.useXstack)
3861 /* Restore bank AFTER calling unsaveRBank,
3862 * since it can trash r0.
3864 emitcode ("pop", "psw");
3868 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3870 if (options.stack10bit)
3872 emitcode ("pop", DP2_RESULT_REG);
3873 emitcode ("pop", "dpx1");
3874 emitcode ("pop", "dph1");
3875 emitcode ("pop", "dpl1");
3877 emitcode ("pop", "dps");
3878 emitcode ("pop", "dpx");
3880 if (!inExcludeList ("dph"))
3881 emitcode ("pop", "dph");
3882 if (!inExcludeList ("dpl"))
3883 emitcode ("pop", "dpl");
3884 if (!inExcludeList ("b"))
3885 emitcode ("pop", "b");
3886 if (!inExcludeList ("acc"))
3887 emitcode ("pop", "acc");
3889 /* if debug then send end of function */
3890 if (options.debug && currFunc)
3892 debugFile->writeEndFunction (currFunc, ic, 1);
3895 emitcode ("reti", "");
3899 if (IFFUNC_CALLEESAVES(sym->type))
3903 /* if any registers used */
3906 /* save the registers used */
3907 for (i = sym->regsUsed->size; i >= 0; i--)
3909 if (bitVectBitValue (sym->regsUsed, i))
3910 emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
3915 /* if debug then send end of function */
3916 if (options.debug && currFunc)
3918 debugFile->writeEndFunction (currFunc, ic, 1);
3921 emitcode ("ret", "");
3924 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3927 /* If this was an interrupt handler using bank 0 that called another */
3928 /* function, then all registers must be saved; nothing to optimized. */
3929 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3930 && !FUNC_REGBANK(sym->type))
3933 /* There are no push/pops to optimize if not callee-saves or ISR */
3934 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3937 /* If there were stack parameters, we cannot optimize without also */
3938 /* fixing all of the stack offsets; this is too dificult to consider. */
3939 if (FUNC_HASSTACKPARM(sym->type))
3942 /* Compute the registers actually used */
3943 regsUsed = newBitVect (ds390_nRegs);
3944 regsUsedPrologue = newBitVect (ds390_nRegs);
3947 if (lnp->ic && lnp->ic->op == FUNCTION)
3948 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3950 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3952 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3953 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3960 if (bitVectBitValue (regsUsedPrologue, DPS_IDX)
3961 && !bitVectBitValue (regsUsed, DPS_IDX))
3963 bitVectUnSetBit (regsUsedPrologue, DPS_IDX);
3966 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3967 && !bitVectBitValue (regsUsed, CND_IDX))
3969 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3970 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3971 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3972 bitVectUnSetBit (regsUsed, CND_IDX);
3975 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3977 /* If this was an interrupt handler that called another function */
3978 /* function, then assume working registers may be modified by it. */
3979 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3981 regsUsed = bitVectSetBit (regsUsed, AP_IDX);
3982 regsUsed = bitVectSetBit (regsUsed, DPX1_IDX);
3983 regsUsed = bitVectSetBit (regsUsed, DPL1_IDX);
3984 regsUsed = bitVectSetBit (regsUsed, DPH1_IDX);
3985 regsUsed = bitVectSetBit (regsUsed, DPX_IDX);
3986 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3987 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3988 regsUsed = bitVectSetBit (regsUsed, DPS_IDX);
3989 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3990 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3991 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3994 /* Remove the unneeded push/pops */
3995 regsUnneeded = newBitVect (ds390_nRegs);
3998 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
4000 if (!strncmp(lnp->line, "push", 4))
4002 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
4003 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4005 connectLine (lnp->prev, lnp->next);
4006 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4009 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
4011 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
4012 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4014 connectLine (lnp->prev, lnp->next);
4015 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4022 for (idx = 0; idx < regsUnneeded->size; idx++)
4023 if (bitVectBitValue (regsUnneeded, idx))
4024 emitcode (";", "eliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
4026 freeBitVect (regsUnneeded);
4027 freeBitVect (regsUsed);
4028 freeBitVect (regsUsedPrologue);
4031 /*-----------------------------------------------------------------*/
4032 /* genJavaNativeRet - generate code for return JavaNative */
4033 /*-----------------------------------------------------------------*/
4034 static void genJavaNativeRet(iCode *ic)
4038 aopOp (IC_LEFT (ic), ic, FALSE,
4039 AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
4040 size = AOP_SIZE (IC_LEFT (ic));
4044 /* it is assigned to GPR0-R3 then push them */
4045 if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
4046 aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
4047 for (i = 0 ; i < size ; i++ ) {
4048 emitcode ("push","%s",
4049 aopGet(IC_LEFT(ic),i,FALSE,TRUE,DP2_RESULT_REG));
4051 for (i = (size-1) ; i >= 0 ; i--) {
4052 emitcode ("pop","a%s",javaRet[i]);
4055 for (i = 0 ; i < size ; i++)
4056 emitcode ("mov","%s,%s",javaRet[i],
4057 aopGet(IC_LEFT(ic),i,FALSE,TRUE,DP2_RESULT_REG));
4059 for (i = size ; i < 4 ; i++ )
4060 emitcode ("mov","%s,#0",javaRet[i]);
4064 /*-----------------------------------------------------------------*/
4065 /* genRet - generate code for return statement */
4066 /*-----------------------------------------------------------------*/
4070 int size, offset = 0, pushed = 0;
4072 D (emitcode (";", "genRet"));
4074 /* if we have no return value then
4075 just generate the "ret" */
4079 /* if this is a JavaNative function then return
4080 value in different register */
4081 if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
4082 genJavaNativeRet(ic);
4085 /* we have something to return then
4086 move the return value into place */
4087 aopOp (IC_LEFT (ic), ic, FALSE,
4088 (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
4089 size = AOP_SIZE (IC_LEFT (ic));
4091 _startLazyDPSEvaluation ();
4093 if (IS_BIT(_G.currentFunc->etype))
4095 movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4102 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
4104 l = aopGet (IC_LEFT (ic), offset++,
4106 emitcode ("push", "%s", l);
4111 /* Since A is the last element of fReturn,
4112 * it is OK to clobber it in the aopGet.
4114 l = aopGet (IC_LEFT (ic), offset,
4115 FALSE, FALSE, NULL);
4116 if (strcmp (fReturn[offset], l))
4117 emitcode ("mov", "%s,%s", fReturn[offset++], l);
4120 _endLazyDPSEvaluation ();
4125 if (strcmp (fReturn[pushed], "a"))
4126 emitcode ("pop", fReturn[pushed]);
4128 emitcode ("pop", "acc");
4130 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
4133 /* generate a jump to the return label
4134 if the next is not the return statement */
4135 if (!(ic->next && ic->next->op == LABEL &&
4136 IC_LABEL (ic->next) == returnLabel))
4138 emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
4142 /*-----------------------------------------------------------------*/
4143 /* genLabel - generates a label */
4144 /*-----------------------------------------------------------------*/
4146 genLabel (iCode * ic)
4148 /* special case never generate */
4149 if (IC_LABEL (ic) == entryLabel)
4152 D (emitcode (";", "genLabel"));
4154 emitLabel (IC_LABEL (ic));
4157 /*-----------------------------------------------------------------*/
4158 /* genGoto - generates a ljmp */
4159 /*-----------------------------------------------------------------*/
4161 genGoto (iCode * ic)
4163 D (emitcode (";", "genGoto"));
4165 emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
4168 /*-----------------------------------------------------------------*/
4169 /* findLabelBackwards: walks back through the iCode chain looking */
4170 /* for the given label. Returns number of iCode instructions */
4171 /* between that label and given ic. */
4172 /* Returns zero if label not found. */
4173 /*-----------------------------------------------------------------*/
4175 findLabelBackwards (iCode * ic, int key)
4184 /* If we have any pushes or pops, we cannot predict the distance.
4185 I don't like this at all, this should be dealt with in the
4187 if (ic->op == IPUSH || ic->op == IPOP) {
4191 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4193 /* printf("findLabelBackwards = %d\n", count); */
4201 /*-----------------------------------------------------------------*/
4202 /* genPlusIncr :- does addition with increment if possible */
4203 /*-----------------------------------------------------------------*/
4205 genPlusIncr (iCode * ic)
4207 unsigned int icount;
4208 unsigned int size = getDataSize (IC_RESULT (ic));
4210 /* will try to generate an increment */
4211 /* if the right side is not a literal
4213 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4216 /* if the literal value of the right hand side
4217 is greater than 4 then it is not worth it */
4218 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4221 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4222 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4224 emitcode("inc","%s",aopGet(IC_RESULT(ic),0,FALSE,FALSE,NULL));
4228 /* if increment 16 bits in register */
4230 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4231 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4232 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4241 /* If the next instruction is a goto and the goto target
4242 * is <= 5 instructions previous to this, we can generate
4243 * jumps straight to that target.
4245 if (ic->next && ic->next->op == GOTO
4246 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4249 D (emitcode (";", "tail increment optimized (range %d)", labelRange));
4250 tlbl = IC_LABEL (ic->next);
4255 tlbl = newiTempLabel (NULL);
4258 l = aopGet (IC_RESULT (ic), LSB, FALSE, FALSE, NULL);
4259 emitcode ("inc", "%s", l);
4261 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4262 IS_AOP_PREG (IC_RESULT (ic)))
4264 emitcode ("cjne", "%s,%s,!tlabel", l, zero, tlbl->key + 100);
4268 emitcode ("clr", "a");
4269 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4272 l = aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE, NULL);
4273 emitcode ("inc", "%s", l);
4276 if (!strcmp(l, "acc"))
4278 emitcode("jnz", "!tlabel", tlbl->key + 100);
4280 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4281 IS_AOP_PREG (IC_RESULT (ic)))
4283 emitcode ("cjne", "%s,%s,!tlabel", l, zero, tlbl->key + 100);
4287 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4290 l = aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE, NULL);
4291 emitcode ("inc", "%s", l);
4295 if (!strcmp(l, "acc"))
4297 emitcode("jnz", "!tlabel", tlbl->key + 100);
4299 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4300 IS_AOP_PREG (IC_RESULT (ic)))
4302 emitcode ("cjne", "%s,%s,!tlabel", l, zero, tlbl->key + 100);
4306 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4309 l = aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE, NULL);
4310 emitcode ("inc", "%s", l);
4320 if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
4321 !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 &&
4322 options.model == MODEL_FLAT24 )
4324 if (IC_RESULT(ic)->isGptr)
4326 emitcode ("mov", "b,%s", aopGet(IC_LEFT (ic), 3, FALSE, FALSE, NULL));
4330 emitcode ("mov", "dpx,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE, NULL));
4332 emitcode ("mov", "dph,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE, NULL));
4334 emitcode ("mov", "dpl,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4338 emitcode ("inc", "dptr");
4342 if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
4343 AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
4345 emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
4347 emitcode ("inc", "dptr");
4348 emitcode ("mov", "dps,#0");
4352 /* if the sizes are greater than 1 then we cannot */
4353 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4354 AOP_SIZE (IC_LEFT (ic)) > 1)
4357 /* we can if the aops of the left & result match or
4358 if they are in registers and the registers are the
4361 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4362 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4363 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4367 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4368 emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
4369 aopPut (IC_RESULT (ic), "a", 0);
4373 _startLazyDPSEvaluation ();
4376 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4378 _endLazyDPSEvaluation ();
4387 /*-----------------------------------------------------------------*/
4388 /* outBitAcc - output a bit in acc */
4389 /*-----------------------------------------------------------------*/
4391 outBitAcc (operand * result)
4393 symbol *tlbl = newiTempLabel (NULL);
4394 /* if the result is a bit */
4395 if (AOP_TYPE (result) == AOP_CRY)
4397 aopPut (result, "a", 0);
4401 emitcode ("jz", "!tlabel", tlbl->key + 100);
4402 emitcode ("mov", "a,%s", one);
4408 /*-----------------------------------------------------------------*/
4409 /* genPlusBits - generates code for addition of two bits */
4410 /*-----------------------------------------------------------------*/
4412 genPlusBits (iCode * ic)
4414 D (emitcode (";", "genPlusBits"));
4416 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4418 symbol *lbl = newiTempLabel (NULL);
4419 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4420 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4421 emitcode ("cpl", "c");
4423 outBitC (IC_RESULT (ic));
4427 emitcode ("clr", "a");
4428 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4429 emitcode ("rlc", "a");
4430 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4431 emitcode ("addc", "a,%s", zero);
4432 outAcc (IC_RESULT (ic));
4437 adjustArithmeticResult (iCode * ic)
4439 if (opIsGptr (IC_RESULT (ic)) &&
4440 opIsGptr (IC_LEFT (ic)) &&
4441 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4443 aopPut (IC_RESULT (ic),
4444 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE, NULL),
4448 if (opIsGptr (IC_RESULT (ic)) &&
4449 opIsGptr (IC_RIGHT (ic)) &&
4450 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4452 aopPut (IC_RESULT (ic),
4453 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE, NULL),
4457 if (opIsGptr (IC_RESULT (ic)) &&
4458 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4459 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4460 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4461 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4464 SNPRINTF (buffer, sizeof(buffer),
4465 "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4466 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4470 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
4471 // generates the result if possible. If result is generated, returns TRUE; otherwise
4472 // returns false and caller must deal with fact that result isn't aopOp'd.
4473 bool aopOp3(iCode * ic)
4475 bool dp1InUse, dp2InUse;
4478 // First, generate the right opcode. DPTR may be used if neither left nor result are
4481 // D (emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
4482 // AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
4483 // AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
4484 // AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
4486 // D (emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
4487 // AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
4488 // AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
4489 // AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
4492 // Right uses DPTR unless left or result is an AOP_STR; however,
4493 // if right is an AOP_STR, it must use DPTR regardless.
4494 if ((AOP_IS_STR (IC_LEFT (ic)) || AOP_IS_STR (IC_RESULT (ic)))
4495 && !AOP_IS_STR (IC_RIGHT (ic)))
4504 aopOp (IC_RIGHT(ic), ic, FALSE, useDp2);
4506 // if the right used DPTR, left MUST use DPTR2.
4507 // if the right used DPTR2, left MUST use DPTR.
4508 // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
4509 // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
4510 // enabling us to assign DPTR to result.
4512 if (AOP_USESDPTR (IC_RIGHT (ic)))
4516 else if (AOP_USESDPTR2 (IC_RIGHT (ic)))
4522 if (AOP_IS_STR (IC_RESULT (ic)) && !AOP_IS_STR (IC_LEFT (ic)))
4532 aopOp (IC_LEFT (ic), ic, FALSE, useDp2);
4535 // We've op'd the left & right. So, if left or right are the same operand as result,
4536 // we know aopOp will succeed, and we can just do it & bail.
4537 if (isOperandEqual (IC_LEFT (ic), IC_RESULT (ic)))
4539 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4542 if (isOperandEqual (IC_RIGHT (ic), IC_RESULT (ic)))
4544 // D (emitcode(";", "aopOp3: (left | right) & result equal"));
4545 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4549 // Operands may be equivalent (but not equal) if they share a spill location. If
4550 // so, use the same DPTR or DPTR2.
4551 if (operandsEqu (IC_LEFT (ic), IC_RESULT (ic)))
4553 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4556 if (operandsEqu (IC_RIGHT (ic), IC_RESULT (ic)))
4558 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4562 // Note which dptrs are currently in use.
4563 dp1InUse = AOP_USESDPTR (IC_LEFT (ic)) || AOP_USESDPTR (IC_RIGHT (ic));
4564 dp2InUse = AOP_USESDPTR2 (IC_LEFT (ic)) || AOP_USESDPTR2 (IC_RIGHT (ic));
4566 // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot
4568 if (dp1InUse && AOP_IS_STR (IC_RESULT (ic)))
4573 // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
4574 if (dp2InUse && AOP_IS_DPTRn (IC_RESULT (ic)))
4579 // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck
4580 if (dp1InUse && dp2InUse && isOperandInFarSpace (IC_RESULT (ic)))
4585 aopOp (IC_RESULT (ic), ic, TRUE, dp1InUse);
4587 // Some sanity checking...
4588 if (dp1InUse && AOP_USESDPTR (IC_RESULT (ic)))
4591 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
4592 __FILE__, __LINE__, ic->filename, ic->lineno);
4593 emitcode(";", ">>> unexpected DPTR here.");
4596 if (dp2InUse && AOP_USESDPTR2 (IC_RESULT (ic)))
4599 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
4600 __FILE__, __LINE__, ic->filename, ic->lineno);
4601 emitcode(";", ">>> unexpected DPTR2 here.");
4607 // Macro to aopOp all three operands of an ic. If this cannot be done,
4608 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
4609 // will be set TRUE. The caller must then handle the case specially, noting
4610 // that the IC_RESULT operand is not aopOp'd.
4612 #define AOP_OP_3_NOFATAL(ic, rc) \
4613 do { rc = !aopOp3(ic); } while (0)
4615 // aopOp the left & right operands of an ic.
4616 #define AOP_OP_2(ic) \
4617 aopOp (IC_RIGHT (ic), ic, FALSE, AOP_IS_STR (IC_LEFT (ic))); \
4618 aopOp (IC_LEFT (ic), ic, FALSE, AOP_USESDPTR (IC_RIGHT (ic)));
4620 // convienience macro.
4621 #define AOP_SET_LOCALS(ic) \
4622 left = IC_LEFT(ic); \
4623 right = IC_RIGHT(ic); \
4624 result = IC_RESULT(ic);
4627 // Given an integer value of pushedSize bytes on the stack,
4628 // adjust it to be resultSize bytes, either by discarding
4629 // the most significant bytes or by zero-padding.
4631 // On exit from this macro, pushedSize will have been adjusted to
4632 // equal resultSize, and ACC may be trashed.
4633 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
4634 /* If the pushed data is bigger than the result, \
4635 * simply discard unused bytes. Icky, but works. \
4637 while (pushedSize > resultSize) \
4639 D (emitcode (";", "discarding unused result byte.")); \
4640 emitcode ("pop", "acc"); \
4643 if (pushedSize < resultSize) \
4645 emitcode ("clr", "a"); \
4646 /* Conversly, we haven't pushed enough here. \
4647 * just zero-pad, and all is well. \
4649 while (pushedSize < resultSize) \
4651 emitcode("push", "acc"); \
4655 assert(pushedSize == resultSize);
4657 /*-----------------------------------------------------------------*/
4658 /* genPlus - generates code for addition */
4659 /*-----------------------------------------------------------------*/
4661 genPlus (iCode * ic)
4663 int size, offset = 0;
4666 bool swappedLR = FALSE;
4668 D (emitcode (";", "genPlus"));
4670 /* special cases :- */
4671 if ( AOP_IS_STR (IC_LEFT (ic)) &&
4672 isOperandLiteral (IC_RIGHT (ic)) && OP_SYMBOL (IC_RESULT (ic))->ruonly) {
4673 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
4674 size = (int)floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4676 while (size--) emitcode ("inc","dptr");
4678 emitcode ("mov", "a,dpl");
4679 emitcode ("add", "a,#!constbyte", size & 0xff);
4680 emitcode ("mov", "dpl,a");
4681 emitcode ("mov", "a,dph");
4682 emitcode ("addc", "a,#!constbyte", (size >> 8) & 0xff);
4683 emitcode ("mov", "dph,a");
4684 emitcode ("mov", "a,dpx");
4685 emitcode ("addc", "a,#!constbyte", (size >> 16) & 0xff);
4686 emitcode ("mov", "dpx,a");
4688 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4691 if ( IS_SYMOP (IC_LEFT (ic)) &&
4692 OP_SYMBOL (IC_LEFT (ic))->remat &&
4693 isOperandInFarSpace (IC_RIGHT (ic))) {
4694 operand *op = IC_RIGHT(ic);
4695 IC_RIGHT(ic) = IC_LEFT(ic);
4699 AOP_OP_3_NOFATAL (ic, pushResult);
4703 D (emitcode (";", "genPlus: must push result: 3 ops in far space"));
4708 /* if literal, literal on the right or
4709 if left requires ACC or right is already
4711 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4712 ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic)))) ||
4713 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4715 operand *t = IC_RIGHT (ic);
4716 IC_RIGHT (ic) = IC_LEFT (ic);
4719 D (emitcode (";", "Swapped plus args."));
4722 /* if both left & right are in bit
4724 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4725 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4731 /* if left in bit space & right literal */
4732 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4733 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4735 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4736 /* if result in bit space */
4737 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4739 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4740 emitcode ("cpl", "c");
4741 outBitC (IC_RESULT (ic));
4745 size = getDataSize (IC_RESULT (ic));
4746 _startLazyDPSEvaluation ();
4749 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4750 emitcode ("addc", "a,%s", zero);
4751 aopPut (IC_RESULT (ic), "a", offset++);
4753 _endLazyDPSEvaluation ();
4758 /* if I can do an increment instead
4759 of add then GOOD for ME */
4760 if (genPlusIncr (ic) == TRUE)
4762 D (emitcode (";", "did genPlusIncr"));
4767 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4769 _startLazyDPSEvaluation ();
4772 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4774 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
4776 emitcode ("add", "a,%s",
4777 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4779 emitcode ("addc", "a,%s",
4780 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4784 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4786 /* right is going to use ACC or we would have taken the
4789 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4791 D(emitcode(";", "+ AOP_ACC special case."););
4792 emitcode("xch", "a, %s", DP2_RESULT_REG);
4794 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4797 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4800 emitcode("add", "a, %s", DP2_RESULT_REG);
4804 emitcode ("add", "a,%s",
4805 aopGet (IC_LEFT(ic), offset, FALSE, FALSE,
4811 emitcode ("addc", "a,%s",
4812 aopGet (IC_LEFT (ic), offset, FALSE, FALSE,
4818 aopPut (IC_RESULT (ic), "a", offset);
4822 emitcode ("push", "acc");
4826 _endLazyDPSEvaluation ();
4830 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4832 size = getDataSize (IC_LEFT (ic));
4833 rSize = getDataSize (IC_RESULT (ic));
4835 ADJUST_PUSHED_RESULT(size, rSize);
4837 _startLazyDPSEvaluation ();
4840 emitcode ("pop", "acc");
4841 aopPut (IC_RESULT (ic), "a", size);
4843 _endLazyDPSEvaluation ();
4846 adjustArithmeticResult (ic);
4849 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4852 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4853 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4857 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4858 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4862 /*-----------------------------------------------------------------*/
4863 /* genMinusDec :- does subtraction with decrement if possible */
4864 /*-----------------------------------------------------------------*/
4866 genMinusDec (iCode * ic)
4868 unsigned int icount;
4869 unsigned int size = getDataSize (IC_RESULT (ic));
4871 /* will try to generate an increment */
4872 /* if the right side is not a literal
4874 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4877 /* if the literal value of the right hand side
4878 is greater than 4 then it is not worth it */
4879 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4882 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4883 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4885 emitcode("dec","%s",aopGet(IC_RESULT(ic),0,FALSE,FALSE,NULL));
4889 /* if decrement 16 bits in register */
4890 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4891 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4892 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4901 /* If the next instruction is a goto and the goto target
4902 * is <= 5 instructions previous to this, we can generate
4903 * jumps straight to that target.
4905 if (ic->next && ic->next->op == GOTO
4906 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4909 D (emitcode (";", "tail decrement optimized (range %d)", labelRange));
4910 tlbl = IC_LABEL (ic->next);
4915 tlbl = newiTempLabel (NULL);
4919 l = aopGet (IC_RESULT (ic), LSB, FALSE, FALSE, NULL);
4920 emitcode ("dec", "%s", l);
4922 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4923 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4924 IS_AOP_PREG (IC_RESULT (ic)))
4926 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4930 emitcode ("mov", "a,#!constbyte",0xff);
4931 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4933 l = aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE, NULL);
4934 emitcode ("dec", "%s", l);
4937 if (!strcmp(l, "acc"))
4939 emitcode("jnz", "!tlabel", tlbl->key + 100);
4941 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4942 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4943 IS_AOP_PREG (IC_RESULT (ic)))
4945 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4949 emitcode ("mov", "a,#!constbyte",0xff);
4950 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4952 l = aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE, NULL);
4953 emitcode ("dec", "%s", l);
4957 if (!strcmp(l, "acc"))
4959 emitcode("jnz", "!tlabel", tlbl->key + 100);
4961 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4962 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4963 IS_AOP_PREG (IC_RESULT (ic)))
4965 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4969 emitcode ("mov", "a,#!constbyte",0xff);
4970 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4972 l = aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE, NULL);
4973 emitcode ("dec", "%s", l);
4982 /* if the sizes are greater than 1 then we cannot */
4983 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4984 AOP_SIZE (IC_LEFT (ic)) > 1)
4987 /* we can if the aops of the left & result match or
4988 if they are in registers and the registers are the
4991 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4992 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4993 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4997 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4999 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL));
5004 l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL);
5007 _startLazyDPSEvaluation ();
5010 emitcode ("dec", "%s", l);
5012 _endLazyDPSEvaluation ();
5014 if (AOP_NEEDSACC (IC_RESULT (ic)))
5015 aopPut (IC_RESULT (ic), "a", 0);
5023 /*-----------------------------------------------------------------*/
5024 /* addSign - complete with sign */
5025 /*-----------------------------------------------------------------*/
5027 addSign (operand * result, int offset, int sign)
5029 int size = (getDataSize (result) - offset);
5032 _startLazyDPSEvaluation();
5035 emitcode ("rlc", "a");
5036 emitcode ("subb", "a,acc");
5039 aopPut (result, "a", offset++);
5046 aopPut (result, zero, offset++);
5049 _endLazyDPSEvaluation();
5053 /*-----------------------------------------------------------------*/
5054 /* genMinusBits - generates code for subtraction of two bits */
5055 /*-----------------------------------------------------------------*/
5057 genMinusBits (iCode * ic)
5059 symbol *lbl = newiTempLabel (NULL);
5061 D (emitcode (";", "genMinusBits"));
5063 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
5065 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
5066 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
5067 emitcode ("cpl", "c");
5069 outBitC (IC_RESULT (ic));
5073 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
5074 emitcode ("subb", "a,acc");
5075 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
5076 emitcode ("inc", "a");
5078 aopPut (IC_RESULT (ic), "a", 0);
5079 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
5083 /*-----------------------------------------------------------------*/
5084 /* genMinus - generates code for subtraction */
5085 /*-----------------------------------------------------------------*/
5087 genMinus (iCode * ic)
5089 int size, offset = 0;
5094 D (emitcode (";", "genMinus"));
5096 AOP_OP_3_NOFATAL(ic, pushResult);
5100 /* special cases :- */
5101 /* if both left & right are in bit space */
5102 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
5103 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
5109 /* if I can do an decrement instead
5110 of subtract then GOOD for ME */
5111 if (genMinusDec (ic) == TRUE)
5116 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
5118 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
5124 lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5129 /* if literal, add a,#-lit, else normal subb */
5130 _startLazyDPSEvaluation ();
5132 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
5133 if (AOP_USESDPTR(IC_RIGHT(ic))) {
5134 emitcode ("mov","b,%s",
5135 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
5136 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
5137 emitcode ("subb","a,b");
5139 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
5140 emitcode ("subb", "a,%s",
5141 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE,
5145 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
5146 /* first add without previous c */
5148 if (!size && lit==-1) {
5149 emitcode ("dec", "a");
5151 emitcode ("add", "a,#!constbyte",
5152 (unsigned int) (lit & 0x0FFL));
5155 emitcode ("addc", "a,#!constbyte",
5156 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5161 emitcode ("push", "acc");
5163 aopPut (IC_RESULT (ic), "a", offset);
5167 _endLazyDPSEvaluation ();
5171 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
5173 size = getDataSize (IC_LEFT (ic));
5174 rSize = getDataSize (IC_RESULT (ic));
5176 ADJUST_PUSHED_RESULT(size, rSize);
5178 _startLazyDPSEvaluation ();
5181 emitcode ("pop", "acc");
5182 aopPut (IC_RESULT (ic), "a", size);
5184 _endLazyDPSEvaluation ();
5187 adjustArithmeticResult (ic);
5190 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5191 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5192 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5196 /*-----------------------------------------------------------------*/
5197 /* genMultbits :- multiplication of bits */
5198 /*-----------------------------------------------------------------*/
5200 genMultbits (operand * left,
5205 D (emitcode (";", "genMultbits"));
5207 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5208 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5209 aopOp(result, ic, TRUE, FALSE);
5213 /*-----------------------------------------------------------------*/
5214 /* genMultOneByte : 8*8=8/16 bit multiplication */
5215 /*-----------------------------------------------------------------*/
5217 genMultOneByte (operand * left,
5224 bool runtimeSign, compiletimeSign;
5225 bool lUnsigned, rUnsigned, pushedB;
5227 /* (if two literals: the value is computed before) */
5228 /* if one literal, literal on the right */
5229 if (AOP_TYPE (left) == AOP_LIT)
5234 /* emitcode (";", "swapped left and right"); */
5236 /* if no literal, unsigned on the right: shorter code */
5237 if ( AOP_TYPE (right) != AOP_LIT
5238 && SPEC_USIGN (getSpec (operandType (left))))
5245 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5246 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5250 if ((lUnsigned && rUnsigned)
5251 /* sorry, I don't know how to get size
5252 without calling aopOp (result,...);
5253 see Feature Request */
5254 /* || size == 1 */ ) /* no, this is not a bug; with a 1 byte result there's
5255 no need to take care about the signedness! */
5257 /* just an unsigned 8 * 8 = 8 multiply
5259 /* emitcode (";","unsigned"); */
5260 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
5261 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
5262 emitcode ("mul", "ab");
5265 aopOp (result, ic, TRUE, FALSE);
5266 size = AOP_SIZE (result);
5268 if (size < 1 || size > 2)
5270 /* this should never happen */
5271 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
5272 size, __FILE__, lineno);
5276 aopPut (result, "a", 0);
5279 aopPut (result, "b", 1);
5285 /* we have to do a signed multiply */
5286 /* emitcode (";", "signed"); */
5288 /* now sign adjust for both left & right */
5290 /* let's see what's needed: */
5291 /* apply negative sign during runtime */
5292 runtimeSign = FALSE;
5293 /* negative sign from literals */
5294 compiletimeSign = FALSE;
5298 if (AOP_TYPE(left) == AOP_LIT)
5300 /* signed literal */
5301 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5303 compiletimeSign = TRUE;
5306 /* signed but not literal */
5312 if (AOP_TYPE(right) == AOP_LIT)
5314 /* signed literal */
5315 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5317 compiletimeSign ^= TRUE;
5320 /* signed but not literal */
5324 /* initialize F0, which stores the runtime sign */
5327 if (compiletimeSign)
5328 emitcode ("setb", "F0"); /* set sign flag */
5330 emitcode ("clr", "F0"); /* reset sign flag */
5333 /* save the signs of the operands */
5334 if (AOP_TYPE(right) == AOP_LIT)
5336 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5338 if (!rUnsigned && val < 0)
5339 emitcode ("mov", "b,#!constbyte", -val);
5341 emitcode ("mov", "b,#!constbyte", (unsigned char) val);
5343 else /* ! literal */
5345 if (rUnsigned) /* emitcode (";", "signed"); */
5346 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
5349 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
5350 lbl = newiTempLabel (NULL);
5351 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5352 emitcode ("cpl", "F0"); /* complement sign flag */
5353 emitcode ("cpl", "a"); /* 2's complement */
5354 emitcode ("inc", "a");
5356 emitcode ("mov", "b,a");
5360 if (AOP_TYPE(left) == AOP_LIT)
5362 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5364 if (!lUnsigned && val < 0)
5365 emitcode ("mov", "a,#!constbyte", -val);
5367 emitcode ("mov", "a,#!constbyte", (unsigned char) val);
5369 else /* ! literal */
5371 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
5373 if (!lUnsigned) /* emitcode (";", "signed"); */
5375 lbl = newiTempLabel (NULL);
5376 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5377 emitcode ("cpl", "F0"); /* complement sign flag */
5378 emitcode ("cpl", "a"); /* 2's complement */
5379 emitcode ("inc", "a");
5384 /* now the multiplication */
5385 emitcode ("mul", "ab");
5387 aopOp(result, ic, TRUE, FALSE);
5388 size = AOP_SIZE (result);
5390 if (size < 1 || size > 2)
5392 /* this should never happen */
5393 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
5394 size, __FILE__, lineno);
5398 if (runtimeSign || compiletimeSign)
5400 lbl = newiTempLabel (NULL);
5402 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5403 emitcode ("cpl", "a"); /* lsb 2's complement */
5405 emitcode ("inc", "a"); /* inc doesn't set carry flag */
5408 emitcode ("add", "a,#1"); /* this sets carry flag */
5409 emitcode ("xch", "a,b");
5410 emitcode ("cpl", "a"); /* msb 2's complement */
5411 emitcode ("addc", "a,#0");
5412 emitcode ("xch", "a,b");
5416 aopPut (result, "a", 0);
5419 aopPut (result, "b", 1);
5424 /*-----------------------------------------------------------------*/
5425 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
5426 /*-----------------------------------------------------------------*/
5427 static void genMultTwoByte (operand *left, operand *right,
5428 operand *result, iCode *ic)
5430 sym_link *retype = getSpec(operandType(right));
5431 sym_link *letype = getSpec(operandType(left));
5432 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5435 if (AOP_TYPE (left) == AOP_LIT) {
5440 /* save EA bit in F1 */
5441 lbl = newiTempLabel(NULL);
5442 emitcode ("setb","F1");
5443 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5444 emitcode ("clr","F1");
5447 /* load up MB with right */
5449 emitcode("clr","F0");
5450 if (AOP_TYPE(right) == AOP_LIT) {
5451 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5453 emitcode("setb","F0");
5456 emitcode ("mov","mb,#!constbyte",val & 0xff);
5457 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5459 lbl = newiTempLabel(NULL);
5460 emitcode ("mov","b,%s",aopGet(right,0,FALSE,FALSE,NULL));
5461 emitcode ("mov","a,%s",aopGet(right,1,FALSE,FALSE,NULL));
5462 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5463 emitcode ("xch", "a,b");
5464 emitcode ("cpl","a");
5465 emitcode ("add", "a,#1");
5466 emitcode ("xch", "a,b");
5467 emitcode ("cpl", "a"); // msb
5468 emitcode ("addc", "a,#0");
5469 emitcode ("setb","F0");
5471 emitcode ("mov","mb,b");
5472 emitcode ("mov","mb,a");
5475 emitcode ("mov","mb,%s",aopGet(right,0,FALSE,FALSE,NULL));
5476 emitcode ("mov","mb,%s",aopGet(right,1,FALSE,FALSE,NULL));
5478 /* load up MA with left */
5480 lbl = newiTempLabel(NULL);
5481 emitcode ("mov","b,%s",aopGet(left,0,FALSE,FALSE,NULL));
5482 emitcode ("mov","a,%s",aopGet(left,1,FALSE,FALSE,NULL));
5483 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5484 emitcode ("xch", "a,b");
5485 emitcode ("cpl","a");
5486 emitcode ("add", "a,#1");
5487 emitcode ("xch", "a,b");
5488 emitcode ("cpl", "a"); // msb
5489 emitcode ("addc","a,#0");
5490 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5491 emitcode ("setb","F0");
5493 emitcode ("mov","ma,b");
5494 emitcode ("mov","ma,a");
5496 emitcode ("mov","ma,%s",aopGet(left,0,FALSE,FALSE,NULL));
5497 emitcode ("mov","ma,%s",aopGet(left,1,FALSE,FALSE,NULL));
5499 /* wait for multiplication to finish */
5500 lbl = newiTempLabel(NULL);
5502 emitcode("mov","a,mcnt1");
5503 emitcode("anl","a,#!constbyte",0x80);
5504 emitcode("jnz","!tlabel",lbl->key+100);
5506 freeAsmop (left, NULL, ic, TRUE);
5507 freeAsmop (right, NULL, ic,TRUE);
5508 aopOp(result, ic, TRUE, FALSE);
5510 /* if unsigned then simple */
5512 emitcode ("mov","a,ma");
5513 if (AOP_SIZE(result) >= 4) aopPut(result,"a",3);
5514 emitcode ("mov","a,ma");
5515 if (AOP_SIZE(result) >= 3) aopPut(result,"a",2);
5516 aopPut(result,"ma",1);
5517 aopPut(result,"ma",0);
5519 emitcode("push","ma");
5520 emitcode("push","ma");
5521 emitcode("push","ma");
5523 /* negate result if needed */
5524 lbl = newiTempLabel(NULL);
5525 emitcode("jnb","F0,!tlabel",lbl->key+100);
5526 emitcode("cpl","a");
5527 emitcode("add","a,#1");
5529 if (AOP_TYPE(result) == AOP_ACC)
5531 D (emitcode(";", "ACC special case."));
5532 /* We know result is the only live aop, and
5533 * it's obviously not a DPTR2, so AP is available.
5535 emitcode("mov", "%s,acc", DP2_RESULT_REG);
5539 aopPut(result,"a",0);
5542 emitcode("pop","acc");
5543 lbl = newiTempLabel(NULL);
5544 emitcode("jnb","F0,!tlabel",lbl->key+100);
5545 emitcode("cpl","a");
5546 emitcode("addc","a,#0");
5548 aopPut(result,"a",1);
5549 emitcode("pop","acc");
5550 if (AOP_SIZE(result) >= 3) {
5551 lbl = newiTempLabel(NULL);
5552 emitcode("jnb","F0,!tlabel",lbl->key+100);
5553 emitcode("cpl","a");
5554 emitcode("addc","a,#0");
5556 aopPut(result,"a",2);
5558 emitcode("pop","acc");
5559 if (AOP_SIZE(result) >= 4) {
5560 lbl = newiTempLabel(NULL);
5561 emitcode("jnb","F0,!tlabel",lbl->key+100);
5562 emitcode("cpl","a");
5563 emitcode("addc","a,#0");
5565 aopPut(result,"a",3);
5567 if (AOP_TYPE(result) == AOP_ACC)
5569 /* We stashed the result away above. */
5570 emitcode("mov", "acc,%s", DP2_RESULT_REG);
5574 freeAsmop (result, NULL, ic, TRUE);
5576 /* restore EA bit in F1 */
5577 lbl = newiTempLabel(NULL);
5578 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5579 emitcode ("setb","EA");
5584 /*-----------------------------------------------------------------*/
5585 /* genMult - generates code for multiplication */
5586 /*-----------------------------------------------------------------*/
5588 genMult (iCode * ic)
5590 operand *left = IC_LEFT (ic);
5591 operand *right = IC_RIGHT (ic);
5592 operand *result = IC_RESULT (ic);
5594 D (emitcode (";", "genMult"));
5596 /* assign the asmops */
5599 /* special cases first */
5601 if (AOP_TYPE (left) == AOP_CRY &&
5602 AOP_TYPE (right) == AOP_CRY)
5604 genMultbits (left, right, result, ic);
5608 /* if both are of size == 1 */
5609 if (AOP_SIZE (left) == 1 &&
5610 AOP_SIZE (right) == 1)
5612 genMultOneByte (left, right, result, ic);
5616 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5617 /* use the ds390 ARITHMETIC accel UNIT */
5618 genMultTwoByte (left, right, result, ic);
5621 /* should have been converted to function call */
5625 freeAsmop (result, NULL, ic, TRUE);
5626 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5627 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5630 /*-----------------------------------------------------------------*/
5631 /* genDivbits :- division of bits */
5632 /*-----------------------------------------------------------------*/
5634 genDivbits (operand * left,
5642 D(emitcode ("; genDivbits",""));
5646 /* the result must be bit */
5647 LOAD_AB_FOR_DIV (left, right, l);
5648 emitcode ("div", "ab");
5649 emitcode ("rrc", "a");
5650 aopOp(result, ic, TRUE, FALSE);
5654 aopPut (result, "c", 0);
5657 /*-----------------------------------------------------------------*/
5658 /* genDivOneByte : 8 bit division */
5659 /*-----------------------------------------------------------------*/
5661 genDivOneByte (operand * left,
5666 bool lUnsigned, rUnsigned, pushedB;
5667 bool runtimeSign, compiletimeSign;
5672 D(emitcode ("; genDivOneByte",""));
5675 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5676 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5680 /* signed or unsigned */
5681 if (lUnsigned && rUnsigned)
5683 /* unsigned is easy */
5684 LOAD_AB_FOR_DIV (left, right, l);
5685 emitcode ("div", "ab");
5688 aopOp (result, ic, TRUE, FALSE);
5689 aopPut (result, "a", 0);
5692 size = AOP_SIZE (result) - 1;
5695 aopPut (result, zero, offset++);
5701 /* signed is a little bit more difficult */
5703 /* now sign adjust for both left & right */
5705 /* let's see what's needed: */
5706 /* apply negative sign during runtime */
5707 runtimeSign = FALSE;
5708 /* negative sign from literals */
5709 compiletimeSign = FALSE;
5713 if (AOP_TYPE(left) == AOP_LIT)
5715 /* signed literal */
5716 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5718 compiletimeSign = TRUE;
5721 /* signed but not literal */
5727 if (AOP_TYPE(right) == AOP_LIT)
5729 /* signed literal */
5730 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5732 compiletimeSign ^= TRUE;
5735 /* signed but not literal */
5739 /* initialize F0, which stores the runtime sign */
5742 if (compiletimeSign)
5743 emitcode ("setb", "F0"); /* set sign flag */
5745 emitcode ("clr", "F0"); /* reset sign flag */
5748 /* save the signs of the operands */
5749 if (AOP_TYPE(right) == AOP_LIT)
5751 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5753 if (!rUnsigned && val < 0)
5754 emitcode ("mov", "b,#0x%02x", -val);
5756 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5758 else /* ! literal */
5761 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
5764 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
5765 lbl = newiTempLabel (NULL);
5766 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5767 emitcode ("cpl", "F0"); /* complement sign flag */
5768 emitcode ("cpl", "a"); /* 2's complement */
5769 emitcode ("inc", "a");
5771 emitcode ("mov", "b,a");
5775 if (AOP_TYPE(left) == AOP_LIT)
5777 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5779 if (!lUnsigned && val < 0)
5780 emitcode ("mov", "a,#0x%02x", -val);
5782 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5784 else /* ! literal */
5786 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
5790 lbl = newiTempLabel (NULL);
5791 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5792 emitcode ("cpl", "F0"); /* complement sign flag */
5793 emitcode ("cpl", "a"); /* 2's complement */
5794 emitcode ("inc", "a");
5799 /* now the division */
5800 emitcode ("nop", "; workaround for DS80C390 div bug.");
5801 emitcode ("div", "ab");
5803 if (runtimeSign || compiletimeSign)
5805 lbl = newiTempLabel (NULL);
5807 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5808 emitcode ("cpl", "a"); /* lsb 2's complement */
5809 emitcode ("inc", "a");
5813 aopOp (result, ic, TRUE, FALSE);
5814 size = AOP_SIZE (result) - 1;
5818 /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
5819 then the result will be in b, a */
5820 emitcode ("mov", "b,a"); /* 1 */
5821 /* msb is 0x00 or 0xff depending on the sign */
5824 emitcode ("mov", "c,F0");
5825 emitcode ("subb", "a,acc");
5826 emitcode ("xch", "a,b"); /* 2 */
5828 aopPut (result, "b", offset++); /* write msb's */
5830 else /* compiletimeSign */
5832 aopPut (result, "#0xff", offset++); /* write msb's */
5834 aopPut (result, "a", 0); /* 3: write lsb */
5839 aopOp(result, ic, TRUE, FALSE);
5840 size = AOP_SIZE (result) - 1;
5842 aopPut (result, "a", 0);
5844 aopPut (result, zero, offset++);
5850 /*-----------------------------------------------------------------*/
5851 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
5852 /*-----------------------------------------------------------------*/
5853 static void genDivTwoByte (operand *left, operand *right,
5854 operand *result, iCode *ic)
5856 sym_link *retype = getSpec(operandType(right));
5857 sym_link *letype = getSpec(operandType(left));
5858 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5861 /* save EA bit in F1 */
5862 lbl = newiTempLabel(NULL);
5863 emitcode ("setb","F1");
5864 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5865 emitcode ("clr","F1");
5868 /* load up MA with left */
5870 emitcode("clr","F0");
5871 lbl = newiTempLabel(NULL);
5872 emitcode ("mov","b,%s",aopGet(left,0,FALSE,FALSE,NULL));
5873 emitcode ("mov","a,%s",aopGet(left,1,FALSE,FALSE,NULL));
5874 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5875 emitcode ("xch", "a,b");
5876 emitcode ("cpl","a");
5877 emitcode ("add", "a,#1");
5878 emitcode ("xch", "a,b");
5879 emitcode ("cpl", "a"); // msb
5880 emitcode ("addc","a,#0");
5881 emitcode ("setb","F0");
5883 emitcode ("mov","ma,b");
5884 emitcode ("mov","ma,a");
5886 emitcode ("mov","ma,%s",aopGet(left,0,FALSE,FALSE,NULL));
5887 emitcode ("mov","ma,%s",aopGet(left,1,FALSE,FALSE,NULL));
5890 /* load up MB with right */
5892 if (AOP_TYPE(right) == AOP_LIT) {
5893 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5895 lbl = newiTempLabel(NULL);
5896 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5897 emitcode("setb","F0");
5901 emitcode ("mov","mb,#!constbyte",val & 0xff);
5902 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5904 lbl = newiTempLabel(NULL);
5905 emitcode ("mov","b,%s",aopGet(right,0,FALSE,FALSE,NULL));
5906 emitcode ("mov","a,%s",aopGet(right,1,FALSE,FALSE,NULL));
5907 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5908 emitcode ("xch", "a,b");
5909 emitcode ("cpl","a");
5910 emitcode ("add", "a,#1");
5911 emitcode ("xch", "a,b");
5912 emitcode ("cpl", "a"); // msb
5913 emitcode ("addc", "a,#0");
5914 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5915 emitcode ("setb","F0");
5917 emitcode ("mov","mb,b");
5918 emitcode ("mov","mb,a");
5921 emitcode ("mov","mb,%s",aopGet(right,0,FALSE,FALSE,NULL));
5922 emitcode ("mov","mb,%s",aopGet(right,1,FALSE,FALSE,NULL));
5925 /* wait for multiplication to finish */
5926 lbl = newiTempLabel(NULL);
5928 emitcode("mov","a,mcnt1");
5929 emitcode("anl","a,#!constbyte",0x80);
5930 emitcode("jnz","!tlabel",lbl->key+100);
5932 freeAsmop (left, NULL, ic, TRUE);
5933 freeAsmop (right, NULL, ic,TRUE);
5934 aopOp(result, ic, TRUE, FALSE);
5936 /* if unsigned then simple */
5938 aopPut(result,"ma",1);
5939 aopPut(result,"ma",0);
5941 emitcode("push","ma");
5943 /* negate result if needed */
5944 lbl = newiTempLabel(NULL);
5945 emitcode("jnb","F0,!tlabel",lbl->key+100);
5946 emitcode("cpl","a");
5947 emitcode("add","a,#1");
5949 aopPut(result,"a",0);
5950 emitcode("pop","acc");
5951 lbl = newiTempLabel(NULL);
5952 emitcode("jnb","F0,!tlabel",lbl->key+100);
5953 emitcode("cpl","a");
5954 emitcode("addc","a,#0");
5956 aopPut(result,"a",1);
5958 freeAsmop (result, NULL, ic, TRUE);
5959 /* restore EA bit in F1 */
5960 lbl = newiTempLabel(NULL);
5961 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5962 emitcode ("setb","EA");
5967 /*-----------------------------------------------------------------*/
5968 /* genDiv - generates code for division */
5969 /*-----------------------------------------------------------------*/
5973 operand *left = IC_LEFT (ic);
5974 operand *right = IC_RIGHT (ic);
5975 operand *result = IC_RESULT (ic);
5977 D (emitcode (";", "genDiv"));
5979 /* assign the amsops */
5982 /* special cases first */
5984 if (AOP_TYPE (left) == AOP_CRY &&
5985 AOP_TYPE (right) == AOP_CRY)
5987 genDivbits (left, right, result, ic);
5991 /* if both are of size == 1 */
5992 if (AOP_SIZE (left) == 1 &&
5993 AOP_SIZE (right) == 1)
5995 genDivOneByte (left, right, result, ic);
5999 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
6000 /* use the ds390 ARITHMETIC accel UNIT */
6001 genDivTwoByte (left, right, result, ic);
6004 /* should have been converted to function call */
6007 freeAsmop (result, NULL, ic, TRUE);
6008 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6009 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6012 /*-----------------------------------------------------------------*/
6013 /* genModbits :- modulus of bits */
6014 /*-----------------------------------------------------------------*/
6016 genModbits (operand * left,
6024 D (emitcode (";", "genModbits"));
6028 /* the result must be bit */
6029 LOAD_AB_FOR_DIV (left, right, l);
6030 emitcode ("div", "ab");
6031 emitcode ("mov", "a,b");
6032 emitcode ("rrc", "a");
6033 aopOp(result, ic, TRUE, FALSE);
6037 aopPut (result, "c", 0);
6040 /*-----------------------------------------------------------------*/
6041 /* genModOneByte : 8 bit modulus */
6042 /*-----------------------------------------------------------------*/
6044 genModOneByte (operand * left,
6049 bool lUnsigned, rUnsigned, pushedB;
6050 bool runtimeSign, compiletimeSign;
6055 D (emitcode (";", "genModOneByte"));
6058 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
6059 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
6063 /* signed or unsigned */
6064 if (lUnsigned && rUnsigned)
6066 /* unsigned is easy */
6067 LOAD_AB_FOR_DIV (left, right, l);
6068 emitcode ("div", "ab");
6069 aopOp (result, ic, TRUE, FALSE);
6070 aopPut (result, "b", 0);
6072 for (size = AOP_SIZE (result) - 1; size--;)
6073 aopPut (result, zero, offset++);
6079 /* signed is a little bit more difficult */
6081 /* now sign adjust for both left & right */
6083 /* modulus: sign of the right operand has no influence on the result! */
6084 if (AOP_TYPE(right) == AOP_LIT)
6086 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
6088 if (!rUnsigned && val < 0)
6089 emitcode ("mov", "b,#0x%02x", -val);
6091 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
6093 else /* not literal */
6096 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
6099 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
6100 lbl = newiTempLabel (NULL);
6101 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
6102 emitcode ("cpl", "a"); /* 2's complement */
6103 emitcode ("inc", "a");
6105 emitcode ("mov", "b,a");
6109 /* let's see what's needed: */
6110 /* apply negative sign during runtime */
6111 runtimeSign = FALSE;
6112 /* negative sign from literals */
6113 compiletimeSign = FALSE;
6115 /* sign adjust left side */
6116 if (AOP_TYPE(left) == AOP_LIT)
6118 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
6120 if (!lUnsigned && val < 0)
6122 compiletimeSign = TRUE; /* set sign flag */
6123 emitcode ("mov", "a,#0x%02x", -val);
6126 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
6128 else /* ! literal */
6130 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
6135 emitcode ("clr", "F0"); /* clear sign flag */
6137 lbl = newiTempLabel (NULL);
6138 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
6139 emitcode ("setb", "F0"); /* set sign flag */
6140 emitcode ("cpl", "a"); /* 2's complement */
6141 emitcode ("inc", "a");
6146 /* now the modulus */
6147 emitcode ("nop", "; workaround for DS80C390 div bug.");
6148 emitcode ("div", "ab");
6150 if (runtimeSign || compiletimeSign)
6152 emitcode ("mov", "a,b");
6153 lbl = newiTempLabel (NULL);
6155 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
6156 emitcode ("cpl", "a"); /* lsb 2's complement */
6157 emitcode ("inc", "a");
6161 aopOp (result, ic, TRUE, FALSE);
6162 size = AOP_SIZE (result) - 1;
6166 /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
6167 then the result will be in b, a */
6168 emitcode ("mov", "b,a"); /* 1 */
6169 /* msb is 0x00 or 0xff depending on the sign */
6172 emitcode ("mov", "c,F0");
6173 emitcode ("subb", "a,acc");
6174 emitcode ("xch", "a,b"); /* 2 */
6176 aopPut (result, "b", offset++); /* write msb's */
6178 else /* compiletimeSign */
6180 aopPut (result, "#0xff", offset++); /* write msb's */
6182 aopPut (result, "a", 0); /* 3: write lsb */
6187 aopOp(result, ic, TRUE, FALSE);
6188 size = AOP_SIZE (result) - 1;
6190 aopPut (result, "b", 0);
6192 aopPut (result, zero, offset++);
6198 /*-----------------------------------------------------------------*/
6199 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
6200 /*-----------------------------------------------------------------*/
6201 static void genModTwoByte (operand *left, operand *right,
6202 operand *result, iCode *ic)
6204 sym_link *retype = getSpec(operandType(right));
6205 sym_link *letype = getSpec(operandType(left));
6206 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
6209 /* load up MA with left */
6210 /* save EA bit in F1 */
6211 lbl = newiTempLabel(NULL);
6212 emitcode ("setb","F1");
6213 emitcode ("jbc","EA,!tlabel",lbl->key+100);
6214 emitcode ("clr","F1");
6218 lbl = newiTempLabel(NULL);
6219 emitcode ("mov","b,%s",aopGet(left,0,FALSE,FALSE,NULL));
6220 emitcode ("mov","a,%s",aopGet(left,1,FALSE,FALSE,NULL));
6221 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
6222 emitcode ("xch", "a,b");
6223 emitcode ("cpl","a");
6224 emitcode ("add", "a,#1");
6225 emitcode ("xch", "a,b");
6226 emitcode ("cpl", "a"); // msb
6227 emitcode ("addc","a,#0");
6229 emitcode ("mov","ma,b");
6230 emitcode ("mov","ma,a");
6232 emitcode ("mov","ma,%s",aopGet(left,0,FALSE,FALSE,NULL));
6233 emitcode ("mov","ma,%s",aopGet(left,1,FALSE,FALSE,NULL));
6236 /* load up MB with right */
6238 if (AOP_TYPE(right) == AOP_LIT) {
6239 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
6243 emitcode ("mov","mb,#!constbyte",val & 0xff);
6244 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
6246 lbl = newiTempLabel(NULL);
6247 emitcode ("mov","b,%s",aopGet(right,0,FALSE,FALSE,NULL));
6248 emitcode ("mov","a,%s",aopGet(right,1,FALSE,FALSE,NULL));
6249 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
6250 emitcode ("xch", "a,b");
6251 emitcode ("cpl","a");
6252 emitcode ("add", "a,#1");
6253 emitcode ("xch", "a,b");
6254 emitcode ("cpl", "a"); // msb
6255 emitcode ("addc", "a,#0");
6257 emitcode ("mov","mb,b");
6258 emitcode ("mov","mb,a");
6261 emitcode ("mov","mb,%s",aopGet(right,0,FALSE,FALSE,NULL));
6262 emitcode ("mov","mb,%s",aopGet(right,1,FALSE,FALSE,NULL));
6265 /* wait for multiplication to finish */
6266 lbl = newiTempLabel(NULL);
6268 emitcode("mov","a,mcnt1");
6269 emitcode("anl","a,#!constbyte",0x80);
6270 emitcode("jnz","!tlabel",lbl->key+100);
6272 freeAsmop (left, NULL, ic, TRUE);
6273 freeAsmop (right, NULL, ic,TRUE);
6274 aopOp(result, ic, TRUE, FALSE);
6276 aopPut(result,"mb",1);
6277 aopPut(result,"mb",0);
6278 freeAsmop (result, NULL, ic, TRUE);
6280 /* restore EA bit in F1 */
6281 lbl = newiTempLabel(NULL);
6282 emitcode ("jnb","F1,!tlabel",lbl->key+100);
6283 emitcode ("setb","EA");
6287 /*-----------------------------------------------------------------*/
6288 /* genMod - generates code for division */
6289 /*-----------------------------------------------------------------*/
6293 operand *left = IC_LEFT (ic);
6294 operand *right = IC_RIGHT (ic);
6295 operand *result = IC_RESULT (ic);
6297 D (emitcode (";", "genMod"));
6299 /* assign the asmops */
6302 /* special cases first */
6304 if (AOP_TYPE (left) == AOP_CRY &&
6305 AOP_TYPE (right) == AOP_CRY)
6307 genModbits (left, right, result, ic);
6311 /* if both are of size == 1 */
6312 if (AOP_SIZE (left) == 1 &&
6313 AOP_SIZE (right) == 1)
6315 genModOneByte (left, right, result, ic);
6319 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
6320 /* use the ds390 ARITHMETIC accel UNIT */
6321 genModTwoByte (left, right, result, ic);
6325 /* should have been converted to function call */
6329 freeAsmop (result, NULL, ic, TRUE);
6330 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6331 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6334 /*-----------------------------------------------------------------*/
6335 /* genIfxJump :- will create a jump depending on the ifx */
6336 /*-----------------------------------------------------------------*/
6338 genIfxJump (iCode * ic, char *jval)
6341 symbol *tlbl = newiTempLabel (NULL);
6344 D (emitcode (";", "genIfxJump"));
6346 /* if true label then we jump if condition
6350 jlbl = IC_TRUE (ic);
6351 inst = ((strcmp (jval, "a") == 0 ? "jz" :
6352 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
6356 /* false label is present */
6357 jlbl = IC_FALSE (ic);
6358 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
6359 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
6361 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
6362 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
6364 emitcode (inst, "!tlabel", tlbl->key + 100);
6365 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
6368 /* mark the icode as generated */
6372 /*-----------------------------------------------------------------*/
6373 /* genCmp :- greater or less than comparison */
6374 /*-----------------------------------------------------------------*/
6376 genCmp (operand * left, operand * right,
6377 iCode * ic, iCode * ifx, int sign)
6379 int size, offset = 0;
6380 unsigned long lit = 0L;
6383 D (emitcode (";", "genCmp"));
6385 result = IC_RESULT (ic);
6387 /* if left & right are bit variables */
6388 if (AOP_TYPE (left) == AOP_CRY &&
6389 AOP_TYPE (right) == AOP_CRY)
6391 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6392 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6396 /* subtract right from left if at the
6397 end the carry flag is set then we know that
6398 left is greater than right */
6399 size = max (AOP_SIZE (left), AOP_SIZE (right));
6401 /* if unsigned char cmp with lit, do cjne left,#right,zz */
6402 if ((size == 1) && !sign &&
6403 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
6405 symbol *lbl = newiTempLabel (NULL);
6406 emitcode ("cjne", "%s,%s,!tlabel",
6407 aopGet (left, offset, FALSE, FALSE, NULL),
6408 aopGet (right, offset, FALSE, FALSE, NULL),
6414 if (AOP_TYPE (right) == AOP_LIT)
6416 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6417 /* optimize if(x < 0) or if(x >= 0) */
6426 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
6428 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6429 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6431 aopOp (result, ic, FALSE, FALSE);
6433 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
6435 freeAsmop (result, NULL, ic, TRUE);
6436 genIfxJump (ifx, "acc.7");
6441 emitcode ("rlc", "a");
6443 goto release_freedLR;
6451 // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
6452 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
6453 // emitcode (";", "genCmp #2");
6454 if (sign && (size == 0))
6456 // emitcode (";", "genCmp #3");
6457 emitcode ("xrl", "a,#!constbyte",0x80);
6458 if (AOP_TYPE (right) == AOP_LIT)
6460 unsigned long lit = (unsigned long)
6461 floatFromVal (AOP (right)->aopu.aop_lit);
6462 // emitcode (";", "genCmp #3.1");
6463 emitcode ("subb", "a,#!constbyte",
6464 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
6468 // emitcode (";", "genCmp #3.2");
6470 MOVB (aopGet (right, offset++, FALSE, FALSE, "b"));
6471 saveAccWarn = DEFAULT_ACC_WARNING;
6472 emitcode ("xrl", "b,#!constbyte",0x80);
6473 emitcode ("subb", "a,b");
6480 // emitcode (";", "genCmp #4");
6482 s = aopGet (right, offset++, FALSE, FALSE, "b");
6483 saveAccWarn = DEFAULT_ACC_WARNING;
6485 emitcode ("subb", "a,%s", s);
6492 /* Don't need the left & right operands any more; do need the result. */
6493 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6494 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6496 aopOp (result, ic, FALSE, FALSE);
6500 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6506 /* if the result is used in the next
6507 ifx conditional branch then generate
6508 code a little differently */
6511 genIfxJump (ifx, "c");
6517 /* leave the result in acc */
6519 freeAsmop (result, NULL, ic, TRUE);
6522 /*-----------------------------------------------------------------*/
6523 /* genCmpGt :- greater than comparison */
6524 /*-----------------------------------------------------------------*/
6526 genCmpGt (iCode * ic, iCode * ifx)
6528 operand *left, *right;
6529 sym_link *letype, *retype;
6532 D (emitcode (";", "genCmpGt"));
6534 left = IC_LEFT (ic);
6535 right = IC_RIGHT (ic);
6537 letype = getSpec (operandType (left));
6538 retype = getSpec (operandType (right));
6539 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6541 /* assign the left & right amsops */
6544 genCmp (right, left, ic, ifx, sign);
6547 /*-----------------------------------------------------------------*/
6548 /* genCmpLt - less than comparisons */
6549 /*-----------------------------------------------------------------*/
6551 genCmpLt (iCode * ic, iCode * ifx)
6553 operand *left, *right;
6554 sym_link *letype, *retype;
6557 D (emitcode (";", "genCmpLt"));
6559 left = IC_LEFT (ic);
6560 right = IC_RIGHT (ic);
6562 letype = getSpec (operandType (left));
6563 retype = getSpec (operandType (right));
6564 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6566 /* assign the left & right amsops */
6569 genCmp (left, right, ic, ifx, sign);
6572 /*-----------------------------------------------------------------*/
6573 /* gencjneshort - compare and jump if not equal */
6574 /*-----------------------------------------------------------------*/
6576 gencjneshort (operand * left, operand * right, symbol * lbl)
6578 int size = max (AOP_SIZE (left), AOP_SIZE (right));
6580 unsigned long lit = 0L;
6582 D (emitcode (";", "gencjneshort"));
6584 /* if the left side is a literal or
6585 if the right is in a pointer register and left
6587 if ((AOP_TYPE (left) == AOP_LIT) ||
6588 (AOP_TYPE (left) == AOP_IMMD) ||
6589 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6596 if (AOP_TYPE (right) == AOP_LIT)
6597 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6599 if (opIsGptr (left) || opIsGptr (right))
6601 /* We are comparing a generic pointer to something.
6602 * Exclude the generic type byte from the comparison.
6605 D (emitcode (";", "cjneshort: generic ptr special case."););
6609 /* if the right side is a literal then anything goes */
6610 if (AOP_TYPE (right) == AOP_LIT &&
6611 AOP_TYPE (left) != AOP_DIR)
6615 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
6616 emitcode ("cjne", "a,%s,!tlabel",
6617 aopGet (right, offset, FALSE, FALSE, NULL),
6623 /* if the right side is in a register or in direct space or
6624 if the left is a pointer register & right is not */
6625 else if (AOP_TYPE (right) == AOP_REG ||
6626 AOP_TYPE (right) == AOP_DIR ||
6627 AOP_TYPE (right) == AOP_LIT ||
6628 AOP_TYPE (right) == AOP_IMMD ||
6629 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6630 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6634 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
6635 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6636 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6637 emitcode ("jnz", "!tlabel", lbl->key + 100);
6639 emitcode ("cjne", "a,%s,!tlabel",
6640 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG),
6647 /* right is a pointer reg need both a & b */
6650 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
6651 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
6652 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
6658 /*-----------------------------------------------------------------*/
6659 /* gencjne - compare and jump if not equal */
6660 /*-----------------------------------------------------------------*/
6662 gencjne (operand * left, operand * right, symbol * lbl)
6664 symbol *tlbl = newiTempLabel (NULL);
6666 D (emitcode (";", "gencjne"));
6668 gencjneshort (left, right, lbl);
6670 emitcode ("mov", "a,%s", one);
6671 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
6673 emitcode ("clr", "a");
6677 /*-----------------------------------------------------------------*/
6678 /* genCmpEq - generates code for equal to */
6679 /*-----------------------------------------------------------------*/
6681 genCmpEq (iCode * ic, iCode * ifx)
6683 operand *left, *right, *result;
6685 D (emitcode (";", "genCmpEq"));
6688 AOP_SET_LOCALS (ic);
6690 /* if literal, literal on the right or
6691 if the right is in a pointer register and left
6693 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6694 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6696 operand *t = IC_RIGHT (ic);
6697 IC_RIGHT (ic) = IC_LEFT (ic);
6701 if (ifx && /* !AOP_SIZE(result) */
6702 OP_SYMBOL (result) &&
6703 OP_SYMBOL (result)->regType == REG_CND)
6706 /* if they are both bit variables */
6707 if (AOP_TYPE (left) == AOP_CRY &&
6708 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6710 if (AOP_TYPE (right) == AOP_LIT)
6712 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6715 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6716 emitcode ("cpl", "c");
6720 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6724 emitcode ("clr", "c");
6726 /* AOP_TYPE(right) == AOP_CRY */
6730 symbol *lbl = newiTempLabel (NULL);
6731 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6732 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6733 emitcode ("cpl", "c");
6736 /* if true label then we jump if condition
6738 tlbl = newiTempLabel (NULL);
6741 emitcode ("jnc", "!tlabel", tlbl->key + 100);
6742 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6746 emitcode ("jc", "!tlabel", tlbl->key + 100);
6747 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6753 tlbl = newiTempLabel (NULL);
6754 gencjneshort (left, right, tlbl);
6757 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6762 symbol *lbl = newiTempLabel (NULL);
6763 emitcode ("sjmp", "!tlabel", lbl->key + 100);
6765 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6769 /* mark the icode as generated */
6772 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6773 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6777 /* if they are both bit variables */
6778 if (AOP_TYPE (left) == AOP_CRY &&
6779 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6781 if (AOP_TYPE (right) == AOP_LIT)
6783 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6786 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6787 emitcode ("cpl", "c");
6791 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6795 emitcode ("clr", "c");
6797 /* AOP_TYPE(right) == AOP_CRY */
6801 symbol *lbl = newiTempLabel (NULL);
6802 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6803 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6804 emitcode ("cpl", "c");
6808 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6809 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6811 aopOp (result, ic, TRUE, FALSE);
6814 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6821 genIfxJump (ifx, "c");
6824 /* if the result is used in an arithmetic operation
6825 then put the result in place */
6830 gencjne (left, right, newiTempLabel (NULL));
6832 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6833 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6835 aopOp (result, ic, TRUE, FALSE);
6837 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6839 aopPut (result, "a", 0);
6844 genIfxJump (ifx, "a");
6847 /* if the result is used in an arithmetic operation
6848 then put the result in place */
6849 if (AOP_TYPE (result) != AOP_CRY)
6851 /* leave the result in acc */
6855 freeAsmop (result, NULL, ic, TRUE);
6858 /*-----------------------------------------------------------------*/
6859 /* ifxForOp - returns the icode containing the ifx for operand */
6860 /*-----------------------------------------------------------------*/
6862 ifxForOp (operand * op, iCode * ic)
6864 /* if true symbol then needs to be assigned */
6865 if (IS_TRUE_SYMOP (op))
6868 /* if this has register type condition and
6869 the next instruction is ifx with the same operand
6870 and live to of the operand is upto the ifx only then */
6872 ic->next->op == IFX &&
6873 IC_COND (ic->next)->key == op->key &&
6874 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6880 /*-----------------------------------------------------------------*/
6881 /* hasInc - operand is incremented before any other use */
6882 /*-----------------------------------------------------------------*/
6884 hasInc (operand *op, iCode *ic, int osize)
6886 sym_link *type = operandType(op);
6887 sym_link *retype = getSpec (type);
6888 iCode *lic = ic->next;
6891 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6892 if (!IS_SYMOP(op)) return NULL;
6894 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6895 if (IS_AGGREGATE(type->next)) return NULL;
6896 if (osize != (isize = getSize(type->next))) return NULL;
6899 /* if operand of the form op = op + <sizeof *op> */
6900 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6901 isOperandEqual(IC_RESULT(lic),op) &&
6902 isOperandLiteral(IC_RIGHT(lic)) &&
6903 operandLitValue(IC_RIGHT(lic)) == isize) {
6906 /* if the operand used or deffed */
6907 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6910 /* if GOTO or IFX */
6911 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6917 /*-----------------------------------------------------------------*/
6918 /* genAndOp - for && operation */
6919 /*-----------------------------------------------------------------*/
6921 genAndOp (iCode * ic)
6923 operand *left, *right, *result;
6926 D (emitcode (";", "genAndOp"));
6928 /* note here that && operations that are in an
6929 if statement are taken away by backPatchLabels
6930 only those used in arthmetic operations remain */
6932 AOP_SET_LOCALS (ic);
6934 /* if both are bit variables */
6935 if (AOP_TYPE (left) == AOP_CRY &&
6936 AOP_TYPE (right) == AOP_CRY)
6938 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6939 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6940 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6941 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6943 aopOp (result,ic,FALSE, FALSE);
6948 tlbl = newiTempLabel (NULL);
6950 emitcode ("jz", "!tlabel", tlbl->key + 100);
6953 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6954 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6956 aopOp (result,ic,FALSE, FALSE);
6960 freeAsmop (result, NULL, ic, TRUE);
6964 /*-----------------------------------------------------------------*/
6965 /* genOrOp - for || operation */
6966 /*-----------------------------------------------------------------*/
6968 genOrOp (iCode * ic)
6970 operand *left, *right, *result;
6973 D (emitcode (";", "genOrOp"));
6975 /* note here that || operations that are in an
6976 if statement are taken away by backPatchLabels
6977 only those used in arthmetic operations remain */
6979 AOP_SET_LOCALS (ic);
6981 /* if both are bit variables */
6982 if (AOP_TYPE (left) == AOP_CRY &&
6983 AOP_TYPE (right) == AOP_CRY)
6985 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6986 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6987 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6988 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6990 aopOp (result,ic,FALSE, FALSE);
6996 tlbl = newiTempLabel (NULL);
6998 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7001 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7002 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7004 aopOp (result,ic,FALSE, FALSE);
7009 freeAsmop (result, NULL, ic, TRUE);
7012 /*-----------------------------------------------------------------*/
7013 /* isLiteralBit - test if lit == 2^n */
7014 /*-----------------------------------------------------------------*/
7016 isLiteralBit (unsigned long lit)
7018 unsigned long pw[32] =
7019 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
7020 0x100L, 0x200L, 0x400L, 0x800L,
7021 0x1000L, 0x2000L, 0x4000L, 0x8000L,
7022 0x10000L, 0x20000L, 0x40000L, 0x80000L,
7023 0x100000L, 0x200000L, 0x400000L, 0x800000L,
7024 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
7025 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
7028 for (idx = 0; idx < 32; idx++)
7034 /*-----------------------------------------------------------------*/
7035 /* continueIfTrue - */
7036 /*-----------------------------------------------------------------*/
7038 continueIfTrue (iCode * ic)
7041 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
7045 /*-----------------------------------------------------------------*/
7047 /*-----------------------------------------------------------------*/
7049 jumpIfTrue (iCode * ic)
7052 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
7056 /*-----------------------------------------------------------------*/
7057 /* jmpTrueOrFalse - */
7058 /*-----------------------------------------------------------------*/
7060 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
7062 // ugly but optimized by peephole
7065 symbol *nlbl = newiTempLabel (NULL);
7066 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
7068 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
7073 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
7079 // Generate code to perform a bit-wise logic operation
7080 // on two operands in far space (assumed to already have been
7081 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
7082 // in far space. This requires pushing the result on the stack
7083 // then popping it into the result.
7085 genFarFarLogicOp(iCode *ic, char *logicOp)
7087 int size, resultSize, compSize;
7091 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
7092 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
7093 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
7095 _startLazyDPSEvaluation();
7096 for (size = compSize; (size--); offset++)
7098 MOVA (aopGet (IC_LEFT(ic), offset, FALSE, FALSE, NULL));
7099 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
7100 MOVA (aopGet (IC_RIGHT(ic), offset, FALSE, FALSE, NULL));
7102 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
7103 emitcode ("push", "acc");
7105 _endLazyDPSEvaluation();
7107 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7108 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7109 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
7111 resultSize = AOP_SIZE(IC_RESULT(ic));
7113 ADJUST_PUSHED_RESULT(compSize, resultSize);
7115 _startLazyDPSEvaluation();
7118 emitcode ("pop", "acc");
7119 aopPut (IC_RESULT (ic), "a", compSize);
7121 _endLazyDPSEvaluation();
7122 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
7126 /*-----------------------------------------------------------------*/
7127 /* genAnd - code for and */
7128 /*-----------------------------------------------------------------*/
7130 genAnd (iCode * ic, iCode * ifx)
7132 operand *left, *right, *result;
7133 int size, offset = 0;
7134 unsigned long lit = 0L;
7139 D (emitcode (";", "genAnd"));
7141 AOP_OP_3_NOFATAL (ic, pushResult);
7142 AOP_SET_LOCALS (ic);
7146 genFarFarLogicOp(ic, "anl");
7151 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7153 AOP_TYPE (left), AOP_TYPE (right));
7154 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7156 AOP_SIZE (left), AOP_SIZE (right));
7159 /* if left is a literal & right is not then exchange them */
7160 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7161 #ifdef LOGIC_OPS_BROKEN
7162 || AOP_NEEDSACC (left)
7166 operand *tmp = right;
7171 /* if result = right then exchange left and right */
7172 if (sameRegs (AOP (result), AOP (right)))
7174 operand *tmp = right;
7179 /* if right is bit then exchange them */
7180 if (AOP_TYPE (right) == AOP_CRY &&
7181 AOP_TYPE (left) != AOP_CRY)
7183 operand *tmp = right;
7187 if (AOP_TYPE (right) == AOP_LIT)
7188 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7190 size = AOP_SIZE (result);
7193 // result = bit & yy;
7194 if (AOP_TYPE (left) == AOP_CRY)
7196 // c = bit & literal;
7197 if (AOP_TYPE (right) == AOP_LIT)
7201 if (size && sameRegs (AOP (result), AOP (left)))
7204 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7209 if (size && (AOP_TYPE (result) == AOP_CRY))
7211 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
7214 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7219 emitcode ("clr", "c");
7224 if (AOP_TYPE (right) == AOP_CRY)
7227 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7228 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
7233 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
7235 emitcode ("rrc", "a");
7236 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
7244 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7245 genIfxJump (ifx, "c");
7249 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7250 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7251 if ((AOP_TYPE (right) == AOP_LIT) &&
7252 (AOP_TYPE (result) == AOP_CRY) &&
7253 (AOP_TYPE (left) != AOP_CRY))
7255 int posbit = isLiteralBit (lit);
7260 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE, NULL));
7264 switch (posbit & 0x07)
7266 case 0: emitcode ("rrc", "a");
7268 case 7: emitcode ("rlc", "a");
7270 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
7279 SNPRINTF (buffer, sizeof(buffer),
7280 "acc.%d", posbit & 0x07);
7281 genIfxJump (ifx, buffer);
7285 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
7292 symbol *tlbl = newiTempLabel (NULL);
7293 int sizel = AOP_SIZE (left);
7295 emitcode ("setb", "c");
7298 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
7300 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7302 if ((posbit = isLiteralBit (bytelit)) != 0)
7303 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
7306 if (bytelit != 0x0FFL)
7307 emitcode ("anl", "a,%s",
7308 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG));
7309 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7314 // bit = left & literal
7317 emitcode ("clr", "c");
7320 // if(left & literal)
7324 jmpTrueOrFalse (ifx, tlbl);
7334 /* if left is same as result */
7335 if (sameRegs (AOP (result), AOP (left)))
7337 for (; size--; offset++)
7339 if (AOP_TYPE (right) == AOP_LIT)
7341 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7342 if (bytelit == 0x0FF)
7344 /* dummy read of volatile operand */
7345 if (isOperandVolatile (left, FALSE))
7346 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7350 else if (bytelit == 0)
7352 aopPut (result, zero, offset);
7354 else if (IS_AOP_PREG (result))
7356 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7357 emitcode ("anl", "a,%s",
7358 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG));
7359 aopPut (result, "a", offset);
7362 emitcode ("anl", "%s,%s",
7363 aopGet (left, offset, FALSE, TRUE, NULL),
7364 aopGet (right, offset, FALSE, FALSE, NULL));
7368 if (AOP_TYPE (left) == AOP_ACC)
7371 emitcode("mov", "a,b");
7372 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7374 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7376 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
7377 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7378 emitcode ("anl", "a,b");
7379 aopPut (result, "a", offset);
7381 else if (aopGetUsesAcc (left, offset))
7383 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7384 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7385 aopPut (result, "a", offset);
7389 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7390 if (IS_AOP_PREG (result))
7392 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7393 aopPut (result, "a", offset);
7396 emitcode ("anl", "%s,a", aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7403 // left & result in different registers
7404 if (AOP_TYPE (result) == AOP_CRY)
7407 // if(size), result in bit
7408 // if(!size && ifx), conditional oper: if(left & right)
7409 symbol *tlbl = newiTempLabel (NULL);
7410 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
7412 emitcode ("setb", "c");
7415 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7416 && AOP_TYPE(left)==AOP_ACC)
7419 emitcode("mov", "a,b");
7420 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, NULL));
7422 else if (AOP_TYPE(left)==AOP_ACC)
7426 bool pushedB = pushB ();
7427 emitcode("mov", "b,a");
7428 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7429 emitcode("anl", "a,b");
7434 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7435 emitcode("anl", "a,b");
7438 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7440 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE, NULL));
7441 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7442 emitcode ("anl", "a,b");
7444 else if (aopGetUsesAcc (left, offset))
7446 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7447 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7451 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7452 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE, DP2_RESULT_REG));
7455 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7465 jmpTrueOrFalse (ifx, tlbl);
7471 for (; (size--); offset++)
7474 // result = left & right
7475 if (AOP_TYPE (right) == AOP_LIT)
7477 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7478 if (bytelit == 0x0FF)
7481 aopGet (left, offset, FALSE, FALSE, NULL),
7485 else if (bytelit == 0)
7487 /* dummy read of volatile operand */
7488 if (isOperandVolatile (left, FALSE))
7489 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7490 aopPut (result, zero, offset);
7493 else if (AOP_TYPE (left) == AOP_ACC)
7497 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, NULL));
7498 aopPut (result, "a", offset);
7503 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE, NULL));
7504 aopPut (result, "b", offset);
7509 // faster than result <- left, anl result,right
7510 // and better if result is SFR
7511 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7512 && AOP_TYPE(left)==AOP_ACC)
7515 emitcode("mov", "a,b");
7516 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, NULL));
7518 else if (AOP_TYPE(left)==AOP_ACC)
7522 bool pushedB = pushB ();
7523 emitcode("mov", "b,a");
7524 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7525 emitcode("anl", "a,b");
7530 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7531 emitcode("anl", "a,b");
7534 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7536 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
7537 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7538 emitcode ("anl", "a,b");
7540 else if (aopGetUsesAcc (left, offset))
7542 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7543 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7547 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7548 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE, DP2_RESULT_REG));
7550 aopPut (result, "a", offset);
7556 freeAsmop (result, NULL, ic, TRUE);
7557 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7558 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7561 /*-----------------------------------------------------------------*/
7562 /* genOr - code for or */
7563 /*-----------------------------------------------------------------*/
7565 genOr (iCode * ic, iCode * ifx)
7567 operand *left, *right, *result;
7568 int size, offset = 0;
7569 unsigned long lit = 0L;
7573 D (emitcode (";", "genOr"));
7575 AOP_OP_3_NOFATAL (ic, pushResult);
7576 AOP_SET_LOCALS (ic);
7580 genFarFarLogicOp(ic, "orl");
7586 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7588 AOP_TYPE (left), AOP_TYPE (right));
7589 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7591 AOP_SIZE (left), AOP_SIZE (right));
7594 /* if left is a literal & right is not then exchange them */
7595 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7596 #ifdef LOGIC_OPS_BROKEN
7597 || AOP_NEEDSACC (left) // I think this is a net loss now.
7601 operand *tmp = right;
7606 /* if result = right then exchange them */
7607 if (sameRegs (AOP (result), AOP (right)))
7609 operand *tmp = right;
7614 /* if right is bit then exchange them */
7615 if (AOP_TYPE (right) == AOP_CRY &&
7616 AOP_TYPE (left) != AOP_CRY)
7618 operand *tmp = right;
7622 if (AOP_TYPE (right) == AOP_LIT)
7623 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7625 size = AOP_SIZE (result);
7629 if (AOP_TYPE (left) == AOP_CRY)
7631 if (AOP_TYPE (right) == AOP_LIT)
7633 // c = bit | literal;
7636 // lit != 0 => result = 1
7637 if (AOP_TYPE (result) == AOP_CRY)
7640 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7642 continueIfTrue (ifx);
7645 emitcode ("setb", "c");
7649 // lit == 0 => result = left
7650 if (size && sameRegs (AOP (result), AOP (left)))
7652 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7657 if (AOP_TYPE (right) == AOP_CRY)
7660 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7661 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7666 symbol *tlbl = newiTempLabel (NULL);
7667 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
7668 emitcode ("setb", "c");
7669 emitcode ("jb", "%s,!tlabel",
7670 AOP (left)->aopu.aop_dir, tlbl->key + 100);
7672 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7673 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7675 jmpTrueOrFalse (ifx, tlbl);
7690 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7691 genIfxJump (ifx, "c");
7695 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7696 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7697 if ((AOP_TYPE (right) == AOP_LIT) &&
7698 (AOP_TYPE (result) == AOP_CRY) &&
7699 (AOP_TYPE (left) != AOP_CRY))
7705 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7707 continueIfTrue (ifx);
7712 // lit = 0, result = boolean(left)
7714 emitcode ("setb", "c");
7718 symbol *tlbl = newiTempLabel (NULL);
7719 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7725 genIfxJump (ifx, "a");
7733 /* if left is same as result */
7734 if (sameRegs (AOP (result), AOP (left)))
7736 for (; size--; offset++)
7738 if (AOP_TYPE (right) == AOP_LIT)
7740 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7743 /* dummy read of volatile operand */
7744 if (isOperandVolatile (left, FALSE))
7745 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7749 else if (bytelit == 0x0FF)
7751 aopPut (result, "#0xFF", offset);
7753 else if (IS_AOP_PREG (left))
7755 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7756 emitcode ("orl", "a,%s",
7757 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7758 aopPut (result, "a", offset);
7762 emitcode ("orl", "%s,%s",
7763 aopGet (left, offset, FALSE, TRUE, NULL),
7764 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7769 if (AOP_TYPE (left) == AOP_ACC)
7772 emitcode("mov", "a,b");
7773 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7775 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7777 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE, NULL));
7778 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7779 emitcode ("orl", "a,b");
7780 aopPut (result, "a", offset);
7782 else if (aopGetUsesAcc (left, offset))
7784 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7785 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7786 aopPut (result, "a", offset);
7790 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7791 if (IS_AOP_PREG (left))
7793 emitcode ("orl", "a,%s",
7794 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7795 aopPut (result, "a", offset);
7799 emitcode ("orl", "%s,a",
7800 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7808 // left & result in different registers
7809 if (AOP_TYPE (result) == AOP_CRY)
7812 // if(size), result in bit
7813 // if(!size && ifx), conditional oper: if(left | right)
7814 symbol *tlbl = newiTempLabel (NULL);
7815 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7817 emitcode ("setb", "c");
7820 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7821 && AOP_TYPE(left)==AOP_ACC)
7824 emitcode("mov", "a,b");
7825 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7827 else if (AOP_TYPE(left)==AOP_ACC)
7831 bool pushedB = pushB ();
7832 emitcode("mov", "b,a");
7833 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7834 emitcode("orl", "a,b");
7839 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7840 emitcode("orl", "a,b");
7843 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7845 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
7846 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7847 emitcode ("orl", "a,b");
7849 else if (aopGetUsesAcc (left, offset))
7851 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7852 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7856 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7857 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE, DP2_RESULT_REG));
7860 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7870 jmpTrueOrFalse (ifx, tlbl);
7876 _startLazyDPSEvaluation();
7877 for (; (size--); offset++)
7880 // result = left | right
7881 if (AOP_TYPE (right) == AOP_LIT)
7883 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7887 aopGet (left, offset, FALSE, FALSE, NULL),
7891 else if (bytelit == 0x0FF)
7893 /* dummy read of volatile operand */
7894 if (isOperandVolatile (left, FALSE))
7895 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7896 aopPut (result, "#0xFF", offset);
7900 // faster than result <- left, orl result,right
7901 // and better if result is SFR
7902 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7903 && AOP_TYPE(left)==AOP_ACC)
7906 emitcode("mov", "a,b");
7907 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7909 else if (AOP_TYPE(left)==AOP_ACC)
7913 bool pushedB = pushB ();
7914 emitcode("mov", "b,a");
7915 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7916 emitcode("orl", "a,b");
7921 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7922 emitcode("orl", "a,b");
7925 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7927 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
7928 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7929 emitcode ("orl", "a,b");
7931 else if (aopGetUsesAcc (left, offset))
7933 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7934 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7938 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7939 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE, DP2_RESULT_REG));
7941 aopPut (result, "a", offset);
7943 _endLazyDPSEvaluation();
7948 freeAsmop (result, NULL, ic, TRUE);
7949 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7950 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7953 /*-----------------------------------------------------------------*/
7954 /* genXor - code for xclusive or */
7955 /*-----------------------------------------------------------------*/
7957 genXor (iCode * ic, iCode * ifx)
7959 operand *left, *right, *result;
7960 int size, offset = 0;
7961 unsigned long lit = 0L;
7965 D (emitcode (";", "genXor"));
7967 AOP_OP_3_NOFATAL (ic, pushResult);
7968 AOP_SET_LOCALS (ic);
7972 genFarFarLogicOp(ic, "xrl");
7977 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7979 AOP_TYPE (left), AOP_TYPE (right));
7980 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7982 AOP_SIZE (left), AOP_SIZE (right));
7985 /* if left is a literal & right is not ||
7986 if left needs acc & right does not */
7987 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7988 #ifdef LOGIC_OPS_BROKEN
7989 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
7993 operand *tmp = right;
7998 /* if result = right then exchange them */
7999 if (sameRegs (AOP (result), AOP (right)))
8001 operand *tmp = right;
8006 /* if right is bit then exchange them */
8007 if (AOP_TYPE (right) == AOP_CRY &&
8008 AOP_TYPE (left) != AOP_CRY)
8010 operand *tmp = right;
8014 if (AOP_TYPE (right) == AOP_LIT)
8015 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8017 size = AOP_SIZE (result);
8021 if (AOP_TYPE (left) == AOP_CRY)
8023 if (AOP_TYPE (right) == AOP_LIT)
8025 // c = bit & literal;
8028 // lit>>1 != 0 => result = 1
8029 if (AOP_TYPE (result) == AOP_CRY)
8032 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
8034 continueIfTrue (ifx);
8037 emitcode ("setb", "c");
8044 // lit == 0, result = left
8045 if (size && sameRegs (AOP (result), AOP (left)))
8047 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
8051 // lit == 1, result = not(left)
8052 if (size && sameRegs (AOP (result), AOP (left)))
8054 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
8059 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
8060 emitcode ("cpl", "c");
8068 symbol *tlbl = newiTempLabel (NULL);
8069 if (AOP_TYPE (right) == AOP_CRY)
8072 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8076 int sizer = AOP_SIZE (right);
8078 // if val>>1 != 0, result = 1
8079 emitcode ("setb", "c");
8082 MOVA (aopGet (right, sizer - 1, FALSE, FALSE, NULL));
8084 // test the msb of the lsb
8085 emitcode ("anl", "a,#!constbyte",0xfe);
8086 emitcode ("jnz", "!tlabel", tlbl->key + 100);
8090 emitcode ("rrc", "a");
8092 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
8093 emitcode ("cpl", "c");
8101 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
8102 genIfxJump (ifx, "c");
8106 /* if left is same as result */
8107 if (sameRegs (AOP (result), AOP (left)))
8109 for (; size--; offset++)
8111 if (AOP_TYPE (right) == AOP_LIT)
8113 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
8116 /* dummy read of volatile operand */
8117 if (isOperandVolatile (left, FALSE))
8118 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8122 else if (IS_AOP_PREG (left))
8124 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8125 emitcode ("xrl", "a,%s",
8126 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG));
8127 aopPut (result, "a", offset);
8131 emitcode ("xrl", "%s,%s",
8132 aopGet (left, offset, FALSE, TRUE, NULL),
8133 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8138 if (AOP_TYPE (left) == AOP_ACC)
8141 emitcode("mov", "a,b");
8142 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8144 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
8146 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
8147 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8148 emitcode ("xrl", "a,b");
8149 aopPut (result, "a", offset);
8151 else if (aopGetUsesAcc (left, offset))
8153 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8154 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8155 aopPut (result, "a", offset);
8159 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
8160 if (IS_AOP_PREG (left))
8162 emitcode ("xrl", "a,%s",
8163 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
8164 aopPut (result, "a", offset);
8167 emitcode ("xrl", "%s,a",
8168 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
8175 // left & result in different registers
8176 if (AOP_TYPE (result) == AOP_CRY)
8179 // if(size), result in bit
8180 // if(!size && ifx), conditional oper: if(left ^ right)
8181 symbol *tlbl = newiTempLabel (NULL);
8182 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
8185 emitcode ("setb", "c");
8188 if ((AOP_TYPE (right) == AOP_LIT) &&
8189 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
8191 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8193 else if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
8194 && AOP_TYPE(left)==AOP_ACC)
8197 emitcode("mov", "a,b");
8198 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8200 else if (AOP_TYPE(left)==AOP_ACC)
8204 bool pushedB = pushB ();
8205 emitcode("mov", "b,a");
8206 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8207 emitcode("xrl", "a,b");
8212 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8213 emitcode("xrl", "a,b");
8216 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
8218 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
8219 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8220 emitcode ("xrl", "a,b");
8222 else if (aopGetUsesAcc (left, offset))
8224 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8225 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8229 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
8230 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
8233 emitcode ("jnz", "!tlabel", tlbl->key + 100);
8243 jmpTrueOrFalse (ifx, tlbl);
8247 for (; (size--); offset++)
8250 // result = left ^ right
8251 if (AOP_TYPE (right) == AOP_LIT)
8253 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
8257 aopGet (left, offset, FALSE, FALSE, NULL),
8261 D (emitcode (";", "better literal XOR."));
8262 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8263 emitcode ("xrl", "a, %s",
8264 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8268 // faster than result <- left, anl result,right
8269 // and better if result is SFR
8270 if (AOP_TYPE (left) == AOP_ACC)
8272 emitcode ("xrl", "a,%s",
8273 aopGet (right, offset,
8274 FALSE, FALSE, DP2_RESULT_REG));
8278 char *rOp = aopGet (right, offset, FALSE, FALSE, NULL);
8279 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
8281 emitcode("mov", "b,a");
8285 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8286 emitcode ("xrl", "a,%s", rOp);
8289 aopPut (result, "a", offset);
8295 freeAsmop (result, NULL, ic, TRUE);
8296 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
8297 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
8300 /*-----------------------------------------------------------------*/
8301 /* genInline - write the inline code out */
8302 /*-----------------------------------------------------------------*/
8304 genInline (iCode * ic)
8306 char *buffer, *bp, *bp1;
8308 D (emitcode (";", "genInline"));
8310 _G.inLine += (!options.asmpeep);
8312 buffer = bp = bp1 = Safe_strdup(IC_INLINE(ic));
8314 /* emit each line as a code */
8325 /* Add \n for labels, not dirs such as c:\mydir */
8326 if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
8340 /* emitcode("",buffer); */
8341 _G.inLine -= (!options.asmpeep);
8344 /*-----------------------------------------------------------------*/
8345 /* genRRC - rotate right with carry */
8346 /*-----------------------------------------------------------------*/
8350 operand *left, *result;
8354 D (emitcode (";", "genRRC"));
8356 /* rotate right with carry */
8357 left = IC_LEFT (ic);
8358 result = IC_RESULT (ic);
8359 aopOp (left, ic, FALSE, FALSE);
8360 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8362 /* move it to the result */
8363 size = AOP_SIZE (result);
8367 _startLazyDPSEvaluation ();
8370 l = aopGet (left, offset, FALSE, FALSE, NULL);
8372 emitcode ("rrc", "a");
8373 if (AOP_SIZE (result) > 1)
8374 aopPut (result, "a", offset--);
8376 _endLazyDPSEvaluation ();
8378 /* now we need to put the carry into the
8379 highest order byte of the result */
8380 if (AOP_SIZE (result) > 1)
8382 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE, NULL);
8385 emitcode ("mov", "acc.7,c");
8386 aopPut (result, "a", AOP_SIZE (result) - 1);
8387 freeAsmop (result, NULL, ic, TRUE);
8388 freeAsmop (left, NULL, ic, TRUE);
8391 /*-----------------------------------------------------------------*/
8392 /* genRLC - generate code for rotate left with carry */
8393 /*-----------------------------------------------------------------*/
8397 operand *left, *result;
8401 D (emitcode (";", "genRLC"));
8403 /* rotate right with carry */
8404 left = IC_LEFT (ic);
8405 result = IC_RESULT (ic);
8406 aopOp (left, ic, FALSE, FALSE);
8407 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8409 /* move it to the result */
8410 size = AOP_SIZE (result);
8414 l = aopGet (left, offset, FALSE, FALSE, NULL);
8416 emitcode ("add", "a,acc");
8417 if (AOP_SIZE (result) > 1)
8419 aopPut (result, "a", offset++);
8422 _startLazyDPSEvaluation ();
8425 l = aopGet (left, offset, FALSE, FALSE, NULL);
8427 emitcode ("rlc", "a");
8428 if (AOP_SIZE (result) > 1)
8429 aopPut (result, "a", offset++);
8431 _endLazyDPSEvaluation ();
8433 /* now we need to put the carry into the
8434 highest order byte of the result */
8435 if (AOP_SIZE (result) > 1)
8437 l = aopGet (result, 0, FALSE, FALSE, NULL);
8440 emitcode ("mov", "acc.0,c");
8441 aopPut (result, "a", 0);
8442 freeAsmop (result, NULL, ic, TRUE);
8443 freeAsmop (left, NULL, ic, TRUE);
8446 /*-----------------------------------------------------------------*/
8447 /* genGetHbit - generates code get highest order bit */
8448 /*-----------------------------------------------------------------*/
8450 genGetHbit (iCode * ic)
8452 operand *left, *result;
8454 D (emitcode (";", "genGetHbit"));
8456 left = IC_LEFT (ic);
8457 result = IC_RESULT (ic);
8458 aopOp (left, ic, FALSE, FALSE);
8459 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8461 /* get the highest order byte into a */
8462 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
8463 if (AOP_TYPE (result) == AOP_CRY)
8465 emitcode ("rlc", "a");
8470 emitcode ("rl", "a");
8471 emitcode ("anl", "a,#1");
8476 freeAsmop (result, NULL, ic, TRUE);
8477 freeAsmop (left, NULL, ic, TRUE);
8480 /*-----------------------------------------------------------------*/
8481 /* genSwap - generates code to swap nibbles or bytes */
8482 /*-----------------------------------------------------------------*/
8484 genSwap (iCode * ic)
8486 operand *left, *result;
8488 D(emitcode ("; genSwap",""));
8490 left = IC_LEFT (ic);
8491 result = IC_RESULT (ic);
8492 aopOp (left, ic, FALSE, FALSE);
8493 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8495 _startLazyDPSEvaluation ();
8496 switch (AOP_SIZE (left))
8498 case 1: /* swap nibbles in byte */
8499 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
8500 emitcode ("swap", "a");
8501 aopPut (result, "a", 0);
8503 case 2: /* swap bytes in word */
8504 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
8506 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
8507 aopPut (result, aopGet (left, 1, FALSE, FALSE, NULL), 0);
8508 aopPut (result, "a", 1);
8510 else if (operandsEqu (left, result))
8513 bool pushedB = FALSE, leftInB = FALSE;
8515 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
8516 if (AOP_NEEDSACC (left) || AOP_NEEDSACC (result))
8519 emitcode ("mov", "b,a");
8523 aopPut (result, aopGet (left, 1, FALSE, FALSE, NULL), 0);
8524 aopPut (result, reg, 1);
8531 aopPut (result, aopGet (left, 1, FALSE, FALSE, NULL), 0);
8532 aopPut (result, aopGet (left, 0, FALSE, FALSE, NULL), 1);
8536 wassertl(FALSE, "unsupported SWAP operand size");
8538 _endLazyDPSEvaluation ();
8540 freeAsmop (result, NULL, ic, TRUE);
8541 freeAsmop (left, NULL, ic, TRUE);
8544 /*-----------------------------------------------------------------*/
8545 /* AccRol - rotate left accumulator by known count */
8546 /*-----------------------------------------------------------------*/
8548 AccRol (int shCount)
8550 shCount &= 0x0007; // shCount : 0..7
8557 emitcode ("rl", "a");
8560 emitcode ("rl", "a");
8561 emitcode ("rl", "a");
8564 emitcode ("swap", "a");
8565 emitcode ("rr", "a");
8568 emitcode ("swap", "a");
8571 emitcode ("swap", "a");
8572 emitcode ("rl", "a");
8575 emitcode ("rr", "a");
8576 emitcode ("rr", "a");
8579 emitcode ("rr", "a");
8584 /*-----------------------------------------------------------------*/
8585 /* AccLsh - left shift accumulator by known count */
8586 /*-----------------------------------------------------------------*/
8588 AccLsh (int shCount)
8593 emitcode ("add", "a,acc");
8594 else if (shCount == 2)
8596 emitcode ("add", "a,acc");
8597 emitcode ("add", "a,acc");
8601 /* rotate left accumulator */
8603 /* and kill the lower order bits */
8604 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
8609 /*-----------------------------------------------------------------*/
8610 /* AccRsh - right shift accumulator by known count */
8611 /*-----------------------------------------------------------------*/
8613 AccRsh (int shCount)
8620 emitcode ("rrc", "a");
8624 /* rotate right accumulator */
8625 AccRol (8 - shCount);
8626 /* and kill the higher order bits */
8627 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
8632 #ifdef BETTER_LITERAL_SHIFT
8633 /*-----------------------------------------------------------------*/
8634 /* AccSRsh - signed right shift accumulator by known count */
8635 /*-----------------------------------------------------------------*/
8637 AccSRsh (int shCount)
8644 emitcode ("mov", "c,acc.7");
8645 emitcode ("rrc", "a");
8647 else if (shCount == 2)
8649 emitcode ("mov", "c,acc.7");
8650 emitcode ("rrc", "a");
8651 emitcode ("mov", "c,acc.7");
8652 emitcode ("rrc", "a");
8656 tlbl = newiTempLabel (NULL);
8657 /* rotate right accumulator */
8658 AccRol (8 - shCount);
8659 /* and kill the higher order bits */
8660 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
8661 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8662 emitcode ("orl", "a,#!constbyte",
8663 (unsigned char) ~SRMask[shCount]);
8670 #ifdef BETTER_LITERAL_SHIFT
8671 /*-----------------------------------------------------------------*/
8672 /* shiftR1Left2Result - shift right one byte from left to result */
8673 /*-----------------------------------------------------------------*/
8675 shiftR1Left2Result (operand * left, int offl,
8676 operand * result, int offr,
8677 int shCount, int sign)
8679 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
8680 /* shift right accumulator */
8685 aopPut (result, "a", offr);
8689 #ifdef BETTER_LITERAL_SHIFT
8690 /*-----------------------------------------------------------------*/
8691 /* shiftL1Left2Result - shift left one byte from left to result */
8692 /*-----------------------------------------------------------------*/
8694 shiftL1Left2Result (operand * left, int offl,
8695 operand * result, int offr, int shCount)
8698 l = aopGet (left, offl, FALSE, FALSE, NULL);
8700 /* shift left accumulator */
8702 aopPut (result, "a", offr);
8706 #ifdef BETTER_LITERAL_SHIFT
8707 /*-----------------------------------------------------------------*/
8708 /* movLeft2Result - move byte from left to result */
8709 /*-----------------------------------------------------------------*/
8711 movLeft2Result (operand * left, int offl,
8712 operand * result, int offr, int sign)
8715 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8717 l = aopGet (left, offl, FALSE, FALSE, NULL);
8719 if (*l == '@' && (IS_AOP_PREG (result)))
8721 emitcode ("mov", "a,%s", l);
8722 aopPut (result, "a", offr);
8728 aopPut (result, l, offr);
8732 /* MSB sign in acc.7 ! */
8733 if (getDataSize (left) == offl + 1)
8736 aopPut (result, "a", offr);
8744 #ifdef BETTER_LITERAL_SHIFT
8745 /*-----------------------------------------------------------------*/
8746 /* AccAXRrl1 - right rotate a:x by 1 */
8747 /*-----------------------------------------------------------------*/
8751 emitcode ("mov", "c,acc.0");
8752 emitcode ("xch", "a,%s", x);
8753 emitcode ("rrc", "a");
8754 emitcode ("xch", "a,%s", x);
8755 emitcode ("rrc", "a");
8759 #ifdef BETTER_LITERAL_SHIFT
8761 /*-----------------------------------------------------------------*/
8762 /* AccAXLrl1 - left rotate a:x by 1 */
8763 /*-----------------------------------------------------------------*/
8767 emitcode ("mov", "c,acc.7");
8768 emitcode ("xch", "a,%s", x);
8769 emitcode ("rlc", "a");
8770 emitcode ("xch", "a,%s", x);
8771 emitcode ("rlc", "a");
8775 #ifdef BETTER_LITERAL_SHIFT
8776 /*-----------------------------------------------------------------*/
8777 /* AccAXRsh1 - right shift c->a:x->c by 1 */
8778 /*-----------------------------------------------------------------*/
8782 emitcode ("rrc", "a");
8783 emitcode ("xch", "a,%s", x);
8784 emitcode ("rrc", "a");
8785 emitcode ("xch", "a,%s", x);
8789 #ifdef BETTER_LITERAL_SHIFT
8790 /*-----------------------------------------------------------------*/
8791 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8792 /*-----------------------------------------------------------------*/
8796 emitcode ("xch", "a,%s", x);
8797 emitcode ("add", "a,acc");
8798 emitcode ("xch", "a,%s", x);
8799 emitcode ("rlc", "a");
8803 #ifdef BETTER_LITERAL_SHIFT
8804 /*-----------------------------------------------------------------*/
8805 /* AccAXLsh - left shift a:x by known count (0..7) */
8806 /*-----------------------------------------------------------------*/
8808 AccAXLsh (char *x, int shCount)
8823 case 5: // AAAAABBB:CCCCCDDD
8825 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8827 emitcode ("anl", "a,#!constbyte",
8828 SLMask[shCount]); // BBB00000:CCCCCDDD
8830 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8832 AccRol (shCount); // DDDCCCCC:BBB00000
8834 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8836 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8838 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8840 emitcode ("anl", "a,#!constbyte",
8841 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8843 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8845 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8848 case 6: // AAAAAABB:CCCCCCDD
8849 emitcode ("anl", "a,#!constbyte",
8850 SRMask[shCount]); // 000000BB:CCCCCCDD
8852 AccAXRrl1 (x); // D000000B:BCCCCCCD
8853 AccAXRrl1 (x); // DD000000:BBCCCCCC
8854 emitcode ("xch", "a,%s", x); // BBCCCCCC:DD000000
8856 emitcode ("mov", "c,acc.0"); // c = B
8857 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8858 emitcode("rrc","a");
8859 emitcode("xch","a,%s", x);
8860 emitcode("rrc","a");
8861 emitcode("mov","c,acc.0"); //<< get correct bit
8862 emitcode("xch","a,%s", x);
8864 emitcode("rrc","a");
8865 emitcode("xch","a,%s", x);
8866 emitcode("rrc","a");
8867 emitcode("xch","a,%s", x);
8870 case 7: // a:x <<= 7
8872 emitcode ("anl", "a,#!constbyte",
8873 SRMask[shCount]); // 0000000B:CCCCCCCD
8875 AccAXRrl1 (x); // D0000000:BCCCCCCC
8877 emitcode ("xch", "a,%s", x); // BCCCCCCC:D0000000
8886 #ifdef BETTER_LITERAL_SHIFT
8888 /*-----------------------------------------------------------------*/
8889 /* AccAXRsh - right shift a:x known count (0..7) */
8890 /*-----------------------------------------------------------------*/
8892 AccAXRsh (char *x, int shCount)
8900 AccAXRsh1 (x); // 0->a:x
8905 AccAXRsh1 (x); // 0->a:x
8908 AccAXRsh1 (x); // 0->a:x
8913 case 5: // AAAAABBB:CCCCCDDD = a:x
8915 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8917 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8919 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8921 emitcode ("anl", "a,#!constbyte",
8922 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8924 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8926 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8928 emitcode ("anl", "a,#!constbyte",
8929 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8931 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8933 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8935 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8938 case 6: // AABBBBBB:CCDDDDDD
8940 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDE
8941 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8943 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8945 emitcode ("anl", "a,#!constbyte",
8946 SRMask[shCount]); // 000000AA:BBBBBBCC
8949 case 7: // ABBBBBBB:CDDDDDDD
8951 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8953 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8955 emitcode ("anl", "a,#!constbyte",
8956 SRMask[shCount]); // 0000000A:BBBBBBBC
8965 #ifdef BETTER_LITERAL_SHIFT
8966 /*-----------------------------------------------------------------*/
8967 /* AccAXRshS - right shift signed a:x known count (0..7) */
8968 /*-----------------------------------------------------------------*/
8970 AccAXRshS (char *x, int shCount)
8978 emitcode ("mov", "c,acc.7");
8979 AccAXRsh1 (x); // s->a:x
8983 emitcode ("mov", "c,acc.7");
8984 AccAXRsh1 (x); // s->a:x
8986 emitcode ("mov", "c,acc.7");
8987 AccAXRsh1 (x); // s->a:x
8992 case 5: // AAAAABBB:CCCCCDDD = a:x
8994 tlbl = newiTempLabel (NULL);
8995 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8997 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8999 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
9001 emitcode ("anl", "a,#!constbyte",
9002 SRMask[shCount]); // 000CCCCC:BBBAAAAA
9004 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
9006 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
9008 emitcode ("anl", "a,#!constbyte",
9009 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
9011 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
9013 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
9015 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
9017 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
9018 emitcode ("orl", "a,#!constbyte",
9019 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
9022 break; // SSSSAAAA:BBBCCCCC
9024 case 6: // AABBBBBB:CCDDDDDD
9026 tlbl = newiTempLabel (NULL);
9028 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
9029 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
9031 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
9033 emitcode ("anl", "a,#!constbyte",
9034 SRMask[shCount]); // 000000AA:BBBBBBCC
9036 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
9037 emitcode ("orl", "a,#!constbyte",
9038 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
9042 case 7: // ABBBBBBB:CDDDDDDD
9044 tlbl = newiTempLabel (NULL);
9046 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
9048 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
9050 emitcode ("anl", "a,#!constbyte",
9051 SRMask[shCount]); // 0000000A:BBBBBBBC
9053 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
9054 emitcode ("orl", "a,#!constbyte",
9055 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
9065 #ifdef BETTER_LITERAL_SHIFT
9067 _loadLeftIntoAx(char **lsb,
9073 // Get the initial value from left into a pair of registers.
9074 // MSB must be in A, LSB can be any register.
9076 // If the result is held in registers, it is an optimization
9077 // if the LSB can be held in the register which will hold the,
9078 // result LSB since this saves us from having to copy it into
9079 // the result following AccAXLsh.
9081 // If the result is addressed indirectly, this is not a gain.
9082 if (AOP_NEEDSACC(result))
9086 _startLazyDPSEvaluation();
9087 if (AOP_TYPE(left) == AOP_DPTR2)
9090 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE, NULL));
9091 // get LSB in DP2_RESULT_REG.
9092 leftByte = aopGet (left, offl, FALSE, FALSE, DP2_RESULT_REG);
9093 assert(!strcmp(leftByte, DP2_RESULT_REG));
9097 // get LSB into DP2_RESULT_REG
9098 leftByte = aopGet (left, offl, FALSE, FALSE, NULL);
9099 if (strcmp(leftByte, DP2_RESULT_REG))
9102 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
9105 leftByte = aopGet (left, offl + MSB16, FALSE, FALSE, NULL);
9106 assert(strcmp(leftByte, DP2_RESULT_REG));
9109 _endLazyDPSEvaluation();
9110 *lsb = DP2_RESULT_REG;
9114 if (sameRegs (AOP (result), AOP (left)) &&
9115 ((offl + MSB16) == offr))
9117 /* don't crash result[offr] */
9118 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
9119 emitcode ("xch", "a,%s",
9120 aopGet (left, offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
9124 movLeft2Result (left, offl, result, offr, 0);
9125 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE, NULL));
9127 *lsb = aopGet (result, offr, FALSE, FALSE, DP2_RESULT_REG);
9128 assert(strcmp(*lsb,"a"));
9133 _storeAxResults(char *lsb,
9137 _startLazyDPSEvaluation();
9138 if (AOP_NEEDSACC(result))
9140 /* We have to explicitly update the result LSB.
9142 emitcode ("xch","a,%s", lsb);
9143 aopPut (result, "a", offr);
9144 emitcode ("mov","a,%s", lsb);
9146 if (getDataSize (result) > 1)
9148 aopPut (result, "a", offr + MSB16);
9150 _endLazyDPSEvaluation();
9153 /*-----------------------------------------------------------------*/
9154 /* shiftL2Left2Result - shift left two bytes from left to result */
9155 /*-----------------------------------------------------------------*/
9157 shiftL2Left2Result (operand * left, int offl,
9158 operand * result, int offr, int shCount)
9162 _loadLeftIntoAx(&lsb, left, result, offl, offr);
9164 AccAXLsh (lsb, shCount);
9166 _storeAxResults(lsb, result, offr);
9170 #ifdef BETTER_LITERAL_SHIFT
9171 /*-----------------------------------------------------------------*/
9172 /* shiftR2Left2Result - shift right two bytes from left to result */
9173 /*-----------------------------------------------------------------*/
9175 shiftR2Left2Result (operand * left, int offl,
9176 operand * result, int offr,
9177 int shCount, int sign)
9181 _loadLeftIntoAx(&lsb, left, result, offl, offr);
9183 /* a:x >> shCount (x = lsb(result)) */
9186 AccAXRshS(lsb, shCount);
9190 AccAXRsh(lsb, shCount);
9193 _storeAxResults(lsb, result, offr);
9197 /*-----------------------------------------------------------------*/
9198 /* shiftLLeftOrResult - shift left one byte from left, or to result */
9199 /*-----------------------------------------------------------------*/
9201 shiftLLeftOrResult (operand * left, int offl,
9202 operand * result, int offr, int shCount)
9204 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
9205 /* shift left accumulator */
9207 /* or with result */
9208 emitcode ("orl", "a,%s",
9209 aopGet (result, offr, FALSE, FALSE, DP2_RESULT_REG));
9210 /* back to result */
9211 aopPut (result, "a", offr);
9216 /*-----------------------------------------------------------------*/
9217 /* shiftRLeftOrResult - shift right one byte from left,or to result */
9218 /*-----------------------------------------------------------------*/
9220 shiftRLeftOrResult (operand * left, int offl,
9221 operand * result, int offr, int shCount)
9223 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
9224 /* shift right accumulator */
9226 /* or with result */
9227 emitcode ("orl", "a,%s",
9228 aopGet (result, offr, FALSE, FALSE, DP2_RESULT_REG));
9229 /* back to result */
9230 aopPut (result, "a", offr);
9234 #ifdef BETTER_LITERAL_SHIFT
9235 /*-----------------------------------------------------------------*/
9236 /* genlshOne - left shift a one byte quantity by known count */
9237 /*-----------------------------------------------------------------*/
9239 genlshOne (operand * result, operand * left, int shCount)
9241 D (emitcode (";", "genlshOne"));
9243 shiftL1Left2Result (left, LSB, result, LSB, shCount);
9247 #ifdef BETTER_LITERAL_SHIFT
9248 /*-----------------------------------------------------------------*/
9249 /* genlshTwo - left shift two bytes by known amount != 0 */
9250 /*-----------------------------------------------------------------*/
9252 genlshTwo (operand * result, operand * left, int shCount)
9256 D (emitcode (";", "genlshTwo"));
9258 size = getDataSize (result);
9260 /* if shCount >= 8 */
9265 _startLazyDPSEvaluation();
9271 _endLazyDPSEvaluation();
9272 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
9273 aopPut (result, zero, LSB);
9277 movLeft2Result (left, LSB, result, MSB16, 0);
9278 aopPut (result, zero, LSB);
9279 _endLazyDPSEvaluation();
9284 aopPut (result, zero, LSB);
9285 _endLazyDPSEvaluation();
9289 /* 1 <= shCount <= 7 */
9293 shiftL1Left2Result (left, LSB, result, LSB, shCount);
9295 shiftL2Left2Result (left, LSB, result, LSB, shCount);
9302 /*-----------------------------------------------------------------*/
9303 /* shiftLLong - shift left one long from left to result */
9304 /* offl = LSB or MSB16 */
9305 /*-----------------------------------------------------------------*/
9307 shiftLLong (operand * left, operand * result, int offr)
9310 int size = AOP_SIZE (result);
9312 if (size >= LSB + offr)
9314 l = aopGet (left, LSB, FALSE, FALSE, NULL);
9316 emitcode ("add", "a,acc");
9317 if (sameRegs (AOP (left), AOP (result)) &&
9318 size >= MSB16 + offr && offr != LSB)
9319 emitcode ("xch", "a,%s",
9320 aopGet (left, LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
9322 aopPut (result, "a", LSB + offr);
9325 if (size >= MSB16 + offr)
9327 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
9329 l = aopGet (left, MSB16, FALSE, FALSE, TRUE);
9332 emitcode ("rlc", "a");
9333 if (sameRegs (AOP (left), AOP (result)) &&
9334 size >= MSB24 + offr && offr != LSB)
9335 emitcode ("xch", "a,%s",
9336 aopGet (left, MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
9338 aopPut (result, "a", MSB16 + offr);
9341 if (size >= MSB24 + offr)
9343 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
9345 l = aopGet (left, MSB24, FALSE, FALSE, NULL);
9348 emitcode ("rlc", "a");
9349 if (sameRegs (AOP (left), AOP (result)) &&
9350 size >= MSB32 + offr && offr != LSB)
9351 emitcode ("xch", "a,%s",
9352 aopGet (left, MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
9354 aopPut (result, "a", MSB24 + offr);
9357 if (size > MSB32 + offr)
9359 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
9361 l = aopGet (left, MSB32, FALSE, FALSE, NULL);
9364 emitcode ("rlc", "a");
9365 aopPut (result, "a", MSB32 + offr);
9368 aopPut (result, zero, LSB);
9374 /*-----------------------------------------------------------------*/
9375 /* genlshFour - shift four byte by a known amount != 0 */
9376 /*-----------------------------------------------------------------*/
9378 genlshFour (operand * result, operand * left, int shCount)
9382 D (emitcode (";", "genlshFour"));
9384 size = AOP_SIZE (result);
9386 /* if shifting more that 3 bytes */
9391 /* lowest order of left goes to the highest
9392 order of the destination */
9393 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
9395 movLeft2Result (left, LSB, result, MSB32, 0);
9396 aopPut (result, zero, LSB);
9397 aopPut (result, zero, MSB16);
9398 aopPut (result, zero, MSB24);
9402 /* more than two bytes */
9403 else if (shCount >= 16)
9405 /* lower order two bytes goes to higher order two bytes */
9407 /* if some more remaining */
9409 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
9412 movLeft2Result (left, MSB16, result, MSB32, 0);
9413 movLeft2Result (left, LSB, result, MSB24, 0);
9415 aopPut (result, zero, MSB16);
9416 aopPut (result, zero, LSB);
9420 /* if more than 1 byte */
9421 else if (shCount >= 8)
9423 /* lower order three bytes goes to higher order three bytes */
9428 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
9430 movLeft2Result (left, LSB, result, MSB16, 0);
9436 movLeft2Result (left, MSB24, result, MSB32, 0);
9437 movLeft2Result (left, MSB16, result, MSB24, 0);
9438 movLeft2Result (left, LSB, result, MSB16, 0);
9439 aopPut (result, zero, LSB);
9441 else if (shCount == 1)
9442 shiftLLong (left, result, MSB16);
9445 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
9446 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
9447 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
9448 aopPut (result, zero, LSB);
9453 /* 1 <= shCount <= 7 */
9454 else if (shCount <= 2)
9456 shiftLLong (left, result, LSB);
9458 shiftLLong (result, result, LSB);
9460 /* 3 <= shCount <= 7, optimize */
9463 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
9464 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
9465 shiftL2Left2Result (left, LSB, result, LSB, shCount);
9470 #ifdef BETTER_LITERAL_SHIFT
9471 /*-----------------------------------------------------------------*/
9472 /* genLeftShiftLiteral - left shifting by known count */
9473 /*-----------------------------------------------------------------*/
9475 genLeftShiftLiteral (operand * left,
9480 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9483 size = getSize (operandType (result));
9485 D (emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
9487 /* We only handle certain easy cases so far. */
9489 && (shCount < (size * 8))
9493 D(emitcode (";", "genLeftShiftLiteral wimping out"););
9497 freeAsmop (right, NULL, ic, TRUE);
9499 aopOp(left, ic, FALSE, FALSE);
9500 aopOp(result, ic, FALSE, AOP_USESDPTR(left));
9503 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
9505 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
9506 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
9508 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
9511 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
9513 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
9514 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
9516 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
9522 emitcode ("; shift left ", "result %d, left %d", size,
9526 /* I suppose that the left size >= result size */
9529 _startLazyDPSEvaluation();
9532 movLeft2Result (left, size, result, size, 0);
9534 _endLazyDPSEvaluation();
9536 else if (shCount >= (size * 8))
9538 _startLazyDPSEvaluation();
9541 aopPut (result, zero, size);
9543 _endLazyDPSEvaluation();
9550 genlshOne (result, left, shCount);
9554 genlshTwo (result, left, shCount);
9558 genlshFour (result, left, shCount);
9562 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9563 "*** ack! mystery literal shift!\n");
9567 freeAsmop (result, NULL, ic, TRUE);
9568 freeAsmop (left, NULL, ic, TRUE);
9573 /*-----------------------------------------------------------------*/
9574 /* genLeftShift - generates code for left shifting */
9575 /*-----------------------------------------------------------------*/
9577 genLeftShift (iCode * ic)
9579 operand *left, *right, *result;
9582 symbol *tlbl, *tlbl1;
9585 D (emitcode (";", "genLeftShift"));
9587 right = IC_RIGHT (ic);
9588 left = IC_LEFT (ic);
9589 result = IC_RESULT (ic);
9591 aopOp (right, ic, FALSE, FALSE);
9594 #ifdef BETTER_LITERAL_SHIFT
9595 /* if the shift count is known then do it
9596 as efficiently as possible */
9597 if (AOP_TYPE (right) == AOP_LIT)
9599 if (genLeftShiftLiteral (left, right, result, ic))
9606 /* shift count is unknown then we have to form
9607 a loop get the loop count in B : Note: we take
9608 only the lower order byte since shifting
9609 more that 32 bits make no sense anyway, ( the
9610 largest size of an object can be only 32 bits ) */
9613 if (AOP_TYPE (right) == AOP_LIT)
9615 /* Really should be handled by genLeftShiftLiteral,
9616 * but since I'm too lazy to fix that today, at least we can make
9617 * some small improvement.
9619 emitcode("mov", "b,#!constbyte",
9620 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9624 MOVB (aopGet (right, 0, FALSE, FALSE, "b"));
9625 emitcode ("inc", "b");
9627 freeAsmop (right, NULL, ic, TRUE);
9628 aopOp (left, ic, FALSE, FALSE);
9629 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9631 /* now move the left to the result if they are not the same */
9632 if (!sameRegs (AOP (left), AOP (result)) &&
9633 AOP_SIZE (result) > 1)
9636 size = AOP_SIZE (result);
9638 _startLazyDPSEvaluation ();
9641 l = aopGet (left, offset, FALSE, TRUE, NULL);
9642 if (*l == '@' && (IS_AOP_PREG (result)))
9645 emitcode ("mov", "a,%s", l);
9646 aopPut (result, "a", offset);
9649 aopPut (result, l, offset);
9652 _endLazyDPSEvaluation ();
9655 tlbl = newiTempLabel (NULL);
9656 size = AOP_SIZE (result);
9658 tlbl1 = newiTempLabel (NULL);
9660 /* if it is only one byte then */
9663 symbol *tlbl1 = newiTempLabel (NULL);
9665 l = aopGet (left, 0, FALSE, FALSE, NULL);
9667 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9669 emitcode ("add", "a,acc");
9671 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9673 aopPut (result, "a", 0);
9677 reAdjustPreg (AOP (result));
9679 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9681 l = aopGet (result, offset, FALSE, FALSE, NULL);
9683 emitcode ("add", "a,acc");
9684 aopPut (result, "a", offset++);
9685 _startLazyDPSEvaluation ();
9688 l = aopGet (result, offset, FALSE, FALSE, NULL);
9690 emitcode ("rlc", "a");
9691 aopPut (result, "a", offset++);
9693 _endLazyDPSEvaluation ();
9694 reAdjustPreg (AOP (result));
9697 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9700 freeAsmop (result, NULL, ic, TRUE);
9701 freeAsmop (left, NULL, ic, TRUE);
9704 #ifdef BETTER_LITERAL_SHIFT
9705 /*-----------------------------------------------------------------*/
9706 /* genrshOne - right shift a one byte quantity by known count */
9707 /*-----------------------------------------------------------------*/
9709 genrshOne (operand * result, operand * left,
9710 int shCount, int sign)
9712 D (emitcode (";", "genrshOne"));
9714 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9718 #ifdef BETTER_LITERAL_SHIFT
9719 /*-----------------------------------------------------------------*/
9720 /* genrshTwo - right shift two bytes by known amount != 0 */
9721 /*-----------------------------------------------------------------*/
9723 genrshTwo (operand * result, operand * left,
9724 int shCount, int sign)
9726 D (emitcode (";", "genrshTwo"));
9728 /* if shCount >= 8 */
9732 _startLazyDPSEvaluation();
9734 shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
9736 movLeft2Result (left, MSB16, result, LSB, sign);
9737 addSign (result, MSB16, sign);
9738 _endLazyDPSEvaluation();
9741 /* 1 <= shCount <= 7 */
9743 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9747 /*-----------------------------------------------------------------*/
9748 /* shiftRLong - shift right one long from left to result */
9749 /* offl = LSB or MSB16 */
9750 /*-----------------------------------------------------------------*/
9752 shiftRLong (operand * left, int offl,
9753 operand * result, int sign)
9755 bool overlapping = regsInCommon (left, result) || operandsEqu(left, result);
9757 if (overlapping && offl>1)
9759 // we are in big trouble, but this shouldn't happen
9760 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9763 MOVA (aopGet (left, MSB32, FALSE, FALSE, NULL));
9770 emitcode ("rlc", "a");
9771 emitcode ("subb", "a,acc");
9772 emitcode ("xch", "a,%s",
9773 aopGet(left, MSB32, FALSE, FALSE, DP2_RESULT_REG));
9777 aopPut (result, zero, MSB32);
9783 emitcode ("clr", "c");
9787 emitcode ("mov", "c,acc.7");
9790 emitcode ("rrc", "a");
9792 if (overlapping && offl==MSB16)
9794 emitcode ("xch", "a,%s", aopGet (left, MSB24, FALSE, FALSE, DP2_RESULT_REG));
9798 aopPut (result, "a", MSB32 - offl);
9799 MOVA (aopGet (left, MSB24, FALSE, FALSE, NULL));
9802 emitcode ("rrc", "a");
9804 if (overlapping && offl==MSB16)
9806 emitcode ("xch", "a,%s", aopGet (left, MSB16, FALSE, FALSE, DP2_RESULT_REG));
9810 aopPut (result, "a", MSB24 - offl);
9811 MOVA (aopGet (left, MSB16, FALSE, FALSE, NULL));
9814 emitcode ("rrc", "a");
9817 aopPut (result, "a", MSB16 - offl);
9821 if (overlapping && offl==MSB16)
9823 emitcode ("xch", "a,%s", aopGet (left, LSB, FALSE, FALSE, DP2_RESULT_REG));
9827 aopPut (result, "a", MSB16 - offl);
9828 MOVA (aopGet (left, LSB, FALSE, FALSE, NULL));
9830 emitcode ("rrc", "a");
9831 aopPut (result, "a", LSB);
9835 /*-----------------------------------------------------------------*/
9836 /* genrshFour - shift four byte by a known amount != 0 */
9837 /*-----------------------------------------------------------------*/
9839 genrshFour (operand * result, operand * left,
9840 int shCount, int sign)
9842 D (emitcode (";", "genrshFour"));
9844 /* if shifting more that 3 bytes */
9848 _startLazyDPSEvaluation();
9850 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9852 movLeft2Result (left, MSB32, result, LSB, sign);
9853 addSign (result, MSB16, sign);
9854 _endLazyDPSEvaluation();
9856 else if (shCount >= 16)
9859 _startLazyDPSEvaluation();
9861 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9864 movLeft2Result (left, MSB24, result, LSB, 0);
9865 movLeft2Result (left, MSB32, result, MSB16, sign);
9867 addSign (result, MSB24, sign);
9868 _endLazyDPSEvaluation();
9870 else if (shCount >= 8)
9873 _startLazyDPSEvaluation();
9876 shiftRLong (left, MSB16, result, sign);
9878 else if (shCount == 0)
9880 movLeft2Result (left, MSB16, result, LSB, 0);
9881 movLeft2Result (left, MSB24, result, MSB16, 0);
9882 movLeft2Result (left, MSB32, result, MSB24, sign);
9883 addSign (result, MSB32, sign);
9887 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9888 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9889 /* the last shift is signed */
9890 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9891 addSign (result, MSB32, sign);
9893 _endLazyDPSEvaluation();
9897 /* 1 <= shCount <= 7 */
9900 shiftRLong (left, LSB, result, sign);
9902 shiftRLong (result, LSB, result, sign);
9906 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9907 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9908 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9913 #ifdef BETTER_LITERAL_SHIFT
9914 /*-----------------------------------------------------------------*/
9915 /* genRightShiftLiteral - right shifting by known count */
9916 /*-----------------------------------------------------------------*/
9918 genRightShiftLiteral (operand * left,
9924 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9927 size = getSize (operandType (result));
9929 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
9931 /* We only handle certain easy cases so far. */
9933 && (shCount < (size * 8))
9938 D(emitcode (";", "genRightShiftLiteral wimping out"););
9942 freeAsmop (right, NULL, ic, TRUE);
9944 aopOp (left, ic, FALSE, FALSE);
9945 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9948 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9952 /* test the LEFT size !!! */
9954 /* I suppose that the left size >= result size */
9957 size = getDataSize (result);
9958 _startLazyDPSEvaluation();
9960 movLeft2Result (left, size, result, size, 0);
9961 _endLazyDPSEvaluation();
9963 else if (shCount >= (size * 8))
9967 /* get sign in acc.7 */
9968 MOVA (aopGet (left, size - 1, FALSE, FALSE, NULL));
9970 addSign (result, LSB, sign);
9977 genrshOne (result, left, shCount, sign);
9981 genrshTwo (result, left, shCount, sign);
9985 genrshFour (result, left, shCount, sign);
9992 freeAsmop (result, NULL, ic, TRUE);
9993 freeAsmop (left, NULL, ic, TRUE);
9999 /*-----------------------------------------------------------------*/
10000 /* genSignedRightShift - right shift of signed number */
10001 /*-----------------------------------------------------------------*/
10003 genSignedRightShift (iCode * ic)
10005 operand *right, *left, *result;
10008 symbol *tlbl, *tlbl1;
10011 D (emitcode (";", "genSignedRightShift"));
10013 /* we do it the hard way put the shift count in b
10014 and loop thru preserving the sign */
10016 right = IC_RIGHT (ic);
10017 left = IC_LEFT (ic);
10018 result = IC_RESULT (ic);
10020 aopOp (right, ic, FALSE, FALSE);
10022 #ifdef BETTER_LITERAL_SHIFT
10023 if (AOP_TYPE (right) == AOP_LIT)
10025 if (genRightShiftLiteral (left, right, result, ic, 1))
10031 /* shift count is unknown then we have to form
10032 a loop get the loop count in B : Note: we take
10033 only the lower order byte since shifting
10034 more that 32 bits make no sense anyway, ( the
10035 largest size of an object can be only 32 bits ) */
10037 pushedB = pushB ();
10038 if (AOP_TYPE (right) == AOP_LIT)
10040 /* Really should be handled by genRightShiftLiteral,
10041 * but since I'm too lazy to fix that today, at least we can make
10042 * some small improvement.
10044 emitcode("mov", "b,#!constbyte",
10045 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
10049 MOVB (aopGet (right, 0, FALSE, FALSE, "b"));
10050 emitcode ("inc", "b");
10052 freeAsmop (right, NULL, ic, TRUE);
10053 aopOp (left, ic, FALSE, FALSE);
10054 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
10056 /* now move the left to the result if they are not the
10058 if (!sameRegs (AOP (left), AOP (result)) &&
10059 AOP_SIZE (result) > 1)
10062 size = AOP_SIZE (result);
10064 _startLazyDPSEvaluation ();
10067 l = aopGet (left, offset, FALSE, TRUE, NULL);
10068 if (*l == '@' && IS_AOP_PREG (result))
10071 emitcode ("mov", "a,%s", l);
10072 aopPut (result, "a", offset);
10075 aopPut (result, l, offset);
10078 _endLazyDPSEvaluation ();
10081 /* mov the highest order bit to OVR */
10082 tlbl = newiTempLabel (NULL);
10083 tlbl1 = newiTempLabel (NULL);
10085 size = AOP_SIZE (result);
10087 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
10088 emitcode ("rlc", "a");
10089 emitcode ("mov", "ov,c");
10090 /* if it is only one byte then */
10093 l = aopGet (left, 0, FALSE, FALSE, NULL);
10095 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
10097 emitcode ("mov", "c,ov");
10098 emitcode ("rrc", "a");
10100 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
10102 aopPut (result, "a", 0);
10106 reAdjustPreg (AOP (result));
10107 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
10109 emitcode ("mov", "c,ov");
10110 _startLazyDPSEvaluation ();
10113 l = aopGet (result, offset, FALSE, FALSE, NULL);
10115 emitcode ("rrc", "a");
10116 aopPut (result, "a", offset--);
10118 _endLazyDPSEvaluation ();
10119 reAdjustPreg (AOP (result));
10121 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
10125 freeAsmop (result, NULL, ic, TRUE);
10126 freeAsmop (left, NULL, ic, TRUE);
10129 /*-----------------------------------------------------------------*/
10130 /* genRightShift - generate code for right shifting */
10131 /*-----------------------------------------------------------------*/
10133 genRightShift (iCode * ic)
10135 operand *right, *left, *result;
10139 symbol *tlbl, *tlbl1;
10142 D (emitcode (";", "genRightShift"));
10144 /* if signed then we do it the hard way preserve the
10145 sign bit moving it inwards */
10146 letype = getSpec (operandType (IC_LEFT (ic)));
10148 if (!SPEC_USIGN (letype))
10150 genSignedRightShift (ic);
10154 /* signed & unsigned types are treated the same : i.e. the
10155 signed is NOT propagated inwards : quoting from the
10156 ANSI - standard : "for E1 >> E2, is equivalent to division
10157 by 2**E2 if unsigned or if it has a non-negative value,
10158 otherwise the result is implementation defined ", MY definition
10159 is that the sign does not get propagated */
10161 right = IC_RIGHT (ic);
10162 left = IC_LEFT (ic);
10163 result = IC_RESULT (ic);
10165 aopOp (right, ic, FALSE, FALSE);
10167 #ifdef BETTER_LITERAL_SHIFT
10168 /* if the shift count is known then do it
10169 as efficiently as possible */
10170 if (AOP_TYPE (right) == AOP_LIT)
10172 if (genRightShiftLiteral (left, right, result, ic, 0))
10179 /* shift count is unknown then we have to form
10180 a loop get the loop count in B : Note: we take
10181 only the lower order byte since shifting
10182 more that 32 bits make no sense anyway, ( the
10183 largest size of an object can be only 32 bits ) */
10185 pushedB = pushB ();
10186 if (AOP_TYPE (right) == AOP_LIT)
10188 /* Really should be handled by genRightShiftLiteral,
10189 * but since I'm too lazy to fix that today, at least we can make
10190 * some small improvement.
10192 emitcode("mov", "b,#!constbyte",
10193 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
10197 MOVB (aopGet (right, 0, FALSE, FALSE, "b"));
10198 emitcode ("inc", "b");
10200 freeAsmop (right, NULL, ic, TRUE);
10201 aopOp (left, ic, FALSE, FALSE);
10202 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
10204 /* now move the left to the result if they are not the
10206 if (!sameRegs (AOP (left), AOP (result)) &&
10207 AOP_SIZE (result) > 1)
10209 size = AOP_SIZE (result);
10211 _startLazyDPSEvaluation ();
10214 l = aopGet (left, offset, FALSE, TRUE, NULL);
10215 if (*l == '@' && IS_AOP_PREG (result))
10218 emitcode ("mov", "a,%s", l);
10219 aopPut (result, "a", offset);
10222 aopPut (result, l, offset);
10225 _endLazyDPSEvaluation ();
10228 tlbl = newiTempLabel (NULL);
10229 tlbl1 = newiTempLabel (NULL);
10230 size = AOP_SIZE (result);
10233 /* if it is only one byte then */
10236 l = aopGet (left, 0, FALSE, FALSE, NULL);
10238 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
10241 emitcode ("rrc", "a");
10243 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
10245 aopPut (result, "a", 0);
10249 reAdjustPreg (AOP (result));
10250 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
10253 _startLazyDPSEvaluation ();
10256 l = aopGet (result, offset, FALSE, FALSE, NULL);
10258 emitcode ("rrc", "a");
10259 aopPut (result, "a", offset--);
10261 _endLazyDPSEvaluation ();
10262 reAdjustPreg (AOP (result));
10265 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
10269 freeAsmop (result, NULL, ic, TRUE);
10270 freeAsmop (left, NULL, ic, TRUE);
10273 /*-----------------------------------------------------------------*/
10274 /* emitPtrByteGet - emits code to get a byte into A through a */
10275 /* pointer register (R0, R1, or DPTR). The */
10276 /* original value of A can be preserved in B. */
10277 /*-----------------------------------------------------------------*/
10279 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
10286 emitcode ("mov", "b,a");
10287 emitcode ("mov", "a,@%s", rname);
10292 emitcode ("mov", "b,a");
10293 emitcode ("movx", "a,@%s", rname);
10298 emitcode ("mov", "b,a");
10299 emitcode ("movx", "a,@dptr");
10304 emitcode ("mov", "b,a");
10305 emitcode ("clr", "a");
10306 emitcode ("movc", "a,@a+dptr");
10312 emitcode ("push", "b");
10313 emitcode ("push", "acc");
10315 emitcode ("lcall", "__gptrget");
10317 emitcode ("pop", "b");
10322 /*-----------------------------------------------------------------*/
10323 /* emitPtrByteSet - emits code to set a byte from src through a */
10324 /* pointer register (R0, R1, or DPTR). */
10325 /*-----------------------------------------------------------------*/
10327 emitPtrByteSet (char *rname, int p_type, char *src)
10336 emitcode ("mov", "@%s,a", rname);
10339 emitcode ("mov", "@%s,%s", rname, src);
10344 emitcode ("movx", "@%s,a", rname);
10349 emitcode ("movx", "@dptr,a");
10354 emitcode ("lcall", "__gptrput");
10359 /*-----------------------------------------------------------------*/
10360 /* genUnpackBits - generates code for unpacking bits */
10361 /*-----------------------------------------------------------------*/
10363 genUnpackBits (operand * result, char *rname, int ptype)
10365 int offset = 0; /* result byte offset */
10366 int rsize; /* result size */
10367 int rlen = 0; /* remaining bitfield length */
10368 sym_link *etype; /* bitfield type information */
10369 int blen; /* bitfield length */
10370 int bstr; /* bitfield starting bit within byte */
10372 D(emitcode ("; genUnpackBits",""));
10374 etype = getSpec (operandType (result));
10375 rsize = getSize (operandType (result));
10376 blen = SPEC_BLEN (etype);
10377 bstr = SPEC_BSTR (etype);
10379 /* If the bitfield length is less than a byte */
10382 emitPtrByteGet (rname, ptype, FALSE);
10384 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
10385 if (!SPEC_USIGN (etype))
10387 /* signed bitfield */
10388 symbol *tlbl = newiTempLabel (NULL);
10390 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
10391 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
10394 aopPut (result, "a", offset++);
10398 /* Bit field did not fit in a byte. Copy all
10399 but the partial byte at the end. */
10400 for (rlen=blen;rlen>=8;rlen-=8)
10402 emitPtrByteGet (rname, ptype, FALSE);
10403 aopPut (result, "a", offset++);
10405 emitcode ("inc", "%s", rname);
10408 /* Handle the partial byte at the end */
10411 emitPtrByteGet (rname, ptype, FALSE);
10412 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
10413 if (!SPEC_USIGN (etype))
10415 /* signed bitfield */
10416 symbol *tlbl = newiTempLabel (NULL);
10418 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
10419 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
10422 aopPut (result, "a", offset++);
10426 if (offset < rsize)
10430 if (SPEC_USIGN (etype))
10434 /* signed bitfield: sign extension with 0x00 or 0xff */
10435 emitcode ("rlc", "a");
10436 emitcode ("subb", "a,acc");
10442 aopPut (result, source, offset++);
10447 /*-----------------------------------------------------------------*/
10448 /* genDataPointerGet - generates code when ptr offset is known */
10449 /*-----------------------------------------------------------------*/
10451 genDataPointerGet (operand * left,
10457 int size, offset = 0;
10458 aopOp (result, ic, TRUE, FALSE);
10460 /* get the string representation of the name */
10461 l = aopGet (left, 0, FALSE, TRUE, NULL);
10462 size = AOP_SIZE (result);
10463 _startLazyDPSEvaluation ();
10468 SNPRINTF (buffer, sizeof(buffer),
10469 "(%s + %d)", l + 1, offset);
10473 SNPRINTF (buffer, sizeof(buffer),
10476 aopPut (result, buffer, offset++);
10478 _endLazyDPSEvaluation ();
10480 freeAsmop (result, NULL, ic, TRUE);
10481 freeAsmop (left, NULL, ic, TRUE);
10484 /*-----------------------------------------------------------------*/
10485 /* genNearPointerGet - emitcode for near pointer fetch */
10486 /*-----------------------------------------------------------------*/
10488 genNearPointerGet (operand * left,
10496 sym_link *rtype, *retype, *letype;
10497 sym_link *ltype = operandType (left);
10500 rtype = operandType (result);
10501 retype = getSpec (rtype);
10502 letype = getSpec (ltype);
10504 aopOp (left, ic, FALSE, FALSE);
10506 /* if left is rematerialisable and
10507 result is not bitfield variable type and
10508 the left is pointer to data space i.e
10509 lower 128 bytes of space */
10510 if (AOP_TYPE (left) == AOP_IMMD &&
10511 !IS_BITFIELD (retype) &&
10512 !IS_BITFIELD (letype) &&
10513 DCL_TYPE (ltype) == POINTER)
10515 genDataPointerGet (left, result, ic);
10519 /* if the value is already in a pointer register
10520 then don't need anything more */
10521 if (!AOP_INPREG (AOP (left)))
10523 /* otherwise get a free pointer register */
10524 aop = newAsmop (0);
10525 preg = getFreePtr (ic, &aop, FALSE);
10526 emitcode ("mov", "%s,%s",
10528 aopGet (left, 0, FALSE, TRUE, DP2_RESULT_REG));
10529 rname = preg->name;
10532 rname = aopGet (left, 0, FALSE, FALSE, DP2_RESULT_REG);
10534 freeAsmop (left, NULL, ic, TRUE);
10535 aopOp (result, ic, FALSE, FALSE);
10537 /* if bitfield then unpack the bits */
10538 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10539 genUnpackBits (result, rname, POINTER);
10542 /* we have can just get the values */
10543 int size = AOP_SIZE (result);
10548 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
10551 emitcode ("mov", "a,@%s", rname);
10552 aopPut (result, "a", offset);
10556 SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
10557 aopPut (result, buffer, offset);
10561 emitcode ("inc", "%s", rname);
10565 /* now some housekeeping stuff */
10566 if (aop) /* we had to allocate for this iCode */
10568 if (pi) { /* post increment present */
10569 aopPut (left, rname, 0);
10571 freeAsmop (NULL, aop, ic, TRUE);
10575 /* we did not allocate which means left
10576 already in a pointer register, then
10577 if size > 0 && this could be used again
10578 we have to point it back to where it
10580 if (AOP_SIZE (result) > 1 &&
10581 !OP_SYMBOL (left)->remat &&
10582 (OP_SYMBOL (left)->liveTo > ic->seq ||
10586 int size = AOP_SIZE (result) - 1;
10588 emitcode ("dec", "%s", rname);
10593 freeAsmop (result, NULL, ic, TRUE);
10594 if (pi) pi->generated = 1;
10597 /*-----------------------------------------------------------------*/
10598 /* genPagedPointerGet - emitcode for paged pointer fetch */
10599 /*-----------------------------------------------------------------*/
10601 genPagedPointerGet (operand * left,
10609 sym_link *rtype, *retype, *letype;
10611 rtype = operandType (result);
10612 retype = getSpec (rtype);
10613 letype = getSpec (operandType (left));
10614 aopOp (left, ic, FALSE, FALSE);
10616 /* if the value is already in a pointer register
10617 then don't need anything more */
10618 if (!AOP_INPREG (AOP (left)))
10620 /* otherwise get a free pointer register */
10621 aop = newAsmop (0);
10622 preg = getFreePtr (ic, &aop, FALSE);
10623 emitcode ("mov", "%s,%s",
10625 aopGet (left, 0, FALSE, TRUE, NULL));
10626 rname = preg->name;
10629 rname = aopGet (left, 0, FALSE, FALSE, NULL);
10631 freeAsmop (left, NULL, ic, TRUE);
10632 aopOp (result, ic, FALSE, FALSE);
10634 /* if bitfield then unpack the bits */
10635 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10636 genUnpackBits (result, rname, PPOINTER);
10639 /* we have can just get the values */
10640 int size = AOP_SIZE (result);
10646 emitcode ("movx", "a,@%s", rname);
10647 aopPut (result, "a", offset);
10652 emitcode ("inc", "%s", rname);
10656 /* now some housekeeping stuff */
10657 if (aop) /* we had to allocate for this iCode */
10660 aopPut (left, rname, 0);
10661 freeAsmop (NULL, aop, ic, TRUE);
10665 /* we did not allocate which means left
10666 already in a pointer register, then
10667 if size > 0 && this could be used again
10668 we have to point it back to where it
10670 if (AOP_SIZE (result) > 1 &&
10671 !OP_SYMBOL (left)->remat &&
10672 (OP_SYMBOL (left)->liveTo > ic->seq ||
10676 int size = AOP_SIZE (result) - 1;
10678 emitcode ("dec", "%s", rname);
10683 freeAsmop (result, NULL, ic, TRUE);
10684 if (pi) pi->generated = 1;
10687 /*-----------------------------------------------------------------*/
10688 /* genFarPointerGet - get value from far space */
10689 /*-----------------------------------------------------------------*/
10691 genFarPointerGet (operand * left,
10692 operand * result, iCode * ic, iCode *pi)
10694 int size, offset, dopi=1;
10695 sym_link *retype = getSpec (operandType (result));
10696 sym_link *letype = getSpec (operandType (left));
10697 D (emitcode (";", "genFarPointerGet"););
10699 aopOp (left, ic, FALSE, FALSE);
10701 /* if the operand is already in dptr
10702 then we do nothing else we move the value to dptr */
10703 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
10705 /* if this is rematerializable */
10706 if (AOP_TYPE (left) == AOP_IMMD)
10708 emitcode ("mov", "dptr,%s", aopGet (left, 0, TRUE, FALSE, NULL));
10712 /* we need to get it byte by byte */
10713 _startLazyDPSEvaluation ();
10714 if (AOP_TYPE (left) != AOP_DPTR)
10716 emitcode ("mov", "dpl,%s", aopGet (left, 0, FALSE, FALSE, NULL));
10717 emitcode ("mov", "dph,%s", aopGet (left, 1, FALSE, FALSE, NULL));
10718 if (options.model == MODEL_FLAT24)
10719 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10723 /* We need to generate a load to DPTR indirect through DPTR. */
10724 D (emitcode (";", "genFarPointerGet -- indirection special case."););
10725 emitcode ("push", "%s", aopGet (left, 0, FALSE, TRUE, NULL));
10726 emitcode ("push", "%s", aopGet (left, 1, FALSE, TRUE, NULL));
10727 if (options.model == MODEL_FLAT24)
10728 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10729 emitcode ("pop", "dph");
10730 emitcode ("pop", "dpl");
10733 _endLazyDPSEvaluation ();
10736 /* so dptr now contains the address */
10737 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10739 /* if bit then unpack */
10740 if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
10741 if (AOP_INDPTRn(left)) {
10742 genSetDPTR(AOP(left)->aopu.dptr);
10744 genUnpackBits (result, "dptr", FPOINTER);
10745 if (AOP_INDPTRn(left)) {
10750 size = AOP_SIZE (result);
10753 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10755 genSetDPTR(AOP(left)->aopu.dptr);
10756 emitcode ("movx", "a,@dptr");
10757 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10758 emitcode ("inc", "dptr");
10760 aopPut (result, "a", offset++);
10763 _startLazyDPSEvaluation ();
10765 if (AOP_INDPTRn(left)) {
10766 genSetDPTR(AOP(left)->aopu.dptr);
10772 emitcode ("movx", "a,@dptr");
10773 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10774 emitcode ("inc", "dptr");
10776 aopPut (result, "a", offset++);
10778 _endLazyDPSEvaluation ();
10781 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10782 if (!AOP_INDPTRn(left)) {
10783 _startLazyDPSEvaluation ();
10784 aopPut (left, "dpl", 0);
10785 aopPut (left, "dph", 1);
10786 if (options.model == MODEL_FLAT24)
10787 aopPut (left, "dpx", 2);
10788 _endLazyDPSEvaluation ();
10791 } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) &&
10792 AOP_SIZE(result) > 1 &&
10794 (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
10796 size = AOP_SIZE (result) - 1;
10797 if (AOP_INDPTRn(left)) {
10798 genSetDPTR(AOP(left)->aopu.dptr);
10800 while (size--) emitcode ("lcall","__decdptr");
10801 if (AOP_INDPTRn(left)) {
10806 freeAsmop (result, NULL, ic, TRUE);
10807 freeAsmop (left, NULL, ic, TRUE);
10810 /*-----------------------------------------------------------------*/
10811 /* genCodePointerGet - get value from code space */
10812 /*-----------------------------------------------------------------*/
10814 genCodePointerGet (operand * left,
10815 operand * result, iCode * ic, iCode *pi)
10817 int size, offset, dopi=1;
10818 sym_link *retype = getSpec (operandType (result));
10820 aopOp (left, ic, FALSE, FALSE);
10822 /* if the operand is already in dptr
10823 then we do nothing else we move the value to dptr */
10824 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
10826 /* if this is rematerializable */
10827 if (AOP_TYPE (left) == AOP_IMMD)
10829 emitcode ("mov", "dptr,%s", aopGet (left, 0, TRUE, FALSE, NULL));
10832 { /* we need to get it byte by byte */
10833 _startLazyDPSEvaluation ();
10834 if (AOP_TYPE (left) != AOP_DPTR)
10836 emitcode ("mov", "dpl,%s", aopGet (left, 0, FALSE, FALSE, NULL));
10837 emitcode ("mov", "dph,%s", aopGet (left, 1, FALSE, FALSE, NULL));
10838 if (options.model == MODEL_FLAT24)
10839 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10843 /* We need to generate a load to DPTR indirect through DPTR. */
10844 D (emitcode (";", "gencodePointerGet -- indirection special case."););
10845 emitcode ("push", "%s", aopGet (left, 0, FALSE, TRUE, NULL));
10846 emitcode ("push", "%s", aopGet (left, 1, FALSE, TRUE, NULL));
10847 if (options.model == MODEL_FLAT24)
10848 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10849 emitcode ("pop", "dph");
10850 emitcode ("pop", "dpl");
10853 _endLazyDPSEvaluation ();
10856 /* so dptr now contains the address */
10857 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10859 /* if bit then unpack */
10860 if (IS_BITFIELD (retype)) {
10861 if (AOP_INDPTRn(left)) {
10862 genSetDPTR(AOP(left)->aopu.dptr);
10864 genUnpackBits (result, "dptr", CPOINTER);
10865 if (AOP_INDPTRn(left)) {
10870 size = AOP_SIZE (result);
10872 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10874 genSetDPTR(AOP(left)->aopu.dptr);
10875 emitcode ("clr", "a");
10876 emitcode ("movc", "a,@a+dptr");
10877 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10878 emitcode ("inc", "dptr");
10880 aopPut (result, "a", offset++);
10883 _startLazyDPSEvaluation ();
10886 if (AOP_INDPTRn(left)) {
10887 genSetDPTR(AOP(left)->aopu.dptr);
10893 emitcode ("clr", "a");
10894 emitcode ("movc", "a,@a+dptr");
10895 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10896 emitcode ("inc", "dptr");
10897 aopPut (result, "a", offset++);
10899 _endLazyDPSEvaluation ();
10902 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10903 if (!AOP_INDPTRn(left)) {
10904 _startLazyDPSEvaluation ();
10906 aopPut (left, "dpl", 0);
10907 aopPut (left, "dph", 1);
10908 if (options.model == MODEL_FLAT24)
10909 aopPut (left, "dpx", 2);
10911 _endLazyDPSEvaluation ();
10914 } else if (IS_SYMOP(left) &&
10915 (OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
10916 AOP_SIZE(result) > 1 &&
10917 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10919 size = AOP_SIZE (result) - 1;
10920 if (AOP_INDPTRn(left)) {
10921 genSetDPTR(AOP(left)->aopu.dptr);
10923 while (size--) emitcode ("lcall","__decdptr");
10924 if (AOP_INDPTRn(left)) {
10929 freeAsmop (result, NULL, ic, TRUE);
10930 freeAsmop (left, NULL, ic, TRUE);
10933 /*-----------------------------------------------------------------*/
10934 /* genGenPointerGet - get value from generic pointer space */
10935 /*-----------------------------------------------------------------*/
10937 genGenPointerGet (operand * left,
10938 operand * result, iCode * ic, iCode * pi)
10942 sym_link *retype = getSpec (operandType (result));
10943 sym_link *letype = getSpec (operandType (left));
10945 D (emitcode (";", "genGenPointerGet"));
10947 aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
10949 pushedB = pushB ();
10950 /* if the operand is already in dptr
10951 then we do nothing else we move the value to dptr */
10952 if (AOP_TYPE (left) != AOP_STR)
10954 /* if this is rematerializable */
10955 if (AOP_TYPE (left) == AOP_IMMD)
10957 emitcode ("mov", "dptr,%s", aopGet (left, 0, TRUE, FALSE, NULL));
10958 if (AOP(left)->aopu.aop_immd.from_cast_remat)
10960 MOVB (aopGet (left, AOP_SIZE(left)-1, FALSE, FALSE, NULL));
10964 emitcode ("mov", "b,#%d", pointerCode (retype));
10968 { /* we need to get it byte by byte */
10969 _startLazyDPSEvaluation ();
10970 emitcode ("mov", "dpl,%s", aopGet (left,0,FALSE,FALSE,NULL));
10971 emitcode ("mov", "dph,%s", aopGet (left,1,FALSE,FALSE,NULL));
10972 if (options.model == MODEL_FLAT24) {
10973 emitcode ("mov", "dpx,%s", aopGet (left,2,FALSE,FALSE,NULL));
10974 emitcode ("mov", "b,%s", aopGet (left,3,FALSE,FALSE,NULL));
10976 emitcode ("mov", "b,%s", aopGet (left,2,FALSE,FALSE,NULL));
10978 _endLazyDPSEvaluation ();
10982 /* so dptr-b now contains the address */
10983 aopOp (result, ic, FALSE, TRUE);
10985 /* if bit then unpack */
10986 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10988 genUnpackBits (result, "dptr", GPOINTER);
10992 size = AOP_SIZE (result);
10999 // Get two bytes at a time, results in _AP & A.
11000 // dptr will be incremented ONCE by __gptrgetWord.
11002 // Note: any change here must be coordinated
11003 // with the implementation of __gptrgetWord
11004 // in device/lib/_gptrget.c
11005 emitcode ("lcall", "__gptrgetWord");
11006 aopPut (result, DP2_RESULT_REG, offset++);
11007 aopPut (result, "a", offset++);
11012 // Only one byte to get.
11013 emitcode ("lcall", "__gptrget");
11014 aopPut (result, "a", offset++);
11017 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
11019 emitcode ("inc", "dptr");
11024 if (pi && AOP_TYPE (left) != AOP_IMMD) {
11025 _startLazyDPSEvaluation ();
11027 aopPut (left, "dpl", 0);
11028 aopPut (left, "dph", 1);
11029 if (options.model == MODEL_FLAT24) {
11030 aopPut (left, "dpx", 2);
11031 aopPut (left, "b", 3);
11032 } else aopPut (left, "b", 2);
11034 _endLazyDPSEvaluation ();
11037 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
11038 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
11040 size = AOP_SIZE (result) - 1;
11041 while (size--) emitcode ("lcall","__decdptr");
11045 freeAsmop (result, NULL, ic, TRUE);
11046 freeAsmop (left, NULL, ic, TRUE);
11049 /*-----------------------------------------------------------------*/
11050 /* genPointerGet - generate code for pointer get */
11051 /*-----------------------------------------------------------------*/
11053 genPointerGet (iCode * ic, iCode *pi)
11055 operand *left, *result;
11056 sym_link *type, *etype;
11059 D (emitcode (";", "genPointerGet"));
11061 left = IC_LEFT (ic);
11062 result = IC_RESULT (ic);
11064 /* depending on the type of pointer we need to
11065 move it to the correct pointer register */
11066 type = operandType (left);
11067 etype = getSpec (type);
11068 /* if left is of type of pointer then it is simple */
11069 if (IS_PTR (type) && !IS_FUNC (type->next))
11070 p_type = DCL_TYPE (type);
11073 /* we have to go by the storage class */
11074 p_type = PTR_TYPE (SPEC_OCLS (etype));
11077 /* special case when cast remat */
11078 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
11079 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
11081 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
11082 type = operandType (left);
11083 p_type = DCL_TYPE (type);
11085 /* now that we have the pointer type we assign
11086 the pointer values */
11092 genNearPointerGet (left, result, ic, pi);
11096 genPagedPointerGet (left, result, ic, pi);
11100 genFarPointerGet (left, result, ic, pi);
11104 genCodePointerGet (left, result, ic, pi);
11108 genGenPointerGet (left, result, ic, pi);
11114 /*-----------------------------------------------------------------*/
11115 /* genPackBits - generates code for packed bit storage */
11116 /*-----------------------------------------------------------------*/
11118 genPackBits (sym_link * etype,
11120 char *rname, int p_type)
11122 int offset = 0; /* source byte offset */
11123 int rlen = 0; /* remaining bitfield length */
11124 int blen; /* bitfield length */
11125 int bstr; /* bitfield starting bit within byte */
11126 int litval; /* source literal value (if AOP_LIT) */
11127 unsigned char mask; /* bitmask within current byte */
11129 D(emitcode ("; genPackBits",""));
11131 blen = SPEC_BLEN (etype);
11132 bstr = SPEC_BSTR (etype);
11134 /* If the bitfield length is less than a byte */
11137 mask = ((unsigned char) (0xFF << (blen + bstr)) |
11138 (unsigned char) (0xFF >> (8 - bstr)));
11140 if (AOP_TYPE (right) == AOP_LIT)
11142 /* Case with a bitfield length <8 and literal source
11144 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
11146 litval &= (~mask) & 0xff;
11147 emitPtrByteGet (rname, p_type, FALSE);
11148 if ((mask|litval)!=0xff)
11149 emitcode ("anl","a,#!constbyte", mask);
11151 emitcode ("orl","a,#!constbyte", litval);
11155 if ((blen==1) && (p_type!=GPOINTER))
11157 /* Case with a bitfield length == 1 and no generic pointer
11159 if (AOP_TYPE (right) == AOP_CRY)
11160 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
11163 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
11164 emitcode ("rrc","a");
11166 emitPtrByteGet (rname, p_type, FALSE);
11167 emitcode ("mov","acc.%d,c",bstr);
11172 /* Case with a bitfield length < 8 and arbitrary source
11174 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
11175 /* shift and mask source value */
11177 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
11179 pushedB = pushB ();
11180 /* transfer A to B and get next byte */
11181 emitPtrByteGet (rname, p_type, TRUE);
11183 emitcode ("anl", "a,#!constbyte", mask);
11184 emitcode ("orl", "a,b");
11185 if (p_type == GPOINTER)
11186 emitcode ("pop", "b");
11192 emitPtrByteSet (rname, p_type, "a");
11196 /* Bit length is greater than 7 bits. In this case, copy */
11197 /* all except the partial byte at the end */
11198 for (rlen=blen;rlen>=8;rlen-=8)
11200 emitPtrByteSet (rname, p_type,
11201 aopGet (right, offset++, FALSE, TRUE, NULL) );
11203 emitcode ("inc", "%s", rname);
11206 /* If there was a partial byte at the end */
11209 mask = (((unsigned char) -1 << rlen) & 0xff);
11211 if (AOP_TYPE (right) == AOP_LIT)
11213 /* Case with partial byte and literal source
11215 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
11216 litval >>= (blen-rlen);
11217 litval &= (~mask) & 0xff;
11218 emitPtrByteGet (rname, p_type, FALSE);
11219 if ((mask|litval)!=0xff)
11220 emitcode ("anl","a,#!constbyte", mask);
11222 emitcode ("orl","a,#!constbyte", litval);
11227 /* Case with partial byte and arbitrary source
11229 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11230 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
11232 pushedB = pushB ();
11233 /* transfer A to B and get next byte */
11234 emitPtrByteGet (rname, p_type, TRUE);
11236 emitcode ("anl", "a,#!constbyte", mask);
11237 emitcode ("orl", "a,b");
11238 if (p_type == GPOINTER)
11239 emitcode ("pop", "b");
11243 emitPtrByteSet (rname, p_type, "a");
11248 /*-----------------------------------------------------------------*/
11249 /* genDataPointerSet - remat pointer to data space */
11250 /*-----------------------------------------------------------------*/
11252 genDataPointerSet (operand * right,
11256 int size, offset = 0;
11257 char *l, buffer[256];
11259 D (emitcode (";", "genDataPointerSet"));
11261 aopOp (right, ic, FALSE, FALSE);
11263 l = aopGet (result, 0, FALSE, TRUE, NULL);
11264 size = AOP_SIZE (right);
11268 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l + 1, offset);
11270 SNPRINTF (buffer, sizeof(buffer), "%s", l + 1);
11271 emitcode ("mov", "%s,%s", buffer,
11272 aopGet (right, offset++, FALSE, FALSE, NULL));
11275 freeAsmop (result, NULL, ic, TRUE);
11276 freeAsmop (right, NULL, ic, TRUE);
11279 /*-----------------------------------------------------------------*/
11280 /* genNearPointerSet - emitcode for near pointer put */
11281 /*-----------------------------------------------------------------*/
11283 genNearPointerSet (operand * right,
11290 sym_link *retype, *letype;
11291 sym_link *ptype = operandType (result);
11293 D (emitcode (";", "genNearPointerSet"));
11295 retype = getSpec (operandType (right));
11296 letype = getSpec (ptype);
11298 aopOp (result, ic, FALSE, FALSE);
11300 /* if the result is rematerializable &
11301 in data space & not a bit variable */
11302 if (AOP_TYPE (result) == AOP_IMMD &&
11303 DCL_TYPE (ptype) == POINTER &&
11304 !IS_BITVAR (retype) &&
11305 !IS_BITVAR (letype))
11307 genDataPointerSet (right, result, ic);
11311 /* if the value is already in a pointer register
11312 then don't need anything more */
11313 if (!AOP_INPREG (AOP (result)))
11315 /* otherwise get a free pointer register */
11318 aop = newAsmop (0);
11319 preg = getFreePtr (ic, &aop, FALSE);
11320 emitcode ("mov", "%s,%s",
11322 aopGet (result, 0, FALSE, TRUE, NULL));
11323 rname = preg->name;
11327 rname = aopGet (result, 0, FALSE, FALSE, NULL);
11330 aopOp (right, ic, FALSE, FALSE);
11332 /* if bitfield then unpack the bits */
11333 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11334 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
11337 /* we can just get the values */
11338 int size = AOP_SIZE (right);
11343 l = aopGet (right, offset, FALSE, TRUE, NULL);
11344 if ((*l == '@') || (strcmp (l, "acc") == 0))
11347 emitcode ("mov", "@%s,a", rname);
11350 emitcode ("mov", "@%s,%s", rname, l);
11352 emitcode ("inc", "%s", rname);
11357 /* now some housekeeping stuff */
11358 if (aop) /* we had to allocate for this iCode */
11361 aopPut (result, rname, 0);
11362 freeAsmop (NULL, aop, ic, TRUE);
11366 /* we did not allocate which means left
11367 already in a pointer register, then
11368 if size > 0 && this could be used again
11369 we have to point it back to where it
11371 if (AOP_SIZE (right) > 1 &&
11372 !OP_SYMBOL (result)->remat &&
11373 (OP_SYMBOL (result)->liveTo > ic->seq ||
11377 int size = AOP_SIZE (right) - 1;
11379 emitcode ("dec", "%s", rname);
11384 if (pi) pi->generated = 1;
11385 freeAsmop (result, NULL, ic, TRUE);
11386 freeAsmop (right, NULL, ic, TRUE);
11389 /*-----------------------------------------------------------------*/
11390 /* genPagedPointerSet - emitcode for Paged pointer put */
11391 /*-----------------------------------------------------------------*/
11393 genPagedPointerSet (operand * right,
11400 sym_link *retype, *letype;
11402 D (emitcode (";", "genPagedPointerSet"));
11404 retype = getSpec (operandType (right));
11405 letype = getSpec (operandType (result));
11407 aopOp (result, ic, FALSE, FALSE);
11409 /* if the value is already in a pointer register
11410 then don't need anything more */
11411 if (!AOP_INPREG (AOP (result)))
11413 /* otherwise get a free pointer register */
11416 aop = newAsmop (0);
11417 preg = getFreePtr (ic, &aop, FALSE);
11418 emitcode ("mov", "%s,%s",
11420 aopGet (result, 0, FALSE, TRUE, NULL));
11421 rname = preg->name;
11424 rname = aopGet (result, 0, FALSE, FALSE, NULL);
11426 aopOp (right, ic, FALSE, FALSE);
11428 /* if bitfield then unpack the bits */
11429 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11430 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
11433 /* we have can just get the values */
11434 int size = AOP_SIZE (right);
11439 l = aopGet (right, offset, FALSE, TRUE, NULL);
11441 emitcode ("movx", "@%s,a", rname);
11444 emitcode ("inc", "%s", rname);
11450 /* now some housekeeping stuff */
11454 aopPut (result, rname, 0);
11455 /* we had to allocate for this iCode */
11456 freeAsmop (NULL, aop, ic, TRUE);
11460 /* we did not allocate which means left
11461 already in a pointer register, then
11462 if size > 0 && this could be used again
11463 we have to point it back to where it
11465 if (AOP_SIZE (right) > 1 &&
11466 !OP_SYMBOL (result)->remat &&
11467 (OP_SYMBOL (result)->liveTo > ic->seq ||
11471 int size = AOP_SIZE (right) - 1;
11473 emitcode ("dec", "%s", rname);
11478 if (pi) pi->generated = 1;
11479 freeAsmop (result, NULL, ic, TRUE);
11480 freeAsmop (right, NULL, ic, TRUE);
11483 /*-----------------------------------------------------------------*/
11484 /* genFarPointerSet - set value from far space */
11485 /*-----------------------------------------------------------------*/
11487 genFarPointerSet (operand * right,
11488 operand * result, iCode * ic, iCode *pi)
11490 int size, offset, dopi=1;
11491 sym_link *retype = getSpec (operandType (right));
11492 sym_link *letype = getSpec (operandType (result));
11494 aopOp (result, ic, FALSE, FALSE);
11496 /* if the operand is already in dptr
11497 then we do nothing else we move the value to dptr */
11498 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
11500 /* if this is remateriazable */
11501 if (AOP_TYPE (result) == AOP_IMMD)
11502 emitcode ("mov", "dptr,%s",
11503 aopGet (result, 0, TRUE, FALSE, NULL));
11506 /* we need to get it byte by byte */
11507 _startLazyDPSEvaluation ();
11508 if (AOP_TYPE (result) != AOP_DPTR)
11510 emitcode ("mov", "dpl,%s", aopGet (result, 0, FALSE, FALSE, NULL));
11511 emitcode ("mov", "dph,%s", aopGet (result, 1, FALSE, FALSE, NULL));
11512 if (options.model == MODEL_FLAT24)
11513 emitcode ("mov", "dpx,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11517 /* We need to generate a load to DPTR indirect through DPTR. */
11518 D (emitcode (";", "genFarPointerSet -- indirection special case."););
11520 emitcode ("push", "%s", aopGet (result, 0, FALSE, TRUE, NULL));
11521 emitcode ("push", "%s", aopGet (result, 1, FALSE, TRUE, NULL));
11522 if (options.model == MODEL_FLAT24)
11523 emitcode ("mov", "dpx,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11524 emitcode ("pop", "dph");
11525 emitcode ("pop", "dpl");
11528 _endLazyDPSEvaluation ();
11531 /* so dptr now contains the address */
11532 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
11534 /* if bit then unpack */
11535 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11537 if (AOP_INDPTRn(result)) {
11538 genSetDPTR(AOP(result)->aopu.dptr);
11540 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
11541 if (AOP_INDPTRn(result)) {
11545 size = AOP_SIZE (right);
11547 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
11549 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11551 genSetDPTR(AOP(result)->aopu.dptr);
11552 emitcode ("movx", "@dptr,a");
11553 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
11554 emitcode ("inc", "dptr");
11558 _startLazyDPSEvaluation ();
11560 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11562 if (AOP_INDPTRn(result)) {
11563 genSetDPTR(AOP(result)->aopu.dptr);
11569 emitcode ("movx", "@dptr,a");
11570 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
11571 emitcode ("inc", "dptr");
11573 _endLazyDPSEvaluation ();
11577 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
11578 if (!AOP_INDPTRn(result)) {
11579 _startLazyDPSEvaluation ();
11581 aopPut (result,"dpl",0);
11582 aopPut (result,"dph",1);
11583 if (options.model == MODEL_FLAT24)
11584 aopPut (result,"dpx",2);
11586 _endLazyDPSEvaluation ();
11589 } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
11590 AOP_SIZE(right) > 1 &&
11591 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
11593 size = AOP_SIZE (right) - 1;
11594 if (AOP_INDPTRn(result)) {
11595 genSetDPTR(AOP(result)->aopu.dptr);
11597 while (size--) emitcode ("lcall","__decdptr");
11598 if (AOP_INDPTRn(result)) {
11602 freeAsmop (result, NULL, ic, TRUE);
11603 freeAsmop (right, NULL, ic, TRUE);
11606 /*-----------------------------------------------------------------*/
11607 /* genGenPointerSet - set value from generic pointer space */
11608 /*-----------------------------------------------------------------*/
11610 genGenPointerSet (operand * right,
11611 operand * result, iCode * ic, iCode *pi)
11615 sym_link *retype = getSpec (operandType (right));
11616 sym_link *letype = getSpec (operandType (result));
11618 aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
11620 pushedB = pushB ();
11621 /* if the operand is already in dptr
11622 then we do nothing else we move the value to dptr */
11623 if (AOP_TYPE (result) != AOP_STR)
11625 _startLazyDPSEvaluation ();
11626 /* if this is remateriazable */
11627 if (AOP_TYPE (result) == AOP_IMMD)
11629 emitcode ("mov", "dptr,%s", aopGet (result, 0, TRUE, FALSE, NULL));
11630 if (AOP(result)->aopu.aop_immd.from_cast_remat)
11632 MOVB (aopGet (result, AOP_SIZE(result)-1, FALSE, FALSE, NULL));
11637 "b,%s + 1", aopGet (result, 0, TRUE, FALSE, NULL));
11641 { /* we need to get it byte by byte */
11642 emitcode ("mov", "dpl,%s", aopGet (result, 0, FALSE, FALSE, NULL));
11643 emitcode ("mov", "dph,%s", aopGet (result, 1, FALSE, FALSE, NULL));
11644 if (options.model == MODEL_FLAT24) {
11645 emitcode ("mov", "dpx,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11646 emitcode ("mov", "b,%s", aopGet (result, 3, FALSE, FALSE, NULL));
11648 emitcode ("mov", "b,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11651 _endLazyDPSEvaluation ();
11653 /* so dptr + b now contains the address */
11654 aopOp (right, ic, FALSE, TRUE);
11656 /* if bit then unpack */
11657 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11659 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
11663 size = AOP_SIZE (right);
11666 _startLazyDPSEvaluation ();
11671 // Set two bytes at a time, passed in _AP & A.
11672 // dptr will be incremented ONCE by __gptrputWord.
11674 // Note: any change here must be coordinated
11675 // with the implementation of __gptrputWord
11676 // in device/lib/_gptrput.c
11677 emitcode("mov", "_ap, %s",
11678 aopGet (right, offset++, FALSE, FALSE, NULL));
11679 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11683 emitcode ("lcall", "__gptrputWord");
11688 // Only one byte to put.
11689 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11693 emitcode ("lcall", "__gptrput");
11696 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
11698 emitcode ("inc", "dptr");
11701 _endLazyDPSEvaluation ();
11704 if (pi && AOP_TYPE (result) != AOP_IMMD) {
11705 _startLazyDPSEvaluation ();
11707 aopPut (result, "dpl",0);
11708 aopPut (result, "dph",1);
11709 if (options.model == MODEL_FLAT24) {
11710 aopPut (result, "dpx",2);
11711 aopPut (result, "b",3);
11713 aopPut (result, "b",2);
11715 _endLazyDPSEvaluation ();
11718 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
11719 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
11721 size = AOP_SIZE (right) - 1;
11722 while (size--) emitcode ("lcall","__decdptr");
11726 freeAsmop (result, NULL, ic, TRUE);
11727 freeAsmop (right, NULL, ic, TRUE);
11730 /*-----------------------------------------------------------------*/
11731 /* genPointerSet - stores the value into a pointer location */
11732 /*-----------------------------------------------------------------*/
11734 genPointerSet (iCode * ic, iCode *pi)
11736 operand *right, *result;
11737 sym_link *type, *etype;
11740 D (emitcode (";", "genPointerSet"));
11742 right = IC_RIGHT (ic);
11743 result = IC_RESULT (ic);
11745 /* depending on the type of pointer we need to
11746 move it to the correct pointer register */
11747 type = operandType (result);
11748 etype = getSpec (type);
11749 /* if left is of type of pointer then it is simple */
11750 if (IS_PTR (type) && !IS_FUNC (type->next))
11752 p_type = DCL_TYPE (type);
11756 /* we have to go by the storage class */
11757 p_type = PTR_TYPE (SPEC_OCLS (etype));
11760 /* special case when cast remat */
11761 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
11762 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
11763 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
11764 type = operandType (result);
11765 p_type = DCL_TYPE (type);
11768 /* now that we have the pointer type we assign
11769 the pointer values */
11775 genNearPointerSet (right, result, ic, pi);
11779 genPagedPointerSet (right, result, ic, pi);
11783 genFarPointerSet (right, result, ic, pi);
11787 genGenPointerSet (right, result, ic, pi);
11791 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11792 "genPointerSet: illegal pointer type");
11796 /*-----------------------------------------------------------------*/
11797 /* genIfx - generate code for Ifx statement */
11798 /*-----------------------------------------------------------------*/
11800 genIfx (iCode * ic, iCode * popIc)
11802 operand *cond = IC_COND (ic);
11806 D (emitcode (";", "genIfx"));
11808 aopOp (cond, ic, FALSE, FALSE);
11810 /* get the value into acc */
11811 if (AOP_TYPE (cond) != AOP_CRY)
11818 if (AOP(cond)->aopu.aop_dir)
11819 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
11822 /* the result is now in the accumulator or a directly addressable bit */
11823 freeAsmop (cond, NULL, ic, TRUE);
11825 /* if there was something to be popped then do it */
11829 /* if the condition is a bit variable */
11831 genIfxJump (ic, dup);
11832 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
11833 genIfxJump (ic, SPIL_LOC (cond)->rname);
11834 else if (isbit && !IS_ITEMP (cond))
11835 genIfxJump (ic, OP_SYMBOL (cond)->rname);
11837 genIfxJump (ic, "a");
11842 /*-----------------------------------------------------------------*/
11843 /* genAddrOf - generates code for address of */
11844 /*-----------------------------------------------------------------*/
11846 genAddrOf (iCode * ic)
11848 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
11851 D (emitcode (";", "genAddrOf"));
11853 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11855 /* if the operand is on the stack then we
11856 need to get the stack offset of this
11861 /* if 10 bit stack */
11862 if (options.stack10bit) {
11866 tsprintf(buff, sizeof(buff),
11867 "#!constbyte",(options.stack_loc >> 16) & 0xff);
11868 /* if it has an offset then we need to compute it */
11869 /* emitcode ("subb", "a,#!constbyte", */
11870 /* -((sym->stack < 0) ? */
11871 /* ((short) (sym->stack - _G.nRegsSaved)) : */
11872 /* ((short) sym->stack)) & 0xff); */
11873 /* emitcode ("mov","b,a"); */
11874 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
11875 /* ((short) (sym->stack - _G.nRegsSaved)) : */
11876 /* ((short) sym->stack)) >> 8) & 0xff); */
11878 emitcode ("mov", "a,_bpx");
11879 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
11880 ((char) (sym->stack - _G.nRegsSaved)) :
11881 ((char) sym->stack )) & 0xff);
11882 emitcode ("mov", "b,a");
11883 emitcode ("mov", "a,_bpx+1");
11885 offset = (((sym->stack < 0) ?
11886 ((short) (sym->stack - _G.nRegsSaved)) :
11887 ((short) sym->stack )) >> 8) & 0xff;
11889 emitcode ("addc","a,#!constbyte", offset);
11891 aopPut (IC_RESULT (ic), "b", 0);
11892 aopPut (IC_RESULT (ic), "a", 1);
11893 aopPut (IC_RESULT (ic), buff, 2);
11895 /* we can just move _bp */
11896 aopPut (IC_RESULT (ic), "_bpx", 0);
11897 aopPut (IC_RESULT (ic), "_bpx+1", 1);
11898 aopPut (IC_RESULT (ic), buff, 2);
11901 /* if it has an offset then we need to compute it */
11904 emitcode ("mov", "a,_bp");
11905 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
11906 aopPut (IC_RESULT (ic), "a", 0);
11910 /* we can just move _bp */
11911 aopPut (IC_RESULT (ic), "_bp", 0);
11913 /* fill the result with zero */
11914 size = AOP_SIZE (IC_RESULT (ic)) - 1;
11917 if (options.stack10bit && size < (FPTRSIZE - 1)) {
11919 "*** warning: pointer to stack var truncated.\n");
11925 aopPut (IC_RESULT (ic), zero, offset++);
11931 /* object not on stack then we need the name */
11932 size = AOP_SIZE (IC_RESULT (ic));
11937 char s[SDCC_NAME_MAX];
11941 tsprintf(s, sizeof(s), "#!his",sym->rname);
11944 tsprintf(s, sizeof(s), "#!hihis",sym->rname);
11947 tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
11949 default: /* should not need this (just in case) */
11950 SNPRINTF (s, sizeof(s), "#(%s >> %d)",
11957 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11960 aopPut (IC_RESULT (ic), s, offset++);
11964 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11968 #if 0 // obsolete, and buggy for != xdata
11969 /*-----------------------------------------------------------------*/
11970 /* genArrayInit - generates code for address of */
11971 /*-----------------------------------------------------------------*/
11973 genArrayInit (iCode * ic)
11975 literalList *iLoop;
11977 int elementSize = 0, eIndex;
11978 unsigned val, lastVal;
11980 operand *left=IC_LEFT(ic);
11982 D (emitcode (";", "genArrayInit"));
11984 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
11986 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
11988 // Load immediate value into DPTR.
11989 emitcode("mov", "dptr, %s",
11990 aopGet (IC_LEFT(ic), 0, TRUE, FALSE, NULL));
11992 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
11995 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11996 "Unexpected operand to genArrayInit.\n");
11999 // a regression because of SDCCcse.c:1.52
12000 emitcode ("mov", "dpl,%s", aopGet (left, 0, FALSE, FALSE, NULL));
12001 emitcode ("mov", "dph,%s", aopGet (left, 1, FALSE, FALSE, NULL));
12002 if (options.model == MODEL_FLAT24)
12003 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
12007 type = operandType(IC_LEFT(ic));
12009 if (type && type->next)
12011 elementSize = getSize(type->next);
12015 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12016 "can't determine element size in genArrayInit.\n");
12020 iLoop = IC_ARRAYILIST(ic);
12025 bool firstpass = TRUE;
12027 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
12028 iLoop->count, (int)iLoop->literalValue, elementSize);
12034 symbol *tlbl = NULL;
12036 count = ix > 256 ? 256 : ix;
12040 tlbl = newiTempLabel (NULL);
12041 if (firstpass || (count & 0xff))
12043 emitcode("mov", "b, #!constbyte", count & 0xff);
12051 for (eIndex = 0; eIndex < elementSize; eIndex++)
12053 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
12054 if (val != lastVal)
12056 emitcode("mov", "a, #!constbyte", val);
12060 emitcode("movx", "@dptr, a");
12061 emitcode("inc", "dptr");
12066 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
12072 iLoop = iLoop->next;
12075 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
12079 /*-----------------------------------------------------------------*/
12080 /* genFarFarAssign - assignment when both are in far space */
12081 /*-----------------------------------------------------------------*/
12083 genFarFarAssign (operand * result, operand * right, iCode * ic)
12085 int size = AOP_SIZE (right);
12087 symbol *rSym = NULL;
12091 /* quick & easy case. */
12092 D (emitcode(";","genFarFarAssign (1 byte case)"));
12093 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
12094 freeAsmop (right, NULL, ic, FALSE);
12095 /* now assign DPTR to result */
12097 aopOp(result, ic, FALSE, FALSE);
12099 aopPut (result, "a", 0);
12100 freeAsmop(result, NULL, ic, FALSE);
12104 /* See if we've got an underlying symbol to abuse. */
12105 if (IS_SYMOP(result) && OP_SYMBOL(result))
12107 if (IS_TRUE_SYMOP(result))
12109 rSym = OP_SYMBOL(result);
12111 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
12113 rSym = OP_SYMBOL(result)->usl.spillLoc;
12117 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
12119 /* We can use the '390 auto-toggle feature to good effect here. */
12121 D (emitcode(";", "genFarFarAssign (390 auto-toggle fun)"));
12122 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12123 emitcode ("mov", "dptr,#%s", rSym->rname);
12124 /* DP2 = result, DP1 = right, DP1 is current. */
12127 emitcode("movx", "a,@dptr");
12128 emitcode("movx", "@dptr,a");
12131 emitcode("inc", "dptr");
12132 emitcode("inc", "dptr");
12135 emitcode("mov", "dps,#0");
12136 freeAsmop (right, NULL, ic, FALSE);
12138 some alternative code for processors without auto-toggle
12139 no time to test now, so later well put in...kpb
12140 D (emitcode(";", "genFarFarAssign (dual-dptr fun)"));
12141 emitcode("mov", "dps,#1"); /* Select DPTR2. */
12142 emitcode ("mov", "dptr,#%s", rSym->rname);
12143 /* DP2 = result, DP1 = right, DP1 is current. */
12147 emitcode("movx", "a,@dptr");
12149 emitcode("inc", "dptr");
12150 emitcode("inc", "dps");
12151 emitcode("movx", "@dptr,a");
12153 emitcode("inc", "dptr");
12154 emitcode("inc", "dps");
12156 emitcode("mov", "dps,#0");
12157 freeAsmop (right, NULL, ic, FALSE);
12162 D (emitcode (";", "genFarFarAssign"));
12163 aopOp (result, ic, TRUE, TRUE);
12165 _startLazyDPSEvaluation ();
12170 aopGet (right, offset, FALSE, FALSE, NULL), offset);
12173 _endLazyDPSEvaluation ();
12174 freeAsmop (result, NULL, ic, FALSE);
12175 freeAsmop (right, NULL, ic, FALSE);
12179 /*-----------------------------------------------------------------*/
12180 /* genAssign - generate code for assignment */
12181 /*-----------------------------------------------------------------*/
12183 genAssign (iCode * ic)
12185 operand *result, *right;
12187 unsigned long lit = 0L;
12189 D (emitcode (";", "genAssign"));
12191 result = IC_RESULT (ic);
12192 right = IC_RIGHT (ic);
12194 /* if they are the same */
12195 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
12198 aopOp (right, ic, FALSE, FALSE);
12200 emitcode (";", "genAssign: resultIsFar = %s",
12201 isOperandInFarSpace (result) ?
12204 /* special case both in far space */
12205 if ((AOP_TYPE (right) == AOP_DPTR ||
12206 AOP_TYPE (right) == AOP_DPTR2) &&
12207 /* IS_TRUE_SYMOP(result) && */
12208 isOperandInFarSpace (result))
12210 genFarFarAssign (result, right, ic);
12214 aopOp (result, ic, TRUE, FALSE);
12216 /* if they are the same registers */
12217 if (sameRegs (AOP (right), AOP (result)))
12220 /* if the result is a bit */
12221 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
12223 /* if the right size is a literal then
12224 we know what the value is */
12225 if (AOP_TYPE (right) == AOP_LIT)
12227 if (((int) operandLitValue (right)))
12228 aopPut (result, one, 0);
12230 aopPut (result, zero, 0);
12234 /* the right is also a bit variable */
12235 if (AOP_TYPE (right) == AOP_CRY)
12237 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
12238 aopPut (result, "c", 0);
12242 /* we need to or */
12244 aopPut (result, "a", 0);
12248 /* bit variables done */
12250 size = AOP_SIZE (result);
12252 if (AOP_TYPE (right) == AOP_LIT)
12253 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
12256 (AOP_TYPE (result) != AOP_REG) &&
12257 (AOP_TYPE (right) == AOP_LIT) &&
12258 !IS_FLOAT (operandType (right)))
12260 _startLazyDPSEvaluation ();
12261 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
12264 aopGet (right, offset, FALSE, FALSE, NULL),
12269 /* And now fill the rest with zeros. */
12272 emitcode ("clr", "a");
12276 aopPut (result, "a", offset++);
12278 _endLazyDPSEvaluation ();
12282 _startLazyDPSEvaluation ();
12286 aopGet (right, offset, FALSE, FALSE, NULL),
12290 _endLazyDPSEvaluation ();
12294 freeAsmop (result, NULL, ic, TRUE);
12295 freeAsmop (right, NULL, ic, TRUE);
12298 /*-----------------------------------------------------------------*/
12299 /* genJumpTab - generates code for jump table */
12300 /*-----------------------------------------------------------------*/
12302 genJumpTab (iCode * ic)
12307 D (emitcode (";", "genJumpTab"));
12309 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
12310 /* get the condition into accumulator */
12311 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE, NULL);
12313 /* multiply by four! */
12314 emitcode ("add", "a,acc");
12315 emitcode ("add", "a,acc");
12316 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
12318 jtab = newiTempLabel (NULL);
12319 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
12320 emitcode ("jmp", "@a+dptr");
12322 /* now generate the jump labels */
12323 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
12324 jtab = setNextItem (IC_JTLABELS (ic)))
12325 emitcode ("ljmp", "!tlabel", jtab->key + 100);
12329 /*-----------------------------------------------------------------*/
12330 /* genCast - gen code for casting */
12331 /*-----------------------------------------------------------------*/
12333 genCast (iCode * ic)
12335 operand *result = IC_RESULT (ic);
12336 sym_link *ctype = operandType (IC_LEFT (ic));
12337 sym_link *rtype = operandType (IC_RIGHT (ic));
12338 operand *right = IC_RIGHT (ic);
12341 D (emitcode (";", "genCast"));
12343 /* if they are equivalent then do nothing */
12344 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
12347 aopOp (right, ic, FALSE, AOP_IS_STR (result));
12348 aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR));
12350 /* if the result is a bit (and not a bitfield) */
12351 if (IS_BIT (OP_SYMBOL (result)->type))
12353 /* if the right size is a literal then
12354 we know what the value is */
12355 if (AOP_TYPE (right) == AOP_LIT)
12357 if (((int) operandLitValue (right)))
12358 aopPut (result, one, 0);
12360 aopPut (result, zero, 0);
12365 /* the right is also a bit variable */
12366 if (AOP_TYPE (right) == AOP_CRY)
12368 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
12369 aopPut (result, "c", 0);
12373 /* we need to or */
12375 aopPut (result, "a", 0);
12379 /* if they are the same size : or less */
12380 if (AOP_SIZE (result) <= AOP_SIZE (right))
12383 /* if they are in the same place */
12384 if (sameRegs (AOP (right), AOP (result)))
12387 /* if they in different places then copy */
12388 size = AOP_SIZE (result);
12390 _startLazyDPSEvaluation ();
12394 aopGet (right, offset, FALSE, FALSE, NULL),
12398 _endLazyDPSEvaluation ();
12402 /* if the result is of type pointer */
12403 if (IS_PTR (ctype))
12407 sym_link *type = operandType (right);
12409 /* pointer to generic pointer */
12410 if (IS_GENPTR (ctype))
12414 p_type = DCL_TYPE (type);
12418 #if OLD_CAST_BEHAVIOR
12419 /* KV: we are converting a non-pointer type to
12420 * a generic pointer. This (ifdef'd out) code
12421 * says that the resulting generic pointer
12422 * should have the same class as the storage
12423 * location of the non-pointer variable.
12425 * For example, converting an int (which happens
12426 * to be stored in DATA space) to a pointer results
12427 * in a DATA generic pointer; if the original int
12428 * in XDATA space, so will be the resulting pointer.
12430 * I don't like that behavior, and thus this change:
12431 * all such conversions will be forced to XDATA and
12432 * throw a warning. If you want some non-XDATA
12433 * type, or you want to suppress the warning, you
12434 * must go through an intermediate cast, like so:
12436 * char _generic *gp = (char _xdata *)(intVar);
12438 sym_link *etype = getSpec (type);
12440 /* we have to go by the storage class */
12441 if (SPEC_OCLS (etype) != generic)
12443 p_type = PTR_TYPE (SPEC_OCLS (etype));
12448 /* Converting unknown class (i.e. register variable)
12449 * to generic pointer. This is not good, but
12450 * we'll make a guess (and throw a warning).
12453 werror (W_INT_TO_GEN_PTR_CAST);
12457 /* the first two bytes are known */
12458 size = GPTRSIZE - 1;
12460 _startLazyDPSEvaluation ();
12464 aopGet (right, offset, FALSE, FALSE, NULL),
12468 _endLazyDPSEvaluation ();
12470 /* the last byte depending on type */
12472 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
12477 // pointerTypeToGPByte will have bitched.
12481 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%x", gpVal);
12482 aopPut (result, gpValStr, GPTRSIZE - 1);
12487 /* just copy the pointers */
12488 size = AOP_SIZE (result);
12490 _startLazyDPSEvaluation ();
12494 aopGet (right, offset, FALSE, FALSE, NULL),
12498 _endLazyDPSEvaluation ();
12502 /* so we now know that the size of destination is greater
12503 than the size of the source */
12504 /* we move to result for the size of source */
12505 size = AOP_SIZE (right);
12507 _startLazyDPSEvaluation ();
12511 aopGet (right, offset, FALSE, FALSE, NULL),
12515 _endLazyDPSEvaluation ();
12517 /* now depending on the sign of the source && destination */
12518 size = AOP_SIZE (result) - AOP_SIZE (right);
12519 /* if unsigned or not an integral type */
12520 /* also, if the source is a bit, we don't need to sign extend, because
12521 * it can't possibly have set the sign bit.
12523 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
12527 aopPut (result, zero, offset++);
12532 /* we need to extend the sign :{ */
12533 MOVA (aopGet (right, AOP_SIZE (right) - 1,
12534 FALSE, FALSE, NULL));
12535 emitcode ("rlc", "a");
12536 emitcode ("subb", "a,acc");
12538 aopPut (result, "a", offset++);
12541 /* we are done hurray !!!! */
12544 freeAsmop (right, NULL, ic, TRUE);
12545 freeAsmop (result, NULL, ic, TRUE);
12549 /*-----------------------------------------------------------------*/
12550 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
12551 /*-----------------------------------------------------------------*/
12552 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
12554 operand *from , *to , *count;
12559 /* we know it has to be 3 parameters */
12560 assert (nparms == 3);
12562 rsave = newBitVect(16);
12563 /* save DPTR if it needs to be saved */
12564 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12565 if (bitVectBitValue(ic->rMask,i))
12566 rsave = bitVectSetBit(rsave,i);
12568 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12569 ds390_rUmaskForOp (IC_RESULT(ic))));
12576 aopOp (from, ic->next, FALSE, FALSE);
12578 /* get from into DPTR1 */
12579 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12580 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12581 if (options.model == MODEL_FLAT24) {
12582 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12585 freeAsmop (from, NULL, ic, FALSE);
12586 aopOp (to, ic, FALSE, FALSE);
12587 /* get "to" into DPTR */
12588 /* if the operand is already in dptr
12589 then we do nothing else we move the value to dptr */
12590 if (AOP_TYPE (to) != AOP_STR) {
12591 /* if already in DPTR then we need to push */
12592 if (AOP_TYPE(to) == AOP_DPTR) {
12593 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12594 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12595 if (options.model == MODEL_FLAT24)
12596 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12597 emitcode ("pop", "dph");
12598 emitcode ("pop", "dpl");
12600 _startLazyDPSEvaluation ();
12601 /* if this is remateriazable */
12602 if (AOP_TYPE (to) == AOP_IMMD) {
12603 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12604 } else { /* we need to get it byte by byte */
12605 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12606 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12607 if (options.model == MODEL_FLAT24) {
12608 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12611 _endLazyDPSEvaluation ();
12614 freeAsmop (to, NULL, ic, FALSE);
12615 _G.dptrInUse = _G.dptr1InUse = 1;
12616 aopOp (count, ic->next->next, FALSE,FALSE);
12617 lbl =newiTempLabel(NULL);
12619 /* now for the actual copy */
12620 if (AOP_TYPE(count) == AOP_LIT &&
12621 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12622 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12624 emitcode ("lcall","__bi_memcpyc2x_s");
12626 emitcode ("lcall","__bi_memcpyx2x_s");
12628 freeAsmop (count, NULL, ic, FALSE);
12630 symbol *lbl1 = newiTempLabel(NULL);
12632 emitcode (";"," Auto increment but no djnz");
12633 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
12634 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
12635 freeAsmop (count, NULL, ic, FALSE);
12636 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12639 emitcode ("clr","a");
12640 emitcode ("movc", "a,@a+dptr");
12642 emitcode ("movx", "a,@dptr");
12643 emitcode ("movx", "@dptr,a");
12644 emitcode ("inc", "dptr");
12645 emitcode ("inc", "dptr");
12646 emitcode ("mov","a,b");
12647 emitcode ("orl","a,_ap");
12648 emitcode ("jz","!tlabel",lbl1->key+100);
12649 emitcode ("mov","a,_ap");
12650 emitcode ("add","a,#!constbyte",0xFF);
12651 emitcode ("mov","_ap,a");
12652 emitcode ("mov","a,b");
12653 emitcode ("addc","a,#!constbyte",0xFF);
12654 emitcode ("mov","b,a");
12655 emitcode ("sjmp","!tlabel",lbl->key+100);
12658 emitcode ("mov", "dps,#0");
12659 _G.dptrInUse = _G.dptr1InUse = 0;
12660 unsavermask(rsave);
12664 /*-----------------------------------------------------------------*/
12665 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
12666 /*-----------------------------------------------------------------*/
12667 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
12669 operand *from , *to , *count;
12674 /* we know it has to be 3 parameters */
12675 assert (nparms == 3);
12677 rsave = newBitVect(16);
12678 /* save DPTR if it needs to be saved */
12679 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12680 if (bitVectBitValue(ic->rMask,i))
12681 rsave = bitVectSetBit(rsave,i);
12683 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12684 ds390_rUmaskForOp (IC_RESULT(ic))));
12691 aopOp (from, ic->next, FALSE, FALSE);
12693 /* get from into DPTR1 */
12694 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12695 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12696 if (options.model == MODEL_FLAT24) {
12697 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12700 freeAsmop (from, NULL, ic, FALSE);
12701 aopOp (to, ic, FALSE, FALSE);
12702 /* get "to" into DPTR */
12703 /* if the operand is already in dptr
12704 then we do nothing else we move the value to dptr */
12705 if (AOP_TYPE (to) != AOP_STR) {
12706 /* if already in DPTR then we need to push */
12707 if (AOP_TYPE(to) == AOP_DPTR) {
12708 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12709 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12710 if (options.model == MODEL_FLAT24)
12711 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12712 emitcode ("pop", "dph");
12713 emitcode ("pop", "dpl");
12715 _startLazyDPSEvaluation ();
12716 /* if this is remateriazable */
12717 if (AOP_TYPE (to) == AOP_IMMD) {
12718 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12719 } else { /* we need to get it byte by byte */
12720 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12721 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12722 if (options.model == MODEL_FLAT24) {
12723 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12726 _endLazyDPSEvaluation ();
12729 freeAsmop (to, NULL, ic, FALSE);
12730 _G.dptrInUse = _G.dptr1InUse = 1;
12731 aopOp (count, ic->next->next, FALSE,FALSE);
12732 lbl =newiTempLabel(NULL);
12733 lbl2 =newiTempLabel(NULL);
12735 /* now for the actual compare */
12736 if (AOP_TYPE(count) == AOP_LIT &&
12737 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12738 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12740 emitcode("lcall","__bi_memcmpc2x_s");
12742 emitcode("lcall","__bi_memcmpx2x_s");
12743 freeAsmop (count, NULL, ic, FALSE);
12744 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12745 aopPut(IC_RESULT(ic),"a",0);
12746 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12748 symbol *lbl1 = newiTempLabel(NULL);
12750 emitcode("push","ar0");
12751 emitcode (";"," Auto increment but no djnz");
12752 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
12753 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
12754 freeAsmop (count, NULL, ic, FALSE);
12755 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12758 emitcode ("clr","a");
12759 emitcode ("movc", "a,@a+dptr");
12761 emitcode ("movx", "a,@dptr");
12762 emitcode ("mov","r0,a");
12763 emitcode ("movx", "a,@dptr");
12764 emitcode ("clr","c");
12765 emitcode ("subb","a,r0");
12766 emitcode ("jnz","!tlabel",lbl2->key+100);
12767 emitcode ("inc", "dptr");
12768 emitcode ("inc", "dptr");
12769 emitcode ("mov","a,b");
12770 emitcode ("orl","a,_ap");
12771 emitcode ("jz","!tlabel",lbl1->key+100);
12772 emitcode ("mov","a,_ap");
12773 emitcode ("add","a,#!constbyte",0xFF);
12774 emitcode ("mov","_ap,a");
12775 emitcode ("mov","a,b");
12776 emitcode ("addc","a,#!constbyte",0xFF);
12777 emitcode ("mov","b,a");
12778 emitcode ("sjmp","!tlabel",lbl->key+100);
12780 emitcode ("clr","a");
12782 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12783 aopPut(IC_RESULT(ic),"a",0);
12784 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12785 emitcode("pop","ar0");
12786 emitcode ("mov", "dps,#0");
12788 _G.dptrInUse = _G.dptr1InUse = 0;
12789 unsavermask(rsave);
12793 /*-----------------------------------------------------------------*/
12794 /* genInp - gen code for __builtin_inp read data from a mem mapped */
12795 /* port, first parameter output area second parameter pointer to */
12796 /* port third parameter count */
12797 /*-----------------------------------------------------------------*/
12798 static void genInp( iCode *ic, int nparms, operand **parms)
12800 operand *from , *to , *count;
12805 /* we know it has to be 3 parameters */
12806 assert (nparms == 3);
12808 rsave = newBitVect(16);
12809 /* save DPTR if it needs to be saved */
12810 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12811 if (bitVectBitValue(ic->rMask,i))
12812 rsave = bitVectSetBit(rsave,i);
12814 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12815 ds390_rUmaskForOp (IC_RESULT(ic))));
12822 aopOp (from, ic->next, FALSE, FALSE);
12824 /* get from into DPTR1 */
12825 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12826 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12827 if (options.model == MODEL_FLAT24) {
12828 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12831 freeAsmop (from, NULL, ic, FALSE);
12832 aopOp (to, ic, FALSE, FALSE);
12833 /* get "to" into DPTR */
12834 /* if the operand is already in dptr
12835 then we do nothing else we move the value to dptr */
12836 if (AOP_TYPE (to) != AOP_STR) {
12837 /* if already in DPTR then we need to push */
12838 if (AOP_TYPE(to) == AOP_DPTR) {
12839 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12840 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12841 if (options.model == MODEL_FLAT24)
12842 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12843 emitcode ("pop", "dph");
12844 emitcode ("pop", "dpl");
12846 _startLazyDPSEvaluation ();
12847 /* if this is remateriazable */
12848 if (AOP_TYPE (to) == AOP_IMMD) {
12849 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12850 } else { /* we need to get it byte by byte */
12851 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12852 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12853 if (options.model == MODEL_FLAT24) {
12854 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12857 _endLazyDPSEvaluation ();
12860 freeAsmop (to, NULL, ic, FALSE);
12862 _G.dptrInUse = _G.dptr1InUse = 1;
12863 aopOp (count, ic->next->next, FALSE,FALSE);
12864 lbl =newiTempLabel(NULL);
12866 /* now for the actual copy */
12867 if (AOP_TYPE(count) == AOP_LIT &&
12868 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12869 emitcode (";","OH JOY auto increment with djnz (very fast)");
12870 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
12871 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12872 freeAsmop (count, NULL, ic, FALSE);
12874 emitcode ("movx", "a,@dptr"); /* read data from port */
12875 emitcode ("dec","dps"); /* switch to DPTR */
12876 emitcode ("movx", "@dptr,a"); /* save into location */
12877 emitcode ("inc", "dptr"); /* point to next area */
12878 emitcode ("inc","dps"); /* switch to DPTR2 */
12879 emitcode ("djnz","b,!tlabel",lbl->key+100);
12881 symbol *lbl1 = newiTempLabel(NULL);
12883 emitcode (";"," Auto increment but no djnz");
12884 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
12885 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
12886 freeAsmop (count, NULL, ic, FALSE);
12887 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
12889 emitcode ("movx", "a,@dptr");
12890 emitcode ("dec","dps"); /* switch to DPTR */
12891 emitcode ("movx", "@dptr,a");
12892 emitcode ("inc", "dptr");
12893 emitcode ("inc","dps"); /* switch to DPTR2 */
12894 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
12895 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
12896 emitcode ("mov","a,b");
12897 emitcode ("orl","a,_ap");
12898 emitcode ("jz","!tlabel",lbl1->key+100);
12899 emitcode ("mov","a,_ap");
12900 emitcode ("add","a,#!constbyte",0xFF);
12901 emitcode ("mov","_ap,a");
12902 emitcode ("mov","a,b");
12903 emitcode ("addc","a,#!constbyte",0xFF);
12904 emitcode ("mov","b,a");
12905 emitcode ("sjmp","!tlabel",lbl->key+100);
12908 emitcode ("mov", "dps,#0");
12909 _G.dptrInUse = _G.dptr1InUse = 0;
12910 unsavermask(rsave);
12914 /*-----------------------------------------------------------------*/
12915 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
12916 /* port, first parameter output area second parameter pointer to */
12917 /* port third parameter count */
12918 /*-----------------------------------------------------------------*/
12919 static void genOutp( iCode *ic, int nparms, operand **parms)
12921 operand *from , *to , *count;
12926 /* we know it has to be 3 parameters */
12927 assert (nparms == 3);
12929 rsave = newBitVect(16);
12930 /* save DPTR if it needs to be saved */
12931 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12932 if (bitVectBitValue(ic->rMask,i))
12933 rsave = bitVectSetBit(rsave,i);
12935 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12936 ds390_rUmaskForOp (IC_RESULT(ic))));
12943 aopOp (from, ic->next, FALSE, FALSE);
12945 /* get from into DPTR1 */
12946 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12947 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12948 if (options.model == MODEL_FLAT24) {
12949 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12952 freeAsmop (from, NULL, ic, FALSE);
12953 aopOp (to, ic, FALSE, FALSE);
12954 /* get "to" into DPTR */
12955 /* if the operand is already in dptr
12956 then we do nothing else we move the value to dptr */
12957 if (AOP_TYPE (to) != AOP_STR) {
12958 /* if already in DPTR then we need to push */
12959 if (AOP_TYPE(to) == AOP_DPTR) {
12960 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12961 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12962 if (options.model == MODEL_FLAT24)
12963 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12964 emitcode ("pop", "dph");
12965 emitcode ("pop", "dpl");
12967 _startLazyDPSEvaluation ();
12968 /* if this is remateriazable */
12969 if (AOP_TYPE (to) == AOP_IMMD) {
12970 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12971 } else { /* we need to get it byte by byte */
12972 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12973 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12974 if (options.model == MODEL_FLAT24) {
12975 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12978 _endLazyDPSEvaluation ();
12981 freeAsmop (to, NULL, ic, FALSE);
12983 _G.dptrInUse = _G.dptr1InUse = 1;
12984 aopOp (count, ic->next->next, FALSE,FALSE);
12985 lbl =newiTempLabel(NULL);
12987 /* now for the actual copy */
12988 if (AOP_TYPE(count) == AOP_LIT &&
12989 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12990 emitcode (";","OH JOY auto increment with djnz (very fast)");
12991 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
12992 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12994 emitcode ("movx", "a,@dptr"); /* read data from port */
12995 emitcode ("inc","dps"); /* switch to DPTR2 */
12996 emitcode ("movx", "@dptr,a"); /* save into location */
12997 emitcode ("inc", "dptr"); /* point to next area */
12998 emitcode ("dec","dps"); /* switch to DPTR */
12999 emitcode ("djnz","b,!tlabel",lbl->key+100);
13000 freeAsmop (count, NULL, ic, FALSE);
13002 symbol *lbl1 = newiTempLabel(NULL);
13004 emitcode (";"," Auto increment but no djnz");
13005 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
13006 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
13007 freeAsmop (count, NULL, ic, FALSE);
13008 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
13010 emitcode ("movx", "a,@dptr");
13011 emitcode ("inc", "dptr");
13012 emitcode ("inc","dps"); /* switch to DPTR2 */
13013 emitcode ("movx", "@dptr,a");
13014 emitcode ("dec","dps"); /* switch to DPTR */
13015 emitcode ("mov","a,b");
13016 emitcode ("orl","a,_ap");
13017 emitcode ("jz","!tlabel",lbl1->key+100);
13018 emitcode ("mov","a,_ap");
13019 emitcode ("add","a,#!constbyte",0xFF);
13020 emitcode ("mov","_ap,a");
13021 emitcode ("mov","a,b");
13022 emitcode ("addc","a,#!constbyte",0xFF);
13023 emitcode ("mov","b,a");
13024 emitcode ("sjmp","!tlabel",lbl->key+100);
13027 emitcode ("mov", "dps,#0");
13028 _G.dptrInUse = _G.dptr1InUse = 0;
13029 unsavermask(rsave);
13033 /*-----------------------------------------------------------------*/
13034 /* genSwapW - swap lower & high order bytes */
13035 /*-----------------------------------------------------------------*/
13036 static void genSwapW(iCode *ic, int nparms, operand **parms)
13040 assert (nparms==1);
13043 dest=IC_RESULT(ic);
13045 assert(getSize(operandType(src))==2);
13047 aopOp (src, ic, FALSE, FALSE);
13048 emitcode ("mov","a,%s",aopGet(src,0,FALSE,FALSE,NULL));
13050 MOVB(aopGet(src,1,FALSE,FALSE,"b"));
13052 freeAsmop (src, NULL, ic, FALSE);
13054 aopOp (dest,ic, FALSE, FALSE);
13055 aopPut(dest,"b",0);
13056 aopPut(dest,"a",1);
13057 freeAsmop (dest, NULL, ic, FALSE);
13060 /*-----------------------------------------------------------------*/
13061 /* genMemsetX - gencode for memSetX data */
13062 /*-----------------------------------------------------------------*/
13063 static void genMemsetX(iCode *ic, int nparms, operand **parms)
13065 operand *to , *val , *count;
13071 /* we know it has to be 3 parameters */
13072 assert (nparms == 3);
13078 /* save DPTR if it needs to be saved */
13079 rsave = newBitVect(16);
13080 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
13081 if (bitVectBitValue(ic->rMask,i))
13082 rsave = bitVectSetBit(rsave,i);
13084 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
13085 ds390_rUmaskForOp (IC_RESULT(ic))));
13088 aopOp (to, ic, FALSE, FALSE);
13089 /* get "to" into DPTR */
13090 /* if the operand is already in dptr
13091 then we do nothing else we move the value to dptr */
13092 if (AOP_TYPE (to) != AOP_STR) {
13093 /* if already in DPTR then we need to push */
13094 if (AOP_TYPE(to) == AOP_DPTR) {
13095 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
13096 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
13097 if (options.model == MODEL_FLAT24)
13098 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
13099 emitcode ("pop", "dph");
13100 emitcode ("pop", "dpl");
13102 _startLazyDPSEvaluation ();
13103 /* if this is remateriazable */
13104 if (AOP_TYPE (to) == AOP_IMMD) {
13105 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
13106 } else { /* we need to get it byte by byte */
13107 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
13108 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
13109 if (options.model == MODEL_FLAT24) {
13110 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
13113 _endLazyDPSEvaluation ();
13116 freeAsmop (to, NULL, ic, FALSE);
13118 aopOp (val, ic->next->next, FALSE,FALSE);
13119 aopOp (count, ic->next->next, FALSE,FALSE);
13120 lbl =newiTempLabel(NULL);
13121 /* now for the actual copy */
13122 if (AOP_TYPE(count) == AOP_LIT &&
13123 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
13124 l = aopGet(val, 0, FALSE, FALSE, NULL);
13125 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
13128 emitcode ("movx", "@dptr,a");
13129 emitcode ("inc", "dptr");
13130 emitcode ("djnz","b,!tlabel",lbl->key+100);
13132 symbol *lbl1 = newiTempLabel(NULL);
13134 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
13135 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
13137 MOVA (aopGet(val, 0, FALSE, FALSE, NULL));
13138 emitcode ("movx", "@dptr,a");
13139 emitcode ("inc", "dptr");
13140 emitcode ("mov","a,b");
13141 emitcode ("orl","a,_ap");
13142 emitcode ("jz","!tlabel",lbl1->key+100);
13143 emitcode ("mov","a,_ap");
13144 emitcode ("add","a,#!constbyte",0xFF);
13145 emitcode ("mov","_ap,a");
13146 emitcode ("mov","a,b");
13147 emitcode ("addc","a,#!constbyte",0xFF);
13148 emitcode ("mov","b,a");
13149 emitcode ("sjmp","!tlabel",lbl->key+100);
13152 freeAsmop (count, NULL, ic, FALSE);
13153 unsavermask(rsave);
13156 /*-----------------------------------------------------------------*/
13157 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
13158 /*-----------------------------------------------------------------*/
13159 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
13162 operand *pnum, *result;
13165 assert (nparms==1);
13166 /* save registers that need to be saved */
13167 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13168 ds390_rUmaskForOp (IC_RESULT(ic))));
13171 aopOp (pnum, ic, FALSE, FALSE);
13172 emitcode ("mov","a,%s",aopGet(pnum,0,FALSE,FALSE,DP2_RESULT_REG));
13173 freeAsmop (pnum, NULL, ic, FALSE);
13174 emitcode ("lcall","NatLib_LoadPrimitive");
13175 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
13176 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
13177 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
13178 for (i = (size-1) ; i >= 0 ; i-- ) {
13179 emitcode ("push","a%s",javaRet[i]);
13181 for (i=0; i < size ; i++ ) {
13182 emitcode ("pop","a%s",
13183 aopGet(result,i,FALSE,FALSE,DP2_RESULT_REG));
13186 for (i = 0 ; i < size ; i++ ) {
13187 aopPut(result,javaRet[i],i);
13190 freeAsmop (result, NULL, ic, FALSE);
13191 unsavermask(rsave);
13194 /*-----------------------------------------------------------------*/
13195 /* genNatLibLoadPointer - calls TINI api function to load pointer */
13196 /*-----------------------------------------------------------------*/
13197 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
13200 operand *pnum, *result;
13204 assert (nparms==1);
13205 /* save registers that need to be saved */
13206 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13207 ds390_rUmaskForOp (IC_RESULT(ic))));
13210 aopOp (pnum, ic, FALSE, FALSE);
13211 emitcode ("mov","a,%s",aopGet(pnum,0,FALSE,FALSE,DP2_RESULT_REG));
13212 freeAsmop (pnum, NULL, ic, FALSE);
13213 emitcode ("lcall","NatLib_LoadPointer");
13214 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
13215 if (AOP_TYPE(result)!=AOP_STR) {
13216 for (i = 0 ; i < size ; i++ ) {
13217 aopPut(result,fReturn[i],i);
13220 freeAsmop (result, NULL, ic, FALSE);
13221 unsavermask(rsave);
13224 /*-----------------------------------------------------------------*/
13225 /* genNatLibInstallStateBlock - */
13226 /*-----------------------------------------------------------------*/
13227 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
13228 operand **parms, const char *name)
13231 operand *psb, *handle;
13232 assert (nparms==2);
13234 /* save registers that need to be saved */
13235 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13236 ds390_rUmaskForOp (IC_RESULT(ic))));
13240 /* put pointer to state block into DPTR1 */
13241 aopOp (psb, ic, FALSE, FALSE);
13242 if (AOP_TYPE (psb) == AOP_IMMD) {
13243 emitcode ("mov","dps,#1");
13244 emitcode ("mov", "dptr,%s",
13245 aopGet (psb, 0, TRUE, FALSE, DP2_RESULT_REG));
13246 emitcode ("mov","dps,#0");
13248 emitcode ("mov","dpl1,%s",aopGet(psb,0,FALSE,FALSE,DP2_RESULT_REG));
13249 emitcode ("mov","dph1,%s",aopGet(psb,1,FALSE,FALSE,DP2_RESULT_REG));
13250 emitcode ("mov","dpx1,%s",aopGet(psb,2,FALSE,FALSE,DP2_RESULT_REG));
13252 freeAsmop (psb, NULL, ic, FALSE);
13254 /* put libraryID into DPTR */
13255 emitcode ("mov","dptr,#LibraryID");
13257 /* put handle into r3:r2 */
13258 aopOp (handle, ic, FALSE, FALSE);
13259 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13260 emitcode ("push","%s",aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13261 emitcode ("push","%s",aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13262 emitcode ("pop","ar3");
13263 emitcode ("pop","ar2");
13265 emitcode ("mov","r2,%s",aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13266 emitcode ("mov","r3,%s",aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13268 freeAsmop (psb, NULL, ic, FALSE);
13270 /* make the call */
13271 emitcode ("lcall","NatLib_Install%sStateBlock",name);
13273 /* put return value into place*/
13275 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
13277 aopPut(IC_RESULT(ic),"a",0);
13278 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13279 unsavermask(rsave);
13282 /*-----------------------------------------------------------------*/
13283 /* genNatLibRemoveStateBlock - */
13284 /*-----------------------------------------------------------------*/
13285 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
13291 /* save registers that need to be saved */
13292 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13293 ds390_rUmaskForOp (IC_RESULT(ic))));
13295 /* put libraryID into DPTR */
13296 emitcode ("mov","dptr,#LibraryID");
13297 /* make the call */
13298 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
13299 unsavermask(rsave);
13302 /*-----------------------------------------------------------------*/
13303 /* genNatLibGetStateBlock - */
13304 /*-----------------------------------------------------------------*/
13305 static void genNatLibGetStateBlock(iCode *ic,int nparms,
13306 operand **parms,const char *name)
13309 symbol *lbl = newiTempLabel(NULL);
13312 /* save registers that need to be saved */
13313 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13314 ds390_rUmaskForOp (IC_RESULT(ic))));
13316 /* put libraryID into DPTR */
13317 emitcode ("mov","dptr,#LibraryID");
13318 /* make the call */
13319 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
13320 emitcode ("jnz","!tlabel",lbl->key+100);
13322 /* put return value into place */
13323 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
13324 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
13325 emitcode ("push","ar3");
13326 emitcode ("push","ar2");
13327 emitcode ("pop","%s",
13328 aopGet(IC_RESULT(ic),0,FALSE,TRUE,DP2_RESULT_REG));
13329 emitcode ("pop","%s",
13330 aopGet(IC_RESULT(ic),1,FALSE,TRUE,DP2_RESULT_REG));
13332 aopPut(IC_RESULT(ic),"r2",0);
13333 aopPut(IC_RESULT(ic),"r3",1);
13335 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13337 unsavermask(rsave);
13340 /*-----------------------------------------------------------------*/
13341 /* genMMMalloc - */
13342 /*-----------------------------------------------------------------*/
13343 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
13344 int size, const char *name)
13349 symbol *lbl = newiTempLabel(NULL);
13351 assert (nparms == 1);
13352 /* save registers that need to be saved */
13353 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13354 ds390_rUmaskForOp (IC_RESULT(ic))));
13357 aopOp (bsize,ic,FALSE,FALSE);
13359 /* put the size in R4-R2 */
13360 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
13361 emitcode("push","%s",aopGet(bsize,0,FALSE,TRUE,DP2_RESULT_REG));
13362 emitcode("push","%s",aopGet(bsize,1,FALSE,TRUE,DP2_RESULT_REG));
13364 emitcode("push","%s",aopGet(bsize,2,FALSE,TRUE,DP2_RESULT_REG));
13365 emitcode("pop","ar4");
13367 emitcode("pop","ar3");
13368 emitcode("pop","ar2");
13370 emitcode ("mov","r2,%s",aopGet(bsize,0,FALSE,TRUE,DP2_RESULT_REG));
13371 emitcode ("mov","r3,%s",aopGet(bsize,1,FALSE,TRUE,DP2_RESULT_REG));
13373 emitcode("mov","r4,%s",aopGet(bsize,2,FALSE,TRUE,DP2_RESULT_REG));
13376 freeAsmop (bsize, NULL, ic, FALSE);
13378 /* make the call */
13379 emitcode ("lcall","MM_%s",name);
13380 emitcode ("jz","!tlabel",lbl->key+100);
13381 emitcode ("mov","r2,#!constbyte",0xff);
13382 emitcode ("mov","r3,#!constbyte",0xff);
13384 /* we don't care about the pointer : we just save the handle */
13385 rsym = OP_SYMBOL(IC_RESULT(ic));
13386 if (rsym->liveFrom != rsym->liveTo) {
13387 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
13388 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
13389 emitcode ("push","ar3");
13390 emitcode ("push","ar2");
13391 emitcode ("pop","%s",
13392 aopGet(IC_RESULT(ic),0,FALSE,TRUE,DP2_RESULT_REG));
13393 emitcode ("pop","%s",
13394 aopGet(IC_RESULT(ic),1,FALSE,TRUE,DP2_RESULT_REG));
13396 aopPut(IC_RESULT(ic),"r2",0);
13397 aopPut(IC_RESULT(ic),"r3",1);
13399 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13401 unsavermask(rsave);
13404 /*-----------------------------------------------------------------*/
13406 /*-----------------------------------------------------------------*/
13407 static void genMMDeref (iCode *ic,int nparms, operand **parms)
13412 assert (nparms == 1);
13413 /* save registers that need to be saved */
13414 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13415 ds390_rUmaskForOp (IC_RESULT(ic))));
13418 aopOp (handle,ic,FALSE,FALSE);
13420 /* put the size in R4-R2 */
13421 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13422 emitcode("push","%s",
13423 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13424 emitcode("push","%s",
13425 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13426 emitcode("pop","ar3");
13427 emitcode("pop","ar2");
13429 emitcode ("mov","r2,%s",
13430 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13431 emitcode ("mov","r3,%s",
13432 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13434 freeAsmop (handle, NULL, ic, FALSE);
13436 /* make the call */
13437 emitcode ("lcall","MM_Deref");
13440 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13441 if (rsym->liveFrom != rsym->liveTo) {
13442 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13443 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
13444 _startLazyDPSEvaluation ();
13446 aopPut(IC_RESULT(ic),"dpl",0);
13447 aopPut(IC_RESULT(ic),"dph",1);
13448 aopPut(IC_RESULT(ic),"dpx",2);
13450 _endLazyDPSEvaluation ();
13455 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13456 unsavermask(rsave);
13459 /*-----------------------------------------------------------------*/
13460 /* genMMUnrestrictedPersist - */
13461 /*-----------------------------------------------------------------*/
13462 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
13467 assert (nparms == 1);
13468 /* save registers that need to be saved */
13469 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13470 ds390_rUmaskForOp (IC_RESULT(ic))));
13473 aopOp (handle,ic,FALSE,FALSE);
13475 /* put the size in R3-R2 */
13476 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13477 emitcode("push","%s",
13478 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13479 emitcode("push","%s",
13480 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13481 emitcode("pop","ar3");
13482 emitcode("pop","ar2");
13484 emitcode ("mov","r2,%s",
13485 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13486 emitcode ("mov","r3,%s",
13487 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13489 freeAsmop (handle, NULL, ic, FALSE);
13491 /* make the call */
13492 emitcode ("lcall","MM_UnrestrictedPersist");
13495 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13496 if (rsym->liveFrom != rsym->liveTo) {
13497 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13498 aopPut(IC_RESULT(ic),"a",0);
13499 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13502 unsavermask(rsave);
13505 /*-----------------------------------------------------------------*/
13506 /* genSystemExecJavaProcess - */
13507 /*-----------------------------------------------------------------*/
13508 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
13511 operand *handle, *pp;
13513 assert (nparms==2);
13514 /* save registers that need to be saved */
13515 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13516 ds390_rUmaskForOp (IC_RESULT(ic))));
13521 /* put the handle in R3-R2 */
13522 aopOp (handle,ic,FALSE,FALSE);
13523 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13524 emitcode("push","%s",
13525 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13526 emitcode("push","%s",
13527 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13528 emitcode("pop","ar3");
13529 emitcode("pop","ar2");
13531 emitcode ("mov","r2,%s",
13532 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13533 emitcode ("mov","r3,%s",
13534 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13536 freeAsmop (handle, NULL, ic, FALSE);
13538 /* put pointer in DPTR */
13539 aopOp (pp,ic,FALSE,FALSE);
13540 if (AOP_TYPE(pp) == AOP_IMMD) {
13541 emitcode ("mov", "dptr,%s",
13542 aopGet (pp, 0, TRUE, FALSE, NULL));
13543 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
13544 emitcode ("mov","dpl,%s",aopGet(pp,0,FALSE,FALSE,NULL));
13545 emitcode ("mov","dph,%s",aopGet(pp,1,FALSE,FALSE,NULL));
13546 emitcode ("mov","dpx,%s",aopGet(pp,2,FALSE,FALSE,NULL));
13548 freeAsmop (handle, NULL, ic, FALSE);
13550 /* make the call */
13551 emitcode ("lcall","System_ExecJavaProcess");
13553 /* put result in place */
13555 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13556 if (rsym->liveFrom != rsym->liveTo) {
13557 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13558 aopPut(IC_RESULT(ic),"a",0);
13559 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13563 unsavermask(rsave);
13566 /*-----------------------------------------------------------------*/
13567 /* genSystemRTCRegisters - */
13568 /*-----------------------------------------------------------------*/
13569 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
13575 assert (nparms==1);
13576 /* save registers that need to be saved */
13577 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13578 ds390_rUmaskForOp (IC_RESULT(ic))));
13581 /* put pointer in DPTR */
13582 aopOp (pp,ic,FALSE,FALSE);
13583 if (AOP_TYPE (pp) == AOP_IMMD) {
13584 emitcode ("mov","dps,#1");
13585 emitcode ("mov", "dptr,%s",
13586 aopGet (pp, 0, TRUE, FALSE, NULL));
13587 emitcode ("mov","dps,#0");
13589 emitcode ("mov","dpl1,%s",
13590 aopGet(pp,0,FALSE,FALSE,DP2_RESULT_REG));
13591 emitcode ("mov","dph1,%s",
13592 aopGet(pp,1,FALSE,FALSE,DP2_RESULT_REG));
13593 emitcode ("mov","dpx1,%s",
13594 aopGet(pp,2,FALSE,FALSE,DP2_RESULT_REG));
13596 freeAsmop (pp, NULL, ic, FALSE);
13598 /* make the call */
13599 emitcode ("lcall","System_%sRTCRegisters",name);
13601 unsavermask(rsave);
13604 /*-----------------------------------------------------------------*/
13605 /* genSystemThreadSleep - */
13606 /*-----------------------------------------------------------------*/
13607 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
13612 assert (nparms==1);
13613 /* save registers that need to be saved */
13614 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13615 ds390_rUmaskForOp (IC_RESULT(ic))));
13618 aopOp(to,ic,FALSE,FALSE);
13619 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
13620 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
13621 emitcode ("push","%s",
13622 aopGet(to,0,FALSE,TRUE,DP2_RESULT_REG));
13623 emitcode ("push","%s",
13624 aopGet(to,1,FALSE,TRUE,DP2_RESULT_REG));
13625 emitcode ("push","%s",
13626 aopGet(to,2,FALSE,TRUE,DP2_RESULT_REG));
13627 emitcode ("push","%s",
13628 aopGet(to,3,FALSE,TRUE,DP2_RESULT_REG));
13629 emitcode ("pop","ar3");
13630 emitcode ("pop","ar2");
13631 emitcode ("pop","ar1");
13632 emitcode ("pop","ar0");
13634 emitcode ("mov","r0,%s",
13635 aopGet(to,0,FALSE,TRUE,DP2_RESULT_REG));
13636 emitcode ("mov","r1,%s",
13637 aopGet(to,1,FALSE,TRUE,DP2_RESULT_REG));
13638 emitcode ("mov","r2,%s",
13639 aopGet(to,2,FALSE,TRUE,DP2_RESULT_REG));
13640 emitcode ("mov","r3,%s",
13641 aopGet(to,3,FALSE,TRUE,DP2_RESULT_REG));
13643 freeAsmop (to, NULL, ic, FALSE);
13645 /* suspend in acc */
13647 aopOp(s,ic,FALSE,FALSE);
13648 emitcode ("mov","a,%s",
13649 aopGet(s,0,FALSE,TRUE,NULL));
13650 freeAsmop (s, NULL, ic, FALSE);
13652 /* make the call */
13653 emitcode ("lcall","System_%s",name);
13655 unsavermask(rsave);
13658 /*-----------------------------------------------------------------*/
13659 /* genSystemThreadResume - */
13660 /*-----------------------------------------------------------------*/
13661 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
13666 assert (nparms==2);
13667 /* save registers that need to be saved */
13668 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13669 ds390_rUmaskForOp (IC_RESULT(ic))));
13675 aopOp(pid,ic,FALSE,FALSE);
13676 emitcode ("mov","r0,%s",
13677 aopGet(pid,0,FALSE,TRUE,DP2_RESULT_REG));
13678 freeAsmop (pid, NULL, ic, FALSE);
13681 aopOp(tid,ic,FALSE,FALSE);
13682 emitcode ("mov","a,%s",
13683 aopGet(tid,0,FALSE,TRUE,DP2_RESULT_REG));
13684 freeAsmop (tid, NULL, ic, FALSE);
13686 emitcode ("lcall","System_ThreadResume");
13688 /* put result into place */
13690 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13691 if (rsym->liveFrom != rsym->liveTo) {
13692 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13693 aopPut(IC_RESULT(ic),"a",0);
13694 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13697 unsavermask(rsave);
13700 /*-----------------------------------------------------------------*/
13701 /* genSystemProcessResume - */
13702 /*-----------------------------------------------------------------*/
13703 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
13708 assert (nparms==1);
13709 /* save registers that need to be saved */
13710 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13711 ds390_rUmaskForOp (IC_RESULT(ic))));
13716 aopOp(pid,ic,FALSE,FALSE);
13717 emitcode ("mov","a,%s",
13718 aopGet(pid,0,FALSE,TRUE,DP2_RESULT_REG));
13719 freeAsmop (pid, NULL, ic, FALSE);
13721 emitcode ("lcall","System_ProcessResume");
13723 unsavermask(rsave);
13726 /*-----------------------------------------------------------------*/
13728 /*-----------------------------------------------------------------*/
13729 static void genSystem (iCode *ic,int nparms,char *name)
13731 assert(nparms == 0);
13733 emitcode ("lcall","System_%s",name);
13736 /*-----------------------------------------------------------------*/
13737 /* genSystemPoll - */
13738 /*-----------------------------------------------------------------*/
13739 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
13744 assert (nparms==1);
13745 /* save registers that need to be saved */
13746 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13747 ds390_rUmaskForOp (IC_RESULT(ic))));
13750 aopOp (fp,ic,FALSE,FALSE);
13751 if (AOP_TYPE (fp) == AOP_IMMD) {
13752 emitcode ("mov", "dptr,%s",
13753 aopGet (fp, 0, TRUE, FALSE, DP2_RESULT_REG));
13754 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
13755 emitcode ("mov","dpl,%s",
13756 aopGet(fp,0,FALSE,FALSE,DP2_RESULT_REG));
13757 emitcode ("mov","dph,%s",
13758 aopGet(fp,1,FALSE,FALSE,DP2_RESULT_REG));
13759 emitcode ("mov","dpx,%s",
13760 aopGet(fp,2,FALSE,FALSE,DP2_RESULT_REG));
13762 freeAsmop (fp, NULL, ic, FALSE);
13764 emitcode ("lcall","System_%sPoll",name);
13766 /* put result into place */
13768 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13769 if (rsym->liveFrom != rsym->liveTo) {
13770 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13771 aopPut(IC_RESULT(ic),"a",0);
13772 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13775 unsavermask(rsave);
13778 /*-----------------------------------------------------------------*/
13779 /* genSystemGetCurrentID - */
13780 /*-----------------------------------------------------------------*/
13781 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
13783 assert (nparms==0);
13785 emitcode ("lcall","System_GetCurrent%sId",name);
13786 /* put result into place */
13788 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13789 if (rsym->liveFrom != rsym->liveTo) {
13790 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13791 aopPut(IC_RESULT(ic),"a",0);
13792 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13797 /*-----------------------------------------------------------------*/
13798 /* genDjnz - generate decrement & jump if not zero instrucion */
13799 /*-----------------------------------------------------------------*/
13801 genDjnz (iCode * ic, iCode * ifx)
13803 symbol *lbl, *lbl1;
13807 /* if the if condition has a false label
13808 then we cannot save */
13809 if (IC_FALSE (ifx))
13812 /* if the minus is not of the form a = a - 1 */
13813 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
13814 !IS_OP_LITERAL (IC_RIGHT (ic)))
13817 if (operandLitValue (IC_RIGHT (ic)) != 1)
13820 /* if the size of this greater than one then no
13822 if (getSize (operandType (IC_RESULT (ic))) > 1)
13825 /* otherwise we can save BIG */
13827 D (emitcode (";", "genDjnz"));
13829 lbl = newiTempLabel (NULL);
13830 lbl1 = newiTempLabel (NULL);
13832 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
13834 if (AOP_NEEDSACC(IC_RESULT(ic)))
13836 /* If the result is accessed indirectly via
13837 * the accumulator, we must explicitly write
13838 * it back after the decrement.
13840 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE, NULL);
13842 if (strcmp(rByte, "a"))
13844 /* Something is hopelessly wrong */
13845 fprintf(stderr, "*** warning: internal error at %s:%d\n",
13846 __FILE__, __LINE__);
13847 /* We can just give up; the generated code will be inefficient,
13848 * but what the hey.
13850 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13853 emitcode ("dec", "%s", rByte);
13854 aopPut (IC_RESULT (ic), rByte, 0);
13855 emitcode ("jnz", "!tlabel", lbl->key + 100);
13857 else if (IS_AOP_PREG (IC_RESULT (ic)))
13859 emitcode ("dec", "%s",
13860 aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL));
13861 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL));
13862 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13863 ifx->generated = 1;
13864 emitcode ("jnz", "!tlabel", lbl->key + 100);
13868 emitcode ("djnz", "%s,!tlabel", aopGet (IC_RESULT (ic), 0, FALSE, TRUE, NULL),
13871 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
13873 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
13876 if (!ifx->generated)
13877 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13878 ifx->generated = 1;
13882 /*-----------------------------------------------------------------*/
13883 /* genReceive - generate code for a receive iCode */
13884 /*-----------------------------------------------------------------*/
13886 genReceive (iCode * ic)
13888 int size = getSize (operandType (IC_RESULT (ic)));
13892 D (emitcode (";", "genReceive"));
13894 if (ic->argreg == 1)
13896 /* first parameter */
13897 if (AOP_IS_STR(IC_RESULT(ic)))
13899 /* Nothing to do: it's already in the proper place. */
13906 useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
13907 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
13908 IS_TRUE_SYMOP (IC_RESULT (ic)));
13911 aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
13914 /* Sanity checking... */
13915 if (AOP_USESDPTR(IC_RESULT(ic)))
13917 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
13918 "genReceive got unexpected DPTR.");
13920 assignResultValue (IC_RESULT (ic), NULL);
13923 else if (ic->argreg > 12)
13924 { /* bit parameters */
13925 if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
13927 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
13928 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
13929 outBitC(IC_RESULT (ic));
13934 /* second receive onwards */
13935 /* this gets a little tricky since unused receives will be
13936 eliminated, we have saved the reg in the type field . and
13937 we use that to figure out which register to use */
13938 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
13939 rb1off = ic->argreg;
13942 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
13945 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13948 /*-----------------------------------------------------------------*/
13949 /* genDummyRead - generate code for dummy read of volatiles */
13950 /*-----------------------------------------------------------------*/
13952 genDummyRead (iCode * ic)
13957 D (emitcode(";", "genDummyRead"));
13959 op = IC_RIGHT (ic);
13960 if (op && IS_SYMOP (op))
13962 aopOp (op, ic, FALSE, FALSE);
13964 /* if the result is a bit */
13965 if (AOP_TYPE (op) == AOP_CRY)
13966 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13969 /* bit variables done */
13971 size = AOP_SIZE (op);
13975 MOVA (aopGet (op, offset, FALSE, FALSE, FALSE));
13980 freeAsmop (op, NULL, ic, TRUE);
13984 if (op && IS_SYMOP (op))
13986 aopOp (op, ic, FALSE, FALSE);
13988 /* if the result is a bit */
13989 if (AOP_TYPE (op) == AOP_CRY)
13990 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13993 /* bit variables done */
13995 size = AOP_SIZE (op);
13999 MOVA (aopGet (op, offset, FALSE, FALSE, FALSE));
14004 freeAsmop (op, NULL, ic, TRUE);
14008 /*-----------------------------------------------------------------*/
14009 /* genCritical - generate code for start of a critical sequence */
14010 /*-----------------------------------------------------------------*/
14012 genCritical (iCode *ic)
14014 symbol *tlbl = newiTempLabel (NULL);
14016 D (emitcode(";", "genCritical"));
14018 if (IC_RESULT (ic))
14020 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
14021 aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
14022 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
14023 aopPut (IC_RESULT (ic), zero, 0);
14025 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
14029 emitcode ("setb", "c");
14030 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
14031 emitcode ("clr", "c");
14033 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
14037 /*-----------------------------------------------------------------*/
14038 /* genEndCritical - generate code for end of a critical sequence */
14039 /*-----------------------------------------------------------------*/
14041 genEndCritical (iCode *ic)
14043 D(emitcode("; genEndCritical",""));
14047 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
14048 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
14050 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
14051 emitcode ("mov", "ea,c");
14055 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE, FALSE));
14056 emitcode ("rrc", "a");
14057 emitcode ("mov", "ea,c");
14059 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
14063 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
14064 emitcode ("mov", "ea,c");
14070 /*-----------------------------------------------------------------*/
14071 /* genBuiltIn - calls the appropriate function to generating code */
14072 /* for a built in function */
14073 /*-----------------------------------------------------------------*/
14074 static void genBuiltIn (iCode *ic)
14076 operand *bi_parms[MAX_BUILTIN_ARGS];
14081 /* get all the arguments for a built in function */
14082 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
14084 /* which function is it */
14085 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
14086 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
14087 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
14088 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
14089 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
14090 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
14091 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
14092 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
14093 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
14094 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
14095 genMemsetX(bi_iCode,nbi_parms,bi_parms);
14096 } else if (strcmp(bif->name,"__builtin_inp")==0) {
14097 genInp(bi_iCode,nbi_parms,bi_parms);
14098 } else if (strcmp(bif->name,"__builtin_outp")==0) {
14099 genOutp(bi_iCode,nbi_parms,bi_parms);
14100 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
14101 genSwapW(bi_iCode,nbi_parms,bi_parms);
14102 /* JavaNative builtIns */
14103 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
14104 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
14105 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
14106 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
14107 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
14108 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
14109 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
14110 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
14111 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
14112 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
14113 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
14114 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
14115 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
14116 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
14117 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
14118 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
14119 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
14120 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
14121 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
14122 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
14123 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
14124 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
14125 } else if (strcmp(bif->name,"MM_Malloc")==0) {
14126 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
14127 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
14128 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
14129 } else if (strcmp(bif->name,"MM_Free")==0) {
14130 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
14131 } else if (strcmp(bif->name,"MM_Deref")==0) {
14132 genMMDeref(bi_iCode,nbi_parms,bi_parms);
14133 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
14134 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
14135 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
14136 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
14137 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
14138 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
14139 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
14140 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
14141 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
14142 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
14143 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
14144 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
14145 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
14146 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
14147 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
14148 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
14149 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
14150 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
14151 } else if (strcmp(bif->name,"System_SaveThread")==0) {
14152 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
14153 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
14154 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
14155 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
14156 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
14157 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
14158 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
14159 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
14160 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
14161 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
14162 genSystem(bi_iCode,nbi_parms,"ProcessYield");
14163 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
14164 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
14165 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
14166 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
14167 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
14168 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
14169 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
14170 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
14171 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
14172 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
14174 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
14180 /*-----------------------------------------------------------------*/
14181 /* gen390Code - generate code for Dallas 390 based controllers */
14182 /*-----------------------------------------------------------------*/
14184 gen390Code (iCode * lic)
14189 _G.currentFunc = NULL;
14190 lineHead = lineCurr = NULL;
14191 dptrn[1][0] = "dpl1";
14192 dptrn[1][1] = "dph1";
14193 dptrn[1][2] = "dpx1";
14195 if (options.model == MODEL_FLAT24) {
14196 fReturnSizeDS390 = 5;
14197 fReturn = fReturn24;
14199 fReturnSizeDS390 = 4;
14200 fReturn = fReturn16;
14201 options.stack10bit=0;
14204 /* print the allocation information */
14205 if (allocInfo && currFunc)
14206 printAllocInfo (currFunc, codeOutBuf);
14208 /* if debug information required */
14209 if (options.debug && currFunc)
14211 debugFile->writeFunction (currFunc, lic);
14213 /* stack pointer name */
14214 if (options.useXstack)
14220 for (ic = lic; ic; ic = ic->next)
14222 _G.current_iCode = ic;
14224 if (ic->lineno && cln != ic->lineno)
14228 debugFile->writeCLine (ic);
14230 if (!options.noCcodeInAsm) {
14231 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
14232 printCLine(ic->filename, ic->lineno));
14236 if (options.iCodeInAsm) {
14237 char *iLine = printILine(ic);
14238 emitcode("", ";ic:%d: %s", ic->key, iLine);
14241 /* if the result is marked as
14242 spilt and rematerializable or code for
14243 this has already been generated then
14245 if (resultRemat (ic) || ic->generated)
14248 /* depending on the operation */
14268 /* IPOP happens only when trying to restore a
14269 spilt live range, if there is an ifx statement
14270 following this pop then the if statement might
14271 be using some of the registers being popped which
14272 would destory the contents of the register so
14273 we need to check for this condition and handle it */
14275 ic->next->op == IFX &&
14276 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
14277 genIfx (ic->next, ic);
14295 genEndFunction (ic);
14315 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
14332 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
14336 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
14343 /* note these two are xlated by algebraic equivalence
14344 during parsing SDCC.y */
14345 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
14346 "got '>=' or '<=' shouldn't have come here");
14350 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
14362 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
14366 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
14370 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
14394 genRightShift (ic);
14397 case GET_VALUE_AT_ADDRESS:
14399 hasInc (IC_LEFT (ic), ic,
14400 getSize (operandType (IC_RESULT (ic)))));
14404 if (POINTER_SET (ic))
14406 hasInc (IC_RESULT (ic), ic,
14407 getSize (operandType (IC_RIGHT (ic)))));
14433 if (ic->builtinSEND)
14436 addSet (&_G.sendSet, ic);
14439 case DUMMY_READ_VOLATILE:
14448 genEndCritical (ic);
14455 #if 0 // obsolete, and buggy for != xdata
14467 /* now we are ready to call the
14468 peep hole optimizer */
14469 if (!options.nopeep)
14470 peepHole (&lineHead);
14472 /* now do the actual printing */
14473 printLine (lineHead, codeOutBuf);