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 /*-----------------------------------------------------------------*/
3359 /* inExcludeList - return 1 if the string is in exclude Reg list */
3360 /*-----------------------------------------------------------------*/
3362 regsCmp(void *p1, void *p2)
3364 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3368 inExcludeList (char *s)
3370 const char *p = setFirstItem(options.excludeRegsSet);
3372 if (p == NULL || STRCASECMP(p, "none") == 0)
3376 return isinSetWith(options.excludeRegsSet, s, regsCmp);
3379 /*-----------------------------------------------------------------*/
3380 /* genFunction - generated code for function entry */
3381 /*-----------------------------------------------------------------*/
3383 genFunction (iCode * ic)
3385 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3387 bool switchedPSW = FALSE;
3388 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3390 D (emitcode (";", "genFunction"));
3393 /* create the function header */
3394 emitcode (";", "-----------------------------------------");
3395 emitcode (";", " function %s", sym->name);
3396 emitcode (";", "-----------------------------------------");
3398 emitcode ("", "%s:", sym->rname);
3399 lineCurr->isLabel = 1;
3400 ftype = operandType (IC_LEFT (ic));
3401 _G.currentFunc = sym;
3403 if (IFFUNC_ISNAKED(ftype))
3405 emitcode(";", "naked function: no prologue.");
3409 if (options.stack_probe)
3410 emitcode ("lcall","__stack_probe");
3412 /* here we need to generate the equates for the
3413 register bank if required */
3414 if (FUNC_REGBANK (ftype) != rbank)
3418 rbank = FUNC_REGBANK (ftype);
3419 for (i = 0; i < ds390_nRegs; i++)
3421 if (regs390[i].print) {
3422 if (strcmp (regs390[i].base, "0") == 0)
3423 emitcode ("", "%s !equ !constbyte",
3425 8 * rbank + regs390[i].offset);
3427 emitcode ("", "%s !equ %s + !constbyte",
3430 8 * rbank + regs390[i].offset);
3435 /* if this is an interrupt service routine then
3436 save acc, b, dpl, dph */
3437 if (IFFUNC_ISISR (sym->type))
3439 if (!inExcludeList ("acc"))
3440 emitcode ("push", "acc");
3441 if (!inExcludeList ("b"))
3442 emitcode ("push", "b");
3443 if (!inExcludeList ("dpl"))
3444 emitcode ("push", "dpl");
3445 if (!inExcludeList ("dph"))
3446 emitcode ("push", "dph");
3447 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3449 emitcode ("push", "dpx");
3450 /* Make sure we're using standard DPTR */
3451 emitcode ("push", "dps");
3452 emitcode ("mov", "dps,#0");
3453 if (options.stack10bit)
3455 /* This ISR could conceivably use DPTR2. Better save it. */
3456 emitcode ("push", "dpl1");
3457 emitcode ("push", "dph1");
3458 emitcode ("push", "dpx1");
3459 emitcode ("push", DP2_RESULT_REG);
3462 /* if this isr has no bank i.e. is going to
3463 run with bank 0 , then we need to save more
3465 if (!FUNC_REGBANK (sym->type))
3469 /* if this function does not call any other
3470 function then we can be economical and
3471 save only those registers that are used */
3472 if (!IFFUNC_HASFCALL(sym->type))
3474 /* if any registers used */
3477 bool bits_pushed = FALSE;
3478 /* save the registers used */
3479 for (i = 0; i < sym->regsUsed->size; i++)
3481 if (bitVectBitValue (sym->regsUsed, i))
3482 bits_pushed = pushReg (i, bits_pushed);
3488 /* this function has a function call. We cannot
3489 determine register usage so we will have to push the
3491 saveRBank (0, ic, FALSE);
3492 if (options.parms_in_bank1) {
3493 for (i=0; i < 8 ; i++ ) {
3494 emitcode ("push","%s",rb1regs[i]);
3501 /* This ISR uses a non-zero bank.
3503 * We assume that the bank is available for our
3506 * However, if this ISR calls a function which uses some
3507 * other bank, we must save that bank entirely.
3509 unsigned long banksToSave = 0;
3511 if (IFFUNC_HASFCALL(sym->type))
3514 #define MAX_REGISTER_BANKS 4
3519 for (i = ic; i; i = i->next)
3521 if (i->op == ENDFUNCTION)
3523 /* we got to the end OK. */
3531 dtype = operandType (IC_LEFT(i));
3533 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3535 /* Mark this bank for saving. */
3536 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3538 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3542 banksToSave |= (1 << FUNC_REGBANK(dtype));
3545 /* And note that we don't need to do it in
3553 /* This is a mess; we have no idea what
3554 * register bank the called function might
3557 * The only thing I can think of to do is
3558 * throw a warning and hope.
3560 werror(W_FUNCPTR_IN_USING_ISR);
3564 if (banksToSave && options.useXstack)
3566 /* Since we aren't passing it an ic,
3567 * saveRBank will assume r0 is available to abuse.
3569 * So switch to our (trashable) bank now, so
3570 * the caller's R0 isn't trashed.
3572 emitcode ("push", "psw");
3573 emitcode ("mov", "psw,#!constbyte",
3574 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3578 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3580 if (banksToSave & (1 << ix))
3582 saveRBank(ix, NULL, FALSE);
3586 // TODO: this needs a closer look
3587 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3592 /* if callee-save to be used for this function
3593 then save the registers being used in this function */
3594 if (IFFUNC_CALLEESAVES(sym->type))
3598 /* if any registers used */
3601 bool bits_pushed = FALSE;
3602 /* save the registers used */
3603 for (i = 0; i < sym->regsUsed->size; i++)
3605 if (bitVectBitValue (sym->regsUsed, i))
3607 bits_pushed = pushReg (i, bits_pushed);
3615 /* set the register bank to the desired value */
3616 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3619 emitcode ("push", "psw");
3620 emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3624 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3625 if (options.stack10bit) {
3626 emitcode ("push","_bpx");
3627 emitcode ("push","_bpx+1");
3628 emitcode ("mov","_bpx,%s",spname);
3629 emitcode ("mov","_bpx+1,esp");
3630 adjustEsp("_bpx+1");
3632 if (options.useXstack)
3634 emitcode ("mov", "r0,%s", spname);
3635 emitcode ("mov", "a,_bp");
3636 emitcode ("movx", "@r0,a");
3637 emitcode ("inc", "%s", spname);
3639 /* set up the stack */
3640 emitcode ("push", "_bp"); /* save the callers stack */
3642 emitcode ("mov", "_bp,%s", spname);
3646 /* adjust the stack for the function */
3649 if (options.stack10bit) {
3650 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
3651 assert (sym->recvSize <= 4);
3652 if (sym->stack <= 8) {
3653 while (i--) emitcode ("push","acc");
3656 emitcode ("mov","a,sp");
3657 emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3658 emitcode ("mov","sp,a");
3659 emitcode ("mov","a,esp");
3661 emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3662 emitcode ("mov","esp,a");
3667 werror (W_STACK_OVERFLOW, sym->name);
3669 if (i > 3 && sym->recvSize < 4) {
3671 emitcode ("mov", "a,sp");
3672 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3673 emitcode ("mov", "sp,a");
3677 emitcode ("inc", "sp");
3684 emitcode ("mov", "a,_spx");
3685 emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3686 emitcode ("mov", "_spx,a");
3689 /* if critical function then turn interrupts off */
3690 if (IFFUNC_ISCRITICAL (ftype))
3692 symbol *tlbl = newiTempLabel (NULL);
3693 emitcode ("setb", "c");
3694 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3695 emitcode ("clr", "c");
3697 emitcode ("push", "psw"); /* save old ea via c in psw */
3701 /*-----------------------------------------------------------------*/
3702 /* genEndFunction - generates epilogue for functions */
3703 /*-----------------------------------------------------------------*/
3705 genEndFunction (iCode * ic)
3707 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3708 lineNode *lnp = lineCurr;
3710 bitVect *regsUsedPrologue;
3711 bitVect *regsUnneeded;
3714 D (emitcode (";", "genEndFunction"));
3716 _G.currentFunc = NULL;
3717 if (IFFUNC_ISNAKED(sym->type))
3719 emitcode(";", "naked function: no epilogue.");
3720 if (options.debug && currFunc)
3721 debugFile->writeEndFunction (currFunc, ic, 0);
3725 if (IFFUNC_ISCRITICAL (sym->type))
3727 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3729 emitcode ("rlc", "a"); /* save c in a */
3730 emitcode ("pop", "psw"); /* restore ea via c in psw */
3731 emitcode ("mov", "ea,c");
3732 emitcode ("rrc", "a"); /* restore c from a */
3736 emitcode ("pop", "psw"); /* restore ea via c in psw */
3737 emitcode ("mov", "ea,c");
3741 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3742 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3744 if (options.stack10bit) {
3746 emitcode ("mov", "sp,_bpx", spname);
3747 emitcode ("mov", "esp,_bpx+1", spname);
3750 emitcode ("mov", "%s,_bp", spname);
3754 /* if use external stack but some variables were
3755 added to the local stack then decrement the
3757 if (options.useXstack && sym->stack) {
3758 emitcode ("mov", "a,sp");
3759 emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3760 emitcode ("mov", "sp,a");
3764 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3765 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3767 if (options.useXstack) {
3768 emitcode ("mov", "r0,%s", spname);
3769 emitcode ("movx", "a,@r0");
3770 emitcode ("mov", "_bp,a");
3771 emitcode ("dec", "%s", spname);
3773 if (options.stack10bit) {
3774 emitcode ("pop", "_bpx+1");
3775 emitcode ("pop", "_bpx");
3777 emitcode ("pop", "_bp");
3782 /* restore the register bank */
3783 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3785 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3786 || !options.useXstack)
3788 /* Special case of ISR using non-zero bank with useXstack
3791 emitcode ("pop", "psw");
3795 if (IFFUNC_ISISR (sym->type))
3798 /* now we need to restore the registers */
3799 /* if this isr has no bank i.e. is going to
3800 run with bank 0 , then we need to save more
3802 if (!FUNC_REGBANK (sym->type))
3805 /* if this function does not call any other
3806 function then we can be economical and
3807 save only those registers that are used */
3808 if (!IFFUNC_HASFCALL(sym->type))
3810 /* if any registers used */
3813 bool bits_popped = FALSE;
3814 /* save the registers used */
3815 for (i = sym->regsUsed->size; i >= 0; i--)
3817 if (bitVectBitValue (sym->regsUsed, i))
3818 bits_popped = popReg (i, bits_popped);
3824 /* this function has a function call. We cannot
3825 determine register usage so we will have to pop the
3827 if (options.parms_in_bank1) {
3828 for (i = 7 ; i >= 0 ; i-- ) {
3829 emitcode ("pop","%s",rb1regs[i]);
3832 unsaveRBank (0, ic, FALSE);
3837 /* This ISR uses a non-zero bank.
3839 * Restore any register banks saved by genFunction
3842 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3845 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3847 if (savedBanks & (1 << ix))
3849 unsaveRBank(ix, NULL, FALSE);
3853 if (options.useXstack)
3855 /* Restore bank AFTER calling unsaveRBank,
3856 * since it can trash r0.
3858 emitcode ("pop", "psw");
3862 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3864 if (options.stack10bit)
3866 emitcode ("pop", DP2_RESULT_REG);
3867 emitcode ("pop", "dpx1");
3868 emitcode ("pop", "dph1");
3869 emitcode ("pop", "dpl1");
3871 emitcode ("pop", "dps");
3872 emitcode ("pop", "dpx");
3874 if (!inExcludeList ("dph"))
3875 emitcode ("pop", "dph");
3876 if (!inExcludeList ("dpl"))
3877 emitcode ("pop", "dpl");
3878 if (!inExcludeList ("b"))
3879 emitcode ("pop", "b");
3880 if (!inExcludeList ("acc"))
3881 emitcode ("pop", "acc");
3883 /* if debug then send end of function */
3884 if (options.debug && currFunc)
3886 debugFile->writeEndFunction (currFunc, ic, 1);
3889 emitcode ("reti", "");
3893 if (IFFUNC_CALLEESAVES(sym->type))
3897 /* if any registers used */
3900 /* save the registers used */
3901 for (i = sym->regsUsed->size; i >= 0; i--)
3903 if (bitVectBitValue (sym->regsUsed, i))
3904 emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
3909 /* if debug then send end of function */
3910 if (options.debug && currFunc)
3912 debugFile->writeEndFunction (currFunc, ic, 1);
3915 emitcode ("ret", "");
3918 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3921 /* If this was an interrupt handler using bank 0 that called another */
3922 /* function, then all registers must be saved; nothing to optimized. */
3923 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3924 && !FUNC_REGBANK(sym->type))
3927 /* There are no push/pops to optimize if not callee-saves or ISR */
3928 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3931 /* If there were stack parameters, we cannot optimize without also */
3932 /* fixing all of the stack offsets; this is too dificult to consider. */
3933 if (FUNC_HASSTACKPARM(sym->type))
3936 /* Compute the registers actually used */
3937 regsUsed = newBitVect (ds390_nRegs);
3938 regsUsedPrologue = newBitVect (ds390_nRegs);
3941 if (lnp->ic && lnp->ic->op == FUNCTION)
3942 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3944 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3946 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3947 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3954 if (bitVectBitValue (regsUsedPrologue, DPS_IDX)
3955 && !bitVectBitValue (regsUsed, DPS_IDX))
3957 bitVectUnSetBit (regsUsedPrologue, DPS_IDX);
3960 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3961 && !bitVectBitValue (regsUsed, CND_IDX))
3963 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3964 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3965 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3966 bitVectUnSetBit (regsUsed, CND_IDX);
3969 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3971 /* If this was an interrupt handler that called another function */
3972 /* function, then assume working registers may be modified by it. */
3973 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3975 regsUsed = bitVectSetBit (regsUsed, AP_IDX);
3976 regsUsed = bitVectSetBit (regsUsed, DPX1_IDX);
3977 regsUsed = bitVectSetBit (regsUsed, DPL1_IDX);
3978 regsUsed = bitVectSetBit (regsUsed, DPH1_IDX);
3979 regsUsed = bitVectSetBit (regsUsed, DPX_IDX);
3980 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3981 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3982 regsUsed = bitVectSetBit (regsUsed, DPS_IDX);
3983 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3984 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3985 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3988 /* Remove the unneeded push/pops */
3989 regsUnneeded = newBitVect (ds390_nRegs);
3992 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3994 if (!strncmp(lnp->line, "push", 4))
3996 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3997 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3999 connectLine (lnp->prev, lnp->next);
4000 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4003 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
4005 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
4006 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4008 connectLine (lnp->prev, lnp->next);
4009 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4016 for (idx = 0; idx < regsUnneeded->size; idx++)
4017 if (bitVectBitValue (regsUnneeded, idx))
4018 emitcode (";", "eliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
4020 freeBitVect (regsUnneeded);
4021 freeBitVect (regsUsed);
4022 freeBitVect (regsUsedPrologue);
4025 /*-----------------------------------------------------------------*/
4026 /* genJavaNativeRet - generate code for return JavaNative */
4027 /*-----------------------------------------------------------------*/
4028 static void genJavaNativeRet(iCode *ic)
4032 aopOp (IC_LEFT (ic), ic, FALSE,
4033 AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
4034 size = AOP_SIZE (IC_LEFT (ic));
4038 /* it is assigned to GPR0-R3 then push them */
4039 if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
4040 aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
4041 for (i = 0 ; i < size ; i++ ) {
4042 emitcode ("push","%s",
4043 aopGet(IC_LEFT(ic),i,FALSE,TRUE,DP2_RESULT_REG));
4045 for (i = (size-1) ; i >= 0 ; i--) {
4046 emitcode ("pop","a%s",javaRet[i]);
4049 for (i = 0 ; i < size ; i++)
4050 emitcode ("mov","%s,%s",javaRet[i],
4051 aopGet(IC_LEFT(ic),i,FALSE,TRUE,DP2_RESULT_REG));
4053 for (i = size ; i < 4 ; i++ )
4054 emitcode ("mov","%s,#0",javaRet[i]);
4058 /*-----------------------------------------------------------------*/
4059 /* genRet - generate code for return statement */
4060 /*-----------------------------------------------------------------*/
4064 int size, offset = 0, pushed = 0;
4066 D (emitcode (";", "genRet"));
4068 /* if we have no return value then
4069 just generate the "ret" */
4073 /* if this is a JavaNative function then return
4074 value in different register */
4075 if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
4076 genJavaNativeRet(ic);
4079 /* we have something to return then
4080 move the return value into place */
4081 aopOp (IC_LEFT (ic), ic, FALSE,
4082 (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
4083 size = AOP_SIZE (IC_LEFT (ic));
4085 _startLazyDPSEvaluation ();
4087 if (IS_BIT(_G.currentFunc->etype))
4089 movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4096 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
4098 l = aopGet (IC_LEFT (ic), offset++,
4100 emitcode ("push", "%s", l);
4105 /* Since A is the last element of fReturn,
4106 * it is OK to clobber it in the aopGet.
4108 l = aopGet (IC_LEFT (ic), offset,
4109 FALSE, FALSE, NULL);
4110 if (strcmp (fReturn[offset], l))
4111 emitcode ("mov", "%s,%s", fReturn[offset++], l);
4114 _endLazyDPSEvaluation ();
4119 if (strcmp (fReturn[pushed], "a"))
4120 emitcode ("pop", fReturn[pushed]);
4122 emitcode ("pop", "acc");
4124 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
4127 /* generate a jump to the return label
4128 if the next is not the return statement */
4129 if (!(ic->next && ic->next->op == LABEL &&
4130 IC_LABEL (ic->next) == returnLabel))
4132 emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
4136 /*-----------------------------------------------------------------*/
4137 /* genLabel - generates a label */
4138 /*-----------------------------------------------------------------*/
4140 genLabel (iCode * ic)
4142 /* special case never generate */
4143 if (IC_LABEL (ic) == entryLabel)
4146 D (emitcode (";", "genLabel"));
4148 emitLabel (IC_LABEL (ic));
4151 /*-----------------------------------------------------------------*/
4152 /* genGoto - generates a ljmp */
4153 /*-----------------------------------------------------------------*/
4155 genGoto (iCode * ic)
4157 D (emitcode (";", "genGoto"));
4159 emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
4162 /*-----------------------------------------------------------------*/
4163 /* findLabelBackwards: walks back through the iCode chain looking */
4164 /* for the given label. Returns number of iCode instructions */
4165 /* between that label and given ic. */
4166 /* Returns zero if label not found. */
4167 /*-----------------------------------------------------------------*/
4169 findLabelBackwards (iCode * ic, int key)
4178 /* If we have any pushes or pops, we cannot predict the distance.
4179 I don't like this at all, this should be dealt with in the
4181 if (ic->op == IPUSH || ic->op == IPOP) {
4185 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4187 /* printf("findLabelBackwards = %d\n", count); */
4195 /*-----------------------------------------------------------------*/
4196 /* genPlusIncr :- does addition with increment if possible */
4197 /*-----------------------------------------------------------------*/
4199 genPlusIncr (iCode * ic)
4201 unsigned int icount;
4202 unsigned int size = getDataSize (IC_RESULT (ic));
4204 /* will try to generate an increment */
4205 /* if the right side is not a literal
4207 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4210 /* if the literal value of the right hand side
4211 is greater than 4 then it is not worth it */
4212 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4215 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4216 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4218 emitcode("inc","%s",aopGet(IC_RESULT(ic),0,FALSE,FALSE,NULL));
4222 /* if increment 16 bits in register */
4224 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4225 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4226 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4235 /* If the next instruction is a goto and the goto target
4236 * is <= 5 instructions previous to this, we can generate
4237 * jumps straight to that target.
4239 if (ic->next && ic->next->op == GOTO
4240 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4243 D (emitcode (";", "tail increment optimized (range %d)", labelRange));
4244 tlbl = IC_LABEL (ic->next);
4249 tlbl = newiTempLabel (NULL);
4252 l = aopGet (IC_RESULT (ic), LSB, FALSE, FALSE, NULL);
4253 emitcode ("inc", "%s", l);
4255 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4256 IS_AOP_PREG (IC_RESULT (ic)))
4258 emitcode ("cjne", "%s,%s,!tlabel", l, zero, tlbl->key + 100);
4262 emitcode ("clr", "a");
4263 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4266 l = aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE, NULL);
4267 emitcode ("inc", "%s", l);
4270 if (!strcmp(l, "acc"))
4272 emitcode("jnz", "!tlabel", tlbl->key + 100);
4274 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4275 IS_AOP_PREG (IC_RESULT (ic)))
4277 emitcode ("cjne", "%s,%s,!tlabel", l, zero, tlbl->key + 100);
4281 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4284 l = aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE, NULL);
4285 emitcode ("inc", "%s", l);
4289 if (!strcmp(l, "acc"))
4291 emitcode("jnz", "!tlabel", tlbl->key + 100);
4293 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4294 IS_AOP_PREG (IC_RESULT (ic)))
4296 emitcode ("cjne", "%s,%s,!tlabel", l, zero, tlbl->key + 100);
4300 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4303 l = aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE, NULL);
4304 emitcode ("inc", "%s", l);
4314 if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
4315 !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 &&
4316 options.model == MODEL_FLAT24 )
4318 if (IC_RESULT(ic)->isGptr)
4320 emitcode ("mov", "b,%s", aopGet(IC_LEFT (ic), 3, FALSE, FALSE, NULL));
4324 emitcode ("mov", "dpx,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE, NULL));
4326 emitcode ("mov", "dph,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE, NULL));
4328 emitcode ("mov", "dpl,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4332 emitcode ("inc", "dptr");
4336 if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
4337 AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
4339 emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
4341 emitcode ("inc", "dptr");
4342 emitcode ("mov", "dps,#0");
4346 /* if the sizes are greater than 1 then we cannot */
4347 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4348 AOP_SIZE (IC_LEFT (ic)) > 1)
4351 /* we can if the aops of the left & result match or
4352 if they are in registers and the registers are the
4355 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4356 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4357 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4361 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4362 emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
4363 aopPut (IC_RESULT (ic), "a", 0);
4367 _startLazyDPSEvaluation ();
4370 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4372 _endLazyDPSEvaluation ();
4381 /*-----------------------------------------------------------------*/
4382 /* outBitAcc - output a bit in acc */
4383 /*-----------------------------------------------------------------*/
4385 outBitAcc (operand * result)
4387 symbol *tlbl = newiTempLabel (NULL);
4388 /* if the result is a bit */
4389 if (AOP_TYPE (result) == AOP_CRY)
4391 aopPut (result, "a", 0);
4395 emitcode ("jz", "!tlabel", tlbl->key + 100);
4396 emitcode ("mov", "a,%s", one);
4402 /*-----------------------------------------------------------------*/
4403 /* genPlusBits - generates code for addition of two bits */
4404 /*-----------------------------------------------------------------*/
4406 genPlusBits (iCode * ic)
4408 D (emitcode (";", "genPlusBits"));
4410 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4412 symbol *lbl = newiTempLabel (NULL);
4413 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4414 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4415 emitcode ("cpl", "c");
4417 outBitC (IC_RESULT (ic));
4421 emitcode ("clr", "a");
4422 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4423 emitcode ("rlc", "a");
4424 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4425 emitcode ("addc", "a,%s", zero);
4426 outAcc (IC_RESULT (ic));
4431 adjustArithmeticResult (iCode * ic)
4433 if (opIsGptr (IC_RESULT (ic)) &&
4434 opIsGptr (IC_LEFT (ic)) &&
4435 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4437 aopPut (IC_RESULT (ic),
4438 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE, NULL),
4442 if (opIsGptr (IC_RESULT (ic)) &&
4443 opIsGptr (IC_RIGHT (ic)) &&
4444 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4446 aopPut (IC_RESULT (ic),
4447 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE, NULL),
4451 if (opIsGptr (IC_RESULT (ic)) &&
4452 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4453 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4454 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4455 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4458 SNPRINTF (buffer, sizeof(buffer),
4459 "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4460 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4464 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
4465 // generates the result if possible. If result is generated, returns TRUE; otherwise
4466 // returns false and caller must deal with fact that result isn't aopOp'd.
4467 bool aopOp3(iCode * ic)
4469 bool dp1InUse, dp2InUse;
4472 // First, generate the right opcode. DPTR may be used if neither left nor result are
4475 // D (emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
4476 // AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
4477 // AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
4478 // AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
4480 // D (emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
4481 // AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
4482 // AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
4483 // AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
4486 // Right uses DPTR unless left or result is an AOP_STR; however,
4487 // if right is an AOP_STR, it must use DPTR regardless.
4488 if ((AOP_IS_STR (IC_LEFT (ic)) || AOP_IS_STR (IC_RESULT (ic)))
4489 && !AOP_IS_STR (IC_RIGHT (ic)))
4498 aopOp (IC_RIGHT(ic), ic, FALSE, useDp2);
4500 // if the right used DPTR, left MUST use DPTR2.
4501 // if the right used DPTR2, left MUST use DPTR.
4502 // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
4503 // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
4504 // enabling us to assign DPTR to result.
4506 if (AOP_USESDPTR (IC_RIGHT (ic)))
4510 else if (AOP_USESDPTR2 (IC_RIGHT (ic)))
4516 if (AOP_IS_STR (IC_RESULT (ic)) && !AOP_IS_STR (IC_LEFT (ic)))
4526 aopOp (IC_LEFT (ic), ic, FALSE, useDp2);
4529 // We've op'd the left & right. So, if left or right are the same operand as result,
4530 // we know aopOp will succeed, and we can just do it & bail.
4531 if (isOperandEqual (IC_LEFT (ic), IC_RESULT (ic)))
4533 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4536 if (isOperandEqual (IC_RIGHT (ic), IC_RESULT (ic)))
4538 // D (emitcode(";", "aopOp3: (left | right) & result equal"));
4539 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4543 // Operands may be equivalent (but not equal) if they share a spill location. If
4544 // so, use the same DPTR or DPTR2.
4545 if (operandsEqu (IC_LEFT (ic), IC_RESULT (ic)))
4547 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4550 if (operandsEqu (IC_RIGHT (ic), IC_RESULT (ic)))
4552 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4556 // Note which dptrs are currently in use.
4557 dp1InUse = AOP_USESDPTR (IC_LEFT (ic)) || AOP_USESDPTR (IC_RIGHT (ic));
4558 dp2InUse = AOP_USESDPTR2 (IC_LEFT (ic)) || AOP_USESDPTR2 (IC_RIGHT (ic));
4560 // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot
4562 if (dp1InUse && AOP_IS_STR (IC_RESULT (ic)))
4567 // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
4568 if (dp2InUse && AOP_IS_DPTRn (IC_RESULT (ic)))
4573 // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck
4574 if (dp1InUse && dp2InUse && isOperandInFarSpace (IC_RESULT (ic)))
4579 aopOp (IC_RESULT (ic), ic, TRUE, dp1InUse);
4581 // Some sanity checking...
4582 if (dp1InUse && AOP_USESDPTR (IC_RESULT (ic)))
4585 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
4586 __FILE__, __LINE__, ic->filename, ic->lineno);
4587 emitcode(";", ">>> unexpected DPTR here.");
4590 if (dp2InUse && AOP_USESDPTR2 (IC_RESULT (ic)))
4593 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
4594 __FILE__, __LINE__, ic->filename, ic->lineno);
4595 emitcode(";", ">>> unexpected DPTR2 here.");
4601 // Macro to aopOp all three operands of an ic. If this cannot be done,
4602 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
4603 // will be set TRUE. The caller must then handle the case specially, noting
4604 // that the IC_RESULT operand is not aopOp'd.
4606 #define AOP_OP_3_NOFATAL(ic, rc) \
4607 do { rc = !aopOp3(ic); } while (0)
4609 // aopOp the left & right operands of an ic.
4610 #define AOP_OP_2(ic) \
4611 aopOp (IC_RIGHT (ic), ic, FALSE, AOP_IS_STR (IC_LEFT (ic))); \
4612 aopOp (IC_LEFT (ic), ic, FALSE, AOP_USESDPTR (IC_RIGHT (ic)));
4614 // convienience macro.
4615 #define AOP_SET_LOCALS(ic) \
4616 left = IC_LEFT(ic); \
4617 right = IC_RIGHT(ic); \
4618 result = IC_RESULT(ic);
4621 // Given an integer value of pushedSize bytes on the stack,
4622 // adjust it to be resultSize bytes, either by discarding
4623 // the most significant bytes or by zero-padding.
4625 // On exit from this macro, pushedSize will have been adjusted to
4626 // equal resultSize, and ACC may be trashed.
4627 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
4628 /* If the pushed data is bigger than the result, \
4629 * simply discard unused bytes. Icky, but works. \
4631 while (pushedSize > resultSize) \
4633 D (emitcode (";", "discarding unused result byte.")); \
4634 emitcode ("pop", "acc"); \
4637 if (pushedSize < resultSize) \
4639 emitcode ("clr", "a"); \
4640 /* Conversly, we haven't pushed enough here. \
4641 * just zero-pad, and all is well. \
4643 while (pushedSize < resultSize) \
4645 emitcode("push", "acc"); \
4649 assert(pushedSize == resultSize);
4651 /*-----------------------------------------------------------------*/
4652 /* genPlus - generates code for addition */
4653 /*-----------------------------------------------------------------*/
4655 genPlus (iCode * ic)
4657 int size, offset = 0;
4660 bool swappedLR = FALSE;
4662 D (emitcode (";", "genPlus"));
4664 /* special cases :- */
4665 if ( AOP_IS_STR (IC_LEFT (ic)) &&
4666 isOperandLiteral (IC_RIGHT (ic)) && OP_SYMBOL (IC_RESULT (ic))->ruonly) {
4667 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
4668 size = (int)floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4670 while (size--) emitcode ("inc","dptr");
4672 emitcode ("mov", "a,dpl");
4673 emitcode ("add", "a,#!constbyte", size & 0xff);
4674 emitcode ("mov", "dpl,a");
4675 emitcode ("mov", "a,dph");
4676 emitcode ("addc", "a,#!constbyte", (size >> 8) & 0xff);
4677 emitcode ("mov", "dph,a");
4678 emitcode ("mov", "a,dpx");
4679 emitcode ("addc", "a,#!constbyte", (size >> 16) & 0xff);
4680 emitcode ("mov", "dpx,a");
4682 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4685 if ( IS_SYMOP (IC_LEFT (ic)) &&
4686 OP_SYMBOL (IC_LEFT (ic))->remat &&
4687 isOperandInFarSpace (IC_RIGHT (ic))) {
4688 operand *op = IC_RIGHT(ic);
4689 IC_RIGHT(ic) = IC_LEFT(ic);
4693 AOP_OP_3_NOFATAL (ic, pushResult);
4697 D (emitcode (";", "genPlus: must push result: 3 ops in far space"));
4702 /* if literal, literal on the right or
4703 if left requires ACC or right is already
4705 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4706 ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic)))) ||
4707 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4709 operand *t = IC_RIGHT (ic);
4710 IC_RIGHT (ic) = IC_LEFT (ic);
4713 D (emitcode (";", "Swapped plus args."));
4716 /* if both left & right are in bit
4718 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4719 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4725 /* if left in bit space & right literal */
4726 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4727 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4729 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4730 /* if result in bit space */
4731 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4733 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4734 emitcode ("cpl", "c");
4735 outBitC (IC_RESULT (ic));
4739 size = getDataSize (IC_RESULT (ic));
4740 _startLazyDPSEvaluation ();
4743 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4744 emitcode ("addc", "a,%s", zero);
4745 aopPut (IC_RESULT (ic), "a", offset++);
4747 _endLazyDPSEvaluation ();
4752 /* if I can do an increment instead
4753 of add then GOOD for ME */
4754 if (genPlusIncr (ic) == TRUE)
4756 D (emitcode (";", "did genPlusIncr"));
4761 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4763 _startLazyDPSEvaluation ();
4766 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4768 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
4770 emitcode ("add", "a,%s",
4771 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4773 emitcode ("addc", "a,%s",
4774 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4778 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4780 /* right is going to use ACC or we would have taken the
4783 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4785 D(emitcode(";", "+ AOP_ACC special case."););
4786 emitcode("xch", "a, %s", DP2_RESULT_REG);
4788 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4791 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4794 emitcode("add", "a, %s", DP2_RESULT_REG);
4798 emitcode ("add", "a,%s",
4799 aopGet (IC_LEFT(ic), offset, FALSE, FALSE,
4805 emitcode ("addc", "a,%s",
4806 aopGet (IC_LEFT (ic), offset, FALSE, FALSE,
4812 aopPut (IC_RESULT (ic), "a", offset);
4816 emitcode ("push", "acc");
4820 _endLazyDPSEvaluation ();
4824 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4826 size = getDataSize (IC_LEFT (ic));
4827 rSize = getDataSize (IC_RESULT (ic));
4829 ADJUST_PUSHED_RESULT(size, rSize);
4831 _startLazyDPSEvaluation ();
4834 emitcode ("pop", "acc");
4835 aopPut (IC_RESULT (ic), "a", size);
4837 _endLazyDPSEvaluation ();
4840 adjustArithmeticResult (ic);
4843 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4846 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4847 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4851 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4852 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4856 /*-----------------------------------------------------------------*/
4857 /* genMinusDec :- does subtraction with decrement if possible */
4858 /*-----------------------------------------------------------------*/
4860 genMinusDec (iCode * ic)
4862 unsigned int icount;
4863 unsigned int size = getDataSize (IC_RESULT (ic));
4865 /* will try to generate an increment */
4866 /* if the right side is not a literal
4868 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4871 /* if the literal value of the right hand side
4872 is greater than 4 then it is not worth it */
4873 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4876 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4877 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4879 emitcode("dec","%s",aopGet(IC_RESULT(ic),0,FALSE,FALSE,NULL));
4883 /* if decrement 16 bits in register */
4884 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4885 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4886 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4895 /* If the next instruction is a goto and the goto target
4896 * is <= 5 instructions previous to this, we can generate
4897 * jumps straight to that target.
4899 if (ic->next && ic->next->op == GOTO
4900 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4903 D (emitcode (";", "tail decrement optimized (range %d)", labelRange));
4904 tlbl = IC_LABEL (ic->next);
4909 tlbl = newiTempLabel (NULL);
4913 l = aopGet (IC_RESULT (ic), LSB, FALSE, FALSE, NULL);
4914 emitcode ("dec", "%s", l);
4916 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4917 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4918 IS_AOP_PREG (IC_RESULT (ic)))
4920 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4924 emitcode ("mov", "a,#!constbyte",0xff);
4925 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4927 l = aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE, NULL);
4928 emitcode ("dec", "%s", l);
4931 if (!strcmp(l, "acc"))
4933 emitcode("jnz", "!tlabel", tlbl->key + 100);
4935 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4936 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4937 IS_AOP_PREG (IC_RESULT (ic)))
4939 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4943 emitcode ("mov", "a,#!constbyte",0xff);
4944 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4946 l = aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE, NULL);
4947 emitcode ("dec", "%s", l);
4951 if (!strcmp(l, "acc"))
4953 emitcode("jnz", "!tlabel", tlbl->key + 100);
4955 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4956 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4957 IS_AOP_PREG (IC_RESULT (ic)))
4959 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4963 emitcode ("mov", "a,#!constbyte",0xff);
4964 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4966 l = aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE, NULL);
4967 emitcode ("dec", "%s", l);
4976 /* if the sizes are greater than 1 then we cannot */
4977 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4978 AOP_SIZE (IC_LEFT (ic)) > 1)
4981 /* we can if the aops of the left & result match or
4982 if they are in registers and the registers are the
4985 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4986 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4987 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4991 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4993 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL));
4998 l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL);
5001 _startLazyDPSEvaluation ();
5004 emitcode ("dec", "%s", l);
5006 _endLazyDPSEvaluation ();
5008 if (AOP_NEEDSACC (IC_RESULT (ic)))
5009 aopPut (IC_RESULT (ic), "a", 0);
5017 /*-----------------------------------------------------------------*/
5018 /* addSign - complete with sign */
5019 /*-----------------------------------------------------------------*/
5021 addSign (operand * result, int offset, int sign)
5023 int size = (getDataSize (result) - offset);
5026 _startLazyDPSEvaluation();
5029 emitcode ("rlc", "a");
5030 emitcode ("subb", "a,acc");
5033 aopPut (result, "a", offset++);
5040 aopPut (result, zero, offset++);
5043 _endLazyDPSEvaluation();
5047 /*-----------------------------------------------------------------*/
5048 /* genMinusBits - generates code for subtraction of two bits */
5049 /*-----------------------------------------------------------------*/
5051 genMinusBits (iCode * ic)
5053 symbol *lbl = newiTempLabel (NULL);
5055 D (emitcode (";", "genMinusBits"));
5057 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
5059 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
5060 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
5061 emitcode ("cpl", "c");
5063 outBitC (IC_RESULT (ic));
5067 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
5068 emitcode ("subb", "a,acc");
5069 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
5070 emitcode ("inc", "a");
5072 aopPut (IC_RESULT (ic), "a", 0);
5073 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
5077 /*-----------------------------------------------------------------*/
5078 /* genMinus - generates code for subtraction */
5079 /*-----------------------------------------------------------------*/
5081 genMinus (iCode * ic)
5083 int size, offset = 0;
5088 D (emitcode (";", "genMinus"));
5090 AOP_OP_3_NOFATAL(ic, pushResult);
5094 /* special cases :- */
5095 /* if both left & right are in bit space */
5096 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
5097 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
5103 /* if I can do an decrement instead
5104 of subtract then GOOD for ME */
5105 if (genMinusDec (ic) == TRUE)
5110 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
5112 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
5118 lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5123 /* if literal, add a,#-lit, else normal subb */
5124 _startLazyDPSEvaluation ();
5126 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
5127 if (AOP_USESDPTR(IC_RIGHT(ic))) {
5128 emitcode ("mov","b,%s",
5129 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
5130 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
5131 emitcode ("subb","a,b");
5133 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
5134 emitcode ("subb", "a,%s",
5135 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE,
5139 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
5140 /* first add without previous c */
5142 if (!size && lit==-1) {
5143 emitcode ("dec", "a");
5145 emitcode ("add", "a,#!constbyte",
5146 (unsigned int) (lit & 0x0FFL));
5149 emitcode ("addc", "a,#!constbyte",
5150 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5155 emitcode ("push", "acc");
5157 aopPut (IC_RESULT (ic), "a", offset);
5161 _endLazyDPSEvaluation ();
5165 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
5167 size = getDataSize (IC_LEFT (ic));
5168 rSize = getDataSize (IC_RESULT (ic));
5170 ADJUST_PUSHED_RESULT(size, rSize);
5172 _startLazyDPSEvaluation ();
5175 emitcode ("pop", "acc");
5176 aopPut (IC_RESULT (ic), "a", size);
5178 _endLazyDPSEvaluation ();
5181 adjustArithmeticResult (ic);
5184 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5185 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5186 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5190 /*-----------------------------------------------------------------*/
5191 /* genMultbits :- multiplication of bits */
5192 /*-----------------------------------------------------------------*/
5194 genMultbits (operand * left,
5199 D (emitcode (";", "genMultbits"));
5201 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5202 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5203 aopOp(result, ic, TRUE, FALSE);
5207 /*-----------------------------------------------------------------*/
5208 /* genMultOneByte : 8*8=8/16 bit multiplication */
5209 /*-----------------------------------------------------------------*/
5211 genMultOneByte (operand * left,
5218 bool runtimeSign, compiletimeSign;
5219 bool lUnsigned, rUnsigned, pushedB;
5221 /* (if two literals: the value is computed before) */
5222 /* if one literal, literal on the right */
5223 if (AOP_TYPE (left) == AOP_LIT)
5228 /* emitcode (";", "swapped left and right"); */
5230 /* if no literal, unsigned on the right: shorter code */
5231 if ( AOP_TYPE (right) != AOP_LIT
5232 && SPEC_USIGN (getSpec (operandType (left))))
5239 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5240 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5244 if ((lUnsigned && rUnsigned)
5245 /* sorry, I don't know how to get size
5246 without calling aopOp (result,...);
5247 see Feature Request */
5248 /* || size == 1 */ ) /* no, this is not a bug; with a 1 byte result there's
5249 no need to take care about the signedness! */
5251 /* just an unsigned 8 * 8 = 8 multiply
5253 /* emitcode (";","unsigned"); */
5254 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
5255 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
5256 emitcode ("mul", "ab");
5259 aopOp (result, ic, TRUE, FALSE);
5260 size = AOP_SIZE (result);
5262 if (size < 1 || size > 2)
5264 /* this should never happen */
5265 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
5266 size, __FILE__, lineno);
5270 aopPut (result, "a", 0);
5273 aopPut (result, "b", 1);
5279 /* we have to do a signed multiply */
5280 /* emitcode (";", "signed"); */
5282 /* now sign adjust for both left & right */
5284 /* let's see what's needed: */
5285 /* apply negative sign during runtime */
5286 runtimeSign = FALSE;
5287 /* negative sign from literals */
5288 compiletimeSign = FALSE;
5292 if (AOP_TYPE(left) == AOP_LIT)
5294 /* signed literal */
5295 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5297 compiletimeSign = TRUE;
5300 /* signed but not literal */
5306 if (AOP_TYPE(right) == AOP_LIT)
5308 /* signed literal */
5309 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5311 compiletimeSign ^= TRUE;
5314 /* signed but not literal */
5318 /* initialize F0, which stores the runtime sign */
5321 if (compiletimeSign)
5322 emitcode ("setb", "F0"); /* set sign flag */
5324 emitcode ("clr", "F0"); /* reset sign flag */
5327 /* save the signs of the operands */
5328 if (AOP_TYPE(right) == AOP_LIT)
5330 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5332 if (!rUnsigned && val < 0)
5333 emitcode ("mov", "b,#!constbyte", -val);
5335 emitcode ("mov", "b,#!constbyte", (unsigned char) val);
5337 else /* ! literal */
5339 if (rUnsigned) /* emitcode (";", "signed"); */
5340 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
5343 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
5344 lbl = newiTempLabel (NULL);
5345 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5346 emitcode ("cpl", "F0"); /* complement sign flag */
5347 emitcode ("cpl", "a"); /* 2's complement */
5348 emitcode ("inc", "a");
5350 emitcode ("mov", "b,a");
5354 if (AOP_TYPE(left) == AOP_LIT)
5356 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5358 if (!lUnsigned && val < 0)
5359 emitcode ("mov", "a,#!constbyte", -val);
5361 emitcode ("mov", "a,#!constbyte", (unsigned char) val);
5363 else /* ! literal */
5365 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
5367 if (!lUnsigned) /* emitcode (";", "signed"); */
5369 lbl = newiTempLabel (NULL);
5370 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5371 emitcode ("cpl", "F0"); /* complement sign flag */
5372 emitcode ("cpl", "a"); /* 2's complement */
5373 emitcode ("inc", "a");
5378 /* now the multiplication */
5379 emitcode ("mul", "ab");
5381 aopOp(result, ic, TRUE, FALSE);
5382 size = AOP_SIZE (result);
5384 if (size < 1 || size > 2)
5386 /* this should never happen */
5387 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
5388 size, __FILE__, lineno);
5392 if (runtimeSign || compiletimeSign)
5394 lbl = newiTempLabel (NULL);
5396 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5397 emitcode ("cpl", "a"); /* lsb 2's complement */
5399 emitcode ("inc", "a"); /* inc doesn't set carry flag */
5402 emitcode ("add", "a,#1"); /* this sets carry flag */
5403 emitcode ("xch", "a,b");
5404 emitcode ("cpl", "a"); /* msb 2's complement */
5405 emitcode ("addc", "a,#0");
5406 emitcode ("xch", "a,b");
5410 aopPut (result, "a", 0);
5413 aopPut (result, "b", 1);
5418 /*-----------------------------------------------------------------*/
5419 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
5420 /*-----------------------------------------------------------------*/
5421 static void genMultTwoByte (operand *left, operand *right,
5422 operand *result, iCode *ic)
5424 sym_link *retype = getSpec(operandType(right));
5425 sym_link *letype = getSpec(operandType(left));
5426 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5429 if (AOP_TYPE (left) == AOP_LIT) {
5434 /* save EA bit in F1 */
5435 lbl = newiTempLabel(NULL);
5436 emitcode ("setb","F1");
5437 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5438 emitcode ("clr","F1");
5441 /* load up MB with right */
5443 emitcode("clr","F0");
5444 if (AOP_TYPE(right) == AOP_LIT) {
5445 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5447 emitcode("setb","F0");
5450 emitcode ("mov","mb,#!constbyte",val & 0xff);
5451 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5453 lbl = newiTempLabel(NULL);
5454 emitcode ("mov","b,%s",aopGet(right,0,FALSE,FALSE,NULL));
5455 emitcode ("mov","a,%s",aopGet(right,1,FALSE,FALSE,NULL));
5456 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5457 emitcode ("xch", "a,b");
5458 emitcode ("cpl","a");
5459 emitcode ("add", "a,#1");
5460 emitcode ("xch", "a,b");
5461 emitcode ("cpl", "a"); // msb
5462 emitcode ("addc", "a,#0");
5463 emitcode ("setb","F0");
5465 emitcode ("mov","mb,b");
5466 emitcode ("mov","mb,a");
5469 emitcode ("mov","mb,%s",aopGet(right,0,FALSE,FALSE,NULL));
5470 emitcode ("mov","mb,%s",aopGet(right,1,FALSE,FALSE,NULL));
5472 /* load up MA with left */
5474 lbl = newiTempLabel(NULL);
5475 emitcode ("mov","b,%s",aopGet(left,0,FALSE,FALSE,NULL));
5476 emitcode ("mov","a,%s",aopGet(left,1,FALSE,FALSE,NULL));
5477 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5478 emitcode ("xch", "a,b");
5479 emitcode ("cpl","a");
5480 emitcode ("add", "a,#1");
5481 emitcode ("xch", "a,b");
5482 emitcode ("cpl", "a"); // msb
5483 emitcode ("addc","a,#0");
5484 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5485 emitcode ("setb","F0");
5487 emitcode ("mov","ma,b");
5488 emitcode ("mov","ma,a");
5490 emitcode ("mov","ma,%s",aopGet(left,0,FALSE,FALSE,NULL));
5491 emitcode ("mov","ma,%s",aopGet(left,1,FALSE,FALSE,NULL));
5493 /* wait for multiplication to finish */
5494 lbl = newiTempLabel(NULL);
5496 emitcode("mov","a,mcnt1");
5497 emitcode("anl","a,#!constbyte",0x80);
5498 emitcode("jnz","!tlabel",lbl->key+100);
5500 freeAsmop (left, NULL, ic, TRUE);
5501 freeAsmop (right, NULL, ic,TRUE);
5502 aopOp(result, ic, TRUE, FALSE);
5504 /* if unsigned then simple */
5506 emitcode ("mov","a,ma");
5507 if (AOP_SIZE(result) >= 4) aopPut(result,"a",3);
5508 emitcode ("mov","a,ma");
5509 if (AOP_SIZE(result) >= 3) aopPut(result,"a",2);
5510 aopPut(result,"ma",1);
5511 aopPut(result,"ma",0);
5513 emitcode("push","ma");
5514 emitcode("push","ma");
5515 emitcode("push","ma");
5517 /* negate result if needed */
5518 lbl = newiTempLabel(NULL);
5519 emitcode("jnb","F0,!tlabel",lbl->key+100);
5520 emitcode("cpl","a");
5521 emitcode("add","a,#1");
5523 if (AOP_TYPE(result) == AOP_ACC)
5525 D (emitcode(";", "ACC special case."));
5526 /* We know result is the only live aop, and
5527 * it's obviously not a DPTR2, so AP is available.
5529 emitcode("mov", "%s,acc", DP2_RESULT_REG);
5533 aopPut(result,"a",0);
5536 emitcode("pop","acc");
5537 lbl = newiTempLabel(NULL);
5538 emitcode("jnb","F0,!tlabel",lbl->key+100);
5539 emitcode("cpl","a");
5540 emitcode("addc","a,#0");
5542 aopPut(result,"a",1);
5543 emitcode("pop","acc");
5544 if (AOP_SIZE(result) >= 3) {
5545 lbl = newiTempLabel(NULL);
5546 emitcode("jnb","F0,!tlabel",lbl->key+100);
5547 emitcode("cpl","a");
5548 emitcode("addc","a,#0");
5550 aopPut(result,"a",2);
5552 emitcode("pop","acc");
5553 if (AOP_SIZE(result) >= 4) {
5554 lbl = newiTempLabel(NULL);
5555 emitcode("jnb","F0,!tlabel",lbl->key+100);
5556 emitcode("cpl","a");
5557 emitcode("addc","a,#0");
5559 aopPut(result,"a",3);
5561 if (AOP_TYPE(result) == AOP_ACC)
5563 /* We stashed the result away above. */
5564 emitcode("mov", "acc,%s", DP2_RESULT_REG);
5568 freeAsmop (result, NULL, ic, TRUE);
5570 /* restore EA bit in F1 */
5571 lbl = newiTempLabel(NULL);
5572 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5573 emitcode ("setb","EA");
5578 /*-----------------------------------------------------------------*/
5579 /* genMult - generates code for multiplication */
5580 /*-----------------------------------------------------------------*/
5582 genMult (iCode * ic)
5584 operand *left = IC_LEFT (ic);
5585 operand *right = IC_RIGHT (ic);
5586 operand *result = IC_RESULT (ic);
5588 D (emitcode (";", "genMult"));
5590 /* assign the asmops */
5593 /* special cases first */
5595 if (AOP_TYPE (left) == AOP_CRY &&
5596 AOP_TYPE (right) == AOP_CRY)
5598 genMultbits (left, right, result, ic);
5602 /* if both are of size == 1 */
5603 if (AOP_SIZE (left) == 1 &&
5604 AOP_SIZE (right) == 1)
5606 genMultOneByte (left, right, result, ic);
5610 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5611 /* use the ds390 ARITHMETIC accel UNIT */
5612 genMultTwoByte (left, right, result, ic);
5615 /* should have been converted to function call */
5619 freeAsmop (result, NULL, ic, TRUE);
5620 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5621 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5624 /*-----------------------------------------------------------------*/
5625 /* genDivbits :- division of bits */
5626 /*-----------------------------------------------------------------*/
5628 genDivbits (operand * left,
5636 D(emitcode ("; genDivbits",""));
5640 /* the result must be bit */
5641 LOAD_AB_FOR_DIV (left, right, l);
5642 emitcode ("div", "ab");
5643 emitcode ("rrc", "a");
5644 aopOp(result, ic, TRUE, FALSE);
5648 aopPut (result, "c", 0);
5651 /*-----------------------------------------------------------------*/
5652 /* genDivOneByte : 8 bit division */
5653 /*-----------------------------------------------------------------*/
5655 genDivOneByte (operand * left,
5660 bool lUnsigned, rUnsigned, pushedB;
5661 bool runtimeSign, compiletimeSign;
5666 D(emitcode ("; genDivOneByte",""));
5669 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5670 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5674 /* signed or unsigned */
5675 if (lUnsigned && rUnsigned)
5677 /* unsigned is easy */
5678 LOAD_AB_FOR_DIV (left, right, l);
5679 emitcode ("div", "ab");
5682 aopOp (result, ic, TRUE, FALSE);
5683 aopPut (result, "a", 0);
5686 size = AOP_SIZE (result) - 1;
5689 aopPut (result, zero, offset++);
5695 /* signed is a little bit more difficult */
5697 /* now sign adjust for both left & right */
5699 /* let's see what's needed: */
5700 /* apply negative sign during runtime */
5701 runtimeSign = FALSE;
5702 /* negative sign from literals */
5703 compiletimeSign = FALSE;
5707 if (AOP_TYPE(left) == AOP_LIT)
5709 /* signed literal */
5710 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5712 compiletimeSign = TRUE;
5715 /* signed but not literal */
5721 if (AOP_TYPE(right) == AOP_LIT)
5723 /* signed literal */
5724 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5726 compiletimeSign ^= TRUE;
5729 /* signed but not literal */
5733 /* initialize F0, which stores the runtime sign */
5736 if (compiletimeSign)
5737 emitcode ("setb", "F0"); /* set sign flag */
5739 emitcode ("clr", "F0"); /* reset sign flag */
5742 /* save the signs of the operands */
5743 if (AOP_TYPE(right) == AOP_LIT)
5745 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5747 if (!rUnsigned && val < 0)
5748 emitcode ("mov", "b,#0x%02x", -val);
5750 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5752 else /* ! literal */
5755 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
5758 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
5759 lbl = newiTempLabel (NULL);
5760 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5761 emitcode ("cpl", "F0"); /* complement sign flag */
5762 emitcode ("cpl", "a"); /* 2's complement */
5763 emitcode ("inc", "a");
5765 emitcode ("mov", "b,a");
5769 if (AOP_TYPE(left) == AOP_LIT)
5771 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5773 if (!lUnsigned && val < 0)
5774 emitcode ("mov", "a,#0x%02x", -val);
5776 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5778 else /* ! literal */
5780 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
5784 lbl = newiTempLabel (NULL);
5785 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5786 emitcode ("cpl", "F0"); /* complement sign flag */
5787 emitcode ("cpl", "a"); /* 2's complement */
5788 emitcode ("inc", "a");
5793 /* now the division */
5794 emitcode ("nop", "; workaround for DS80C390 div bug.");
5795 emitcode ("div", "ab");
5797 if (runtimeSign || compiletimeSign)
5799 lbl = newiTempLabel (NULL);
5801 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5802 emitcode ("cpl", "a"); /* lsb 2's complement */
5803 emitcode ("inc", "a");
5807 aopOp (result, ic, TRUE, FALSE);
5808 size = AOP_SIZE (result) - 1;
5812 /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
5813 then the result will be in b, a */
5814 emitcode ("mov", "b,a"); /* 1 */
5815 /* msb is 0x00 or 0xff depending on the sign */
5818 emitcode ("mov", "c,F0");
5819 emitcode ("subb", "a,acc");
5820 emitcode ("xch", "a,b"); /* 2 */
5822 aopPut (result, "b", offset++); /* write msb's */
5824 else /* compiletimeSign */
5826 aopPut (result, "#0xff", offset++); /* write msb's */
5828 aopPut (result, "a", 0); /* 3: write lsb */
5833 aopOp(result, ic, TRUE, FALSE);
5834 size = AOP_SIZE (result) - 1;
5836 aopPut (result, "a", 0);
5838 aopPut (result, zero, offset++);
5844 /*-----------------------------------------------------------------*/
5845 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
5846 /*-----------------------------------------------------------------*/
5847 static void genDivTwoByte (operand *left, operand *right,
5848 operand *result, iCode *ic)
5850 sym_link *retype = getSpec(operandType(right));
5851 sym_link *letype = getSpec(operandType(left));
5852 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5855 /* save EA bit in F1 */
5856 lbl = newiTempLabel(NULL);
5857 emitcode ("setb","F1");
5858 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5859 emitcode ("clr","F1");
5862 /* load up MA with left */
5864 emitcode("clr","F0");
5865 lbl = newiTempLabel(NULL);
5866 emitcode ("mov","b,%s",aopGet(left,0,FALSE,FALSE,NULL));
5867 emitcode ("mov","a,%s",aopGet(left,1,FALSE,FALSE,NULL));
5868 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5869 emitcode ("xch", "a,b");
5870 emitcode ("cpl","a");
5871 emitcode ("add", "a,#1");
5872 emitcode ("xch", "a,b");
5873 emitcode ("cpl", "a"); // msb
5874 emitcode ("addc","a,#0");
5875 emitcode ("setb","F0");
5877 emitcode ("mov","ma,b");
5878 emitcode ("mov","ma,a");
5880 emitcode ("mov","ma,%s",aopGet(left,0,FALSE,FALSE,NULL));
5881 emitcode ("mov","ma,%s",aopGet(left,1,FALSE,FALSE,NULL));
5884 /* load up MB with right */
5886 if (AOP_TYPE(right) == AOP_LIT) {
5887 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5889 lbl = newiTempLabel(NULL);
5890 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5891 emitcode("setb","F0");
5895 emitcode ("mov","mb,#!constbyte",val & 0xff);
5896 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5898 lbl = newiTempLabel(NULL);
5899 emitcode ("mov","b,%s",aopGet(right,0,FALSE,FALSE,NULL));
5900 emitcode ("mov","a,%s",aopGet(right,1,FALSE,FALSE,NULL));
5901 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5902 emitcode ("xch", "a,b");
5903 emitcode ("cpl","a");
5904 emitcode ("add", "a,#1");
5905 emitcode ("xch", "a,b");
5906 emitcode ("cpl", "a"); // msb
5907 emitcode ("addc", "a,#0");
5908 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5909 emitcode ("setb","F0");
5911 emitcode ("mov","mb,b");
5912 emitcode ("mov","mb,a");
5915 emitcode ("mov","mb,%s",aopGet(right,0,FALSE,FALSE,NULL));
5916 emitcode ("mov","mb,%s",aopGet(right,1,FALSE,FALSE,NULL));
5919 /* wait for multiplication to finish */
5920 lbl = newiTempLabel(NULL);
5922 emitcode("mov","a,mcnt1");
5923 emitcode("anl","a,#!constbyte",0x80);
5924 emitcode("jnz","!tlabel",lbl->key+100);
5926 freeAsmop (left, NULL, ic, TRUE);
5927 freeAsmop (right, NULL, ic,TRUE);
5928 aopOp(result, ic, TRUE, FALSE);
5930 /* if unsigned then simple */
5932 aopPut(result,"ma",1);
5933 aopPut(result,"ma",0);
5935 emitcode("push","ma");
5937 /* negate result if needed */
5938 lbl = newiTempLabel(NULL);
5939 emitcode("jnb","F0,!tlabel",lbl->key+100);
5940 emitcode("cpl","a");
5941 emitcode("add","a,#1");
5943 aopPut(result,"a",0);
5944 emitcode("pop","acc");
5945 lbl = newiTempLabel(NULL);
5946 emitcode("jnb","F0,!tlabel",lbl->key+100);
5947 emitcode("cpl","a");
5948 emitcode("addc","a,#0");
5950 aopPut(result,"a",1);
5952 freeAsmop (result, NULL, ic, TRUE);
5953 /* restore EA bit in F1 */
5954 lbl = newiTempLabel(NULL);
5955 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5956 emitcode ("setb","EA");
5961 /*-----------------------------------------------------------------*/
5962 /* genDiv - generates code for division */
5963 /*-----------------------------------------------------------------*/
5967 operand *left = IC_LEFT (ic);
5968 operand *right = IC_RIGHT (ic);
5969 operand *result = IC_RESULT (ic);
5971 D (emitcode (";", "genDiv"));
5973 /* assign the amsops */
5976 /* special cases first */
5978 if (AOP_TYPE (left) == AOP_CRY &&
5979 AOP_TYPE (right) == AOP_CRY)
5981 genDivbits (left, right, result, ic);
5985 /* if both are of size == 1 */
5986 if (AOP_SIZE (left) == 1 &&
5987 AOP_SIZE (right) == 1)
5989 genDivOneByte (left, right, result, ic);
5993 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5994 /* use the ds390 ARITHMETIC accel UNIT */
5995 genDivTwoByte (left, right, result, ic);
5998 /* should have been converted to function call */
6001 freeAsmop (result, NULL, ic, TRUE);
6002 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6003 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6006 /*-----------------------------------------------------------------*/
6007 /* genModbits :- modulus of bits */
6008 /*-----------------------------------------------------------------*/
6010 genModbits (operand * left,
6018 D (emitcode (";", "genModbits"));
6022 /* the result must be bit */
6023 LOAD_AB_FOR_DIV (left, right, l);
6024 emitcode ("div", "ab");
6025 emitcode ("mov", "a,b");
6026 emitcode ("rrc", "a");
6027 aopOp(result, ic, TRUE, FALSE);
6031 aopPut (result, "c", 0);
6034 /*-----------------------------------------------------------------*/
6035 /* genModOneByte : 8 bit modulus */
6036 /*-----------------------------------------------------------------*/
6038 genModOneByte (operand * left,
6043 bool lUnsigned, rUnsigned, pushedB;
6044 bool runtimeSign, compiletimeSign;
6049 D (emitcode (";", "genModOneByte"));
6052 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
6053 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
6057 /* signed or unsigned */
6058 if (lUnsigned && rUnsigned)
6060 /* unsigned is easy */
6061 LOAD_AB_FOR_DIV (left, right, l);
6062 emitcode ("div", "ab");
6063 aopOp (result, ic, TRUE, FALSE);
6064 aopPut (result, "b", 0);
6066 for (size = AOP_SIZE (result) - 1; size--;)
6067 aopPut (result, zero, offset++);
6073 /* signed is a little bit more difficult */
6075 /* now sign adjust for both left & right */
6077 /* modulus: sign of the right operand has no influence on the result! */
6078 if (AOP_TYPE(right) == AOP_LIT)
6080 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
6082 if (!rUnsigned && val < 0)
6083 emitcode ("mov", "b,#0x%02x", -val);
6085 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
6087 else /* not literal */
6090 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
6093 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
6094 lbl = newiTempLabel (NULL);
6095 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
6096 emitcode ("cpl", "a"); /* 2's complement */
6097 emitcode ("inc", "a");
6099 emitcode ("mov", "b,a");
6103 /* let's see what's needed: */
6104 /* apply negative sign during runtime */
6105 runtimeSign = FALSE;
6106 /* negative sign from literals */
6107 compiletimeSign = FALSE;
6109 /* sign adjust left side */
6110 if (AOP_TYPE(left) == AOP_LIT)
6112 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
6114 if (!lUnsigned && val < 0)
6116 compiletimeSign = TRUE; /* set sign flag */
6117 emitcode ("mov", "a,#0x%02x", -val);
6120 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
6122 else /* ! literal */
6124 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
6129 emitcode ("clr", "F0"); /* clear sign flag */
6131 lbl = newiTempLabel (NULL);
6132 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
6133 emitcode ("setb", "F0"); /* set sign flag */
6134 emitcode ("cpl", "a"); /* 2's complement */
6135 emitcode ("inc", "a");
6140 /* now the modulus */
6141 emitcode ("nop", "; workaround for DS80C390 div bug.");
6142 emitcode ("div", "ab");
6144 if (runtimeSign || compiletimeSign)
6146 emitcode ("mov", "a,b");
6147 lbl = newiTempLabel (NULL);
6149 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
6150 emitcode ("cpl", "a"); /* lsb 2's complement */
6151 emitcode ("inc", "a");
6155 aopOp (result, ic, TRUE, FALSE);
6156 size = AOP_SIZE (result) - 1;
6160 /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
6161 then the result will be in b, a */
6162 emitcode ("mov", "b,a"); /* 1 */
6163 /* msb is 0x00 or 0xff depending on the sign */
6166 emitcode ("mov", "c,F0");
6167 emitcode ("subb", "a,acc");
6168 emitcode ("xch", "a,b"); /* 2 */
6170 aopPut (result, "b", offset++); /* write msb's */
6172 else /* compiletimeSign */
6174 aopPut (result, "#0xff", offset++); /* write msb's */
6176 aopPut (result, "a", 0); /* 3: write lsb */
6181 aopOp(result, ic, TRUE, FALSE);
6182 size = AOP_SIZE (result) - 1;
6184 aopPut (result, "b", 0);
6186 aopPut (result, zero, offset++);
6192 /*-----------------------------------------------------------------*/
6193 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
6194 /*-----------------------------------------------------------------*/
6195 static void genModTwoByte (operand *left, operand *right,
6196 operand *result, iCode *ic)
6198 sym_link *retype = getSpec(operandType(right));
6199 sym_link *letype = getSpec(operandType(left));
6200 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
6203 /* load up MA with left */
6204 /* save EA bit in F1 */
6205 lbl = newiTempLabel(NULL);
6206 emitcode ("setb","F1");
6207 emitcode ("jbc","EA,!tlabel",lbl->key+100);
6208 emitcode ("clr","F1");
6212 lbl = newiTempLabel(NULL);
6213 emitcode ("mov","b,%s",aopGet(left,0,FALSE,FALSE,NULL));
6214 emitcode ("mov","a,%s",aopGet(left,1,FALSE,FALSE,NULL));
6215 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
6216 emitcode ("xch", "a,b");
6217 emitcode ("cpl","a");
6218 emitcode ("add", "a,#1");
6219 emitcode ("xch", "a,b");
6220 emitcode ("cpl", "a"); // msb
6221 emitcode ("addc","a,#0");
6223 emitcode ("mov","ma,b");
6224 emitcode ("mov","ma,a");
6226 emitcode ("mov","ma,%s",aopGet(left,0,FALSE,FALSE,NULL));
6227 emitcode ("mov","ma,%s",aopGet(left,1,FALSE,FALSE,NULL));
6230 /* load up MB with right */
6232 if (AOP_TYPE(right) == AOP_LIT) {
6233 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
6237 emitcode ("mov","mb,#!constbyte",val & 0xff);
6238 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
6240 lbl = newiTempLabel(NULL);
6241 emitcode ("mov","b,%s",aopGet(right,0,FALSE,FALSE,NULL));
6242 emitcode ("mov","a,%s",aopGet(right,1,FALSE,FALSE,NULL));
6243 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
6244 emitcode ("xch", "a,b");
6245 emitcode ("cpl","a");
6246 emitcode ("add", "a,#1");
6247 emitcode ("xch", "a,b");
6248 emitcode ("cpl", "a"); // msb
6249 emitcode ("addc", "a,#0");
6251 emitcode ("mov","mb,b");
6252 emitcode ("mov","mb,a");
6255 emitcode ("mov","mb,%s",aopGet(right,0,FALSE,FALSE,NULL));
6256 emitcode ("mov","mb,%s",aopGet(right,1,FALSE,FALSE,NULL));
6259 /* wait for multiplication to finish */
6260 lbl = newiTempLabel(NULL);
6262 emitcode("mov","a,mcnt1");
6263 emitcode("anl","a,#!constbyte",0x80);
6264 emitcode("jnz","!tlabel",lbl->key+100);
6266 freeAsmop (left, NULL, ic, TRUE);
6267 freeAsmop (right, NULL, ic,TRUE);
6268 aopOp(result, ic, TRUE, FALSE);
6270 aopPut(result,"mb",1);
6271 aopPut(result,"mb",0);
6272 freeAsmop (result, NULL, ic, TRUE);
6274 /* restore EA bit in F1 */
6275 lbl = newiTempLabel(NULL);
6276 emitcode ("jnb","F1,!tlabel",lbl->key+100);
6277 emitcode ("setb","EA");
6281 /*-----------------------------------------------------------------*/
6282 /* genMod - generates code for division */
6283 /*-----------------------------------------------------------------*/
6287 operand *left = IC_LEFT (ic);
6288 operand *right = IC_RIGHT (ic);
6289 operand *result = IC_RESULT (ic);
6291 D (emitcode (";", "genMod"));
6293 /* assign the asmops */
6296 /* special cases first */
6298 if (AOP_TYPE (left) == AOP_CRY &&
6299 AOP_TYPE (right) == AOP_CRY)
6301 genModbits (left, right, result, ic);
6305 /* if both are of size == 1 */
6306 if (AOP_SIZE (left) == 1 &&
6307 AOP_SIZE (right) == 1)
6309 genModOneByte (left, right, result, ic);
6313 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
6314 /* use the ds390 ARITHMETIC accel UNIT */
6315 genModTwoByte (left, right, result, ic);
6319 /* should have been converted to function call */
6323 freeAsmop (result, NULL, ic, TRUE);
6324 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6325 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6328 /*-----------------------------------------------------------------*/
6329 /* genIfxJump :- will create a jump depending on the ifx */
6330 /*-----------------------------------------------------------------*/
6332 genIfxJump (iCode * ic, char *jval)
6335 symbol *tlbl = newiTempLabel (NULL);
6338 D (emitcode (";", "genIfxJump"));
6340 /* if true label then we jump if condition
6344 jlbl = IC_TRUE (ic);
6345 inst = ((strcmp (jval, "a") == 0 ? "jz" :
6346 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
6350 /* false label is present */
6351 jlbl = IC_FALSE (ic);
6352 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
6353 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
6355 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
6356 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
6358 emitcode (inst, "!tlabel", tlbl->key + 100);
6359 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
6362 /* mark the icode as generated */
6366 /*-----------------------------------------------------------------*/
6367 /* genCmp :- greater or less than comparison */
6368 /*-----------------------------------------------------------------*/
6370 genCmp (operand * left, operand * right,
6371 iCode * ic, iCode * ifx, int sign)
6373 int size, offset = 0;
6374 unsigned long lit = 0L;
6377 D (emitcode (";", "genCmp"));
6379 result = IC_RESULT (ic);
6381 /* if left & right are bit variables */
6382 if (AOP_TYPE (left) == AOP_CRY &&
6383 AOP_TYPE (right) == AOP_CRY)
6385 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6386 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6390 /* subtract right from left if at the
6391 end the carry flag is set then we know that
6392 left is greater than right */
6393 size = max (AOP_SIZE (left), AOP_SIZE (right));
6395 /* if unsigned char cmp with lit, do cjne left,#right,zz */
6396 if ((size == 1) && !sign &&
6397 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
6399 symbol *lbl = newiTempLabel (NULL);
6400 emitcode ("cjne", "%s,%s,!tlabel",
6401 aopGet (left, offset, FALSE, FALSE, NULL),
6402 aopGet (right, offset, FALSE, FALSE, NULL),
6408 if (AOP_TYPE (right) == AOP_LIT)
6410 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6411 /* optimize if(x < 0) or if(x >= 0) */
6420 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
6422 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6423 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6425 aopOp (result, ic, FALSE, FALSE);
6427 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
6429 freeAsmop (result, NULL, ic, TRUE);
6430 genIfxJump (ifx, "acc.7");
6435 emitcode ("rlc", "a");
6437 goto release_freedLR;
6445 // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
6446 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
6447 // emitcode (";", "genCmp #2");
6448 if (sign && (size == 0))
6450 // emitcode (";", "genCmp #3");
6451 emitcode ("xrl", "a,#!constbyte",0x80);
6452 if (AOP_TYPE (right) == AOP_LIT)
6454 unsigned long lit = (unsigned long)
6455 floatFromVal (AOP (right)->aopu.aop_lit);
6456 // emitcode (";", "genCmp #3.1");
6457 emitcode ("subb", "a,#!constbyte",
6458 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
6462 // emitcode (";", "genCmp #3.2");
6464 MOVB (aopGet (right, offset++, FALSE, FALSE, "b"));
6465 saveAccWarn = DEFAULT_ACC_WARNING;
6466 emitcode ("xrl", "b,#!constbyte",0x80);
6467 emitcode ("subb", "a,b");
6474 // emitcode (";", "genCmp #4");
6476 s = aopGet (right, offset++, FALSE, FALSE, "b");
6477 saveAccWarn = DEFAULT_ACC_WARNING;
6479 emitcode ("subb", "a,%s", s);
6486 /* Don't need the left & right operands any more; do need the result. */
6487 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6488 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6490 aopOp (result, ic, FALSE, FALSE);
6494 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6500 /* if the result is used in the next
6501 ifx conditional branch then generate
6502 code a little differently */
6505 genIfxJump (ifx, "c");
6511 /* leave the result in acc */
6513 freeAsmop (result, NULL, ic, TRUE);
6516 /*-----------------------------------------------------------------*/
6517 /* genCmpGt :- greater than comparison */
6518 /*-----------------------------------------------------------------*/
6520 genCmpGt (iCode * ic, iCode * ifx)
6522 operand *left, *right;
6523 sym_link *letype, *retype;
6526 D (emitcode (";", "genCmpGt"));
6528 left = IC_LEFT (ic);
6529 right = IC_RIGHT (ic);
6531 letype = getSpec (operandType (left));
6532 retype = getSpec (operandType (right));
6533 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6535 /* assign the left & right amsops */
6538 genCmp (right, left, ic, ifx, sign);
6541 /*-----------------------------------------------------------------*/
6542 /* genCmpLt - less than comparisons */
6543 /*-----------------------------------------------------------------*/
6545 genCmpLt (iCode * ic, iCode * ifx)
6547 operand *left, *right;
6548 sym_link *letype, *retype;
6551 D (emitcode (";", "genCmpLt"));
6553 left = IC_LEFT (ic);
6554 right = IC_RIGHT (ic);
6556 letype = getSpec (operandType (left));
6557 retype = getSpec (operandType (right));
6558 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6560 /* assign the left & right amsops */
6563 genCmp (left, right, ic, ifx, sign);
6566 /*-----------------------------------------------------------------*/
6567 /* gencjneshort - compare and jump if not equal */
6568 /*-----------------------------------------------------------------*/
6570 gencjneshort (operand * left, operand * right, symbol * lbl)
6572 int size = max (AOP_SIZE (left), AOP_SIZE (right));
6574 unsigned long lit = 0L;
6576 D (emitcode (";", "gencjneshort"));
6578 /* if the left side is a literal or
6579 if the right is in a pointer register and left
6581 if ((AOP_TYPE (left) == AOP_LIT) ||
6582 (AOP_TYPE (left) == AOP_IMMD) ||
6583 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6590 if (AOP_TYPE (right) == AOP_LIT)
6591 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6593 if (opIsGptr (left) || opIsGptr (right))
6595 /* We are comparing a generic pointer to something.
6596 * Exclude the generic type byte from the comparison.
6599 D (emitcode (";", "cjneshort: generic ptr special case."););
6603 /* if the right side is a literal then anything goes */
6604 if (AOP_TYPE (right) == AOP_LIT &&
6605 AOP_TYPE (left) != AOP_DIR)
6609 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
6610 emitcode ("cjne", "a,%s,!tlabel",
6611 aopGet (right, offset, FALSE, FALSE, NULL),
6617 /* if the right side is in a register or in direct space or
6618 if the left is a pointer register & right is not */
6619 else if (AOP_TYPE (right) == AOP_REG ||
6620 AOP_TYPE (right) == AOP_DIR ||
6621 AOP_TYPE (right) == AOP_LIT ||
6622 AOP_TYPE (right) == AOP_IMMD ||
6623 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6624 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6628 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
6629 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6630 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6631 emitcode ("jnz", "!tlabel", lbl->key + 100);
6633 emitcode ("cjne", "a,%s,!tlabel",
6634 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG),
6641 /* right is a pointer reg need both a & b */
6644 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
6645 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
6646 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
6652 /*-----------------------------------------------------------------*/
6653 /* gencjne - compare and jump if not equal */
6654 /*-----------------------------------------------------------------*/
6656 gencjne (operand * left, operand * right, symbol * lbl)
6658 symbol *tlbl = newiTempLabel (NULL);
6660 D (emitcode (";", "gencjne"));
6662 gencjneshort (left, right, lbl);
6664 emitcode ("mov", "a,%s", one);
6665 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
6667 emitcode ("clr", "a");
6671 /*-----------------------------------------------------------------*/
6672 /* genCmpEq - generates code for equal to */
6673 /*-----------------------------------------------------------------*/
6675 genCmpEq (iCode * ic, iCode * ifx)
6677 operand *left, *right, *result;
6679 D (emitcode (";", "genCmpEq"));
6682 AOP_SET_LOCALS (ic);
6684 /* if literal, literal on the right or
6685 if the right is in a pointer register and left
6687 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6688 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6690 operand *t = IC_RIGHT (ic);
6691 IC_RIGHT (ic) = IC_LEFT (ic);
6695 if (ifx && /* !AOP_SIZE(result) */
6696 OP_SYMBOL (result) &&
6697 OP_SYMBOL (result)->regType == REG_CND)
6700 /* if they are both bit variables */
6701 if (AOP_TYPE (left) == AOP_CRY &&
6702 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6704 if (AOP_TYPE (right) == AOP_LIT)
6706 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6709 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6710 emitcode ("cpl", "c");
6714 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6718 emitcode ("clr", "c");
6720 /* AOP_TYPE(right) == AOP_CRY */
6724 symbol *lbl = newiTempLabel (NULL);
6725 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6726 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6727 emitcode ("cpl", "c");
6730 /* if true label then we jump if condition
6732 tlbl = newiTempLabel (NULL);
6735 emitcode ("jnc", "!tlabel", tlbl->key + 100);
6736 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6740 emitcode ("jc", "!tlabel", tlbl->key + 100);
6741 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6747 tlbl = newiTempLabel (NULL);
6748 gencjneshort (left, right, tlbl);
6751 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6756 symbol *lbl = newiTempLabel (NULL);
6757 emitcode ("sjmp", "!tlabel", lbl->key + 100);
6759 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6763 /* mark the icode as generated */
6766 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6767 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6771 /* if they are both bit variables */
6772 if (AOP_TYPE (left) == AOP_CRY &&
6773 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6775 if (AOP_TYPE (right) == AOP_LIT)
6777 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6780 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6781 emitcode ("cpl", "c");
6785 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6789 emitcode ("clr", "c");
6791 /* AOP_TYPE(right) == AOP_CRY */
6795 symbol *lbl = newiTempLabel (NULL);
6796 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6797 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6798 emitcode ("cpl", "c");
6802 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6803 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6805 aopOp (result, ic, TRUE, FALSE);
6808 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6815 genIfxJump (ifx, "c");
6818 /* if the result is used in an arithmetic operation
6819 then put the result in place */
6824 gencjne (left, right, newiTempLabel (NULL));
6826 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6827 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6829 aopOp (result, ic, TRUE, FALSE);
6831 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6833 aopPut (result, "a", 0);
6838 genIfxJump (ifx, "a");
6841 /* if the result is used in an arithmetic operation
6842 then put the result in place */
6843 if (AOP_TYPE (result) != AOP_CRY)
6845 /* leave the result in acc */
6849 freeAsmop (result, NULL, ic, TRUE);
6852 /*-----------------------------------------------------------------*/
6853 /* ifxForOp - returns the icode containing the ifx for operand */
6854 /*-----------------------------------------------------------------*/
6856 ifxForOp (operand * op, iCode * ic)
6858 /* if true symbol then needs to be assigned */
6859 if (IS_TRUE_SYMOP (op))
6862 /* if this has register type condition and
6863 the next instruction is ifx with the same operand
6864 and live to of the operand is upto the ifx only then */
6866 ic->next->op == IFX &&
6867 IC_COND (ic->next)->key == op->key &&
6868 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6874 /*-----------------------------------------------------------------*/
6875 /* hasInc - operand is incremented before any other use */
6876 /*-----------------------------------------------------------------*/
6878 hasInc (operand *op, iCode *ic, int osize)
6880 sym_link *type = operandType(op);
6881 sym_link *retype = getSpec (type);
6882 iCode *lic = ic->next;
6885 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6886 if (!IS_SYMOP(op)) return NULL;
6888 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6889 if (IS_AGGREGATE(type->next)) return NULL;
6890 if (osize != (isize = getSize(type->next))) return NULL;
6893 /* if operand of the form op = op + <sizeof *op> */
6894 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6895 isOperandEqual(IC_RESULT(lic),op) &&
6896 isOperandLiteral(IC_RIGHT(lic)) &&
6897 operandLitValue(IC_RIGHT(lic)) == isize) {
6900 /* if the operand used or deffed */
6901 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6904 /* if GOTO or IFX */
6905 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6911 /*-----------------------------------------------------------------*/
6912 /* genAndOp - for && operation */
6913 /*-----------------------------------------------------------------*/
6915 genAndOp (iCode * ic)
6917 operand *left, *right, *result;
6920 D (emitcode (";", "genAndOp"));
6922 /* note here that && operations that are in an
6923 if statement are taken away by backPatchLabels
6924 only those used in arthmetic operations remain */
6926 AOP_SET_LOCALS (ic);
6928 /* if both are bit variables */
6929 if (AOP_TYPE (left) == AOP_CRY &&
6930 AOP_TYPE (right) == AOP_CRY)
6932 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6933 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6934 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6935 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6937 aopOp (result,ic,FALSE, FALSE);
6942 tlbl = newiTempLabel (NULL);
6944 emitcode ("jz", "!tlabel", tlbl->key + 100);
6947 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6948 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6950 aopOp (result,ic,FALSE, FALSE);
6954 freeAsmop (result, NULL, ic, TRUE);
6958 /*-----------------------------------------------------------------*/
6959 /* genOrOp - for || operation */
6960 /*-----------------------------------------------------------------*/
6962 genOrOp (iCode * ic)
6964 operand *left, *right, *result;
6967 D (emitcode (";", "genOrOp"));
6969 /* note here that || operations that are in an
6970 if statement are taken away by backPatchLabels
6971 only those used in arthmetic operations remain */
6973 AOP_SET_LOCALS (ic);
6975 /* if both are bit variables */
6976 if (AOP_TYPE (left) == AOP_CRY &&
6977 AOP_TYPE (right) == AOP_CRY)
6979 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6980 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6981 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6982 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6984 aopOp (result,ic,FALSE, FALSE);
6990 tlbl = newiTempLabel (NULL);
6992 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6995 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6996 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6998 aopOp (result,ic,FALSE, FALSE);
7003 freeAsmop (result, NULL, ic, TRUE);
7006 /*-----------------------------------------------------------------*/
7007 /* isLiteralBit - test if lit == 2^n */
7008 /*-----------------------------------------------------------------*/
7010 isLiteralBit (unsigned long lit)
7012 unsigned long pw[32] =
7013 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
7014 0x100L, 0x200L, 0x400L, 0x800L,
7015 0x1000L, 0x2000L, 0x4000L, 0x8000L,
7016 0x10000L, 0x20000L, 0x40000L, 0x80000L,
7017 0x100000L, 0x200000L, 0x400000L, 0x800000L,
7018 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
7019 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
7022 for (idx = 0; idx < 32; idx++)
7028 /*-----------------------------------------------------------------*/
7029 /* continueIfTrue - */
7030 /*-----------------------------------------------------------------*/
7032 continueIfTrue (iCode * ic)
7035 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
7039 /*-----------------------------------------------------------------*/
7041 /*-----------------------------------------------------------------*/
7043 jumpIfTrue (iCode * ic)
7046 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
7050 /*-----------------------------------------------------------------*/
7051 /* jmpTrueOrFalse - */
7052 /*-----------------------------------------------------------------*/
7054 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
7056 // ugly but optimized by peephole
7059 symbol *nlbl = newiTempLabel (NULL);
7060 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
7062 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
7067 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
7073 // Generate code to perform a bit-wise logic operation
7074 // on two operands in far space (assumed to already have been
7075 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
7076 // in far space. This requires pushing the result on the stack
7077 // then popping it into the result.
7079 genFarFarLogicOp(iCode *ic, char *logicOp)
7081 int size, resultSize, compSize;
7085 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
7086 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
7087 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
7089 _startLazyDPSEvaluation();
7090 for (size = compSize; (size--); offset++)
7092 MOVA (aopGet (IC_LEFT(ic), offset, FALSE, FALSE, NULL));
7093 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
7094 MOVA (aopGet (IC_RIGHT(ic), offset, FALSE, FALSE, NULL));
7096 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
7097 emitcode ("push", "acc");
7099 _endLazyDPSEvaluation();
7101 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7102 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7103 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
7105 resultSize = AOP_SIZE(IC_RESULT(ic));
7107 ADJUST_PUSHED_RESULT(compSize, resultSize);
7109 _startLazyDPSEvaluation();
7112 emitcode ("pop", "acc");
7113 aopPut (IC_RESULT (ic), "a", compSize);
7115 _endLazyDPSEvaluation();
7116 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
7120 /*-----------------------------------------------------------------*/
7121 /* genAnd - code for and */
7122 /*-----------------------------------------------------------------*/
7124 genAnd (iCode * ic, iCode * ifx)
7126 operand *left, *right, *result;
7127 int size, offset = 0;
7128 unsigned long lit = 0L;
7133 D (emitcode (";", "genAnd"));
7135 AOP_OP_3_NOFATAL (ic, pushResult);
7136 AOP_SET_LOCALS (ic);
7140 genFarFarLogicOp(ic, "anl");
7145 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7147 AOP_TYPE (left), AOP_TYPE (right));
7148 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7150 AOP_SIZE (left), AOP_SIZE (right));
7153 /* if left is a literal & right is not then exchange them */
7154 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7155 #ifdef LOGIC_OPS_BROKEN
7156 || AOP_NEEDSACC (left)
7160 operand *tmp = right;
7165 /* if result = right then exchange left and right */
7166 if (sameRegs (AOP (result), AOP (right)))
7168 operand *tmp = right;
7173 /* if right is bit then exchange them */
7174 if (AOP_TYPE (right) == AOP_CRY &&
7175 AOP_TYPE (left) != AOP_CRY)
7177 operand *tmp = right;
7181 if (AOP_TYPE (right) == AOP_LIT)
7182 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7184 size = AOP_SIZE (result);
7187 // result = bit & yy;
7188 if (AOP_TYPE (left) == AOP_CRY)
7190 // c = bit & literal;
7191 if (AOP_TYPE (right) == AOP_LIT)
7195 if (size && sameRegs (AOP (result), AOP (left)))
7198 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7203 if (size && (AOP_TYPE (result) == AOP_CRY))
7205 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
7208 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7213 emitcode ("clr", "c");
7218 if (AOP_TYPE (right) == AOP_CRY)
7221 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7222 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
7227 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
7229 emitcode ("rrc", "a");
7230 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
7238 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7239 genIfxJump (ifx, "c");
7243 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7244 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7245 if ((AOP_TYPE (right) == AOP_LIT) &&
7246 (AOP_TYPE (result) == AOP_CRY) &&
7247 (AOP_TYPE (left) != AOP_CRY))
7249 int posbit = isLiteralBit (lit);
7254 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE, NULL));
7258 switch (posbit & 0x07)
7260 case 0: emitcode ("rrc", "a");
7262 case 7: emitcode ("rlc", "a");
7264 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
7273 SNPRINTF (buffer, sizeof(buffer),
7274 "acc.%d", posbit & 0x07);
7275 genIfxJump (ifx, buffer);
7279 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
7286 symbol *tlbl = newiTempLabel (NULL);
7287 int sizel = AOP_SIZE (left);
7289 emitcode ("setb", "c");
7292 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
7294 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7296 if ((posbit = isLiteralBit (bytelit)) != 0)
7297 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
7300 if (bytelit != 0x0FFL)
7301 emitcode ("anl", "a,%s",
7302 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG));
7303 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7308 // bit = left & literal
7311 emitcode ("clr", "c");
7314 // if(left & literal)
7318 jmpTrueOrFalse (ifx, tlbl);
7328 /* if left is same as result */
7329 if (sameRegs (AOP (result), AOP (left)))
7331 for (; size--; offset++)
7333 if (AOP_TYPE (right) == AOP_LIT)
7335 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7336 if (bytelit == 0x0FF)
7338 /* dummy read of volatile operand */
7339 if (isOperandVolatile (left, FALSE))
7340 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7344 else if (bytelit == 0)
7346 aopPut (result, zero, offset);
7348 else if (IS_AOP_PREG (result))
7350 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7351 emitcode ("anl", "a,%s",
7352 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG));
7353 aopPut (result, "a", offset);
7356 emitcode ("anl", "%s,%s",
7357 aopGet (left, offset, FALSE, TRUE, NULL),
7358 aopGet (right, offset, FALSE, FALSE, NULL));
7362 if (AOP_TYPE (left) == AOP_ACC)
7365 emitcode("mov", "a,b");
7366 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7368 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7370 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
7371 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7372 emitcode ("anl", "a,b");
7373 aopPut (result, "a", offset);
7375 else if (aopGetUsesAcc (left, offset))
7377 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7378 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7379 aopPut (result, "a", offset);
7383 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7384 if (IS_AOP_PREG (result))
7386 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7387 aopPut (result, "a", offset);
7390 emitcode ("anl", "%s,a", aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7397 // left & result in different registers
7398 if (AOP_TYPE (result) == AOP_CRY)
7401 // if(size), result in bit
7402 // if(!size && ifx), conditional oper: if(left & right)
7403 symbol *tlbl = newiTempLabel (NULL);
7404 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
7406 emitcode ("setb", "c");
7409 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7410 && AOP_TYPE(left)==AOP_ACC)
7413 emitcode("mov", "a,b");
7414 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, NULL));
7416 else if (AOP_TYPE(left)==AOP_ACC)
7420 bool pushedB = pushB ();
7421 emitcode("mov", "b,a");
7422 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7423 emitcode("anl", "a,b");
7428 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7429 emitcode("anl", "a,b");
7432 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7434 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE, NULL));
7435 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7436 emitcode ("anl", "a,b");
7438 else if (aopGetUsesAcc (left, offset))
7440 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7441 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7445 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7446 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE, DP2_RESULT_REG));
7449 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7459 jmpTrueOrFalse (ifx, tlbl);
7465 for (; (size--); offset++)
7468 // result = left & right
7469 if (AOP_TYPE (right) == AOP_LIT)
7471 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7472 if (bytelit == 0x0FF)
7475 aopGet (left, offset, FALSE, FALSE, NULL),
7479 else if (bytelit == 0)
7481 /* dummy read of volatile operand */
7482 if (isOperandVolatile (left, FALSE))
7483 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7484 aopPut (result, zero, offset);
7487 else if (AOP_TYPE (left) == AOP_ACC)
7491 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, NULL));
7492 aopPut (result, "a", offset);
7497 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE, NULL));
7498 aopPut (result, "b", offset);
7503 // faster than result <- left, anl result,right
7504 // and better if result is SFR
7505 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7506 && AOP_TYPE(left)==AOP_ACC)
7509 emitcode("mov", "a,b");
7510 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, NULL));
7512 else if (AOP_TYPE(left)==AOP_ACC)
7516 bool pushedB = pushB ();
7517 emitcode("mov", "b,a");
7518 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7519 emitcode("anl", "a,b");
7524 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7525 emitcode("anl", "a,b");
7528 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7530 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
7531 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7532 emitcode ("anl", "a,b");
7534 else if (aopGetUsesAcc (left, offset))
7536 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7537 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7541 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7542 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE, DP2_RESULT_REG));
7544 aopPut (result, "a", offset);
7550 freeAsmop (result, NULL, ic, TRUE);
7551 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7552 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7555 /*-----------------------------------------------------------------*/
7556 /* genOr - code for or */
7557 /*-----------------------------------------------------------------*/
7559 genOr (iCode * ic, iCode * ifx)
7561 operand *left, *right, *result;
7562 int size, offset = 0;
7563 unsigned long lit = 0L;
7567 D (emitcode (";", "genOr"));
7569 AOP_OP_3_NOFATAL (ic, pushResult);
7570 AOP_SET_LOCALS (ic);
7574 genFarFarLogicOp(ic, "orl");
7580 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7582 AOP_TYPE (left), AOP_TYPE (right));
7583 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7585 AOP_SIZE (left), AOP_SIZE (right));
7588 /* if left is a literal & right is not then exchange them */
7589 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7590 #ifdef LOGIC_OPS_BROKEN
7591 || AOP_NEEDSACC (left) // I think this is a net loss now.
7595 operand *tmp = right;
7600 /* if result = right then exchange them */
7601 if (sameRegs (AOP (result), AOP (right)))
7603 operand *tmp = right;
7608 /* if right is bit then exchange them */
7609 if (AOP_TYPE (right) == AOP_CRY &&
7610 AOP_TYPE (left) != AOP_CRY)
7612 operand *tmp = right;
7616 if (AOP_TYPE (right) == AOP_LIT)
7617 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7619 size = AOP_SIZE (result);
7623 if (AOP_TYPE (left) == AOP_CRY)
7625 if (AOP_TYPE (right) == AOP_LIT)
7627 // c = bit | literal;
7630 // lit != 0 => result = 1
7631 if (AOP_TYPE (result) == AOP_CRY)
7634 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7636 continueIfTrue (ifx);
7639 emitcode ("setb", "c");
7643 // lit == 0 => result = left
7644 if (size && sameRegs (AOP (result), AOP (left)))
7646 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7651 if (AOP_TYPE (right) == AOP_CRY)
7654 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7655 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7660 symbol *tlbl = newiTempLabel (NULL);
7661 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
7662 emitcode ("setb", "c");
7663 emitcode ("jb", "%s,!tlabel",
7664 AOP (left)->aopu.aop_dir, tlbl->key + 100);
7666 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7667 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7669 jmpTrueOrFalse (ifx, tlbl);
7684 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7685 genIfxJump (ifx, "c");
7689 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7690 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7691 if ((AOP_TYPE (right) == AOP_LIT) &&
7692 (AOP_TYPE (result) == AOP_CRY) &&
7693 (AOP_TYPE (left) != AOP_CRY))
7699 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7701 continueIfTrue (ifx);
7706 // lit = 0, result = boolean(left)
7708 emitcode ("setb", "c");
7712 symbol *tlbl = newiTempLabel (NULL);
7713 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7719 genIfxJump (ifx, "a");
7727 /* if left is same as result */
7728 if (sameRegs (AOP (result), AOP (left)))
7730 for (; size--; offset++)
7732 if (AOP_TYPE (right) == AOP_LIT)
7734 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7737 /* dummy read of volatile operand */
7738 if (isOperandVolatile (left, FALSE))
7739 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7743 else if (bytelit == 0x0FF)
7745 aopPut (result, "#0xFF", offset);
7747 else if (IS_AOP_PREG (left))
7749 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7750 emitcode ("orl", "a,%s",
7751 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7752 aopPut (result, "a", offset);
7756 emitcode ("orl", "%s,%s",
7757 aopGet (left, offset, FALSE, TRUE, NULL),
7758 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7763 if (AOP_TYPE (left) == AOP_ACC)
7766 emitcode("mov", "a,b");
7767 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7769 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7771 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE, NULL));
7772 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7773 emitcode ("orl", "a,b");
7774 aopPut (result, "a", offset);
7776 else if (aopGetUsesAcc (left, offset))
7778 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7779 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7780 aopPut (result, "a", offset);
7784 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7785 if (IS_AOP_PREG (left))
7787 emitcode ("orl", "a,%s",
7788 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7789 aopPut (result, "a", offset);
7793 emitcode ("orl", "%s,a",
7794 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7802 // left & result in different registers
7803 if (AOP_TYPE (result) == AOP_CRY)
7806 // if(size), result in bit
7807 // if(!size && ifx), conditional oper: if(left | right)
7808 symbol *tlbl = newiTempLabel (NULL);
7809 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7811 emitcode ("setb", "c");
7814 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7815 && AOP_TYPE(left)==AOP_ACC)
7818 emitcode("mov", "a,b");
7819 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7821 else if (AOP_TYPE(left)==AOP_ACC)
7825 bool pushedB = pushB ();
7826 emitcode("mov", "b,a");
7827 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7828 emitcode("orl", "a,b");
7833 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7834 emitcode("orl", "a,b");
7837 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7839 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
7840 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7841 emitcode ("orl", "a,b");
7843 else if (aopGetUsesAcc (left, offset))
7845 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7846 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7850 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7851 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE, DP2_RESULT_REG));
7854 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7864 jmpTrueOrFalse (ifx, tlbl);
7870 _startLazyDPSEvaluation();
7871 for (; (size--); offset++)
7874 // result = left | right
7875 if (AOP_TYPE (right) == AOP_LIT)
7877 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7881 aopGet (left, offset, FALSE, FALSE, NULL),
7885 else if (bytelit == 0x0FF)
7887 /* dummy read of volatile operand */
7888 if (isOperandVolatile (left, FALSE))
7889 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7890 aopPut (result, "#0xFF", offset);
7894 // faster than result <- left, orl result,right
7895 // and better if result is SFR
7896 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7897 && AOP_TYPE(left)==AOP_ACC)
7900 emitcode("mov", "a,b");
7901 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7903 else if (AOP_TYPE(left)==AOP_ACC)
7907 bool pushedB = pushB ();
7908 emitcode("mov", "b,a");
7909 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7910 emitcode("orl", "a,b");
7915 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7916 emitcode("orl", "a,b");
7919 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7921 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
7922 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7923 emitcode ("orl", "a,b");
7925 else if (aopGetUsesAcc (left, offset))
7927 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7928 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7932 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7933 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE, DP2_RESULT_REG));
7935 aopPut (result, "a", offset);
7937 _endLazyDPSEvaluation();
7942 freeAsmop (result, NULL, ic, TRUE);
7943 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7944 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7947 /*-----------------------------------------------------------------*/
7948 /* genXor - code for xclusive or */
7949 /*-----------------------------------------------------------------*/
7951 genXor (iCode * ic, iCode * ifx)
7953 operand *left, *right, *result;
7954 int size, offset = 0;
7955 unsigned long lit = 0L;
7959 D (emitcode (";", "genXor"));
7961 AOP_OP_3_NOFATAL (ic, pushResult);
7962 AOP_SET_LOCALS (ic);
7966 genFarFarLogicOp(ic, "xrl");
7971 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7973 AOP_TYPE (left), AOP_TYPE (right));
7974 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7976 AOP_SIZE (left), AOP_SIZE (right));
7979 /* if left is a literal & right is not ||
7980 if left needs acc & right does not */
7981 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7982 #ifdef LOGIC_OPS_BROKEN
7983 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
7987 operand *tmp = right;
7992 /* if result = right then exchange them */
7993 if (sameRegs (AOP (result), AOP (right)))
7995 operand *tmp = right;
8000 /* if right is bit then exchange them */
8001 if (AOP_TYPE (right) == AOP_CRY &&
8002 AOP_TYPE (left) != AOP_CRY)
8004 operand *tmp = right;
8008 if (AOP_TYPE (right) == AOP_LIT)
8009 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8011 size = AOP_SIZE (result);
8015 if (AOP_TYPE (left) == AOP_CRY)
8017 if (AOP_TYPE (right) == AOP_LIT)
8019 // c = bit & literal;
8022 // lit>>1 != 0 => result = 1
8023 if (AOP_TYPE (result) == AOP_CRY)
8026 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
8028 continueIfTrue (ifx);
8031 emitcode ("setb", "c");
8038 // lit == 0, result = left
8039 if (size && sameRegs (AOP (result), AOP (left)))
8041 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
8045 // lit == 1, result = not(left)
8046 if (size && sameRegs (AOP (result), AOP (left)))
8048 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
8053 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
8054 emitcode ("cpl", "c");
8062 symbol *tlbl = newiTempLabel (NULL);
8063 if (AOP_TYPE (right) == AOP_CRY)
8066 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8070 int sizer = AOP_SIZE (right);
8072 // if val>>1 != 0, result = 1
8073 emitcode ("setb", "c");
8076 MOVA (aopGet (right, sizer - 1, FALSE, FALSE, NULL));
8078 // test the msb of the lsb
8079 emitcode ("anl", "a,#!constbyte",0xfe);
8080 emitcode ("jnz", "!tlabel", tlbl->key + 100);
8084 emitcode ("rrc", "a");
8086 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
8087 emitcode ("cpl", "c");
8095 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
8096 genIfxJump (ifx, "c");
8100 /* if left is same as result */
8101 if (sameRegs (AOP (result), AOP (left)))
8103 for (; size--; offset++)
8105 if (AOP_TYPE (right) == AOP_LIT)
8107 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
8110 /* dummy read of volatile operand */
8111 if (isOperandVolatile (left, FALSE))
8112 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8116 else if (IS_AOP_PREG (left))
8118 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8119 emitcode ("xrl", "a,%s",
8120 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG));
8121 aopPut (result, "a", offset);
8125 emitcode ("xrl", "%s,%s",
8126 aopGet (left, offset, FALSE, TRUE, NULL),
8127 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8132 if (AOP_TYPE (left) == AOP_ACC)
8135 emitcode("mov", "a,b");
8136 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8138 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
8140 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
8141 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8142 emitcode ("xrl", "a,b");
8143 aopPut (result, "a", offset);
8145 else if (aopGetUsesAcc (left, offset))
8147 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8148 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8149 aopPut (result, "a", offset);
8153 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
8154 if (IS_AOP_PREG (left))
8156 emitcode ("xrl", "a,%s",
8157 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
8158 aopPut (result, "a", offset);
8161 emitcode ("xrl", "%s,a",
8162 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
8169 // left & result in different registers
8170 if (AOP_TYPE (result) == AOP_CRY)
8173 // if(size), result in bit
8174 // if(!size && ifx), conditional oper: if(left ^ right)
8175 symbol *tlbl = newiTempLabel (NULL);
8176 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
8179 emitcode ("setb", "c");
8182 if ((AOP_TYPE (right) == AOP_LIT) &&
8183 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
8185 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8187 else if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
8188 && AOP_TYPE(left)==AOP_ACC)
8191 emitcode("mov", "a,b");
8192 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8194 else if (AOP_TYPE(left)==AOP_ACC)
8198 bool pushedB = pushB ();
8199 emitcode("mov", "b,a");
8200 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8201 emitcode("xrl", "a,b");
8206 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8207 emitcode("xrl", "a,b");
8210 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
8212 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
8213 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8214 emitcode ("xrl", "a,b");
8216 else if (aopGetUsesAcc (left, offset))
8218 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8219 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8223 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
8224 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
8227 emitcode ("jnz", "!tlabel", tlbl->key + 100);
8237 jmpTrueOrFalse (ifx, tlbl);
8241 for (; (size--); offset++)
8244 // result = left ^ right
8245 if (AOP_TYPE (right) == AOP_LIT)
8247 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
8251 aopGet (left, offset, FALSE, FALSE, NULL),
8255 D (emitcode (";", "better literal XOR."));
8256 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8257 emitcode ("xrl", "a, %s",
8258 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8262 // faster than result <- left, anl result,right
8263 // and better if result is SFR
8264 if (AOP_TYPE (left) == AOP_ACC)
8266 emitcode ("xrl", "a,%s",
8267 aopGet (right, offset,
8268 FALSE, FALSE, DP2_RESULT_REG));
8272 char *rOp = aopGet (right, offset, FALSE, FALSE, NULL);
8273 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
8275 emitcode("mov", "b,a");
8279 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8280 emitcode ("xrl", "a,%s", rOp);
8283 aopPut (result, "a", offset);
8289 freeAsmop (result, NULL, ic, TRUE);
8290 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
8291 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
8294 /*-----------------------------------------------------------------*/
8295 /* genInline - write the inline code out */
8296 /*-----------------------------------------------------------------*/
8298 genInline (iCode * ic)
8300 char *buffer, *bp, *bp1;
8302 D (emitcode (";", "genInline"));
8304 _G.inLine += (!options.asmpeep);
8306 buffer = bp = bp1 = Safe_strdup(IC_INLINE(ic));
8308 /* emit each line as a code */
8319 /* Add \n for labels, not dirs such as c:\mydir */
8320 if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
8334 /* emitcode("",buffer); */
8335 _G.inLine -= (!options.asmpeep);
8338 /*-----------------------------------------------------------------*/
8339 /* genRRC - rotate right with carry */
8340 /*-----------------------------------------------------------------*/
8344 operand *left, *result;
8348 D (emitcode (";", "genRRC"));
8350 /* rotate right with carry */
8351 left = IC_LEFT (ic);
8352 result = IC_RESULT (ic);
8353 aopOp (left, ic, FALSE, FALSE);
8354 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8356 /* move it to the result */
8357 size = AOP_SIZE (result);
8361 _startLazyDPSEvaluation ();
8364 l = aopGet (left, offset, FALSE, FALSE, NULL);
8366 emitcode ("rrc", "a");
8367 if (AOP_SIZE (result) > 1)
8368 aopPut (result, "a", offset--);
8370 _endLazyDPSEvaluation ();
8372 /* now we need to put the carry into the
8373 highest order byte of the result */
8374 if (AOP_SIZE (result) > 1)
8376 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE, NULL);
8379 emitcode ("mov", "acc.7,c");
8380 aopPut (result, "a", AOP_SIZE (result) - 1);
8381 freeAsmop (result, NULL, ic, TRUE);
8382 freeAsmop (left, NULL, ic, TRUE);
8385 /*-----------------------------------------------------------------*/
8386 /* genRLC - generate code for rotate left with carry */
8387 /*-----------------------------------------------------------------*/
8391 operand *left, *result;
8395 D (emitcode (";", "genRLC"));
8397 /* rotate right with carry */
8398 left = IC_LEFT (ic);
8399 result = IC_RESULT (ic);
8400 aopOp (left, ic, FALSE, FALSE);
8401 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8403 /* move it to the result */
8404 size = AOP_SIZE (result);
8408 l = aopGet (left, offset, FALSE, FALSE, NULL);
8410 emitcode ("add", "a,acc");
8411 if (AOP_SIZE (result) > 1)
8413 aopPut (result, "a", offset++);
8416 _startLazyDPSEvaluation ();
8419 l = aopGet (left, offset, FALSE, FALSE, NULL);
8421 emitcode ("rlc", "a");
8422 if (AOP_SIZE (result) > 1)
8423 aopPut (result, "a", offset++);
8425 _endLazyDPSEvaluation ();
8427 /* now we need to put the carry into the
8428 highest order byte of the result */
8429 if (AOP_SIZE (result) > 1)
8431 l = aopGet (result, 0, FALSE, FALSE, NULL);
8434 emitcode ("mov", "acc.0,c");
8435 aopPut (result, "a", 0);
8436 freeAsmop (result, NULL, ic, TRUE);
8437 freeAsmop (left, NULL, ic, TRUE);
8440 /*-----------------------------------------------------------------*/
8441 /* genGetHbit - generates code get highest order bit */
8442 /*-----------------------------------------------------------------*/
8444 genGetHbit (iCode * ic)
8446 operand *left, *result;
8448 D (emitcode (";", "genGetHbit"));
8450 left = IC_LEFT (ic);
8451 result = IC_RESULT (ic);
8452 aopOp (left, ic, FALSE, FALSE);
8453 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8455 /* get the highest order byte into a */
8456 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
8457 if (AOP_TYPE (result) == AOP_CRY)
8459 emitcode ("rlc", "a");
8464 emitcode ("rl", "a");
8465 emitcode ("anl", "a,#1");
8470 freeAsmop (result, NULL, ic, TRUE);
8471 freeAsmop (left, NULL, ic, TRUE);
8474 /*-----------------------------------------------------------------*/
8475 /* genSwap - generates code to swap nibbles or bytes */
8476 /*-----------------------------------------------------------------*/
8478 genSwap (iCode * ic)
8480 operand *left, *result;
8482 D(emitcode ("; genSwap",""));
8484 left = IC_LEFT (ic);
8485 result = IC_RESULT (ic);
8486 aopOp (left, ic, FALSE, FALSE);
8487 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8489 _startLazyDPSEvaluation ();
8490 switch (AOP_SIZE (left))
8492 case 1: /* swap nibbles in byte */
8493 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
8494 emitcode ("swap", "a");
8495 aopPut (result, "a", 0);
8497 case 2: /* swap bytes in word */
8498 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
8500 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
8501 aopPut (result, aopGet (left, 1, FALSE, FALSE, NULL), 0);
8502 aopPut (result, "a", 1);
8504 else if (operandsEqu (left, result))
8507 bool pushedB = FALSE, leftInB = FALSE;
8509 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
8510 if (AOP_NEEDSACC (left) || AOP_NEEDSACC (result))
8513 emitcode ("mov", "b,a");
8517 aopPut (result, aopGet (left, 1, FALSE, FALSE, NULL), 0);
8518 aopPut (result, reg, 1);
8525 aopPut (result, aopGet (left, 1, FALSE, FALSE, NULL), 0);
8526 aopPut (result, aopGet (left, 0, FALSE, FALSE, NULL), 1);
8530 wassertl(FALSE, "unsupported SWAP operand size");
8532 _endLazyDPSEvaluation ();
8534 freeAsmop (result, NULL, ic, TRUE);
8535 freeAsmop (left, NULL, ic, TRUE);
8538 /*-----------------------------------------------------------------*/
8539 /* AccRol - rotate left accumulator by known count */
8540 /*-----------------------------------------------------------------*/
8542 AccRol (int shCount)
8544 shCount &= 0x0007; // shCount : 0..7
8551 emitcode ("rl", "a");
8554 emitcode ("rl", "a");
8555 emitcode ("rl", "a");
8558 emitcode ("swap", "a");
8559 emitcode ("rr", "a");
8562 emitcode ("swap", "a");
8565 emitcode ("swap", "a");
8566 emitcode ("rl", "a");
8569 emitcode ("rr", "a");
8570 emitcode ("rr", "a");
8573 emitcode ("rr", "a");
8578 /*-----------------------------------------------------------------*/
8579 /* AccLsh - left shift accumulator by known count */
8580 /*-----------------------------------------------------------------*/
8582 AccLsh (int shCount)
8587 emitcode ("add", "a,acc");
8588 else if (shCount == 2)
8590 emitcode ("add", "a,acc");
8591 emitcode ("add", "a,acc");
8595 /* rotate left accumulator */
8597 /* and kill the lower order bits */
8598 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
8603 /*-----------------------------------------------------------------*/
8604 /* AccRsh - right shift accumulator by known count */
8605 /*-----------------------------------------------------------------*/
8607 AccRsh (int shCount)
8614 emitcode ("rrc", "a");
8618 /* rotate right accumulator */
8619 AccRol (8 - shCount);
8620 /* and kill the higher order bits */
8621 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
8626 #ifdef BETTER_LITERAL_SHIFT
8627 /*-----------------------------------------------------------------*/
8628 /* AccSRsh - signed right shift accumulator by known count */
8629 /*-----------------------------------------------------------------*/
8631 AccSRsh (int shCount)
8638 emitcode ("mov", "c,acc.7");
8639 emitcode ("rrc", "a");
8641 else if (shCount == 2)
8643 emitcode ("mov", "c,acc.7");
8644 emitcode ("rrc", "a");
8645 emitcode ("mov", "c,acc.7");
8646 emitcode ("rrc", "a");
8650 tlbl = newiTempLabel (NULL);
8651 /* rotate right accumulator */
8652 AccRol (8 - shCount);
8653 /* and kill the higher order bits */
8654 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
8655 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8656 emitcode ("orl", "a,#!constbyte",
8657 (unsigned char) ~SRMask[shCount]);
8664 #ifdef BETTER_LITERAL_SHIFT
8665 /*-----------------------------------------------------------------*/
8666 /* shiftR1Left2Result - shift right one byte from left to result */
8667 /*-----------------------------------------------------------------*/
8669 shiftR1Left2Result (operand * left, int offl,
8670 operand * result, int offr,
8671 int shCount, int sign)
8673 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
8674 /* shift right accumulator */
8679 aopPut (result, "a", offr);
8683 #ifdef BETTER_LITERAL_SHIFT
8684 /*-----------------------------------------------------------------*/
8685 /* shiftL1Left2Result - shift left one byte from left to result */
8686 /*-----------------------------------------------------------------*/
8688 shiftL1Left2Result (operand * left, int offl,
8689 operand * result, int offr, int shCount)
8692 l = aopGet (left, offl, FALSE, FALSE, NULL);
8694 /* shift left accumulator */
8696 aopPut (result, "a", offr);
8700 #ifdef BETTER_LITERAL_SHIFT
8701 /*-----------------------------------------------------------------*/
8702 /* movLeft2Result - move byte from left to result */
8703 /*-----------------------------------------------------------------*/
8705 movLeft2Result (operand * left, int offl,
8706 operand * result, int offr, int sign)
8709 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8711 l = aopGet (left, offl, FALSE, FALSE, NULL);
8713 if (*l == '@' && (IS_AOP_PREG (result)))
8715 emitcode ("mov", "a,%s", l);
8716 aopPut (result, "a", offr);
8722 aopPut (result, l, offr);
8726 /* MSB sign in acc.7 ! */
8727 if (getDataSize (left) == offl + 1)
8730 aopPut (result, "a", offr);
8738 #ifdef BETTER_LITERAL_SHIFT
8739 /*-----------------------------------------------------------------*/
8740 /* AccAXRrl1 - right rotate a:x by 1 */
8741 /*-----------------------------------------------------------------*/
8745 emitcode ("mov", "c,acc.0");
8746 emitcode ("xch", "a,%s", x);
8747 emitcode ("rrc", "a");
8748 emitcode ("xch", "a,%s", x);
8749 emitcode ("rrc", "a");
8753 #ifdef BETTER_LITERAL_SHIFT
8755 /*-----------------------------------------------------------------*/
8756 /* AccAXLrl1 - left rotate a:x by 1 */
8757 /*-----------------------------------------------------------------*/
8761 emitcode ("mov", "c,acc.7");
8762 emitcode ("xch", "a,%s", x);
8763 emitcode ("rlc", "a");
8764 emitcode ("xch", "a,%s", x);
8765 emitcode ("rlc", "a");
8769 #ifdef BETTER_LITERAL_SHIFT
8770 /*-----------------------------------------------------------------*/
8771 /* AccAXRsh1 - right shift c->a:x->c by 1 */
8772 /*-----------------------------------------------------------------*/
8776 emitcode ("rrc", "a");
8777 emitcode ("xch", "a,%s", x);
8778 emitcode ("rrc", "a");
8779 emitcode ("xch", "a,%s", x);
8783 #ifdef BETTER_LITERAL_SHIFT
8784 /*-----------------------------------------------------------------*/
8785 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8786 /*-----------------------------------------------------------------*/
8790 emitcode ("xch", "a,%s", x);
8791 emitcode ("add", "a,acc");
8792 emitcode ("xch", "a,%s", x);
8793 emitcode ("rlc", "a");
8797 #ifdef BETTER_LITERAL_SHIFT
8798 /*-----------------------------------------------------------------*/
8799 /* AccAXLsh - left shift a:x by known count (0..7) */
8800 /*-----------------------------------------------------------------*/
8802 AccAXLsh (char *x, int shCount)
8817 case 5: // AAAAABBB:CCCCCDDD
8819 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8821 emitcode ("anl", "a,#!constbyte",
8822 SLMask[shCount]); // BBB00000:CCCCCDDD
8824 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8826 AccRol (shCount); // DDDCCCCC:BBB00000
8828 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8830 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8832 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8834 emitcode ("anl", "a,#!constbyte",
8835 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8837 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8839 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8842 case 6: // AAAAAABB:CCCCCCDD
8843 emitcode ("anl", "a,#!constbyte",
8844 SRMask[shCount]); // 000000BB:CCCCCCDD
8846 AccAXRrl1 (x); // D000000B:BCCCCCCD
8847 AccAXRrl1 (x); // DD000000:BBCCCCCC
8848 emitcode ("xch", "a,%s", x); // BBCCCCCC:DD000000
8850 emitcode ("mov", "c,acc.0"); // c = B
8851 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8852 emitcode("rrc","a");
8853 emitcode("xch","a,%s", x);
8854 emitcode("rrc","a");
8855 emitcode("mov","c,acc.0"); //<< get correct bit
8856 emitcode("xch","a,%s", x);
8858 emitcode("rrc","a");
8859 emitcode("xch","a,%s", x);
8860 emitcode("rrc","a");
8861 emitcode("xch","a,%s", x);
8864 case 7: // a:x <<= 7
8866 emitcode ("anl", "a,#!constbyte",
8867 SRMask[shCount]); // 0000000B:CCCCCCCD
8869 AccAXRrl1 (x); // D0000000:BCCCCCCC
8871 emitcode ("xch", "a,%s", x); // BCCCCCCC:D0000000
8880 #ifdef BETTER_LITERAL_SHIFT
8882 /*-----------------------------------------------------------------*/
8883 /* AccAXRsh - right shift a:x known count (0..7) */
8884 /*-----------------------------------------------------------------*/
8886 AccAXRsh (char *x, int shCount)
8894 AccAXRsh1 (x); // 0->a:x
8899 AccAXRsh1 (x); // 0->a:x
8902 AccAXRsh1 (x); // 0->a:x
8907 case 5: // AAAAABBB:CCCCCDDD = a:x
8909 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8911 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8913 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8915 emitcode ("anl", "a,#!constbyte",
8916 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8918 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8920 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8922 emitcode ("anl", "a,#!constbyte",
8923 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8925 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8927 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8929 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8932 case 6: // AABBBBBB:CCDDDDDD
8934 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDE
8935 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8937 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8939 emitcode ("anl", "a,#!constbyte",
8940 SRMask[shCount]); // 000000AA:BBBBBBCC
8943 case 7: // ABBBBBBB:CDDDDDDD
8945 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8947 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8949 emitcode ("anl", "a,#!constbyte",
8950 SRMask[shCount]); // 0000000A:BBBBBBBC
8959 #ifdef BETTER_LITERAL_SHIFT
8960 /*-----------------------------------------------------------------*/
8961 /* AccAXRshS - right shift signed a:x known count (0..7) */
8962 /*-----------------------------------------------------------------*/
8964 AccAXRshS (char *x, int shCount)
8972 emitcode ("mov", "c,acc.7");
8973 AccAXRsh1 (x); // s->a:x
8977 emitcode ("mov", "c,acc.7");
8978 AccAXRsh1 (x); // s->a:x
8980 emitcode ("mov", "c,acc.7");
8981 AccAXRsh1 (x); // s->a:x
8986 case 5: // AAAAABBB:CCCCCDDD = a:x
8988 tlbl = newiTempLabel (NULL);
8989 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8991 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8993 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8995 emitcode ("anl", "a,#!constbyte",
8996 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8998 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
9000 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
9002 emitcode ("anl", "a,#!constbyte",
9003 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
9005 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
9007 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
9009 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
9011 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
9012 emitcode ("orl", "a,#!constbyte",
9013 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
9016 break; // SSSSAAAA:BBBCCCCC
9018 case 6: // AABBBBBB:CCDDDDDD
9020 tlbl = newiTempLabel (NULL);
9022 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
9023 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
9025 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
9027 emitcode ("anl", "a,#!constbyte",
9028 SRMask[shCount]); // 000000AA:BBBBBBCC
9030 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
9031 emitcode ("orl", "a,#!constbyte",
9032 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
9036 case 7: // ABBBBBBB:CDDDDDDD
9038 tlbl = newiTempLabel (NULL);
9040 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
9042 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
9044 emitcode ("anl", "a,#!constbyte",
9045 SRMask[shCount]); // 0000000A:BBBBBBBC
9047 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
9048 emitcode ("orl", "a,#!constbyte",
9049 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
9059 #ifdef BETTER_LITERAL_SHIFT
9061 _loadLeftIntoAx(char **lsb,
9067 // Get the initial value from left into a pair of registers.
9068 // MSB must be in A, LSB can be any register.
9070 // If the result is held in registers, it is an optimization
9071 // if the LSB can be held in the register which will hold the,
9072 // result LSB since this saves us from having to copy it into
9073 // the result following AccAXLsh.
9075 // If the result is addressed indirectly, this is not a gain.
9076 if (AOP_NEEDSACC(result))
9080 _startLazyDPSEvaluation();
9081 if (AOP_TYPE(left) == AOP_DPTR2)
9084 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE, NULL));
9085 // get LSB in DP2_RESULT_REG.
9086 leftByte = aopGet (left, offl, FALSE, FALSE, DP2_RESULT_REG);
9087 assert(!strcmp(leftByte, DP2_RESULT_REG));
9091 // get LSB into DP2_RESULT_REG
9092 leftByte = aopGet (left, offl, FALSE, FALSE, NULL);
9093 if (strcmp(leftByte, DP2_RESULT_REG))
9096 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
9099 leftByte = aopGet (left, offl + MSB16, FALSE, FALSE, NULL);
9100 assert(strcmp(leftByte, DP2_RESULT_REG));
9103 _endLazyDPSEvaluation();
9104 *lsb = DP2_RESULT_REG;
9108 if (sameRegs (AOP (result), AOP (left)) &&
9109 ((offl + MSB16) == offr))
9111 /* don't crash result[offr] */
9112 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
9113 emitcode ("xch", "a,%s",
9114 aopGet (left, offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
9118 movLeft2Result (left, offl, result, offr, 0);
9119 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE, NULL));
9121 *lsb = aopGet (result, offr, FALSE, FALSE, DP2_RESULT_REG);
9122 assert(strcmp(*lsb,"a"));
9127 _storeAxResults(char *lsb,
9131 _startLazyDPSEvaluation();
9132 if (AOP_NEEDSACC(result))
9134 /* We have to explicitly update the result LSB.
9136 emitcode ("xch","a,%s", lsb);
9137 aopPut (result, "a", offr);
9138 emitcode ("mov","a,%s", lsb);
9140 if (getDataSize (result) > 1)
9142 aopPut (result, "a", offr + MSB16);
9144 _endLazyDPSEvaluation();
9147 /*-----------------------------------------------------------------*/
9148 /* shiftL2Left2Result - shift left two bytes from left to result */
9149 /*-----------------------------------------------------------------*/
9151 shiftL2Left2Result (operand * left, int offl,
9152 operand * result, int offr, int shCount)
9156 _loadLeftIntoAx(&lsb, left, result, offl, offr);
9158 AccAXLsh (lsb, shCount);
9160 _storeAxResults(lsb, result, offr);
9164 #ifdef BETTER_LITERAL_SHIFT
9165 /*-----------------------------------------------------------------*/
9166 /* shiftR2Left2Result - shift right two bytes from left to result */
9167 /*-----------------------------------------------------------------*/
9169 shiftR2Left2Result (operand * left, int offl,
9170 operand * result, int offr,
9171 int shCount, int sign)
9175 _loadLeftIntoAx(&lsb, left, result, offl, offr);
9177 /* a:x >> shCount (x = lsb(result)) */
9180 AccAXRshS(lsb, shCount);
9184 AccAXRsh(lsb, shCount);
9187 _storeAxResults(lsb, result, offr);
9191 /*-----------------------------------------------------------------*/
9192 /* shiftLLeftOrResult - shift left one byte from left, or to result */
9193 /*-----------------------------------------------------------------*/
9195 shiftLLeftOrResult (operand * left, int offl,
9196 operand * result, int offr, int shCount)
9198 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
9199 /* shift left accumulator */
9201 /* or with result */
9202 emitcode ("orl", "a,%s",
9203 aopGet (result, offr, FALSE, FALSE, DP2_RESULT_REG));
9204 /* back to result */
9205 aopPut (result, "a", offr);
9210 /*-----------------------------------------------------------------*/
9211 /* shiftRLeftOrResult - shift right one byte from left,or to result */
9212 /*-----------------------------------------------------------------*/
9214 shiftRLeftOrResult (operand * left, int offl,
9215 operand * result, int offr, int shCount)
9217 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
9218 /* shift right accumulator */
9220 /* or with result */
9221 emitcode ("orl", "a,%s",
9222 aopGet (result, offr, FALSE, FALSE, DP2_RESULT_REG));
9223 /* back to result */
9224 aopPut (result, "a", offr);
9228 #ifdef BETTER_LITERAL_SHIFT
9229 /*-----------------------------------------------------------------*/
9230 /* genlshOne - left shift a one byte quantity by known count */
9231 /*-----------------------------------------------------------------*/
9233 genlshOne (operand * result, operand * left, int shCount)
9235 D (emitcode (";", "genlshOne"));
9237 shiftL1Left2Result (left, LSB, result, LSB, shCount);
9241 #ifdef BETTER_LITERAL_SHIFT
9242 /*-----------------------------------------------------------------*/
9243 /* genlshTwo - left shift two bytes by known amount != 0 */
9244 /*-----------------------------------------------------------------*/
9246 genlshTwo (operand * result, operand * left, int shCount)
9250 D (emitcode (";", "genlshTwo"));
9252 size = getDataSize (result);
9254 /* if shCount >= 8 */
9259 _startLazyDPSEvaluation();
9265 _endLazyDPSEvaluation();
9266 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
9267 aopPut (result, zero, LSB);
9271 movLeft2Result (left, LSB, result, MSB16, 0);
9272 aopPut (result, zero, LSB);
9273 _endLazyDPSEvaluation();
9278 aopPut (result, zero, LSB);
9279 _endLazyDPSEvaluation();
9283 /* 1 <= shCount <= 7 */
9287 shiftL1Left2Result (left, LSB, result, LSB, shCount);
9289 shiftL2Left2Result (left, LSB, result, LSB, shCount);
9296 /*-----------------------------------------------------------------*/
9297 /* shiftLLong - shift left one long from left to result */
9298 /* offl = LSB or MSB16 */
9299 /*-----------------------------------------------------------------*/
9301 shiftLLong (operand * left, operand * result, int offr)
9304 int size = AOP_SIZE (result);
9306 if (size >= LSB + offr)
9308 l = aopGet (left, LSB, FALSE, FALSE, NULL);
9310 emitcode ("add", "a,acc");
9311 if (sameRegs (AOP (left), AOP (result)) &&
9312 size >= MSB16 + offr && offr != LSB)
9313 emitcode ("xch", "a,%s",
9314 aopGet (left, LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
9316 aopPut (result, "a", LSB + offr);
9319 if (size >= MSB16 + offr)
9321 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
9323 l = aopGet (left, MSB16, FALSE, FALSE, TRUE);
9326 emitcode ("rlc", "a");
9327 if (sameRegs (AOP (left), AOP (result)) &&
9328 size >= MSB24 + offr && offr != LSB)
9329 emitcode ("xch", "a,%s",
9330 aopGet (left, MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
9332 aopPut (result, "a", MSB16 + offr);
9335 if (size >= MSB24 + offr)
9337 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
9339 l = aopGet (left, MSB24, FALSE, FALSE, NULL);
9342 emitcode ("rlc", "a");
9343 if (sameRegs (AOP (left), AOP (result)) &&
9344 size >= MSB32 + offr && offr != LSB)
9345 emitcode ("xch", "a,%s",
9346 aopGet (left, MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
9348 aopPut (result, "a", MSB24 + offr);
9351 if (size > MSB32 + offr)
9353 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
9355 l = aopGet (left, MSB32, FALSE, FALSE, NULL);
9358 emitcode ("rlc", "a");
9359 aopPut (result, "a", MSB32 + offr);
9362 aopPut (result, zero, LSB);
9368 /*-----------------------------------------------------------------*/
9369 /* genlshFour - shift four byte by a known amount != 0 */
9370 /*-----------------------------------------------------------------*/
9372 genlshFour (operand * result, operand * left, int shCount)
9376 D (emitcode (";", "genlshFour"));
9378 size = AOP_SIZE (result);
9380 /* if shifting more that 3 bytes */
9385 /* lowest order of left goes to the highest
9386 order of the destination */
9387 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
9389 movLeft2Result (left, LSB, result, MSB32, 0);
9390 aopPut (result, zero, LSB);
9391 aopPut (result, zero, MSB16);
9392 aopPut (result, zero, MSB24);
9396 /* more than two bytes */
9397 else if (shCount >= 16)
9399 /* lower order two bytes goes to higher order two bytes */
9401 /* if some more remaining */
9403 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
9406 movLeft2Result (left, MSB16, result, MSB32, 0);
9407 movLeft2Result (left, LSB, result, MSB24, 0);
9409 aopPut (result, zero, MSB16);
9410 aopPut (result, zero, LSB);
9414 /* if more than 1 byte */
9415 else if (shCount >= 8)
9417 /* lower order three bytes goes to higher order three bytes */
9422 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
9424 movLeft2Result (left, LSB, result, MSB16, 0);
9430 movLeft2Result (left, MSB24, result, MSB32, 0);
9431 movLeft2Result (left, MSB16, result, MSB24, 0);
9432 movLeft2Result (left, LSB, result, MSB16, 0);
9433 aopPut (result, zero, LSB);
9435 else if (shCount == 1)
9436 shiftLLong (left, result, MSB16);
9439 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
9440 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
9441 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
9442 aopPut (result, zero, LSB);
9447 /* 1 <= shCount <= 7 */
9448 else if (shCount <= 2)
9450 shiftLLong (left, result, LSB);
9452 shiftLLong (result, result, LSB);
9454 /* 3 <= shCount <= 7, optimize */
9457 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
9458 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
9459 shiftL2Left2Result (left, LSB, result, LSB, shCount);
9464 #ifdef BETTER_LITERAL_SHIFT
9465 /*-----------------------------------------------------------------*/
9466 /* genLeftShiftLiteral - left shifting by known count */
9467 /*-----------------------------------------------------------------*/
9469 genLeftShiftLiteral (operand * left,
9474 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9477 size = getSize (operandType (result));
9479 D (emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
9481 /* We only handle certain easy cases so far. */
9483 && (shCount < (size * 8))
9487 D(emitcode (";", "genLeftShiftLiteral wimping out"););
9491 freeAsmop (right, NULL, ic, TRUE);
9493 aopOp(left, ic, FALSE, FALSE);
9494 aopOp(result, ic, FALSE, AOP_USESDPTR(left));
9497 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
9499 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
9500 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
9502 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
9505 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
9507 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
9508 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
9510 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
9516 emitcode ("; shift left ", "result %d, left %d", size,
9520 /* I suppose that the left size >= result size */
9523 _startLazyDPSEvaluation();
9526 movLeft2Result (left, size, result, size, 0);
9528 _endLazyDPSEvaluation();
9530 else if (shCount >= (size * 8))
9532 _startLazyDPSEvaluation();
9535 aopPut (result, zero, size);
9537 _endLazyDPSEvaluation();
9544 genlshOne (result, left, shCount);
9548 genlshTwo (result, left, shCount);
9552 genlshFour (result, left, shCount);
9556 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9557 "*** ack! mystery literal shift!\n");
9561 freeAsmop (result, NULL, ic, TRUE);
9562 freeAsmop (left, NULL, ic, TRUE);
9567 /*-----------------------------------------------------------------*/
9568 /* genLeftShift - generates code for left shifting */
9569 /*-----------------------------------------------------------------*/
9571 genLeftShift (iCode * ic)
9573 operand *left, *right, *result;
9576 symbol *tlbl, *tlbl1;
9579 D (emitcode (";", "genLeftShift"));
9581 right = IC_RIGHT (ic);
9582 left = IC_LEFT (ic);
9583 result = IC_RESULT (ic);
9585 aopOp (right, ic, FALSE, FALSE);
9588 #ifdef BETTER_LITERAL_SHIFT
9589 /* if the shift count is known then do it
9590 as efficiently as possible */
9591 if (AOP_TYPE (right) == AOP_LIT)
9593 if (genLeftShiftLiteral (left, right, result, ic))
9600 /* shift count is unknown then we have to form
9601 a loop get the loop count in B : Note: we take
9602 only the lower order byte since shifting
9603 more that 32 bits make no sense anyway, ( the
9604 largest size of an object can be only 32 bits ) */
9607 if (AOP_TYPE (right) == AOP_LIT)
9609 /* Really should be handled by genLeftShiftLiteral,
9610 * but since I'm too lazy to fix that today, at least we can make
9611 * some small improvement.
9613 emitcode("mov", "b,#!constbyte",
9614 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9618 MOVB (aopGet (right, 0, FALSE, FALSE, "b"));
9619 emitcode ("inc", "b");
9621 freeAsmop (right, NULL, ic, TRUE);
9622 aopOp (left, ic, FALSE, FALSE);
9623 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9625 /* now move the left to the result if they are not the same */
9626 if (!sameRegs (AOP (left), AOP (result)) &&
9627 AOP_SIZE (result) > 1)
9630 size = AOP_SIZE (result);
9632 _startLazyDPSEvaluation ();
9635 l = aopGet (left, offset, FALSE, TRUE, NULL);
9636 if (*l == '@' && (IS_AOP_PREG (result)))
9639 emitcode ("mov", "a,%s", l);
9640 aopPut (result, "a", offset);
9643 aopPut (result, l, offset);
9646 _endLazyDPSEvaluation ();
9649 tlbl = newiTempLabel (NULL);
9650 size = AOP_SIZE (result);
9652 tlbl1 = newiTempLabel (NULL);
9654 /* if it is only one byte then */
9657 symbol *tlbl1 = newiTempLabel (NULL);
9659 l = aopGet (left, 0, FALSE, FALSE, NULL);
9661 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9663 emitcode ("add", "a,acc");
9665 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9667 aopPut (result, "a", 0);
9671 reAdjustPreg (AOP (result));
9673 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9675 l = aopGet (result, offset, FALSE, FALSE, NULL);
9677 emitcode ("add", "a,acc");
9678 aopPut (result, "a", offset++);
9679 _startLazyDPSEvaluation ();
9682 l = aopGet (result, offset, FALSE, FALSE, NULL);
9684 emitcode ("rlc", "a");
9685 aopPut (result, "a", offset++);
9687 _endLazyDPSEvaluation ();
9688 reAdjustPreg (AOP (result));
9691 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9694 freeAsmop (result, NULL, ic, TRUE);
9695 freeAsmop (left, NULL, ic, TRUE);
9698 #ifdef BETTER_LITERAL_SHIFT
9699 /*-----------------------------------------------------------------*/
9700 /* genrshOne - right shift a one byte quantity by known count */
9701 /*-----------------------------------------------------------------*/
9703 genrshOne (operand * result, operand * left,
9704 int shCount, int sign)
9706 D (emitcode (";", "genrshOne"));
9708 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9712 #ifdef BETTER_LITERAL_SHIFT
9713 /*-----------------------------------------------------------------*/
9714 /* genrshTwo - right shift two bytes by known amount != 0 */
9715 /*-----------------------------------------------------------------*/
9717 genrshTwo (operand * result, operand * left,
9718 int shCount, int sign)
9720 D (emitcode (";", "genrshTwo"));
9722 /* if shCount >= 8 */
9726 _startLazyDPSEvaluation();
9728 shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
9730 movLeft2Result (left, MSB16, result, LSB, sign);
9731 addSign (result, MSB16, sign);
9732 _endLazyDPSEvaluation();
9735 /* 1 <= shCount <= 7 */
9737 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9741 /*-----------------------------------------------------------------*/
9742 /* shiftRLong - shift right one long from left to result */
9743 /* offl = LSB or MSB16 */
9744 /*-----------------------------------------------------------------*/
9746 shiftRLong (operand * left, int offl,
9747 operand * result, int sign)
9749 bool overlapping = regsInCommon (left, result) || operandsEqu(left, result);
9751 if (overlapping && offl>1)
9753 // we are in big trouble, but this shouldn't happen
9754 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9757 MOVA (aopGet (left, MSB32, FALSE, FALSE, NULL));
9764 emitcode ("rlc", "a");
9765 emitcode ("subb", "a,acc");
9766 emitcode ("xch", "a,%s",
9767 aopGet(left, MSB32, FALSE, FALSE, DP2_RESULT_REG));
9771 aopPut (result, zero, MSB32);
9777 emitcode ("clr", "c");
9781 emitcode ("mov", "c,acc.7");
9784 emitcode ("rrc", "a");
9786 if (overlapping && offl==MSB16)
9788 emitcode ("xch", "a,%s", aopGet (left, MSB24, FALSE, FALSE, DP2_RESULT_REG));
9792 aopPut (result, "a", MSB32 - offl);
9793 MOVA (aopGet (left, MSB24, FALSE, FALSE, NULL));
9796 emitcode ("rrc", "a");
9798 if (overlapping && offl==MSB16)
9800 emitcode ("xch", "a,%s", aopGet (left, MSB16, FALSE, FALSE, DP2_RESULT_REG));
9804 aopPut (result, "a", MSB24 - offl);
9805 MOVA (aopGet (left, MSB16, FALSE, FALSE, NULL));
9808 emitcode ("rrc", "a");
9811 aopPut (result, "a", MSB16 - offl);
9815 if (overlapping && offl==MSB16)
9817 emitcode ("xch", "a,%s", aopGet (left, LSB, FALSE, FALSE, DP2_RESULT_REG));
9821 aopPut (result, "a", MSB16 - offl);
9822 MOVA (aopGet (left, LSB, FALSE, FALSE, NULL));
9824 emitcode ("rrc", "a");
9825 aopPut (result, "a", LSB);
9829 /*-----------------------------------------------------------------*/
9830 /* genrshFour - shift four byte by a known amount != 0 */
9831 /*-----------------------------------------------------------------*/
9833 genrshFour (operand * result, operand * left,
9834 int shCount, int sign)
9836 D (emitcode (";", "genrshFour"));
9838 /* if shifting more that 3 bytes */
9842 _startLazyDPSEvaluation();
9844 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9846 movLeft2Result (left, MSB32, result, LSB, sign);
9847 addSign (result, MSB16, sign);
9848 _endLazyDPSEvaluation();
9850 else if (shCount >= 16)
9853 _startLazyDPSEvaluation();
9855 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9858 movLeft2Result (left, MSB24, result, LSB, 0);
9859 movLeft2Result (left, MSB32, result, MSB16, sign);
9861 addSign (result, MSB24, sign);
9862 _endLazyDPSEvaluation();
9864 else if (shCount >= 8)
9867 _startLazyDPSEvaluation();
9870 shiftRLong (left, MSB16, result, sign);
9872 else if (shCount == 0)
9874 movLeft2Result (left, MSB16, result, LSB, 0);
9875 movLeft2Result (left, MSB24, result, MSB16, 0);
9876 movLeft2Result (left, MSB32, result, MSB24, sign);
9877 addSign (result, MSB32, sign);
9881 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9882 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9883 /* the last shift is signed */
9884 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9885 addSign (result, MSB32, sign);
9887 _endLazyDPSEvaluation();
9891 /* 1 <= shCount <= 7 */
9894 shiftRLong (left, LSB, result, sign);
9896 shiftRLong (result, LSB, result, sign);
9900 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9901 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9902 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9907 #ifdef BETTER_LITERAL_SHIFT
9908 /*-----------------------------------------------------------------*/
9909 /* genRightShiftLiteral - right shifting by known count */
9910 /*-----------------------------------------------------------------*/
9912 genRightShiftLiteral (operand * left,
9918 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9921 size = getSize (operandType (result));
9923 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
9925 /* We only handle certain easy cases so far. */
9927 && (shCount < (size * 8))
9932 D(emitcode (";", "genRightShiftLiteral wimping out"););
9936 freeAsmop (right, NULL, ic, TRUE);
9938 aopOp (left, ic, FALSE, FALSE);
9939 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9942 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9946 /* test the LEFT size !!! */
9948 /* I suppose that the left size >= result size */
9951 size = getDataSize (result);
9952 _startLazyDPSEvaluation();
9954 movLeft2Result (left, size, result, size, 0);
9955 _endLazyDPSEvaluation();
9957 else if (shCount >= (size * 8))
9961 /* get sign in acc.7 */
9962 MOVA (aopGet (left, size - 1, FALSE, FALSE, NULL));
9964 addSign (result, LSB, sign);
9971 genrshOne (result, left, shCount, sign);
9975 genrshTwo (result, left, shCount, sign);
9979 genrshFour (result, left, shCount, sign);
9986 freeAsmop (result, NULL, ic, TRUE);
9987 freeAsmop (left, NULL, ic, TRUE);
9993 /*-----------------------------------------------------------------*/
9994 /* genSignedRightShift - right shift of signed number */
9995 /*-----------------------------------------------------------------*/
9997 genSignedRightShift (iCode * ic)
9999 operand *right, *left, *result;
10002 symbol *tlbl, *tlbl1;
10005 D (emitcode (";", "genSignedRightShift"));
10007 /* we do it the hard way put the shift count in b
10008 and loop thru preserving the sign */
10010 right = IC_RIGHT (ic);
10011 left = IC_LEFT (ic);
10012 result = IC_RESULT (ic);
10014 aopOp (right, ic, FALSE, FALSE);
10016 #ifdef BETTER_LITERAL_SHIFT
10017 if (AOP_TYPE (right) == AOP_LIT)
10019 if (genRightShiftLiteral (left, right, result, ic, 1))
10025 /* shift count is unknown then we have to form
10026 a loop get the loop count in B : Note: we take
10027 only the lower order byte since shifting
10028 more that 32 bits make no sense anyway, ( the
10029 largest size of an object can be only 32 bits ) */
10031 pushedB = pushB ();
10032 if (AOP_TYPE (right) == AOP_LIT)
10034 /* Really should be handled by genRightShiftLiteral,
10035 * but since I'm too lazy to fix that today, at least we can make
10036 * some small improvement.
10038 emitcode("mov", "b,#!constbyte",
10039 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
10043 MOVB (aopGet (right, 0, FALSE, FALSE, "b"));
10044 emitcode ("inc", "b");
10046 freeAsmop (right, NULL, ic, TRUE);
10047 aopOp (left, ic, FALSE, FALSE);
10048 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
10050 /* now move the left to the result if they are not the
10052 if (!sameRegs (AOP (left), AOP (result)) &&
10053 AOP_SIZE (result) > 1)
10056 size = AOP_SIZE (result);
10058 _startLazyDPSEvaluation ();
10061 l = aopGet (left, offset, FALSE, TRUE, NULL);
10062 if (*l == '@' && IS_AOP_PREG (result))
10065 emitcode ("mov", "a,%s", l);
10066 aopPut (result, "a", offset);
10069 aopPut (result, l, offset);
10072 _endLazyDPSEvaluation ();
10075 /* mov the highest order bit to OVR */
10076 tlbl = newiTempLabel (NULL);
10077 tlbl1 = newiTempLabel (NULL);
10079 size = AOP_SIZE (result);
10081 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
10082 emitcode ("rlc", "a");
10083 emitcode ("mov", "ov,c");
10084 /* if it is only one byte then */
10087 l = aopGet (left, 0, FALSE, FALSE, NULL);
10089 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
10091 emitcode ("mov", "c,ov");
10092 emitcode ("rrc", "a");
10094 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
10096 aopPut (result, "a", 0);
10100 reAdjustPreg (AOP (result));
10101 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
10103 emitcode ("mov", "c,ov");
10104 _startLazyDPSEvaluation ();
10107 l = aopGet (result, offset, FALSE, FALSE, NULL);
10109 emitcode ("rrc", "a");
10110 aopPut (result, "a", offset--);
10112 _endLazyDPSEvaluation ();
10113 reAdjustPreg (AOP (result));
10115 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
10119 freeAsmop (result, NULL, ic, TRUE);
10120 freeAsmop (left, NULL, ic, TRUE);
10123 /*-----------------------------------------------------------------*/
10124 /* genRightShift - generate code for right shifting */
10125 /*-----------------------------------------------------------------*/
10127 genRightShift (iCode * ic)
10129 operand *right, *left, *result;
10133 symbol *tlbl, *tlbl1;
10136 D (emitcode (";", "genRightShift"));
10138 /* if signed then we do it the hard way preserve the
10139 sign bit moving it inwards */
10140 letype = getSpec (operandType (IC_LEFT (ic)));
10142 if (!SPEC_USIGN (letype))
10144 genSignedRightShift (ic);
10148 /* signed & unsigned types are treated the same : i.e. the
10149 signed is NOT propagated inwards : quoting from the
10150 ANSI - standard : "for E1 >> E2, is equivalent to division
10151 by 2**E2 if unsigned or if it has a non-negative value,
10152 otherwise the result is implementation defined ", MY definition
10153 is that the sign does not get propagated */
10155 right = IC_RIGHT (ic);
10156 left = IC_LEFT (ic);
10157 result = IC_RESULT (ic);
10159 aopOp (right, ic, FALSE, FALSE);
10161 #ifdef BETTER_LITERAL_SHIFT
10162 /* if the shift count is known then do it
10163 as efficiently as possible */
10164 if (AOP_TYPE (right) == AOP_LIT)
10166 if (genRightShiftLiteral (left, right, result, ic, 0))
10173 /* shift count is unknown then we have to form
10174 a loop get the loop count in B : Note: we take
10175 only the lower order byte since shifting
10176 more that 32 bits make no sense anyway, ( the
10177 largest size of an object can be only 32 bits ) */
10179 pushedB = pushB ();
10180 if (AOP_TYPE (right) == AOP_LIT)
10182 /* Really should be handled by genRightShiftLiteral,
10183 * but since I'm too lazy to fix that today, at least we can make
10184 * some small improvement.
10186 emitcode("mov", "b,#!constbyte",
10187 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
10191 MOVB (aopGet (right, 0, FALSE, FALSE, "b"));
10192 emitcode ("inc", "b");
10194 freeAsmop (right, NULL, ic, TRUE);
10195 aopOp (left, ic, FALSE, FALSE);
10196 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
10198 /* now move the left to the result if they are not the
10200 if (!sameRegs (AOP (left), AOP (result)) &&
10201 AOP_SIZE (result) > 1)
10203 size = AOP_SIZE (result);
10205 _startLazyDPSEvaluation ();
10208 l = aopGet (left, offset, FALSE, TRUE, NULL);
10209 if (*l == '@' && IS_AOP_PREG (result))
10212 emitcode ("mov", "a,%s", l);
10213 aopPut (result, "a", offset);
10216 aopPut (result, l, offset);
10219 _endLazyDPSEvaluation ();
10222 tlbl = newiTempLabel (NULL);
10223 tlbl1 = newiTempLabel (NULL);
10224 size = AOP_SIZE (result);
10227 /* if it is only one byte then */
10230 l = aopGet (left, 0, FALSE, FALSE, NULL);
10232 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
10235 emitcode ("rrc", "a");
10237 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
10239 aopPut (result, "a", 0);
10243 reAdjustPreg (AOP (result));
10244 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
10247 _startLazyDPSEvaluation ();
10250 l = aopGet (result, offset, FALSE, FALSE, NULL);
10252 emitcode ("rrc", "a");
10253 aopPut (result, "a", offset--);
10255 _endLazyDPSEvaluation ();
10256 reAdjustPreg (AOP (result));
10259 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
10263 freeAsmop (result, NULL, ic, TRUE);
10264 freeAsmop (left, NULL, ic, TRUE);
10267 /*-----------------------------------------------------------------*/
10268 /* emitPtrByteGet - emits code to get a byte into A through a */
10269 /* pointer register (R0, R1, or DPTR). The */
10270 /* original value of A can be preserved in B. */
10271 /*-----------------------------------------------------------------*/
10273 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
10280 emitcode ("mov", "b,a");
10281 emitcode ("mov", "a,@%s", rname);
10286 emitcode ("mov", "b,a");
10287 emitcode ("movx", "a,@%s", rname);
10292 emitcode ("mov", "b,a");
10293 emitcode ("movx", "a,@dptr");
10298 emitcode ("mov", "b,a");
10299 emitcode ("clr", "a");
10300 emitcode ("movc", "a,@a+dptr");
10306 emitcode ("push", "b");
10307 emitcode ("push", "acc");
10309 emitcode ("lcall", "__gptrget");
10311 emitcode ("pop", "b");
10316 /*-----------------------------------------------------------------*/
10317 /* emitPtrByteSet - emits code to set a byte from src through a */
10318 /* pointer register (R0, R1, or DPTR). */
10319 /*-----------------------------------------------------------------*/
10321 emitPtrByteSet (char *rname, int p_type, char *src)
10330 emitcode ("mov", "@%s,a", rname);
10333 emitcode ("mov", "@%s,%s", rname, src);
10338 emitcode ("movx", "@%s,a", rname);
10343 emitcode ("movx", "@dptr,a");
10348 emitcode ("lcall", "__gptrput");
10353 /*-----------------------------------------------------------------*/
10354 /* genUnpackBits - generates code for unpacking bits */
10355 /*-----------------------------------------------------------------*/
10357 genUnpackBits (operand * result, char *rname, int ptype)
10359 int offset = 0; /* result byte offset */
10360 int rsize; /* result size */
10361 int rlen = 0; /* remaining bitfield length */
10362 sym_link *etype; /* bitfield type information */
10363 int blen; /* bitfield length */
10364 int bstr; /* bitfield starting bit within byte */
10366 D(emitcode ("; genUnpackBits",""));
10368 etype = getSpec (operandType (result));
10369 rsize = getSize (operandType (result));
10370 blen = SPEC_BLEN (etype);
10371 bstr = SPEC_BSTR (etype);
10373 /* If the bitfield length is less than a byte */
10376 emitPtrByteGet (rname, ptype, FALSE);
10378 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
10379 if (!SPEC_USIGN (etype))
10381 /* signed bitfield */
10382 symbol *tlbl = newiTempLabel (NULL);
10384 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
10385 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
10388 aopPut (result, "a", offset++);
10392 /* Bit field did not fit in a byte. Copy all
10393 but the partial byte at the end. */
10394 for (rlen=blen;rlen>=8;rlen-=8)
10396 emitPtrByteGet (rname, ptype, FALSE);
10397 aopPut (result, "a", offset++);
10399 emitcode ("inc", "%s", rname);
10402 /* Handle the partial byte at the end */
10405 emitPtrByteGet (rname, ptype, FALSE);
10406 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
10407 if (!SPEC_USIGN (etype))
10409 /* signed bitfield */
10410 symbol *tlbl = newiTempLabel (NULL);
10412 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
10413 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
10416 aopPut (result, "a", offset++);
10420 if (offset < rsize)
10424 if (SPEC_USIGN (etype))
10428 /* signed bitfield: sign extension with 0x00 or 0xff */
10429 emitcode ("rlc", "a");
10430 emitcode ("subb", "a,acc");
10436 aopPut (result, source, offset++);
10441 /*-----------------------------------------------------------------*/
10442 /* genDataPointerGet - generates code when ptr offset is known */
10443 /*-----------------------------------------------------------------*/
10445 genDataPointerGet (operand * left,
10451 int size, offset = 0;
10452 aopOp (result, ic, TRUE, FALSE);
10454 /* get the string representation of the name */
10455 l = aopGet (left, 0, FALSE, TRUE, NULL);
10456 size = AOP_SIZE (result);
10457 _startLazyDPSEvaluation ();
10462 SNPRINTF (buffer, sizeof(buffer),
10463 "(%s + %d)", l + 1, offset);
10467 SNPRINTF (buffer, sizeof(buffer),
10470 aopPut (result, buffer, offset++);
10472 _endLazyDPSEvaluation ();
10474 freeAsmop (result, NULL, ic, TRUE);
10475 freeAsmop (left, NULL, ic, TRUE);
10478 /*-----------------------------------------------------------------*/
10479 /* genNearPointerGet - emitcode for near pointer fetch */
10480 /*-----------------------------------------------------------------*/
10482 genNearPointerGet (operand * left,
10490 sym_link *rtype, *retype, *letype;
10491 sym_link *ltype = operandType (left);
10494 rtype = operandType (result);
10495 retype = getSpec (rtype);
10496 letype = getSpec (ltype);
10498 aopOp (left, ic, FALSE, FALSE);
10500 /* if left is rematerialisable and
10501 result is not bitfield variable type and
10502 the left is pointer to data space i.e
10503 lower 128 bytes of space */
10504 if (AOP_TYPE (left) == AOP_IMMD &&
10505 !IS_BITFIELD (retype) &&
10506 !IS_BITFIELD (letype) &&
10507 DCL_TYPE (ltype) == POINTER)
10509 genDataPointerGet (left, result, ic);
10513 /* if the value is already in a pointer register
10514 then don't need anything more */
10515 if (!AOP_INPREG (AOP (left)))
10517 /* otherwise get a free pointer register */
10518 aop = newAsmop (0);
10519 preg = getFreePtr (ic, &aop, FALSE);
10520 emitcode ("mov", "%s,%s",
10522 aopGet (left, 0, FALSE, TRUE, DP2_RESULT_REG));
10523 rname = preg->name;
10526 rname = aopGet (left, 0, FALSE, FALSE, DP2_RESULT_REG);
10528 freeAsmop (left, NULL, ic, TRUE);
10529 aopOp (result, ic, FALSE, FALSE);
10531 /* if bitfield then unpack the bits */
10532 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10533 genUnpackBits (result, rname, POINTER);
10536 /* we have can just get the values */
10537 int size = AOP_SIZE (result);
10542 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
10545 emitcode ("mov", "a,@%s", rname);
10546 aopPut (result, "a", offset);
10550 SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
10551 aopPut (result, buffer, offset);
10555 emitcode ("inc", "%s", rname);
10559 /* now some housekeeping stuff */
10560 if (aop) /* we had to allocate for this iCode */
10562 if (pi) { /* post increment present */
10563 aopPut (left, rname, 0);
10565 freeAsmop (NULL, aop, ic, TRUE);
10569 /* we did not allocate which means left
10570 already in a pointer register, then
10571 if size > 0 && this could be used again
10572 we have to point it back to where it
10574 if (AOP_SIZE (result) > 1 &&
10575 !OP_SYMBOL (left)->remat &&
10576 (OP_SYMBOL (left)->liveTo > ic->seq ||
10580 int size = AOP_SIZE (result) - 1;
10582 emitcode ("dec", "%s", rname);
10587 freeAsmop (result, NULL, ic, TRUE);
10588 if (pi) pi->generated = 1;
10591 /*-----------------------------------------------------------------*/
10592 /* genPagedPointerGet - emitcode for paged pointer fetch */
10593 /*-----------------------------------------------------------------*/
10595 genPagedPointerGet (operand * left,
10603 sym_link *rtype, *retype, *letype;
10605 rtype = operandType (result);
10606 retype = getSpec (rtype);
10607 letype = getSpec (operandType (left));
10608 aopOp (left, ic, FALSE, FALSE);
10610 /* if the value is already in a pointer register
10611 then don't need anything more */
10612 if (!AOP_INPREG (AOP (left)))
10614 /* otherwise get a free pointer register */
10615 aop = newAsmop (0);
10616 preg = getFreePtr (ic, &aop, FALSE);
10617 emitcode ("mov", "%s,%s",
10619 aopGet (left, 0, FALSE, TRUE, NULL));
10620 rname = preg->name;
10623 rname = aopGet (left, 0, FALSE, FALSE, NULL);
10625 freeAsmop (left, NULL, ic, TRUE);
10626 aopOp (result, ic, FALSE, FALSE);
10628 /* if bitfield then unpack the bits */
10629 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10630 genUnpackBits (result, rname, PPOINTER);
10633 /* we have can just get the values */
10634 int size = AOP_SIZE (result);
10640 emitcode ("movx", "a,@%s", rname);
10641 aopPut (result, "a", offset);
10646 emitcode ("inc", "%s", rname);
10650 /* now some housekeeping stuff */
10651 if (aop) /* we had to allocate for this iCode */
10654 aopPut (left, rname, 0);
10655 freeAsmop (NULL, aop, ic, TRUE);
10659 /* we did not allocate which means left
10660 already in a pointer register, then
10661 if size > 0 && this could be used again
10662 we have to point it back to where it
10664 if (AOP_SIZE (result) > 1 &&
10665 !OP_SYMBOL (left)->remat &&
10666 (OP_SYMBOL (left)->liveTo > ic->seq ||
10670 int size = AOP_SIZE (result) - 1;
10672 emitcode ("dec", "%s", rname);
10677 freeAsmop (result, NULL, ic, TRUE);
10678 if (pi) pi->generated = 1;
10681 /*-----------------------------------------------------------------*/
10682 /* genFarPointerGet - get value from far space */
10683 /*-----------------------------------------------------------------*/
10685 genFarPointerGet (operand * left,
10686 operand * result, iCode * ic, iCode *pi)
10688 int size, offset, dopi=1;
10689 sym_link *retype = getSpec (operandType (result));
10690 sym_link *letype = getSpec (operandType (left));
10691 D (emitcode (";", "genFarPointerGet"););
10693 aopOp (left, ic, FALSE, FALSE);
10695 /* if the operand is already in dptr
10696 then we do nothing else we move the value to dptr */
10697 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
10699 /* if this is rematerializable */
10700 if (AOP_TYPE (left) == AOP_IMMD)
10702 emitcode ("mov", "dptr,%s", aopGet (left, 0, TRUE, FALSE, NULL));
10706 /* we need to get it byte by byte */
10707 _startLazyDPSEvaluation ();
10708 if (AOP_TYPE (left) != AOP_DPTR)
10710 emitcode ("mov", "dpl,%s", aopGet (left, 0, FALSE, FALSE, NULL));
10711 emitcode ("mov", "dph,%s", aopGet (left, 1, FALSE, FALSE, NULL));
10712 if (options.model == MODEL_FLAT24)
10713 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10717 /* We need to generate a load to DPTR indirect through DPTR. */
10718 D (emitcode (";", "genFarPointerGet -- indirection special case."););
10719 emitcode ("push", "%s", aopGet (left, 0, FALSE, TRUE, NULL));
10720 emitcode ("push", "%s", aopGet (left, 1, FALSE, TRUE, NULL));
10721 if (options.model == MODEL_FLAT24)
10722 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10723 emitcode ("pop", "dph");
10724 emitcode ("pop", "dpl");
10727 _endLazyDPSEvaluation ();
10730 /* so dptr now contains the address */
10731 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10733 /* if bit then unpack */
10734 if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
10735 if (AOP_INDPTRn(left)) {
10736 genSetDPTR(AOP(left)->aopu.dptr);
10738 genUnpackBits (result, "dptr", FPOINTER);
10739 if (AOP_INDPTRn(left)) {
10744 size = AOP_SIZE (result);
10747 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10749 genSetDPTR(AOP(left)->aopu.dptr);
10750 emitcode ("movx", "a,@dptr");
10751 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10752 emitcode ("inc", "dptr");
10754 aopPut (result, "a", offset++);
10757 _startLazyDPSEvaluation ();
10759 if (AOP_INDPTRn(left)) {
10760 genSetDPTR(AOP(left)->aopu.dptr);
10766 emitcode ("movx", "a,@dptr");
10767 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10768 emitcode ("inc", "dptr");
10770 aopPut (result, "a", offset++);
10772 _endLazyDPSEvaluation ();
10775 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10776 if (!AOP_INDPTRn(left)) {
10777 _startLazyDPSEvaluation ();
10778 aopPut (left, "dpl", 0);
10779 aopPut (left, "dph", 1);
10780 if (options.model == MODEL_FLAT24)
10781 aopPut (left, "dpx", 2);
10782 _endLazyDPSEvaluation ();
10785 } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) &&
10786 AOP_SIZE(result) > 1 &&
10788 (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
10790 size = AOP_SIZE (result) - 1;
10791 if (AOP_INDPTRn(left)) {
10792 genSetDPTR(AOP(left)->aopu.dptr);
10794 while (size--) emitcode ("lcall","__decdptr");
10795 if (AOP_INDPTRn(left)) {
10800 freeAsmop (result, NULL, ic, TRUE);
10801 freeAsmop (left, NULL, ic, TRUE);
10804 /*-----------------------------------------------------------------*/
10805 /* genCodePointerGet - get value from code space */
10806 /*-----------------------------------------------------------------*/
10808 genCodePointerGet (operand * left,
10809 operand * result, iCode * ic, iCode *pi)
10811 int size, offset, dopi=1;
10812 sym_link *retype = getSpec (operandType (result));
10814 aopOp (left, ic, FALSE, FALSE);
10816 /* if the operand is already in dptr
10817 then we do nothing else we move the value to dptr */
10818 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
10820 /* if this is rematerializable */
10821 if (AOP_TYPE (left) == AOP_IMMD)
10823 emitcode ("mov", "dptr,%s", aopGet (left, 0, TRUE, FALSE, NULL));
10826 { /* we need to get it byte by byte */
10827 _startLazyDPSEvaluation ();
10828 if (AOP_TYPE (left) != AOP_DPTR)
10830 emitcode ("mov", "dpl,%s", aopGet (left, 0, FALSE, FALSE, NULL));
10831 emitcode ("mov", "dph,%s", aopGet (left, 1, FALSE, FALSE, NULL));
10832 if (options.model == MODEL_FLAT24)
10833 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10837 /* We need to generate a load to DPTR indirect through DPTR. */
10838 D (emitcode (";", "gencodePointerGet -- indirection special case."););
10839 emitcode ("push", "%s", aopGet (left, 0, FALSE, TRUE, NULL));
10840 emitcode ("push", "%s", aopGet (left, 1, FALSE, TRUE, NULL));
10841 if (options.model == MODEL_FLAT24)
10842 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10843 emitcode ("pop", "dph");
10844 emitcode ("pop", "dpl");
10847 _endLazyDPSEvaluation ();
10850 /* so dptr now contains the address */
10851 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10853 /* if bit then unpack */
10854 if (IS_BITFIELD (retype)) {
10855 if (AOP_INDPTRn(left)) {
10856 genSetDPTR(AOP(left)->aopu.dptr);
10858 genUnpackBits (result, "dptr", CPOINTER);
10859 if (AOP_INDPTRn(left)) {
10864 size = AOP_SIZE (result);
10866 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10868 genSetDPTR(AOP(left)->aopu.dptr);
10869 emitcode ("clr", "a");
10870 emitcode ("movc", "a,@a+dptr");
10871 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10872 emitcode ("inc", "dptr");
10874 aopPut (result, "a", offset++);
10877 _startLazyDPSEvaluation ();
10880 if (AOP_INDPTRn(left)) {
10881 genSetDPTR(AOP(left)->aopu.dptr);
10887 emitcode ("clr", "a");
10888 emitcode ("movc", "a,@a+dptr");
10889 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10890 emitcode ("inc", "dptr");
10891 aopPut (result, "a", offset++);
10893 _endLazyDPSEvaluation ();
10896 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10897 if (!AOP_INDPTRn(left)) {
10898 _startLazyDPSEvaluation ();
10900 aopPut (left, "dpl", 0);
10901 aopPut (left, "dph", 1);
10902 if (options.model == MODEL_FLAT24)
10903 aopPut (left, "dpx", 2);
10905 _endLazyDPSEvaluation ();
10908 } else if (IS_SYMOP(left) &&
10909 (OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
10910 AOP_SIZE(result) > 1 &&
10911 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10913 size = AOP_SIZE (result) - 1;
10914 if (AOP_INDPTRn(left)) {
10915 genSetDPTR(AOP(left)->aopu.dptr);
10917 while (size--) emitcode ("lcall","__decdptr");
10918 if (AOP_INDPTRn(left)) {
10923 freeAsmop (result, NULL, ic, TRUE);
10924 freeAsmop (left, NULL, ic, TRUE);
10927 /*-----------------------------------------------------------------*/
10928 /* genGenPointerGet - get value from generic pointer space */
10929 /*-----------------------------------------------------------------*/
10931 genGenPointerGet (operand * left,
10932 operand * result, iCode * ic, iCode * pi)
10936 sym_link *retype = getSpec (operandType (result));
10937 sym_link *letype = getSpec (operandType (left));
10939 D (emitcode (";", "genGenPointerGet"));
10941 aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
10943 pushedB = pushB ();
10944 /* if the operand is already in dptr
10945 then we do nothing else we move the value to dptr */
10946 if (AOP_TYPE (left) != AOP_STR)
10948 /* if this is rematerializable */
10949 if (AOP_TYPE (left) == AOP_IMMD)
10951 emitcode ("mov", "dptr,%s", aopGet (left, 0, TRUE, FALSE, NULL));
10952 if (AOP(left)->aopu.aop_immd.from_cast_remat)
10954 MOVB (aopGet (left, AOP_SIZE(left)-1, FALSE, FALSE, NULL));
10958 emitcode ("mov", "b,#%d", pointerCode (retype));
10962 { /* we need to get it byte by byte */
10963 _startLazyDPSEvaluation ();
10964 emitcode ("mov", "dpl,%s", aopGet (left,0,FALSE,FALSE,NULL));
10965 emitcode ("mov", "dph,%s", aopGet (left,1,FALSE,FALSE,NULL));
10966 if (options.model == MODEL_FLAT24) {
10967 emitcode ("mov", "dpx,%s", aopGet (left,2,FALSE,FALSE,NULL));
10968 emitcode ("mov", "b,%s", aopGet (left,3,FALSE,FALSE,NULL));
10970 emitcode ("mov", "b,%s", aopGet (left,2,FALSE,FALSE,NULL));
10972 _endLazyDPSEvaluation ();
10976 /* so dptr-b now contains the address */
10977 aopOp (result, ic, FALSE, TRUE);
10979 /* if bit then unpack */
10980 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10982 genUnpackBits (result, "dptr", GPOINTER);
10986 size = AOP_SIZE (result);
10993 // Get two bytes at a time, results in _AP & A.
10994 // dptr will be incremented ONCE by __gptrgetWord.
10996 // Note: any change here must be coordinated
10997 // with the implementation of __gptrgetWord
10998 // in device/lib/_gptrget.c
10999 emitcode ("lcall", "__gptrgetWord");
11000 aopPut (result, DP2_RESULT_REG, offset++);
11001 aopPut (result, "a", offset++);
11006 // Only one byte to get.
11007 emitcode ("lcall", "__gptrget");
11008 aopPut (result, "a", offset++);
11011 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
11013 emitcode ("inc", "dptr");
11018 if (pi && AOP_TYPE (left) != AOP_IMMD) {
11019 _startLazyDPSEvaluation ();
11021 aopPut (left, "dpl", 0);
11022 aopPut (left, "dph", 1);
11023 if (options.model == MODEL_FLAT24) {
11024 aopPut (left, "dpx", 2);
11025 aopPut (left, "b", 3);
11026 } else aopPut (left, "b", 2);
11028 _endLazyDPSEvaluation ();
11031 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
11032 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
11034 size = AOP_SIZE (result) - 1;
11035 while (size--) emitcode ("lcall","__decdptr");
11039 freeAsmop (result, NULL, ic, TRUE);
11040 freeAsmop (left, NULL, ic, TRUE);
11043 /*-----------------------------------------------------------------*/
11044 /* genPointerGet - generate code for pointer get */
11045 /*-----------------------------------------------------------------*/
11047 genPointerGet (iCode * ic, iCode *pi)
11049 operand *left, *result;
11050 sym_link *type, *etype;
11053 D (emitcode (";", "genPointerGet"));
11055 left = IC_LEFT (ic);
11056 result = IC_RESULT (ic);
11058 /* depending on the type of pointer we need to
11059 move it to the correct pointer register */
11060 type = operandType (left);
11061 etype = getSpec (type);
11062 /* if left is of type of pointer then it is simple */
11063 if (IS_PTR (type) && !IS_FUNC (type->next))
11064 p_type = DCL_TYPE (type);
11067 /* we have to go by the storage class */
11068 p_type = PTR_TYPE (SPEC_OCLS (etype));
11071 /* special case when cast remat */
11072 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
11073 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
11075 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
11076 type = operandType (left);
11077 p_type = DCL_TYPE (type);
11079 /* now that we have the pointer type we assign
11080 the pointer values */
11086 genNearPointerGet (left, result, ic, pi);
11090 genPagedPointerGet (left, result, ic, pi);
11094 genFarPointerGet (left, result, ic, pi);
11098 genCodePointerGet (left, result, ic, pi);
11102 genGenPointerGet (left, result, ic, pi);
11108 /*-----------------------------------------------------------------*/
11109 /* genPackBits - generates code for packed bit storage */
11110 /*-----------------------------------------------------------------*/
11112 genPackBits (sym_link * etype,
11114 char *rname, int p_type)
11116 int offset = 0; /* source byte offset */
11117 int rlen = 0; /* remaining bitfield length */
11118 int blen; /* bitfield length */
11119 int bstr; /* bitfield starting bit within byte */
11120 int litval; /* source literal value (if AOP_LIT) */
11121 unsigned char mask; /* bitmask within current byte */
11123 D(emitcode ("; genPackBits",""));
11125 blen = SPEC_BLEN (etype);
11126 bstr = SPEC_BSTR (etype);
11128 /* If the bitfield length is less than a byte */
11131 mask = ((unsigned char) (0xFF << (blen + bstr)) |
11132 (unsigned char) (0xFF >> (8 - bstr)));
11134 if (AOP_TYPE (right) == AOP_LIT)
11136 /* Case with a bitfield length <8 and literal source
11138 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
11140 litval &= (~mask) & 0xff;
11141 emitPtrByteGet (rname, p_type, FALSE);
11142 if ((mask|litval)!=0xff)
11143 emitcode ("anl","a,#!constbyte", mask);
11145 emitcode ("orl","a,#!constbyte", litval);
11149 if ((blen==1) && (p_type!=GPOINTER))
11151 /* Case with a bitfield length == 1 and no generic pointer
11153 if (AOP_TYPE (right) == AOP_CRY)
11154 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
11157 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
11158 emitcode ("rrc","a");
11160 emitPtrByteGet (rname, p_type, FALSE);
11161 emitcode ("mov","acc.%d,c",bstr);
11166 /* Case with a bitfield length < 8 and arbitrary source
11168 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
11169 /* shift and mask source value */
11171 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
11173 pushedB = pushB ();
11174 /* transfer A to B and get next byte */
11175 emitPtrByteGet (rname, p_type, TRUE);
11177 emitcode ("anl", "a,#!constbyte", mask);
11178 emitcode ("orl", "a,b");
11179 if (p_type == GPOINTER)
11180 emitcode ("pop", "b");
11186 emitPtrByteSet (rname, p_type, "a");
11190 /* Bit length is greater than 7 bits. In this case, copy */
11191 /* all except the partial byte at the end */
11192 for (rlen=blen;rlen>=8;rlen-=8)
11194 emitPtrByteSet (rname, p_type,
11195 aopGet (right, offset++, FALSE, TRUE, NULL) );
11197 emitcode ("inc", "%s", rname);
11200 /* If there was a partial byte at the end */
11203 mask = (((unsigned char) -1 << rlen) & 0xff);
11205 if (AOP_TYPE (right) == AOP_LIT)
11207 /* Case with partial byte and literal source
11209 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
11210 litval >>= (blen-rlen);
11211 litval &= (~mask) & 0xff;
11212 emitPtrByteGet (rname, p_type, FALSE);
11213 if ((mask|litval)!=0xff)
11214 emitcode ("anl","a,#!constbyte", mask);
11216 emitcode ("orl","a,#!constbyte", litval);
11221 /* Case with partial byte and arbitrary source
11223 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11224 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
11226 pushedB = pushB ();
11227 /* transfer A to B and get next byte */
11228 emitPtrByteGet (rname, p_type, TRUE);
11230 emitcode ("anl", "a,#!constbyte", mask);
11231 emitcode ("orl", "a,b");
11232 if (p_type == GPOINTER)
11233 emitcode ("pop", "b");
11237 emitPtrByteSet (rname, p_type, "a");
11242 /*-----------------------------------------------------------------*/
11243 /* genDataPointerSet - remat pointer to data space */
11244 /*-----------------------------------------------------------------*/
11246 genDataPointerSet (operand * right,
11250 int size, offset = 0;
11251 char *l, buffer[256];
11253 D (emitcode (";", "genDataPointerSet"));
11255 aopOp (right, ic, FALSE, FALSE);
11257 l = aopGet (result, 0, FALSE, TRUE, NULL);
11258 size = AOP_SIZE (right);
11262 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l + 1, offset);
11264 SNPRINTF (buffer, sizeof(buffer), "%s", l + 1);
11265 emitcode ("mov", "%s,%s", buffer,
11266 aopGet (right, offset++, FALSE, FALSE, NULL));
11269 freeAsmop (result, NULL, ic, TRUE);
11270 freeAsmop (right, NULL, ic, TRUE);
11273 /*-----------------------------------------------------------------*/
11274 /* genNearPointerSet - emitcode for near pointer put */
11275 /*-----------------------------------------------------------------*/
11277 genNearPointerSet (operand * right,
11284 sym_link *retype, *letype;
11285 sym_link *ptype = operandType (result);
11287 D (emitcode (";", "genNearPointerSet"));
11289 retype = getSpec (operandType (right));
11290 letype = getSpec (ptype);
11292 aopOp (result, ic, FALSE, FALSE);
11294 /* if the result is rematerializable &
11295 in data space & not a bit variable */
11296 if (AOP_TYPE (result) == AOP_IMMD &&
11297 DCL_TYPE (ptype) == POINTER &&
11298 !IS_BITVAR (retype) &&
11299 !IS_BITVAR (letype))
11301 genDataPointerSet (right, result, ic);
11305 /* if the value is already in a pointer register
11306 then don't need anything more */
11307 if (!AOP_INPREG (AOP (result)))
11309 /* otherwise get a free pointer register */
11312 aop = newAsmop (0);
11313 preg = getFreePtr (ic, &aop, FALSE);
11314 emitcode ("mov", "%s,%s",
11316 aopGet (result, 0, FALSE, TRUE, NULL));
11317 rname = preg->name;
11321 rname = aopGet (result, 0, FALSE, FALSE, NULL);
11324 aopOp (right, ic, FALSE, FALSE);
11326 /* if bitfield then unpack the bits */
11327 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11328 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
11331 /* we can just get the values */
11332 int size = AOP_SIZE (right);
11337 l = aopGet (right, offset, FALSE, TRUE, NULL);
11338 if ((*l == '@') || (strcmp (l, "acc") == 0))
11341 emitcode ("mov", "@%s,a", rname);
11344 emitcode ("mov", "@%s,%s", rname, l);
11346 emitcode ("inc", "%s", rname);
11351 /* now some housekeeping stuff */
11352 if (aop) /* we had to allocate for this iCode */
11355 aopPut (result, rname, 0);
11356 freeAsmop (NULL, aop, ic, TRUE);
11360 /* we did not allocate which means left
11361 already in a pointer register, then
11362 if size > 0 && this could be used again
11363 we have to point it back to where it
11365 if (AOP_SIZE (right) > 1 &&
11366 !OP_SYMBOL (result)->remat &&
11367 (OP_SYMBOL (result)->liveTo > ic->seq ||
11371 int size = AOP_SIZE (right) - 1;
11373 emitcode ("dec", "%s", rname);
11378 if (pi) pi->generated = 1;
11379 freeAsmop (result, NULL, ic, TRUE);
11380 freeAsmop (right, NULL, ic, TRUE);
11383 /*-----------------------------------------------------------------*/
11384 /* genPagedPointerSet - emitcode for Paged pointer put */
11385 /*-----------------------------------------------------------------*/
11387 genPagedPointerSet (operand * right,
11394 sym_link *retype, *letype;
11396 D (emitcode (";", "genPagedPointerSet"));
11398 retype = getSpec (operandType (right));
11399 letype = getSpec (operandType (result));
11401 aopOp (result, ic, FALSE, FALSE);
11403 /* if the value is already in a pointer register
11404 then don't need anything more */
11405 if (!AOP_INPREG (AOP (result)))
11407 /* otherwise get a free pointer register */
11410 aop = newAsmop (0);
11411 preg = getFreePtr (ic, &aop, FALSE);
11412 emitcode ("mov", "%s,%s",
11414 aopGet (result, 0, FALSE, TRUE, NULL));
11415 rname = preg->name;
11418 rname = aopGet (result, 0, FALSE, FALSE, NULL);
11420 aopOp (right, ic, FALSE, FALSE);
11422 /* if bitfield then unpack the bits */
11423 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11424 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
11427 /* we have can just get the values */
11428 int size = AOP_SIZE (right);
11433 l = aopGet (right, offset, FALSE, TRUE, NULL);
11435 emitcode ("movx", "@%s,a", rname);
11438 emitcode ("inc", "%s", rname);
11444 /* now some housekeeping stuff */
11448 aopPut (result, rname, 0);
11449 /* we had to allocate for this iCode */
11450 freeAsmop (NULL, aop, ic, TRUE);
11454 /* we did not allocate which means left
11455 already in a pointer register, then
11456 if size > 0 && this could be used again
11457 we have to point it back to where it
11459 if (AOP_SIZE (right) > 1 &&
11460 !OP_SYMBOL (result)->remat &&
11461 (OP_SYMBOL (result)->liveTo > ic->seq ||
11465 int size = AOP_SIZE (right) - 1;
11467 emitcode ("dec", "%s", rname);
11472 if (pi) pi->generated = 1;
11473 freeAsmop (result, NULL, ic, TRUE);
11474 freeAsmop (right, NULL, ic, TRUE);
11477 /*-----------------------------------------------------------------*/
11478 /* genFarPointerSet - set value from far space */
11479 /*-----------------------------------------------------------------*/
11481 genFarPointerSet (operand * right,
11482 operand * result, iCode * ic, iCode *pi)
11484 int size, offset, dopi=1;
11485 sym_link *retype = getSpec (operandType (right));
11486 sym_link *letype = getSpec (operandType (result));
11488 aopOp (result, ic, FALSE, FALSE);
11490 /* if the operand is already in dptr
11491 then we do nothing else we move the value to dptr */
11492 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
11494 /* if this is remateriazable */
11495 if (AOP_TYPE (result) == AOP_IMMD)
11496 emitcode ("mov", "dptr,%s",
11497 aopGet (result, 0, TRUE, FALSE, NULL));
11500 /* we need to get it byte by byte */
11501 _startLazyDPSEvaluation ();
11502 if (AOP_TYPE (result) != AOP_DPTR)
11504 emitcode ("mov", "dpl,%s", aopGet (result, 0, FALSE, FALSE, NULL));
11505 emitcode ("mov", "dph,%s", aopGet (result, 1, FALSE, FALSE, NULL));
11506 if (options.model == MODEL_FLAT24)
11507 emitcode ("mov", "dpx,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11511 /* We need to generate a load to DPTR indirect through DPTR. */
11512 D (emitcode (";", "genFarPointerSet -- indirection special case."););
11514 emitcode ("push", "%s", aopGet (result, 0, FALSE, TRUE, NULL));
11515 emitcode ("push", "%s", aopGet (result, 1, FALSE, TRUE, NULL));
11516 if (options.model == MODEL_FLAT24)
11517 emitcode ("mov", "dpx,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11518 emitcode ("pop", "dph");
11519 emitcode ("pop", "dpl");
11522 _endLazyDPSEvaluation ();
11525 /* so dptr now contains the address */
11526 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
11528 /* if bit then unpack */
11529 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11531 if (AOP_INDPTRn(result)) {
11532 genSetDPTR(AOP(result)->aopu.dptr);
11534 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
11535 if (AOP_INDPTRn(result)) {
11539 size = AOP_SIZE (right);
11541 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
11543 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11545 genSetDPTR(AOP(result)->aopu.dptr);
11546 emitcode ("movx", "@dptr,a");
11547 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
11548 emitcode ("inc", "dptr");
11552 _startLazyDPSEvaluation ();
11554 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11556 if (AOP_INDPTRn(result)) {
11557 genSetDPTR(AOP(result)->aopu.dptr);
11563 emitcode ("movx", "@dptr,a");
11564 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
11565 emitcode ("inc", "dptr");
11567 _endLazyDPSEvaluation ();
11571 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
11572 if (!AOP_INDPTRn(result)) {
11573 _startLazyDPSEvaluation ();
11575 aopPut (result,"dpl",0);
11576 aopPut (result,"dph",1);
11577 if (options.model == MODEL_FLAT24)
11578 aopPut (result,"dpx",2);
11580 _endLazyDPSEvaluation ();
11583 } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
11584 AOP_SIZE(right) > 1 &&
11585 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
11587 size = AOP_SIZE (right) - 1;
11588 if (AOP_INDPTRn(result)) {
11589 genSetDPTR(AOP(result)->aopu.dptr);
11591 while (size--) emitcode ("lcall","__decdptr");
11592 if (AOP_INDPTRn(result)) {
11596 freeAsmop (result, NULL, ic, TRUE);
11597 freeAsmop (right, NULL, ic, TRUE);
11600 /*-----------------------------------------------------------------*/
11601 /* genGenPointerSet - set value from generic pointer space */
11602 /*-----------------------------------------------------------------*/
11604 genGenPointerSet (operand * right,
11605 operand * result, iCode * ic, iCode *pi)
11609 sym_link *retype = getSpec (operandType (right));
11610 sym_link *letype = getSpec (operandType (result));
11612 aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
11614 pushedB = pushB ();
11615 /* if the operand is already in dptr
11616 then we do nothing else we move the value to dptr */
11617 if (AOP_TYPE (result) != AOP_STR)
11619 _startLazyDPSEvaluation ();
11620 /* if this is remateriazable */
11621 if (AOP_TYPE (result) == AOP_IMMD)
11623 emitcode ("mov", "dptr,%s", aopGet (result, 0, TRUE, FALSE, NULL));
11624 if (AOP(result)->aopu.aop_immd.from_cast_remat)
11626 MOVB (aopGet (result, AOP_SIZE(result)-1, FALSE, FALSE, NULL));
11631 "b,%s + 1", aopGet (result, 0, TRUE, FALSE, NULL));
11635 { /* we need to get it byte by byte */
11636 emitcode ("mov", "dpl,%s", aopGet (result, 0, FALSE, FALSE, NULL));
11637 emitcode ("mov", "dph,%s", aopGet (result, 1, FALSE, FALSE, NULL));
11638 if (options.model == MODEL_FLAT24) {
11639 emitcode ("mov", "dpx,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11640 emitcode ("mov", "b,%s", aopGet (result, 3, FALSE, FALSE, NULL));
11642 emitcode ("mov", "b,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11645 _endLazyDPSEvaluation ();
11647 /* so dptr + b now contains the address */
11648 aopOp (right, ic, FALSE, TRUE);
11650 /* if bit then unpack */
11651 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11653 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
11657 size = AOP_SIZE (right);
11660 _startLazyDPSEvaluation ();
11665 // Set two bytes at a time, passed in _AP & A.
11666 // dptr will be incremented ONCE by __gptrputWord.
11668 // Note: any change here must be coordinated
11669 // with the implementation of __gptrputWord
11670 // in device/lib/_gptrput.c
11671 emitcode("mov", "_ap, %s",
11672 aopGet (right, offset++, FALSE, FALSE, NULL));
11673 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11677 emitcode ("lcall", "__gptrputWord");
11682 // Only one byte to put.
11683 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11687 emitcode ("lcall", "__gptrput");
11690 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
11692 emitcode ("inc", "dptr");
11695 _endLazyDPSEvaluation ();
11698 if (pi && AOP_TYPE (result) != AOP_IMMD) {
11699 _startLazyDPSEvaluation ();
11701 aopPut (result, "dpl",0);
11702 aopPut (result, "dph",1);
11703 if (options.model == MODEL_FLAT24) {
11704 aopPut (result, "dpx",2);
11705 aopPut (result, "b",3);
11707 aopPut (result, "b",2);
11709 _endLazyDPSEvaluation ();
11712 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
11713 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
11715 size = AOP_SIZE (right) - 1;
11716 while (size--) emitcode ("lcall","__decdptr");
11720 freeAsmop (result, NULL, ic, TRUE);
11721 freeAsmop (right, NULL, ic, TRUE);
11724 /*-----------------------------------------------------------------*/
11725 /* genPointerSet - stores the value into a pointer location */
11726 /*-----------------------------------------------------------------*/
11728 genPointerSet (iCode * ic, iCode *pi)
11730 operand *right, *result;
11731 sym_link *type, *etype;
11734 D (emitcode (";", "genPointerSet"));
11736 right = IC_RIGHT (ic);
11737 result = IC_RESULT (ic);
11739 /* depending on the type of pointer we need to
11740 move it to the correct pointer register */
11741 type = operandType (result);
11742 etype = getSpec (type);
11743 /* if left is of type of pointer then it is simple */
11744 if (IS_PTR (type) && !IS_FUNC (type->next))
11746 p_type = DCL_TYPE (type);
11750 /* we have to go by the storage class */
11751 p_type = PTR_TYPE (SPEC_OCLS (etype));
11754 /* special case when cast remat */
11755 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
11756 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
11757 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
11758 type = operandType (result);
11759 p_type = DCL_TYPE (type);
11762 /* now that we have the pointer type we assign
11763 the pointer values */
11769 genNearPointerSet (right, result, ic, pi);
11773 genPagedPointerSet (right, result, ic, pi);
11777 genFarPointerSet (right, result, ic, pi);
11781 genGenPointerSet (right, result, ic, pi);
11785 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11786 "genPointerSet: illegal pointer type");
11790 /*-----------------------------------------------------------------*/
11791 /* genIfx - generate code for Ifx statement */
11792 /*-----------------------------------------------------------------*/
11794 genIfx (iCode * ic, iCode * popIc)
11796 operand *cond = IC_COND (ic);
11800 D (emitcode (";", "genIfx"));
11802 aopOp (cond, ic, FALSE, FALSE);
11804 /* get the value into acc */
11805 if (AOP_TYPE (cond) != AOP_CRY)
11812 if (AOP(cond)->aopu.aop_dir)
11813 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
11816 /* the result is now in the accumulator or a directly addressable bit */
11817 freeAsmop (cond, NULL, ic, TRUE);
11819 /* if there was something to be popped then do it */
11823 /* if the condition is a bit variable */
11825 genIfxJump (ic, dup);
11826 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
11827 genIfxJump (ic, SPIL_LOC (cond)->rname);
11828 else if (isbit && !IS_ITEMP (cond))
11829 genIfxJump (ic, OP_SYMBOL (cond)->rname);
11831 genIfxJump (ic, "a");
11836 /*-----------------------------------------------------------------*/
11837 /* genAddrOf - generates code for address of */
11838 /*-----------------------------------------------------------------*/
11840 genAddrOf (iCode * ic)
11842 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
11845 D (emitcode (";", "genAddrOf"));
11847 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11849 /* if the operand is on the stack then we
11850 need to get the stack offset of this
11855 /* if 10 bit stack */
11856 if (options.stack10bit) {
11860 tsprintf(buff, sizeof(buff),
11861 "#!constbyte",(options.stack_loc >> 16) & 0xff);
11862 /* if it has an offset then we need to compute it */
11863 /* emitcode ("subb", "a,#!constbyte", */
11864 /* -((sym->stack < 0) ? */
11865 /* ((short) (sym->stack - _G.nRegsSaved)) : */
11866 /* ((short) sym->stack)) & 0xff); */
11867 /* emitcode ("mov","b,a"); */
11868 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
11869 /* ((short) (sym->stack - _G.nRegsSaved)) : */
11870 /* ((short) sym->stack)) >> 8) & 0xff); */
11872 emitcode ("mov", "a,_bpx");
11873 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
11874 ((char) (sym->stack - _G.nRegsSaved)) :
11875 ((char) sym->stack )) & 0xff);
11876 emitcode ("mov", "b,a");
11877 emitcode ("mov", "a,_bpx+1");
11879 offset = (((sym->stack < 0) ?
11880 ((short) (sym->stack - _G.nRegsSaved)) :
11881 ((short) sym->stack )) >> 8) & 0xff;
11883 emitcode ("addc","a,#!constbyte", offset);
11885 aopPut (IC_RESULT (ic), "b", 0);
11886 aopPut (IC_RESULT (ic), "a", 1);
11887 aopPut (IC_RESULT (ic), buff, 2);
11889 /* we can just move _bp */
11890 aopPut (IC_RESULT (ic), "_bpx", 0);
11891 aopPut (IC_RESULT (ic), "_bpx+1", 1);
11892 aopPut (IC_RESULT (ic), buff, 2);
11895 /* if it has an offset then we need to compute it */
11898 emitcode ("mov", "a,_bp");
11899 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
11900 aopPut (IC_RESULT (ic), "a", 0);
11904 /* we can just move _bp */
11905 aopPut (IC_RESULT (ic), "_bp", 0);
11907 /* fill the result with zero */
11908 size = AOP_SIZE (IC_RESULT (ic)) - 1;
11911 if (options.stack10bit && size < (FPTRSIZE - 1)) {
11913 "*** warning: pointer to stack var truncated.\n");
11919 aopPut (IC_RESULT (ic), zero, offset++);
11925 /* object not on stack then we need the name */
11926 size = AOP_SIZE (IC_RESULT (ic));
11931 char s[SDCC_NAME_MAX];
11935 tsprintf(s, sizeof(s), "#!his",sym->rname);
11938 tsprintf(s, sizeof(s), "#!hihis",sym->rname);
11941 tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
11943 default: /* should not need this (just in case) */
11944 SNPRINTF (s, sizeof(s), "#(%s >> %d)",
11951 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11954 aopPut (IC_RESULT (ic), s, offset++);
11958 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11962 #if 0 // obsolete, and buggy for != xdata
11963 /*-----------------------------------------------------------------*/
11964 /* genArrayInit - generates code for address of */
11965 /*-----------------------------------------------------------------*/
11967 genArrayInit (iCode * ic)
11969 literalList *iLoop;
11971 int elementSize = 0, eIndex;
11972 unsigned val, lastVal;
11974 operand *left=IC_LEFT(ic);
11976 D (emitcode (";", "genArrayInit"));
11978 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
11980 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
11982 // Load immediate value into DPTR.
11983 emitcode("mov", "dptr, %s",
11984 aopGet (IC_LEFT(ic), 0, TRUE, FALSE, NULL));
11986 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
11989 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11990 "Unexpected operand to genArrayInit.\n");
11993 // a regression because of SDCCcse.c:1.52
11994 emitcode ("mov", "dpl,%s", aopGet (left, 0, FALSE, FALSE, NULL));
11995 emitcode ("mov", "dph,%s", aopGet (left, 1, FALSE, FALSE, NULL));
11996 if (options.model == MODEL_FLAT24)
11997 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
12001 type = operandType(IC_LEFT(ic));
12003 if (type && type->next)
12005 elementSize = getSize(type->next);
12009 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12010 "can't determine element size in genArrayInit.\n");
12014 iLoop = IC_ARRAYILIST(ic);
12019 bool firstpass = TRUE;
12021 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
12022 iLoop->count, (int)iLoop->literalValue, elementSize);
12028 symbol *tlbl = NULL;
12030 count = ix > 256 ? 256 : ix;
12034 tlbl = newiTempLabel (NULL);
12035 if (firstpass || (count & 0xff))
12037 emitcode("mov", "b, #!constbyte", count & 0xff);
12045 for (eIndex = 0; eIndex < elementSize; eIndex++)
12047 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
12048 if (val != lastVal)
12050 emitcode("mov", "a, #!constbyte", val);
12054 emitcode("movx", "@dptr, a");
12055 emitcode("inc", "dptr");
12060 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
12066 iLoop = iLoop->next;
12069 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
12073 /*-----------------------------------------------------------------*/
12074 /* genFarFarAssign - assignment when both are in far space */
12075 /*-----------------------------------------------------------------*/
12077 genFarFarAssign (operand * result, operand * right, iCode * ic)
12079 int size = AOP_SIZE (right);
12081 symbol *rSym = NULL;
12085 /* quick & easy case. */
12086 D (emitcode(";","genFarFarAssign (1 byte case)"));
12087 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
12088 freeAsmop (right, NULL, ic, FALSE);
12089 /* now assign DPTR to result */
12091 aopOp(result, ic, FALSE, FALSE);
12093 aopPut (result, "a", 0);
12094 freeAsmop(result, NULL, ic, FALSE);
12098 /* See if we've got an underlying symbol to abuse. */
12099 if (IS_SYMOP(result) && OP_SYMBOL(result))
12101 if (IS_TRUE_SYMOP(result))
12103 rSym = OP_SYMBOL(result);
12105 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
12107 rSym = OP_SYMBOL(result)->usl.spillLoc;
12111 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
12113 /* We can use the '390 auto-toggle feature to good effect here. */
12115 D (emitcode(";", "genFarFarAssign (390 auto-toggle fun)"));
12116 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12117 emitcode ("mov", "dptr,#%s", rSym->rname);
12118 /* DP2 = result, DP1 = right, DP1 is current. */
12121 emitcode("movx", "a,@dptr");
12122 emitcode("movx", "@dptr,a");
12125 emitcode("inc", "dptr");
12126 emitcode("inc", "dptr");
12129 emitcode("mov", "dps,#0");
12130 freeAsmop (right, NULL, ic, FALSE);
12132 some alternative code for processors without auto-toggle
12133 no time to test now, so later well put in...kpb
12134 D (emitcode(";", "genFarFarAssign (dual-dptr fun)"));
12135 emitcode("mov", "dps,#1"); /* Select DPTR2. */
12136 emitcode ("mov", "dptr,#%s", rSym->rname);
12137 /* DP2 = result, DP1 = right, DP1 is current. */
12141 emitcode("movx", "a,@dptr");
12143 emitcode("inc", "dptr");
12144 emitcode("inc", "dps");
12145 emitcode("movx", "@dptr,a");
12147 emitcode("inc", "dptr");
12148 emitcode("inc", "dps");
12150 emitcode("mov", "dps,#0");
12151 freeAsmop (right, NULL, ic, FALSE);
12156 D (emitcode (";", "genFarFarAssign"));
12157 aopOp (result, ic, TRUE, TRUE);
12159 _startLazyDPSEvaluation ();
12164 aopGet (right, offset, FALSE, FALSE, NULL), offset);
12167 _endLazyDPSEvaluation ();
12168 freeAsmop (result, NULL, ic, FALSE);
12169 freeAsmop (right, NULL, ic, FALSE);
12173 /*-----------------------------------------------------------------*/
12174 /* genAssign - generate code for assignment */
12175 /*-----------------------------------------------------------------*/
12177 genAssign (iCode * ic)
12179 operand *result, *right;
12181 unsigned long lit = 0L;
12183 D (emitcode (";", "genAssign"));
12185 result = IC_RESULT (ic);
12186 right = IC_RIGHT (ic);
12188 /* if they are the same */
12189 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
12192 aopOp (right, ic, FALSE, FALSE);
12194 emitcode (";", "genAssign: resultIsFar = %s",
12195 isOperandInFarSpace (result) ?
12198 /* special case both in far space */
12199 if ((AOP_TYPE (right) == AOP_DPTR ||
12200 AOP_TYPE (right) == AOP_DPTR2) &&
12201 /* IS_TRUE_SYMOP(result) && */
12202 isOperandInFarSpace (result))
12204 genFarFarAssign (result, right, ic);
12208 aopOp (result, ic, TRUE, FALSE);
12210 /* if they are the same registers */
12211 if (sameRegs (AOP (right), AOP (result)))
12214 /* if the result is a bit */
12215 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
12217 /* if the right size is a literal then
12218 we know what the value is */
12219 if (AOP_TYPE (right) == AOP_LIT)
12221 if (((int) operandLitValue (right)))
12222 aopPut (result, one, 0);
12224 aopPut (result, zero, 0);
12228 /* the right is also a bit variable */
12229 if (AOP_TYPE (right) == AOP_CRY)
12231 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
12232 aopPut (result, "c", 0);
12236 /* we need to or */
12238 aopPut (result, "a", 0);
12242 /* bit variables done */
12244 size = AOP_SIZE (result);
12246 if (AOP_TYPE (right) == AOP_LIT)
12247 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
12250 (AOP_TYPE (result) != AOP_REG) &&
12251 (AOP_TYPE (right) == AOP_LIT) &&
12252 !IS_FLOAT (operandType (right)))
12254 _startLazyDPSEvaluation ();
12255 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
12258 aopGet (right, offset, FALSE, FALSE, NULL),
12263 /* And now fill the rest with zeros. */
12266 emitcode ("clr", "a");
12270 aopPut (result, "a", offset++);
12272 _endLazyDPSEvaluation ();
12276 _startLazyDPSEvaluation ();
12280 aopGet (right, offset, FALSE, FALSE, NULL),
12284 _endLazyDPSEvaluation ();
12288 freeAsmop (result, NULL, ic, TRUE);
12289 freeAsmop (right, NULL, ic, TRUE);
12292 /*-----------------------------------------------------------------*/
12293 /* genJumpTab - generates code for jump table */
12294 /*-----------------------------------------------------------------*/
12296 genJumpTab (iCode * ic)
12301 D (emitcode (";", "genJumpTab"));
12303 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
12304 /* get the condition into accumulator */
12305 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE, NULL);
12307 /* multiply by four! */
12308 emitcode ("add", "a,acc");
12309 emitcode ("add", "a,acc");
12310 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
12312 jtab = newiTempLabel (NULL);
12313 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
12314 emitcode ("jmp", "@a+dptr");
12316 /* now generate the jump labels */
12317 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
12318 jtab = setNextItem (IC_JTLABELS (ic)))
12319 emitcode ("ljmp", "!tlabel", jtab->key + 100);
12323 /*-----------------------------------------------------------------*/
12324 /* genCast - gen code for casting */
12325 /*-----------------------------------------------------------------*/
12327 genCast (iCode * ic)
12329 operand *result = IC_RESULT (ic);
12330 sym_link *ctype = operandType (IC_LEFT (ic));
12331 sym_link *rtype = operandType (IC_RIGHT (ic));
12332 operand *right = IC_RIGHT (ic);
12335 D (emitcode (";", "genCast"));
12337 /* if they are equivalent then do nothing */
12338 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
12341 aopOp (right, ic, FALSE, AOP_IS_STR (result));
12342 aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR));
12344 /* if the result is a bit (and not a bitfield) */
12345 if (IS_BIT (OP_SYMBOL (result)->type))
12347 /* if the right size is a literal then
12348 we know what the value is */
12349 if (AOP_TYPE (right) == AOP_LIT)
12351 if (((int) operandLitValue (right)))
12352 aopPut (result, one, 0);
12354 aopPut (result, zero, 0);
12359 /* the right is also a bit variable */
12360 if (AOP_TYPE (right) == AOP_CRY)
12362 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
12363 aopPut (result, "c", 0);
12367 /* we need to or */
12369 aopPut (result, "a", 0);
12373 /* if they are the same size : or less */
12374 if (AOP_SIZE (result) <= AOP_SIZE (right))
12377 /* if they are in the same place */
12378 if (sameRegs (AOP (right), AOP (result)))
12381 /* if they in different places then copy */
12382 size = AOP_SIZE (result);
12384 _startLazyDPSEvaluation ();
12388 aopGet (right, offset, FALSE, FALSE, NULL),
12392 _endLazyDPSEvaluation ();
12396 /* if the result is of type pointer */
12397 if (IS_PTR (ctype))
12401 sym_link *type = operandType (right);
12403 /* pointer to generic pointer */
12404 if (IS_GENPTR (ctype))
12408 p_type = DCL_TYPE (type);
12412 #if OLD_CAST_BEHAVIOR
12413 /* KV: we are converting a non-pointer type to
12414 * a generic pointer. This (ifdef'd out) code
12415 * says that the resulting generic pointer
12416 * should have the same class as the storage
12417 * location of the non-pointer variable.
12419 * For example, converting an int (which happens
12420 * to be stored in DATA space) to a pointer results
12421 * in a DATA generic pointer; if the original int
12422 * in XDATA space, so will be the resulting pointer.
12424 * I don't like that behavior, and thus this change:
12425 * all such conversions will be forced to XDATA and
12426 * throw a warning. If you want some non-XDATA
12427 * type, or you want to suppress the warning, you
12428 * must go through an intermediate cast, like so:
12430 * char _generic *gp = (char _xdata *)(intVar);
12432 sym_link *etype = getSpec (type);
12434 /* we have to go by the storage class */
12435 if (SPEC_OCLS (etype) != generic)
12437 p_type = PTR_TYPE (SPEC_OCLS (etype));
12442 /* Converting unknown class (i.e. register variable)
12443 * to generic pointer. This is not good, but
12444 * we'll make a guess (and throw a warning).
12447 werror (W_INT_TO_GEN_PTR_CAST);
12451 /* the first two bytes are known */
12452 size = GPTRSIZE - 1;
12454 _startLazyDPSEvaluation ();
12458 aopGet (right, offset, FALSE, FALSE, NULL),
12462 _endLazyDPSEvaluation ();
12464 /* the last byte depending on type */
12466 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
12471 // pointerTypeToGPByte will have bitched.
12475 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%x", gpVal);
12476 aopPut (result, gpValStr, GPTRSIZE - 1);
12481 /* just copy the pointers */
12482 size = AOP_SIZE (result);
12484 _startLazyDPSEvaluation ();
12488 aopGet (right, offset, FALSE, FALSE, NULL),
12492 _endLazyDPSEvaluation ();
12496 /* so we now know that the size of destination is greater
12497 than the size of the source */
12498 /* we move to result for the size of source */
12499 size = AOP_SIZE (right);
12501 _startLazyDPSEvaluation ();
12505 aopGet (right, offset, FALSE, FALSE, NULL),
12509 _endLazyDPSEvaluation ();
12511 /* now depending on the sign of the source && destination */
12512 size = AOP_SIZE (result) - AOP_SIZE (right);
12513 /* if unsigned or not an integral type */
12514 /* also, if the source is a bit, we don't need to sign extend, because
12515 * it can't possibly have set the sign bit.
12517 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
12521 aopPut (result, zero, offset++);
12526 /* we need to extend the sign :{ */
12527 MOVA (aopGet (right, AOP_SIZE (right) - 1,
12528 FALSE, FALSE, NULL));
12529 emitcode ("rlc", "a");
12530 emitcode ("subb", "a,acc");
12532 aopPut (result, "a", offset++);
12535 /* we are done hurray !!!! */
12538 freeAsmop (right, NULL, ic, TRUE);
12539 freeAsmop (result, NULL, ic, TRUE);
12543 /*-----------------------------------------------------------------*/
12544 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
12545 /*-----------------------------------------------------------------*/
12546 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
12548 operand *from , *to , *count;
12553 /* we know it has to be 3 parameters */
12554 assert (nparms == 3);
12556 rsave = newBitVect(16);
12557 /* save DPTR if it needs to be saved */
12558 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12559 if (bitVectBitValue(ic->rMask,i))
12560 rsave = bitVectSetBit(rsave,i);
12562 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12563 ds390_rUmaskForOp (IC_RESULT(ic))));
12570 aopOp (from, ic->next, FALSE, FALSE);
12572 /* get from into DPTR1 */
12573 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12574 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12575 if (options.model == MODEL_FLAT24) {
12576 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12579 freeAsmop (from, NULL, ic, FALSE);
12580 aopOp (to, ic, FALSE, FALSE);
12581 /* get "to" into DPTR */
12582 /* if the operand is already in dptr
12583 then we do nothing else we move the value to dptr */
12584 if (AOP_TYPE (to) != AOP_STR) {
12585 /* if already in DPTR then we need to push */
12586 if (AOP_TYPE(to) == AOP_DPTR) {
12587 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12588 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12589 if (options.model == MODEL_FLAT24)
12590 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12591 emitcode ("pop", "dph");
12592 emitcode ("pop", "dpl");
12594 _startLazyDPSEvaluation ();
12595 /* if this is remateriazable */
12596 if (AOP_TYPE (to) == AOP_IMMD) {
12597 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12598 } else { /* we need to get it byte by byte */
12599 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12600 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12601 if (options.model == MODEL_FLAT24) {
12602 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12605 _endLazyDPSEvaluation ();
12608 freeAsmop (to, NULL, ic, FALSE);
12609 _G.dptrInUse = _G.dptr1InUse = 1;
12610 aopOp (count, ic->next->next, FALSE,FALSE);
12611 lbl =newiTempLabel(NULL);
12613 /* now for the actual copy */
12614 if (AOP_TYPE(count) == AOP_LIT &&
12615 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12616 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12618 emitcode ("lcall","__bi_memcpyc2x_s");
12620 emitcode ("lcall","__bi_memcpyx2x_s");
12622 freeAsmop (count, NULL, ic, FALSE);
12624 symbol *lbl1 = newiTempLabel(NULL);
12626 emitcode (";"," Auto increment but no djnz");
12627 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
12628 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
12629 freeAsmop (count, NULL, ic, FALSE);
12630 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12633 emitcode ("clr","a");
12634 emitcode ("movc", "a,@a+dptr");
12636 emitcode ("movx", "a,@dptr");
12637 emitcode ("movx", "@dptr,a");
12638 emitcode ("inc", "dptr");
12639 emitcode ("inc", "dptr");
12640 emitcode ("mov","a,b");
12641 emitcode ("orl","a,_ap");
12642 emitcode ("jz","!tlabel",lbl1->key+100);
12643 emitcode ("mov","a,_ap");
12644 emitcode ("add","a,#!constbyte",0xFF);
12645 emitcode ("mov","_ap,a");
12646 emitcode ("mov","a,b");
12647 emitcode ("addc","a,#!constbyte",0xFF);
12648 emitcode ("mov","b,a");
12649 emitcode ("sjmp","!tlabel",lbl->key+100);
12652 emitcode ("mov", "dps,#0");
12653 _G.dptrInUse = _G.dptr1InUse = 0;
12654 unsavermask(rsave);
12658 /*-----------------------------------------------------------------*/
12659 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
12660 /*-----------------------------------------------------------------*/
12661 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
12663 operand *from , *to , *count;
12668 /* we know it has to be 3 parameters */
12669 assert (nparms == 3);
12671 rsave = newBitVect(16);
12672 /* save DPTR if it needs to be saved */
12673 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12674 if (bitVectBitValue(ic->rMask,i))
12675 rsave = bitVectSetBit(rsave,i);
12677 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12678 ds390_rUmaskForOp (IC_RESULT(ic))));
12685 aopOp (from, ic->next, FALSE, FALSE);
12687 /* get from into DPTR1 */
12688 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12689 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12690 if (options.model == MODEL_FLAT24) {
12691 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12694 freeAsmop (from, NULL, ic, FALSE);
12695 aopOp (to, ic, FALSE, FALSE);
12696 /* get "to" into DPTR */
12697 /* if the operand is already in dptr
12698 then we do nothing else we move the value to dptr */
12699 if (AOP_TYPE (to) != AOP_STR) {
12700 /* if already in DPTR then we need to push */
12701 if (AOP_TYPE(to) == AOP_DPTR) {
12702 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12703 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12704 if (options.model == MODEL_FLAT24)
12705 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12706 emitcode ("pop", "dph");
12707 emitcode ("pop", "dpl");
12709 _startLazyDPSEvaluation ();
12710 /* if this is remateriazable */
12711 if (AOP_TYPE (to) == AOP_IMMD) {
12712 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12713 } else { /* we need to get it byte by byte */
12714 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12715 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12716 if (options.model == MODEL_FLAT24) {
12717 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12720 _endLazyDPSEvaluation ();
12723 freeAsmop (to, NULL, ic, FALSE);
12724 _G.dptrInUse = _G.dptr1InUse = 1;
12725 aopOp (count, ic->next->next, FALSE,FALSE);
12726 lbl =newiTempLabel(NULL);
12727 lbl2 =newiTempLabel(NULL);
12729 /* now for the actual compare */
12730 if (AOP_TYPE(count) == AOP_LIT &&
12731 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12732 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12734 emitcode("lcall","__bi_memcmpc2x_s");
12736 emitcode("lcall","__bi_memcmpx2x_s");
12737 freeAsmop (count, NULL, ic, FALSE);
12738 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12739 aopPut(IC_RESULT(ic),"a",0);
12740 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12742 symbol *lbl1 = newiTempLabel(NULL);
12744 emitcode("push","ar0");
12745 emitcode (";"," Auto increment but no djnz");
12746 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
12747 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
12748 freeAsmop (count, NULL, ic, FALSE);
12749 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12752 emitcode ("clr","a");
12753 emitcode ("movc", "a,@a+dptr");
12755 emitcode ("movx", "a,@dptr");
12756 emitcode ("mov","r0,a");
12757 emitcode ("movx", "a,@dptr");
12758 emitcode ("clr","c");
12759 emitcode ("subb","a,r0");
12760 emitcode ("jnz","!tlabel",lbl2->key+100);
12761 emitcode ("inc", "dptr");
12762 emitcode ("inc", "dptr");
12763 emitcode ("mov","a,b");
12764 emitcode ("orl","a,_ap");
12765 emitcode ("jz","!tlabel",lbl1->key+100);
12766 emitcode ("mov","a,_ap");
12767 emitcode ("add","a,#!constbyte",0xFF);
12768 emitcode ("mov","_ap,a");
12769 emitcode ("mov","a,b");
12770 emitcode ("addc","a,#!constbyte",0xFF);
12771 emitcode ("mov","b,a");
12772 emitcode ("sjmp","!tlabel",lbl->key+100);
12774 emitcode ("clr","a");
12776 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12777 aopPut(IC_RESULT(ic),"a",0);
12778 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12779 emitcode("pop","ar0");
12780 emitcode ("mov", "dps,#0");
12782 _G.dptrInUse = _G.dptr1InUse = 0;
12783 unsavermask(rsave);
12787 /*-----------------------------------------------------------------*/
12788 /* genInp - gen code for __builtin_inp read data from a mem mapped */
12789 /* port, first parameter output area second parameter pointer to */
12790 /* port third parameter count */
12791 /*-----------------------------------------------------------------*/
12792 static void genInp( iCode *ic, int nparms, operand **parms)
12794 operand *from , *to , *count;
12799 /* we know it has to be 3 parameters */
12800 assert (nparms == 3);
12802 rsave = newBitVect(16);
12803 /* save DPTR if it needs to be saved */
12804 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12805 if (bitVectBitValue(ic->rMask,i))
12806 rsave = bitVectSetBit(rsave,i);
12808 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12809 ds390_rUmaskForOp (IC_RESULT(ic))));
12816 aopOp (from, ic->next, FALSE, FALSE);
12818 /* get from into DPTR1 */
12819 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12820 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12821 if (options.model == MODEL_FLAT24) {
12822 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12825 freeAsmop (from, NULL, ic, FALSE);
12826 aopOp (to, ic, FALSE, FALSE);
12827 /* get "to" into DPTR */
12828 /* if the operand is already in dptr
12829 then we do nothing else we move the value to dptr */
12830 if (AOP_TYPE (to) != AOP_STR) {
12831 /* if already in DPTR then we need to push */
12832 if (AOP_TYPE(to) == AOP_DPTR) {
12833 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12834 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12835 if (options.model == MODEL_FLAT24)
12836 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12837 emitcode ("pop", "dph");
12838 emitcode ("pop", "dpl");
12840 _startLazyDPSEvaluation ();
12841 /* if this is remateriazable */
12842 if (AOP_TYPE (to) == AOP_IMMD) {
12843 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12844 } else { /* we need to get it byte by byte */
12845 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12846 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12847 if (options.model == MODEL_FLAT24) {
12848 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12851 _endLazyDPSEvaluation ();
12854 freeAsmop (to, NULL, ic, FALSE);
12856 _G.dptrInUse = _G.dptr1InUse = 1;
12857 aopOp (count, ic->next->next, FALSE,FALSE);
12858 lbl =newiTempLabel(NULL);
12860 /* now for the actual copy */
12861 if (AOP_TYPE(count) == AOP_LIT &&
12862 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12863 emitcode (";","OH JOY auto increment with djnz (very fast)");
12864 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
12865 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12866 freeAsmop (count, NULL, ic, FALSE);
12868 emitcode ("movx", "a,@dptr"); /* read data from port */
12869 emitcode ("dec","dps"); /* switch to DPTR */
12870 emitcode ("movx", "@dptr,a"); /* save into location */
12871 emitcode ("inc", "dptr"); /* point to next area */
12872 emitcode ("inc","dps"); /* switch to DPTR2 */
12873 emitcode ("djnz","b,!tlabel",lbl->key+100);
12875 symbol *lbl1 = newiTempLabel(NULL);
12877 emitcode (";"," Auto increment but no djnz");
12878 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
12879 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
12880 freeAsmop (count, NULL, ic, FALSE);
12881 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
12883 emitcode ("movx", "a,@dptr");
12884 emitcode ("dec","dps"); /* switch to DPTR */
12885 emitcode ("movx", "@dptr,a");
12886 emitcode ("inc", "dptr");
12887 emitcode ("inc","dps"); /* switch to DPTR2 */
12888 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
12889 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
12890 emitcode ("mov","a,b");
12891 emitcode ("orl","a,_ap");
12892 emitcode ("jz","!tlabel",lbl1->key+100);
12893 emitcode ("mov","a,_ap");
12894 emitcode ("add","a,#!constbyte",0xFF);
12895 emitcode ("mov","_ap,a");
12896 emitcode ("mov","a,b");
12897 emitcode ("addc","a,#!constbyte",0xFF);
12898 emitcode ("mov","b,a");
12899 emitcode ("sjmp","!tlabel",lbl->key+100);
12902 emitcode ("mov", "dps,#0");
12903 _G.dptrInUse = _G.dptr1InUse = 0;
12904 unsavermask(rsave);
12908 /*-----------------------------------------------------------------*/
12909 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
12910 /* port, first parameter output area second parameter pointer to */
12911 /* port third parameter count */
12912 /*-----------------------------------------------------------------*/
12913 static void genOutp( iCode *ic, int nparms, operand **parms)
12915 operand *from , *to , *count;
12920 /* we know it has to be 3 parameters */
12921 assert (nparms == 3);
12923 rsave = newBitVect(16);
12924 /* save DPTR if it needs to be saved */
12925 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12926 if (bitVectBitValue(ic->rMask,i))
12927 rsave = bitVectSetBit(rsave,i);
12929 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12930 ds390_rUmaskForOp (IC_RESULT(ic))));
12937 aopOp (from, ic->next, FALSE, FALSE);
12939 /* get from into DPTR1 */
12940 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12941 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12942 if (options.model == MODEL_FLAT24) {
12943 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12946 freeAsmop (from, NULL, ic, FALSE);
12947 aopOp (to, ic, FALSE, FALSE);
12948 /* get "to" into DPTR */
12949 /* if the operand is already in dptr
12950 then we do nothing else we move the value to dptr */
12951 if (AOP_TYPE (to) != AOP_STR) {
12952 /* if already in DPTR then we need to push */
12953 if (AOP_TYPE(to) == AOP_DPTR) {
12954 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12955 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12956 if (options.model == MODEL_FLAT24)
12957 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12958 emitcode ("pop", "dph");
12959 emitcode ("pop", "dpl");
12961 _startLazyDPSEvaluation ();
12962 /* if this is remateriazable */
12963 if (AOP_TYPE (to) == AOP_IMMD) {
12964 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12965 } else { /* we need to get it byte by byte */
12966 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12967 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12968 if (options.model == MODEL_FLAT24) {
12969 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12972 _endLazyDPSEvaluation ();
12975 freeAsmop (to, NULL, ic, FALSE);
12977 _G.dptrInUse = _G.dptr1InUse = 1;
12978 aopOp (count, ic->next->next, FALSE,FALSE);
12979 lbl =newiTempLabel(NULL);
12981 /* now for the actual copy */
12982 if (AOP_TYPE(count) == AOP_LIT &&
12983 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12984 emitcode (";","OH JOY auto increment with djnz (very fast)");
12985 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
12986 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12988 emitcode ("movx", "a,@dptr"); /* read data from port */
12989 emitcode ("inc","dps"); /* switch to DPTR2 */
12990 emitcode ("movx", "@dptr,a"); /* save into location */
12991 emitcode ("inc", "dptr"); /* point to next area */
12992 emitcode ("dec","dps"); /* switch to DPTR */
12993 emitcode ("djnz","b,!tlabel",lbl->key+100);
12994 freeAsmop (count, NULL, ic, FALSE);
12996 symbol *lbl1 = newiTempLabel(NULL);
12998 emitcode (";"," Auto increment but no djnz");
12999 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
13000 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
13001 freeAsmop (count, NULL, ic, FALSE);
13002 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
13004 emitcode ("movx", "a,@dptr");
13005 emitcode ("inc", "dptr");
13006 emitcode ("inc","dps"); /* switch to DPTR2 */
13007 emitcode ("movx", "@dptr,a");
13008 emitcode ("dec","dps"); /* switch to DPTR */
13009 emitcode ("mov","a,b");
13010 emitcode ("orl","a,_ap");
13011 emitcode ("jz","!tlabel",lbl1->key+100);
13012 emitcode ("mov","a,_ap");
13013 emitcode ("add","a,#!constbyte",0xFF);
13014 emitcode ("mov","_ap,a");
13015 emitcode ("mov","a,b");
13016 emitcode ("addc","a,#!constbyte",0xFF);
13017 emitcode ("mov","b,a");
13018 emitcode ("sjmp","!tlabel",lbl->key+100);
13021 emitcode ("mov", "dps,#0");
13022 _G.dptrInUse = _G.dptr1InUse = 0;
13023 unsavermask(rsave);
13027 /*-----------------------------------------------------------------*/
13028 /* genSwapW - swap lower & high order bytes */
13029 /*-----------------------------------------------------------------*/
13030 static void genSwapW(iCode *ic, int nparms, operand **parms)
13034 assert (nparms==1);
13037 dest=IC_RESULT(ic);
13039 assert(getSize(operandType(src))==2);
13041 aopOp (src, ic, FALSE, FALSE);
13042 emitcode ("mov","a,%s",aopGet(src,0,FALSE,FALSE,NULL));
13044 MOVB(aopGet(src,1,FALSE,FALSE,"b"));
13046 freeAsmop (src, NULL, ic, FALSE);
13048 aopOp (dest,ic, FALSE, FALSE);
13049 aopPut(dest,"b",0);
13050 aopPut(dest,"a",1);
13051 freeAsmop (dest, NULL, ic, FALSE);
13054 /*-----------------------------------------------------------------*/
13055 /* genMemsetX - gencode for memSetX data */
13056 /*-----------------------------------------------------------------*/
13057 static void genMemsetX(iCode *ic, int nparms, operand **parms)
13059 operand *to , *val , *count;
13065 /* we know it has to be 3 parameters */
13066 assert (nparms == 3);
13072 /* save DPTR if it needs to be saved */
13073 rsave = newBitVect(16);
13074 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
13075 if (bitVectBitValue(ic->rMask,i))
13076 rsave = bitVectSetBit(rsave,i);
13078 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
13079 ds390_rUmaskForOp (IC_RESULT(ic))));
13082 aopOp (to, ic, FALSE, FALSE);
13083 /* get "to" into DPTR */
13084 /* if the operand is already in dptr
13085 then we do nothing else we move the value to dptr */
13086 if (AOP_TYPE (to) != AOP_STR) {
13087 /* if already in DPTR then we need to push */
13088 if (AOP_TYPE(to) == AOP_DPTR) {
13089 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
13090 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
13091 if (options.model == MODEL_FLAT24)
13092 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
13093 emitcode ("pop", "dph");
13094 emitcode ("pop", "dpl");
13096 _startLazyDPSEvaluation ();
13097 /* if this is remateriazable */
13098 if (AOP_TYPE (to) == AOP_IMMD) {
13099 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
13100 } else { /* we need to get it byte by byte */
13101 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
13102 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
13103 if (options.model == MODEL_FLAT24) {
13104 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
13107 _endLazyDPSEvaluation ();
13110 freeAsmop (to, NULL, ic, FALSE);
13112 aopOp (val, ic->next->next, FALSE,FALSE);
13113 aopOp (count, ic->next->next, FALSE,FALSE);
13114 lbl =newiTempLabel(NULL);
13115 /* now for the actual copy */
13116 if (AOP_TYPE(count) == AOP_LIT &&
13117 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
13118 l = aopGet(val, 0, FALSE, FALSE, NULL);
13119 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
13122 emitcode ("movx", "@dptr,a");
13123 emitcode ("inc", "dptr");
13124 emitcode ("djnz","b,!tlabel",lbl->key+100);
13126 symbol *lbl1 = newiTempLabel(NULL);
13128 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
13129 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
13131 MOVA (aopGet(val, 0, FALSE, FALSE, NULL));
13132 emitcode ("movx", "@dptr,a");
13133 emitcode ("inc", "dptr");
13134 emitcode ("mov","a,b");
13135 emitcode ("orl","a,_ap");
13136 emitcode ("jz","!tlabel",lbl1->key+100);
13137 emitcode ("mov","a,_ap");
13138 emitcode ("add","a,#!constbyte",0xFF);
13139 emitcode ("mov","_ap,a");
13140 emitcode ("mov","a,b");
13141 emitcode ("addc","a,#!constbyte",0xFF);
13142 emitcode ("mov","b,a");
13143 emitcode ("sjmp","!tlabel",lbl->key+100);
13146 freeAsmop (count, NULL, ic, FALSE);
13147 unsavermask(rsave);
13150 /*-----------------------------------------------------------------*/
13151 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
13152 /*-----------------------------------------------------------------*/
13153 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
13156 operand *pnum, *result;
13159 assert (nparms==1);
13160 /* save registers that need to be saved */
13161 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13162 ds390_rUmaskForOp (IC_RESULT(ic))));
13165 aopOp (pnum, ic, FALSE, FALSE);
13166 emitcode ("mov","a,%s",aopGet(pnum,0,FALSE,FALSE,DP2_RESULT_REG));
13167 freeAsmop (pnum, NULL, ic, FALSE);
13168 emitcode ("lcall","NatLib_LoadPrimitive");
13169 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
13170 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
13171 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
13172 for (i = (size-1) ; i >= 0 ; i-- ) {
13173 emitcode ("push","a%s",javaRet[i]);
13175 for (i=0; i < size ; i++ ) {
13176 emitcode ("pop","a%s",
13177 aopGet(result,i,FALSE,FALSE,DP2_RESULT_REG));
13180 for (i = 0 ; i < size ; i++ ) {
13181 aopPut(result,javaRet[i],i);
13184 freeAsmop (result, NULL, ic, FALSE);
13185 unsavermask(rsave);
13188 /*-----------------------------------------------------------------*/
13189 /* genNatLibLoadPointer - calls TINI api function to load pointer */
13190 /*-----------------------------------------------------------------*/
13191 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
13194 operand *pnum, *result;
13198 assert (nparms==1);
13199 /* save registers that need to be saved */
13200 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13201 ds390_rUmaskForOp (IC_RESULT(ic))));
13204 aopOp (pnum, ic, FALSE, FALSE);
13205 emitcode ("mov","a,%s",aopGet(pnum,0,FALSE,FALSE,DP2_RESULT_REG));
13206 freeAsmop (pnum, NULL, ic, FALSE);
13207 emitcode ("lcall","NatLib_LoadPointer");
13208 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
13209 if (AOP_TYPE(result)!=AOP_STR) {
13210 for (i = 0 ; i < size ; i++ ) {
13211 aopPut(result,fReturn[i],i);
13214 freeAsmop (result, NULL, ic, FALSE);
13215 unsavermask(rsave);
13218 /*-----------------------------------------------------------------*/
13219 /* genNatLibInstallStateBlock - */
13220 /*-----------------------------------------------------------------*/
13221 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
13222 operand **parms, const char *name)
13225 operand *psb, *handle;
13226 assert (nparms==2);
13228 /* save registers that need to be saved */
13229 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13230 ds390_rUmaskForOp (IC_RESULT(ic))));
13234 /* put pointer to state block into DPTR1 */
13235 aopOp (psb, ic, FALSE, FALSE);
13236 if (AOP_TYPE (psb) == AOP_IMMD) {
13237 emitcode ("mov","dps,#1");
13238 emitcode ("mov", "dptr,%s",
13239 aopGet (psb, 0, TRUE, FALSE, DP2_RESULT_REG));
13240 emitcode ("mov","dps,#0");
13242 emitcode ("mov","dpl1,%s",aopGet(psb,0,FALSE,FALSE,DP2_RESULT_REG));
13243 emitcode ("mov","dph1,%s",aopGet(psb,1,FALSE,FALSE,DP2_RESULT_REG));
13244 emitcode ("mov","dpx1,%s",aopGet(psb,2,FALSE,FALSE,DP2_RESULT_REG));
13246 freeAsmop (psb, NULL, ic, FALSE);
13248 /* put libraryID into DPTR */
13249 emitcode ("mov","dptr,#LibraryID");
13251 /* put handle into r3:r2 */
13252 aopOp (handle, ic, FALSE, FALSE);
13253 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13254 emitcode ("push","%s",aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13255 emitcode ("push","%s",aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13256 emitcode ("pop","ar3");
13257 emitcode ("pop","ar2");
13259 emitcode ("mov","r2,%s",aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13260 emitcode ("mov","r3,%s",aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13262 freeAsmop (psb, NULL, ic, FALSE);
13264 /* make the call */
13265 emitcode ("lcall","NatLib_Install%sStateBlock",name);
13267 /* put return value into place*/
13269 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
13271 aopPut(IC_RESULT(ic),"a",0);
13272 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13273 unsavermask(rsave);
13276 /*-----------------------------------------------------------------*/
13277 /* genNatLibRemoveStateBlock - */
13278 /*-----------------------------------------------------------------*/
13279 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
13285 /* save registers that need to be saved */
13286 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13287 ds390_rUmaskForOp (IC_RESULT(ic))));
13289 /* put libraryID into DPTR */
13290 emitcode ("mov","dptr,#LibraryID");
13291 /* make the call */
13292 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
13293 unsavermask(rsave);
13296 /*-----------------------------------------------------------------*/
13297 /* genNatLibGetStateBlock - */
13298 /*-----------------------------------------------------------------*/
13299 static void genNatLibGetStateBlock(iCode *ic,int nparms,
13300 operand **parms,const char *name)
13303 symbol *lbl = newiTempLabel(NULL);
13306 /* save registers that need to be saved */
13307 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13308 ds390_rUmaskForOp (IC_RESULT(ic))));
13310 /* put libraryID into DPTR */
13311 emitcode ("mov","dptr,#LibraryID");
13312 /* make the call */
13313 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
13314 emitcode ("jnz","!tlabel",lbl->key+100);
13316 /* put return value into place */
13317 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
13318 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
13319 emitcode ("push","ar3");
13320 emitcode ("push","ar2");
13321 emitcode ("pop","%s",
13322 aopGet(IC_RESULT(ic),0,FALSE,TRUE,DP2_RESULT_REG));
13323 emitcode ("pop","%s",
13324 aopGet(IC_RESULT(ic),1,FALSE,TRUE,DP2_RESULT_REG));
13326 aopPut(IC_RESULT(ic),"r2",0);
13327 aopPut(IC_RESULT(ic),"r3",1);
13329 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13331 unsavermask(rsave);
13334 /*-----------------------------------------------------------------*/
13335 /* genMMMalloc - */
13336 /*-----------------------------------------------------------------*/
13337 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
13338 int size, const char *name)
13343 symbol *lbl = newiTempLabel(NULL);
13345 assert (nparms == 1);
13346 /* save registers that need to be saved */
13347 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13348 ds390_rUmaskForOp (IC_RESULT(ic))));
13351 aopOp (bsize,ic,FALSE,FALSE);
13353 /* put the size in R4-R2 */
13354 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
13355 emitcode("push","%s",aopGet(bsize,0,FALSE,TRUE,DP2_RESULT_REG));
13356 emitcode("push","%s",aopGet(bsize,1,FALSE,TRUE,DP2_RESULT_REG));
13358 emitcode("push","%s",aopGet(bsize,2,FALSE,TRUE,DP2_RESULT_REG));
13359 emitcode("pop","ar4");
13361 emitcode("pop","ar3");
13362 emitcode("pop","ar2");
13364 emitcode ("mov","r2,%s",aopGet(bsize,0,FALSE,TRUE,DP2_RESULT_REG));
13365 emitcode ("mov","r3,%s",aopGet(bsize,1,FALSE,TRUE,DP2_RESULT_REG));
13367 emitcode("mov","r4,%s",aopGet(bsize,2,FALSE,TRUE,DP2_RESULT_REG));
13370 freeAsmop (bsize, NULL, ic, FALSE);
13372 /* make the call */
13373 emitcode ("lcall","MM_%s",name);
13374 emitcode ("jz","!tlabel",lbl->key+100);
13375 emitcode ("mov","r2,#!constbyte",0xff);
13376 emitcode ("mov","r3,#!constbyte",0xff);
13378 /* we don't care about the pointer : we just save the handle */
13379 rsym = OP_SYMBOL(IC_RESULT(ic));
13380 if (rsym->liveFrom != rsym->liveTo) {
13381 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
13382 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
13383 emitcode ("push","ar3");
13384 emitcode ("push","ar2");
13385 emitcode ("pop","%s",
13386 aopGet(IC_RESULT(ic),0,FALSE,TRUE,DP2_RESULT_REG));
13387 emitcode ("pop","%s",
13388 aopGet(IC_RESULT(ic),1,FALSE,TRUE,DP2_RESULT_REG));
13390 aopPut(IC_RESULT(ic),"r2",0);
13391 aopPut(IC_RESULT(ic),"r3",1);
13393 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13395 unsavermask(rsave);
13398 /*-----------------------------------------------------------------*/
13400 /*-----------------------------------------------------------------*/
13401 static void genMMDeref (iCode *ic,int nparms, operand **parms)
13406 assert (nparms == 1);
13407 /* save registers that need to be saved */
13408 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13409 ds390_rUmaskForOp (IC_RESULT(ic))));
13412 aopOp (handle,ic,FALSE,FALSE);
13414 /* put the size in R4-R2 */
13415 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13416 emitcode("push","%s",
13417 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13418 emitcode("push","%s",
13419 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13420 emitcode("pop","ar3");
13421 emitcode("pop","ar2");
13423 emitcode ("mov","r2,%s",
13424 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13425 emitcode ("mov","r3,%s",
13426 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13428 freeAsmop (handle, NULL, ic, FALSE);
13430 /* make the call */
13431 emitcode ("lcall","MM_Deref");
13434 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13435 if (rsym->liveFrom != rsym->liveTo) {
13436 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13437 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
13438 _startLazyDPSEvaluation ();
13440 aopPut(IC_RESULT(ic),"dpl",0);
13441 aopPut(IC_RESULT(ic),"dph",1);
13442 aopPut(IC_RESULT(ic),"dpx",2);
13444 _endLazyDPSEvaluation ();
13449 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13450 unsavermask(rsave);
13453 /*-----------------------------------------------------------------*/
13454 /* genMMUnrestrictedPersist - */
13455 /*-----------------------------------------------------------------*/
13456 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
13461 assert (nparms == 1);
13462 /* save registers that need to be saved */
13463 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13464 ds390_rUmaskForOp (IC_RESULT(ic))));
13467 aopOp (handle,ic,FALSE,FALSE);
13469 /* put the size in R3-R2 */
13470 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13471 emitcode("push","%s",
13472 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13473 emitcode("push","%s",
13474 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13475 emitcode("pop","ar3");
13476 emitcode("pop","ar2");
13478 emitcode ("mov","r2,%s",
13479 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13480 emitcode ("mov","r3,%s",
13481 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13483 freeAsmop (handle, NULL, ic, FALSE);
13485 /* make the call */
13486 emitcode ("lcall","MM_UnrestrictedPersist");
13489 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13490 if (rsym->liveFrom != rsym->liveTo) {
13491 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13492 aopPut(IC_RESULT(ic),"a",0);
13493 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13496 unsavermask(rsave);
13499 /*-----------------------------------------------------------------*/
13500 /* genSystemExecJavaProcess - */
13501 /*-----------------------------------------------------------------*/
13502 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
13505 operand *handle, *pp;
13507 assert (nparms==2);
13508 /* save registers that need to be saved */
13509 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13510 ds390_rUmaskForOp (IC_RESULT(ic))));
13515 /* put the handle in R3-R2 */
13516 aopOp (handle,ic,FALSE,FALSE);
13517 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13518 emitcode("push","%s",
13519 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13520 emitcode("push","%s",
13521 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13522 emitcode("pop","ar3");
13523 emitcode("pop","ar2");
13525 emitcode ("mov","r2,%s",
13526 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13527 emitcode ("mov","r3,%s",
13528 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13530 freeAsmop (handle, NULL, ic, FALSE);
13532 /* put pointer in DPTR */
13533 aopOp (pp,ic,FALSE,FALSE);
13534 if (AOP_TYPE(pp) == AOP_IMMD) {
13535 emitcode ("mov", "dptr,%s",
13536 aopGet (pp, 0, TRUE, FALSE, NULL));
13537 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
13538 emitcode ("mov","dpl,%s",aopGet(pp,0,FALSE,FALSE,NULL));
13539 emitcode ("mov","dph,%s",aopGet(pp,1,FALSE,FALSE,NULL));
13540 emitcode ("mov","dpx,%s",aopGet(pp,2,FALSE,FALSE,NULL));
13542 freeAsmop (handle, NULL, ic, FALSE);
13544 /* make the call */
13545 emitcode ("lcall","System_ExecJavaProcess");
13547 /* put result in place */
13549 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13550 if (rsym->liveFrom != rsym->liveTo) {
13551 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13552 aopPut(IC_RESULT(ic),"a",0);
13553 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13557 unsavermask(rsave);
13560 /*-----------------------------------------------------------------*/
13561 /* genSystemRTCRegisters - */
13562 /*-----------------------------------------------------------------*/
13563 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
13569 assert (nparms==1);
13570 /* save registers that need to be saved */
13571 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13572 ds390_rUmaskForOp (IC_RESULT(ic))));
13575 /* put pointer in DPTR */
13576 aopOp (pp,ic,FALSE,FALSE);
13577 if (AOP_TYPE (pp) == AOP_IMMD) {
13578 emitcode ("mov","dps,#1");
13579 emitcode ("mov", "dptr,%s",
13580 aopGet (pp, 0, TRUE, FALSE, NULL));
13581 emitcode ("mov","dps,#0");
13583 emitcode ("mov","dpl1,%s",
13584 aopGet(pp,0,FALSE,FALSE,DP2_RESULT_REG));
13585 emitcode ("mov","dph1,%s",
13586 aopGet(pp,1,FALSE,FALSE,DP2_RESULT_REG));
13587 emitcode ("mov","dpx1,%s",
13588 aopGet(pp,2,FALSE,FALSE,DP2_RESULT_REG));
13590 freeAsmop (pp, NULL, ic, FALSE);
13592 /* make the call */
13593 emitcode ("lcall","System_%sRTCRegisters",name);
13595 unsavermask(rsave);
13598 /*-----------------------------------------------------------------*/
13599 /* genSystemThreadSleep - */
13600 /*-----------------------------------------------------------------*/
13601 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
13606 assert (nparms==1);
13607 /* save registers that need to be saved */
13608 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13609 ds390_rUmaskForOp (IC_RESULT(ic))));
13612 aopOp(to,ic,FALSE,FALSE);
13613 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
13614 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
13615 emitcode ("push","%s",
13616 aopGet(to,0,FALSE,TRUE,DP2_RESULT_REG));
13617 emitcode ("push","%s",
13618 aopGet(to,1,FALSE,TRUE,DP2_RESULT_REG));
13619 emitcode ("push","%s",
13620 aopGet(to,2,FALSE,TRUE,DP2_RESULT_REG));
13621 emitcode ("push","%s",
13622 aopGet(to,3,FALSE,TRUE,DP2_RESULT_REG));
13623 emitcode ("pop","ar3");
13624 emitcode ("pop","ar2");
13625 emitcode ("pop","ar1");
13626 emitcode ("pop","ar0");
13628 emitcode ("mov","r0,%s",
13629 aopGet(to,0,FALSE,TRUE,DP2_RESULT_REG));
13630 emitcode ("mov","r1,%s",
13631 aopGet(to,1,FALSE,TRUE,DP2_RESULT_REG));
13632 emitcode ("mov","r2,%s",
13633 aopGet(to,2,FALSE,TRUE,DP2_RESULT_REG));
13634 emitcode ("mov","r3,%s",
13635 aopGet(to,3,FALSE,TRUE,DP2_RESULT_REG));
13637 freeAsmop (to, NULL, ic, FALSE);
13639 /* suspend in acc */
13641 aopOp(s,ic,FALSE,FALSE);
13642 emitcode ("mov","a,%s",
13643 aopGet(s,0,FALSE,TRUE,NULL));
13644 freeAsmop (s, NULL, ic, FALSE);
13646 /* make the call */
13647 emitcode ("lcall","System_%s",name);
13649 unsavermask(rsave);
13652 /*-----------------------------------------------------------------*/
13653 /* genSystemThreadResume - */
13654 /*-----------------------------------------------------------------*/
13655 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
13660 assert (nparms==2);
13661 /* save registers that need to be saved */
13662 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13663 ds390_rUmaskForOp (IC_RESULT(ic))));
13669 aopOp(pid,ic,FALSE,FALSE);
13670 emitcode ("mov","r0,%s",
13671 aopGet(pid,0,FALSE,TRUE,DP2_RESULT_REG));
13672 freeAsmop (pid, NULL, ic, FALSE);
13675 aopOp(tid,ic,FALSE,FALSE);
13676 emitcode ("mov","a,%s",
13677 aopGet(tid,0,FALSE,TRUE,DP2_RESULT_REG));
13678 freeAsmop (tid, NULL, ic, FALSE);
13680 emitcode ("lcall","System_ThreadResume");
13682 /* put result into place */
13684 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13685 if (rsym->liveFrom != rsym->liveTo) {
13686 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13687 aopPut(IC_RESULT(ic),"a",0);
13688 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13691 unsavermask(rsave);
13694 /*-----------------------------------------------------------------*/
13695 /* genSystemProcessResume - */
13696 /*-----------------------------------------------------------------*/
13697 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
13702 assert (nparms==1);
13703 /* save registers that need to be saved */
13704 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13705 ds390_rUmaskForOp (IC_RESULT(ic))));
13710 aopOp(pid,ic,FALSE,FALSE);
13711 emitcode ("mov","a,%s",
13712 aopGet(pid,0,FALSE,TRUE,DP2_RESULT_REG));
13713 freeAsmop (pid, NULL, ic, FALSE);
13715 emitcode ("lcall","System_ProcessResume");
13717 unsavermask(rsave);
13720 /*-----------------------------------------------------------------*/
13722 /*-----------------------------------------------------------------*/
13723 static void genSystem (iCode *ic,int nparms,char *name)
13725 assert(nparms == 0);
13727 emitcode ("lcall","System_%s",name);
13730 /*-----------------------------------------------------------------*/
13731 /* genSystemPoll - */
13732 /*-----------------------------------------------------------------*/
13733 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
13738 assert (nparms==1);
13739 /* save registers that need to be saved */
13740 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13741 ds390_rUmaskForOp (IC_RESULT(ic))));
13744 aopOp (fp,ic,FALSE,FALSE);
13745 if (AOP_TYPE (fp) == AOP_IMMD) {
13746 emitcode ("mov", "dptr,%s",
13747 aopGet (fp, 0, TRUE, FALSE, DP2_RESULT_REG));
13748 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
13749 emitcode ("mov","dpl,%s",
13750 aopGet(fp,0,FALSE,FALSE,DP2_RESULT_REG));
13751 emitcode ("mov","dph,%s",
13752 aopGet(fp,1,FALSE,FALSE,DP2_RESULT_REG));
13753 emitcode ("mov","dpx,%s",
13754 aopGet(fp,2,FALSE,FALSE,DP2_RESULT_REG));
13756 freeAsmop (fp, NULL, ic, FALSE);
13758 emitcode ("lcall","System_%sPoll",name);
13760 /* put result into place */
13762 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13763 if (rsym->liveFrom != rsym->liveTo) {
13764 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13765 aopPut(IC_RESULT(ic),"a",0);
13766 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13769 unsavermask(rsave);
13772 /*-----------------------------------------------------------------*/
13773 /* genSystemGetCurrentID - */
13774 /*-----------------------------------------------------------------*/
13775 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
13777 assert (nparms==0);
13779 emitcode ("lcall","System_GetCurrent%sId",name);
13780 /* put result into place */
13782 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13783 if (rsym->liveFrom != rsym->liveTo) {
13784 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13785 aopPut(IC_RESULT(ic),"a",0);
13786 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13791 /*-----------------------------------------------------------------*/
13792 /* genDjnz - generate decrement & jump if not zero instrucion */
13793 /*-----------------------------------------------------------------*/
13795 genDjnz (iCode * ic, iCode * ifx)
13797 symbol *lbl, *lbl1;
13801 /* if the if condition has a false label
13802 then we cannot save */
13803 if (IC_FALSE (ifx))
13806 /* if the minus is not of the form a = a - 1 */
13807 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
13808 !IS_OP_LITERAL (IC_RIGHT (ic)))
13811 if (operandLitValue (IC_RIGHT (ic)) != 1)
13814 /* if the size of this greater than one then no
13816 if (getSize (operandType (IC_RESULT (ic))) > 1)
13819 /* otherwise we can save BIG */
13821 D (emitcode (";", "genDjnz"));
13823 lbl = newiTempLabel (NULL);
13824 lbl1 = newiTempLabel (NULL);
13826 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
13828 if (AOP_NEEDSACC(IC_RESULT(ic)))
13830 /* If the result is accessed indirectly via
13831 * the accumulator, we must explicitly write
13832 * it back after the decrement.
13834 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE, NULL);
13836 if (strcmp(rByte, "a"))
13838 /* Something is hopelessly wrong */
13839 fprintf(stderr, "*** warning: internal error at %s:%d\n",
13840 __FILE__, __LINE__);
13841 /* We can just give up; the generated code will be inefficient,
13842 * but what the hey.
13844 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13847 emitcode ("dec", "%s", rByte);
13848 aopPut (IC_RESULT (ic), rByte, 0);
13849 emitcode ("jnz", "!tlabel", lbl->key + 100);
13851 else if (IS_AOP_PREG (IC_RESULT (ic)))
13853 emitcode ("dec", "%s",
13854 aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL));
13855 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL));
13856 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13857 ifx->generated = 1;
13858 emitcode ("jnz", "!tlabel", lbl->key + 100);
13862 emitcode ("djnz", "%s,!tlabel", aopGet (IC_RESULT (ic), 0, FALSE, TRUE, NULL),
13865 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
13867 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
13870 if (!ifx->generated)
13871 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13872 ifx->generated = 1;
13876 /*-----------------------------------------------------------------*/
13877 /* genReceive - generate code for a receive iCode */
13878 /*-----------------------------------------------------------------*/
13880 genReceive (iCode * ic)
13882 int size = getSize (operandType (IC_RESULT (ic)));
13886 D (emitcode (";", "genReceive"));
13888 if (ic->argreg == 1)
13890 /* first parameter */
13891 if (AOP_IS_STR(IC_RESULT(ic)))
13893 /* Nothing to do: it's already in the proper place. */
13900 useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
13901 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
13902 IS_TRUE_SYMOP (IC_RESULT (ic)));
13905 aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
13908 /* Sanity checking... */
13909 if (AOP_USESDPTR(IC_RESULT(ic)))
13911 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
13912 "genReceive got unexpected DPTR.");
13914 assignResultValue (IC_RESULT (ic), NULL);
13917 else if (ic->argreg > 12)
13918 { /* bit parameters */
13919 if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
13921 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
13922 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
13923 outBitC(IC_RESULT (ic));
13928 /* second receive onwards */
13929 /* this gets a little tricky since unused receives will be
13930 eliminated, we have saved the reg in the type field . and
13931 we use that to figure out which register to use */
13932 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
13933 rb1off = ic->argreg;
13936 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
13939 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13942 /*-----------------------------------------------------------------*/
13943 /* genDummyRead - generate code for dummy read of volatiles */
13944 /*-----------------------------------------------------------------*/
13946 genDummyRead (iCode * ic)
13951 D (emitcode(";", "genDummyRead"));
13953 op = IC_RIGHT (ic);
13954 if (op && IS_SYMOP (op))
13956 aopOp (op, ic, FALSE, FALSE);
13958 /* if the result is a bit */
13959 if (AOP_TYPE (op) == AOP_CRY)
13960 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13963 /* bit variables done */
13965 size = AOP_SIZE (op);
13969 MOVA (aopGet (op, offset, FALSE, FALSE, FALSE));
13974 freeAsmop (op, NULL, ic, TRUE);
13978 if (op && IS_SYMOP (op))
13980 aopOp (op, ic, FALSE, FALSE);
13982 /* if the result is a bit */
13983 if (AOP_TYPE (op) == AOP_CRY)
13984 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13987 /* bit variables done */
13989 size = AOP_SIZE (op);
13993 MOVA (aopGet (op, offset, FALSE, FALSE, FALSE));
13998 freeAsmop (op, NULL, ic, TRUE);
14002 /*-----------------------------------------------------------------*/
14003 /* genCritical - generate code for start of a critical sequence */
14004 /*-----------------------------------------------------------------*/
14006 genCritical (iCode *ic)
14008 symbol *tlbl = newiTempLabel (NULL);
14010 D (emitcode(";", "genCritical"));
14012 if (IC_RESULT (ic))
14014 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
14015 aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
14016 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
14017 aopPut (IC_RESULT (ic), zero, 0);
14019 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
14023 emitcode ("setb", "c");
14024 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
14025 emitcode ("clr", "c");
14027 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
14031 /*-----------------------------------------------------------------*/
14032 /* genEndCritical - generate code for end of a critical sequence */
14033 /*-----------------------------------------------------------------*/
14035 genEndCritical (iCode *ic)
14037 D(emitcode("; genEndCritical",""));
14041 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
14042 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
14044 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
14045 emitcode ("mov", "ea,c");
14049 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE, FALSE));
14050 emitcode ("rrc", "a");
14051 emitcode ("mov", "ea,c");
14053 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
14057 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
14058 emitcode ("mov", "ea,c");
14064 /*-----------------------------------------------------------------*/
14065 /* genBuiltIn - calls the appropriate function to generating code */
14066 /* for a built in function */
14067 /*-----------------------------------------------------------------*/
14068 static void genBuiltIn (iCode *ic)
14070 operand *bi_parms[MAX_BUILTIN_ARGS];
14075 /* get all the arguments for a built in function */
14076 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
14078 /* which function is it */
14079 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
14080 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
14081 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
14082 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
14083 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
14084 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
14085 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
14086 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
14087 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
14088 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
14089 genMemsetX(bi_iCode,nbi_parms,bi_parms);
14090 } else if (strcmp(bif->name,"__builtin_inp")==0) {
14091 genInp(bi_iCode,nbi_parms,bi_parms);
14092 } else if (strcmp(bif->name,"__builtin_outp")==0) {
14093 genOutp(bi_iCode,nbi_parms,bi_parms);
14094 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
14095 genSwapW(bi_iCode,nbi_parms,bi_parms);
14096 /* JavaNative builtIns */
14097 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
14098 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
14099 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
14100 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
14101 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
14102 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
14103 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
14104 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
14105 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
14106 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
14107 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
14108 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
14109 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
14110 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
14111 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
14112 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
14113 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
14114 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
14115 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
14116 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
14117 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
14118 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
14119 } else if (strcmp(bif->name,"MM_Malloc")==0) {
14120 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
14121 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
14122 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
14123 } else if (strcmp(bif->name,"MM_Free")==0) {
14124 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
14125 } else if (strcmp(bif->name,"MM_Deref")==0) {
14126 genMMDeref(bi_iCode,nbi_parms,bi_parms);
14127 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
14128 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
14129 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
14130 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
14131 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
14132 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
14133 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
14134 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
14135 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
14136 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
14137 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
14138 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
14139 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
14140 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
14141 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
14142 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
14143 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
14144 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
14145 } else if (strcmp(bif->name,"System_SaveThread")==0) {
14146 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
14147 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
14148 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
14149 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
14150 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
14151 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
14152 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
14153 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
14154 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
14155 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
14156 genSystem(bi_iCode,nbi_parms,"ProcessYield");
14157 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
14158 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
14159 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
14160 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
14161 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
14162 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
14163 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
14164 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
14165 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
14166 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
14168 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
14174 /*-----------------------------------------------------------------*/
14175 /* gen390Code - generate code for Dallas 390 based controllers */
14176 /*-----------------------------------------------------------------*/
14178 gen390Code (iCode * lic)
14183 _G.currentFunc = NULL;
14184 lineHead = lineCurr = NULL;
14185 dptrn[1][0] = "dpl1";
14186 dptrn[1][1] = "dph1";
14187 dptrn[1][2] = "dpx1";
14189 if (options.model == MODEL_FLAT24) {
14190 fReturnSizeDS390 = 5;
14191 fReturn = fReturn24;
14193 fReturnSizeDS390 = 4;
14194 fReturn = fReturn16;
14195 options.stack10bit=0;
14198 /* print the allocation information */
14199 if (allocInfo && currFunc)
14200 printAllocInfo (currFunc, codeOutBuf);
14202 /* if debug information required */
14203 if (options.debug && currFunc)
14205 debugFile->writeFunction (currFunc, lic);
14207 /* stack pointer name */
14208 if (options.useXstack)
14214 for (ic = lic; ic; ic = ic->next)
14216 _G.current_iCode = ic;
14218 if (ic->lineno && cln != ic->lineno)
14222 debugFile->writeCLine (ic);
14224 if (!options.noCcodeInAsm) {
14225 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
14226 printCLine(ic->filename, ic->lineno));
14230 if (options.iCodeInAsm) {
14231 char *iLine = printILine(ic);
14232 emitcode("", ";ic:%d: %s", ic->key, iLine);
14235 /* if the result is marked as
14236 spilt and rematerializable or code for
14237 this has already been generated then
14239 if (resultRemat (ic) || ic->generated)
14242 /* depending on the operation */
14262 /* IPOP happens only when trying to restore a
14263 spilt live range, if there is an ifx statement
14264 following this pop then the if statement might
14265 be using some of the registers being popped which
14266 would destory the contents of the register so
14267 we need to check for this condition and handle it */
14269 ic->next->op == IFX &&
14270 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
14271 genIfx (ic->next, ic);
14289 genEndFunction (ic);
14309 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
14326 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
14330 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
14337 /* note these two are xlated by algebraic equivalence
14338 during parsing SDCC.y */
14339 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
14340 "got '>=' or '<=' shouldn't have come here");
14344 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
14356 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
14360 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
14364 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
14388 genRightShift (ic);
14391 case GET_VALUE_AT_ADDRESS:
14393 hasInc (IC_LEFT (ic), ic,
14394 getSize (operandType (IC_RESULT (ic)))));
14398 if (POINTER_SET (ic))
14400 hasInc (IC_RESULT (ic), ic,
14401 getSize (operandType (IC_RIGHT (ic)))));
14427 if (ic->builtinSEND)
14430 addSet (&_G.sendSet, ic);
14433 case DUMMY_READ_VOLATILE:
14442 genEndCritical (ic);
14449 #if 0 // obsolete, and buggy for != xdata
14456 /* This should never happen, right? */
14457 fprintf(stderr, "*** Probable error: unsupported op 0x%x (%c) in %s @ %d\n",
14458 ic->op, ic->op, __FILE__, __LINE__);
14464 /* now we are ready to call the
14465 peep hole optimizer */
14466 if (!options.nopeep)
14467 peepHole (&lineHead);
14469 /* now do the actual printing */
14470 printLine (lineHead, codeOutBuf);