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 -------------------------------------------------------------------------*/
29 #define D(x) do if (options.verboseAsm) {x;} while(0)
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)));
247 lineCurr->isInline = _G.inLine;
248 lineCurr->isDebug = _G.debugLine;
249 lineCurr->ic = _G.current_iCode;
250 lineCurr->aln = ds390newAsmLineNode(_currentDPS);
251 lineCurr->isComment = (*lbp == ';');
260 emitLabel (symbol *tlbl)
262 emitcode ("", "!tlabeldef", tlbl->key + 100);
263 lineCurr->isLabel = 1;
266 /*-----------------------------------------------------------------*/
267 /* ds390_emitDebuggerSymbol - associate the current code location */
268 /* with a debugger symbol */
269 /*-----------------------------------------------------------------*/
271 ds390_emitDebuggerSymbol (char * debugSym)
274 emitcode ("", "%s ==.", debugSym);
278 /*-----------------------------------------------------------------*/
279 /* mova - moves specified value into accumulator */
280 /*-----------------------------------------------------------------*/
284 /* do some early peephole optimization */
285 if (!strncmp(x, "a", 2) || !strncmp(x, "acc", 4))
288 emitcode("mov", "a,%s", x);
291 /*-----------------------------------------------------------------*/
292 /* movb - moves specified value into register b */
293 /*-----------------------------------------------------------------*/
297 /* do some early peephole optimization */
298 if (!strncmp(x, "b", 2))
301 emitcode("mov","b,%s", x);
304 /*-----------------------------------------------------------------*/
305 /* movc - moves specified value into the carry */
306 /*-----------------------------------------------------------------*/
314 else if (strcmp (s, "c"))
315 {/* it's not in carry already */
317 /* set C, if a >= 1 */
318 emitcode ("add", "a,#0xff");
322 /*-----------------------------------------------------------------*/
323 /* pushB - saves register B if necessary */
324 /*-----------------------------------------------------------------*/
328 bool pushedB = FALSE;
332 emitcode ("push", "b");
333 // printf("B was in use !\n");
343 /*-----------------------------------------------------------------*/
344 /* popB - restores value of register B if necessary */
345 /*-----------------------------------------------------------------*/
351 emitcode ("pop", "b");
359 /*-----------------------------------------------------------------*/
360 /* pushReg - saves register */
361 /*-----------------------------------------------------------------*/
363 pushReg (int index, bool bits_pushed)
365 regs * reg = REG_WITH_INDEX (index);
366 if (reg->type == REG_BIT)
369 emitcode ("push", "%s", reg->base);
373 emitcode ("push", "%s", reg->dname);
377 /*-----------------------------------------------------------------*/
378 /* popReg - restores register */
379 /*-----------------------------------------------------------------*/
381 popReg (int index, bool bits_popped)
383 regs * reg = REG_WITH_INDEX (index);
384 if (reg->type == REG_BIT)
387 emitcode ("pop", "%s", reg->base);
391 emitcode ("pop", "%s", reg->dname);
395 /*-----------------------------------------------------------------*/
396 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
397 /*-----------------------------------------------------------------*/
399 getFreePtr (iCode * ic, asmop ** aopp, bool result)
404 /* the logic: if r0 & r1 used in the instruction
405 then we are in trouble otherwise */
407 /* first check if r0 & r1 are used by this
408 instruction, in which case we are in trouble */
409 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
410 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
415 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
416 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
418 /* if no usage of r0 then return it */
421 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
422 (*aopp)->type = AOP_R0;
424 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
427 /* if no usage of r1 then return it */
430 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
431 (*aopp)->type = AOP_R1;
433 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R1_IDX);
436 /* now we know they both have usage */
437 /* if r0 not used in this instruction */
440 /* push it if not already pushed */
443 emitcode ("push", "%s",
444 REG_WITH_INDEX (R0_IDX)->dname);
448 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
449 (*aopp)->type = AOP_R0;
451 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
454 /* if r1 not used then */
458 /* push it if not already pushed */
461 emitcode ("push", "%s",
462 REG_WITH_INDEX (R1_IDX)->dname);
466 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
467 (*aopp)->type = AOP_R1;
468 return REG_WITH_INDEX (R1_IDX);
472 /* I said end of world, but not quite end of world yet */
473 /* if this is a result then we can push it on the stack */
476 (*aopp)->type = AOP_STK;
480 /* now this is REALLY the end of the world */
481 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
482 "getFreePtr should never reach here");
485 return NULL; // notreached, but makes compiler happy.
489 /*-----------------------------------------------------------------*/
490 /* genSetDPTR: generate code to select which DPTR is in use (zero */
491 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */
492 /* alternate DPTR (DPL1/DPH1/DPX1). */
493 /*-----------------------------------------------------------------*/
498 /* If we are doing lazy evaluation, simply note the desired
499 * change, but don't emit any code yet.
509 emitcode ("mov", "dps,#0");
514 emitcode ("mov", "dps,#1");
518 /*------------------------------------------------------------------*/
519 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
521 /* Any code that operates on DPTR (NB: not on the individual */
522 /* components, like DPH) *must* call _flushLazyDPS() before using */
523 /* DPTR within a lazy DPS evaluation block. */
525 /* Note that aopPut and aopGet already contain the proper calls to */
526 /* _flushLazyDPS, so it is safe to use these calls within a lazy */
527 /* DPS evaluation block. */
529 /* Also, _flushLazyDPS must be called before any flow control */
530 /* operations that could potentially branch out of the block. */
532 /* Lazy DPS evaluation is simply an optimization (though an */
533 /* important one), so if in doubt, leave it out. */
534 /*------------------------------------------------------------------*/
536 _startLazyDPSEvaluation (void)
540 #ifdef BETTER_LITERAL_SHIFT
547 /*------------------------------------------------------------------*/
548 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
549 /* desired one. Call before using DPTR within a lazy DPS evaluation */
551 /*------------------------------------------------------------------*/
561 if (_desiredDPS != _currentDPS)
565 emitcode ("inc", "dps");
569 emitcode ("dec", "dps");
571 _currentDPS = _desiredDPS;
575 /*-----------------------------------------------------------------*/
576 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
578 /* Forces us back to the safe state (standard DPTR selected). */
579 /*-----------------------------------------------------------------*/
581 _endLazyDPSEvaluation (void)
583 #ifdef BETTER_LITERAL_SHIFT
601 /*-----------------------------------------------------------------*/
602 /* newAsmop - creates a new asmOp */
603 /*-----------------------------------------------------------------*/
605 newAsmop (short type)
609 aop = Safe_calloc (1, sizeof (asmop));
615 /*-----------------------------------------------------------------*/
616 /* pointerCode - returns the code for a pointer type */
617 /*-----------------------------------------------------------------*/
619 pointerCode (sym_link * etype)
622 return PTR_TYPE (SPEC_OCLS (etype));
626 /*-----------------------------------------------------------------*/
627 /* leftRightUseAcc - returns size of accumulator use by operands */
628 /*-----------------------------------------------------------------*/
630 leftRightUseAcc(iCode *ic)
639 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
640 "null iCode pointer");
647 if (IS_OP_ACCUSE (op))
650 size = getSize (OP_SYMBOL (op)->type);
655 else if (ic->op == JUMPTABLE)
658 if (IS_OP_ACCUSE (op))
661 size = getSize (OP_SYMBOL (op)->type);
669 if (IS_OP_ACCUSE (op))
672 size = getSize (OP_SYMBOL (op)->type);
677 if (IS_OP_ACCUSE (op))
680 size = getSize (OP_SYMBOL (op)->type);
692 /*-----------------------------------------------------------------*/
693 /* aopForSym - for a true symbol */
694 /*-----------------------------------------------------------------*/
696 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
700 bool accuse = leftRightUseAcc (ic) || _G.accInUse;
701 char *dpl = useDP2 ? "dpl1" : "dpl";
702 char *dph = useDP2 ? "dph1" : "dph";
703 char *dpx = useDP2 ? "dpx1" : "dpx";
705 wassertl (ic != NULL, "Got a null iCode");
706 wassertl (sym != NULL, "Got a null symbol");
708 space = SPEC_OCLS (sym->etype);
710 /* if already has one */
713 if ((sym->aop->type == AOP_DPTR && useDP2)
714 || (sym->aop->type == AOP_DPTR2 && !useDP2))
718 sym->aop->allocated++;
723 /* assign depending on the storage class */
724 /* if it is on the stack or indirectly addressable */
725 /* space we need to assign either r0 or r1 to it */
726 if ((sym->onStack && !options.stack10bit) || sym->iaccess)
728 sym->aop = aop = newAsmop (0);
729 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
730 aop->size = getSize (sym->type);
732 /* now assign the address of the variable to
733 the pointer register */
734 if (aop->type != AOP_STK)
738 signed char offset = ((sym->stack < 0) ?
739 ((signed char) (sym->stack - _G.nRegsSaved)) :
740 ((signed char) sym->stack)) & 0xff;
742 if ((abs(offset) <= 3) ||
743 (accuse && (abs(offset) <= 7)))
745 emitcode ("mov", "%s,_bp",
746 aop->aopu.aop_ptr->name);
749 emitcode ("dec", aop->aopu.aop_ptr->name);
754 emitcode ("inc", aop->aopu.aop_ptr->name);
761 emitcode ("push", "acc");
762 emitcode ("mov", "a,_bp");
763 emitcode ("add", "a,#!constbyte", offset);
764 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
766 emitcode ("pop", "acc");
771 emitcode ("mov", "%s,#%s",
772 aop->aopu.aop_ptr->name,
775 aop->paged = space->paged;
778 aop->aopu.aop_stk = sym->stack;
782 if (sym->onStack && options.stack10bit)
784 short stack_val = -((sym->stack < 0) ?
785 ((short) (sym->stack - _G.nRegsSaved)) :
786 ((short) sym->stack)) ;
788 emitcode ("push",dpl);
789 emitcode ("push",dph);
790 emitcode ("push",dpx);
792 /* It's on the 10 bit stack, which is located in
795 if (stack_val < 0 && stack_val > -5)
796 { /* between -5 & -1 */
797 if (options.model == MODEL_FLAT24)
799 emitcode ("mov", "%s,#!constbyte", dpx,
800 (options.stack_loc >> 16) & 0xff);
802 emitcode ("mov", "%s,_bpx+1", dph);
803 emitcode ("mov", "%s,_bpx", dpl);
805 emitcode ("mov","dps,#1");
807 stack_val = -stack_val;
808 while (stack_val--) {
809 emitcode ("inc","dptr");
812 emitcode("mov","dps,#0");
818 emitcode ("push", "acc");
820 emitcode ("mov", "a,_bpx");
821 emitcode ("clr","c");
822 emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
823 emitcode ("mov","%s,a", dpl);
824 emitcode ("mov","a,_bpx+1");
825 emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
826 emitcode ("mov", "%s,a", dph);
827 if (options.model == MODEL_FLAT24)
829 emitcode ("mov", "%s,#!constbyte", dpx,
830 (options.stack_loc >> 16) & 0xff);
834 emitcode ("pop", "acc");
836 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
837 aop->size = getSize (sym->type);
841 /* if in bit space */
842 if (IN_BITSPACE (space))
844 sym->aop = aop = newAsmop (AOP_CRY);
845 aop->aopu.aop_dir = sym->rname;
846 aop->size = getSize (sym->type);
849 /* if it is in direct space */
850 if (IN_DIRSPACE (space))
852 sym->aop = aop = newAsmop (AOP_DIR);
853 aop->aopu.aop_dir = sym->rname;
854 aop->size = getSize (sym->type);
858 /* special case for a function */
859 if (IS_FUNC (sym->type) && !(sym->isitmp))
861 sym->aop = aop = newAsmop (AOP_IMMD);
862 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
863 aop->size = FPTRSIZE;
867 /* only remaining is far space */
868 /* in which case DPTR gets the address */
869 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
874 emitcode ("mov", "dptr,#%s", sym->rname);
879 emitcode ("mov", "dptr,#%s", sym->rname);
881 aop->size = getSize (sym->type);
883 /* if it is in code space */
884 if (IN_CODESPACE (space))
890 /*-----------------------------------------------------------------*/
891 /* aopForRemat - rematerializes an object */
892 /*-----------------------------------------------------------------*/
894 aopForRemat (symbol * sym)
896 iCode *ic = sym->rematiCode;
897 asmop *aop = newAsmop (AOP_IMMD);
904 val += (int) operandLitValue (IC_RIGHT (ic));
905 else if (ic->op == '-')
906 val -= (int) operandLitValue (IC_RIGHT (ic));
907 else if (IS_CAST_ICODE(ic))
909 sym_link *from_type = operandType(IC_RIGHT(ic));
910 aop->aopu.aop_immd.from_cast_remat = 1;
911 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
912 ptr_type = pointerTypeToGPByte (DCL_TYPE(from_type), NULL, NULL);
917 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
922 SNPRINTF (buffer, sizeof(buffer),
924 OP_SYMBOL (IC_LEFT (ic))->rname,
925 val >= 0 ? '+' : '-',
926 abs (val) & 0xffffff);
930 if (IS_ASSIGN_ICODE(ic) && isOperandLiteral(IC_RIGHT(ic)))
932 SNPRINTF(buffer, sizeof(buffer),
933 "0x%x",(int) operandLitValue (IC_RIGHT (ic)));
937 strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
941 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
942 /* set immd2 field if required */
943 if (aop->aopu.aop_immd.from_cast_remat)
945 tsprintf(buffer, sizeof(buffer), "#!constbyte",ptr_type);
946 aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
952 /*-----------------------------------------------------------------*/
953 /* aopHasRegs - returns true if aop has regs between from-to */
954 /*-----------------------------------------------------------------*/
955 static int aopHasRegs(asmop *aop, int from, int to)
959 if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
961 for (; size < aop->size ; size++) {
963 for (reg = from ; reg <= to ; reg++)
964 if (aop->aopu.aop_reg[size] == REG_WITH_INDEX(reg)) return 1;
969 /*-----------------------------------------------------------------*/
970 /* regsInCommon - two operands have some registers in common */
971 /*-----------------------------------------------------------------*/
973 regsInCommon (operand * op1, operand * op2)
978 /* if they have registers in common */
979 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
982 sym1 = OP_SYMBOL (op1);
983 sym2 = OP_SYMBOL (op2);
985 if (sym1->nRegs == 0 || sym2->nRegs == 0)
988 for (i = 0; i < sym1->nRegs; i++)
994 for (j = 0; j < sym2->nRegs; j++)
999 if (sym2->regs[j] == sym1->regs[i])
1007 /*-----------------------------------------------------------------*/
1008 /* operandsEqu - equivalent */
1009 /*-----------------------------------------------------------------*/
1011 operandsEqu (operand * op1, operand * op2)
1013 symbol *sym1, *sym2;
1015 /* if they're not symbols */
1016 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
1019 sym1 = OP_SYMBOL (op1);
1020 sym2 = OP_SYMBOL (op2);
1022 /* if both are itemps & one is spilt
1023 and the other is not then false */
1024 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
1025 sym1->isspilt != sym2->isspilt)
1028 /* if they are the same */
1032 /* if they have the same rname */
1033 if (sym1->rname[0] && sym2->rname[0] &&
1034 strcmp (sym1->rname, sym2->rname) == 0 &&
1035 !(IS_PARM (op2) && IS_ITEMP (op1)))
1038 /* if left is a tmp & right is not */
1039 if (IS_ITEMP (op1) &&
1042 (sym1->usl.spillLoc == sym2))
1045 if (IS_ITEMP (op2) &&
1049 (sym2->usl.spillLoc == sym1))
1052 /* are they spilt to the same location */
1053 if (IS_ITEMP (op2) &&
1057 (sym1->usl.spillLoc == sym2->usl.spillLoc))
1063 /*-----------------------------------------------------------------*/
1064 /* sameRegs - two asmops have the same registers */
1065 /*-----------------------------------------------------------------*/
1067 sameRegs (asmop * aop1, asmop * aop2)
1073 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
1080 if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
1083 if (aop1->type != aop2->type)
1086 if (aop1->size != aop2->size)
1089 for (i = 0; i < aop1->size; i++)
1090 if (aop1->aopu.aop_reg[i] != aop2->aopu.aop_reg[i])
1096 /*-----------------------------------------------------------------*/
1097 /* aopOp - allocates an asmop for an operand : */
1098 /*-----------------------------------------------------------------*/
1100 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
1109 /* if this a literal */
1110 if (IS_OP_LITERAL (op))
1112 op->aop = aop = newAsmop (AOP_LIT);
1113 aop->aopu.aop_lit = op->operand.valOperand;
1114 aop->size = getSize (operandType (op));
1118 /* if already has a asmop then continue */
1121 if ((op->aop->type == AOP_DPTR && useDP2)
1122 || (op->aop->type == AOP_DPTR2 && !useDP2))
1126 op->aop->allocated++;
1131 /* if the underlying symbol has a aop */
1132 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
1134 op->aop = OP_SYMBOL (op)->aop;
1135 if ((op->aop->type == AOP_DPTR && useDP2)
1136 || (op->aop->type == AOP_DPTR2 && !useDP2))
1140 op->aop->allocated++;
1145 /* if this is a true symbol */
1146 if (IS_TRUE_SYMOP (op))
1148 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
1152 /* this is a temporary : this has
1158 e) can be a return use only */
1160 sym = OP_SYMBOL (op);
1162 /* if the type is a conditional */
1163 if (sym->regType == REG_CND)
1165 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
1170 /* if it is spilt then two situations
1172 b) has a spill location */
1173 if (sym->isspilt || sym->nRegs == 0)
1176 /* rematerialize it NOW */
1179 sym->aop = op->aop = aop = aopForRemat (sym);
1180 aop->size = getSize (sym->type);
1187 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
1188 aop->size = getSize (sym->type);
1189 for (i = 0; i < 2; i++)
1190 aop->aopu.aop_str[i] = accUse[i];
1200 /* a AOP_STR uses DPTR, but DPTR is already in use;
1203 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
1206 aop = op->aop = sym->aop = newAsmop (AOP_STR);
1207 aop->size = getSize (sym->type);
1208 for (i = 0; i < fReturnSizeDS390; i++)
1209 aop->aopu.aop_str[i] = fReturn[i];
1213 if (sym->dptr) { /* has been allocated to a DPTRn */
1214 aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
1215 aop->size = getSize (sym->type);
1216 aop->aopu.dptr = sym->dptr;
1220 if (sym->usl.spillLoc)
1222 asmop *oldAsmOp = NULL;
1224 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1226 /* force a new aop if sizes differ */
1227 oldAsmOp = sym->usl.spillLoc->aop;
1228 sym->usl.spillLoc->aop = NULL;
1230 sym->aop = op->aop = aop =
1231 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
1232 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1234 /* Don't reuse the new aop, go with the last one */
1235 sym->usl.spillLoc->aop = oldAsmOp;
1237 aop->size = getSize (sym->type);
1241 /* else must be a dummy iTemp */
1242 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1243 aop->size = getSize (sym->type);
1247 /* if the type is a bit register */
1248 if (sym->regType == REG_BIT)
1250 sym->aop = op->aop = aop = newAsmop (AOP_CRY);
1251 aop->size = sym->nRegs;//1???
1252 aop->aopu.aop_reg[0] = sym->regs[0];
1253 aop->aopu.aop_dir = sym->regs[0]->name;
1257 /* must be in a register */
1258 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1259 aop->size = sym->nRegs;
1260 for (i = 0; i < sym->nRegs; i++)
1261 aop->aopu.aop_reg[i] = sym->regs[i];
1264 /*-----------------------------------------------------------------*/
1265 /* freeAsmop - free up the asmop given to an operand */
1266 /*-----------------------------------------------------------------*/
1268 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1285 /* depending on the asmop type only three cases need work
1286 AOP_R0, AOP_R1 & AOP_STK */
1294 emitcode ("pop", "ar0");
1298 bitVectUnSetBit (ic->rUsed, R0_IDX);
1306 emitcode ("pop", "ar1");
1310 bitVectUnSetBit (ic->rUsed, R1_IDX);
1316 int stk = aop->aopu.aop_stk + aop->size;
1317 bitVectUnSetBit (ic->rUsed, R0_IDX);
1318 bitVectUnSetBit (ic->rUsed, R1_IDX);
1320 getFreePtr (ic, &aop, FALSE);
1322 if (options.stack10bit)
1324 /* I'm not sure what to do here yet... */
1327 "*** Warning: probably generating bad code for "
1328 "10 bit stack mode.\n");
1333 emitcode ("mov", "a,_bp");
1334 emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
1335 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1339 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1344 emitcode ("pop", "acc");
1345 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1348 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1351 freeAsmop (op, NULL, ic, TRUE);
1354 emitcode ("pop", "ar1");
1359 emitcode ("pop", "ar0");
1364 if (_G.dptr1InUse) {
1365 emitcode ("pop","dpx1");
1366 emitcode ("pop","dph1");
1367 emitcode ("pop","dpl1");
1372 emitcode ("pop","dpx");
1373 emitcode ("pop","dph");
1374 emitcode ("pop","dpl");
1380 /* all other cases just dealloc */
1386 OP_SYMBOL (op)->aop = NULL;
1387 /* if the symbol has a spill */
1389 SPIL_LOC (op)->aop = NULL;
1394 #define DEFAULT_ACC_WARNING 0
1395 static int saveAccWarn = DEFAULT_ACC_WARNING;
1398 /*-----------------------------------------------------------------*/
1399 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
1400 /* clobber the accumulator */
1401 /*-----------------------------------------------------------------*/
1403 aopGetUsesAcc (operand * oper, int offset)
1405 asmop * aop = AOP (oper);
1407 if (offset > (aop->size - 1))
1427 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1438 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1444 /* Error case --- will have been caught already */
1450 /*-------------------------------------------------------------------*/
1451 /* aopGet - for fetching value of the aop */
1453 /* Set saveAcc to NULL if you are sure it is OK to clobber the value */
1454 /* in the accumulator. Set it to the name of a free register */
1455 /* if acc must be preserved; the register will be used to preserve */
1456 /* acc temporarily and to return the result byte. */
1457 /*-------------------------------------------------------------------*/
1459 aopGet (operand * oper,
1465 asmop * aop = AOP (oper);
1467 /* offset is greater than
1469 if (offset > (aop->size - 1) &&
1470 aop->type != AOP_LIT)
1473 /* depending on type */
1481 /* if we need to increment it */
1482 while (offset > aop->coff)
1484 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1488 while (offset < aop->coff)
1490 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1497 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1498 return (dname ? "acc" : "a");
1500 SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1501 return Safe_strdup(buffer);
1504 assert(offset <= 3);
1505 return dptrn[aop->aopu.dptr][offset];
1510 if (aop->type == AOP_DPTR2)
1518 // if (aop->type != AOP_DPTR2)
1520 // if (saveAccWarn) { fprintf(stderr, "saveAcc for DPTR...\n"); }
1521 // emitcode(";", "spanky: saveAcc for DPTR");
1524 emitcode ("xch", "a, %s", saveAcc);
1529 while (offset > aop->coff)
1531 emitcode ("inc", "dptr");
1535 while (offset < aop->coff)
1537 emitcode ("lcall", "__decdptr");
1544 emitcode ("clr", "a");
1545 emitcode ("movc", "a,@a+dptr");
1549 emitcode ("movx", "a,@dptr");
1552 if (aop->type == AOP_DPTR2)
1560 emitcode ("xch", "a, %s", saveAcc);
1561 // if (strcmp(saveAcc, "_ap"))
1563 // emitcode(";", "spiffy: non _ap return from aopGet.");
1568 return (dname ? "acc" : "a");
1571 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1573 SNPRINTF(buffer, sizeof(buffer),
1574 "%s",aop->aopu.aop_immd.aop_immd2);
1578 SNPRINTF(buffer, sizeof(buffer),
1579 "#%s", aop->aopu.aop_immd.aop_immd1);
1585 tsprintf(buffer, sizeof(buffer),
1586 "#!his",aop->aopu.aop_immd.aop_immd1);
1589 tsprintf(buffer, sizeof(buffer),
1590 "#!hihis",aop->aopu.aop_immd.aop_immd1);
1593 tsprintf(buffer, sizeof(buffer),
1594 "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1596 default: /* should not need this (just in case) */
1597 SNPRINTF (buffer, sizeof(buffer),
1599 aop->aopu.aop_immd.aop_immd1,
1605 SNPRINTF (buffer, sizeof(buffer),
1607 aop->aopu.aop_immd.aop_immd1);
1609 return Safe_strdup(buffer);
1612 if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
1614 SNPRINTF (buffer, sizeof(buffer),
1616 aop->aopu.aop_dir, offset * 8);
1620 SNPRINTF (buffer, sizeof(buffer),
1627 SNPRINTF (buffer, sizeof(buffer),
1632 return Safe_strdup(buffer);
1636 return aop->aopu.aop_reg[offset]->dname;
1638 return aop->aopu.aop_reg[offset]->name;
1641 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1642 emitcode ("clr", "a");
1643 emitcode ("rlc", "a");
1644 return (dname ? "acc" : "a");
1647 if (!offset && dname)
1649 return aop->aopu.aop_str[offset];
1652 return aopLiteral (aop->aopu.aop_lit, offset);
1656 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1660 return aop->aopu.aop_str[offset];
1664 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1665 "aopget got unsupported aop->type");
1668 return NULL; // not reached, but makes compiler happy.
1671 /*-----------------------------------------------------------------*/
1672 /* aopPutUsesAcc - indicates ahead of time whether aopPut() will */
1673 /* clobber the accumulator */
1674 /*-----------------------------------------------------------------*/
1676 aopPutUsesAcc (operand * oper, const char *s, int offset)
1678 asmop * aop = AOP (oper);
1680 if (offset > (aop->size - 1))
1690 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1699 return ((aop->paged) || (*s == '@'));
1703 return (!aop->aopu.aop_dir || strcmp(s, aop->aopu.aop_dir));
1711 /* Error case --- will have been caught already */
1717 /*-----------------------------------------------------------------*/
1718 /* aopPut - puts a string for a aop and indicates if acc is in use */
1719 /*-----------------------------------------------------------------*/
1721 aopPut (operand * result, const char *s, int offset)
1723 bool bvolatile = isOperandVolatile (result, FALSE);
1724 bool accuse = FALSE;
1725 asmop * aop = AOP (result);
1726 const char *d = NULL;
1728 if (aop->size && offset > (aop->size - 1))
1730 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1731 "aopPut got offset > aop->size");
1735 /* will assign value to value */
1736 /* depending on where it is ofcourse */
1740 MOVA (s); /* read s in case it was volatile */
1745 if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1747 SNPRINTF (buffer, sizeof(buffer),
1749 aop->aopu.aop_dir, offset * 8);
1753 SNPRINTF (buffer, sizeof(buffer),
1755 aop->aopu.aop_dir, offset);
1759 SNPRINTF (buffer, sizeof(buffer),
1764 if (strcmp (buffer, s) || bvolatile)
1766 emitcode ("mov", "%s,%s", buffer, s);
1768 if (!strcmp (buffer, "acc"))
1775 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1776 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1779 strcmp (s, "r0") == 0 ||
1780 strcmp (s, "r1") == 0 ||
1781 strcmp (s, "r2") == 0 ||
1782 strcmp (s, "r3") == 0 ||
1783 strcmp (s, "r4") == 0 ||
1784 strcmp (s, "r5") == 0 ||
1785 strcmp (s, "r6") == 0 ||
1786 strcmp (s, "r7") == 0)
1788 emitcode ("mov", "%s,%s",
1789 aop->aopu.aop_reg[offset]->dname, s);
1793 emitcode ("mov", "%s,%s",
1794 aop->aopu.aop_reg[offset]->name, s);
1800 emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1806 if (aop->type == AOP_DPTR2)
1814 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1815 "aopPut writing to code space");
1819 while (offset > aop->coff)
1822 emitcode ("inc", "dptr");
1825 while (offset < aop->coff)
1828 emitcode ("lcall", "__decdptr");
1833 /* if not in accumulator */
1836 emitcode ("movx", "@dptr,a");
1838 if (aop->type == AOP_DPTR2)
1846 while (offset > aop->coff)
1849 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1851 while (offset < aop->coff)
1854 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1861 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1866 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1868 else if (strcmp (s, "r0") == 0 ||
1869 strcmp (s, "r1") == 0 ||
1870 strcmp (s, "r2") == 0 ||
1871 strcmp (s, "r3") == 0 ||
1872 strcmp (s, "r4") == 0 ||
1873 strcmp (s, "r5") == 0 ||
1874 strcmp (s, "r6") == 0 ||
1875 strcmp (s, "r7") == 0)
1878 SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1879 emitcode ("mov", "@%s,%s",
1880 aop->aopu.aop_ptr->name, buffer);
1884 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1889 if (strcmp (s, "a") == 0)
1891 emitcode ("push", "acc");
1896 emitcode ("push", "acc");
1898 else if (strcmp (s, "r0") == 0 ||
1899 strcmp (s, "r1") == 0 ||
1900 strcmp (s, "r2") == 0 ||
1901 strcmp (s, "r3") == 0 ||
1902 strcmp (s, "r4") == 0 ||
1903 strcmp (s, "r5") == 0 ||
1904 strcmp (s, "r6") == 0 ||
1905 strcmp (s, "r7") == 0)
1908 SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1909 emitcode ("push", buffer);
1913 emitcode ("push", s);
1919 // destination is carry for return-use-only
1920 d = (IS_OP_RUONLY (result)) ? "c" : aop->aopu.aop_dir;
1922 // source is no literal and not in carry
1923 if ((s != zero) && (s != one) && strcmp (s, "c"))
1926 /* set C, if a >= 1 */
1927 emitcode ("add", "a,#!constbyte",0xff);
1930 // now source is zero, one or carry
1932 /* if result no bit variable */
1935 if (!strcmp (s, "c"))
1937 /* inefficient: move carry into A and use jz/jnz */
1938 emitcode ("clr", "a");
1939 emitcode ("rlc", "a");
1949 emitcode ("clr", "%s", d);
1951 emitcode ("setb", "%s", d);
1952 else if (strcmp (s, d))
1953 emitcode ("mov", "%s,c", d);
1958 if (strcmp (aop->aopu.aop_str[offset], s) || bvolatile)
1959 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1965 if (!offset && (strcmp (s, "acc") == 0) && !bvolatile)
1968 if (strcmp (aop->aopu.aop_str[offset], s) && !bvolatile)
1969 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1973 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1974 "aopPut got unsupported aop->type");
1982 /*--------------------------------------------------------------------*/
1983 /* reAdjustPreg - points a register back to where it should (coff==0) */
1984 /*--------------------------------------------------------------------*/
1986 reAdjustPreg (asmop * aop)
1988 if ((aop->coff==0) || (aop->size <= 1))
1996 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
2000 if (aop->type == AOP_DPTR2)
2007 emitcode ("lcall", "__decdptr");
2010 if (aop->type == AOP_DPTR2)
2019 /*-----------------------------------------------------------------*/
2020 /* opIsGptr: returns non-zero if the passed operand is */
2021 /* a generic pointer type. */
2022 /*-----------------------------------------------------------------*/
2024 opIsGptr (operand * op)
2026 if (op && IS_GENPTR (operandType (op)) && (AOP_SIZE (op) == GPTRSIZE))
2033 /*-----------------------------------------------------------------*/
2034 /* getDataSize - get the operand data size */
2035 /*-----------------------------------------------------------------*/
2037 getDataSize (operand * op)
2039 int size = AOP_SIZE (op);
2041 if (size == GPTRSIZE)
2043 sym_link *type = operandType (op);
2044 if (IS_GENPTR (type))
2046 /* generic pointer; arithmetic operations
2047 * should ignore the high byte (pointer type).
2055 /*-----------------------------------------------------------------*/
2056 /* outAcc - output Acc */
2057 /*-----------------------------------------------------------------*/
2059 outAcc (operand * result)
2062 size = getDataSize (result);
2065 aopPut (result, "a", 0);
2068 /* unsigned or positive */
2071 aopPut (result, zero, offset++);
2076 /*-----------------------------------------------------------------*/
2077 /* outBitC - output a bit C */
2078 /*-----------------------------------------------------------------*/
2080 outBitC (operand * result)
2082 /* if the result is bit */
2083 if (AOP_TYPE (result) == AOP_CRY)
2085 aopPut (result, "c", 0);
2089 emitcode ("clr", "a");
2090 emitcode ("rlc", "a");
2095 /*-----------------------------------------------------------------*/
2096 /* toBoolean - emit code for orl a,operator(sizeop) */
2097 /*-----------------------------------------------------------------*/
2099 toBoolean (operand * oper)
2101 int size = AOP_SIZE (oper) - 1;
2105 /* The generic part of a generic pointer should
2106 * not participate in it's truth value.
2108 * i.e. 0x10000000 is zero.
2110 if (opIsGptr (oper))
2112 D (emitcode (";", "toBoolean: generic ptr special case."));
2116 _startLazyDPSEvaluation ();
2117 MOVA (aopGet (oper, 0, FALSE, FALSE, NULL));
2118 if (AOP_NEEDSACC (oper) && size && (AOP (oper)->type != AOP_ACC))
2121 emitcode("mov", "b,a");
2124 MOVA (aopGet (oper, offset++, FALSE, FALSE, NULL));
2125 emitcode ("orl", "b,a");
2127 MOVA (aopGet (oper, offset++, FALSE, FALSE, NULL));
2128 emitcode ("orl", "a,b");
2135 emitcode ("orl", "a,%s",
2136 aopGet (oper, offset++, FALSE, FALSE, NULL));
2139 _endLazyDPSEvaluation ();
2143 /*-----------------------------------------------------------------*/
2144 /* genNot - generate code for ! operation */
2145 /*-----------------------------------------------------------------*/
2151 D (emitcode (";", "genNot"));
2153 /* assign asmOps to operand & result */
2154 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2155 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
2157 /* if in bit space then a special case */
2158 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2160 /* if left==result then cpl bit */
2161 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2163 emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2167 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2168 emitcode ("cpl", "c");
2169 outBitC (IC_RESULT (ic));
2174 toBoolean (IC_LEFT (ic));
2176 /* set C, if a == 0 */
2177 tlbl = newiTempLabel (NULL);
2178 emitcode ("cjne", "a,#0x01,!tlabel", tlbl->key + 100);
2180 outBitC (IC_RESULT (ic));
2183 /* release the aops */
2184 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2185 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2189 /*-----------------------------------------------------------------*/
2190 /* genCpl - generate code for complement */
2191 /*-----------------------------------------------------------------*/
2198 sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
2200 D(emitcode (";", "genCpl"));
2202 /* assign asmOps to operand & result */
2203 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2204 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
2206 /* special case if in bit space */
2207 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2211 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
2212 (SPEC_USIGN (letype) && IS_CHAR (letype)))
2214 /* promotion rules are responsible for this strange result:
2215 bit -> int -> ~int -> bit
2216 uchar -> int -> ~int -> bit
2218 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
2222 tlbl=newiTempLabel(NULL);
2223 l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE, NULL);
2224 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
2225 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
2226 IS_AOP_PREG (IC_LEFT (ic)))
2228 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
2233 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
2236 outBitC (IC_RESULT(ic));
2240 size = AOP_SIZE (IC_RESULT (ic));
2241 _startLazyDPSEvaluation ();
2244 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL);
2246 emitcode ("cpl", "a");
2247 aopPut (IC_RESULT (ic), "a", offset++);
2249 _endLazyDPSEvaluation ();
2253 /* release the aops */
2254 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2255 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2258 /*-----------------------------------------------------------------*/
2259 /* genUminusFloat - unary minus for floating points */
2260 /*-----------------------------------------------------------------*/
2262 genUminusFloat (operand * op, operand * result)
2264 int size, offset = 0;
2267 D (emitcode (";", "genUminusFloat"));
2269 /* for this we just copy and then flip the bit */
2271 _startLazyDPSEvaluation ();
2272 size = AOP_SIZE (op) - 1;
2277 aopGet (op, offset, FALSE, FALSE, NULL),
2282 l = aopGet (op, offset, FALSE, FALSE, NULL);
2285 emitcode ("cpl", "acc.7");
2286 aopPut (result, "a", offset);
2287 _endLazyDPSEvaluation ();
2290 /*-----------------------------------------------------------------*/
2291 /* genUminus - unary minus code generation */
2292 /*-----------------------------------------------------------------*/
2294 genUminus (iCode * ic)
2299 D (emitcode (";", "genUminus"));
2302 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2303 aopOp (IC_RESULT (ic), ic, TRUE, (AOP_TYPE(IC_LEFT (ic)) == AOP_DPTR));
2305 /* if both in bit space then special
2307 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2308 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2311 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2312 emitcode ("cpl", "c");
2313 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2317 optype = operandType (IC_LEFT (ic));
2319 /* if float then do float stuff */
2320 if (IS_FLOAT (optype))
2322 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2326 /* otherwise subtract from zero */
2327 size = AOP_SIZE (IC_LEFT (ic));
2329 _startLazyDPSEvaluation ();
2332 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL);
2333 if (!strcmp (l, "a"))
2337 emitcode ("cpl", "a");
2338 emitcode ("addc", "a,#0x00");
2344 emitcode ("clr", "a");
2345 emitcode ("subb", "a,%s", l);
2347 aopPut (IC_RESULT (ic), "a", offset++);
2349 _endLazyDPSEvaluation ();
2351 /* if any remaining bytes in the result */
2352 /* we just need to propagate the sign */
2353 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2355 emitcode ("rlc", "a");
2356 emitcode ("subb", "a,acc");
2358 aopPut (IC_RESULT (ic), "a", offset++);
2362 /* release the aops */
2363 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2364 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2367 /*-----------------------------------------------------------------*/
2368 /* savermask - saves registers in the mask */
2369 /*-----------------------------------------------------------------*/
2370 static void savermask(bitVect *rs_mask)
2374 if (options.useXstack)
2376 if (bitVectBitValue (rs_mask, R0_IDX))
2377 emitcode ("mov", "b,r0");
2378 emitcode ("mov", "r0,%s", spname);
2379 for (i = 0; i < ds390_nRegs; i++)
2381 if (bitVectBitValue (rs_mask, i))
2384 emitcode ("mov", "a,b");
2386 emitcode ("mov", "a,%s", REG_WITH_INDEX (i)->name);
2387 emitcode ("movx", "@r0,a");
2388 emitcode ("inc", "r0");
2391 emitcode ("mov", "%s,r0", spname);
2392 if (bitVectBitValue (rs_mask, R0_IDX))
2393 emitcode ("mov", "r0,b");
2397 bool bits_pushed = FALSE;
2398 for (i = 0; i < ds390_nRegs; i++)
2400 if (bitVectBitValue (rs_mask, i))
2402 bits_pushed = pushReg (i, bits_pushed);
2408 /*-----------------------------------------------------------------*/
2409 /* saveRegisters - will look for a call and save the registers */
2410 /*-----------------------------------------------------------------*/
2412 saveRegisters (iCode * lic)
2418 for (ic = lic; ic; ic = ic->next)
2419 if (ic->op == CALL || ic->op == PCALL)
2424 fprintf (stderr, "found parameter push with no function call\n");
2428 /* if the registers have been saved already or don't need to be then
2431 || (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))) && !TARGET_IS_DS400) )
2434 /* special case if DPTR alive across a function call then must save it
2435 even though callee saves */
2436 if (IS_SYMOP(IC_LEFT(ic)) &&
2437 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)));
2449 /* save the registers in use at this time but skip the
2450 ones for the result */
2451 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2452 ds390_rUmaskForOp (IC_RESULT(ic)));
2458 /*-----------------------------------------------------------------*/
2459 /* usavermask - restore registers with mask */
2460 /*-----------------------------------------------------------------*/
2461 static void unsavermask(bitVect *rs_mask)
2465 if (options.useXstack)
2467 emitcode ("mov", "r0,%s", spname);
2468 for (i = ds390_nRegs; i >= 0; i--)
2470 if (bitVectBitValue (rs_mask, i))
2472 regs * reg = REG_WITH_INDEX (i);
2473 emitcode ("dec", "r0");
2474 emitcode ("movx", "a,@r0");
2477 emitcode ("push", "acc");
2481 emitcode ("mov", "%s,a", reg->name);
2485 emitcode ("mov", "%s,r0", spname);
2486 if (bitVectBitValue (rs_mask, R0_IDX))
2488 emitcode ("pop", "ar0");
2493 bool bits_popped = FALSE;
2494 for (i = ds390_nRegs; i >= 0; i--)
2496 if (bitVectBitValue (rs_mask, i))
2498 bits_popped = popReg (i, bits_popped);
2504 /*-----------------------------------------------------------------*/
2505 /* unsaveRegisters - pop the pushed registers */
2506 /*-----------------------------------------------------------------*/
2508 unsaveRegisters (iCode * ic)
2512 if (IS_SYMOP(IC_LEFT (ic)) &&
2513 IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2515 rsave = newBitVect(ic->rMask->size);
2516 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2517 if (bitVectBitValue(ic->rMask,i))
2518 rsave = bitVectSetBit(rsave,i);
2520 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2522 /* restore the registers in use at this time but skip the
2523 ones for the result */
2524 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2525 ds390_rUmaskForOp (IC_RESULT(ic)));
2531 /*-----------------------------------------------------------------*/
2533 /*-----------------------------------------------------------------*/
2535 pushSide (operand * oper, int size, iCode * ic)
2538 int nPushed = _G.r0Pushed + _G.r1Pushed;
2540 aopOp (oper, ic, FALSE, FALSE);
2542 if (nPushed != _G.r0Pushed + _G.r1Pushed)
2544 while (offset < size)
2546 char *l = aopGet (oper, offset, FALSE, TRUE, NULL);
2547 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2549 freeAsmop (oper, NULL, ic, TRUE);
2551 while (offset < size)
2553 emitcode ("push", "%s", fReturn[offset++]);
2558 _startLazyDPSEvaluation ();
2561 char *l = aopGet (oper, offset++, FALSE, TRUE, NULL);
2562 if (AOP_TYPE (oper) != AOP_REG &&
2563 AOP_TYPE (oper) != AOP_DIR &&
2567 emitcode ("push", "acc");
2571 emitcode ("push", "%s", l);
2574 _endLazyDPSEvaluation ();
2575 freeAsmop (oper, NULL, ic, TRUE);
2578 /*-----------------------------------------------------------------*/
2579 /* assignResultValue - also indicates if acc is in use afterwards */
2580 /*-----------------------------------------------------------------*/
2582 assignResultValue (operand * oper, operand * func)
2585 unsigned size = AOP_SIZE (oper);
2586 bool accuse = FALSE;
2587 bool pushedA = FALSE;
2589 if (func && IS_BIT (OP_SYM_ETYPE (func)))
2595 if (size == fReturnSizeDS390)
2597 /* I don't think this case can ever happen... */
2598 /* ACC is the last part of this. If writing the result
2599 * uses ACC, we must preserve it.
2601 if (AOP_NEEDSACC(oper))
2603 emitcode(";", "assignResultValue special case for ACC.");
2604 emitcode("push", "acc");
2610 _startLazyDPSEvaluation ();
2613 accuse |= aopPut (oper, fReturn[offset], offset);
2616 _endLazyDPSEvaluation ();
2620 emitcode ("pop", "acc");
2621 accuse |= aopPut (oper, "a", offset);
2627 /*-----------------------------------------------------------------*/
2628 /* genXpush - pushes onto the external stack */
2629 /*-----------------------------------------------------------------*/
2631 genXpush (iCode * ic)
2633 asmop *aop = newAsmop (0);
2635 int size, offset = 0;
2637 D (emitcode (";", "genXpush"));
2639 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2640 r = getFreePtr (ic, &aop, FALSE);
2642 size = AOP_SIZE (IC_LEFT (ic));
2646 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
2647 emitcode ("mov", "%s,_spx", r->name);
2648 emitcode ("inc", "_spx"); // allocate space first
2649 emitcode ("movx", "@%s,a", r->name);
2653 // allocate space first
2654 emitcode ("mov", "%s,_spx", r->name);
2656 emitcode ("add", "a,#%d", size);
2657 emitcode ("mov", "_spx,a");
2659 _startLazyDPSEvaluation ();
2662 MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE, NULL));
2663 emitcode ("movx", "@%s,a", r->name);
2664 emitcode ("inc", "%s", r->name);
2666 _endLazyDPSEvaluation ();
2669 freeAsmop (NULL, aop, ic, TRUE);
2670 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2673 /*-----------------------------------------------------------------*/
2674 /* genIpush - generate code for pushing this gets a little complex */
2675 /*-----------------------------------------------------------------*/
2677 genIpush (iCode * ic)
2679 int size, offset = 0;
2683 D (emitcode (";", "genIpush"));
2685 /* if this is not a parm push : ie. it is spill push
2686 and spill push is always done on the local stack */
2690 /* and the item is spilt then do nothing */
2691 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2694 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2695 size = AOP_SIZE (IC_LEFT (ic));
2696 /* push it on the stack */
2697 _startLazyDPSEvaluation ();
2700 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE, NULL);
2706 emitcode ("push", "%s", l);
2708 _endLazyDPSEvaluation ();
2712 /* this is a parameter push: in this case we call
2713 the routine to find the call and save those
2714 registers that need to be saved */
2717 /* if use external stack then call the external
2718 stack pushing routine */
2719 if (options.useXstack)
2725 /* then do the push */
2726 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2728 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2729 size = AOP_SIZE (IC_LEFT (ic));
2731 _startLazyDPSEvaluation ();
2734 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE, NULL);
2735 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2736 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2739 if (strcmp (l, prev) || *l == '@')
2741 emitcode ("push", "acc");
2745 emitcode ("push", "%s", l);
2749 _endLazyDPSEvaluation ();
2751 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2754 /*-----------------------------------------------------------------*/
2755 /* genIpop - recover the registers: can happen only for spilling */
2756 /*-----------------------------------------------------------------*/
2758 genIpop (iCode * ic)
2762 D (emitcode (";", "genIpop"));
2764 /* if the temp was not pushed then */
2765 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2768 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2769 size = AOP_SIZE (IC_LEFT (ic));
2770 offset = (size - 1);
2771 _startLazyDPSEvaluation ();
2774 emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2775 FALSE, TRUE, NULL));
2777 _endLazyDPSEvaluation ();
2779 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2782 /*-----------------------------------------------------------------*/
2783 /* popForBranch - recover the spilt registers for a branch */
2784 /*-----------------------------------------------------------------*/
2786 popForBranch (iCode * ic, bool markGenerated)
2788 while (ic && ic->op == IPOP)
2792 ic->generated = 1; /* mark the icode as generated */
2797 /*-----------------------------------------------------------------*/
2798 /* saveRBank - saves an entire register bank on the stack */
2799 /*-----------------------------------------------------------------*/
2801 saveRBank (int bank, iCode * ic, bool pushPsw)
2804 int count = 8 + (ds390_nBitRegs/8) + (pushPsw ? 1 : 0);
2808 if (options.useXstack)
2812 /* Assume r0 is available for use. */
2813 r = REG_WITH_INDEX (R0_IDX);
2818 r = getFreePtr (ic, &aop, FALSE);
2820 // allocate space first
2821 emitcode ("mov", "%s,_spx", r->name);
2823 emitcode ("add", "a,#%d", count);
2824 emitcode ("mov", "_spx,a");
2827 for (i = 0; i < 8; i++) /* only R0-R7 needs saving */
2829 if (options.useXstack)
2831 emitcode ("mov", "a,(%s+%d)",
2832 regs390[i].base, 8 * bank + regs390[i].offset);
2833 emitcode ("movx", "@%s,a", r->name);
2835 emitcode ("inc", "%s", r->name);
2838 emitcode ("push", "(%s+%d)",
2839 regs390[i].base, 8 * bank + regs390[i].offset);
2842 if (ds390_nBitRegs > 0)
2844 if (options.useXstack)
2846 emitcode ("mov", "a,bits");
2847 emitcode ("movx", "@%s,a", r->name);
2849 emitcode ("inc", "%s", r->name);
2853 emitcode ("push", "bits");
2860 if (options.useXstack)
2862 emitcode ("mov", "a,psw");
2863 emitcode ("movx", "@%s,a", r->name);
2867 emitcode ("push", "psw");
2870 emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2875 freeAsmop (NULL, aop, ic, TRUE);
2884 /*-----------------------------------------------------------------*/
2885 /* unsaveRBank - restores the register bank from stack */
2886 /*-----------------------------------------------------------------*/
2888 unsaveRBank (int bank, iCode * ic, bool popPsw)
2894 if (options.useXstack)
2898 /* Assume r0 is available for use. */
2899 r = REG_WITH_INDEX (R0_IDX);
2904 r = getFreePtr (ic, &aop, FALSE);
2906 emitcode ("mov", "%s,_spx", r->name);
2911 if (options.useXstack)
2913 emitcode ("dec", "%s", r->name);
2914 emitcode ("movx", "a,@%s", r->name);
2915 emitcode ("mov", "psw,a");
2919 emitcode ("pop", "psw");
2923 if (ds390_nBitRegs > 0)
2925 if (options.useXstack)
2927 emitcode ("dec", "%s", r->name);
2928 emitcode ("movx", "a,@%s", r->name);
2929 emitcode ("mov", "bits,a");
2933 emitcode ("pop", "bits");
2937 for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2939 if (options.useXstack)
2941 emitcode ("dec", "%s", r->name);
2942 emitcode ("movx", "a,@%s", r->name);
2943 emitcode ("mov", "(%s+%d),a",
2944 regs390[i].base, 8 * bank + regs390[i].offset);
2948 emitcode ("pop", "(%s+%d)",
2949 regs390[i].base, 8 * bank + regs390[i].offset);
2953 if (options.useXstack)
2955 emitcode ("mov", "_spx,%s", r->name);
2960 freeAsmop (NULL, aop, ic, TRUE);
2964 /*-----------------------------------------------------------------*/
2965 /* genSend - gen code for SEND */
2966 /*-----------------------------------------------------------------*/
2967 static void genSend(set *sendSet)
2972 static int rb1_count = 0;
2974 /* first we do all bit parameters */
2975 for (sic = setFirstItem (sendSet); sic;
2976 sic = setNextItem (sendSet))
2978 if (sic->argreg > 12)
2980 int bit = sic->argreg-13;
2982 aopOp (IC_LEFT (sic), sic, FALSE,
2983 (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2985 /* if left is a literal then
2986 we know what the value is */
2987 if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2989 if (((int) operandLitValue (IC_LEFT (sic))))
2990 emitcode ("setb", "b[%d]", bit);
2992 emitcode ("clr", "b[%d]", bit);
2994 else if (AOP_TYPE (IC_LEFT (sic)) == AOP_CRY)
2996 char *l = AOP (IC_LEFT (sic))->aopu.aop_dir;
2997 if (strcmp (l, "c"))
2998 emitcode ("mov", "c,%s", l);
2999 emitcode ("mov", "b[%d],c", bit);
3004 toBoolean (IC_LEFT (sic));
3005 /* set C, if a >= 1 */
3006 emitcode ("add", "a,#0xff");
3007 emitcode ("mov", "b[%d],c", bit);
3012 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
3018 saveRegisters (setFirstItem (sendSet));
3019 emitcode ("mov", "bits,b");
3022 /* then we do all other parameters */
3023 for (sic = setFirstItem (sendSet); sic;
3024 sic = setNextItem (sendSet))
3026 if (sic->argreg <= 12)
3028 int size, offset = 0;
3030 size = getSize (operandType (IC_LEFT (sic)));
3031 D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
3033 { /* first parameter */
3034 // we know that dpl(hxb) is the result, so
3036 _startLazyDPSEvaluation ();
3039 aopOp (IC_LEFT (sic), sic, FALSE,
3040 (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
3044 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
3048 char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE, NULL);
3049 if (strcmp (l, fReturn[offset]))
3051 emitcode ("mov", "%s,%s", fReturn[offset], l);
3055 _endLazyDPSEvaluation ();
3056 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
3060 { /* if more parameter in registers */
3061 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
3064 emitcode ("mov","b1_%d,%s",rb1_count++,
3065 aopGet (IC_LEFT (sic), offset, FALSE, FALSE, NULL));
3068 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
3076 adjustEsp(const char *reg)
3078 emitcode ("anl","%s,#3", reg);
3079 if (TARGET_IS_DS400)
3081 emitcode ("orl","%s,#!constbyte",
3083 (options.stack_loc >> 8) & 0xff);
3087 /*-----------------------------------------------------------------*/
3088 /* selectRegBank - emit code to select the register bank */
3089 /*-----------------------------------------------------------------*/
3091 selectRegBank (short bank, bool keepFlags)
3093 /* if f.e. result is in carry */
3096 emitcode ("anl", "psw,#0xE7");
3098 emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
3102 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
3106 /*-----------------------------------------------------------------*/
3107 /* genCall - generates a call statement */
3108 /*-----------------------------------------------------------------*/
3110 genCall (iCode * ic)
3114 bool restoreBank = FALSE;
3115 bool swapBanks = FALSE;
3116 bool accuse = FALSE;
3117 bool accPushed = FALSE;
3118 bool resultInF0 = FALSE;
3119 bool assignResultGenerated = FALSE;
3121 D (emitcode (";", "genCall"));
3123 /* if we are calling a not _naked function that is not using
3124 the same register bank then we need to save the
3125 destination registers on the stack */
3126 dtype = operandType (IC_LEFT (ic));
3127 etype = getSpec(dtype);
3128 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
3129 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
3130 IFFUNC_ISISR (currFunc->type))
3134 /* This is unexpected; the bank should have been saved in
3137 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
3143 /* if caller saves & we have not saved then */
3147 /* if send set is not empty then assign */
3148 /* We've saved all the registers we care about;
3149 * therefore, we may clobber any register not used
3150 * in the calling convention (i.e. anything not in
3155 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
3156 genSend(reverseSet(_G.sendSet));
3158 genSend(_G.sendSet);
3165 emitcode ("mov", "psw,#!constbyte",
3166 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3170 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
3171 OP_SYMBOL (IC_LEFT (ic))->rname :
3172 OP_SYMBOL (IC_LEFT (ic))->name));
3176 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
3179 /* if we need assign a result value */
3180 if ((IS_ITEMP (IC_RESULT (ic)) &&
3181 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3182 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3183 OP_SYMBOL (IC_RESULT (ic))->accuse ||
3184 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3185 IS_TRUE_SYMOP (IC_RESULT (ic)))
3187 if (isOperandInFarSpace (IC_RESULT (ic))
3188 && getSize (operandType (IC_RESULT (ic))) <= 2)
3190 int size = getSize (operandType (IC_RESULT (ic)));
3191 bool pushedB = FALSE;
3193 /* Special case for 1 or 2 byte return in far space. */
3198 emitcode ("mov", "b,%s", fReturn[1]);
3202 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
3207 aopPut (IC_RESULT (ic), "a", 0);
3211 aopPut (IC_RESULT (ic), "b", 1);
3213 assignResultGenerated = TRUE;
3214 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3218 bool pushedB = pushB ();
3219 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
3222 accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3223 assignResultGenerated = TRUE;
3224 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3228 /* adjust the stack for parameters if required */
3232 if (options.stack10bit) {
3233 if (ic->parmBytes <= 10) {
3234 emitcode(";","stack adjustment for parms");
3235 for (i=0; i < ic->parmBytes ; i++) {
3236 emitcode("pop","acc");
3240 emitcode ("clr","c");
3241 emitcode ("mov","a,sp");
3242 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
3243 emitcode ("mov","sp,a");
3244 emitcode ("mov","a,esp");
3246 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
3247 emitcode ("mov","esp,a");
3251 if (ic->parmBytes > 3)
3255 emitcode ("push", "acc");
3258 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3259 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3260 !assignResultGenerated)
3262 emitcode ("mov", "F0,c");
3266 emitcode ("mov", "a,%s", spname);
3267 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
3268 emitcode ("mov", "%s,a", spname);
3270 /* unsaveRegisters from xstack needs acc, but */
3271 /* unsaveRegisters from stack needs this popped */
3272 if (accPushed && !options.useXstack)
3274 emitcode ("pop", "acc");
3279 for (i = 0; i < ic->parmBytes; i++)
3280 emitcode ("dec", "%s", spname);
3284 /* if we had saved some registers then unsave them */
3285 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3287 if (accuse && !accPushed && options.useXstack)
3289 /* xstack needs acc, but doesn't touch normal stack */
3290 emitcode ("push", "acc");
3293 unsaveRegisters (ic);
3296 /* if register bank was saved then pop them */
3298 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
3300 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
3303 emitcode ("mov", "c,F0");
3305 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
3306 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3307 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3311 emitcode ("pop", "acc");
3314 /*-----------------------------------------------------------------*/
3315 /* genPcall - generates a call by pointer statement */
3316 /*-----------------------------------------------------------------*/
3318 genPcall (iCode * ic)
3322 symbol *rlbl = newiTempLabel (NULL);
3323 bool restoreBank=FALSE;
3324 bool resultInF0 = FALSE;
3326 D (emitcode (";", "genPcall"));
3328 dtype = operandType (IC_LEFT (ic))->next;
3329 etype = getSpec(dtype);
3330 /* if caller saves & we have not saved then */
3334 /* if we are calling a not _naked function that is not using
3335 the same register bank then we need to save the
3336 destination registers on the stack */
3337 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
3338 IFFUNC_ISISR (currFunc->type) &&
3339 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
3340 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3344 /* push the return address on to the stack */
3345 emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
3346 emitcode ("push", "acc");
3347 emitcode ("mov", "a,#!hil", (rlbl->key + 100));
3348 emitcode ("push", "acc");
3350 if (options.model == MODEL_FLAT24)
3352 emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
3353 emitcode ("push", "acc");
3356 /* now push the function address */
3357 pushSide (IC_LEFT (ic), FPTRSIZE, ic);
3359 /* if send set is not empty then assign */
3362 genSend(reverseSet(_G.sendSet));
3367 emitcode ("ret", "");
3371 /* if we need assign a result value */
3372 if ((IS_ITEMP (IC_RESULT (ic)) &&
3373 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3374 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3375 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3376 IS_TRUE_SYMOP (IC_RESULT (ic)))
3380 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
3383 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3385 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3388 /* adjust the stack for parameters if required */
3392 if (options.stack10bit) {
3393 if (ic->parmBytes <= 10) {
3394 emitcode(";","stack adjustment for parms");
3395 for (i=0; i < ic->parmBytes ; i++) {
3396 emitcode("pop","acc");
3399 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3400 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3402 emitcode ("mov", "F0,c");
3407 emitcode ("clr","c");
3408 emitcode ("mov","a,sp");
3409 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
3410 emitcode ("mov","sp,a");
3411 emitcode ("mov","a,esp");
3413 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
3414 emitcode ("mov","esp,a");
3418 if (ic->parmBytes > 3) {
3419 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3420 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3422 emitcode ("mov", "F0,c");
3426 emitcode ("mov", "a,%s", spname);
3427 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
3428 emitcode ("mov", "%s,a", spname);
3431 for (i = 0; i < ic->parmBytes; i++)
3432 emitcode ("dec", "%s", spname);
3435 /* if register bank was saved then unsave them */
3437 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3439 /* if we had saved some registers then unsave them */
3441 unsaveRegisters (ic);
3443 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3446 emitcode ("mov", "c,F0");
3448 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
3449 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3450 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3454 /*-----------------------------------------------------------------*/
3455 /* resultRemat - result is rematerializable */
3456 /*-----------------------------------------------------------------*/
3458 resultRemat (iCode * ic)
3460 if (SKIP_IC (ic) || ic->op == IFX)
3463 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3465 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3466 if (sym->remat && !POINTER_SET (ic))
3473 /*-----------------------------------------------------------------*/
3474 /* inExcludeList - return 1 if the string is in exclude Reg list */
3475 /*-----------------------------------------------------------------*/
3477 regsCmp(void *p1, void *p2)
3479 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3483 inExcludeList (char *s)
3485 const char *p = setFirstItem(options.excludeRegsSet);
3487 if (p == NULL || STRCASECMP(p, "none") == 0)
3491 return isinSetWith(options.excludeRegsSet, s, regsCmp);
3494 /*-----------------------------------------------------------------*/
3495 /* genFunction - generated code for function entry */
3496 /*-----------------------------------------------------------------*/
3498 genFunction (iCode * ic)
3500 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3502 bool switchedPSW = FALSE;
3503 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3505 D (emitcode (";", "genFunction"));
3508 /* create the function header */
3509 emitcode (";", "-----------------------------------------");
3510 emitcode (";", " function %s", sym->name);
3511 emitcode (";", "-----------------------------------------");
3513 emitcode ("", "%s:", sym->rname);
3514 lineCurr->isLabel = 1;
3515 ftype = operandType (IC_LEFT (ic));
3516 _G.currentFunc = sym;
3518 if (IFFUNC_ISNAKED(ftype))
3520 emitcode(";", "naked function: no prologue.");
3524 if (options.stack_probe)
3525 emitcode ("lcall","__stack_probe");
3527 /* here we need to generate the equates for the
3528 register bank if required */
3529 if (FUNC_REGBANK (ftype) != rbank)
3533 rbank = FUNC_REGBANK (ftype);
3534 for (i = 0; i < ds390_nRegs; i++)
3536 if (regs390[i].print) {
3537 if (strcmp (regs390[i].base, "0") == 0)
3538 emitcode ("", "%s !equ !constbyte",
3540 8 * rbank + regs390[i].offset);
3542 emitcode ("", "%s !equ %s + !constbyte",
3545 8 * rbank + regs390[i].offset);
3550 /* if this is an interrupt service routine then
3551 save acc, b, dpl, dph */
3552 if (IFFUNC_ISISR (sym->type))
3554 if (!inExcludeList ("acc"))
3555 emitcode ("push", "acc");
3556 if (!inExcludeList ("b"))
3557 emitcode ("push", "b");
3558 if (!inExcludeList ("dpl"))
3559 emitcode ("push", "dpl");
3560 if (!inExcludeList ("dph"))
3561 emitcode ("push", "dph");
3562 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3564 emitcode ("push", "dpx");
3565 /* Make sure we're using standard DPTR */
3566 emitcode ("push", "dps");
3567 emitcode ("mov", "dps,#0");
3568 if (options.stack10bit)
3570 /* This ISR could conceivably use DPTR2. Better save it. */
3571 emitcode ("push", "dpl1");
3572 emitcode ("push", "dph1");
3573 emitcode ("push", "dpx1");
3574 emitcode ("push", DP2_RESULT_REG);
3577 /* if this isr has no bank i.e. is going to
3578 run with bank 0 , then we need to save more
3580 if (!FUNC_REGBANK (sym->type))
3584 /* if this function does not call any other
3585 function then we can be economical and
3586 save only those registers that are used */
3587 if (!IFFUNC_HASFCALL(sym->type))
3589 /* if any registers used */
3592 bool bits_pushed = FALSE;
3593 /* save the registers used */
3594 for (i = 0; i < sym->regsUsed->size; i++)
3596 if (bitVectBitValue (sym->regsUsed, i))
3597 bits_pushed = pushReg (i, bits_pushed);
3603 /* this function has a function call. We cannot
3604 determine register usage so we will have to push the
3606 saveRBank (0, ic, FALSE);
3607 if (options.parms_in_bank1)
3609 for (i=0; i < 8 ; i++ )
3611 emitcode ("push","%s",rb1regs[i]);
3618 /* This ISR uses a non-zero bank.
3620 * We assume that the bank is available for our
3623 * However, if this ISR calls a function which uses some
3624 * other bank, we must save that bank entirely.
3626 unsigned long banksToSave = 0;
3628 if (IFFUNC_HASFCALL(sym->type))
3631 #define MAX_REGISTER_BANKS 4
3636 for (i = ic; i; i = i->next)
3638 if (i->op == ENDFUNCTION)
3640 /* we got to the end OK. */
3648 dtype = operandType (IC_LEFT(i));
3650 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3652 /* Mark this bank for saving. */
3653 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3655 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3659 banksToSave |= (1 << FUNC_REGBANK(dtype));
3662 /* And note that we don't need to do it in
3670 /* This is a mess; we have no idea what
3671 * register bank the called function might
3674 * The only thing I can think of to do is
3675 * throw a warning and hope.
3677 werror(W_FUNCPTR_IN_USING_ISR);
3681 if (banksToSave && options.useXstack)
3683 /* Since we aren't passing it an ic,
3684 * saveRBank will assume r0 is available to abuse.
3686 * So switch to our (trashable) bank now, so
3687 * the caller's R0 isn't trashed.
3689 emitcode ("push", "psw");
3690 emitcode ("mov", "psw,#!constbyte",
3691 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3695 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3697 if (banksToSave & (1 << ix))
3699 saveRBank(ix, NULL, FALSE);
3703 // TODO: this needs a closer look
3704 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3709 /* if callee-save to be used for this function
3710 then save the registers being used in this function */
3711 if (IFFUNC_CALLEESAVES(sym->type))
3715 /* if any registers used */
3718 bool bits_pushed = FALSE;
3719 /* save the registers used */
3720 for (i = 0; i < sym->regsUsed->size; i++)
3722 if (bitVectBitValue (sym->regsUsed, i))
3724 bits_pushed = pushReg (i, bits_pushed);
3732 /* set the register bank to the desired value */
3733 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3736 emitcode ("push", "psw");
3737 emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3741 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3742 if (options.stack10bit) {
3743 emitcode ("push","_bpx");
3744 emitcode ("push","_bpx+1");
3745 emitcode ("mov","_bpx,%s",spname);
3746 emitcode ("mov","_bpx+1,esp");
3747 adjustEsp("_bpx+1");
3749 if (options.useXstack)
3751 emitcode ("mov", "r0,%s", spname);
3752 emitcode ("mov", "a,_bp");
3753 emitcode ("movx", "@r0,a");
3754 emitcode ("inc", "%s", spname);
3756 /* set up the stack */
3757 emitcode ("push", "_bp"); /* save the callers stack */
3759 emitcode ("mov", "_bp,%s", spname);
3763 /* adjust the stack for the function */
3766 if (options.stack10bit) {
3767 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
3768 assert (sym->recvSize <= 4);
3769 if (sym->stack <= 8) {
3770 while (i--) emitcode ("push","acc");
3773 emitcode ("mov","a,sp");
3774 emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3775 emitcode ("mov","sp,a");
3776 emitcode ("mov","a,esp");
3778 emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3779 emitcode ("mov","esp,a");
3784 werror (W_STACK_OVERFLOW, sym->name);
3786 if (i > 3 && sym->recvSize < 4) {
3788 emitcode ("mov", "a,sp");
3789 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3790 emitcode ("mov", "sp,a");
3794 emitcode ("inc", "sp");
3801 emitcode ("mov", "a,_spx");
3802 emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3803 emitcode ("mov", "_spx,a");
3806 /* if critical function then turn interrupts off */
3807 if (IFFUNC_ISCRITICAL (ftype))
3809 symbol *tlbl = newiTempLabel (NULL);
3810 emitcode ("setb", "c");
3811 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3812 emitcode ("clr", "c");
3814 emitcode ("push", "psw"); /* save old ea via c in psw */
3818 /*-----------------------------------------------------------------*/
3819 /* genEndFunction - generates epilogue for functions */
3820 /*-----------------------------------------------------------------*/
3822 genEndFunction (iCode * ic)
3824 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3825 lineNode *lnp = lineCurr;
3827 bitVect *regsUsedPrologue;
3828 bitVect *regsUnneeded;
3831 D (emitcode (";", "genEndFunction"));
3833 _G.currentFunc = NULL;
3834 if (IFFUNC_ISNAKED(sym->type))
3836 emitcode(";", "naked function: no epilogue.");
3837 if (options.debug && currFunc)
3838 debugFile->writeEndFunction (currFunc, ic, 0);
3842 if (IFFUNC_ISCRITICAL (sym->type))
3844 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3846 emitcode ("rlc", "a"); /* save c in a */
3847 emitcode ("pop", "psw"); /* restore ea via c in psw */
3848 emitcode ("mov", "ea,c");
3849 emitcode ("rrc", "a"); /* restore c from a */
3853 emitcode ("pop", "psw"); /* restore ea via c in psw */
3854 emitcode ("mov", "ea,c");
3858 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3859 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3861 if (options.stack10bit) {
3863 emitcode ("mov", "sp,_bpx", spname);
3864 emitcode ("mov", "esp,_bpx+1", spname);
3867 emitcode ("mov", "%s,_bp", spname);
3871 /* if use external stack but some variables were
3872 added to the local stack then decrement the
3874 if (options.useXstack && sym->stack) {
3875 emitcode ("mov", "a,sp");
3876 emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3877 emitcode ("mov", "sp,a");
3881 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3882 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3884 if (options.useXstack) {
3885 emitcode ("mov", "r0,%s", spname);
3886 emitcode ("movx", "a,@r0");
3887 emitcode ("mov", "_bp,a");
3888 emitcode ("dec", "%s", spname);
3890 if (options.stack10bit) {
3891 emitcode ("pop", "_bpx+1");
3892 emitcode ("pop", "_bpx");
3894 emitcode ("pop", "_bp");
3899 /* restore the register bank */
3900 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3902 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3903 || !options.useXstack)
3905 /* Special case of ISR using non-zero bank with useXstack
3908 emitcode ("pop", "psw");
3912 if (IFFUNC_ISISR (sym->type))
3915 /* now we need to restore the registers */
3916 /* if this isr has no bank i.e. is going to
3917 run with bank 0 , then we need to save more
3919 if (!FUNC_REGBANK (sym->type))
3922 /* if this function does not call any other
3923 function then we can be economical and
3924 save only those registers that are used */
3925 if (!IFFUNC_HASFCALL(sym->type))
3927 /* if any registers used */
3930 bool bits_popped = FALSE;
3931 /* save the registers used */
3932 for (i = sym->regsUsed->size; i >= 0; i--)
3934 if (bitVectBitValue (sym->regsUsed, i))
3935 bits_popped = popReg (i, bits_popped);
3941 /* this function has a function call. We cannot
3942 determine register usage so we will have to pop the
3944 if (options.parms_in_bank1)
3946 for (i = 7 ; i >= 0 ; i-- )
3948 emitcode ("pop","%s",rb1regs[i]);
3951 unsaveRBank (0, ic, FALSE);
3956 /* This ISR uses a non-zero bank.
3958 * Restore any register banks saved by genFunction
3961 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3964 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3966 if (savedBanks & (1 << ix))
3968 unsaveRBank(ix, NULL, FALSE);
3972 if (options.useXstack)
3974 /* Restore bank AFTER calling unsaveRBank,
3975 * since it can trash r0.
3977 emitcode ("pop", "psw");
3981 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3983 if (options.stack10bit)
3985 emitcode ("pop", DP2_RESULT_REG);
3986 emitcode ("pop", "dpx1");
3987 emitcode ("pop", "dph1");
3988 emitcode ("pop", "dpl1");
3990 emitcode ("pop", "dps");
3991 emitcode ("pop", "dpx");
3993 if (!inExcludeList ("dph"))
3994 emitcode ("pop", "dph");
3995 if (!inExcludeList ("dpl"))
3996 emitcode ("pop", "dpl");
3997 if (!inExcludeList ("b"))
3998 emitcode ("pop", "b");
3999 if (!inExcludeList ("acc"))
4000 emitcode ("pop", "acc");
4002 /* if debug then send end of function */
4003 if (options.debug && currFunc)
4005 debugFile->writeEndFunction (currFunc, ic, 1);
4008 emitcode ("reti", "");
4012 if (IFFUNC_CALLEESAVES(sym->type))
4016 /* if any registers used */
4019 /* save the registers used */
4020 for (i = sym->regsUsed->size; i >= 0; i--)
4022 if (bitVectBitValue (sym->regsUsed, i))
4023 emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
4028 /* if debug then send end of function */
4029 if (options.debug && currFunc)
4031 debugFile->writeEndFunction (currFunc, ic, 1);
4034 emitcode ("ret", "");
4037 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
4040 /* If this was an interrupt handler using bank 0 that called another */
4041 /* function, then all registers must be saved; nothing to optimized. */
4042 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
4043 && !FUNC_REGBANK(sym->type))
4046 /* There are no push/pops to optimize if not callee-saves or ISR */
4047 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
4050 /* If there were stack parameters, we cannot optimize without also */
4051 /* fixing all of the stack offsets; this is too dificult to consider. */
4052 if (FUNC_HASSTACKPARM(sym->type))
4055 /* Compute the registers actually used */
4056 regsUsed = newBitVect (ds390_nRegs);
4057 regsUsedPrologue = newBitVect (ds390_nRegs);
4060 if (lnp->ic && lnp->ic->op == FUNCTION)
4061 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
4063 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
4065 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
4066 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
4073 if (bitVectBitValue (regsUsedPrologue, DPS_IDX)
4074 && !bitVectBitValue (regsUsed, DPS_IDX))
4076 bitVectUnSetBit (regsUsedPrologue, DPS_IDX);
4079 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
4080 && !bitVectBitValue (regsUsed, CND_IDX))
4082 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
4083 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
4084 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
4085 bitVectUnSetBit (regsUsed, CND_IDX);
4088 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
4090 /* If this was an interrupt handler that called another function */
4091 /* function, then assume working registers may be modified by it. */
4092 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
4094 regsUsed = bitVectSetBit (regsUsed, AP_IDX);
4095 regsUsed = bitVectSetBit (regsUsed, DPX1_IDX);
4096 regsUsed = bitVectSetBit (regsUsed, DPL1_IDX);
4097 regsUsed = bitVectSetBit (regsUsed, DPH1_IDX);
4098 regsUsed = bitVectSetBit (regsUsed, DPX_IDX);
4099 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
4100 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
4101 regsUsed = bitVectSetBit (regsUsed, DPS_IDX);
4102 regsUsed = bitVectSetBit (regsUsed, B_IDX);
4103 regsUsed = bitVectSetBit (regsUsed, A_IDX);
4104 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
4107 /* Remove the unneeded push/pops */
4108 regsUnneeded = newBitVect (ds390_nRegs);
4111 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
4113 if (!strncmp(lnp->line, "push", 4))
4115 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
4116 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4118 connectLine (lnp->prev, lnp->next);
4119 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4122 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
4124 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
4125 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4127 connectLine (lnp->prev, lnp->next);
4128 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4135 for (idx = 0; idx < regsUnneeded->size; idx++)
4136 if (bitVectBitValue (regsUnneeded, idx))
4137 emitcode (";", "eliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
4139 freeBitVect (regsUnneeded);
4140 freeBitVect (regsUsed);
4141 freeBitVect (regsUsedPrologue);
4144 /*-----------------------------------------------------------------*/
4145 /* genJavaNativeRet - generate code for return JavaNative */
4146 /*-----------------------------------------------------------------*/
4147 static void genJavaNativeRet(iCode *ic)
4151 aopOp (IC_LEFT (ic), ic, FALSE,
4152 AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
4153 size = AOP_SIZE (IC_LEFT (ic));
4157 /* it is assigned to GPR0-R3 then push them */
4158 if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
4159 aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
4160 for (i = 0 ; i < size ; i++ ) {
4161 emitcode ("push","%s",
4162 aopGet(IC_LEFT(ic),i,FALSE,TRUE,DP2_RESULT_REG));
4164 for (i = (size-1) ; i >= 0 ; i--) {
4165 emitcode ("pop","a%s",javaRet[i]);
4168 for (i = 0 ; i < size ; i++)
4169 emitcode ("mov","%s,%s",javaRet[i],
4170 aopGet(IC_LEFT(ic),i,FALSE,TRUE,DP2_RESULT_REG));
4172 for (i = size ; i < 4 ; i++ )
4173 emitcode ("mov","%s,#0",javaRet[i]);
4177 /*-----------------------------------------------------------------*/
4178 /* genRet - generate code for return statement */
4179 /*-----------------------------------------------------------------*/
4183 int size, offset = 0, pushed = 0;
4185 D (emitcode (";", "genRet"));
4187 /* if we have no return value then
4188 just generate the "ret" */
4192 /* if this is a JavaNative function then return
4193 value in different register */
4194 if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
4195 genJavaNativeRet(ic);
4198 /* we have something to return then
4199 move the return value into place */
4200 aopOp (IC_LEFT (ic), ic, FALSE,
4201 (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
4202 size = AOP_SIZE (IC_LEFT (ic));
4204 _startLazyDPSEvaluation ();
4206 if (IS_BIT(_G.currentFunc->etype))
4208 movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4215 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
4217 l = aopGet (IC_LEFT (ic), offset++,
4219 emitcode ("push", "%s", l);
4224 /* Since A is the last element of fReturn,
4225 * it is OK to clobber it in the aopGet.
4227 l = aopGet (IC_LEFT (ic), offset,
4228 FALSE, FALSE, NULL);
4229 if (strcmp (fReturn[offset], l))
4230 emitcode ("mov", "%s,%s", fReturn[offset++], l);
4233 _endLazyDPSEvaluation ();
4238 if (strcmp (fReturn[pushed], "a"))
4239 emitcode ("pop", fReturn[pushed]);
4241 emitcode ("pop", "acc");
4243 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
4246 /* generate a jump to the return label
4247 if the next is not the return statement */
4248 if (!(ic->next && ic->next->op == LABEL &&
4249 IC_LABEL (ic->next) == returnLabel))
4251 emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
4255 /*-----------------------------------------------------------------*/
4256 /* genLabel - generates a label */
4257 /*-----------------------------------------------------------------*/
4259 genLabel (iCode * ic)
4261 /* special case never generate */
4262 if (IC_LABEL (ic) == entryLabel)
4265 D (emitcode (";", "genLabel"));
4267 emitLabel (IC_LABEL (ic));
4270 /*-----------------------------------------------------------------*/
4271 /* genGoto - generates a ljmp */
4272 /*-----------------------------------------------------------------*/
4274 genGoto (iCode * ic)
4276 D (emitcode (";", "genGoto"));
4278 emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
4281 /*-----------------------------------------------------------------*/
4282 /* findLabelBackwards: walks back through the iCode chain looking */
4283 /* for the given label. Returns number of iCode instructions */
4284 /* between that label and given ic. */
4285 /* Returns zero if label not found. */
4286 /*-----------------------------------------------------------------*/
4288 findLabelBackwards (iCode * ic, int key)
4297 /* If we have any pushes or pops, we cannot predict the distance.
4298 I don't like this at all, this should be dealt with in the
4300 if (ic->op == IPUSH || ic->op == IPOP) {
4304 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4306 /* printf("findLabelBackwards = %d\n", count); */
4314 /*-----------------------------------------------------------------*/
4315 /* genPlusIncr :- does addition with increment if possible */
4316 /*-----------------------------------------------------------------*/
4318 genPlusIncr (iCode * ic)
4320 unsigned int icount;
4321 unsigned int size = getDataSize (IC_RESULT (ic));
4323 /* will try to generate an increment */
4324 /* if the right side is not a literal
4326 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4329 /* if the literal value of the right hand side
4330 is greater than 4 then it is not worth it */
4331 if ((icount = (unsigned int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4334 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4335 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4337 emitcode("inc","%s",aopGet(IC_RESULT(ic),0,FALSE,FALSE,NULL));
4341 /* if increment 16 bits in register */
4343 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4344 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4345 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4354 /* If the next instruction is a goto and the goto target
4355 * is <= 5 instructions previous to this, we can generate
4356 * jumps straight to that target.
4358 if (ic->next && ic->next->op == GOTO
4359 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4362 D (emitcode (";", "tail increment optimized (range %d)", labelRange));
4363 tlbl = IC_LABEL (ic->next);
4368 tlbl = newiTempLabel (NULL);
4371 l = aopGet (IC_RESULT (ic), LSB, FALSE, FALSE, NULL);
4372 emitcode ("inc", "%s", l);
4374 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4375 IS_AOP_PREG (IC_RESULT (ic)))
4377 emitcode ("cjne", "%s,%s,!tlabel", l, zero, tlbl->key + 100);
4381 emitcode ("clr", "a");
4382 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4385 l = aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE, NULL);
4386 emitcode ("inc", "%s", l);
4389 if (!strcmp(l, "acc"))
4391 emitcode("jnz", "!tlabel", tlbl->key + 100);
4393 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4394 IS_AOP_PREG (IC_RESULT (ic)))
4396 emitcode ("cjne", "%s,%s,!tlabel", l, zero, tlbl->key + 100);
4400 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4403 l = aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE, NULL);
4404 emitcode ("inc", "%s", l);
4408 if (!strcmp(l, "acc"))
4410 emitcode("jnz", "!tlabel", tlbl->key + 100);
4412 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4413 IS_AOP_PREG (IC_RESULT (ic)))
4415 emitcode ("cjne", "%s,%s,!tlabel", l, zero, tlbl->key + 100);
4419 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4422 l = aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE, NULL);
4423 emitcode ("inc", "%s", l);
4433 if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
4434 !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 &&
4435 options.model == MODEL_FLAT24 )
4437 if (IC_RESULT(ic)->isGptr)
4439 emitcode ("mov", "b,%s", aopGet(IC_LEFT (ic), 3, FALSE, FALSE, NULL));
4443 emitcode ("mov", "dpx,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE, NULL));
4445 emitcode ("mov", "dph,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE, NULL));
4447 emitcode ("mov", "dpl,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4451 emitcode ("inc", "dptr");
4455 if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
4456 AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
4459 emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
4461 emitcode ("inc", "dptr");
4462 emitcode ("mov", "dps,#0");
4466 /* if the sizes are greater than 1 then we cannot */
4467 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4468 AOP_SIZE (IC_LEFT (ic)) > 1)
4471 /* we can if the aops of the left & result match or
4472 if they are in registers and the registers are the
4475 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4476 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4477 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4481 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4482 emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
4483 aopPut (IC_RESULT (ic), "a", 0);
4487 _startLazyDPSEvaluation ();
4490 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4492 _endLazyDPSEvaluation ();
4501 /*-----------------------------------------------------------------*/
4502 /* outBitAcc - output a bit in acc */
4503 /*-----------------------------------------------------------------*/
4505 outBitAcc (operand * result)
4507 symbol *tlbl = newiTempLabel (NULL);
4508 /* if the result is a bit */
4509 if (AOP_TYPE (result) == AOP_CRY)
4511 aopPut (result, "a", 0);
4515 emitcode ("jz", "!tlabel", tlbl->key + 100);
4516 emitcode ("mov", "a,%s", one);
4522 /*-----------------------------------------------------------------*/
4523 /* genPlusBits - generates code for addition of two bits */
4524 /*-----------------------------------------------------------------*/
4526 genPlusBits (iCode * ic)
4528 D (emitcode (";", "genPlusBits"));
4530 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4531 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4533 symbol *lbl = newiTempLabel (NULL);
4534 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4535 emitcode ("cpl", "c");
4537 outBitC (IC_RESULT (ic));
4541 emitcode ("clr", "a");
4542 emitcode ("rlc", "a");
4543 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4544 emitcode ("addc", "a,%s", zero);
4545 outAcc (IC_RESULT (ic));
4550 adjustArithmeticResult (iCode * ic)
4552 if (opIsGptr (IC_RESULT (ic)) &&
4553 opIsGptr (IC_LEFT (ic)) &&
4554 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4556 aopPut (IC_RESULT (ic),
4557 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE, NULL),
4561 if (opIsGptr (IC_RESULT (ic)) &&
4562 opIsGptr (IC_RIGHT (ic)) &&
4563 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4565 aopPut (IC_RESULT (ic),
4566 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE, NULL),
4570 if (opIsGptr (IC_RESULT (ic)) &&
4571 IC_LEFT (ic) && AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4572 IC_RIGHT (ic) && AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4573 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4574 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4577 SNPRINTF (buffer, sizeof(buffer),
4578 "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4579 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4583 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
4584 // generates the result if possible. If result is generated, returns TRUE; otherwise
4585 // returns false and caller must deal with fact that result isn't aopOp'd.
4586 bool aopOp3(iCode * ic)
4588 bool dp1InUse, dp2InUse;
4591 // First, generate the right opcode. DPTR may be used if neither left nor result are
4594 // D (emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
4595 // AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
4596 // AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
4597 // AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
4599 // D (emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
4600 // AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
4601 // AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
4602 // AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
4605 // Right uses DPTR unless left or result is an AOP_STR; however,
4606 // if right is an AOP_STR, it must use DPTR regardless.
4607 if ((AOP_IS_STR (IC_LEFT (ic)) || AOP_IS_STR (IC_RESULT (ic)))
4608 && !AOP_IS_STR (IC_RIGHT (ic)))
4617 aopOp (IC_RIGHT(ic), ic, FALSE, useDp2);
4619 // if the right used DPTR, left MUST use DPTR2.
4620 // if the right used DPTR2, left MUST use DPTR.
4621 // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
4622 // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
4623 // enabling us to assign DPTR to result.
4625 if (AOP_USESDPTR (IC_RIGHT (ic)))
4629 else if (AOP_USESDPTR2 (IC_RIGHT (ic)))
4635 if (AOP_IS_STR (IC_RESULT (ic)) && !AOP_IS_STR (IC_LEFT (ic)))
4645 aopOp (IC_LEFT (ic), ic, FALSE, useDp2);
4648 // We've op'd the left & right. So, if left or right are the same operand as result,
4649 // we know aopOp will succeed, and we can just do it & bail.
4650 if (isOperandEqual (IC_LEFT (ic), IC_RESULT (ic)))
4652 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4655 if (isOperandEqual (IC_RIGHT (ic), IC_RESULT (ic)))
4657 // D (emitcode(";", "aopOp3: (left | right) & result equal"));
4658 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4662 // Operands may be equivalent (but not equal) if they share a spill location. If
4663 // so, use the same DPTR or DPTR2.
4664 if (operandsEqu (IC_LEFT (ic), IC_RESULT (ic)))
4666 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4669 if (operandsEqu (IC_RIGHT (ic), IC_RESULT (ic)))
4671 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4675 // Note which dptrs are currently in use.
4676 dp1InUse = AOP_USESDPTR (IC_LEFT (ic)) || AOP_USESDPTR (IC_RIGHT (ic));
4677 dp2InUse = AOP_USESDPTR2 (IC_LEFT (ic)) || AOP_USESDPTR2 (IC_RIGHT (ic));
4679 // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot
4681 if (dp1InUse && AOP_IS_STR (IC_RESULT (ic)))
4686 // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
4687 if (dp2InUse && AOP_IS_DPTRn (IC_RESULT (ic)))
4692 // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck
4693 if (dp1InUse && dp2InUse && isOperandInFarSpace (IC_RESULT (ic)))
4698 aopOp (IC_RESULT (ic), ic, TRUE, dp1InUse);
4700 // Some sanity checking...
4701 if (dp1InUse && AOP_USESDPTR (IC_RESULT (ic)))
4704 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
4705 __FILE__, __LINE__, ic->filename, ic->lineno);
4706 emitcode(";", ">>> unexpected DPTR here.");
4709 if (dp2InUse && AOP_USESDPTR2 (IC_RESULT (ic)))
4712 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
4713 __FILE__, __LINE__, ic->filename, ic->lineno);
4714 emitcode(";", ">>> unexpected DPTR2 here.");
4720 // Macro to aopOp all three operands of an ic. If this cannot be done,
4721 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
4722 // will be set TRUE. The caller must then handle the case specially, noting
4723 // that the IC_RESULT operand is not aopOp'd.
4725 #define AOP_OP_3_NOFATAL(ic, rc) \
4726 do { rc = !aopOp3(ic); } while (0)
4728 // aopOp the left & right operands of an ic.
4729 #define AOP_OP_2(ic) \
4730 aopOp (IC_RIGHT (ic), ic, FALSE, AOP_IS_STR (IC_LEFT (ic))); \
4731 aopOp (IC_LEFT (ic), ic, FALSE, AOP_USESDPTR (IC_RIGHT (ic)));
4733 // convienience macro.
4734 #define AOP_SET_LOCALS(ic) \
4735 left = IC_LEFT(ic); \
4736 right = IC_RIGHT(ic); \
4737 result = IC_RESULT(ic);
4740 // Given an integer value of pushedSize bytes on the stack,
4741 // adjust it to be resultSize bytes, either by discarding
4742 // the most significant bytes or by zero-padding.
4744 // On exit from this macro, pushedSize will have been adjusted to
4745 // equal resultSize, and ACC may be trashed.
4746 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
4747 /* If the pushed data is bigger than the result, \
4748 * simply discard unused bytes. Icky, but works. \
4750 while (pushedSize > resultSize) \
4752 D (emitcode (";", "discarding unused result byte.")); \
4753 emitcode ("pop", "acc"); \
4756 if (pushedSize < resultSize) \
4758 emitcode ("clr", "a"); \
4759 /* Conversly, we haven't pushed enough here. \
4760 * just zero-pad, and all is well. \
4762 while (pushedSize < resultSize) \
4764 emitcode("push", "acc"); \
4768 assert(pushedSize == resultSize);
4770 /*-----------------------------------------------------------------*/
4771 /* genPlus - generates code for addition */
4772 /*-----------------------------------------------------------------*/
4774 genPlus (iCode * ic)
4776 int size, offset = 0;
4779 bool swappedLR = FALSE;
4781 D (emitcode (";", "genPlus"));
4783 /* special cases :- */
4784 if ( AOP_IS_STR (IC_LEFT (ic)) &&
4785 isOperandLiteral (IC_RIGHT (ic)) && OP_SYMBOL (IC_RESULT (ic))->ruonly) {
4786 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
4787 size = (int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4789 while (size--) emitcode ("inc","dptr");
4791 emitcode ("mov", "a,dpl");
4792 emitcode ("add", "a,#!constbyte", size & 0xff);
4793 emitcode ("mov", "dpl,a");
4794 emitcode ("mov", "a,dph");
4795 emitcode ("addc", "a,#!constbyte", (size >> 8) & 0xff);
4796 emitcode ("mov", "dph,a");
4797 emitcode ("mov", "a,dpx");
4798 emitcode ("addc", "a,#!constbyte", (size >> 16) & 0xff);
4799 emitcode ("mov", "dpx,a");
4801 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4804 if ( IS_SYMOP (IC_LEFT (ic)) &&
4805 OP_SYMBOL (IC_LEFT (ic))->remat &&
4806 isOperandInFarSpace (IC_RIGHT (ic))) {
4807 operand *op = IC_RIGHT(ic);
4808 IC_RIGHT(ic) = IC_LEFT(ic);
4812 AOP_OP_3_NOFATAL (ic, pushResult);
4816 D (emitcode (";", "genPlus: must push result: 3 ops in far space"));
4821 /* if literal, literal on the right or
4822 if left requires ACC or right is already
4824 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4825 ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic)))) ||
4826 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4828 operand *t = IC_RIGHT (ic);
4829 IC_RIGHT (ic) = IC_LEFT (ic);
4832 D (emitcode (";", "Swapped plus args."));
4835 /* if both left & right are in bit
4837 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4838 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4844 /* if left in bit space & right literal */
4845 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4846 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4848 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4849 /* if result in bit space */
4850 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4852 if (ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4853 emitcode ("cpl", "c");
4854 outBitC (IC_RESULT (ic));
4858 size = getDataSize (IC_RESULT (ic));
4859 _startLazyDPSEvaluation ();
4862 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4863 emitcode ("addc", "a,%s", zero);
4864 aopPut (IC_RESULT (ic), "a", offset++);
4866 _endLazyDPSEvaluation ();
4871 /* if I can do an increment instead
4872 of add then GOOD for ME */
4873 if (genPlusIncr (ic) == TRUE)
4875 D (emitcode (";", "did genPlusIncr"));
4880 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4882 _startLazyDPSEvaluation ();
4885 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4887 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
4889 emitcode ("add", "a,%s",
4890 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4892 emitcode ("addc", "a,%s",
4893 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4897 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4899 /* right is going to use ACC or we would have taken the
4902 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4904 D(emitcode(";", "+ AOP_ACC special case."););
4905 emitcode("xch", "a, %s", DP2_RESULT_REG);
4907 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4910 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4913 emitcode("add", "a, %s", DP2_RESULT_REG);
4917 emitcode ("add", "a,%s",
4918 aopGet (IC_LEFT(ic), offset, FALSE, FALSE,
4924 emitcode ("addc", "a,%s",
4925 aopGet (IC_LEFT (ic), offset, FALSE, FALSE,
4931 aopPut (IC_RESULT (ic), "a", offset);
4935 emitcode ("push", "acc");
4939 _endLazyDPSEvaluation ();
4943 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4945 size = getDataSize (IC_LEFT (ic));
4946 rSize = getDataSize (IC_RESULT (ic));
4948 ADJUST_PUSHED_RESULT(size, rSize);
4950 _startLazyDPSEvaluation ();
4953 emitcode ("pop", "acc");
4954 aopPut (IC_RESULT (ic), "a", size);
4956 _endLazyDPSEvaluation ();
4959 adjustArithmeticResult (ic);
4962 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4965 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4966 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4970 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4971 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4975 /*-----------------------------------------------------------------*/
4976 /* genMinusDec :- does subtraction with decrement if possible */
4977 /*-----------------------------------------------------------------*/
4979 genMinusDec (iCode * ic)
4981 unsigned int icount;
4982 unsigned int size = getDataSize (IC_RESULT (ic));
4984 /* will try to generate an increment */
4985 /* if the right side is not a literal
4987 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4990 /* if the literal value of the right hand side
4991 is greater than 4 then it is not worth it */
4992 if ((icount = (unsigned int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4995 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4996 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4998 emitcode("dec","%s",aopGet(IC_RESULT(ic),0,FALSE,FALSE,NULL));
5002 /* if decrement 16 bits in register */
5003 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
5004 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
5005 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
5014 /* If the next instruction is a goto and the goto target
5015 * is <= 5 instructions previous to this, we can generate
5016 * jumps straight to that target.
5018 if (ic->next && ic->next->op == GOTO
5019 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
5022 D (emitcode (";", "tail decrement optimized (range %d)", labelRange));
5023 tlbl = IC_LABEL (ic->next);
5028 tlbl = newiTempLabel (NULL);
5032 l = aopGet (IC_RESULT (ic), LSB, FALSE, FALSE, NULL);
5033 emitcode ("dec", "%s", l);
5035 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
5036 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
5037 IS_AOP_PREG (IC_RESULT (ic)))
5039 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
5043 emitcode ("mov", "a,#!constbyte",0xff);
5044 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
5046 l = aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE, NULL);
5047 emitcode ("dec", "%s", l);
5050 if (!strcmp(l, "acc"))
5052 emitcode("jnz", "!tlabel", tlbl->key + 100);
5054 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
5055 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
5056 IS_AOP_PREG (IC_RESULT (ic)))
5058 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
5062 emitcode ("mov", "a,#!constbyte",0xff);
5063 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
5065 l = aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE, NULL);
5066 emitcode ("dec", "%s", l);
5070 if (!strcmp(l, "acc"))
5072 emitcode("jnz", "!tlabel", tlbl->key + 100);
5074 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
5075 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
5076 IS_AOP_PREG (IC_RESULT (ic)))
5078 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
5082 emitcode ("mov", "a,#!constbyte",0xff);
5083 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
5085 l = aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE, NULL);
5086 emitcode ("dec", "%s", l);
5095 /* if the sizes are greater than 1 then we cannot */
5096 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
5097 AOP_SIZE (IC_LEFT (ic)) > 1)
5100 /* we can if the aops of the left & result match or
5101 if they are in registers and the registers are the
5104 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
5105 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
5106 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
5110 if (aopGetUsesAcc (IC_LEFT (ic), 0))
5112 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL));
5117 l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL);
5120 _startLazyDPSEvaluation ();
5123 emitcode ("dec", "%s", l);
5125 _endLazyDPSEvaluation ();
5127 if (AOP_NEEDSACC (IC_RESULT (ic)))
5128 aopPut (IC_RESULT (ic), "a", 0);
5136 /*-----------------------------------------------------------------*/
5137 /* addSign - complete with sign */
5138 /*-----------------------------------------------------------------*/
5140 addSign (operand * result, int offset, int sign)
5142 int size = (getDataSize (result) - offset);
5145 _startLazyDPSEvaluation();
5148 emitcode ("rlc", "a");
5149 emitcode ("subb", "a,acc");
5152 aopPut (result, "a", offset++);
5159 aopPut (result, zero, offset++);
5162 _endLazyDPSEvaluation();
5166 /*-----------------------------------------------------------------*/
5167 /* genMinusBits - generates code for subtraction of two bits */
5168 /*-----------------------------------------------------------------*/
5170 genMinusBits (iCode * ic)
5172 symbol *lbl = newiTempLabel (NULL);
5174 D (emitcode (";", "genMinusBits"));
5176 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
5178 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
5179 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
5180 emitcode ("cpl", "c");
5182 outBitC (IC_RESULT (ic));
5186 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
5187 emitcode ("subb", "a,acc");
5188 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
5189 emitcode ("inc", "a");
5191 aopPut (IC_RESULT (ic), "a", 0);
5192 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
5196 /*-----------------------------------------------------------------*/
5197 /* genMinus - generates code for subtraction */
5198 /*-----------------------------------------------------------------*/
5200 genMinus (iCode * ic)
5202 int size, offset = 0;
5207 D (emitcode (";", "genMinus"));
5209 AOP_OP_3_NOFATAL(ic, pushResult);
5213 /* special cases :- */
5214 /* if both left & right are in bit space */
5215 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
5216 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
5222 /* if I can do an decrement instead
5223 of subtract then GOOD for ME */
5224 if (genMinusDec (ic) == TRUE)
5229 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
5231 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
5237 lit = (long) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5242 /* if literal, add a,#-lit, else normal subb */
5243 _startLazyDPSEvaluation ();
5245 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
5246 if (AOP_USESDPTR(IC_RIGHT(ic))) {
5247 emitcode ("mov","b,%s",
5248 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
5249 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
5250 emitcode ("subb","a,b");
5252 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
5253 emitcode ("subb", "a,%s",
5254 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE,
5258 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
5259 /* first add without previous c */
5261 if (!size && lit==-1) {
5262 emitcode ("dec", "a");
5264 emitcode ("add", "a,#!constbyte",
5265 (unsigned int) (lit & 0x0FFL));
5268 emitcode ("addc", "a,#!constbyte",
5269 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5274 emitcode ("push", "acc");
5276 aopPut (IC_RESULT (ic), "a", offset);
5280 _endLazyDPSEvaluation ();
5284 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
5286 size = getDataSize (IC_LEFT (ic));
5287 rSize = getDataSize (IC_RESULT (ic));
5289 ADJUST_PUSHED_RESULT(size, rSize);
5291 _startLazyDPSEvaluation ();
5294 emitcode ("pop", "acc");
5295 aopPut (IC_RESULT (ic), "a", size);
5297 _endLazyDPSEvaluation ();
5300 adjustArithmeticResult (ic);
5303 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5304 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5305 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5309 /*-----------------------------------------------------------------*/
5310 /* genMultbits :- multiplication of bits */
5311 /*-----------------------------------------------------------------*/
5313 genMultbits (operand * left,
5318 D (emitcode (";", "genMultbits"));
5320 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5321 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5322 aopOp(result, ic, TRUE, FALSE);
5326 /*-----------------------------------------------------------------*/
5327 /* genMultOneByte : 8*8=8/16 bit multiplication */
5328 /*-----------------------------------------------------------------*/
5330 genMultOneByte (operand * left,
5337 bool runtimeSign, compiletimeSign;
5338 bool lUnsigned, rUnsigned, pushedB;
5340 /* (if two literals: the value is computed before) */
5341 /* if one literal, literal on the right */
5342 if (AOP_TYPE (left) == AOP_LIT)
5347 /* emitcode (";", "swapped left and right"); */
5349 /* if no literal, unsigned on the right: shorter code */
5350 if ( AOP_TYPE (right) != AOP_LIT
5351 && SPEC_USIGN (getSpec (operandType (left))))
5358 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5359 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5363 if ((lUnsigned && rUnsigned)
5364 /* sorry, I don't know how to get size
5365 without calling aopOp (result,...);
5366 see Feature Request */
5367 /* || size == 1 */ ) /* no, this is not a bug; with a 1 byte result there's
5368 no need to take care about the signedness! */
5370 /* just an unsigned 8 * 8 = 8 multiply
5372 /* emitcode (";","unsigned"); */
5373 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
5374 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
5375 emitcode ("mul", "ab");
5378 aopOp (result, ic, TRUE, FALSE);
5379 size = AOP_SIZE (result);
5381 if (size < 1 || size > 2)
5383 /* this should never happen */
5384 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
5385 size, __FILE__, lineno);
5389 aopPut (result, "a", 0);
5392 aopPut (result, "b", 1);
5398 /* we have to do a signed multiply */
5399 /* emitcode (";", "signed"); */
5401 /* now sign adjust for both left & right */
5403 /* let's see what's needed: */
5404 /* apply negative sign during runtime */
5405 runtimeSign = FALSE;
5406 /* negative sign from literals */
5407 compiletimeSign = FALSE;
5411 if (AOP_TYPE(left) == AOP_LIT)
5413 /* signed literal */
5414 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5416 compiletimeSign = TRUE;
5419 /* signed but not literal */
5425 if (AOP_TYPE(right) == AOP_LIT)
5427 /* signed literal */
5428 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
5430 compiletimeSign ^= TRUE;
5433 /* signed but not literal */
5437 /* initialize F0, which stores the runtime sign */
5440 if (compiletimeSign)
5441 emitcode ("setb", "F0"); /* set sign flag */
5443 emitcode ("clr", "F0"); /* reset sign flag */
5446 /* save the signs of the operands */
5447 if (AOP_TYPE(right) == AOP_LIT)
5449 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
5451 if (!rUnsigned && val < 0)
5452 emitcode ("mov", "b,#!constbyte", -val);
5454 emitcode ("mov", "b,#!constbyte", (unsigned char) val);
5456 else /* ! literal */
5458 if (rUnsigned) /* emitcode (";", "signed"); */
5459 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
5462 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
5463 lbl = newiTempLabel (NULL);
5464 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5465 emitcode ("cpl", "F0"); /* complement sign flag */
5466 emitcode ("cpl", "a"); /* 2's complement */
5467 emitcode ("inc", "a");
5469 emitcode ("mov", "b,a");
5473 if (AOP_TYPE(left) == AOP_LIT)
5475 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5477 if (!lUnsigned && val < 0)
5478 emitcode ("mov", "a,#!constbyte", -val);
5480 emitcode ("mov", "a,#!constbyte", (unsigned char) val);
5482 else /* ! literal */
5484 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
5486 if (!lUnsigned) /* emitcode (";", "signed"); */
5488 lbl = newiTempLabel (NULL);
5489 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5490 emitcode ("cpl", "F0"); /* complement sign flag */
5491 emitcode ("cpl", "a"); /* 2's complement */
5492 emitcode ("inc", "a");
5497 /* now the multiplication */
5498 emitcode ("mul", "ab");
5500 aopOp(result, ic, TRUE, FALSE);
5501 size = AOP_SIZE (result);
5503 if (size < 1 || size > 2)
5505 /* this should never happen */
5506 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
5507 size, __FILE__, lineno);
5511 if (runtimeSign || compiletimeSign)
5513 lbl = newiTempLabel (NULL);
5515 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5516 emitcode ("cpl", "a"); /* lsb 2's complement */
5518 emitcode ("inc", "a"); /* inc doesn't set carry flag */
5521 emitcode ("add", "a,#0x01"); /* this sets carry flag */
5522 emitcode ("xch", "a,b");
5523 emitcode ("cpl", "a"); /* msb 2's complement */
5524 emitcode ("addc", "a,#0x00");
5525 emitcode ("xch", "a,b");
5529 aopPut (result, "a", 0);
5532 aopPut (result, "b", 1);
5537 /*-----------------------------------------------------------------*/
5538 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
5539 /*-----------------------------------------------------------------*/
5540 static void genMultTwoByte (operand *left, operand *right,
5541 operand *result, iCode *ic)
5543 sym_link *retype = getSpec(operandType(right));
5544 sym_link *letype = getSpec(operandType(left));
5545 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5548 if (AOP_TYPE (left) == AOP_LIT) {
5553 /* save EA bit in F1 */
5554 lbl = newiTempLabel(NULL);
5555 emitcode ("setb","F1");
5556 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5557 emitcode ("clr","F1");
5560 /* load up MB with right */
5562 emitcode("clr","F0");
5563 if (AOP_TYPE(right) == AOP_LIT) {
5564 int val=(int) ulFromVal (AOP (right)->aopu.aop_lit);
5566 emitcode("setb","F0");
5569 emitcode ("mov","mb,#!constbyte",val & 0xff);
5570 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5572 lbl = newiTempLabel(NULL);
5573 emitcode ("mov","b,%s",aopGet(right,0,FALSE,FALSE,NULL));
5574 emitcode ("mov","a,%s",aopGet(right,1,FALSE,FALSE,NULL));
5575 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5576 emitcode ("xch", "a,b");
5577 emitcode ("cpl","a");
5578 emitcode ("add", "a,#1");
5579 emitcode ("xch", "a,b");
5580 emitcode ("cpl", "a"); // msb
5581 emitcode ("addc", "a,#0");
5582 emitcode ("setb","F0");
5584 emitcode ("mov","mb,b");
5585 emitcode ("mov","mb,a");
5588 emitcode ("mov","mb,%s",aopGet(right,0,FALSE,FALSE,NULL));
5589 emitcode ("mov","mb,%s",aopGet(right,1,FALSE,FALSE,NULL));
5591 /* load up MA with left */
5593 lbl = newiTempLabel(NULL);
5594 emitcode ("mov","b,%s",aopGet(left,0,FALSE,FALSE,NULL));
5595 emitcode ("mov","a,%s",aopGet(left,1,FALSE,FALSE,NULL));
5596 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5597 emitcode ("xch", "a,b");
5598 emitcode ("cpl","a");
5599 emitcode ("add", "a,#1");
5600 emitcode ("xch", "a,b");
5601 emitcode ("cpl", "a"); // msb
5602 emitcode ("addc","a,#0");
5603 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5604 emitcode ("setb","F0");
5606 emitcode ("mov","ma,b");
5607 emitcode ("mov","ma,a");
5609 emitcode ("mov","ma,%s",aopGet(left,0,FALSE,FALSE,NULL));
5610 emitcode ("mov","ma,%s",aopGet(left,1,FALSE,FALSE,NULL));
5612 /* wait for multiplication to finish */
5613 lbl = newiTempLabel(NULL);
5615 emitcode("mov","a,mcnt1");
5616 emitcode("anl","a,#!constbyte",0x80);
5617 emitcode("jnz","!tlabel",lbl->key+100);
5619 freeAsmop (left, NULL, ic, TRUE);
5620 freeAsmop (right, NULL, ic,TRUE);
5621 aopOp(result, ic, TRUE, FALSE);
5623 /* if unsigned then simple */
5625 emitcode ("mov","a,ma");
5626 if (AOP_SIZE(result) >= 4) aopPut(result,"a",3);
5627 emitcode ("mov","a,ma");
5628 if (AOP_SIZE(result) >= 3) aopPut(result,"a",2);
5629 aopPut(result,"ma",1);
5630 aopPut(result,"ma",0);
5632 emitcode("push","ma");
5633 emitcode("push","ma");
5634 emitcode("push","ma");
5636 /* negate result if needed */
5637 lbl = newiTempLabel(NULL);
5638 emitcode("jnb","F0,!tlabel",lbl->key+100);
5639 emitcode("cpl","a");
5640 emitcode("add","a,#1");
5642 if (AOP_TYPE(result) == AOP_ACC)
5644 D (emitcode(";", "ACC special case."));
5645 /* We know result is the only live aop, and
5646 * it's obviously not a DPTR2, so AP is available.
5648 emitcode("mov", "%s,acc", DP2_RESULT_REG);
5652 aopPut(result,"a",0);
5655 emitcode("pop","acc");
5656 lbl = newiTempLabel(NULL);
5657 emitcode("jnb","F0,!tlabel",lbl->key+100);
5658 emitcode("cpl","a");
5659 emitcode("addc","a,#0");
5661 aopPut(result,"a",1);
5662 emitcode("pop","acc");
5663 if (AOP_SIZE(result) >= 3) {
5664 lbl = newiTempLabel(NULL);
5665 emitcode("jnb","F0,!tlabel",lbl->key+100);
5666 emitcode("cpl","a");
5667 emitcode("addc","a,#0");
5669 aopPut(result,"a",2);
5671 emitcode("pop","acc");
5672 if (AOP_SIZE(result) >= 4) {
5673 lbl = newiTempLabel(NULL);
5674 emitcode("jnb","F0,!tlabel",lbl->key+100);
5675 emitcode("cpl","a");
5676 emitcode("addc","a,#0");
5678 aopPut(result,"a",3);
5680 if (AOP_TYPE(result) == AOP_ACC)
5682 /* We stashed the result away above. */
5683 emitcode("mov", "acc,%s", DP2_RESULT_REG);
5687 freeAsmop (result, NULL, ic, TRUE);
5689 /* restore EA bit in F1 */
5690 lbl = newiTempLabel(NULL);
5691 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5692 emitcode ("setb","EA");
5697 /*-----------------------------------------------------------------*/
5698 /* genMult - generates code for multiplication */
5699 /*-----------------------------------------------------------------*/
5701 genMult (iCode * ic)
5703 operand *left = IC_LEFT (ic);
5704 operand *right = IC_RIGHT (ic);
5705 operand *result = IC_RESULT (ic);
5707 D (emitcode (";", "genMult"));
5709 /* assign the asmops */
5712 /* special cases first */
5714 if (AOP_TYPE (left) == AOP_CRY &&
5715 AOP_TYPE (right) == AOP_CRY)
5717 genMultbits (left, right, result, ic);
5721 /* if both are of size == 1 */
5722 if (AOP_SIZE (left) == 1 &&
5723 AOP_SIZE (right) == 1)
5725 genMultOneByte (left, right, result, ic);
5729 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5730 /* use the ds390 ARITHMETIC accel UNIT */
5731 genMultTwoByte (left, right, result, ic);
5734 /* should have been converted to function call */
5738 freeAsmop (result, NULL, ic, TRUE);
5739 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5740 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5743 /*-----------------------------------------------------------------*/
5744 /* genDivbits :- division of bits */
5745 /*-----------------------------------------------------------------*/
5747 genDivbits (operand * left,
5755 D(emitcode (";", "genDivbits"));
5759 /* the result must be bit */
5760 LOAD_AB_FOR_DIV (left, right, l);
5761 emitcode ("div", "ab");
5762 emitcode ("rrc", "a");
5763 aopOp(result, ic, TRUE, FALSE);
5767 aopPut (result, "c", 0);
5770 /*-----------------------------------------------------------------*/
5771 /* genDivOneByte : 8 bit division */
5772 /*-----------------------------------------------------------------*/
5774 genDivOneByte (operand * left,
5779 bool lUnsigned, rUnsigned, pushedB;
5780 bool runtimeSign, compiletimeSign;
5785 D(emitcode (";", "genDivOneByte"));
5788 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5789 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5793 /* signed or unsigned */
5794 if (lUnsigned && rUnsigned)
5796 /* unsigned is easy */
5797 LOAD_AB_FOR_DIV (left, right, l);
5798 emitcode ("div", "ab");
5801 aopOp (result, ic, TRUE, FALSE);
5802 aopPut (result, "a", 0);
5805 size = AOP_SIZE (result) - 1;
5808 aopPut (result, zero, offset++);
5814 /* signed is a little bit more difficult */
5816 /* now sign adjust for both left & right */
5818 /* let's see what's needed: */
5819 /* apply negative sign during runtime */
5820 runtimeSign = FALSE;
5821 /* negative sign from literals */
5822 compiletimeSign = FALSE;
5826 if (AOP_TYPE(left) == AOP_LIT)
5828 /* signed literal */
5829 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5831 compiletimeSign = TRUE;
5834 /* signed but not literal */
5840 if (AOP_TYPE(right) == AOP_LIT)
5842 /* signed literal */
5843 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
5845 compiletimeSign ^= TRUE;
5848 /* signed but not literal */
5852 /* initialize F0, which stores the runtime sign */
5855 if (compiletimeSign)
5856 emitcode ("setb", "F0"); /* set sign flag */
5858 emitcode ("clr", "F0"); /* reset sign flag */
5861 /* save the signs of the operands */
5862 if (AOP_TYPE(right) == AOP_LIT)
5864 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
5866 if (!rUnsigned && val < 0)
5867 emitcode ("mov", "b,#0x%02x", -val);
5869 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5871 else /* ! literal */
5874 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
5877 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
5878 lbl = newiTempLabel (NULL);
5879 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5880 emitcode ("cpl", "F0"); /* complement sign flag */
5881 emitcode ("cpl", "a"); /* 2's complement */
5882 emitcode ("inc", "a");
5884 emitcode ("mov", "b,a");
5888 if (AOP_TYPE(left) == AOP_LIT)
5890 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5892 if (!lUnsigned && val < 0)
5893 emitcode ("mov", "a,#0x%02x", -val);
5895 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5897 else /* ! literal */
5899 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
5903 lbl = newiTempLabel (NULL);
5904 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5905 emitcode ("cpl", "F0"); /* complement sign flag */
5906 emitcode ("cpl", "a"); /* 2's complement */
5907 emitcode ("inc", "a");
5912 /* now the division */
5913 emitcode ("nop", "; workaround for DS80C390 div bug.");
5914 emitcode ("div", "ab");
5916 if (runtimeSign || compiletimeSign)
5918 lbl = newiTempLabel (NULL);
5920 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5921 emitcode ("cpl", "a"); /* lsb 2's complement */
5922 emitcode ("inc", "a");
5926 aopOp (result, ic, TRUE, FALSE);
5927 size = AOP_SIZE (result) - 1;
5931 /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
5932 then the result will be in b, a */
5933 emitcode ("mov", "b,a"); /* 1 */
5934 /* msb is 0x00 or 0xff depending on the sign */
5937 emitcode ("mov", "c,F0");
5938 emitcode ("subb", "a,acc");
5939 emitcode ("xch", "a,b"); /* 2 */
5941 aopPut (result, "b", offset++); /* write msb's */
5943 else /* compiletimeSign */
5945 aopPut (result, "#0xff", offset++); /* write msb's */
5947 aopPut (result, "a", 0); /* 3: write lsb */
5952 aopOp(result, ic, TRUE, FALSE);
5953 size = AOP_SIZE (result) - 1;
5955 aopPut (result, "a", 0);
5957 aopPut (result, zero, offset++);
5963 /*-----------------------------------------------------------------*/
5964 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
5965 /*-----------------------------------------------------------------*/
5966 static void genDivTwoByte (operand *left, operand *right,
5967 operand *result, iCode *ic)
5969 sym_link *retype = getSpec(operandType(right));
5970 sym_link *letype = getSpec(operandType(left));
5971 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5974 /* save EA bit in F1 */
5975 lbl = newiTempLabel(NULL);
5976 emitcode ("setb","F1");
5977 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5978 emitcode ("clr","F1");
5981 /* load up MA with left */
5983 emitcode("clr","F0");
5984 lbl = newiTempLabel(NULL);
5985 emitcode ("mov","b,%s",aopGet(left,0,FALSE,FALSE,NULL));
5986 emitcode ("mov","a,%s",aopGet(left,1,FALSE,FALSE,NULL));
5987 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5988 emitcode ("xch", "a,b");
5989 emitcode ("cpl","a");
5990 emitcode ("add", "a,#1");
5991 emitcode ("xch", "a,b");
5992 emitcode ("cpl", "a"); // msb
5993 emitcode ("addc","a,#0");
5994 emitcode ("setb","F0");
5996 emitcode ("mov","ma,b");
5997 emitcode ("mov","ma,a");
5999 emitcode ("mov","ma,%s",aopGet(left,0,FALSE,FALSE,NULL));
6000 emitcode ("mov","ma,%s",aopGet(left,1,FALSE,FALSE,NULL));
6003 /* load up MB with right */
6005 if (AOP_TYPE(right) == AOP_LIT) {
6006 int val=(int) ulFromVal (AOP (right)->aopu.aop_lit);
6008 lbl = newiTempLabel(NULL);
6009 emitcode ("jbc","F0,!tlabel",lbl->key+100);
6010 emitcode("setb","F0");
6014 emitcode ("mov","mb,#!constbyte",val & 0xff);
6015 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
6017 lbl = newiTempLabel(NULL);
6018 emitcode ("mov","b,%s",aopGet(right,0,FALSE,FALSE,NULL));
6019 emitcode ("mov","a,%s",aopGet(right,1,FALSE,FALSE,NULL));
6020 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
6021 emitcode ("xch", "a,b");
6022 emitcode ("cpl","a");
6023 emitcode ("add", "a,#1");
6024 emitcode ("xch", "a,b");
6025 emitcode ("cpl", "a"); // msb
6026 emitcode ("addc", "a,#0");
6027 emitcode ("jbc","F0,!tlabel",lbl->key+100);
6028 emitcode ("setb","F0");
6030 emitcode ("mov","mb,b");
6031 emitcode ("mov","mb,a");
6034 emitcode ("mov","mb,%s",aopGet(right,0,FALSE,FALSE,NULL));
6035 emitcode ("mov","mb,%s",aopGet(right,1,FALSE,FALSE,NULL));
6038 /* wait for multiplication to finish */
6039 lbl = newiTempLabel(NULL);
6041 emitcode("mov","a,mcnt1");
6042 emitcode("anl","a,#!constbyte",0x80);
6043 emitcode("jnz","!tlabel",lbl->key+100);
6045 freeAsmop (left, NULL, ic, TRUE);
6046 freeAsmop (right, NULL, ic,TRUE);
6047 aopOp(result, ic, TRUE, FALSE);
6049 /* if unsigned then simple */
6051 aopPut(result,"ma",1);
6052 aopPut(result,"ma",0);
6054 emitcode("push","ma");
6056 /* negate result if needed */
6057 lbl = newiTempLabel(NULL);
6058 emitcode("jnb","F0,!tlabel",lbl->key+100);
6059 emitcode("cpl","a");
6060 emitcode("add","a,#1");
6062 aopPut(result,"a",0);
6063 emitcode("pop","acc");
6064 lbl = newiTempLabel(NULL);
6065 emitcode("jnb","F0,!tlabel",lbl->key+100);
6066 emitcode("cpl","a");
6067 emitcode("addc","a,#0");
6069 aopPut(result,"a",1);
6071 freeAsmop (result, NULL, ic, TRUE);
6072 /* restore EA bit in F1 */
6073 lbl = newiTempLabel(NULL);
6074 emitcode ("jnb","F1,!tlabel",lbl->key+100);
6075 emitcode ("setb","EA");
6080 /*-----------------------------------------------------------------*/
6081 /* genDiv - generates code for division */
6082 /*-----------------------------------------------------------------*/
6086 operand *left = IC_LEFT (ic);
6087 operand *right = IC_RIGHT (ic);
6088 operand *result = IC_RESULT (ic);
6090 D (emitcode (";", "genDiv"));
6092 /* assign the amsops */
6095 /* special cases first */
6097 if (AOP_TYPE (left) == AOP_CRY &&
6098 AOP_TYPE (right) == AOP_CRY)
6100 genDivbits (left, right, result, ic);
6104 /* if both are of size == 1 */
6105 if (AOP_SIZE (left) == 1 &&
6106 AOP_SIZE (right) == 1)
6108 genDivOneByte (left, right, result, ic);
6112 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
6113 /* use the ds390 ARITHMETIC accel UNIT */
6114 genDivTwoByte (left, right, result, ic);
6117 /* should have been converted to function call */
6120 freeAsmop (result, NULL, ic, TRUE);
6121 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6122 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6125 /*-----------------------------------------------------------------*/
6126 /* genModbits :- modulus of bits */
6127 /*-----------------------------------------------------------------*/
6129 genModbits (operand * left,
6137 D (emitcode (";", "genModbits"));
6141 /* the result must be bit */
6142 LOAD_AB_FOR_DIV (left, right, l);
6143 emitcode ("div", "ab");
6144 emitcode ("mov", "a,b");
6145 emitcode ("rrc", "a");
6146 aopOp(result, ic, TRUE, FALSE);
6150 aopPut (result, "c", 0);
6153 /*-----------------------------------------------------------------*/
6154 /* genModOneByte : 8 bit modulus */
6155 /*-----------------------------------------------------------------*/
6157 genModOneByte (operand * left,
6162 bool lUnsigned, rUnsigned, pushedB;
6163 bool runtimeSign, compiletimeSign;
6168 D (emitcode (";", "genModOneByte"));
6171 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
6172 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
6176 /* signed or unsigned */
6177 if (lUnsigned && rUnsigned)
6179 /* unsigned is easy */
6180 LOAD_AB_FOR_DIV (left, right, l);
6181 emitcode ("div", "ab");
6182 aopOp (result, ic, TRUE, FALSE);
6183 aopPut (result, "b", 0);
6185 for (size = AOP_SIZE (result) - 1; size--;)
6186 aopPut (result, zero, offset++);
6192 /* signed is a little bit more difficult */
6194 /* now sign adjust for both left & right */
6196 /* modulus: sign of the right operand has no influence on the result! */
6197 if (AOP_TYPE(right) == AOP_LIT)
6199 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
6201 if (!rUnsigned && val < 0)
6202 emitcode ("mov", "b,#0x%02x", -val);
6204 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
6206 else /* not literal */
6209 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
6212 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
6213 lbl = newiTempLabel (NULL);
6214 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
6215 emitcode ("cpl", "a"); /* 2's complement */
6216 emitcode ("inc", "a");
6218 emitcode ("mov", "b,a");
6222 /* let's see what's needed: */
6223 /* apply negative sign during runtime */
6224 runtimeSign = FALSE;
6225 /* negative sign from literals */
6226 compiletimeSign = FALSE;
6228 /* sign adjust left side */
6229 if (AOP_TYPE(left) == AOP_LIT)
6231 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
6233 if (!lUnsigned && val < 0)
6235 compiletimeSign = TRUE; /* set sign flag */
6236 emitcode ("mov", "a,#0x%02x", -val);
6239 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
6241 else /* ! literal */
6243 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
6248 emitcode ("clr", "F0"); /* clear sign flag */
6250 lbl = newiTempLabel (NULL);
6251 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
6252 emitcode ("setb", "F0"); /* set sign flag */
6253 emitcode ("cpl", "a"); /* 2's complement */
6254 emitcode ("inc", "a");
6259 /* now the modulus */
6260 emitcode ("nop", "; workaround for DS80C390 div bug.");
6261 emitcode ("div", "ab");
6263 if (runtimeSign || compiletimeSign)
6265 emitcode ("mov", "a,b");
6266 lbl = newiTempLabel (NULL);
6268 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
6269 emitcode ("cpl", "a"); /* lsb 2's complement */
6270 emitcode ("inc", "a");
6274 aopOp (result, ic, TRUE, FALSE);
6275 size = AOP_SIZE (result) - 1;
6279 /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
6280 then the result will be in b, a */
6281 emitcode ("mov", "b,a"); /* 1 */
6282 /* msb is 0x00 or 0xff depending on the sign */
6285 emitcode ("mov", "c,F0");
6286 emitcode ("subb", "a,acc");
6287 emitcode ("xch", "a,b"); /* 2 */
6289 aopPut (result, "b", offset++); /* write msb's */
6291 else /* compiletimeSign */
6293 aopPut (result, "#0xff", offset++); /* write msb's */
6295 aopPut (result, "a", 0); /* 3: write lsb */
6300 aopOp(result, ic, TRUE, FALSE);
6301 size = AOP_SIZE (result) - 1;
6303 aopPut (result, "b", 0);
6305 aopPut (result, zero, offset++);
6311 /*-----------------------------------------------------------------*/
6312 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
6313 /*-----------------------------------------------------------------*/
6314 static void genModTwoByte (operand *left, operand *right,
6315 operand *result, iCode *ic)
6317 sym_link *retype = getSpec(operandType(right));
6318 sym_link *letype = getSpec(operandType(left));
6319 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
6322 /* load up MA with left */
6323 /* save EA bit in F1 */
6324 lbl = newiTempLabel(NULL);
6325 emitcode ("setb","F1");
6326 emitcode ("jbc","EA,!tlabel",lbl->key+100);
6327 emitcode ("clr","F1");
6331 lbl = newiTempLabel(NULL);
6332 emitcode ("mov","b,%s",aopGet(left,0,FALSE,FALSE,NULL));
6333 emitcode ("mov","a,%s",aopGet(left,1,FALSE,FALSE,NULL));
6334 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
6335 emitcode ("xch", "a,b");
6336 emitcode ("cpl","a");
6337 emitcode ("add", "a,#1");
6338 emitcode ("xch", "a,b");
6339 emitcode ("cpl", "a"); // msb
6340 emitcode ("addc","a,#0");
6342 emitcode ("mov","ma,b");
6343 emitcode ("mov","ma,a");
6345 emitcode ("mov","ma,%s",aopGet(left,0,FALSE,FALSE,NULL));
6346 emitcode ("mov","ma,%s",aopGet(left,1,FALSE,FALSE,NULL));
6349 /* load up MB with right */
6351 if (AOP_TYPE(right) == AOP_LIT) {
6352 int val=(int) ulFromVal (AOP (right)->aopu.aop_lit);
6356 emitcode ("mov","mb,#!constbyte",val & 0xff);
6357 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
6359 lbl = newiTempLabel(NULL);
6360 emitcode ("mov","b,%s",aopGet(right,0,FALSE,FALSE,NULL));
6361 emitcode ("mov","a,%s",aopGet(right,1,FALSE,FALSE,NULL));
6362 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
6363 emitcode ("xch", "a,b");
6364 emitcode ("cpl","a");
6365 emitcode ("add", "a,#1");
6366 emitcode ("xch", "a,b");
6367 emitcode ("cpl", "a"); // msb
6368 emitcode ("addc", "a,#0");
6370 emitcode ("mov","mb,b");
6371 emitcode ("mov","mb,a");
6374 emitcode ("mov","mb,%s",aopGet(right,0,FALSE,FALSE,NULL));
6375 emitcode ("mov","mb,%s",aopGet(right,1,FALSE,FALSE,NULL));
6378 /* wait for multiplication to finish */
6379 lbl = newiTempLabel(NULL);
6381 emitcode("mov","a,mcnt1");
6382 emitcode("anl","a,#!constbyte",0x80);
6383 emitcode("jnz","!tlabel",lbl->key+100);
6385 freeAsmop (left, NULL, ic, TRUE);
6386 freeAsmop (right, NULL, ic,TRUE);
6387 aopOp(result, ic, TRUE, FALSE);
6389 aopPut(result,"mb",1);
6390 aopPut(result,"mb",0);
6391 freeAsmop (result, NULL, ic, TRUE);
6393 /* restore EA bit in F1 */
6394 lbl = newiTempLabel(NULL);
6395 emitcode ("jnb","F1,!tlabel",lbl->key+100);
6396 emitcode ("setb","EA");
6400 /*-----------------------------------------------------------------*/
6401 /* genMod - generates code for division */
6402 /*-----------------------------------------------------------------*/
6406 operand *left = IC_LEFT (ic);
6407 operand *right = IC_RIGHT (ic);
6408 operand *result = IC_RESULT (ic);
6410 D (emitcode (";", "genMod"));
6412 /* assign the asmops */
6415 /* special cases first */
6417 if (AOP_TYPE (left) == AOP_CRY &&
6418 AOP_TYPE (right) == AOP_CRY)
6420 genModbits (left, right, result, ic);
6424 /* if both are of size == 1 */
6425 if (AOP_SIZE (left) == 1 &&
6426 AOP_SIZE (right) == 1)
6428 genModOneByte (left, right, result, ic);
6432 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
6433 /* use the ds390 ARITHMETIC accel UNIT */
6434 genModTwoByte (left, right, result, ic);
6438 /* should have been converted to function call */
6442 freeAsmop (result, NULL, ic, TRUE);
6443 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6444 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6447 /*-----------------------------------------------------------------*/
6448 /* genIfxJump :- will create a jump depending on the ifx */
6449 /*-----------------------------------------------------------------*/
6451 genIfxJump (iCode * ic, char *jval, iCode *popIc)
6454 symbol *tlbl = newiTempLabel (NULL);
6457 /* if there is something to be popped then do it first */
6458 popForBranch (popIc, TRUE);
6460 D (emitcode (";", "genIfxJump"));
6462 /* if true label then we jump if condition
6466 jlbl = IC_TRUE (ic);
6467 inst = ((strcmp (jval, "a") == 0 ? "jz" :
6468 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
6472 /* false label is present */
6473 jlbl = IC_FALSE (ic);
6474 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
6475 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
6477 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
6478 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
6480 emitcode (inst, "!tlabel", tlbl->key + 100);
6481 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
6484 /* mark the icode as generated */
6488 /*-----------------------------------------------------------------*/
6489 /* genCmp :- greater or less than comparison */
6490 /*-----------------------------------------------------------------*/
6492 genCmp (operand * left, operand * right,
6493 iCode * ic, iCode * ifx, int sign)
6495 int size, offset = 0;
6496 unsigned long lit = 0L;
6499 D (emitcode (";", "genCmp"));
6501 result = IC_RESULT (ic);
6503 /* if left & right are bit variables */
6504 if (AOP_TYPE (left) == AOP_CRY &&
6505 AOP_TYPE (right) == AOP_CRY)
6507 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6508 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6512 /* subtract right from left if at the
6513 end the carry flag is set then we know that
6514 left is greater than right */
6515 size = max (AOP_SIZE (left), AOP_SIZE (right));
6517 /* if unsigned char cmp with lit, do cjne left,#right,zz */
6518 if ((size == 1) && !sign &&
6519 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
6521 symbol *lbl = newiTempLabel (NULL);
6522 emitcode ("cjne", "%s,%s,!tlabel",
6523 aopGet (left, offset, FALSE, FALSE, NULL),
6524 aopGet (right, offset, FALSE, FALSE, NULL),
6530 if (AOP_TYPE (right) == AOP_LIT)
6532 lit = ulFromVal (AOP (right)->aopu.aop_lit);
6533 /* optimize if(x < 0) or if(x >= 0) */
6542 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
6544 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6545 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6547 aopOp (result, ic, FALSE, FALSE);
6549 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
6551 freeAsmop (result, NULL, ic, TRUE);
6552 genIfxJump (ifx, "acc.7", ic->next);
6557 emitcode ("rlc", "a");
6559 goto release_freedLR;
6567 // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
6568 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
6569 // emitcode (";", "genCmp #2");
6570 if (sign && (size == 0))
6572 // emitcode (";", "genCmp #3");
6573 emitcode ("xrl", "a,#!constbyte",0x80);
6574 if (AOP_TYPE (right) == AOP_LIT)
6576 unsigned long lit = ulFromVal (AOP (right)->aopu.aop_lit);
6577 // emitcode (";", "genCmp #3.1");
6578 emitcode ("subb", "a,#!constbyte",
6579 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
6583 // emitcode (";", "genCmp #3.2");
6585 MOVB (aopGet (right, offset++, FALSE, FALSE, "b"));
6586 saveAccWarn = DEFAULT_ACC_WARNING;
6587 emitcode ("xrl", "b,#!constbyte",0x80);
6588 emitcode ("subb", "a,b");
6595 // emitcode (";", "genCmp #4");
6597 s = aopGet (right, offset++, FALSE, FALSE, "b");
6598 saveAccWarn = DEFAULT_ACC_WARNING;
6600 emitcode ("subb", "a,%s", s);
6607 /* Don't need the left & right operands any more; do need the result. */
6608 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6609 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6611 aopOp (result, ic, FALSE, FALSE);
6615 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6621 /* if the result is used in the next
6622 ifx conditional branch then generate
6623 code a little differently */
6626 genIfxJump (ifx, "c", ic->next);
6632 /* leave the result in acc */
6634 freeAsmop (result, NULL, ic, TRUE);
6637 /*-----------------------------------------------------------------*/
6638 /* genCmpGt :- greater than comparison */
6639 /*-----------------------------------------------------------------*/
6641 genCmpGt (iCode * ic, iCode * ifx)
6643 operand *left, *right;
6644 sym_link *letype, *retype;
6647 D (emitcode (";", "genCmpGt"));
6649 left = IC_LEFT (ic);
6650 right = IC_RIGHT (ic);
6652 letype = getSpec (operandType (left));
6653 retype = getSpec (operandType (right));
6654 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6656 /* assign the left & right amsops */
6659 genCmp (right, left, ic, ifx, sign);
6662 /*-----------------------------------------------------------------*/
6663 /* genCmpLt - less than comparisons */
6664 /*-----------------------------------------------------------------*/
6666 genCmpLt (iCode * ic, iCode * ifx)
6668 operand *left, *right;
6669 sym_link *letype, *retype;
6672 D (emitcode (";", "genCmpLt"));
6674 left = IC_LEFT (ic);
6675 right = IC_RIGHT (ic);
6677 letype = getSpec (operandType (left));
6678 retype = getSpec (operandType (right));
6679 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6681 /* assign the left & right amsops */
6684 genCmp (left, right, ic, ifx, sign);
6687 /*-----------------------------------------------------------------*/
6688 /* gencjneshort - compare and jump if not equal */
6689 /*-----------------------------------------------------------------*/
6691 gencjneshort (operand * left, operand * right, symbol * lbl)
6693 int size = max (AOP_SIZE (left), AOP_SIZE (right));
6695 unsigned long lit = 0L;
6697 D (emitcode (";", "gencjneshort"));
6699 /* if the left side is a literal or
6700 if the right is in a pointer register and left
6702 if ((AOP_TYPE (left) == AOP_LIT) ||
6703 (AOP_TYPE (left) == AOP_IMMD) ||
6704 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6711 if (AOP_TYPE (right) == AOP_LIT)
6712 lit = ulFromVal (AOP (right)->aopu.aop_lit);
6714 if (opIsGptr (left) || opIsGptr (right))
6716 /* We are comparing a generic pointer to something.
6717 * Exclude the generic type byte from the comparison.
6720 D (emitcode (";", "cjneshort: generic ptr special case."););
6724 /* if the right side is a literal then anything goes */
6725 if (AOP_TYPE (right) == AOP_LIT &&
6726 AOP_TYPE (left) != AOP_DIR)
6730 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
6731 emitcode ("cjne", "a,%s,!tlabel",
6732 aopGet (right, offset, FALSE, FALSE, NULL),
6738 /* if the right side is in a register or in direct space or
6739 if the left is a pointer register & right is not */
6740 else if (AOP_TYPE (right) == AOP_REG ||
6741 AOP_TYPE (right) == AOP_DIR ||
6742 AOP_TYPE (right) == AOP_LIT ||
6743 AOP_TYPE (right) == AOP_IMMD ||
6744 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6745 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6749 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
6750 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6751 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6752 emitcode ("jnz", "!tlabel", lbl->key + 100);
6754 emitcode ("cjne", "a,%s,!tlabel",
6755 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG),
6762 /* right is a pointer reg need both a & b */
6765 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
6766 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
6767 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
6773 /*-----------------------------------------------------------------*/
6774 /* gencjne - compare and jump if not equal */
6775 /*-----------------------------------------------------------------*/
6777 gencjne (operand * left, operand * right, symbol * lbl)
6779 symbol *tlbl = newiTempLabel (NULL);
6781 D (emitcode (";", "gencjne"));
6783 gencjneshort (left, right, lbl);
6785 emitcode ("mov", "a,%s", one);
6786 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
6788 emitcode ("clr", "a");
6792 /*-----------------------------------------------------------------*/
6793 /* genCmpEq - generates code for equal to */
6794 /*-----------------------------------------------------------------*/
6796 genCmpEq (iCode * ic, iCode * ifx)
6798 operand *left, *right, *result;
6799 iCode * popIc = ic->next;
6801 D (emitcode (";", "genCmpEq"));
6804 AOP_SET_LOCALS (ic);
6806 /* if literal, literal on the right or
6807 if the right is in a pointer register and left
6809 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6810 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6812 operand *t = IC_RIGHT (ic);
6813 IC_RIGHT (ic) = IC_LEFT (ic);
6817 if (ifx && /* !AOP_SIZE(result) */
6818 OP_SYMBOL (result) &&
6819 OP_SYMBOL (result)->regType == REG_CND)
6822 /* if they are both bit variables */
6823 if (AOP_TYPE (left) == AOP_CRY &&
6824 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6826 if (AOP_TYPE (right) == AOP_LIT)
6828 unsigned long lit = ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6831 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6832 emitcode ("cpl", "c");
6836 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6840 emitcode ("clr", "c");
6842 /* AOP_TYPE(right) == AOP_CRY */
6846 symbol *lbl = newiTempLabel (NULL);
6847 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6848 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6849 emitcode ("cpl", "c");
6852 /* if true label then we jump if condition
6854 tlbl = newiTempLabel (NULL);
6857 emitcode ("jnc", "!tlabel", tlbl->key + 100);
6858 popForBranch (popIc, FALSE);
6859 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6863 emitcode ("jc", "!tlabel", tlbl->key + 100);
6864 popForBranch (popIc, FALSE);
6865 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6871 tlbl = newiTempLabel (NULL);
6872 gencjneshort (left, right, tlbl);
6875 popForBranch (popIc, FALSE);
6876 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6881 symbol *lbl = newiTempLabel (NULL);
6882 emitcode ("sjmp", "!tlabel", lbl->key + 100);
6884 popForBranch (popIc, FALSE);
6885 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6889 /* mark the icode as generated */
6892 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6893 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6897 /* if they are both bit variables */
6898 if (AOP_TYPE (left) == AOP_CRY &&
6899 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6901 if (AOP_TYPE (right) == AOP_LIT)
6903 unsigned long lit = ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6906 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6907 emitcode ("cpl", "c");
6911 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6915 emitcode ("clr", "c");
6917 /* AOP_TYPE(right) == AOP_CRY */
6921 symbol *lbl = newiTempLabel (NULL);
6922 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6923 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6924 emitcode ("cpl", "c");
6928 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6929 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6931 aopOp (result, ic, TRUE, FALSE);
6934 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6941 genIfxJump (ifx, "c", popIc);
6944 /* if the result is used in an arithmetic operation
6945 then put the result in place */
6950 gencjne (left, right, newiTempLabel (NULL));
6952 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6953 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6955 aopOp (result, ic, TRUE, FALSE);
6957 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6959 aopPut (result, "a", 0);
6964 genIfxJump (ifx, "a", popIc);
6967 /* if the result is used in an arithmetic operation
6968 then put the result in place */
6969 if (AOP_TYPE (result) != AOP_CRY)
6971 /* leave the result in acc */
6975 freeAsmop (result, NULL, ic, TRUE);
6978 /*-----------------------------------------------------------------*/
6979 /* ifxForOp - returns the icode containing the ifx for operand */
6980 /*-----------------------------------------------------------------*/
6982 ifxForOp (operand * op, iCode * ic)
6986 /* if true symbol then needs to be assigned */
6987 if (IS_TRUE_SYMOP (op))
6990 /* if this has register type condition and
6991 while skipping ipop's (see bug 1509084),
6992 the next instruction is ifx with the same operand
6993 and live to of the operand is upto the ifx only then */
6994 for (ifxIc = ic->next; ifxIc && ifxIc->op == IPOP; ifxIc = ifxIc->next);
6995 if (ifxIc && ifxIc->op == IFX &&
6996 IC_COND (ifxIc)->key == op->key &&
6997 OP_SYMBOL (op)->liveTo <= ifxIc->seq)
7003 /*-----------------------------------------------------------------*/
7004 /* hasInc - operand is incremented before any other use */
7005 /*-----------------------------------------------------------------*/
7007 hasInc (operand *op, iCode *ic, int osize)
7009 sym_link *type = operandType(op);
7010 sym_link *retype = getSpec (type);
7011 iCode *lic = ic->next;
7014 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
7015 if (!IS_SYMOP(op)) return NULL;
7017 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
7018 if (IS_AGGREGATE(type->next)) return NULL;
7019 if (osize != (isize = getSize(type->next))) return NULL;
7023 /* if operand of the form op = op + <sizeof *op> */
7024 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
7025 isOperandEqual(IC_RESULT(lic),op) &&
7026 isOperandLiteral(IC_RIGHT(lic)) &&
7027 operandLitValue(IC_RIGHT(lic)) == isize)
7031 /* if the operand used or deffed */
7032 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key)
7036 /* if GOTO or IFX */
7037 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
7043 /*-----------------------------------------------------------------*/
7044 /* genAndOp - for && operation */
7045 /*-----------------------------------------------------------------*/
7047 genAndOp (iCode * ic)
7049 operand *left, *right, *result;
7052 D (emitcode (";", "genAndOp"));
7054 /* note here that && operations that are in an
7055 if statement are taken away by backPatchLabels
7056 only those used in arthmetic operations remain */
7058 AOP_SET_LOCALS (ic);
7060 /* if both are bit variables */
7061 if (AOP_TYPE (left) == AOP_CRY &&
7062 AOP_TYPE (right) == AOP_CRY)
7064 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7065 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
7066 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7067 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7069 aopOp (result,ic,FALSE, FALSE);
7074 tlbl = newiTempLabel (NULL);
7076 emitcode ("jz", "!tlabel", tlbl->key + 100);
7079 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7080 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7082 aopOp (result,ic,FALSE, FALSE);
7086 freeAsmop (result, NULL, ic, TRUE);
7090 /*-----------------------------------------------------------------*/
7091 /* genOrOp - for || operation */
7092 /*-----------------------------------------------------------------*/
7094 genOrOp (iCode * ic)
7096 operand *left, *right, *result;
7099 D (emitcode (";", "genOrOp"));
7101 /* note here that || operations that are in an
7102 if statement are taken away by backPatchLabels
7103 only those used in arthmetic operations remain */
7105 AOP_SET_LOCALS (ic);
7107 /* if both are bit variables */
7108 if (AOP_TYPE (left) == AOP_CRY &&
7109 AOP_TYPE (right) == AOP_CRY)
7111 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7112 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
7113 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7114 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7116 aopOp (result,ic,FALSE, FALSE);
7122 tlbl = newiTempLabel (NULL);
7124 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7127 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7128 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7130 aopOp (result,ic,FALSE, FALSE);
7135 freeAsmop (result, NULL, ic, TRUE);
7138 /*-----------------------------------------------------------------*/
7139 /* isLiteralBit - test if lit == 2^n */
7140 /*-----------------------------------------------------------------*/
7142 isLiteralBit (unsigned long lit)
7144 unsigned long pw[32] =
7145 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
7146 0x100L, 0x200L, 0x400L, 0x800L,
7147 0x1000L, 0x2000L, 0x4000L, 0x8000L,
7148 0x10000L, 0x20000L, 0x40000L, 0x80000L,
7149 0x100000L, 0x200000L, 0x400000L, 0x800000L,
7150 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
7151 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
7154 for (idx = 0; idx < 32; idx++)
7160 /*-----------------------------------------------------------------*/
7161 /* continueIfTrue - */
7162 /*-----------------------------------------------------------------*/
7164 continueIfTrue (iCode * ic)
7167 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
7171 /*-----------------------------------------------------------------*/
7173 /*-----------------------------------------------------------------*/
7175 jumpIfTrue (iCode * ic)
7178 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
7182 /*-----------------------------------------------------------------*/
7183 /* jmpTrueOrFalse - */
7184 /*-----------------------------------------------------------------*/
7186 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
7188 // ugly but optimized by peephole
7191 symbol *nlbl = newiTempLabel (NULL);
7192 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
7194 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
7199 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
7205 // Generate code to perform a bit-wise logic operation
7206 // on two operands in far space (assumed to already have been
7207 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
7208 // in far space. This requires pushing the result on the stack
7209 // then popping it into the result.
7211 genFarFarLogicOp(iCode *ic, char *logicOp)
7213 int size, resultSize, compSize;
7217 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
7218 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
7219 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
7221 _startLazyDPSEvaluation();
7222 for (size = compSize; (size--); offset++)
7224 MOVA (aopGet (IC_LEFT(ic), offset, FALSE, FALSE, NULL));
7225 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
7226 MOVA (aopGet (IC_RIGHT(ic), offset, FALSE, FALSE, NULL));
7228 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
7229 emitcode ("push", "acc");
7231 _endLazyDPSEvaluation();
7233 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7234 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7235 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
7237 resultSize = AOP_SIZE(IC_RESULT(ic));
7239 ADJUST_PUSHED_RESULT(compSize, resultSize);
7241 _startLazyDPSEvaluation();
7244 emitcode ("pop", "acc");
7245 aopPut (IC_RESULT (ic), "a", compSize);
7247 _endLazyDPSEvaluation();
7248 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
7252 /*-----------------------------------------------------------------*/
7253 /* genAnd - code for and */
7254 /*-----------------------------------------------------------------*/
7256 genAnd (iCode * ic, iCode * ifx)
7258 operand *left, *right, *result;
7259 int size, offset = 0;
7260 unsigned long lit = 0L;
7265 D (emitcode (";", "genAnd"));
7267 AOP_OP_3_NOFATAL (ic, pushResult);
7268 AOP_SET_LOCALS (ic);
7272 genFarFarLogicOp(ic, "anl");
7277 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
7279 AOP_TYPE (left), AOP_TYPE (right));
7280 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
7282 AOP_SIZE (left), AOP_SIZE (right));
7285 /* if left is a literal & right is not then exchange them */
7286 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7287 #ifdef LOGIC_OPS_BROKEN
7288 || AOP_NEEDSACC (left)
7292 operand *tmp = right;
7297 /* if result = right then exchange left and right */
7298 if (sameRegs (AOP (result), AOP (right)))
7300 operand *tmp = right;
7305 /* if right is bit then exchange them */
7306 if (AOP_TYPE (right) == AOP_CRY &&
7307 AOP_TYPE (left) != AOP_CRY)
7309 operand *tmp = right;
7313 if (AOP_TYPE (right) == AOP_LIT)
7314 lit = ulFromVal (AOP (right)->aopu.aop_lit);
7316 size = AOP_SIZE (result);
7319 // result = bit & yy;
7320 if (AOP_TYPE (left) == AOP_CRY)
7322 // c = bit & literal;
7323 if (AOP_TYPE (right) == AOP_LIT)
7327 if (size && sameRegs (AOP (result), AOP (left)))
7330 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7335 if (size && (AOP_TYPE (result) == AOP_CRY))
7337 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
7340 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7345 emitcode ("clr", "c");
7350 if (AOP_TYPE (right) == AOP_CRY)
7353 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7354 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
7359 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
7361 emitcode ("rrc", "a");
7362 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
7370 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7371 genIfxJump (ifx, "c", ic->next);
7375 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7376 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7377 if ((AOP_TYPE (right) == AOP_LIT) &&
7378 (AOP_TYPE (result) == AOP_CRY) &&
7379 (AOP_TYPE (left) != AOP_CRY))
7381 int posbit = isLiteralBit (lit);
7386 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE, NULL));
7390 switch (posbit & 0x07)
7392 case 0: emitcode ("rrc", "a");
7394 case 7: emitcode ("rlc", "a");
7396 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
7405 SNPRINTF (buffer, sizeof(buffer),
7406 "acc.%d", posbit & 0x07);
7407 genIfxJump (ifx, buffer, ic->next);
7411 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
7418 symbol *tlbl = newiTempLabel (NULL);
7419 int sizel = AOP_SIZE (left);
7421 emitcode ("setb", "c");
7424 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
7426 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7428 if ((posbit = isLiteralBit (bytelit)) != 0)
7429 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
7432 if (bytelit != 0x0FFL)
7433 emitcode ("anl", "a,%s",
7434 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG));
7435 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7440 // bit = left & literal
7443 emitcode ("clr", "c");
7446 // if(left & literal)
7450 jmpTrueOrFalse (ifx, tlbl);
7460 /* if left is same as result */
7461 if (sameRegs (AOP (result), AOP (left)))
7463 for (; size--; offset++)
7465 if (AOP_TYPE (right) == AOP_LIT)
7467 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7468 if (bytelit == 0x0FF)
7470 /* dummy read of volatile operand */
7471 if (isOperandVolatile (left, FALSE))
7472 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7476 else if (bytelit == 0)
7478 aopPut (result, zero, offset);
7480 else if (IS_AOP_PREG (result))
7482 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7483 emitcode ("anl", "a,%s",
7484 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG));
7485 aopPut (result, "a", offset);
7488 emitcode ("anl", "%s,%s",
7489 aopGet (left, offset, FALSE, TRUE, NULL),
7490 aopGet (right, offset, FALSE, FALSE, NULL));
7494 if (AOP_TYPE (left) == AOP_ACC)
7497 emitcode("mov", "a,b");
7498 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7500 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7502 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
7503 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7504 emitcode ("anl", "a,b");
7505 aopPut (result, "a", offset);
7507 else if (aopGetUsesAcc (left, offset))
7509 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7510 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7511 aopPut (result, "a", offset);
7515 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7516 if (IS_AOP_PREG (result))
7518 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7519 aopPut (result, "a", offset);
7522 emitcode ("anl", "%s,a", aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7529 // left & result in different registers
7530 if (AOP_TYPE (result) == AOP_CRY)
7533 // if(size), result in bit
7534 // if(!size && ifx), conditional oper: if(left & right)
7535 symbol *tlbl = newiTempLabel (NULL);
7536 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
7538 emitcode ("setb", "c");
7541 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7542 && AOP_TYPE(left)==AOP_ACC)
7545 emitcode("mov", "a,b");
7546 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, NULL));
7548 else if (AOP_TYPE(left)==AOP_ACC)
7552 bool pushedB = pushB ();
7553 emitcode("mov", "b,a");
7554 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7555 emitcode("anl", "a,b");
7560 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7561 emitcode("anl", "a,b");
7564 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7566 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE, NULL));
7567 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7568 emitcode ("anl", "a,b");
7570 else if (aopGetUsesAcc (left, offset))
7572 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7573 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7577 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7578 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE, DP2_RESULT_REG));
7581 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7591 jmpTrueOrFalse (ifx, tlbl);
7597 for (; (size--); offset++)
7600 // result = left & right
7601 if (AOP_TYPE (right) == AOP_LIT)
7603 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7604 if (bytelit == 0x0FF)
7607 aopGet (left, offset, FALSE, FALSE, NULL),
7611 else if (bytelit == 0)
7613 /* dummy read of volatile operand */
7614 if (isOperandVolatile (left, FALSE))
7615 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7616 aopPut (result, zero, offset);
7619 else if (AOP_TYPE (left) == AOP_ACC)
7623 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, NULL));
7624 aopPut (result, "a", offset);
7629 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE, NULL));
7630 aopPut (result, "b", offset);
7635 // faster than result <- left, anl result,right
7636 // and better if result is SFR
7637 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7638 && AOP_TYPE(left)==AOP_ACC)
7641 emitcode("mov", "a,b");
7642 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, NULL));
7644 else if (AOP_TYPE(left)==AOP_ACC)
7648 bool pushedB = pushB ();
7649 emitcode("mov", "b,a");
7650 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7651 emitcode("anl", "a,b");
7656 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7657 emitcode("anl", "a,b");
7660 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7662 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
7663 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7664 emitcode ("anl", "a,b");
7666 else if (aopGetUsesAcc (left, offset))
7668 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7669 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7673 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7674 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE, DP2_RESULT_REG));
7676 aopPut (result, "a", offset);
7682 freeAsmop (result, NULL, ic, TRUE);
7683 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7684 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7687 /*-----------------------------------------------------------------*/
7688 /* genOr - code for or */
7689 /*-----------------------------------------------------------------*/
7691 genOr (iCode * ic, iCode * ifx)
7693 operand *left, *right, *result;
7694 int size, offset = 0;
7695 unsigned long lit = 0L;
7699 D (emitcode (";", "genOr"));
7701 AOP_OP_3_NOFATAL (ic, pushResult);
7702 AOP_SET_LOCALS (ic);
7706 genFarFarLogicOp(ic, "orl");
7712 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
7714 AOP_TYPE (left), AOP_TYPE (right));
7715 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
7717 AOP_SIZE (left), AOP_SIZE (right));
7720 /* if left is a literal & right is not then exchange them */
7721 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7722 #ifdef LOGIC_OPS_BROKEN
7723 || AOP_NEEDSACC (left) // I think this is a net loss now.
7727 operand *tmp = right;
7732 /* if result = right then exchange them */
7733 if (sameRegs (AOP (result), AOP (right)))
7735 operand *tmp = right;
7740 /* if right is bit then exchange them */
7741 if (AOP_TYPE (right) == AOP_CRY &&
7742 AOP_TYPE (left) != AOP_CRY)
7744 operand *tmp = right;
7748 if (AOP_TYPE (right) == AOP_LIT)
7749 lit = ulFromVal (AOP (right)->aopu.aop_lit);
7751 size = AOP_SIZE (result);
7755 if (AOP_TYPE (left) == AOP_CRY)
7757 if (AOP_TYPE (right) == AOP_LIT)
7759 // c = bit | literal;
7762 // lit != 0 => result = 1
7763 if (AOP_TYPE (result) == AOP_CRY)
7766 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7768 continueIfTrue (ifx);
7771 emitcode ("setb", "c");
7775 // lit == 0 => result = left
7776 if (size && sameRegs (AOP (result), AOP (left)))
7778 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7783 if (AOP_TYPE (right) == AOP_CRY)
7786 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7787 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7792 symbol *tlbl = newiTempLabel (NULL);
7793 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
7794 emitcode ("setb", "c");
7795 emitcode ("jb", "%s,!tlabel",
7796 AOP (left)->aopu.aop_dir, tlbl->key + 100);
7798 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7799 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7801 jmpTrueOrFalse (ifx, tlbl);
7816 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7817 genIfxJump (ifx, "c", ic->next);
7821 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7822 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7823 if ((AOP_TYPE (right) == AOP_LIT) &&
7824 (AOP_TYPE (result) == AOP_CRY) &&
7825 (AOP_TYPE (left) != AOP_CRY))
7831 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7833 continueIfTrue (ifx);
7838 // lit = 0, result = boolean(left)
7840 emitcode ("setb", "c");
7844 symbol *tlbl = newiTempLabel (NULL);
7845 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7850 { /* FIXME, thats pretty fishy, check for ifx!=0, testcase .. */
7851 genIfxJump (ifx, "a", ic->next);
7859 /* if left is same as result */
7860 if (sameRegs (AOP (result), AOP (left)))
7862 for (; size--; offset++)
7864 if (AOP_TYPE (right) == AOP_LIT)
7866 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7869 /* dummy read of volatile operand */
7870 if (isOperandVolatile (left, FALSE))
7871 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7875 else if (bytelit == 0x0FF)
7877 aopPut (result, "#0xFF", offset);
7879 else if (IS_AOP_PREG (left))
7881 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7882 emitcode ("orl", "a,%s",
7883 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7884 aopPut (result, "a", offset);
7888 emitcode ("orl", "%s,%s",
7889 aopGet (left, offset, FALSE, TRUE, NULL),
7890 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7895 if (AOP_TYPE (left) == AOP_ACC)
7898 emitcode("mov", "a,b");
7899 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7901 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7903 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE, NULL));
7904 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7905 emitcode ("orl", "a,b");
7906 aopPut (result, "a", offset);
7908 else if (aopGetUsesAcc (left, offset))
7910 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7911 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7912 aopPut (result, "a", offset);
7916 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7917 if (IS_AOP_PREG (left))
7919 emitcode ("orl", "a,%s",
7920 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7921 aopPut (result, "a", offset);
7925 emitcode ("orl", "%s,a",
7926 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7934 // left & result in different registers
7935 if (AOP_TYPE (result) == AOP_CRY)
7938 // if(size), result in bit
7939 // if(!size && ifx), conditional oper: if(left | right)
7940 symbol *tlbl = newiTempLabel (NULL);
7941 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7943 emitcode ("setb", "c");
7946 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7947 && AOP_TYPE(left)==AOP_ACC)
7950 emitcode("mov", "a,b");
7951 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7953 else if (AOP_TYPE(left)==AOP_ACC)
7957 bool pushedB = pushB ();
7958 emitcode("mov", "b,a");
7959 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7960 emitcode("orl", "a,b");
7965 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7966 emitcode("orl", "a,b");
7969 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7971 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
7972 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7973 emitcode ("orl", "a,b");
7975 else if (aopGetUsesAcc (left, offset))
7977 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7978 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7982 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7983 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE, DP2_RESULT_REG));
7986 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7996 jmpTrueOrFalse (ifx, tlbl);
8002 _startLazyDPSEvaluation();
8003 for (; (size--); offset++)
8006 // result = left | right
8007 if (AOP_TYPE (right) == AOP_LIT)
8009 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
8013 aopGet (left, offset, FALSE, FALSE, NULL),
8017 else if (bytelit == 0x0FF)
8019 /* dummy read of volatile operand */
8020 if (isOperandVolatile (left, FALSE))
8021 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8022 aopPut (result, "#0xFF", offset);
8026 // faster than result <- left, orl result,right
8027 // and better if result is SFR
8028 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
8029 && AOP_TYPE(left)==AOP_ACC)
8032 emitcode("mov", "a,b");
8033 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8035 else if (AOP_TYPE(left)==AOP_ACC)
8039 bool pushedB = pushB ();
8040 emitcode("mov", "b,a");
8041 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8042 emitcode("orl", "a,b");
8047 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8048 emitcode("orl", "a,b");
8051 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
8053 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
8054 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8055 emitcode ("orl", "a,b");
8057 else if (aopGetUsesAcc (left, offset))
8059 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8060 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8064 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
8065 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE, DP2_RESULT_REG));
8067 aopPut (result, "a", offset);
8069 _endLazyDPSEvaluation();
8074 freeAsmop (result, NULL, ic, TRUE);
8075 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
8076 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
8079 /*-----------------------------------------------------------------*/
8080 /* genXor - code for xclusive or */
8081 /*-----------------------------------------------------------------*/
8083 genXor (iCode * ic, iCode * ifx)
8085 operand *left, *right, *result;
8086 int size, offset = 0;
8087 unsigned long lit = 0L;
8091 D (emitcode (";", "genXor"));
8093 AOP_OP_3_NOFATAL (ic, pushResult);
8094 AOP_SET_LOCALS (ic);
8098 genFarFarLogicOp(ic, "xrl");
8103 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
8105 AOP_TYPE (left), AOP_TYPE (right));
8106 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
8108 AOP_SIZE (left), AOP_SIZE (right));
8111 /* if left is a literal & right is not ||
8112 if left needs acc & right does not */
8113 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
8114 #ifdef LOGIC_OPS_BROKEN
8115 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
8119 operand *tmp = right;
8124 /* if result = right then exchange them */
8125 if (sameRegs (AOP (result), AOP (right)))
8127 operand *tmp = right;
8132 /* if right is bit then exchange them */
8133 if (AOP_TYPE (right) == AOP_CRY &&
8134 AOP_TYPE (left) != AOP_CRY)
8136 operand *tmp = right;
8141 if (AOP_TYPE (right) == AOP_LIT)
8142 lit = ulFromVal (AOP (right)->aopu.aop_lit);
8144 size = AOP_SIZE (result);
8148 if (AOP_TYPE (left) == AOP_CRY)
8150 if (AOP_TYPE (right) == AOP_LIT)
8152 // c = bit & literal;
8155 // lit>>1 != 0 => result = 1
8156 if (AOP_TYPE (result) == AOP_CRY)
8159 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
8161 continueIfTrue (ifx);
8164 emitcode ("setb", "c");
8171 // lit == 0, result = left
8172 if (size && sameRegs (AOP (result), AOP (left)))
8174 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
8178 // lit == 1, result = not(left)
8179 if (size && sameRegs (AOP (result), AOP (left)))
8181 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
8186 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
8187 emitcode ("cpl", "c");
8195 symbol *tlbl = newiTempLabel (NULL);
8196 if (AOP_TYPE (right) == AOP_CRY)
8199 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8203 int sizer = AOP_SIZE (right);
8205 // if val>>1 != 0, result = 1
8206 emitcode ("setb", "c");
8209 MOVA (aopGet (right, sizer - 1, FALSE, FALSE, NULL));
8211 // test the msb of the lsb
8212 emitcode ("anl", "a,#!constbyte",0xfe);
8213 emitcode ("jnz", "!tlabel", tlbl->key + 100);
8217 emitcode ("rrc", "a");
8219 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
8220 emitcode ("cpl", "c");
8228 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
8229 genIfxJump (ifx, "c", ic->next);
8233 /* if left is same as result */
8234 if (sameRegs (AOP (result), AOP (left)))
8236 for (; size--; offset++)
8238 if (AOP_TYPE (right) == AOP_LIT)
8240 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
8243 /* dummy read of volatile operand */
8244 if (isOperandVolatile (left, FALSE))
8245 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8249 else if (IS_AOP_PREG (left))
8251 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8252 emitcode ("xrl", "a,%s",
8253 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG));
8254 aopPut (result, "a", offset);
8258 emitcode ("xrl", "%s,%s",
8259 aopGet (left, offset, FALSE, TRUE, NULL),
8260 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8265 if (AOP_TYPE (left) == AOP_ACC)
8268 emitcode("mov", "a,b");
8269 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8271 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
8273 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
8274 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8275 emitcode ("xrl", "a,b");
8276 aopPut (result, "a", offset);
8278 else if (aopGetUsesAcc (left, offset))
8280 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8281 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8282 aopPut (result, "a", offset);
8286 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
8287 if (IS_AOP_PREG (left))
8289 emitcode ("xrl", "a,%s",
8290 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
8291 aopPut (result, "a", offset);
8294 emitcode ("xrl", "%s,a",
8295 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
8302 // left & result in different registers
8303 if (AOP_TYPE (result) == AOP_CRY)
8306 // if(size), result in bit
8307 // if(!size && ifx), conditional oper: if(left ^ right)
8308 symbol *tlbl = newiTempLabel (NULL);
8309 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
8312 emitcode ("setb", "c");
8315 if ((AOP_TYPE (right) == AOP_LIT) &&
8316 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
8318 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8320 else if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
8321 && AOP_TYPE(left)==AOP_ACC)
8324 emitcode("mov", "a,b");
8325 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8327 else if (AOP_TYPE(left)==AOP_ACC)
8331 bool pushedB = pushB ();
8332 emitcode("mov", "b,a");
8333 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8334 emitcode("xrl", "a,b");
8339 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8340 emitcode("xrl", "a,b");
8343 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
8345 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
8346 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8347 emitcode ("xrl", "a,b");
8349 else if (aopGetUsesAcc (left, offset))
8351 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8352 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8356 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
8357 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
8360 emitcode ("jnz", "!tlabel", tlbl->key + 100);
8370 jmpTrueOrFalse (ifx, tlbl);
8374 for (; (size--); offset++)
8377 // result = left ^ right
8378 if (AOP_TYPE (right) == AOP_LIT)
8380 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
8384 aopGet (left, offset, FALSE, FALSE, NULL),
8388 D (emitcode (";", "better literal XOR."));
8389 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8390 emitcode ("xrl", "a, %s",
8391 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8395 // faster than result <- left, anl result,right
8396 // and better if result is SFR
8397 if (AOP_TYPE (left) == AOP_ACC)
8399 emitcode ("xrl", "a,%s",
8400 aopGet (right, offset,
8401 FALSE, FALSE, DP2_RESULT_REG));
8405 char *rOp = aopGet (right, offset, FALSE, FALSE, NULL);
8406 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
8408 emitcode("mov", "b,a");
8412 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8413 emitcode ("xrl", "a,%s", rOp);
8416 aopPut (result, "a", offset);
8422 freeAsmop (result, NULL, ic, TRUE);
8423 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
8424 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
8427 /*-----------------------------------------------------------------*/
8428 /* genInline - write the inline code out */
8429 /*-----------------------------------------------------------------*/
8431 genInline (iCode * ic)
8433 char *buffer, *bp, *bp1;
8434 bool inComment = FALSE;
8436 D (emitcode (";", "genInline"));
8438 _G.inLine += (!options.asmpeep);
8440 buffer = bp = bp1 = Safe_strdup (IC_INLINE (ic));
8442 /* emit each line as a code */
8460 /* Add \n for labels, not dirs such as c:\mydir */
8461 if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
8479 _G.inLine -= (!options.asmpeep);
8482 /*-----------------------------------------------------------------*/
8483 /* genRRC - rotate right with carry */
8484 /*-----------------------------------------------------------------*/
8488 operand *left, *result;
8492 D (emitcode (";", "genRRC"));
8494 /* rotate right with carry */
8495 left = IC_LEFT (ic);
8496 result = IC_RESULT (ic);
8497 aopOp (left, ic, FALSE, FALSE);
8498 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8500 /* move it to the result */
8501 size = AOP_SIZE (result);
8505 _startLazyDPSEvaluation ();
8508 l = aopGet (left, offset, FALSE, FALSE, NULL);
8510 emitcode ("rrc", "a");
8511 if (AOP_SIZE (result) > 1)
8512 aopPut (result, "a", offset--);
8514 _endLazyDPSEvaluation ();
8516 /* now we need to put the carry into the
8517 highest order byte of the result */
8518 if (AOP_SIZE (result) > 1)
8520 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE, NULL);
8523 emitcode ("mov", "acc.7,c");
8524 aopPut (result, "a", AOP_SIZE (result) - 1);
8525 freeAsmop (result, NULL, ic, TRUE);
8526 freeAsmop (left, NULL, ic, TRUE);
8529 /*-----------------------------------------------------------------*/
8530 /* genRLC - generate code for rotate left with carry */
8531 /*-----------------------------------------------------------------*/
8535 operand *left, *result;
8539 D (emitcode (";", "genRLC"));
8541 /* rotate right with carry */
8542 left = IC_LEFT (ic);
8543 result = IC_RESULT (ic);
8544 aopOp (left, ic, FALSE, FALSE);
8545 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8547 /* move it to the result */
8548 size = AOP_SIZE (result);
8552 l = aopGet (left, offset, FALSE, FALSE, NULL);
8554 emitcode ("add", "a,acc");
8555 if (AOP_SIZE (result) > 1)
8557 aopPut (result, "a", offset++);
8560 _startLazyDPSEvaluation ();
8563 l = aopGet (left, offset, FALSE, FALSE, NULL);
8565 emitcode ("rlc", "a");
8566 if (AOP_SIZE (result) > 1)
8567 aopPut (result, "a", offset++);
8569 _endLazyDPSEvaluation ();
8571 /* now we need to put the carry into the
8572 highest order byte of the result */
8573 if (AOP_SIZE (result) > 1)
8575 l = aopGet (result, 0, FALSE, FALSE, NULL);
8578 emitcode ("mov", "acc.0,c");
8579 aopPut (result, "a", 0);
8580 freeAsmop (result, NULL, ic, TRUE);
8581 freeAsmop (left, NULL, ic, TRUE);
8584 /*-----------------------------------------------------------------*/
8585 /* genGetHbit - generates code get highest order bit */
8586 /*-----------------------------------------------------------------*/
8588 genGetHbit (iCode * ic)
8590 operand *left, *result;
8592 D (emitcode (";", "genGetHbit"));
8594 left = IC_LEFT (ic);
8595 result = IC_RESULT (ic);
8596 aopOp (left, ic, FALSE, FALSE);
8597 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8599 /* get the highest order byte into a */
8600 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
8601 if (AOP_TYPE (result) == AOP_CRY)
8603 emitcode ("rlc", "a");
8608 emitcode ("rl", "a");
8609 emitcode ("anl", "a,#0x01");
8614 freeAsmop (result, NULL, ic, TRUE);
8615 freeAsmop (left, NULL, ic, TRUE);
8618 /*-----------------------------------------------------------------*/
8619 /* genSwap - generates code to swap nibbles or bytes */
8620 /*-----------------------------------------------------------------*/
8622 genSwap (iCode * ic)
8624 operand *left, *result;
8626 D(emitcode (";", "genSwap"));
8628 left = IC_LEFT (ic);
8629 result = IC_RESULT (ic);
8630 aopOp (left, ic, FALSE, FALSE);
8631 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8633 _startLazyDPSEvaluation ();
8634 switch (AOP_SIZE (left))
8636 case 1: /* swap nibbles in byte */
8637 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
8638 emitcode ("swap", "a");
8639 aopPut (result, "a", 0);
8641 case 2: /* swap bytes in word */
8642 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
8644 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
8645 aopPut (result, aopGet (left, 1, FALSE, FALSE, NULL), 0);
8646 aopPut (result, "a", 1);
8648 else if (operandsEqu (left, result))
8651 bool pushedB = FALSE, leftInB = FALSE;
8653 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
8654 if (AOP_NEEDSACC (left) || AOP_NEEDSACC (result))
8657 emitcode ("mov", "b,a");
8661 aopPut (result, aopGet (left, 1, FALSE, FALSE, NULL), 0);
8662 aopPut (result, reg, 1);
8669 aopPut (result, aopGet (left, 1, FALSE, FALSE, NULL), 0);
8670 aopPut (result, aopGet (left, 0, FALSE, FALSE, NULL), 1);
8674 wassertl(FALSE, "unsupported SWAP operand size");
8676 _endLazyDPSEvaluation ();
8678 freeAsmop (result, NULL, ic, TRUE);
8679 freeAsmop (left, NULL, ic, TRUE);
8682 /*-----------------------------------------------------------------*/
8683 /* AccRol - rotate left accumulator by known count */
8684 /*-----------------------------------------------------------------*/
8686 AccRol (int shCount)
8688 shCount &= 0x0007; // shCount : 0..7
8695 emitcode ("rl", "a");
8698 emitcode ("rl", "a");
8699 emitcode ("rl", "a");
8702 emitcode ("swap", "a");
8703 emitcode ("rr", "a");
8706 emitcode ("swap", "a");
8709 emitcode ("swap", "a");
8710 emitcode ("rl", "a");
8713 emitcode ("rr", "a");
8714 emitcode ("rr", "a");
8717 emitcode ("rr", "a");
8722 /*-----------------------------------------------------------------*/
8723 /* AccLsh - left shift accumulator by known count */
8724 /*-----------------------------------------------------------------*/
8726 AccLsh (int shCount)
8731 emitcode ("add", "a,acc");
8732 else if (shCount == 2)
8734 emitcode ("add", "a,acc");
8735 emitcode ("add", "a,acc");
8739 /* rotate left accumulator */
8741 /* and kill the lower order bits */
8742 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
8747 /*-----------------------------------------------------------------*/
8748 /* AccRsh - right shift accumulator by known count */
8749 /*-----------------------------------------------------------------*/
8751 AccRsh (int shCount)
8758 emitcode ("rrc", "a");
8762 /* rotate right accumulator */
8763 AccRol (8 - shCount);
8764 /* and kill the higher order bits */
8765 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
8770 #ifdef BETTER_LITERAL_SHIFT
8771 /*-----------------------------------------------------------------*/
8772 /* AccSRsh - signed right shift accumulator by known count */
8773 /*-----------------------------------------------------------------*/
8775 AccSRsh (int shCount)
8782 emitcode ("mov", "c,acc.7");
8783 emitcode ("rrc", "a");
8785 else if (shCount == 2)
8787 emitcode ("mov", "c,acc.7");
8788 emitcode ("rrc", "a");
8789 emitcode ("mov", "c,acc.7");
8790 emitcode ("rrc", "a");
8794 tlbl = newiTempLabel (NULL);
8795 /* rotate right accumulator */
8796 AccRol (8 - shCount);
8797 /* and kill the higher order bits */
8798 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
8799 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8800 emitcode ("orl", "a,#!constbyte",
8801 (unsigned char) ~SRMask[shCount]);
8808 #ifdef BETTER_LITERAL_SHIFT
8809 /*-----------------------------------------------------------------*/
8810 /* shiftR1Left2Result - shift right one byte from left to result */
8811 /*-----------------------------------------------------------------*/
8813 shiftR1Left2Result (operand * left, int offl,
8814 operand * result, int offr,
8815 int shCount, int sign)
8817 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
8818 /* shift right accumulator */
8823 aopPut (result, "a", offr);
8827 #ifdef BETTER_LITERAL_SHIFT
8828 /*-----------------------------------------------------------------*/
8829 /* shiftL1Left2Result - shift left one byte from left to result */
8830 /*-----------------------------------------------------------------*/
8832 shiftL1Left2Result (operand * left, int offl,
8833 operand * result, int offr, int shCount)
8836 l = aopGet (left, offl, FALSE, FALSE, NULL);
8838 /* shift left accumulator */
8840 aopPut (result, "a", offr);
8844 #ifdef BETTER_LITERAL_SHIFT
8845 /*-----------------------------------------------------------------*/
8846 /* movLeft2Result - move byte from left to result */
8847 /*-----------------------------------------------------------------*/
8849 movLeft2Result (operand * left, int offl,
8850 operand * result, int offr, int sign)
8853 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8855 l = aopGet (left, offl, FALSE, FALSE, NULL);
8857 if (*l == '@' && (IS_AOP_PREG (result)))
8859 emitcode ("mov", "a,%s", l);
8860 aopPut (result, "a", offr);
8866 aopPut (result, l, offr);
8870 /* MSB sign in acc.7 ! */
8871 if (getDataSize (left) == offl + 1)
8874 aopPut (result, "a", offr);
8882 #ifdef BETTER_LITERAL_SHIFT
8883 /*-----------------------------------------------------------------*/
8884 /* AccAXRrl1 - right rotate a:x by 1 */
8885 /*-----------------------------------------------------------------*/
8889 emitcode ("mov", "c,acc.0");
8890 emitcode ("xch", "a,%s", x);
8891 emitcode ("rrc", "a");
8892 emitcode ("xch", "a,%s", x);
8893 emitcode ("rrc", "a");
8897 #ifdef BETTER_LITERAL_SHIFT
8899 /*-----------------------------------------------------------------*/
8900 /* AccAXLrl1 - left rotate a:x by 1 */
8901 /*-----------------------------------------------------------------*/
8905 emitcode ("mov", "c,acc.7");
8906 emitcode ("xch", "a,%s", x);
8907 emitcode ("rlc", "a");
8908 emitcode ("xch", "a,%s", x);
8909 emitcode ("rlc", "a");
8913 #ifdef BETTER_LITERAL_SHIFT
8914 /*-----------------------------------------------------------------*/
8915 /* AccAXRsh1 - right shift c->a:x->c by 1 */
8916 /*-----------------------------------------------------------------*/
8920 emitcode ("rrc", "a");
8921 emitcode ("xch", "a,%s", x);
8922 emitcode ("rrc", "a");
8923 emitcode ("xch", "a,%s", x);
8927 #ifdef BETTER_LITERAL_SHIFT
8928 /*-----------------------------------------------------------------*/
8929 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8930 /*-----------------------------------------------------------------*/
8934 emitcode ("xch", "a,%s", x);
8935 emitcode ("add", "a,acc");
8936 emitcode ("xch", "a,%s", x);
8937 emitcode ("rlc", "a");
8941 #ifdef BETTER_LITERAL_SHIFT
8942 /*-----------------------------------------------------------------*/
8943 /* AccAXLsh - left shift a:x by known count (0..7) */
8944 /*-----------------------------------------------------------------*/
8946 AccAXLsh (char *x, int shCount)
8961 case 5: // AAAAABBB:CCCCCDDD
8963 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8965 emitcode ("anl", "a,#!constbyte",
8966 SLMask[shCount]); // BBB00000:CCCCCDDD
8968 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8970 AccRol (shCount); // DDDCCCCC:BBB00000
8972 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8974 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8976 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8978 emitcode ("anl", "a,#!constbyte",
8979 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8981 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8983 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8986 case 6: // AAAAAABB:CCCCCCDD
8987 emitcode ("anl", "a,#!constbyte",
8988 SRMask[shCount]); // 000000BB:CCCCCCDD
8990 AccAXRrl1 (x); // D000000B:BCCCCCCD
8991 AccAXRrl1 (x); // DD000000:BBCCCCCC
8992 emitcode ("xch", "a,%s", x); // BBCCCCCC:DD000000
8994 emitcode ("mov", "c,acc.0"); // c = B
8995 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8996 emitcode("rrc","a");
8997 emitcode("xch","a,%s", x);
8998 emitcode("rrc","a");
8999 emitcode("mov","c,acc.0"); //<< get correct bit
9000 emitcode("xch","a,%s", x);
9002 emitcode("rrc","a");
9003 emitcode("xch","a,%s", x);
9004 emitcode("rrc","a");
9005 emitcode("xch","a,%s", x);
9008 case 7: // a:x <<= 7
9010 emitcode ("anl", "a,#!constbyte",
9011 SRMask[shCount]); // 0000000B:CCCCCCCD
9013 AccAXRrl1 (x); // D0000000:BCCCCCCC
9015 emitcode ("xch", "a,%s", x); // BCCCCCCC:D0000000
9024 #ifdef BETTER_LITERAL_SHIFT
9026 /*-----------------------------------------------------------------*/
9027 /* AccAXRsh - right shift a:x known count (0..7) */
9028 /*-----------------------------------------------------------------*/
9030 AccAXRsh (char *x, int shCount)
9038 AccAXRsh1 (x); // 0->a:x
9043 AccAXRsh1 (x); // 0->a:x
9046 AccAXRsh1 (x); // 0->a:x
9051 case 5: // AAAAABBB:CCCCCDDD = a:x
9053 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
9055 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
9057 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
9059 emitcode ("anl", "a,#!constbyte",
9060 SRMask[shCount]); // 000CCCCC:BBBAAAAA
9062 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
9064 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
9066 emitcode ("anl", "a,#!constbyte",
9067 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
9069 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
9071 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
9073 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
9076 case 6: // AABBBBBB:CCDDDDDD
9078 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDE
9079 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
9081 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
9083 emitcode ("anl", "a,#!constbyte",
9084 SRMask[shCount]); // 000000AA:BBBBBBCC
9087 case 7: // ABBBBBBB:CDDDDDDD
9089 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
9091 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
9093 emitcode ("anl", "a,#!constbyte",
9094 SRMask[shCount]); // 0000000A:BBBBBBBC
9103 #ifdef BETTER_LITERAL_SHIFT
9104 /*-----------------------------------------------------------------*/
9105 /* AccAXRshS - right shift signed a:x known count (0..7) */
9106 /*-----------------------------------------------------------------*/
9108 AccAXRshS (char *x, int shCount)
9116 emitcode ("mov", "c,acc.7");
9117 AccAXRsh1 (x); // s->a:x
9121 emitcode ("mov", "c,acc.7");
9122 AccAXRsh1 (x); // s->a:x
9124 emitcode ("mov", "c,acc.7");
9125 AccAXRsh1 (x); // s->a:x
9130 case 5: // AAAAABBB:CCCCCDDD = a:x
9132 tlbl = newiTempLabel (NULL);
9133 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
9135 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
9137 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
9139 emitcode ("anl", "a,#!constbyte",
9140 SRMask[shCount]); // 000CCCCC:BBBAAAAA
9142 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
9144 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
9146 emitcode ("anl", "a,#!constbyte",
9147 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
9149 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
9151 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
9153 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
9155 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
9156 emitcode ("orl", "a,#!constbyte",
9157 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
9160 break; // SSSSAAAA:BBBCCCCC
9162 case 6: // AABBBBBB:CCDDDDDD
9164 tlbl = newiTempLabel (NULL);
9166 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
9167 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
9169 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
9171 emitcode ("anl", "a,#!constbyte",
9172 SRMask[shCount]); // 000000AA:BBBBBBCC
9174 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
9175 emitcode ("orl", "a,#!constbyte",
9176 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
9180 case 7: // ABBBBBBB:CDDDDDDD
9182 tlbl = newiTempLabel (NULL);
9184 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
9186 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
9188 emitcode ("anl", "a,#!constbyte",
9189 SRMask[shCount]); // 0000000A:BBBBBBBC
9191 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
9192 emitcode ("orl", "a,#!constbyte",
9193 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
9203 #ifdef BETTER_LITERAL_SHIFT
9205 _loadLeftIntoAx(char **lsb,
9211 // Get the initial value from left into a pair of registers.
9212 // MSB must be in A, LSB can be any register.
9214 // If the result is held in registers, it is an optimization
9215 // if the LSB can be held in the register which will hold the,
9216 // result LSB since this saves us from having to copy it into
9217 // the result following AccAXLsh.
9219 // If the result is addressed indirectly, this is not a gain.
9220 if (AOP_NEEDSACC(result))
9224 _startLazyDPSEvaluation();
9225 if (AOP_TYPE(left) == AOP_DPTR2)
9228 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE, NULL));
9229 // get LSB in DP2_RESULT_REG.
9230 leftByte = aopGet (left, offl, FALSE, FALSE, DP2_RESULT_REG);
9231 assert(!strcmp(leftByte, DP2_RESULT_REG));
9235 // get LSB into DP2_RESULT_REG
9236 leftByte = aopGet (left, offl, FALSE, FALSE, NULL);
9237 if (strcmp(leftByte, DP2_RESULT_REG))
9240 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
9243 leftByte = aopGet (left, offl + MSB16, FALSE, FALSE, NULL);
9244 assert(strcmp(leftByte, DP2_RESULT_REG));
9247 _endLazyDPSEvaluation();
9248 *lsb = DP2_RESULT_REG;
9252 if (sameRegs (AOP (result), AOP (left)) &&
9253 ((offl + MSB16) == offr))
9255 /* don't crash result[offr] */
9256 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
9257 emitcode ("xch", "a,%s",
9258 aopGet (left, offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
9262 movLeft2Result (left, offl, result, offr, 0);
9263 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE, NULL));
9265 *lsb = aopGet (result, offr, FALSE, FALSE, DP2_RESULT_REG);
9266 assert(strcmp(*lsb,"a"));
9271 _storeAxResults(char *lsb,
9275 _startLazyDPSEvaluation();
9276 if (AOP_NEEDSACC(result))
9278 /* We have to explicitly update the result LSB.
9280 emitcode ("xch","a,%s", lsb);
9281 aopPut (result, "a", offr);
9282 emitcode ("mov","a,%s", lsb);
9284 if (getDataSize (result) > 1)
9286 aopPut (result, "a", offr + MSB16);
9288 _endLazyDPSEvaluation();
9291 /*-----------------------------------------------------------------*/
9292 /* shiftL2Left2Result - shift left two bytes from left to result */
9293 /*-----------------------------------------------------------------*/
9295 shiftL2Left2Result (operand * left, int offl,
9296 operand * result, int offr, int shCount)
9300 _loadLeftIntoAx(&lsb, left, result, offl, offr);
9302 AccAXLsh (lsb, shCount);
9304 _storeAxResults(lsb, result, offr);
9308 #ifdef BETTER_LITERAL_SHIFT
9309 /*-----------------------------------------------------------------*/
9310 /* shiftR2Left2Result - shift right two bytes from left to result */
9311 /*-----------------------------------------------------------------*/
9313 shiftR2Left2Result (operand * left, int offl,
9314 operand * result, int offr,
9315 int shCount, int sign)
9319 _loadLeftIntoAx(&lsb, left, result, offl, offr);
9321 /* a:x >> shCount (x = lsb(result)) */
9324 AccAXRshS(lsb, shCount);
9328 AccAXRsh(lsb, shCount);
9331 _storeAxResults(lsb, result, offr);
9335 /*-----------------------------------------------------------------*/
9336 /* shiftLLeftOrResult - shift left one byte from left, or to result */
9337 /*-----------------------------------------------------------------*/
9339 shiftLLeftOrResult (operand * left, int offl,
9340 operand * result, int offr, int shCount)
9342 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
9343 /* shift left accumulator */
9345 /* or with result */
9346 emitcode ("orl", "a,%s",
9347 aopGet (result, offr, FALSE, FALSE, DP2_RESULT_REG));
9348 /* back to result */
9349 aopPut (result, "a", offr);
9354 /*-----------------------------------------------------------------*/
9355 /* shiftRLeftOrResult - shift right one byte from left,or to result */
9356 /*-----------------------------------------------------------------*/
9358 shiftRLeftOrResult (operand * left, int offl,
9359 operand * result, int offr, int shCount)
9361 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
9362 /* shift right accumulator */
9364 /* or with result */
9365 emitcode ("orl", "a,%s",
9366 aopGet (result, offr, FALSE, FALSE, DP2_RESULT_REG));
9367 /* back to result */
9368 aopPut (result, "a", offr);
9372 #ifdef BETTER_LITERAL_SHIFT
9373 /*-----------------------------------------------------------------*/
9374 /* genlshOne - left shift a one byte quantity by known count */
9375 /*-----------------------------------------------------------------*/
9377 genlshOne (operand * result, operand * left, int shCount)
9379 D (emitcode (";", "genlshOne"));
9381 shiftL1Left2Result (left, LSB, result, LSB, shCount);
9385 #ifdef BETTER_LITERAL_SHIFT
9386 /*-----------------------------------------------------------------*/
9387 /* genlshTwo - left shift two bytes by known amount != 0 */
9388 /*-----------------------------------------------------------------*/
9390 genlshTwo (operand * result, operand * left, int shCount)
9394 D (emitcode (";", "genlshTwo"));
9396 size = getDataSize (result);
9398 /* if shCount >= 8 */
9403 _startLazyDPSEvaluation();
9409 _endLazyDPSEvaluation();
9410 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
9411 aopPut (result, zero, LSB);
9415 movLeft2Result (left, LSB, result, MSB16, 0);
9416 aopPut (result, zero, LSB);
9417 _endLazyDPSEvaluation();
9422 aopPut (result, zero, LSB);
9423 _endLazyDPSEvaluation();
9427 /* 1 <= shCount <= 7 */
9431 shiftL1Left2Result (left, LSB, result, LSB, shCount);
9433 shiftL2Left2Result (left, LSB, result, LSB, shCount);
9440 /*-----------------------------------------------------------------*/
9441 /* shiftLLong - shift left one long from left to result */
9442 /* offl = LSB or MSB16 */
9443 /*-----------------------------------------------------------------*/
9445 shiftLLong (operand * left, operand * result, int offr)
9448 int size = AOP_SIZE (result);
9450 if (size >= LSB + offr)
9452 l = aopGet (left, LSB, FALSE, FALSE, NULL);
9454 emitcode ("add", "a,acc");
9455 if (sameRegs (AOP (left), AOP (result)) &&
9456 size >= MSB16 + offr && offr != LSB)
9457 emitcode ("xch", "a,%s",
9458 aopGet (left, LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
9460 aopPut (result, "a", LSB + offr);
9463 if (size >= MSB16 + offr)
9465 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
9467 l = aopGet (left, MSB16, FALSE, FALSE, TRUE);
9470 emitcode ("rlc", "a");
9471 if (sameRegs (AOP (left), AOP (result)) &&
9472 size >= MSB24 + offr && offr != LSB)
9473 emitcode ("xch", "a,%s",
9474 aopGet (left, MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
9476 aopPut (result, "a", MSB16 + offr);
9479 if (size >= MSB24 + offr)
9481 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
9483 l = aopGet (left, MSB24, FALSE, FALSE, NULL);
9486 emitcode ("rlc", "a");
9487 if (sameRegs (AOP (left), AOP (result)) &&
9488 size >= MSB32 + offr && offr != LSB)
9489 emitcode ("xch", "a,%s",
9490 aopGet (left, MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
9492 aopPut (result, "a", MSB24 + offr);
9495 if (size > MSB32 + offr)
9497 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
9499 l = aopGet (left, MSB32, FALSE, FALSE, NULL);
9502 emitcode ("rlc", "a");
9503 aopPut (result, "a", MSB32 + offr);
9506 aopPut (result, zero, LSB);
9512 /*-----------------------------------------------------------------*/
9513 /* genlshFour - shift four byte by a known amount != 0 */
9514 /*-----------------------------------------------------------------*/
9516 genlshFour (operand * result, operand * left, int shCount)
9520 D (emitcode (";", "genlshFour"));
9522 size = AOP_SIZE (result);
9524 /* if shifting more that 3 bytes */
9529 /* lowest order of left goes to the highest
9530 order of the destination */
9531 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
9533 movLeft2Result (left, LSB, result, MSB32, 0);
9534 aopPut (result, zero, LSB);
9535 aopPut (result, zero, MSB16);
9536 aopPut (result, zero, MSB24);
9540 /* more than two bytes */
9541 else if (shCount >= 16)
9543 /* lower order two bytes goes to higher order two bytes */
9545 /* if some more remaining */
9547 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
9550 movLeft2Result (left, MSB16, result, MSB32, 0);
9551 movLeft2Result (left, LSB, result, MSB24, 0);
9553 aopPut (result, zero, MSB16);
9554 aopPut (result, zero, LSB);
9558 /* if more than 1 byte */
9559 else if (shCount >= 8)
9561 /* lower order three bytes goes to higher order three bytes */
9566 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
9568 movLeft2Result (left, LSB, result, MSB16, 0);
9574 movLeft2Result (left, MSB24, result, MSB32, 0);
9575 movLeft2Result (left, MSB16, result, MSB24, 0);
9576 movLeft2Result (left, LSB, result, MSB16, 0);
9577 aopPut (result, zero, LSB);
9579 else if (shCount == 1)
9580 shiftLLong (left, result, MSB16);
9583 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
9584 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
9585 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
9586 aopPut (result, zero, LSB);
9591 /* 1 <= shCount <= 7 */
9592 else if (shCount <= 2)
9594 shiftLLong (left, result, LSB);
9596 shiftLLong (result, result, LSB);
9598 /* 3 <= shCount <= 7, optimize */
9601 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
9602 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
9603 shiftL2Left2Result (left, LSB, result, LSB, shCount);
9608 #ifdef BETTER_LITERAL_SHIFT
9609 /*-----------------------------------------------------------------*/
9610 /* genLeftShiftLiteral - left shifting by known count */
9611 /*-----------------------------------------------------------------*/
9613 genLeftShiftLiteral (operand * left,
9618 int shCount = (int) ulFromVal (AOP (right)->aopu.aop_lit);
9621 size = getSize (operandType (result));
9623 D (emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
9625 /* We only handle certain easy cases so far. */
9627 && (shCount < (size * 8))
9631 D(emitcode (";", "genLeftShiftLiteral wimping out"););
9635 freeAsmop (right, NULL, ic, TRUE);
9637 aopOp(left, ic, FALSE, FALSE);
9638 aopOp(result, ic, FALSE, AOP_USESDPTR(left));
9641 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
9643 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
9644 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
9646 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
9649 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
9651 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
9652 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
9654 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
9660 emitcode ("; shift left ", "result %d, left %d", size,
9664 /* I suppose that the left size >= result size */
9667 _startLazyDPSEvaluation();
9670 movLeft2Result (left, size, result, size, 0);
9672 _endLazyDPSEvaluation();
9674 else if (shCount >= (size * 8))
9676 _startLazyDPSEvaluation();
9679 aopPut (result, zero, size);
9681 _endLazyDPSEvaluation();
9688 genlshOne (result, left, shCount);
9692 genlshTwo (result, left, shCount);
9696 genlshFour (result, left, shCount);
9700 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9701 "*** ack! mystery literal shift!\n");
9705 freeAsmop (result, NULL, ic, TRUE);
9706 freeAsmop (left, NULL, ic, TRUE);
9711 /*-----------------------------------------------------------------*/
9712 /* genLeftShift - generates code for left shifting */
9713 /*-----------------------------------------------------------------*/
9715 genLeftShift (iCode * ic)
9717 operand *left, *right, *result;
9720 symbol *tlbl, *tlbl1;
9723 D (emitcode (";", "genLeftShift"));
9725 right = IC_RIGHT (ic);
9726 left = IC_LEFT (ic);
9727 result = IC_RESULT (ic);
9729 aopOp (right, ic, FALSE, FALSE);
9732 #ifdef BETTER_LITERAL_SHIFT
9733 /* if the shift count is known then do it
9734 as efficiently as possible */
9735 if (AOP_TYPE (right) == AOP_LIT)
9737 if (genLeftShiftLiteral (left, right, result, ic))
9744 /* shift count is unknown then we have to form
9745 a loop get the loop count in B : Note: we take
9746 only the lower order byte since shifting
9747 more that 32 bits make no sense anyway, ( the
9748 largest size of an object can be only 32 bits ) */
9751 if (AOP_TYPE (right) == AOP_LIT)
9753 /* Really should be handled by genLeftShiftLiteral,
9754 * but since I'm too lazy to fix that today, at least we can make
9755 * some small improvement.
9757 emitcode("mov", "b,#!constbyte",
9758 ((int) ulFromVal (AOP (right)->aopu.aop_lit)) + 1);
9762 MOVB (aopGet (right, 0, FALSE, FALSE, "b"));
9763 emitcode ("inc", "b");
9765 freeAsmop (right, NULL, ic, TRUE);
9766 aopOp (left, ic, FALSE, FALSE);
9767 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9769 /* now move the left to the result if they are not the same */
9770 if (!sameRegs (AOP (left), AOP (result)) &&
9771 AOP_SIZE (result) > 1)
9774 size = AOP_SIZE (result);
9776 _startLazyDPSEvaluation ();
9779 l = aopGet (left, offset, FALSE, TRUE, NULL);
9780 if (*l == '@' && (IS_AOP_PREG (result)))
9783 emitcode ("mov", "a,%s", l);
9784 aopPut (result, "a", offset);
9787 aopPut (result, l, offset);
9790 _endLazyDPSEvaluation ();
9793 tlbl = newiTempLabel (NULL);
9794 size = AOP_SIZE (result);
9796 tlbl1 = newiTempLabel (NULL);
9798 /* if it is only one byte then */
9801 symbol *tlbl1 = newiTempLabel (NULL);
9803 l = aopGet (left, 0, FALSE, FALSE, NULL);
9805 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9807 emitcode ("add", "a,acc");
9809 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9811 aopPut (result, "a", 0);
9815 reAdjustPreg (AOP (result));
9817 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9819 l = aopGet (result, offset, FALSE, FALSE, NULL);
9821 emitcode ("add", "a,acc");
9822 aopPut (result, "a", offset++);
9823 _startLazyDPSEvaluation ();
9826 l = aopGet (result, offset, FALSE, FALSE, NULL);
9828 emitcode ("rlc", "a");
9829 aopPut (result, "a", offset++);
9831 _endLazyDPSEvaluation ();
9832 reAdjustPreg (AOP (result));
9835 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9838 freeAsmop (result, NULL, ic, TRUE);
9839 freeAsmop (left, NULL, ic, TRUE);
9842 #ifdef BETTER_LITERAL_SHIFT
9843 /*-----------------------------------------------------------------*/
9844 /* genrshOne - right shift a one byte quantity by known count */
9845 /*-----------------------------------------------------------------*/
9847 genrshOne (operand * result, operand * left,
9848 int shCount, int sign)
9850 D (emitcode (";", "genrshOne"));
9852 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9856 #ifdef BETTER_LITERAL_SHIFT
9857 /*-----------------------------------------------------------------*/
9858 /* genrshTwo - right shift two bytes by known amount != 0 */
9859 /*-----------------------------------------------------------------*/
9861 genrshTwo (operand * result, operand * left,
9862 int shCount, int sign)
9864 D (emitcode (";", "genrshTwo"));
9866 /* if shCount >= 8 */
9870 _startLazyDPSEvaluation();
9872 shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
9874 movLeft2Result (left, MSB16, result, LSB, sign);
9875 addSign (result, MSB16, sign);
9876 _endLazyDPSEvaluation();
9879 /* 1 <= shCount <= 7 */
9881 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9885 /*-----------------------------------------------------------------*/
9886 /* shiftRLong - shift right one long from left to result */
9887 /* offl = LSB or MSB16 */
9888 /*-----------------------------------------------------------------*/
9890 shiftRLong (operand * left, int offl,
9891 operand * result, int sign)
9893 bool overlapping = regsInCommon (left, result) || operandsEqu(left, result);
9895 if (overlapping && offl>1)
9897 // we are in big trouble, but this shouldn't happen
9898 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9901 MOVA (aopGet (left, MSB32, FALSE, FALSE, NULL));
9908 emitcode ("rlc", "a");
9909 emitcode ("subb", "a,acc");
9910 emitcode ("xch", "a,%s",
9911 aopGet(left, MSB32, FALSE, FALSE, DP2_RESULT_REG));
9915 aopPut (result, zero, MSB32);
9921 emitcode ("clr", "c");
9925 emitcode ("mov", "c,acc.7");
9928 emitcode ("rrc", "a");
9930 if (overlapping && offl==MSB16)
9932 emitcode ("xch", "a,%s", aopGet (left, MSB24, FALSE, FALSE, DP2_RESULT_REG));
9936 aopPut (result, "a", MSB32 - offl);
9937 MOVA (aopGet (left, MSB24, FALSE, FALSE, NULL));
9940 emitcode ("rrc", "a");
9942 if (overlapping && offl==MSB16)
9944 emitcode ("xch", "a,%s", aopGet (left, MSB16, FALSE, FALSE, DP2_RESULT_REG));
9948 aopPut (result, "a", MSB24 - offl);
9949 MOVA (aopGet (left, MSB16, FALSE, FALSE, NULL));
9952 emitcode ("rrc", "a");
9955 aopPut (result, "a", MSB16 - offl);
9959 if (overlapping && offl==MSB16)
9961 emitcode ("xch", "a,%s", aopGet (left, LSB, FALSE, FALSE, DP2_RESULT_REG));
9965 aopPut (result, "a", MSB16 - offl);
9966 MOVA (aopGet (left, LSB, FALSE, FALSE, NULL));
9968 emitcode ("rrc", "a");
9969 aopPut (result, "a", LSB);
9973 /*-----------------------------------------------------------------*/
9974 /* genrshFour - shift four byte by a known amount != 0 */
9975 /*-----------------------------------------------------------------*/
9977 genrshFour (operand * result, operand * left,
9978 int shCount, int sign)
9980 D (emitcode (";", "genrshFour"));
9982 /* if shifting more that 3 bytes */
9986 _startLazyDPSEvaluation();
9988 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9990 movLeft2Result (left, MSB32, result, LSB, sign);
9991 addSign (result, MSB16, sign);
9992 _endLazyDPSEvaluation();
9994 else if (shCount >= 16)
9997 _startLazyDPSEvaluation();
9999 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
10002 movLeft2Result (left, MSB24, result, LSB, 0);
10003 movLeft2Result (left, MSB32, result, MSB16, sign);
10005 addSign (result, MSB24, sign);
10006 _endLazyDPSEvaluation();
10008 else if (shCount >= 8)
10011 _startLazyDPSEvaluation();
10014 shiftRLong (left, MSB16, result, sign);
10016 else if (shCount == 0)
10018 movLeft2Result (left, MSB16, result, LSB, 0);
10019 movLeft2Result (left, MSB24, result, MSB16, 0);
10020 movLeft2Result (left, MSB32, result, MSB24, sign);
10021 addSign (result, MSB32, sign);
10025 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
10026 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
10027 /* the last shift is signed */
10028 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
10029 addSign (result, MSB32, sign);
10031 _endLazyDPSEvaluation();
10035 /* 1 <= shCount <= 7 */
10038 shiftRLong (left, LSB, result, sign);
10040 shiftRLong (result, LSB, result, sign);
10044 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
10045 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
10046 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
10051 #ifdef BETTER_LITERAL_SHIFT
10052 /*-----------------------------------------------------------------*/
10053 /* genRightShiftLiteral - right shifting by known count */
10054 /*-----------------------------------------------------------------*/
10056 genRightShiftLiteral (operand * left,
10062 int shCount = (int) ulFromVal (AOP (right)->aopu.aop_lit);
10065 size = getSize (operandType (result));
10067 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
10069 /* We only handle certain easy cases so far. */
10071 && (shCount < (size * 8))
10076 D(emitcode (";", "genRightShiftLiteral wimping out"););
10080 freeAsmop (right, NULL, ic, TRUE);
10082 aopOp (left, ic, FALSE, FALSE);
10083 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
10086 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
10090 /* test the LEFT size !!! */
10092 /* I suppose that the left size >= result size */
10095 size = getDataSize (result);
10096 _startLazyDPSEvaluation();
10098 movLeft2Result (left, size, result, size, 0);
10099 _endLazyDPSEvaluation();
10101 else if (shCount >= (size * 8))
10105 /* get sign in acc.7 */
10106 MOVA (aopGet (left, size - 1, FALSE, FALSE, NULL));
10108 addSign (result, LSB, sign);
10115 genrshOne (result, left, shCount, sign);
10119 genrshTwo (result, left, shCount, sign);
10123 genrshFour (result, left, shCount, sign);
10130 freeAsmop (result, NULL, ic, TRUE);
10131 freeAsmop (left, NULL, ic, TRUE);
10137 /*-----------------------------------------------------------------*/
10138 /* genSignedRightShift - right shift of signed number */
10139 /*-----------------------------------------------------------------*/
10141 genSignedRightShift (iCode * ic)
10143 operand *right, *left, *result;
10146 symbol *tlbl, *tlbl1;
10149 D (emitcode (";", "genSignedRightShift"));
10151 /* we do it the hard way put the shift count in b
10152 and loop thru preserving the sign */
10154 right = IC_RIGHT (ic);
10155 left = IC_LEFT (ic);
10156 result = IC_RESULT (ic);
10158 aopOp (right, ic, FALSE, FALSE);
10160 #ifdef BETTER_LITERAL_SHIFT
10161 if (AOP_TYPE (right) == AOP_LIT)
10163 if (genRightShiftLiteral (left, right, result, ic, 1))
10169 /* shift count is unknown then we have to form
10170 a loop get the loop count in B : Note: we take
10171 only the lower order byte since shifting
10172 more that 32 bits make no sense anyway, ( the
10173 largest size of an object can be only 32 bits ) */
10175 pushedB = pushB ();
10176 if (AOP_TYPE (right) == AOP_LIT)
10178 /* Really should be handled by genRightShiftLiteral,
10179 * but since I'm too lazy to fix that today, at least we can make
10180 * some small improvement.
10182 emitcode("mov", "b,#!constbyte",
10183 ((int) ulFromVal (AOP (right)->aopu.aop_lit)) + 1);
10187 MOVB (aopGet (right, 0, FALSE, FALSE, "b"));
10188 emitcode ("inc", "b");
10190 freeAsmop (right, NULL, ic, TRUE);
10191 aopOp (left, ic, FALSE, FALSE);
10192 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
10194 /* now move the left to the result if they are not the
10196 if (!sameRegs (AOP (left), AOP (result)) &&
10197 AOP_SIZE (result) > 1)
10200 size = AOP_SIZE (result);
10202 _startLazyDPSEvaluation ();
10205 l = aopGet (left, offset, FALSE, TRUE, NULL);
10206 if (*l == '@' && IS_AOP_PREG (result))
10209 emitcode ("mov", "a,%s", l);
10210 aopPut (result, "a", offset);
10213 aopPut (result, l, offset);
10216 _endLazyDPSEvaluation ();
10219 /* mov the highest order bit to OVR */
10220 tlbl = newiTempLabel (NULL);
10221 tlbl1 = newiTempLabel (NULL);
10223 size = AOP_SIZE (result);
10225 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
10226 emitcode ("rlc", "a");
10227 emitcode ("mov", "ov,c");
10228 /* if it is only one byte then */
10231 l = aopGet (left, 0, FALSE, FALSE, NULL);
10233 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
10235 emitcode ("mov", "c,ov");
10236 emitcode ("rrc", "a");
10238 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
10240 aopPut (result, "a", 0);
10244 reAdjustPreg (AOP (result));
10245 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
10247 emitcode ("mov", "c,ov");
10248 _startLazyDPSEvaluation ();
10251 l = aopGet (result, offset, FALSE, FALSE, NULL);
10253 emitcode ("rrc", "a");
10254 aopPut (result, "a", offset--);
10256 _endLazyDPSEvaluation ();
10257 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 /* genRightShift - generate code for right shifting */
10269 /*-----------------------------------------------------------------*/
10271 genRightShift (iCode * ic)
10273 operand *right, *left, *result;
10277 symbol *tlbl, *tlbl1;
10280 D (emitcode (";", "genRightShift"));
10282 /* if signed then we do it the hard way preserve the
10283 sign bit moving it inwards */
10284 letype = getSpec (operandType (IC_LEFT (ic)));
10286 if (!SPEC_USIGN (letype))
10288 genSignedRightShift (ic);
10292 /* signed & unsigned types are treated the same : i.e. the
10293 signed is NOT propagated inwards : quoting from the
10294 ANSI - standard : "for E1 >> E2, is equivalent to division
10295 by 2**E2 if unsigned or if it has a non-negative value,
10296 otherwise the result is implementation defined ", MY definition
10297 is that the sign does not get propagated */
10299 right = IC_RIGHT (ic);
10300 left = IC_LEFT (ic);
10301 result = IC_RESULT (ic);
10303 aopOp (right, ic, FALSE, FALSE);
10305 #ifdef BETTER_LITERAL_SHIFT
10306 /* if the shift count is known then do it
10307 as efficiently as possible */
10308 if (AOP_TYPE (right) == AOP_LIT)
10310 if (genRightShiftLiteral (left, right, result, ic, 0))
10317 /* shift count is unknown then we have to form
10318 a loop get the loop count in B : Note: we take
10319 only the lower order byte since shifting
10320 more that 32 bits make no sense anyway, ( the
10321 largest size of an object can be only 32 bits ) */
10323 pushedB = pushB ();
10324 if (AOP_TYPE (right) == AOP_LIT)
10326 /* Really should be handled by genRightShiftLiteral,
10327 * but since I'm too lazy to fix that today, at least we can make
10328 * some small improvement.
10330 emitcode("mov", "b,#!constbyte",
10331 ((int) ulFromVal (AOP (right)->aopu.aop_lit)) + 1);
10335 MOVB (aopGet (right, 0, FALSE, FALSE, "b"));
10336 emitcode ("inc", "b");
10338 freeAsmop (right, NULL, ic, TRUE);
10339 aopOp (left, ic, FALSE, FALSE);
10340 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
10342 /* now move the left to the result if they are not the
10344 if (!sameRegs (AOP (left), AOP (result)) &&
10345 AOP_SIZE (result) > 1)
10347 size = AOP_SIZE (result);
10349 _startLazyDPSEvaluation ();
10352 l = aopGet (left, offset, FALSE, TRUE, NULL);
10353 if (*l == '@' && IS_AOP_PREG (result))
10356 emitcode ("mov", "a,%s", l);
10357 aopPut (result, "a", offset);
10360 aopPut (result, l, offset);
10363 _endLazyDPSEvaluation ();
10366 tlbl = newiTempLabel (NULL);
10367 tlbl1 = newiTempLabel (NULL);
10368 size = AOP_SIZE (result);
10371 /* if it is only one byte then */
10374 l = aopGet (left, 0, FALSE, FALSE, NULL);
10376 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
10379 emitcode ("rrc", "a");
10381 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
10383 aopPut (result, "a", 0);
10387 reAdjustPreg (AOP (result));
10388 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
10391 _startLazyDPSEvaluation ();
10394 l = aopGet (result, offset, FALSE, FALSE, NULL);
10396 emitcode ("rrc", "a");
10397 aopPut (result, "a", offset--);
10399 _endLazyDPSEvaluation ();
10400 reAdjustPreg (AOP (result));
10403 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
10407 freeAsmop (result, NULL, ic, TRUE);
10408 freeAsmop (left, NULL, ic, TRUE);
10411 /*-----------------------------------------------------------------*/
10412 /* emitPtrByteGet - emits code to get a byte into A through a */
10413 /* pointer register (R0, R1, or DPTR). The */
10414 /* original value of A can be preserved in B. */
10415 /*-----------------------------------------------------------------*/
10417 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
10424 emitcode ("mov", "b,a");
10425 emitcode ("mov", "a,@%s", rname);
10430 emitcode ("mov", "b,a");
10431 emitcode ("movx", "a,@%s", rname);
10436 emitcode ("mov", "b,a");
10437 emitcode ("movx", "a,@dptr");
10442 emitcode ("mov", "b,a");
10443 emitcode ("clr", "a");
10444 emitcode ("movc", "a,@a+dptr");
10450 emitcode ("push", "b");
10451 emitcode ("push", "acc");
10453 emitcode ("lcall", "__gptrget");
10455 emitcode ("pop", "b");
10460 /*-----------------------------------------------------------------*/
10461 /* emitPtrByteSet - emits code to set a byte from src through a */
10462 /* pointer register (R0, R1, or DPTR). */
10463 /*-----------------------------------------------------------------*/
10465 emitPtrByteSet (char *rname, int p_type, char *src)
10474 emitcode ("mov", "@%s,a", rname);
10477 emitcode ("mov", "@%s,%s", rname, src);
10482 emitcode ("movx", "@%s,a", rname);
10487 emitcode ("movx", "@dptr,a");
10492 emitcode ("lcall", "__gptrput");
10497 /*-----------------------------------------------------------------*/
10498 /* genUnpackBits - generates code for unpacking bits */
10499 /*-----------------------------------------------------------------*/
10501 genUnpackBits (operand * result, char *rname, int ptype)
10503 int offset = 0; /* result byte offset */
10504 int rsize; /* result size */
10505 int rlen = 0; /* remaining bitfield length */
10506 sym_link *etype; /* bitfield type information */
10507 int blen; /* bitfield length */
10508 int bstr; /* bitfield starting bit within byte */
10510 D(emitcode (";", "genUnpackBits"));
10512 etype = getSpec (operandType (result));
10513 rsize = getSize (operandType (result));
10514 blen = SPEC_BLEN (etype);
10515 bstr = SPEC_BSTR (etype);
10517 /* If the bitfield length is less than a byte */
10520 emitPtrByteGet (rname, ptype, FALSE);
10522 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
10523 if (!SPEC_USIGN (etype))
10525 /* signed bitfield */
10526 symbol *tlbl = newiTempLabel (NULL);
10528 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
10529 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
10532 aopPut (result, "a", offset++);
10536 /* Bit field did not fit in a byte. Copy all
10537 but the partial byte at the end. */
10538 for (rlen=blen;rlen>=8;rlen-=8)
10540 emitPtrByteGet (rname, ptype, FALSE);
10541 aopPut (result, "a", offset++);
10543 emitcode ("inc", "%s", rname);
10546 /* Handle the partial byte at the end */
10549 emitPtrByteGet (rname, ptype, FALSE);
10550 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
10551 if (!SPEC_USIGN (etype))
10553 /* signed bitfield */
10554 symbol *tlbl = newiTempLabel (NULL);
10556 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
10557 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
10560 aopPut (result, "a", offset++);
10564 if (offset < rsize)
10568 if (SPEC_USIGN (etype))
10572 /* signed bitfield: sign extension with 0x00 or 0xff */
10573 emitcode ("rlc", "a");
10574 emitcode ("subb", "a,acc");
10580 aopPut (result, source, offset++);
10585 /*-----------------------------------------------------------------*/
10586 /* genDataPointerGet - generates code when ptr offset is known */
10587 /*-----------------------------------------------------------------*/
10589 genDataPointerGet (operand * left,
10595 int size, offset = 0;
10596 aopOp (result, ic, TRUE, FALSE);
10598 /* get the string representation of the name */
10599 l = aopGet (left, 0, FALSE, TRUE, NULL);
10600 size = AOP_SIZE (result);
10601 _startLazyDPSEvaluation ();
10606 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l + 1, offset);
10610 SNPRINTF (buffer, sizeof(buffer), "%s", l + 1);
10612 aopPut (result, buffer, offset++);
10614 _endLazyDPSEvaluation ();
10616 freeAsmop (result, NULL, ic, TRUE);
10617 freeAsmop (left, NULL, ic, TRUE);
10620 /*-----------------------------------------------------------------*/
10621 /* genNearPointerGet - emitcode for near pointer fetch */
10622 /*-----------------------------------------------------------------*/
10624 genNearPointerGet (operand * left,
10632 sym_link *rtype, *retype, *letype;
10633 sym_link *ltype = operandType (left);
10636 rtype = operandType (result);
10637 retype = getSpec (rtype);
10638 letype = getSpec (ltype);
10640 aopOp (left, ic, FALSE, FALSE);
10642 /* if left is rematerialisable and
10643 result is not bitfield variable type and
10644 the left is pointer to data space i.e
10645 lower 128 bytes of space */
10646 if (AOP_TYPE (left) == AOP_IMMD &&
10647 !IS_BITFIELD (retype) &&
10648 !IS_BITFIELD (letype) &&
10649 DCL_TYPE (ltype) == POINTER)
10651 genDataPointerGet (left, result, ic);
10655 /* if the value is already in a pointer register
10656 then don't need anything more */
10657 if (!AOP_INPREG (AOP (left)))
10659 /* otherwise get a free pointer register */
10660 aop = newAsmop (0);
10661 preg = getFreePtr (ic, &aop, FALSE);
10662 emitcode ("mov", "%s,%s",
10664 aopGet (left, 0, FALSE, TRUE, DP2_RESULT_REG));
10665 rname = preg->name;
10668 rname = aopGet (left, 0, FALSE, FALSE, DP2_RESULT_REG);
10670 freeAsmop (left, NULL, ic, TRUE);
10671 aopOp (result, ic, FALSE, FALSE);
10673 /* if bitfield then unpack the bits */
10674 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10675 genUnpackBits (result, rname, POINTER);
10678 /* we have can just get the values */
10679 int size = AOP_SIZE (result);
10684 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
10687 emitcode ("mov", "a,@%s", rname);
10688 aopPut (result, "a", offset);
10692 SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
10693 aopPut (result, buffer, offset);
10697 emitcode ("inc", "%s", rname);
10701 /* now some housekeeping stuff */
10702 if (aop) /* we had to allocate for this iCode */
10704 if (pi) { /* post increment present */
10705 aopPut (left, rname, 0);
10707 freeAsmop (NULL, aop, ic, TRUE);
10711 /* we did not allocate which means left
10712 already in a pointer register, then
10713 if size > 0 && this could be used again
10714 we have to point it back to where it
10716 if (AOP_SIZE (result) > 1 &&
10717 !OP_SYMBOL (left)->remat &&
10718 (OP_SYMBOL (left)->liveTo > ic->seq ||
10722 int size = AOP_SIZE (result) - 1;
10724 emitcode ("dec", "%s", rname);
10729 freeAsmop (result, NULL, ic, TRUE);
10730 if (pi) pi->generated = 1;
10733 /*-----------------------------------------------------------------*/
10734 /* genPagedPointerGet - emitcode for paged pointer fetch */
10735 /*-----------------------------------------------------------------*/
10737 genPagedPointerGet (operand * left,
10745 sym_link *rtype, *retype, *letype;
10747 rtype = operandType (result);
10748 retype = getSpec (rtype);
10749 letype = getSpec (operandType (left));
10750 aopOp (left, ic, FALSE, FALSE);
10752 /* if the value is already in a pointer register
10753 then don't need anything more */
10754 if (!AOP_INPREG (AOP (left)))
10756 /* otherwise get a free pointer register */
10757 aop = newAsmop (0);
10758 preg = getFreePtr (ic, &aop, FALSE);
10759 emitcode ("mov", "%s,%s",
10761 aopGet (left, 0, FALSE, TRUE, NULL));
10762 rname = preg->name;
10765 rname = aopGet (left, 0, FALSE, FALSE, NULL);
10767 freeAsmop (left, NULL, ic, TRUE);
10768 aopOp (result, ic, FALSE, FALSE);
10770 /* if bitfield then unpack the bits */
10771 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10772 genUnpackBits (result, rname, PPOINTER);
10775 /* we have can just get the values */
10776 int size = AOP_SIZE (result);
10782 emitcode ("movx", "a,@%s", rname);
10783 aopPut (result, "a", offset);
10788 emitcode ("inc", "%s", rname);
10792 /* now some housekeeping stuff */
10793 if (aop) /* we had to allocate for this iCode */
10796 aopPut (left, rname, 0);
10797 freeAsmop (NULL, aop, ic, TRUE);
10801 /* we did not allocate which means left
10802 already in a pointer register, then
10803 if size > 0 && this could be used again
10804 we have to point it back to where it
10806 if (AOP_SIZE (result) > 1 &&
10807 !OP_SYMBOL (left)->remat &&
10808 (OP_SYMBOL (left)->liveTo > ic->seq ||
10812 int size = AOP_SIZE (result) - 1;
10814 emitcode ("dec", "%s", rname);
10819 freeAsmop (result, NULL, ic, TRUE);
10820 if (pi) pi->generated = 1;
10823 /*-----------------------------------------------------------------*/
10824 /* genFarPointerGet - get value from far space */
10825 /*-----------------------------------------------------------------*/
10827 genFarPointerGet (operand * left,
10828 operand * result, iCode * ic, iCode *pi)
10830 int size, offset, dopi=1;
10831 sym_link *retype = getSpec (operandType (result));
10832 sym_link *letype = getSpec (operandType (left));
10833 D (emitcode (";", "genFarPointerGet"););
10835 aopOp (left, ic, FALSE, FALSE);
10837 /* if the operand is already in dptr
10838 then we do nothing else we move the value to dptr */
10839 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
10841 /* if this is rematerializable */
10842 if (AOP_TYPE (left) == AOP_IMMD)
10844 emitcode ("mov", "dptr,%s", aopGet (left, 0, TRUE, FALSE, NULL));
10848 /* we need to get it byte by byte */
10849 _startLazyDPSEvaluation ();
10850 if (AOP_TYPE (left) != AOP_DPTR)
10852 emitcode ("mov", "dpl,%s", aopGet (left, 0, FALSE, FALSE, NULL));
10853 emitcode ("mov", "dph,%s", aopGet (left, 1, FALSE, FALSE, NULL));
10854 if (options.model == MODEL_FLAT24)
10855 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10859 /* We need to generate a load to DPTR indirect through DPTR. */
10860 D (emitcode (";", "genFarPointerGet -- indirection special case."););
10861 emitcode ("push", "%s", aopGet (left, 0, FALSE, TRUE, NULL));
10862 emitcode ("push", "%s", aopGet (left, 1, FALSE, TRUE, NULL));
10863 if (options.model == MODEL_FLAT24)
10864 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10865 emitcode ("pop", "dph");
10866 emitcode ("pop", "dpl");
10869 _endLazyDPSEvaluation ();
10872 /* so dptr now contains the address */
10873 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10875 /* if bit then unpack */
10876 if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
10877 if (AOP_INDPTRn(left)) {
10878 genSetDPTR(AOP(left)->aopu.dptr);
10880 genUnpackBits (result, "dptr", FPOINTER);
10881 if (AOP_INDPTRn(left)) {
10886 size = AOP_SIZE (result);
10889 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10891 genSetDPTR(AOP(left)->aopu.dptr);
10892 emitcode ("movx", "a,@dptr");
10893 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10894 emitcode ("inc", "dptr");
10896 aopPut (result, "a", offset++);
10899 _startLazyDPSEvaluation ();
10901 if (AOP_INDPTRn(left)) {
10902 genSetDPTR(AOP(left)->aopu.dptr);
10908 emitcode ("movx", "a,@dptr");
10909 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10910 emitcode ("inc", "dptr");
10912 aopPut (result, "a", offset++);
10914 _endLazyDPSEvaluation ();
10917 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10918 if (!AOP_INDPTRn(left)) {
10919 _startLazyDPSEvaluation ();
10920 aopPut (left, "dpl", 0);
10921 aopPut (left, "dph", 1);
10922 if (options.model == MODEL_FLAT24)
10923 aopPut (left, "dpx", 2);
10924 _endLazyDPSEvaluation ();
10927 } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) &&
10928 AOP_SIZE(result) > 1 &&
10930 (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
10932 size = AOP_SIZE (result) - 1;
10933 if (AOP_INDPTRn(left)) {
10934 genSetDPTR(AOP(left)->aopu.dptr);
10936 while (size--) emitcode ("lcall","__decdptr");
10937 if (AOP_INDPTRn(left)) {
10942 freeAsmop (result, NULL, ic, TRUE);
10943 freeAsmop (left, NULL, ic, TRUE);
10946 /*-----------------------------------------------------------------*/
10947 /* genCodePointerGet - get value from code space */
10948 /*-----------------------------------------------------------------*/
10950 genCodePointerGet (operand * left,
10951 operand * result, iCode * ic, iCode *pi)
10953 int size, offset, dopi=1;
10954 sym_link *retype = getSpec (operandType (result));
10956 aopOp (left, ic, FALSE, FALSE);
10958 /* if the operand is already in dptr
10959 then we do nothing else we move the value to dptr */
10960 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
10962 /* if this is rematerializable */
10963 if (AOP_TYPE (left) == AOP_IMMD)
10965 emitcode ("mov", "dptr,%s", aopGet (left, 0, TRUE, FALSE, NULL));
10968 { /* we need to get it byte by byte */
10969 _startLazyDPSEvaluation ();
10970 if (AOP_TYPE (left) != AOP_DPTR)
10972 emitcode ("mov", "dpl,%s", aopGet (left, 0, FALSE, FALSE, NULL));
10973 emitcode ("mov", "dph,%s", aopGet (left, 1, FALSE, FALSE, NULL));
10974 if (options.model == MODEL_FLAT24)
10975 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10979 /* We need to generate a load to DPTR indirect through DPTR. */
10980 D (emitcode (";", "gencodePointerGet -- indirection special case."););
10981 emitcode ("push", "%s", aopGet (left, 0, FALSE, TRUE, NULL));
10982 emitcode ("push", "%s", aopGet (left, 1, FALSE, TRUE, NULL));
10983 if (options.model == MODEL_FLAT24)
10984 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10985 emitcode ("pop", "dph");
10986 emitcode ("pop", "dpl");
10989 _endLazyDPSEvaluation ();
10992 /* so dptr now contains the address */
10993 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10995 /* if bit then unpack */
10996 if (IS_BITFIELD (retype)) {
10997 if (AOP_INDPTRn(left)) {
10998 genSetDPTR(AOP(left)->aopu.dptr);
11000 genUnpackBits (result, "dptr", CPOINTER);
11001 if (AOP_INDPTRn(left)) {
11006 size = AOP_SIZE (result);
11008 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
11010 genSetDPTR(AOP(left)->aopu.dptr);
11011 emitcode ("clr", "a");
11012 emitcode ("movc", "a,@a+dptr");
11013 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
11014 emitcode ("inc", "dptr");
11016 aopPut (result, "a", offset++);
11019 _startLazyDPSEvaluation ();
11022 if (AOP_INDPTRn(left)) {
11023 genSetDPTR(AOP(left)->aopu.dptr);
11029 emitcode ("clr", "a");
11030 emitcode ("movc", "a,@a+dptr");
11031 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
11032 emitcode ("inc", "dptr");
11033 aopPut (result, "a", offset++);
11035 _endLazyDPSEvaluation ();
11038 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
11039 if (!AOP_INDPTRn(left)) {
11040 _startLazyDPSEvaluation ();
11042 aopPut (left, "dpl", 0);
11043 aopPut (left, "dph", 1);
11044 if (options.model == MODEL_FLAT24)
11045 aopPut (left, "dpx", 2);
11047 _endLazyDPSEvaluation ();
11050 } else if (IS_SYMOP(left) &&
11051 (OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
11052 AOP_SIZE(result) > 1 &&
11053 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
11055 size = AOP_SIZE (result) - 1;
11056 if (AOP_INDPTRn(left)) {
11057 genSetDPTR(AOP(left)->aopu.dptr);
11059 while (size--) emitcode ("lcall","__decdptr");
11060 if (AOP_INDPTRn(left)) {
11065 freeAsmop (result, NULL, ic, TRUE);
11066 freeAsmop (left, NULL, ic, TRUE);
11069 /*-----------------------------------------------------------------*/
11070 /* genGenPointerGet - get value from generic pointer space */
11071 /*-----------------------------------------------------------------*/
11073 genGenPointerGet (operand * left,
11074 operand * result, iCode * ic, iCode * pi)
11078 sym_link *retype = getSpec (operandType (result));
11079 sym_link *letype = getSpec (operandType (left));
11081 D (emitcode (";", "genGenPointerGet"));
11083 aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
11085 pushedB = pushB ();
11086 /* if the operand is already in dptr
11087 then we do nothing else we move the value to dptr */
11088 if (AOP_TYPE (left) != AOP_STR)
11090 /* if this is rematerializable */
11091 if (AOP_TYPE (left) == AOP_IMMD)
11093 emitcode ("mov", "dptr,%s", aopGet (left, 0, TRUE, FALSE, NULL));
11094 if (AOP(left)->aopu.aop_immd.from_cast_remat)
11096 MOVB (aopGet (left, AOP_SIZE(left)-1, FALSE, FALSE, NULL));
11100 emitcode ("mov", "b,#%d", pointerCode (retype));
11104 { /* we need to get it byte by byte */
11105 _startLazyDPSEvaluation ();
11106 emitcode ("mov", "dpl,%s", aopGet (left,0,FALSE,FALSE,NULL));
11107 emitcode ("mov", "dph,%s", aopGet (left,1,FALSE,FALSE,NULL));
11108 if (options.model == MODEL_FLAT24) {
11109 emitcode ("mov", "dpx,%s", aopGet (left,2,FALSE,FALSE,NULL));
11110 emitcode ("mov", "b,%s", aopGet (left,3,FALSE,FALSE,NULL));
11112 emitcode ("mov", "b,%s", aopGet (left,2,FALSE,FALSE,NULL));
11114 _endLazyDPSEvaluation ();
11118 /* so dptr-b now contains the address */
11119 aopOp (result, ic, FALSE, TRUE);
11121 /* if bit then unpack */
11122 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11124 genUnpackBits (result, "dptr", GPOINTER);
11128 size = AOP_SIZE (result);
11135 // Get two bytes at a time, results in _AP & A.
11136 // dptr will be incremented ONCE by __gptrgetWord.
11138 // Note: any change here must be coordinated
11139 // with the implementation of __gptrgetWord
11140 // in device/lib/_gptrget.c
11141 emitcode ("lcall", "__gptrgetWord");
11142 aopPut (result, "a", offset++);
11143 aopPut (result, DP2_RESULT_REG, offset++);
11148 // Only one byte to get.
11149 emitcode ("lcall", "__gptrget");
11150 aopPut (result, "a", offset++);
11153 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
11155 emitcode ("inc", "dptr");
11160 if (pi && AOP_TYPE (left) != AOP_IMMD) {
11161 _startLazyDPSEvaluation ();
11163 aopPut (left, "dpl", 0);
11164 aopPut (left, "dph", 1);
11165 if (options.model == MODEL_FLAT24) {
11166 aopPut (left, "dpx", 2);
11167 aopPut (left, "b", 3);
11168 } else aopPut (left, "b", 2);
11170 _endLazyDPSEvaluation ();
11173 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
11174 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
11176 size = AOP_SIZE (result) - 1;
11177 while (size--) emitcode ("lcall","__decdptr");
11181 freeAsmop (result, NULL, ic, TRUE);
11182 freeAsmop (left, NULL, ic, TRUE);
11185 /*-----------------------------------------------------------------*/
11186 /* genPointerGet - generate code for pointer get */
11187 /*-----------------------------------------------------------------*/
11189 genPointerGet (iCode * ic, iCode *pi)
11191 operand *left, *result;
11192 sym_link *type, *etype;
11195 D (emitcode (";", "genPointerGet"));
11197 left = IC_LEFT (ic);
11198 result = IC_RESULT (ic);
11200 /* depending on the type of pointer we need to
11201 move it to the correct pointer register */
11202 type = operandType (left);
11203 etype = getSpec (type);
11204 /* if left is of type of pointer then it is simple */
11205 if (IS_PTR (type) && !IS_FUNC (type->next))
11207 p_type = DCL_TYPE (type);
11211 /* we have to go by the storage class */
11212 p_type = PTR_TYPE (SPEC_OCLS (etype));
11215 /* special case when cast remat */
11216 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
11217 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
11219 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
11220 type = operandType (left);
11221 p_type = DCL_TYPE (type);
11223 /* now that we have the pointer type we assign
11224 the pointer values */
11230 genNearPointerGet (left, result, ic, pi);
11234 genPagedPointerGet (left, result, ic, pi);
11238 genFarPointerGet (left, result, ic, pi);
11242 genCodePointerGet (left, result, ic, pi);
11246 genGenPointerGet (left, result, ic, pi);
11252 /*-----------------------------------------------------------------*/
11253 /* genPackBits - generates code for packed bit storage */
11254 /*-----------------------------------------------------------------*/
11256 genPackBits (sym_link * etype,
11258 char *rname, int p_type)
11260 int offset = 0; /* source byte offset */
11261 int rlen = 0; /* remaining bitfield length */
11262 int blen; /* bitfield length */
11263 int bstr; /* bitfield starting bit within byte */
11264 int litval; /* source literal value (if AOP_LIT) */
11265 unsigned char mask; /* bitmask within current byte */
11267 D(emitcode (";", "genPackBits"));
11269 blen = SPEC_BLEN (etype);
11270 bstr = SPEC_BSTR (etype);
11272 /* If the bitfield length is less than a byte */
11275 mask = ((unsigned char) (0xFF << (blen + bstr)) |
11276 (unsigned char) (0xFF >> (8 - bstr)));
11278 if (AOP_TYPE (right) == AOP_LIT)
11280 /* Case with a bitfield length <8 and literal source
11282 litval = (int) ulFromVal (AOP (right)->aopu.aop_lit);
11284 litval &= (~mask) & 0xff;
11285 emitPtrByteGet (rname, p_type, FALSE);
11286 if ((mask|litval)!=0xff)
11287 emitcode ("anl","a,#!constbyte", mask);
11289 emitcode ("orl","a,#!constbyte", litval);
11293 if ((blen==1) && (p_type!=GPOINTER))
11295 /* Case with a bitfield length == 1 and no generic pointer
11297 if (AOP_TYPE (right) == AOP_CRY)
11298 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
11301 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
11302 emitcode ("rrc","a");
11304 emitPtrByteGet (rname, p_type, FALSE);
11305 emitcode ("mov","acc.%d,c",bstr);
11310 /* Case with a bitfield length < 8 and arbitrary source
11312 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
11313 /* shift and mask source value */
11315 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
11317 pushedB = pushB ();
11318 /* transfer A to B and get next byte */
11319 emitPtrByteGet (rname, p_type, TRUE);
11321 emitcode ("anl", "a,#!constbyte", mask);
11322 emitcode ("orl", "a,b");
11323 if (p_type == GPOINTER)
11324 emitcode ("pop", "b");
11330 emitPtrByteSet (rname, p_type, "a");
11334 /* Bit length is greater than 7 bits. In this case, copy */
11335 /* all except the partial byte at the end */
11336 for (rlen=blen;rlen>=8;rlen-=8)
11338 emitPtrByteSet (rname, p_type,
11339 aopGet (right, offset++, FALSE, TRUE, NULL) );
11341 emitcode ("inc", "%s", rname);
11344 /* If there was a partial byte at the end */
11347 mask = (((unsigned char) -1 << rlen) & 0xff);
11349 if (AOP_TYPE (right) == AOP_LIT)
11351 /* Case with partial byte and literal source
11353 litval = (int) ulFromVal (AOP (right)->aopu.aop_lit);
11354 litval >>= (blen-rlen);
11355 litval &= (~mask) & 0xff;
11356 emitPtrByteGet (rname, p_type, FALSE);
11357 if ((mask|litval)!=0xff)
11358 emitcode ("anl","a,#!constbyte", mask);
11360 emitcode ("orl","a,#!constbyte", litval);
11365 /* Case with partial byte and arbitrary source
11367 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11368 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
11370 pushedB = pushB ();
11371 /* transfer A to B and get next byte */
11372 emitPtrByteGet (rname, p_type, TRUE);
11374 emitcode ("anl", "a,#!constbyte", mask);
11375 emitcode ("orl", "a,b");
11376 if (p_type == GPOINTER)
11377 emitcode ("pop", "b");
11381 emitPtrByteSet (rname, p_type, "a");
11386 /*-----------------------------------------------------------------*/
11387 /* genDataPointerSet - remat pointer to data space */
11388 /*-----------------------------------------------------------------*/
11390 genDataPointerSet (operand * right,
11394 int size, offset = 0;
11395 char *l, buffer[256];
11397 D (emitcode (";", "genDataPointerSet"));
11399 aopOp (right, ic, FALSE, FALSE);
11401 l = aopGet (result, 0, FALSE, TRUE, NULL);
11402 size = AOP_SIZE (right);
11406 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l + 1, offset);
11408 SNPRINTF (buffer, sizeof(buffer), "%s", l + 1);
11409 emitcode ("mov", "%s,%s", buffer,
11410 aopGet (right, offset++, FALSE, FALSE, NULL));
11413 freeAsmop (right, NULL, ic, TRUE);
11414 freeAsmop (result, NULL, ic, TRUE);
11417 /*-----------------------------------------------------------------*/
11418 /* genNearPointerSet - emitcode for near pointer put */
11419 /*-----------------------------------------------------------------*/
11421 genNearPointerSet (operand * right,
11428 sym_link *retype, *letype;
11429 sym_link *ptype = operandType (result);
11431 D (emitcode (";", "genNearPointerSet"));
11433 retype = getSpec (operandType (right));
11434 letype = getSpec (ptype);
11436 aopOp (result, ic, FALSE, FALSE);
11438 /* if the result is rematerializable &
11439 in data space & not a bit variable */
11440 if (AOP_TYPE (result) == AOP_IMMD &&
11441 DCL_TYPE (ptype) == POINTER &&
11442 !IS_BITVAR (retype) &&
11443 !IS_BITVAR (letype))
11445 genDataPointerSet (right, result, ic);
11449 /* if the value is already in a pointer register
11450 then don't need anything more */
11451 if (!AOP_INPREG (AOP (result)))
11453 /* otherwise get a free pointer register */
11456 aop = newAsmop (0);
11457 preg = getFreePtr (ic, &aop, FALSE);
11458 emitcode ("mov", "%s,%s",
11460 aopGet (result, 0, FALSE, TRUE, NULL));
11461 rname = preg->name;
11465 rname = aopGet (result, 0, FALSE, FALSE, NULL);
11468 aopOp (right, ic, FALSE, FALSE);
11470 /* if bitfield then unpack the bits */
11471 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11472 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
11475 /* we can just get the values */
11476 int size = AOP_SIZE (right);
11481 l = aopGet (right, offset, FALSE, TRUE, NULL);
11482 if ((*l == '@') || (strcmp (l, "acc") == 0))
11485 emitcode ("mov", "@%s,a", rname);
11488 emitcode ("mov", "@%s,%s", rname, l);
11490 emitcode ("inc", "%s", rname);
11495 /* now some housekeeping stuff */
11496 if (aop) /* we had to allocate for this iCode */
11499 aopPut (result, rname, 0);
11500 freeAsmop (NULL, aop, ic, TRUE);
11504 /* we did not allocate which means left
11505 already in a pointer register, then
11506 if size > 0 && this could be used again
11507 we have to point it back to where it
11509 if (AOP_SIZE (right) > 1 &&
11510 !OP_SYMBOL (result)->remat &&
11511 (OP_SYMBOL (result)->liveTo > ic->seq ||
11515 int size = AOP_SIZE (right) - 1;
11517 emitcode ("dec", "%s", rname);
11524 freeAsmop (right, NULL, ic, TRUE);
11525 freeAsmop (result, NULL, ic, TRUE);
11528 /*-----------------------------------------------------------------*/
11529 /* genPagedPointerSet - emitcode for Paged pointer put */
11530 /*-----------------------------------------------------------------*/
11532 genPagedPointerSet (operand * right,
11539 sym_link *retype, *letype;
11541 D (emitcode (";", "genPagedPointerSet"));
11543 retype = getSpec (operandType (right));
11544 letype = getSpec (operandType (result));
11546 aopOp (result, ic, FALSE, FALSE);
11548 /* if the value is already in a pointer register
11549 then don't need anything more */
11550 if (!AOP_INPREG (AOP (result)))
11552 /* otherwise get a free pointer register */
11555 aop = newAsmop (0);
11556 preg = getFreePtr (ic, &aop, FALSE);
11557 emitcode ("mov", "%s,%s",
11559 aopGet (result, 0, FALSE, TRUE, NULL));
11560 rname = preg->name;
11564 rname = aopGet (result, 0, FALSE, FALSE, NULL);
11567 aopOp (right, ic, FALSE, FALSE);
11569 /* if bitfield then unpack the bits */
11570 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11571 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
11574 /* we can just get the values */
11575 int size = AOP_SIZE (right);
11580 l = aopGet (right, offset, FALSE, TRUE, NULL);
11582 emitcode ("movx", "@%s,a", rname);
11584 emitcode ("inc", "%s", rname);
11589 /* now some housekeeping stuff */
11593 aopPut (result, rname, 0);
11594 /* we had to allocate for this iCode */
11595 freeAsmop (NULL, aop, ic, TRUE);
11599 /* we did not allocate which means left
11600 already in a pointer register, then
11601 if size > 0 && this could be used again
11602 we have to point it back to where it
11604 if (AOP_SIZE (right) > 1 &&
11605 !OP_SYMBOL (result)->remat &&
11606 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth) &&
11609 int size = AOP_SIZE (right) - 1;
11611 emitcode ("dec", "%s", rname);
11618 freeAsmop (right, NULL, ic, TRUE);
11619 freeAsmop (result, NULL, ic, TRUE);
11622 /*-----------------------------------------------------------------*/
11623 /* genFarPointerSet - set value from far space */
11624 /*-----------------------------------------------------------------*/
11626 genFarPointerSet (operand * right,
11627 operand * result, iCode * ic, iCode *pi)
11629 int size, offset, dopi=1;
11630 sym_link *retype = getSpec (operandType (right));
11631 sym_link *letype = getSpec (operandType (result));
11633 aopOp (result, ic, FALSE, FALSE);
11635 /* if the operand is already in dptr
11636 then we do nothing else we move the value to dptr */
11637 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
11639 /* if this is remateriazable */
11640 if (AOP_TYPE (result) == AOP_IMMD)
11641 emitcode ("mov", "dptr,%s",
11642 aopGet (result, 0, TRUE, FALSE, NULL));
11645 /* we need to get it byte by byte */
11646 _startLazyDPSEvaluation ();
11647 if (AOP_TYPE (result) != AOP_DPTR)
11649 emitcode ("mov", "dpl,%s", aopGet (result, 0, FALSE, FALSE, NULL));
11650 emitcode ("mov", "dph,%s", aopGet (result, 1, FALSE, FALSE, NULL));
11651 if (options.model == MODEL_FLAT24)
11652 emitcode ("mov", "dpx,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11656 /* We need to generate a load to DPTR indirect through DPTR. */
11657 D (emitcode (";", "genFarPointerSet -- indirection special case."););
11659 emitcode ("push", "%s", aopGet (result, 0, FALSE, TRUE, NULL));
11660 emitcode ("push", "%s", aopGet (result, 1, FALSE, TRUE, NULL));
11661 if (options.model == MODEL_FLAT24)
11662 emitcode ("mov", "dpx,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11663 emitcode ("pop", "dph");
11664 emitcode ("pop", "dpl");
11667 _endLazyDPSEvaluation ();
11670 /* so dptr now contains the address */
11671 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
11673 /* if bit then unpack */
11674 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11676 if (AOP_INDPTRn(result)) {
11677 genSetDPTR(AOP(result)->aopu.dptr);
11679 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
11680 if (AOP_INDPTRn(result)) {
11684 size = AOP_SIZE (right);
11686 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
11688 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11690 genSetDPTR(AOP(result)->aopu.dptr);
11691 emitcode ("movx", "@dptr,a");
11692 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
11693 emitcode ("inc", "dptr");
11697 _startLazyDPSEvaluation ();
11699 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11701 if (AOP_INDPTRn(result)) {
11702 genSetDPTR(AOP(result)->aopu.dptr);
11708 emitcode ("movx", "@dptr,a");
11709 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
11710 emitcode ("inc", "dptr");
11712 _endLazyDPSEvaluation ();
11716 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
11717 if (!AOP_INDPTRn(result)) {
11718 _startLazyDPSEvaluation ();
11720 aopPut (result,"dpl",0);
11721 aopPut (result,"dph",1);
11722 if (options.model == MODEL_FLAT24)
11723 aopPut (result,"dpx",2);
11725 _endLazyDPSEvaluation ();
11728 } else if (IS_SYMOP (result) &&
11729 (OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
11730 AOP_SIZE(right) > 1 &&
11731 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
11733 size = AOP_SIZE (right) - 1;
11734 if (AOP_INDPTRn(result)) {
11735 genSetDPTR(AOP(result)->aopu.dptr);
11737 while (size--) emitcode ("lcall","__decdptr");
11738 if (AOP_INDPTRn(result)) {
11742 freeAsmop (result, NULL, ic, TRUE);
11743 freeAsmop (right, NULL, ic, TRUE);
11746 /*-----------------------------------------------------------------*/
11747 /* genGenPointerSet - set value from generic pointer space */
11748 /*-----------------------------------------------------------------*/
11750 genGenPointerSet (operand * right,
11751 operand * result, iCode * ic, iCode * pi)
11755 sym_link *retype = getSpec (operandType (right));
11756 sym_link *letype = getSpec (operandType (result));
11758 aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
11760 pushedB = pushB ();
11761 /* if the operand is already in dptr
11762 then we do nothing else we move the value to dptr */
11763 if (AOP_TYPE (result) != AOP_STR)
11765 _startLazyDPSEvaluation ();
11766 /* if this is remateriazable */
11767 if (AOP_TYPE (result) == AOP_IMMD)
11769 emitcode ("mov", "dptr,%s", aopGet (result, 0, TRUE, FALSE, NULL));
11770 if (AOP(result)->aopu.aop_immd.from_cast_remat)
11772 MOVB (aopGet (result, AOP_SIZE(result)-1, FALSE, FALSE, NULL));
11777 "b,%s + 1", aopGet (result, 0, TRUE, FALSE, NULL));
11781 { /* we need to get it byte by byte */
11782 emitcode ("mov", "dpl,%s", aopGet (result, 0, FALSE, FALSE, NULL));
11783 emitcode ("mov", "dph,%s", aopGet (result, 1, FALSE, FALSE, NULL));
11784 if (options.model == MODEL_FLAT24) {
11785 emitcode ("mov", "dpx,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11786 emitcode ("mov", "b,%s", aopGet (result, 3, FALSE, FALSE, NULL));
11788 emitcode ("mov", "b,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11791 _endLazyDPSEvaluation ();
11793 /* so dptr + b now contains the address */
11794 aopOp (right, ic, FALSE, TRUE);
11796 /* if bit then unpack */
11797 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11799 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
11803 size = AOP_SIZE (right);
11806 _startLazyDPSEvaluation ();
11811 // Set two bytes at a time, passed in _AP & A.
11812 // dptr will be incremented ONCE by __gptrputWord.
11814 // Note: any change here must be coordinated
11815 // with the implementation of __gptrputWord
11816 // in device/lib/_gptrput.c
11817 emitcode("mov", "_ap, %s",
11818 aopGet (right, offset++, FALSE, FALSE, NULL));
11819 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11823 emitcode ("lcall", "__gptrputWord");
11828 // Only one byte to put.
11829 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11833 emitcode ("lcall", "__gptrput");
11836 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
11838 emitcode ("inc", "dptr");
11841 _endLazyDPSEvaluation ();
11844 if (pi && AOP_TYPE (result) != AOP_IMMD) {
11845 _startLazyDPSEvaluation ();
11847 aopPut (result, "dpl",0);
11848 aopPut (result, "dph",1);
11849 if (options.model == MODEL_FLAT24) {
11850 aopPut (result, "dpx",2);
11851 aopPut (result, "b",3);
11853 aopPut (result, "b",2);
11855 _endLazyDPSEvaluation ();
11858 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
11859 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
11861 size = AOP_SIZE (right) - 1;
11862 while (size--) emitcode ("lcall","__decdptr");
11866 freeAsmop (result, NULL, ic, TRUE);
11867 freeAsmop (right, NULL, ic, TRUE);
11870 /*-----------------------------------------------------------------*/
11871 /* genPointerSet - stores the value into a pointer location */
11872 /*-----------------------------------------------------------------*/
11874 genPointerSet (iCode * ic, iCode *pi)
11876 operand *right, *result;
11877 sym_link *type, *etype;
11880 D (emitcode (";", "genPointerSet"));
11882 right = IC_RIGHT (ic);
11883 result = IC_RESULT (ic);
11885 /* depending on the type of pointer we need to
11886 move it to the correct pointer register */
11887 type = operandType (result);
11888 etype = getSpec (type);
11889 /* if left is of type of pointer then it is simple */
11890 if (IS_PTR (type) && !IS_FUNC (type->next))
11892 p_type = DCL_TYPE (type);
11896 /* we have to go by the storage class */
11897 p_type = PTR_TYPE (SPEC_OCLS (etype));
11900 /* special case when cast remat */
11901 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
11902 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
11903 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
11904 type = operandType (result);
11905 p_type = DCL_TYPE (type);
11908 /* now that we have the pointer type we assign
11909 the pointer values */
11915 genNearPointerSet (right, result, ic, pi);
11919 genPagedPointerSet (right, result, ic, pi);
11923 genFarPointerSet (right, result, ic, pi);
11927 genGenPointerSet (right, result, ic, pi);
11931 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11932 "genPointerSet: illegal pointer type");
11936 /*-----------------------------------------------------------------*/
11937 /* genIfx - generate code for Ifx statement */
11938 /*-----------------------------------------------------------------*/
11940 genIfx (iCode * ic, iCode * popIc)
11942 operand *cond = IC_COND (ic);
11946 D (emitcode (";", "genIfx"));
11948 aopOp (cond, ic, FALSE, FALSE);
11950 /* get the value into acc */
11951 if (AOP_TYPE (cond) != AOP_CRY)
11958 if (AOP(cond)->aopu.aop_dir)
11959 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
11962 /* the result is now in the accumulator or a directly addressable bit */
11963 freeAsmop (cond, NULL, ic, TRUE);
11965 /* if the condition is a bit variable */
11967 genIfxJump (ic, dup, popIc);
11968 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
11969 genIfxJump (ic, SPIL_LOC (cond)->rname, popIc);
11970 else if (isbit && !IS_ITEMP (cond))
11971 genIfxJump (ic, OP_SYMBOL (cond)->rname, popIc);
11973 genIfxJump (ic, "a", popIc);
11978 /*-----------------------------------------------------------------*/
11979 /* genAddrOf - generates code for address of */
11980 /*-----------------------------------------------------------------*/
11982 genAddrOf (iCode * ic)
11984 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
11986 bool pushedA = FALSE;
11988 D (emitcode (";", "genAddrOf"));
11990 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11992 /* if the operand is on the stack then we
11993 need to get the stack offset of this
11997 /* if 10 bit stack */
11998 if (options.stack10bit) {
12002 tsprintf(buff, sizeof(buff),
12003 "#!constbyte",(options.stack_loc >> 16) & 0xff);
12004 /* if it has an offset then we need to compute it */
12005 /* emitcode ("subb", "a,#!constbyte", */
12006 /* -((sym->stack < 0) ? */
12007 /* ((short) (sym->stack - _G.nRegsSaved)) : */
12008 /* ((short) sym->stack)) & 0xff); */
12009 /* emitcode ("mov","b,a"); */
12010 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
12011 /* ((short) (sym->stack - _G.nRegsSaved)) : */
12012 /* ((short) sym->stack)) >> 8) & 0xff); */
12014 emitcode ("mov", "a,_bpx");
12015 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
12016 ((char) (sym->stack - _G.nRegsSaved)) :
12017 ((char) sym->stack )) & 0xff);
12018 emitcode ("mov", "b,a");
12019 emitcode ("mov", "a,_bpx+1");
12021 offset = (((sym->stack < 0) ?
12022 ((short) (sym->stack - _G.nRegsSaved)) :
12023 ((short) sym->stack )) >> 8) & 0xff;
12025 emitcode ("addc","a,#!constbyte", offset);
12027 if (aopPutUsesAcc (IC_RESULT (ic), "b", 0))
12029 emitcode ("push", "acc");
12032 aopPut (IC_RESULT (ic), "b", 0);
12034 emitcode ("pop", "acc");
12035 aopPut (IC_RESULT (ic), "a", 1);
12036 aopPut (IC_RESULT (ic), buff, 2);
12038 /* we can just move _bp */
12039 aopPut (IC_RESULT (ic), "_bpx", 0);
12040 aopPut (IC_RESULT (ic), "_bpx+1", 1);
12041 aopPut (IC_RESULT (ic), buff, 2);
12044 /* if it has an offset then we need to compute it */
12047 emitcode ("mov", "a,_bp");
12048 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
12049 aopPut (IC_RESULT (ic), "a", 0);
12053 /* we can just move _bp */
12054 aopPut (IC_RESULT (ic), "_bp", 0);
12056 /* fill the result with zero */
12057 size = AOP_SIZE (IC_RESULT (ic)) - 1;
12060 if (options.stack10bit && size < (FPTRSIZE - 1)) {
12062 "*** warning: pointer to stack var truncated.\n");
12068 aopPut (IC_RESULT (ic), zero, offset++);
12074 /* object not on stack then we need the name */
12075 size = getDataSize (IC_RESULT (ic));
12080 char s[SDCC_NAME_MAX];
12085 tsprintf(s, sizeof(s), "#!his",sym->rname);
12088 tsprintf(s, sizeof(s), "#!hihis",sym->rname);
12091 tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
12093 default: /* should not need this (just in case) */
12094 SNPRINTF (s, sizeof(s), "#(%s >> %d)", sym->rname, offset * 8);
12099 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
12101 aopPut (IC_RESULT (ic), s, offset++);
12103 if (opIsGptr (IC_RESULT (ic)))
12106 SNPRINTF (buffer, sizeof(buffer), "#0x%02x",
12107 pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
12108 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
12112 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
12115 #if 0 // obsolete, and buggy for != xdata
12116 /*-----------------------------------------------------------------*/
12117 /* genArrayInit - generates code for address of */
12118 /*-----------------------------------------------------------------*/
12120 genArrayInit (iCode * ic)
12122 literalList *iLoop;
12124 int elementSize = 0, eIndex;
12125 unsigned val, lastVal;
12127 operand *left=IC_LEFT(ic);
12129 D (emitcode (";", "genArrayInit"));
12131 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
12133 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
12135 // Load immediate value into DPTR.
12136 emitcode("mov", "dptr, %s",
12137 aopGet (IC_LEFT(ic), 0, TRUE, FALSE, NULL));
12139 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
12142 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12143 "Unexpected operand to genArrayInit.\n");
12146 // a regression because of SDCCcse.c:1.52
12147 emitcode ("mov", "dpl,%s", aopGet (left, 0, FALSE, FALSE, NULL));
12148 emitcode ("mov", "dph,%s", aopGet (left, 1, FALSE, FALSE, NULL));
12149 if (options.model == MODEL_FLAT24)
12150 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
12154 type = operandType(IC_LEFT(ic));
12156 if (type && type->next)
12158 elementSize = getSize(type->next);
12162 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12163 "can't determine element size in genArrayInit.\n");
12167 iLoop = IC_ARRAYILIST(ic);
12172 bool firstpass = TRUE;
12174 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
12175 iLoop->count, (int)iLoop->literalValue, elementSize);
12181 symbol *tlbl = NULL;
12183 count = ix > 256 ? 256 : ix;
12187 tlbl = newiTempLabel (NULL);
12188 if (firstpass || (count & 0xff))
12190 emitcode("mov", "b, #!constbyte", count & 0xff);
12198 for (eIndex = 0; eIndex < elementSize; eIndex++)
12200 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
12201 if (val != lastVal)
12203 emitcode("mov", "a, #!constbyte", val);
12207 emitcode("movx", "@dptr, a");
12208 emitcode("inc", "dptr");
12213 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
12219 iLoop = iLoop->next;
12222 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
12226 /*-----------------------------------------------------------------*/
12227 /* genFarFarAssign - assignment when both are in far space */
12228 /*-----------------------------------------------------------------*/
12230 genFarFarAssign (operand * result, operand * right, iCode * ic)
12232 int size = AOP_SIZE (right);
12234 symbol *rSym = NULL;
12238 /* quick & easy case. */
12239 D (emitcode(";","genFarFarAssign (1 byte case)"));
12240 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
12241 freeAsmop (right, NULL, ic, FALSE);
12242 /* now assign DPTR to result */
12244 aopOp(result, ic, FALSE, FALSE);
12246 aopPut (result, "a", 0);
12247 freeAsmop(result, NULL, ic, FALSE);
12251 /* See if we've got an underlying symbol to abuse. */
12252 if (IS_SYMOP(result) && OP_SYMBOL(result))
12254 if (IS_TRUE_SYMOP(result))
12256 rSym = OP_SYMBOL(result);
12258 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
12260 rSym = OP_SYMBOL(result)->usl.spillLoc;
12264 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
12266 /* We can use the '390 auto-toggle feature to good effect here. */
12268 D (emitcode(";", "genFarFarAssign (390 auto-toggle fun)"));
12269 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12270 emitcode ("mov", "dptr,#%s", rSym->rname);
12271 /* DP2 = result, DP1 = right, DP1 is current. */
12274 emitcode("movx", "a,@dptr");
12275 emitcode("movx", "@dptr,a");
12278 emitcode("inc", "dptr");
12279 emitcode("inc", "dptr");
12282 emitcode("mov", "dps,#0");
12283 freeAsmop (right, NULL, ic, FALSE);
12285 some alternative code for processors without auto-toggle
12286 no time to test now, so later well put in...kpb
12287 D (emitcode(";", "genFarFarAssign (dual-dptr fun)"));
12288 emitcode("mov", "dps,#1"); /* Select DPTR2. */
12289 emitcode ("mov", "dptr,#%s", rSym->rname);
12290 /* DP2 = result, DP1 = right, DP1 is current. */
12294 emitcode("movx", "a,@dptr");
12296 emitcode("inc", "dptr");
12297 emitcode("inc", "dps");
12298 emitcode("movx", "@dptr,a");
12300 emitcode("inc", "dptr");
12301 emitcode("inc", "dps");
12303 emitcode("mov", "dps,#0");
12304 freeAsmop (right, NULL, ic, FALSE);
12309 D (emitcode (";", "genFarFarAssign"));
12310 aopOp (result, ic, TRUE, TRUE);
12312 _startLazyDPSEvaluation ();
12317 aopGet (right, offset, FALSE, FALSE, NULL), offset);
12320 _endLazyDPSEvaluation ();
12321 freeAsmop (result, NULL, ic, FALSE);
12322 freeAsmop (right, NULL, ic, FALSE);
12326 /*-----------------------------------------------------------------*/
12327 /* genAssign - generate code for assignment */
12328 /*-----------------------------------------------------------------*/
12330 genAssign (iCode * ic)
12332 operand *result, *right;
12334 unsigned long lit = 0L;
12336 D (emitcode (";", "genAssign"));
12338 result = IC_RESULT (ic);
12339 right = IC_RIGHT (ic);
12341 /* if they are the same */
12342 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
12345 aopOp (right, ic, FALSE, FALSE);
12347 emitcode (";", "genAssign: resultIsFar = %s",
12348 isOperandInFarSpace (result) ?
12351 /* special case both in far space */
12352 if ((AOP_TYPE (right) == AOP_DPTR ||
12353 AOP_TYPE (right) == AOP_DPTR2) &&
12354 /* IS_TRUE_SYMOP(result) && */
12355 isOperandInFarSpace (result))
12357 genFarFarAssign (result, right, ic);
12361 aopOp (result, ic, TRUE, FALSE);
12363 /* if they are the same registers */
12364 if (sameRegs (AOP (right), AOP (result)))
12367 /* if the result is a bit */
12368 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
12370 /* if the right size is a literal then
12371 we know what the value is */
12372 if (AOP_TYPE (right) == AOP_LIT)
12374 if (((int) operandLitValue (right)))
12375 aopPut (result, one, 0);
12377 aopPut (result, zero, 0);
12381 /* the right is also a bit variable */
12382 if (AOP_TYPE (right) == AOP_CRY)
12384 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
12385 aopPut (result, "c", 0);
12389 /* we need to or */
12391 aopPut (result, "a", 0);
12395 /* bit variables done */
12397 size = getDataSize (result);
12399 if (AOP_TYPE (right) == AOP_LIT)
12400 lit = ulFromVal (AOP (right)->aopu.aop_lit);
12403 (AOP_TYPE (result) != AOP_REG) &&
12404 (AOP_TYPE (right) == AOP_LIT) &&
12405 !IS_FLOAT (operandType (right)))
12407 _startLazyDPSEvaluation ();
12408 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
12411 aopGet (right, offset, FALSE, FALSE, NULL),
12416 /* And now fill the rest with zeros. */
12419 emitcode ("clr", "a");
12423 aopPut (result, "a", offset++);
12425 _endLazyDPSEvaluation ();
12429 _startLazyDPSEvaluation ();
12433 aopGet (right, offset, FALSE, FALSE, NULL),
12437 _endLazyDPSEvaluation ();
12439 adjustArithmeticResult (ic);
12442 freeAsmop (result, NULL, ic, TRUE);
12443 freeAsmop (right, NULL, ic, TRUE);
12446 /*-----------------------------------------------------------------*/
12447 /* genJumpTab - generates code for jump table */
12448 /*-----------------------------------------------------------------*/
12450 genJumpTab (iCode * ic)
12455 D (emitcode (";", "genJumpTab"));
12457 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
12458 /* get the condition into accumulator */
12459 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE, NULL);
12461 /* multiply by four! */
12462 emitcode ("add", "a,acc");
12463 emitcode ("add", "a,acc");
12464 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
12466 jtab = newiTempLabel (NULL);
12467 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
12468 emitcode ("jmp", "@a+dptr");
12470 /* now generate the jump labels */
12471 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
12472 jtab = setNextItem (IC_JTLABELS (ic)))
12473 emitcode ("ljmp", "!tlabel", jtab->key + 100);
12477 /*-----------------------------------------------------------------*/
12478 /* genCast - gen code for casting */
12479 /*-----------------------------------------------------------------*/
12481 genCast (iCode * ic)
12483 operand *result = IC_RESULT (ic);
12484 sym_link *ctype = operandType (IC_LEFT (ic));
12485 sym_link *rtype = operandType (IC_RIGHT (ic));
12486 operand *right = IC_RIGHT (ic);
12489 D (emitcode (";", "genCast"));
12491 /* if they are equivalent then do nothing */
12492 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
12495 aopOp (right, ic, FALSE, AOP_IS_STR (result));
12496 aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR));
12498 /* if the result is a bit (and not a bitfield) */
12499 if (IS_BIT (OP_SYMBOL (result)->type))
12501 /* if the right size is a literal then
12502 we know what the value is */
12503 if (AOP_TYPE (right) == AOP_LIT)
12505 if (((int) operandLitValue (right)))
12506 aopPut (result, one, 0);
12508 aopPut (result, zero, 0);
12513 /* the right is also a bit variable */
12514 if (AOP_TYPE (right) == AOP_CRY)
12516 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
12517 aopPut (result, "c", 0);
12521 /* we need to or */
12523 aopPut (result, "a", 0);
12527 /* if they are the same size : or less */
12528 if (AOP_SIZE (result) <= AOP_SIZE (right))
12531 /* if they are in the same place */
12532 if (sameRegs (AOP (right), AOP (result)))
12535 /* if they in different places then copy */
12536 size = AOP_SIZE (result);
12538 _startLazyDPSEvaluation ();
12542 aopGet (right, offset, FALSE, FALSE, NULL),
12546 _endLazyDPSEvaluation ();
12550 /* if the result is of type pointer */
12551 if (IS_PTR (ctype))
12555 sym_link *type = operandType (right);
12557 /* pointer to generic pointer */
12558 if (IS_GENPTR (ctype))
12562 p_type = DCL_TYPE (type);
12566 #if OLD_CAST_BEHAVIOR
12567 /* KV: we are converting a non-pointer type to
12568 * a generic pointer. This (ifdef'd out) code
12569 * says that the resulting generic pointer
12570 * should have the same class as the storage
12571 * location of the non-pointer variable.
12573 * For example, converting an int (which happens
12574 * to be stored in DATA space) to a pointer results
12575 * in a DATA generic pointer; if the original int
12576 * in XDATA space, so will be the resulting pointer.
12578 * I don't like that behavior, and thus this change:
12579 * all such conversions will be forced to XDATA and
12580 * throw a warning. If you want some non-XDATA
12581 * type, or you want to suppress the warning, you
12582 * must go through an intermediate cast, like so:
12584 * char _generic *gp = (char _xdata *)(intVar);
12586 sym_link *etype = getSpec (type);
12588 /* we have to go by the storage class */
12589 if (SPEC_OCLS (etype) != generic)
12591 p_type = PTR_TYPE (SPEC_OCLS (etype));
12596 /* Converting unknown class (i.e. register variable)
12597 * to generic pointer. This is not good, but
12598 * we'll make a guess (and throw a warning).
12601 werror (W_INT_TO_GEN_PTR_CAST);
12605 /* the first two bytes are known */
12606 size = GPTRSIZE - 1;
12608 _startLazyDPSEvaluation ();
12612 aopGet (right, offset, FALSE, FALSE, NULL),
12616 _endLazyDPSEvaluation ();
12618 /* the last byte depending on type */
12620 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
12625 // pointerTypeToGPByte will have bitched.
12629 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%x", gpVal);
12630 aopPut (result, gpValStr, GPTRSIZE - 1);
12635 /* just copy the pointers */
12636 size = AOP_SIZE (result);
12638 _startLazyDPSEvaluation ();
12642 aopGet (right, offset, FALSE, FALSE, NULL),
12646 _endLazyDPSEvaluation ();
12650 /* so we now know that the size of destination is greater
12651 than the size of the source */
12652 /* we move to result for the size of source */
12653 size = AOP_SIZE (right);
12655 _startLazyDPSEvaluation ();
12659 aopGet (right, offset, FALSE, FALSE, NULL),
12663 _endLazyDPSEvaluation ();
12665 /* now depending on the sign of the source && destination */
12666 size = AOP_SIZE (result) - AOP_SIZE (right);
12667 /* if unsigned or not an integral type */
12668 /* also, if the source is a bit, we don't need to sign extend, because
12669 * it can't possibly have set the sign bit.
12671 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
12675 aopPut (result, zero, offset++);
12680 /* we need to extend the sign :{ */
12681 MOVA (aopGet (right, AOP_SIZE (right) - 1,
12682 FALSE, FALSE, NULL));
12683 emitcode ("rlc", "a");
12684 emitcode ("subb", "a,acc");
12686 aopPut (result, "a", offset++);
12689 /* we are done hurray !!!! */
12692 freeAsmop (right, NULL, ic, TRUE);
12693 freeAsmop (result, NULL, ic, TRUE);
12697 /*-----------------------------------------------------------------*/
12698 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
12699 /*-----------------------------------------------------------------*/
12700 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
12702 operand *from , *to , *count;
12707 /* we know it has to be 3 parameters */
12708 assert (nparms == 3);
12710 rsave = newBitVect(16);
12711 /* save DPTR if it needs to be saved */
12712 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12713 if (bitVectBitValue(ic->rMask,i))
12714 rsave = bitVectSetBit(rsave,i);
12716 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12717 ds390_rUmaskForOp (IC_RESULT(ic))));
12724 aopOp (from, ic->next, FALSE, FALSE);
12726 /* get from into DPTR1 */
12727 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12728 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12729 if (options.model == MODEL_FLAT24) {
12730 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12733 freeAsmop (from, NULL, ic, FALSE);
12734 aopOp (to, ic, FALSE, FALSE);
12735 /* get "to" into DPTR */
12736 /* if the operand is already in dptr
12737 then we do nothing else we move the value to dptr */
12738 if (AOP_TYPE (to) != AOP_STR) {
12739 /* if already in DPTR then we need to push */
12740 if (AOP_TYPE(to) == AOP_DPTR) {
12741 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12742 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12743 if (options.model == MODEL_FLAT24)
12744 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12745 emitcode ("pop", "dph");
12746 emitcode ("pop", "dpl");
12748 _startLazyDPSEvaluation ();
12749 /* if this is remateriazable */
12750 if (AOP_TYPE (to) == AOP_IMMD) {
12751 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12752 } else { /* we need to get it byte by byte */
12753 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12754 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12755 if (options.model == MODEL_FLAT24) {
12756 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12759 _endLazyDPSEvaluation ();
12762 freeAsmop (to, NULL, ic, FALSE);
12763 _G.dptrInUse = _G.dptr1InUse = 1;
12764 aopOp (count, ic->next->next, FALSE,FALSE);
12765 lbl =newiTempLabel(NULL);
12767 /* now for the actual copy */
12768 if (AOP_TYPE(count) == AOP_LIT &&
12769 (int) ulFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12770 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12772 emitcode ("lcall","__bi_memcpyc2x_s");
12774 emitcode ("lcall","__bi_memcpyx2x_s");
12776 freeAsmop (count, NULL, ic, FALSE);
12778 symbol *lbl1 = newiTempLabel(NULL);
12780 emitcode (";"," Auto increment but no djnz");
12781 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
12782 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
12783 freeAsmop (count, NULL, ic, FALSE);
12784 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12787 emitcode ("clr","a");
12788 emitcode ("movc", "a,@a+dptr");
12790 emitcode ("movx", "a,@dptr");
12791 emitcode ("movx", "@dptr,a");
12792 emitcode ("inc", "dptr");
12793 emitcode ("inc", "dptr");
12794 emitcode ("mov","a,b");
12795 emitcode ("orl","a,_ap");
12796 emitcode ("jz","!tlabel",lbl1->key+100);
12797 emitcode ("mov","a,_ap");
12798 emitcode ("add","a,#!constbyte",0xFF);
12799 emitcode ("mov","_ap,a");
12800 emitcode ("mov","a,b");
12801 emitcode ("addc","a,#!constbyte",0xFF);
12802 emitcode ("mov","b,a");
12803 emitcode ("sjmp","!tlabel",lbl->key+100);
12806 emitcode ("mov", "dps,#0");
12807 _G.dptrInUse = _G.dptr1InUse = 0;
12808 unsavermask(rsave);
12812 /*-----------------------------------------------------------------*/
12813 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
12814 /*-----------------------------------------------------------------*/
12815 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
12817 operand *from , *to , *count;
12822 /* we know it has to be 3 parameters */
12823 assert (nparms == 3);
12825 rsave = newBitVect(16);
12826 /* save DPTR if it needs to be saved */
12827 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12828 if (bitVectBitValue(ic->rMask,i))
12829 rsave = bitVectSetBit(rsave,i);
12831 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12832 ds390_rUmaskForOp (IC_RESULT(ic))));
12839 aopOp (from, ic->next, FALSE, FALSE);
12841 /* get from into DPTR1 */
12842 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12843 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12844 if (options.model == MODEL_FLAT24) {
12845 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12848 freeAsmop (from, NULL, ic, FALSE);
12849 aopOp (to, ic, FALSE, FALSE);
12850 /* get "to" into DPTR */
12851 /* if the operand is already in dptr
12852 then we do nothing else we move the value to dptr */
12853 if (AOP_TYPE (to) != AOP_STR) {
12854 /* if already in DPTR then we need to push */
12855 if (AOP_TYPE(to) == AOP_DPTR) {
12856 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12857 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12858 if (options.model == MODEL_FLAT24)
12859 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12860 emitcode ("pop", "dph");
12861 emitcode ("pop", "dpl");
12863 _startLazyDPSEvaluation ();
12864 /* if this is remateriazable */
12865 if (AOP_TYPE (to) == AOP_IMMD) {
12866 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12867 } else { /* we need to get it byte by byte */
12868 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12869 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12870 if (options.model == MODEL_FLAT24) {
12871 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12874 _endLazyDPSEvaluation ();
12877 freeAsmop (to, NULL, ic, FALSE);
12878 _G.dptrInUse = _G.dptr1InUse = 1;
12879 aopOp (count, ic->next->next, FALSE,FALSE);
12880 lbl =newiTempLabel(NULL);
12881 lbl2 =newiTempLabel(NULL);
12883 /* now for the actual compare */
12884 if (AOP_TYPE(count) == AOP_LIT &&
12885 (int) ulFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12886 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12888 emitcode("lcall","__bi_memcmpc2x_s");
12890 emitcode("lcall","__bi_memcmpx2x_s");
12891 freeAsmop (count, NULL, ic, FALSE);
12892 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12893 aopPut(IC_RESULT(ic),"a",0);
12894 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12896 symbol *lbl1 = newiTempLabel(NULL);
12898 emitcode("push","ar0");
12899 emitcode (";"," Auto increment but no djnz");
12900 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
12901 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
12902 freeAsmop (count, NULL, ic, FALSE);
12903 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12906 emitcode ("clr","a");
12907 emitcode ("movc", "a,@a+dptr");
12909 emitcode ("movx", "a,@dptr");
12910 emitcode ("mov","r0,a");
12911 emitcode ("movx", "a,@dptr");
12912 emitcode ("clr","c");
12913 emitcode ("subb","a,r0");
12914 emitcode ("jnz","!tlabel",lbl2->key+100);
12915 emitcode ("inc", "dptr");
12916 emitcode ("inc", "dptr");
12917 emitcode ("mov","a,b");
12918 emitcode ("orl","a,_ap");
12919 emitcode ("jz","!tlabel",lbl1->key+100);
12920 emitcode ("mov","a,_ap");
12921 emitcode ("add","a,#!constbyte",0xFF);
12922 emitcode ("mov","_ap,a");
12923 emitcode ("mov","a,b");
12924 emitcode ("addc","a,#!constbyte",0xFF);
12925 emitcode ("mov","b,a");
12926 emitcode ("sjmp","!tlabel",lbl->key+100);
12928 emitcode ("clr","a");
12930 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12931 aopPut(IC_RESULT(ic),"a",0);
12932 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12933 emitcode("pop","ar0");
12934 emitcode ("mov", "dps,#0");
12936 _G.dptrInUse = _G.dptr1InUse = 0;
12937 unsavermask(rsave);
12941 /*-----------------------------------------------------------------*/
12942 /* genInp - gen code for __builtin_inp read data from a mem mapped */
12943 /* port, first parameter output area second parameter pointer to */
12944 /* port third parameter count */
12945 /*-----------------------------------------------------------------*/
12946 static void genInp( iCode *ic, int nparms, operand **parms)
12948 operand *from , *to , *count;
12953 /* we know it has to be 3 parameters */
12954 assert (nparms == 3);
12956 rsave = newBitVect(16);
12957 /* save DPTR if it needs to be saved */
12958 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12959 if (bitVectBitValue(ic->rMask,i))
12960 rsave = bitVectSetBit(rsave,i);
12962 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12963 ds390_rUmaskForOp (IC_RESULT(ic))));
12970 aopOp (from, ic->next, FALSE, FALSE);
12972 /* get from into DPTR1 */
12973 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12974 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12975 if (options.model == MODEL_FLAT24) {
12976 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12979 freeAsmop (from, NULL, ic, FALSE);
12980 aopOp (to, ic, FALSE, FALSE);
12981 /* get "to" into DPTR */
12982 /* if the operand is already in dptr
12983 then we do nothing else we move the value to dptr */
12984 if (AOP_TYPE (to) != AOP_STR) {
12985 /* if already in DPTR then we need to push */
12986 if (AOP_TYPE(to) == AOP_DPTR) {
12987 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12988 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12989 if (options.model == MODEL_FLAT24)
12990 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12991 emitcode ("pop", "dph");
12992 emitcode ("pop", "dpl");
12994 _startLazyDPSEvaluation ();
12995 /* if this is remateriazable */
12996 if (AOP_TYPE (to) == AOP_IMMD) {
12997 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12998 } else { /* we need to get it byte by byte */
12999 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
13000 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
13001 if (options.model == MODEL_FLAT24) {
13002 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
13005 _endLazyDPSEvaluation ();
13008 freeAsmop (to, NULL, ic, FALSE);
13010 _G.dptrInUse = _G.dptr1InUse = 1;
13011 aopOp (count, ic->next->next, FALSE,FALSE);
13012 lbl =newiTempLabel(NULL);
13014 /* now for the actual copy */
13015 if (AOP_TYPE(count) == AOP_LIT &&
13016 (int) ulFromVal (AOP(count)->aopu.aop_lit) <= 256) {
13017 emitcode (";","OH JOY auto increment with djnz (very fast)");
13018 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
13019 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
13020 freeAsmop (count, NULL, ic, FALSE);
13022 emitcode ("movx", "a,@dptr"); /* read data from port */
13023 emitcode ("dec","dps"); /* switch to DPTR */
13024 emitcode ("movx", "@dptr,a"); /* save into location */
13025 emitcode ("inc", "dptr"); /* point to next area */
13026 emitcode ("inc","dps"); /* switch to DPTR2 */
13027 emitcode ("djnz","b,!tlabel",lbl->key+100);
13029 symbol *lbl1 = newiTempLabel(NULL);
13031 emitcode (";"," Auto increment but no djnz");
13032 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
13033 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
13034 freeAsmop (count, NULL, ic, FALSE);
13035 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
13037 emitcode ("movx", "a,@dptr");
13038 emitcode ("dec","dps"); /* switch to DPTR */
13039 emitcode ("movx", "@dptr,a");
13040 emitcode ("inc", "dptr");
13041 emitcode ("inc","dps"); /* switch to DPTR2 */
13042 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
13043 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
13044 emitcode ("mov","a,b");
13045 emitcode ("orl","a,_ap");
13046 emitcode ("jz","!tlabel",lbl1->key+100);
13047 emitcode ("mov","a,_ap");
13048 emitcode ("add","a,#!constbyte",0xFF);
13049 emitcode ("mov","_ap,a");
13050 emitcode ("mov","a,b");
13051 emitcode ("addc","a,#!constbyte",0xFF);
13052 emitcode ("mov","b,a");
13053 emitcode ("sjmp","!tlabel",lbl->key+100);
13056 emitcode ("mov", "dps,#0");
13057 _G.dptrInUse = _G.dptr1InUse = 0;
13058 unsavermask(rsave);
13062 /*-----------------------------------------------------------------*/
13063 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
13064 /* port, first parameter output area second parameter pointer to */
13065 /* port third parameter count */
13066 /*-----------------------------------------------------------------*/
13067 static void genOutp( iCode *ic, int nparms, operand **parms)
13069 operand *from , *to , *count;
13074 /* we know it has to be 3 parameters */
13075 assert (nparms == 3);
13077 rsave = newBitVect(16);
13078 /* save DPTR if it needs to be saved */
13079 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
13080 if (bitVectBitValue(ic->rMask,i))
13081 rsave = bitVectSetBit(rsave,i);
13083 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
13084 ds390_rUmaskForOp (IC_RESULT(ic))));
13091 aopOp (from, ic->next, FALSE, FALSE);
13093 /* get from into DPTR1 */
13094 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
13095 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
13096 if (options.model == MODEL_FLAT24) {
13097 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
13100 freeAsmop (from, NULL, ic, FALSE);
13101 aopOp (to, ic, FALSE, FALSE);
13102 /* get "to" into DPTR */
13103 /* if the operand is already in dptr
13104 then we do nothing else we move the value to dptr */
13105 if (AOP_TYPE (to) != AOP_STR) {
13106 /* if already in DPTR then we need to push */
13107 if (AOP_TYPE(to) == AOP_DPTR) {
13108 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
13109 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
13110 if (options.model == MODEL_FLAT24)
13111 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
13112 emitcode ("pop", "dph");
13113 emitcode ("pop", "dpl");
13115 _startLazyDPSEvaluation ();
13116 /* if this is remateriazable */
13117 if (AOP_TYPE (to) == AOP_IMMD) {
13118 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
13119 } else { /* we need to get it byte by byte */
13120 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
13121 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
13122 if (options.model == MODEL_FLAT24) {
13123 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
13126 _endLazyDPSEvaluation ();
13129 freeAsmop (to, NULL, ic, FALSE);
13131 _G.dptrInUse = _G.dptr1InUse = 1;
13132 aopOp (count, ic->next->next, FALSE,FALSE);
13133 lbl =newiTempLabel(NULL);
13135 /* now for the actual copy */
13136 if (AOP_TYPE(count) == AOP_LIT &&
13137 (int) ulFromVal (AOP(count)->aopu.aop_lit) <= 256) {
13138 emitcode (";","OH JOY auto increment with djnz (very fast)");
13139 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
13140 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
13142 emitcode ("movx", "a,@dptr"); /* read data from port */
13143 emitcode ("inc","dps"); /* switch to DPTR2 */
13144 emitcode ("movx", "@dptr,a"); /* save into location */
13145 emitcode ("inc", "dptr"); /* point to next area */
13146 emitcode ("dec","dps"); /* switch to DPTR */
13147 emitcode ("djnz","b,!tlabel",lbl->key+100);
13148 freeAsmop (count, NULL, ic, FALSE);
13150 symbol *lbl1 = newiTempLabel(NULL);
13152 emitcode (";"," Auto increment but no djnz");
13153 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
13154 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
13155 freeAsmop (count, NULL, ic, FALSE);
13156 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
13158 emitcode ("movx", "a,@dptr");
13159 emitcode ("inc", "dptr");
13160 emitcode ("inc","dps"); /* switch to DPTR2 */
13161 emitcode ("movx", "@dptr,a");
13162 emitcode ("dec","dps"); /* switch to DPTR */
13163 emitcode ("mov","a,b");
13164 emitcode ("orl","a,_ap");
13165 emitcode ("jz","!tlabel",lbl1->key+100);
13166 emitcode ("mov","a,_ap");
13167 emitcode ("add","a,#!constbyte",0xFF);
13168 emitcode ("mov","_ap,a");
13169 emitcode ("mov","a,b");
13170 emitcode ("addc","a,#!constbyte",0xFF);
13171 emitcode ("mov","b,a");
13172 emitcode ("sjmp","!tlabel",lbl->key+100);
13175 emitcode ("mov", "dps,#0");
13176 _G.dptrInUse = _G.dptr1InUse = 0;
13177 unsavermask(rsave);
13181 /*-----------------------------------------------------------------*/
13182 /* genSwapW - swap lower & high order bytes */
13183 /*-----------------------------------------------------------------*/
13184 static void genSwapW(iCode *ic, int nparms, operand **parms)
13188 assert (nparms==1);
13191 dest=IC_RESULT(ic);
13193 assert(getSize(operandType(src))==2);
13195 aopOp (src, ic, FALSE, FALSE);
13196 emitcode ("mov","a,%s",aopGet(src,0,FALSE,FALSE,NULL));
13198 MOVB(aopGet(src,1,FALSE,FALSE,"b"));
13200 freeAsmop (src, NULL, ic, FALSE);
13202 aopOp (dest,ic, FALSE, FALSE);
13203 aopPut(dest,"b",0);
13204 aopPut(dest,"a",1);
13205 freeAsmop (dest, NULL, ic, FALSE);
13208 /*-----------------------------------------------------------------*/
13209 /* genMemsetX - gencode for memSetX data */
13210 /*-----------------------------------------------------------------*/
13211 static void genMemsetX(iCode *ic, int nparms, operand **parms)
13213 operand *to , *val , *count;
13219 /* we know it has to be 3 parameters */
13220 assert (nparms == 3);
13226 /* save DPTR if it needs to be saved */
13227 rsave = newBitVect(16);
13228 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
13229 if (bitVectBitValue(ic->rMask,i))
13230 rsave = bitVectSetBit(rsave,i);
13232 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
13233 ds390_rUmaskForOp (IC_RESULT(ic))));
13236 aopOp (to, ic, FALSE, FALSE);
13237 /* get "to" into DPTR */
13238 /* if the operand is already in dptr
13239 then we do nothing else we move the value to dptr */
13240 if (AOP_TYPE (to) != AOP_STR) {
13241 /* if already in DPTR then we need to push */
13242 if (AOP_TYPE(to) == AOP_DPTR) {
13243 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
13244 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
13245 if (options.model == MODEL_FLAT24)
13246 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
13247 emitcode ("pop", "dph");
13248 emitcode ("pop", "dpl");
13250 _startLazyDPSEvaluation ();
13251 /* if this is remateriazable */
13252 if (AOP_TYPE (to) == AOP_IMMD) {
13253 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
13254 } else { /* we need to get it byte by byte */
13255 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
13256 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
13257 if (options.model == MODEL_FLAT24) {
13258 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
13261 _endLazyDPSEvaluation ();
13264 freeAsmop (to, NULL, ic, FALSE);
13266 aopOp (val, ic->next->next, FALSE,FALSE);
13267 aopOp (count, ic->next->next, FALSE,FALSE);
13268 lbl =newiTempLabel(NULL);
13269 /* now for the actual copy */
13270 if (AOP_TYPE(count) == AOP_LIT &&
13271 (int) ulFromVal (AOP(count)->aopu.aop_lit) <= 256) {
13272 l = aopGet(val, 0, FALSE, FALSE, NULL);
13273 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
13276 emitcode ("movx", "@dptr,a");
13277 emitcode ("inc", "dptr");
13278 emitcode ("djnz","b,!tlabel",lbl->key+100);
13280 symbol *lbl1 = newiTempLabel(NULL);
13282 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
13283 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
13285 MOVA (aopGet(val, 0, FALSE, FALSE, NULL));
13286 emitcode ("movx", "@dptr,a");
13287 emitcode ("inc", "dptr");
13288 emitcode ("mov","a,b");
13289 emitcode ("orl","a,_ap");
13290 emitcode ("jz","!tlabel",lbl1->key+100);
13291 emitcode ("mov","a,_ap");
13292 emitcode ("add","a,#!constbyte",0xFF);
13293 emitcode ("mov","_ap,a");
13294 emitcode ("mov","a,b");
13295 emitcode ("addc","a,#!constbyte",0xFF);
13296 emitcode ("mov","b,a");
13297 emitcode ("sjmp","!tlabel",lbl->key+100);
13300 freeAsmop (count, NULL, ic, FALSE);
13301 unsavermask(rsave);
13304 /*-----------------------------------------------------------------*/
13305 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
13306 /*-----------------------------------------------------------------*/
13307 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
13310 operand *pnum, *result;
13313 assert (nparms==1);
13314 /* save registers that need to be saved */
13315 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13316 ds390_rUmaskForOp (IC_RESULT(ic))));
13319 aopOp (pnum, ic, FALSE, FALSE);
13320 emitcode ("mov","a,%s",aopGet(pnum,0,FALSE,FALSE,DP2_RESULT_REG));
13321 freeAsmop (pnum, NULL, ic, FALSE);
13322 emitcode ("lcall","NatLib_LoadPrimitive");
13323 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
13324 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
13325 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
13326 for (i = (size-1) ; i >= 0 ; i-- ) {
13327 emitcode ("push","a%s",javaRet[i]);
13329 for (i=0; i < size ; i++ ) {
13330 emitcode ("pop","a%s",
13331 aopGet(result,i,FALSE,FALSE,DP2_RESULT_REG));
13334 for (i = 0 ; i < size ; i++ ) {
13335 aopPut(result,javaRet[i],i);
13338 freeAsmop (result, NULL, ic, FALSE);
13339 unsavermask(rsave);
13342 /*-----------------------------------------------------------------*/
13343 /* genNatLibLoadPointer - calls TINI api function to load pointer */
13344 /*-----------------------------------------------------------------*/
13345 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
13348 operand *pnum, *result;
13352 assert (nparms==1);
13353 /* save registers that need to be saved */
13354 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13355 ds390_rUmaskForOp (IC_RESULT(ic))));
13358 aopOp (pnum, ic, FALSE, FALSE);
13359 emitcode ("mov","a,%s",aopGet(pnum,0,FALSE,FALSE,DP2_RESULT_REG));
13360 freeAsmop (pnum, NULL, ic, FALSE);
13361 emitcode ("lcall","NatLib_LoadPointer");
13362 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
13363 if (AOP_TYPE(result)!=AOP_STR) {
13364 for (i = 0 ; i < size ; i++ ) {
13365 aopPut(result,fReturn[i],i);
13368 freeAsmop (result, NULL, ic, FALSE);
13369 unsavermask(rsave);
13372 /*-----------------------------------------------------------------*/
13373 /* genNatLibInstallStateBlock - */
13374 /*-----------------------------------------------------------------*/
13375 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
13376 operand **parms, const char *name)
13379 operand *psb, *handle;
13380 assert (nparms==2);
13382 /* save registers that need to be saved */
13383 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13384 ds390_rUmaskForOp (IC_RESULT(ic))));
13388 /* put pointer to state block into DPTR1 */
13389 aopOp (psb, ic, FALSE, FALSE);
13390 if (AOP_TYPE (psb) == AOP_IMMD) {
13391 emitcode ("mov","dps,#1");
13392 emitcode ("mov", "dptr,%s",
13393 aopGet (psb, 0, TRUE, FALSE, DP2_RESULT_REG));
13394 emitcode ("mov","dps,#0");
13396 emitcode ("mov","dpl1,%s",aopGet(psb,0,FALSE,FALSE,DP2_RESULT_REG));
13397 emitcode ("mov","dph1,%s",aopGet(psb,1,FALSE,FALSE,DP2_RESULT_REG));
13398 emitcode ("mov","dpx1,%s",aopGet(psb,2,FALSE,FALSE,DP2_RESULT_REG));
13400 freeAsmop (psb, NULL, ic, FALSE);
13402 /* put libraryID into DPTR */
13403 emitcode ("mov","dptr,#LibraryID");
13405 /* put handle into r3:r2 */
13406 aopOp (handle, ic, FALSE, FALSE);
13407 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13408 emitcode ("push","%s",aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13409 emitcode ("push","%s",aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13410 emitcode ("pop","ar3");
13411 emitcode ("pop","ar2");
13413 emitcode ("mov","r2,%s",aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13414 emitcode ("mov","r3,%s",aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13416 freeAsmop (psb, NULL, ic, FALSE);
13418 /* make the call */
13419 emitcode ("lcall","NatLib_Install%sStateBlock",name);
13421 /* put return value into place*/
13423 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
13425 aopPut(IC_RESULT(ic),"a",0);
13426 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13427 unsavermask(rsave);
13430 /*-----------------------------------------------------------------*/
13431 /* genNatLibRemoveStateBlock - */
13432 /*-----------------------------------------------------------------*/
13433 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
13439 /* save registers that need to be saved */
13440 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13441 ds390_rUmaskForOp (IC_RESULT(ic))));
13443 /* put libraryID into DPTR */
13444 emitcode ("mov","dptr,#LibraryID");
13445 /* make the call */
13446 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
13447 unsavermask(rsave);
13450 /*-----------------------------------------------------------------*/
13451 /* genNatLibGetStateBlock - */
13452 /*-----------------------------------------------------------------*/
13453 static void genNatLibGetStateBlock(iCode *ic,int nparms,
13454 operand **parms,const char *name)
13457 symbol *lbl = newiTempLabel(NULL);
13460 /* save registers that need to be saved */
13461 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13462 ds390_rUmaskForOp (IC_RESULT(ic))));
13464 /* put libraryID into DPTR */
13465 emitcode ("mov","dptr,#LibraryID");
13466 /* make the call */
13467 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
13468 emitcode ("jnz","!tlabel",lbl->key+100);
13470 /* put return value into place */
13471 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
13472 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
13473 emitcode ("push","ar3");
13474 emitcode ("push","ar2");
13475 emitcode ("pop","%s",
13476 aopGet(IC_RESULT(ic),0,FALSE,TRUE,DP2_RESULT_REG));
13477 emitcode ("pop","%s",
13478 aopGet(IC_RESULT(ic),1,FALSE,TRUE,DP2_RESULT_REG));
13480 aopPut(IC_RESULT(ic),"r2",0);
13481 aopPut(IC_RESULT(ic),"r3",1);
13483 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13485 unsavermask(rsave);
13488 /*-----------------------------------------------------------------*/
13489 /* genMMMalloc - */
13490 /*-----------------------------------------------------------------*/
13491 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
13492 int size, const char *name)
13497 symbol *lbl = newiTempLabel(NULL);
13499 assert (nparms == 1);
13500 /* save registers that need to be saved */
13501 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13502 ds390_rUmaskForOp (IC_RESULT(ic))));
13505 aopOp (bsize,ic,FALSE,FALSE);
13507 /* put the size in R4-R2 */
13508 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
13509 emitcode("push","%s",aopGet(bsize,0,FALSE,TRUE,DP2_RESULT_REG));
13510 emitcode("push","%s",aopGet(bsize,1,FALSE,TRUE,DP2_RESULT_REG));
13512 emitcode("push","%s",aopGet(bsize,2,FALSE,TRUE,DP2_RESULT_REG));
13513 emitcode("pop","ar4");
13515 emitcode("pop","ar3");
13516 emitcode("pop","ar2");
13518 emitcode ("mov","r2,%s",aopGet(bsize,0,FALSE,TRUE,DP2_RESULT_REG));
13519 emitcode ("mov","r3,%s",aopGet(bsize,1,FALSE,TRUE,DP2_RESULT_REG));
13521 emitcode("mov","r4,%s",aopGet(bsize,2,FALSE,TRUE,DP2_RESULT_REG));
13524 freeAsmop (bsize, NULL, ic, FALSE);
13526 /* make the call */
13527 emitcode ("lcall","MM_%s",name);
13528 emitcode ("jz","!tlabel",lbl->key+100);
13529 emitcode ("mov","r2,#!constbyte",0xff);
13530 emitcode ("mov","r3,#!constbyte",0xff);
13532 /* we don't care about the pointer : we just save the handle */
13533 rsym = OP_SYMBOL(IC_RESULT(ic));
13534 if (rsym->liveFrom != rsym->liveTo) {
13535 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
13536 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
13537 emitcode ("push","ar3");
13538 emitcode ("push","ar2");
13539 emitcode ("pop","%s",
13540 aopGet(IC_RESULT(ic),0,FALSE,TRUE,DP2_RESULT_REG));
13541 emitcode ("pop","%s",
13542 aopGet(IC_RESULT(ic),1,FALSE,TRUE,DP2_RESULT_REG));
13544 aopPut(IC_RESULT(ic),"r2",0);
13545 aopPut(IC_RESULT(ic),"r3",1);
13547 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13549 unsavermask(rsave);
13552 /*-----------------------------------------------------------------*/
13554 /*-----------------------------------------------------------------*/
13555 static void genMMDeref (iCode *ic,int nparms, operand **parms)
13560 assert (nparms == 1);
13561 /* save registers that need to be saved */
13562 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13563 ds390_rUmaskForOp (IC_RESULT(ic))));
13566 aopOp (handle,ic,FALSE,FALSE);
13568 /* put the size in R4-R2 */
13569 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13570 emitcode("push","%s",
13571 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13572 emitcode("push","%s",
13573 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13574 emitcode("pop","ar3");
13575 emitcode("pop","ar2");
13577 emitcode ("mov","r2,%s",
13578 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13579 emitcode ("mov","r3,%s",
13580 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13582 freeAsmop (handle, NULL, ic, FALSE);
13584 /* make the call */
13585 emitcode ("lcall","MM_Deref");
13588 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13589 if (rsym->liveFrom != rsym->liveTo) {
13590 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13591 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
13592 _startLazyDPSEvaluation ();
13594 aopPut(IC_RESULT(ic),"dpl",0);
13595 aopPut(IC_RESULT(ic),"dph",1);
13596 aopPut(IC_RESULT(ic),"dpx",2);
13598 _endLazyDPSEvaluation ();
13603 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13604 unsavermask(rsave);
13607 /*-----------------------------------------------------------------*/
13608 /* genMMUnrestrictedPersist - */
13609 /*-----------------------------------------------------------------*/
13610 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
13615 assert (nparms == 1);
13616 /* save registers that need to be saved */
13617 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13618 ds390_rUmaskForOp (IC_RESULT(ic))));
13621 aopOp (handle,ic,FALSE,FALSE);
13623 /* put the size in R3-R2 */
13624 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13625 emitcode("push","%s",
13626 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13627 emitcode("push","%s",
13628 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13629 emitcode("pop","ar3");
13630 emitcode("pop","ar2");
13632 emitcode ("mov","r2,%s",
13633 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13634 emitcode ("mov","r3,%s",
13635 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13637 freeAsmop (handle, NULL, ic, FALSE);
13639 /* make the call */
13640 emitcode ("lcall","MM_UnrestrictedPersist");
13643 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13644 if (rsym->liveFrom != rsym->liveTo) {
13645 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13646 aopPut(IC_RESULT(ic),"a",0);
13647 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13650 unsavermask(rsave);
13653 /*-----------------------------------------------------------------*/
13654 /* genSystemExecJavaProcess - */
13655 /*-----------------------------------------------------------------*/
13656 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
13659 operand *handle, *pp;
13661 assert (nparms==2);
13662 /* save registers that need to be saved */
13663 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13664 ds390_rUmaskForOp (IC_RESULT(ic))));
13669 /* put the handle in R3-R2 */
13670 aopOp (handle,ic,FALSE,FALSE);
13671 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13672 emitcode("push","%s",
13673 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13674 emitcode("push","%s",
13675 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13676 emitcode("pop","ar3");
13677 emitcode("pop","ar2");
13679 emitcode ("mov","r2,%s",
13680 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13681 emitcode ("mov","r3,%s",
13682 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13684 freeAsmop (handle, NULL, ic, FALSE);
13686 /* put pointer in DPTR */
13687 aopOp (pp,ic,FALSE,FALSE);
13688 if (AOP_TYPE(pp) == AOP_IMMD) {
13689 emitcode ("mov", "dptr,%s",
13690 aopGet (pp, 0, TRUE, FALSE, NULL));
13691 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
13692 emitcode ("mov","dpl,%s",aopGet(pp,0,FALSE,FALSE,NULL));
13693 emitcode ("mov","dph,%s",aopGet(pp,1,FALSE,FALSE,NULL));
13694 emitcode ("mov","dpx,%s",aopGet(pp,2,FALSE,FALSE,NULL));
13696 freeAsmop (handle, NULL, ic, FALSE);
13698 /* make the call */
13699 emitcode ("lcall","System_ExecJavaProcess");
13701 /* put result in place */
13703 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13704 if (rsym->liveFrom != rsym->liveTo) {
13705 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13706 aopPut(IC_RESULT(ic),"a",0);
13707 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13711 unsavermask(rsave);
13714 /*-----------------------------------------------------------------*/
13715 /* genSystemRTCRegisters - */
13716 /*-----------------------------------------------------------------*/
13717 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
13723 assert (nparms==1);
13724 /* save registers that need to be saved */
13725 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13726 ds390_rUmaskForOp (IC_RESULT(ic))));
13729 /* put pointer in DPTR */
13730 aopOp (pp,ic,FALSE,FALSE);
13731 if (AOP_TYPE (pp) == AOP_IMMD) {
13732 emitcode ("mov","dps,#1");
13733 emitcode ("mov", "dptr,%s",
13734 aopGet (pp, 0, TRUE, FALSE, NULL));
13735 emitcode ("mov","dps,#0");
13737 emitcode ("mov","dpl1,%s",
13738 aopGet(pp,0,FALSE,FALSE,DP2_RESULT_REG));
13739 emitcode ("mov","dph1,%s",
13740 aopGet(pp,1,FALSE,FALSE,DP2_RESULT_REG));
13741 emitcode ("mov","dpx1,%s",
13742 aopGet(pp,2,FALSE,FALSE,DP2_RESULT_REG));
13744 freeAsmop (pp, NULL, ic, FALSE);
13746 /* make the call */
13747 emitcode ("lcall","System_%sRTCRegisters",name);
13749 unsavermask(rsave);
13752 /*-----------------------------------------------------------------*/
13753 /* genSystemThreadSleep - */
13754 /*-----------------------------------------------------------------*/
13755 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
13760 assert (nparms==1);
13761 /* save registers that need to be saved */
13762 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13763 ds390_rUmaskForOp (IC_RESULT(ic))));
13766 aopOp(to,ic,FALSE,FALSE);
13767 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
13768 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
13769 emitcode ("push","%s",
13770 aopGet(to,0,FALSE,TRUE,DP2_RESULT_REG));
13771 emitcode ("push","%s",
13772 aopGet(to,1,FALSE,TRUE,DP2_RESULT_REG));
13773 emitcode ("push","%s",
13774 aopGet(to,2,FALSE,TRUE,DP2_RESULT_REG));
13775 emitcode ("push","%s",
13776 aopGet(to,3,FALSE,TRUE,DP2_RESULT_REG));
13777 emitcode ("pop","ar3");
13778 emitcode ("pop","ar2");
13779 emitcode ("pop","ar1");
13780 emitcode ("pop","ar0");
13782 emitcode ("mov","r0,%s",
13783 aopGet(to,0,FALSE,TRUE,DP2_RESULT_REG));
13784 emitcode ("mov","r1,%s",
13785 aopGet(to,1,FALSE,TRUE,DP2_RESULT_REG));
13786 emitcode ("mov","r2,%s",
13787 aopGet(to,2,FALSE,TRUE,DP2_RESULT_REG));
13788 emitcode ("mov","r3,%s",
13789 aopGet(to,3,FALSE,TRUE,DP2_RESULT_REG));
13791 freeAsmop (to, NULL, ic, FALSE);
13793 /* suspend in acc */
13795 aopOp(s,ic,FALSE,FALSE);
13796 emitcode ("mov","a,%s",
13797 aopGet(s,0,FALSE,TRUE,NULL));
13798 freeAsmop (s, NULL, ic, FALSE);
13800 /* make the call */
13801 emitcode ("lcall","System_%s",name);
13803 unsavermask(rsave);
13806 /*-----------------------------------------------------------------*/
13807 /* genSystemThreadResume - */
13808 /*-----------------------------------------------------------------*/
13809 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
13814 assert (nparms==2);
13815 /* save registers that need to be saved */
13816 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13817 ds390_rUmaskForOp (IC_RESULT(ic))));
13823 aopOp(pid,ic,FALSE,FALSE);
13824 emitcode ("mov","r0,%s",
13825 aopGet(pid,0,FALSE,TRUE,DP2_RESULT_REG));
13826 freeAsmop (pid, NULL, ic, FALSE);
13829 aopOp(tid,ic,FALSE,FALSE);
13830 emitcode ("mov","a,%s",
13831 aopGet(tid,0,FALSE,TRUE,DP2_RESULT_REG));
13832 freeAsmop (tid, NULL, ic, FALSE);
13834 emitcode ("lcall","System_ThreadResume");
13836 /* put result into place */
13838 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13839 if (rsym->liveFrom != rsym->liveTo) {
13840 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13841 aopPut(IC_RESULT(ic),"a",0);
13842 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13845 unsavermask(rsave);
13848 /*-----------------------------------------------------------------*/
13849 /* genSystemProcessResume - */
13850 /*-----------------------------------------------------------------*/
13851 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
13856 assert (nparms==1);
13857 /* save registers that need to be saved */
13858 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13859 ds390_rUmaskForOp (IC_RESULT(ic))));
13864 aopOp(pid,ic,FALSE,FALSE);
13865 emitcode ("mov","a,%s",
13866 aopGet(pid,0,FALSE,TRUE,DP2_RESULT_REG));
13867 freeAsmop (pid, NULL, ic, FALSE);
13869 emitcode ("lcall","System_ProcessResume");
13871 unsavermask(rsave);
13874 /*-----------------------------------------------------------------*/
13876 /*-----------------------------------------------------------------*/
13877 static void genSystem (iCode *ic,int nparms,char *name)
13879 assert(nparms == 0);
13881 emitcode ("lcall","System_%s",name);
13884 /*-----------------------------------------------------------------*/
13885 /* genSystemPoll - */
13886 /*-----------------------------------------------------------------*/
13887 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
13892 assert (nparms==1);
13893 /* save registers that need to be saved */
13894 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13895 ds390_rUmaskForOp (IC_RESULT(ic))));
13898 aopOp (fp,ic,FALSE,FALSE);
13899 if (AOP_TYPE (fp) == AOP_IMMD) {
13900 emitcode ("mov", "dptr,%s",
13901 aopGet (fp, 0, TRUE, FALSE, DP2_RESULT_REG));
13902 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
13903 emitcode ("mov","dpl,%s",
13904 aopGet(fp,0,FALSE,FALSE,DP2_RESULT_REG));
13905 emitcode ("mov","dph,%s",
13906 aopGet(fp,1,FALSE,FALSE,DP2_RESULT_REG));
13907 emitcode ("mov","dpx,%s",
13908 aopGet(fp,2,FALSE,FALSE,DP2_RESULT_REG));
13910 freeAsmop (fp, NULL, ic, FALSE);
13912 emitcode ("lcall","System_%sPoll",name);
13914 /* put result into place */
13916 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13917 if (rsym->liveFrom != rsym->liveTo) {
13918 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13919 aopPut(IC_RESULT(ic),"a",0);
13920 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13923 unsavermask(rsave);
13926 /*-----------------------------------------------------------------*/
13927 /* genSystemGetCurrentID - */
13928 /*-----------------------------------------------------------------*/
13929 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
13931 assert (nparms==0);
13933 emitcode ("lcall","System_GetCurrent%sId",name);
13934 /* put result into place */
13936 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13937 if (rsym->liveFrom != rsym->liveTo) {
13938 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13939 aopPut(IC_RESULT(ic),"a",0);
13940 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13945 /*-----------------------------------------------------------------*/
13946 /* genDjnz - generate decrement & jump if not zero instrucion */
13947 /*-----------------------------------------------------------------*/
13949 genDjnz (iCode * ic, iCode * ifx)
13951 symbol *lbl, *lbl1;
13955 /* if the if condition has a false label
13956 then we cannot save */
13957 if (IC_FALSE (ifx))
13960 /* if the minus is not of the form a = a - 1 */
13961 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
13962 !IS_OP_LITERAL (IC_RIGHT (ic)))
13965 if (operandLitValue (IC_RIGHT (ic)) != 1)
13968 /* if the size of this greater than one then no
13970 if (getSize (operandType (IC_RESULT (ic))) > 1)
13973 /* otherwise we can save BIG */
13975 D (emitcode (";", "genDjnz"));
13977 lbl = newiTempLabel (NULL);
13978 lbl1 = newiTempLabel (NULL);
13980 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
13982 if (AOP_NEEDSACC(IC_RESULT(ic)))
13984 /* If the result is accessed indirectly via
13985 * the accumulator, we must explicitly write
13986 * it back after the decrement.
13988 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE, NULL);
13990 if (strcmp(rByte, "a"))
13992 /* Something is hopelessly wrong */
13993 fprintf(stderr, "*** warning: internal error at %s:%d\n",
13994 __FILE__, __LINE__);
13995 /* We can just give up; the generated code will be inefficient,
13996 * but what the hey.
13998 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
14001 emitcode ("dec", "%s", rByte);
14002 aopPut (IC_RESULT (ic), rByte, 0);
14003 emitcode ("jnz", "!tlabel", lbl->key + 100);
14005 else if (IS_AOP_PREG (IC_RESULT (ic)))
14007 emitcode ("dec", "%s",
14008 aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL));
14009 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL));
14010 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
14011 ifx->generated = 1;
14012 emitcode ("jnz", "!tlabel", lbl->key + 100);
14016 emitcode ("djnz", "%s,!tlabel", aopGet (IC_RESULT (ic), 0, FALSE, TRUE, NULL),
14019 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
14021 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
14024 if (!ifx->generated)
14025 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
14026 ifx->generated = 1;
14030 /*-----------------------------------------------------------------*/
14031 /* genReceive - generate code for a receive iCode */
14032 /*-----------------------------------------------------------------*/
14034 genReceive (iCode * ic)
14036 int size = getSize (operandType (IC_RESULT (ic)));
14040 D (emitcode (";", "genReceive"));
14042 if (ic->argreg == 1)
14044 /* first parameter */
14045 if (AOP_IS_STR(IC_RESULT(ic)))
14047 /* Nothing to do: it's already in the proper place. */
14054 useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
14055 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
14056 IS_TRUE_SYMOP (IC_RESULT (ic)));
14059 aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
14062 /* Sanity checking... */
14063 if (AOP_USESDPTR(IC_RESULT(ic)))
14065 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
14066 "genReceive got unexpected DPTR.");
14068 assignResultValue (IC_RESULT (ic), NULL);
14071 else if (ic->argreg > 12)
14072 { /* bit parameters */
14073 if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
14075 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
14076 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
14077 outBitC(IC_RESULT (ic));
14082 /* second receive onwards */
14083 /* this gets a little tricky since unused receives will be
14084 eliminated, we have saved the reg in the type field . and
14085 we use that to figure out which register to use */
14086 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
14087 rb1off = ic->argreg;
14090 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
14093 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
14096 /*-----------------------------------------------------------------*/
14097 /* genDummyRead - generate code for dummy read of volatiles */
14098 /*-----------------------------------------------------------------*/
14100 genDummyRead (iCode * ic)
14105 D (emitcode(";", "genDummyRead"));
14107 op = IC_RIGHT (ic);
14108 if (op && IS_SYMOP (op))
14110 aopOp (op, ic, FALSE, FALSE);
14112 /* if the result is a bit */
14113 if (AOP_TYPE (op) == AOP_CRY)
14114 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
14117 /* bit variables done */
14119 size = AOP_SIZE (op);
14123 MOVA (aopGet (op, offset, FALSE, FALSE, FALSE));
14128 freeAsmop (op, NULL, ic, TRUE);
14132 if (op && IS_SYMOP (op))
14134 aopOp (op, ic, FALSE, FALSE);
14136 /* if the result is a bit */
14137 if (AOP_TYPE (op) == AOP_CRY)
14138 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
14141 /* bit variables done */
14143 size = AOP_SIZE (op);
14147 MOVA (aopGet (op, offset, FALSE, FALSE, FALSE));
14152 freeAsmop (op, NULL, ic, TRUE);
14156 /*-----------------------------------------------------------------*/
14157 /* genCritical - generate code for start of a critical sequence */
14158 /*-----------------------------------------------------------------*/
14160 genCritical (iCode *ic)
14162 symbol *tlbl = newiTempLabel (NULL);
14164 D (emitcode(";", "genCritical"));
14166 if (IC_RESULT (ic))
14168 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
14169 aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
14170 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
14171 aopPut (IC_RESULT (ic), zero, 0);
14173 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
14177 emitcode ("setb", "c");
14178 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
14179 emitcode ("clr", "c");
14181 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
14185 /*-----------------------------------------------------------------*/
14186 /* genEndCritical - generate code for end of a critical sequence */
14187 /*-----------------------------------------------------------------*/
14189 genEndCritical (iCode *ic)
14191 D(emitcode(";", "genEndCritical"));
14195 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
14196 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
14198 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
14199 emitcode ("mov", "ea,c");
14203 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE, FALSE));
14204 emitcode ("rrc", "a");
14205 emitcode ("mov", "ea,c");
14207 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
14211 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
14212 emitcode ("mov", "ea,c");
14218 /*-----------------------------------------------------------------*/
14219 /* genBuiltIn - calls the appropriate function to generating code */
14220 /* for a built in function */
14221 /*-----------------------------------------------------------------*/
14222 static void genBuiltIn (iCode *ic)
14224 operand *bi_parms[MAX_BUILTIN_ARGS];
14229 /* get all the arguments for a built in function */
14230 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
14232 /* which function is it */
14233 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
14234 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
14235 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
14236 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
14237 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
14238 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
14239 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
14240 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
14241 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
14242 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
14243 genMemsetX(bi_iCode,nbi_parms,bi_parms);
14244 } else if (strcmp(bif->name,"__builtin_inp")==0) {
14245 genInp(bi_iCode,nbi_parms,bi_parms);
14246 } else if (strcmp(bif->name,"__builtin_outp")==0) {
14247 genOutp(bi_iCode,nbi_parms,bi_parms);
14248 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
14249 genSwapW(bi_iCode,nbi_parms,bi_parms);
14250 /* JavaNative builtIns */
14251 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
14252 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
14253 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
14254 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
14255 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
14256 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
14257 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
14258 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
14259 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
14260 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
14261 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
14262 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
14263 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
14264 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
14265 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
14266 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
14267 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
14268 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
14269 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
14270 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
14271 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
14272 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
14273 } else if (strcmp(bif->name,"MM_Malloc")==0) {
14274 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
14275 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
14276 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
14277 } else if (strcmp(bif->name,"MM_Free")==0) {
14278 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
14279 } else if (strcmp(bif->name,"MM_Deref")==0) {
14280 genMMDeref(bi_iCode,nbi_parms,bi_parms);
14281 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
14282 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
14283 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
14284 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
14285 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
14286 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
14287 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
14288 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
14289 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
14290 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
14291 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
14292 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
14293 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
14294 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
14295 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
14296 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
14297 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
14298 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
14299 } else if (strcmp(bif->name,"System_SaveThread")==0) {
14300 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
14301 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
14302 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
14303 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
14304 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
14305 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
14306 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
14307 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
14308 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
14309 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
14310 genSystem(bi_iCode,nbi_parms,"ProcessYield");
14311 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
14312 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
14313 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
14314 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
14315 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
14316 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
14317 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
14318 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
14319 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
14320 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
14322 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
14328 /*-----------------------------------------------------------------*/
14329 /* gen390Code - generate code for Dallas 390 based controllers */
14330 /*-----------------------------------------------------------------*/
14332 gen390Code (iCode * lic)
14337 _G.currentFunc = NULL;
14338 lineHead = lineCurr = NULL;
14339 dptrn[1][0] = "dpl1";
14340 dptrn[1][1] = "dph1";
14341 dptrn[1][2] = "dpx1";
14343 if (options.model == MODEL_FLAT24) {
14344 fReturnSizeDS390 = 5;
14345 fReturn = fReturn24;
14347 fReturnSizeDS390 = 4;
14348 fReturn = fReturn16;
14349 options.stack10bit=0;
14352 /* print the allocation information */
14353 if (allocInfo && currFunc)
14354 printAllocInfo (currFunc, codeOutBuf);
14356 /* if debug information required */
14357 if (options.debug && currFunc)
14359 debugFile->writeFunction (currFunc, lic);
14361 /* stack pointer name */
14362 if (options.useXstack)
14368 for (ic = lic; ic; ic = ic->next)
14370 _G.current_iCode = ic;
14372 if (ic->lineno && cln != ic->lineno)
14376 debugFile->writeCLine (ic);
14378 if (!options.noCcodeInAsm) {
14379 emitcode (";", "%s:%d: %s", ic->filename, ic->lineno,
14380 printCLine(ic->filename, ic->lineno));
14384 if (options.iCodeInAsm) {
14385 const char *iLine = printILine(ic);
14386 emitcode(";", "ic:%d: %s", ic->key, iLine);
14389 /* if the result is marked as
14390 spilt and rematerializable or code for
14391 this has already been generated then
14393 if (resultRemat (ic) || ic->generated)
14396 /* depending on the operation */
14417 iCode *ifxIc, *popIc;
14418 bool CommonRegs = FALSE;
14420 /* IPOP happens only when trying to restore a
14421 spilt live range, if there is an ifx statement
14422 following this pop (or several) then the if statement might
14423 be using some of the registers being popped which
14424 would destory the contents of the register so
14425 we need to check for this condition and handle it */
14426 for (ifxIc = ic->next; ifxIc && ifxIc->op == IPOP; ifxIc = ifxIc->next);
14427 for (popIc = ic; popIc && popIc->op == IPOP; popIc = popIc->next)
14428 CommonRegs |= (ifxIc && ifxIc->op == IFX && !ifxIc->generated &&
14429 regsInCommon (IC_LEFT (popIc), IC_COND (ifxIc)));
14431 genIfx (ifxIc, ic);
14450 genEndFunction (ic);
14470 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
14487 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
14491 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
14498 /* note these two are xlated by algebraic equivalence
14499 during parsing SDCC.y */
14500 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
14501 "got '>=' or '<=' shouldn't have come here");
14505 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
14517 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
14521 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
14525 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
14549 genRightShift (ic);
14552 case GET_VALUE_AT_ADDRESS:
14554 hasInc (IC_LEFT (ic), ic,
14555 getSize (operandType (IC_RESULT (ic)))));
14559 if (POINTER_SET (ic))
14561 hasInc (IC_RESULT (ic), ic,
14562 getSize (operandType (IC_RIGHT (ic)))));
14588 if (ic->builtinSEND)
14591 addSet (&_G.sendSet, ic);
14594 case DUMMY_READ_VOLATILE:
14603 genEndCritical (ic);
14610 #if 0 // obsolete, and buggy for != xdata
14617 /* This should never happen, right? */
14618 fprintf(stderr, "*** Probable error: unsupported op 0x%x (%c) in %s @ %d\n",
14619 ic->op, ic->op, __FILE__, __LINE__);
14625 /* now we are ready to call the
14626 peep hole optimizer */
14627 if (!options.nopeep)
14628 peepHole (&lineHead);
14630 /* now do the actual printing */
14631 printLine (lineHead, codeOutBuf);