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 /* aopPut - puts a string for a aop and indicates if acc is in use */
1673 /*-----------------------------------------------------------------*/
1675 aopPut (operand * result, const char *s, int offset)
1677 bool bvolatile = isOperandVolatile (result, FALSE);
1678 bool accuse = FALSE;
1679 asmop * aop = AOP (result);
1680 const char *d = NULL;
1682 if (aop->size && offset > (aop->size - 1))
1684 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1685 "aopPut got offset > aop->size");
1689 /* will assign value to value */
1690 /* depending on where it is ofcourse */
1694 MOVA (s); /* read s in case it was volatile */
1699 if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1701 SNPRINTF (buffer, sizeof(buffer),
1703 aop->aopu.aop_dir, offset * 8);
1707 SNPRINTF (buffer, sizeof(buffer),
1709 aop->aopu.aop_dir, offset);
1713 SNPRINTF (buffer, sizeof(buffer),
1718 if (strcmp (buffer, s) || bvolatile)
1720 emitcode ("mov", "%s,%s", buffer, s);
1722 if (!strcmp (buffer, "acc"))
1729 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1730 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1733 strcmp (s, "r0") == 0 ||
1734 strcmp (s, "r1") == 0 ||
1735 strcmp (s, "r2") == 0 ||
1736 strcmp (s, "r3") == 0 ||
1737 strcmp (s, "r4") == 0 ||
1738 strcmp (s, "r5") == 0 ||
1739 strcmp (s, "r6") == 0 ||
1740 strcmp (s, "r7") == 0)
1742 emitcode ("mov", "%s,%s",
1743 aop->aopu.aop_reg[offset]->dname, s);
1747 emitcode ("mov", "%s,%s",
1748 aop->aopu.aop_reg[offset]->name, s);
1754 emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1760 if (aop->type == AOP_DPTR2)
1768 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1769 "aopPut writing to code space");
1773 while (offset > aop->coff)
1776 emitcode ("inc", "dptr");
1779 while (offset < aop->coff)
1782 emitcode ("lcall", "__decdptr");
1787 /* if not in accumulator */
1790 emitcode ("movx", "@dptr,a");
1792 if (aop->type == AOP_DPTR2)
1800 while (offset > aop->coff)
1803 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1805 while (offset < aop->coff)
1808 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1815 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1820 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1822 else if (strcmp (s, "r0") == 0 ||
1823 strcmp (s, "r1") == 0 ||
1824 strcmp (s, "r2") == 0 ||
1825 strcmp (s, "r3") == 0 ||
1826 strcmp (s, "r4") == 0 ||
1827 strcmp (s, "r5") == 0 ||
1828 strcmp (s, "r6") == 0 ||
1829 strcmp (s, "r7") == 0)
1832 SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1833 emitcode ("mov", "@%s,%s",
1834 aop->aopu.aop_ptr->name, buffer);
1838 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1843 if (strcmp (s, "a") == 0)
1845 emitcode ("push", "acc");
1850 emitcode ("push", "acc");
1852 else if (strcmp (s, "r0") == 0 ||
1853 strcmp (s, "r1") == 0 ||
1854 strcmp (s, "r2") == 0 ||
1855 strcmp (s, "r3") == 0 ||
1856 strcmp (s, "r4") == 0 ||
1857 strcmp (s, "r5") == 0 ||
1858 strcmp (s, "r6") == 0 ||
1859 strcmp (s, "r7") == 0)
1862 SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1863 emitcode ("push", buffer);
1867 emitcode ("push", s);
1873 // destination is carry for return-use-only
1874 d = (IS_OP_RUONLY (result)) ? "c" : aop->aopu.aop_dir;
1876 // source is no literal and not in carry
1877 if ((s != zero) && (s != one) && strcmp (s, "c"))
1880 /* set C, if a >= 1 */
1881 emitcode ("add", "a,#!constbyte",0xff);
1884 // now source is zero, one or carry
1886 /* if result no bit variable */
1889 if (!strcmp (s, "c"))
1891 /* inefficient: move carry into A and use jz/jnz */
1892 emitcode ("clr", "a");
1893 emitcode ("rlc", "a");
1903 emitcode ("clr", "%s", d);
1905 emitcode ("setb", "%s", d);
1906 else if (strcmp (s, d))
1907 emitcode ("mov", "%s,c", d);
1912 if (strcmp (aop->aopu.aop_str[offset], s) || bvolatile)
1913 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1919 if (!offset && (strcmp (s, "acc") == 0) && !bvolatile)
1922 if (strcmp (aop->aopu.aop_str[offset], s) && !bvolatile)
1923 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1927 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1928 "aopPut got unsupported aop->type");
1936 /*--------------------------------------------------------------------*/
1937 /* reAdjustPreg - points a register back to where it should (coff==0) */
1938 /*--------------------------------------------------------------------*/
1940 reAdjustPreg (asmop * aop)
1942 if ((aop->coff==0) || (aop->size <= 1))
1950 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1954 if (aop->type == AOP_DPTR2)
1961 emitcode ("lcall", "__decdptr");
1964 if (aop->type == AOP_DPTR2)
1973 /*-----------------------------------------------------------------*/
1974 /* opIsGptr: returns non-zero if the passed operand is */
1975 /* a generic pointer type. */
1976 /*-----------------------------------------------------------------*/
1978 opIsGptr (operand * op)
1980 if (op && IS_GENPTR (operandType (op)) && (AOP_SIZE (op) == GPTRSIZE))
1987 /*-----------------------------------------------------------------*/
1988 /* getDataSize - get the operand data size */
1989 /*-----------------------------------------------------------------*/
1991 getDataSize (operand * op)
1993 int size = AOP_SIZE (op);
1995 if (size == GPTRSIZE)
1997 sym_link *type = operandType (op);
1998 if (IS_GENPTR (type))
2000 /* generic pointer; arithmetic operations
2001 * should ignore the high byte (pointer type).
2009 /*-----------------------------------------------------------------*/
2010 /* outAcc - output Acc */
2011 /*-----------------------------------------------------------------*/
2013 outAcc (operand * result)
2016 size = getDataSize (result);
2019 aopPut (result, "a", 0);
2022 /* unsigned or positive */
2025 aopPut (result, zero, offset++);
2030 /*-----------------------------------------------------------------*/
2031 /* outBitC - output a bit C */
2032 /*-----------------------------------------------------------------*/
2034 outBitC (operand * result)
2036 /* if the result is bit */
2037 if (AOP_TYPE (result) == AOP_CRY)
2039 aopPut (result, "c", 0);
2043 emitcode ("clr", "a");
2044 emitcode ("rlc", "a");
2049 /*-----------------------------------------------------------------*/
2050 /* toBoolean - emit code for orl a,operator(sizeop) */
2051 /*-----------------------------------------------------------------*/
2053 toBoolean (operand * oper)
2055 int size = AOP_SIZE (oper) - 1;
2059 /* The generic part of a generic pointer should
2060 * not participate in it's truth value.
2062 * i.e. 0x10000000 is zero.
2064 if (opIsGptr (oper))
2066 D (emitcode (";", "toBoolean: generic ptr special case."));
2070 _startLazyDPSEvaluation ();
2071 MOVA (aopGet (oper, 0, FALSE, FALSE, NULL));
2072 if (AOP_NEEDSACC (oper) && size && (AOP (oper)->type != AOP_ACC))
2075 emitcode("mov", "b,a");
2078 MOVA (aopGet (oper, offset++, FALSE, FALSE, NULL));
2079 emitcode ("orl", "b,a");
2081 MOVA (aopGet (oper, offset++, FALSE, FALSE, NULL));
2082 emitcode ("orl", "a,b");
2089 emitcode ("orl", "a,%s",
2090 aopGet (oper, offset++, FALSE, FALSE, NULL));
2093 _endLazyDPSEvaluation ();
2097 /*-----------------------------------------------------------------*/
2098 /* genNot - generate code for ! operation */
2099 /*-----------------------------------------------------------------*/
2105 D (emitcode (";", "genNot"));
2107 /* assign asmOps to operand & result */
2108 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2109 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
2111 /* if in bit space then a special case */
2112 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2114 /* if left==result then cpl bit */
2115 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2117 emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2121 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2122 emitcode ("cpl", "c");
2123 outBitC (IC_RESULT (ic));
2128 toBoolean (IC_LEFT (ic));
2130 /* set C, if a == 0 */
2131 tlbl = newiTempLabel (NULL);
2132 emitcode ("cjne", "a,#0x01,!tlabel", tlbl->key + 100);
2134 outBitC (IC_RESULT (ic));
2137 /* release the aops */
2138 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2139 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2143 /*-----------------------------------------------------------------*/
2144 /* genCpl - generate code for complement */
2145 /*-----------------------------------------------------------------*/
2152 sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
2154 D(emitcode (";", "genCpl"));
2156 /* assign asmOps to operand & result */
2157 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2158 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
2160 /* special case if in bit space */
2161 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2165 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
2166 (SPEC_USIGN (letype) && IS_CHAR (letype)))
2168 /* promotion rules are responsible for this strange result:
2169 bit -> int -> ~int -> bit
2170 uchar -> int -> ~int -> bit
2172 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
2176 tlbl=newiTempLabel(NULL);
2177 l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE, NULL);
2178 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
2179 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
2180 IS_AOP_PREG (IC_LEFT (ic)))
2182 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
2187 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
2190 outBitC (IC_RESULT(ic));
2194 size = AOP_SIZE (IC_RESULT (ic));
2195 _startLazyDPSEvaluation ();
2198 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL);
2200 emitcode ("cpl", "a");
2201 aopPut (IC_RESULT (ic), "a", offset++);
2203 _endLazyDPSEvaluation ();
2207 /* release the aops */
2208 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2209 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2212 /*-----------------------------------------------------------------*/
2213 /* genUminusFloat - unary minus for floating points */
2214 /*-----------------------------------------------------------------*/
2216 genUminusFloat (operand * op, operand * result)
2218 int size, offset = 0;
2221 D (emitcode (";", "genUminusFloat"));
2223 /* for this we just copy and then flip the bit */
2225 _startLazyDPSEvaluation ();
2226 size = AOP_SIZE (op) - 1;
2231 aopGet (op, offset, FALSE, FALSE, NULL),
2236 l = aopGet (op, offset, FALSE, FALSE, NULL);
2239 emitcode ("cpl", "acc.7");
2240 aopPut (result, "a", offset);
2241 _endLazyDPSEvaluation ();
2244 /*-----------------------------------------------------------------*/
2245 /* genUminus - unary minus code generation */
2246 /*-----------------------------------------------------------------*/
2248 genUminus (iCode * ic)
2253 D (emitcode (";", "genUminus"));
2256 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2257 aopOp (IC_RESULT (ic), ic, TRUE, (AOP_TYPE(IC_LEFT (ic)) == AOP_DPTR));
2259 /* if both in bit space then special
2261 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2262 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2265 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2266 emitcode ("cpl", "c");
2267 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2271 optype = operandType (IC_LEFT (ic));
2273 /* if float then do float stuff */
2274 if (IS_FLOAT (optype))
2276 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2280 /* otherwise subtract from zero */
2281 size = AOP_SIZE (IC_LEFT (ic));
2283 _startLazyDPSEvaluation ();
2286 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL);
2287 if (!strcmp (l, "a"))
2291 emitcode ("cpl", "a");
2292 emitcode ("addc", "a,#0x00");
2298 emitcode ("clr", "a");
2299 emitcode ("subb", "a,%s", l);
2301 aopPut (IC_RESULT (ic), "a", offset++);
2303 _endLazyDPSEvaluation ();
2305 /* if any remaining bytes in the result */
2306 /* we just need to propagate the sign */
2307 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2309 emitcode ("rlc", "a");
2310 emitcode ("subb", "a,acc");
2312 aopPut (IC_RESULT (ic), "a", offset++);
2316 /* release the aops */
2317 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2318 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2321 /*-----------------------------------------------------------------*/
2322 /* savermask - saves registers in the mask */
2323 /*-----------------------------------------------------------------*/
2324 static void savermask(bitVect *rs_mask)
2328 if (options.useXstack)
2330 if (bitVectBitValue (rs_mask, R0_IDX))
2331 emitcode ("mov", "b,r0");
2332 emitcode ("mov", "r0,%s", spname);
2333 for (i = 0; i < ds390_nRegs; i++)
2335 if (bitVectBitValue (rs_mask, i))
2338 emitcode ("mov", "a,b");
2340 emitcode ("mov", "a,%s", REG_WITH_INDEX (i)->name);
2341 emitcode ("movx", "@r0,a");
2342 emitcode ("inc", "r0");
2345 emitcode ("mov", "%s,r0", spname);
2346 if (bitVectBitValue (rs_mask, R0_IDX))
2347 emitcode ("mov", "r0,b");
2351 bool bits_pushed = FALSE;
2352 for (i = 0; i < ds390_nRegs; i++)
2354 if (bitVectBitValue (rs_mask, i))
2356 bits_pushed = pushReg (i, bits_pushed);
2362 /*-----------------------------------------------------------------*/
2363 /* saveRegisters - will look for a call and save the registers */
2364 /*-----------------------------------------------------------------*/
2366 saveRegisters (iCode * lic)
2372 for (ic = lic; ic; ic = ic->next)
2373 if (ic->op == CALL || ic->op == PCALL)
2378 fprintf (stderr, "found parameter push with no function call\n");
2382 /* if the registers have been saved already or don't need to be then
2385 || (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))) && !TARGET_IS_DS400) )
2388 /* special case if DPTR alive across a function call then must save it
2389 even though callee saves */
2390 if (IS_SYMOP(IC_LEFT(ic)) &&
2391 IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type))
2394 rsave = newBitVect(ic->rMask->size);
2395 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2396 if (bitVectBitValue(ic->rMask,i))
2397 rsave = bitVectSetBit(rsave,i);
2399 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2403 /* save the registers in use at this time but skip the
2404 ones for the result */
2405 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2406 ds390_rUmaskForOp (IC_RESULT(ic)));
2412 /*-----------------------------------------------------------------*/
2413 /* usavermask - restore registers with mask */
2414 /*-----------------------------------------------------------------*/
2415 static void unsavermask(bitVect *rs_mask)
2419 if (options.useXstack)
2421 emitcode ("mov", "r0,%s", spname);
2422 for (i = ds390_nRegs; i >= 0; i--)
2424 if (bitVectBitValue (rs_mask, i))
2426 regs * reg = REG_WITH_INDEX (i);
2427 emitcode ("dec", "r0");
2428 emitcode ("movx", "a,@r0");
2431 emitcode ("push", "acc");
2435 emitcode ("mov", "%s,a", reg->name);
2439 emitcode ("mov", "%s,r0", spname);
2440 if (bitVectBitValue (rs_mask, R0_IDX))
2442 emitcode ("pop", "ar0");
2447 bool bits_popped = FALSE;
2448 for (i = ds390_nRegs; i >= 0; i--)
2450 if (bitVectBitValue (rs_mask, i))
2452 bits_popped = popReg (i, bits_popped);
2458 /*-----------------------------------------------------------------*/
2459 /* unsaveRegisters - pop the pushed registers */
2460 /*-----------------------------------------------------------------*/
2462 unsaveRegisters (iCode * ic)
2466 if (IS_SYMOP(IC_LEFT (ic)) &&
2467 IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2469 rsave = newBitVect(ic->rMask->size);
2470 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2471 if (bitVectBitValue(ic->rMask,i))
2472 rsave = bitVectSetBit(rsave,i);
2474 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2476 /* restore the registers in use at this time but skip the
2477 ones for the result */
2478 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2479 ds390_rUmaskForOp (IC_RESULT(ic)));
2485 /*-----------------------------------------------------------------*/
2487 /*-----------------------------------------------------------------*/
2489 pushSide (operand * oper, int size, iCode * ic)
2492 int nPushed = _G.r0Pushed + _G.r1Pushed;
2494 aopOp (oper, ic, FALSE, FALSE);
2496 if (nPushed != _G.r0Pushed + _G.r1Pushed)
2498 while (offset < size)
2500 char *l = aopGet (oper, offset, FALSE, TRUE, NULL);
2501 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2503 freeAsmop (oper, NULL, ic, TRUE);
2505 while (offset < size)
2507 emitcode ("push", "%s", fReturn[offset++]);
2512 _startLazyDPSEvaluation ();
2515 char *l = aopGet (oper, offset++, FALSE, TRUE, NULL);
2516 if (AOP_TYPE (oper) != AOP_REG &&
2517 AOP_TYPE (oper) != AOP_DIR &&
2521 emitcode ("push", "acc");
2525 emitcode ("push", "%s", l);
2528 _endLazyDPSEvaluation ();
2529 freeAsmop (oper, NULL, ic, TRUE);
2532 /*-----------------------------------------------------------------*/
2533 /* assignResultValue - also indicates if acc is in use afterwards */
2534 /*-----------------------------------------------------------------*/
2536 assignResultValue (operand * oper, operand * func)
2539 unsigned size = AOP_SIZE (oper);
2540 bool accuse = FALSE;
2541 bool pushedA = FALSE;
2543 if (func && IS_BIT (OP_SYM_ETYPE (func)))
2549 if (size == fReturnSizeDS390)
2551 /* I don't think this case can ever happen... */
2552 /* ACC is the last part of this. If writing the result
2553 * uses ACC, we must preserve it.
2555 if (AOP_NEEDSACC(oper))
2557 emitcode(";", "assignResultValue special case for ACC.");
2558 emitcode("push", "acc");
2564 _startLazyDPSEvaluation ();
2567 accuse |= aopPut (oper, fReturn[offset], offset);
2570 _endLazyDPSEvaluation ();
2574 emitcode ("pop", "acc");
2575 accuse |= aopPut (oper, "a", offset);
2581 /*-----------------------------------------------------------------*/
2582 /* genXpush - pushes onto the external stack */
2583 /*-----------------------------------------------------------------*/
2585 genXpush (iCode * ic)
2587 asmop *aop = newAsmop (0);
2589 int size, offset = 0;
2591 D (emitcode (";", "genXpush"));
2593 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2594 r = getFreePtr (ic, &aop, FALSE);
2596 size = AOP_SIZE (IC_LEFT (ic));
2600 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
2601 emitcode ("mov", "%s,_spx", r->name);
2602 emitcode ("inc", "_spx"); // allocate space first
2603 emitcode ("movx", "@%s,a", r->name);
2607 // allocate space first
2608 emitcode ("mov", "%s,_spx", r->name);
2610 emitcode ("add", "a,#%d", size);
2611 emitcode ("mov", "_spx,a");
2613 _startLazyDPSEvaluation ();
2616 MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE, NULL));
2617 emitcode ("movx", "@%s,a", r->name);
2618 emitcode ("inc", "%s", r->name);
2620 _endLazyDPSEvaluation ();
2623 freeAsmop (NULL, aop, ic, TRUE);
2624 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2627 /*-----------------------------------------------------------------*/
2628 /* genIpush - generate code for pushing this gets a little complex */
2629 /*-----------------------------------------------------------------*/
2631 genIpush (iCode * ic)
2633 int size, offset = 0;
2637 D (emitcode (";", "genIpush"));
2639 /* if this is not a parm push : ie. it is spill push
2640 and spill push is always done on the local stack */
2644 /* and the item is spilt then do nothing */
2645 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2648 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2649 size = AOP_SIZE (IC_LEFT (ic));
2650 /* push it on the stack */
2651 _startLazyDPSEvaluation ();
2654 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE, NULL);
2660 emitcode ("push", "%s", l);
2662 _endLazyDPSEvaluation ();
2666 /* this is a parameter push: in this case we call
2667 the routine to find the call and save those
2668 registers that need to be saved */
2671 /* if use external stack then call the external
2672 stack pushing routine */
2673 if (options.useXstack)
2679 /* then do the push */
2680 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2682 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2683 size = AOP_SIZE (IC_LEFT (ic));
2685 _startLazyDPSEvaluation ();
2688 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE, NULL);
2689 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2690 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2693 if (strcmp (l, prev) || *l == '@')
2695 emitcode ("push", "acc");
2699 emitcode ("push", "%s", l);
2703 _endLazyDPSEvaluation ();
2705 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2708 /*-----------------------------------------------------------------*/
2709 /* genIpop - recover the registers: can happen only for spilling */
2710 /*-----------------------------------------------------------------*/
2712 genIpop (iCode * ic)
2716 D (emitcode (";", "genIpop"));
2718 /* if the temp was not pushed then */
2719 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2722 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2723 size = AOP_SIZE (IC_LEFT (ic));
2724 offset = (size - 1);
2725 _startLazyDPSEvaluation ();
2728 emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2729 FALSE, TRUE, NULL));
2731 _endLazyDPSEvaluation ();
2733 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2736 /*-----------------------------------------------------------------*/
2737 /* popForBranch - recover the spilt registers for a branch */
2738 /*-----------------------------------------------------------------*/
2740 popForBranch (iCode * ic, bool markGenerated)
2742 while (ic && ic->op == IPOP)
2746 ic->generated = 1; /* mark the icode as generated */
2751 /*-----------------------------------------------------------------*/
2752 /* saveRBank - saves an entire register bank on the stack */
2753 /*-----------------------------------------------------------------*/
2755 saveRBank (int bank, iCode * ic, bool pushPsw)
2758 int count = 8 + (ds390_nBitRegs/8) + (pushPsw ? 1 : 0);
2762 if (options.useXstack)
2766 /* Assume r0 is available for use. */
2767 r = REG_WITH_INDEX (R0_IDX);
2772 r = getFreePtr (ic, &aop, FALSE);
2774 // allocate space first
2775 emitcode ("mov", "%s,_spx", r->name);
2777 emitcode ("add", "a,#%d", count);
2778 emitcode ("mov", "_spx,a");
2781 for (i = 0; i < 8; i++) /* only R0-R7 needs saving */
2783 if (options.useXstack)
2785 emitcode ("mov", "a,(%s+%d)",
2786 regs390[i].base, 8 * bank + regs390[i].offset);
2787 emitcode ("movx", "@%s,a", r->name);
2789 emitcode ("inc", "%s", r->name);
2792 emitcode ("push", "(%s+%d)",
2793 regs390[i].base, 8 * bank + regs390[i].offset);
2796 if (ds390_nBitRegs > 0)
2798 if (options.useXstack)
2800 emitcode ("mov", "a,bits");
2801 emitcode ("movx", "@%s,a", r->name);
2803 emitcode ("inc", "%s", r->name);
2807 emitcode ("push", "bits");
2814 if (options.useXstack)
2816 emitcode ("mov", "a,psw");
2817 emitcode ("movx", "@%s,a", r->name);
2821 emitcode ("push", "psw");
2824 emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2829 freeAsmop (NULL, aop, ic, TRUE);
2838 /*-----------------------------------------------------------------*/
2839 /* unsaveRBank - restores the register bank from stack */
2840 /*-----------------------------------------------------------------*/
2842 unsaveRBank (int bank, iCode * ic, bool popPsw)
2848 if (options.useXstack)
2852 /* Assume r0 is available for use. */
2853 r = REG_WITH_INDEX (R0_IDX);
2858 r = getFreePtr (ic, &aop, FALSE);
2860 emitcode ("mov", "%s,_spx", r->name);
2865 if (options.useXstack)
2867 emitcode ("dec", "%s", r->name);
2868 emitcode ("movx", "a,@%s", r->name);
2869 emitcode ("mov", "psw,a");
2873 emitcode ("pop", "psw");
2877 if (ds390_nBitRegs > 0)
2879 if (options.useXstack)
2881 emitcode ("dec", "%s", r->name);
2882 emitcode ("movx", "a,@%s", r->name);
2883 emitcode ("mov", "bits,a");
2887 emitcode ("pop", "bits");
2891 for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2893 if (options.useXstack)
2895 emitcode ("dec", "%s", r->name);
2896 emitcode ("movx", "a,@%s", r->name);
2897 emitcode ("mov", "(%s+%d),a",
2898 regs390[i].base, 8 * bank + regs390[i].offset);
2902 emitcode ("pop", "(%s+%d)",
2903 regs390[i].base, 8 * bank + regs390[i].offset);
2907 if (options.useXstack)
2909 emitcode ("mov", "_spx,%s", r->name);
2914 freeAsmop (NULL, aop, ic, TRUE);
2918 /*-----------------------------------------------------------------*/
2919 /* genSend - gen code for SEND */
2920 /*-----------------------------------------------------------------*/
2921 static void genSend(set *sendSet)
2926 static int rb1_count = 0;
2928 /* first we do all bit parameters */
2929 for (sic = setFirstItem (sendSet); sic;
2930 sic = setNextItem (sendSet))
2932 if (sic->argreg > 12)
2934 int bit = sic->argreg-13;
2936 aopOp (IC_LEFT (sic), sic, FALSE,
2937 (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2939 /* if left is a literal then
2940 we know what the value is */
2941 if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2943 if (((int) operandLitValue (IC_LEFT (sic))))
2944 emitcode ("setb", "b[%d]", bit);
2946 emitcode ("clr", "b[%d]", bit);
2948 else if (AOP_TYPE (IC_LEFT (sic)) == AOP_CRY)
2950 char *l = AOP (IC_LEFT (sic))->aopu.aop_dir;
2951 if (strcmp (l, "c"))
2952 emitcode ("mov", "c,%s", l);
2953 emitcode ("mov", "b[%d],c", bit);
2958 toBoolean (IC_LEFT (sic));
2959 /* set C, if a >= 1 */
2960 emitcode ("add", "a,#0xff");
2961 emitcode ("mov", "b[%d],c", bit);
2966 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2972 saveRegisters (setFirstItem (sendSet));
2973 emitcode ("mov", "bits,b");
2976 /* then we do all other parameters */
2977 for (sic = setFirstItem (sendSet); sic;
2978 sic = setNextItem (sendSet))
2980 if (sic->argreg <= 12)
2982 int size, offset = 0;
2984 size = getSize (operandType (IC_LEFT (sic)));
2985 D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2987 { /* first parameter */
2988 // we know that dpl(hxb) is the result, so
2990 _startLazyDPSEvaluation ();
2993 aopOp (IC_LEFT (sic), sic, FALSE,
2994 (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2998 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
3002 char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE, NULL);
3003 if (strcmp (l, fReturn[offset]))
3005 emitcode ("mov", "%s,%s", fReturn[offset], l);
3009 _endLazyDPSEvaluation ();
3010 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
3014 { /* if more parameter in registers */
3015 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
3018 emitcode ("mov","b1_%d,%s",rb1_count++,
3019 aopGet (IC_LEFT (sic), offset, FALSE, FALSE, NULL));
3022 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
3030 adjustEsp(const char *reg)
3032 emitcode ("anl","%s,#3", reg);
3033 if (TARGET_IS_DS400)
3035 emitcode ("orl","%s,#!constbyte",
3037 (options.stack_loc >> 8) & 0xff);
3041 /*-----------------------------------------------------------------*/
3042 /* selectRegBank - emit code to select the register bank */
3043 /*-----------------------------------------------------------------*/
3045 selectRegBank (short bank, bool keepFlags)
3047 /* if f.e. result is in carry */
3050 emitcode ("anl", "psw,#0xE7");
3052 emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
3056 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
3060 /*-----------------------------------------------------------------*/
3061 /* genCall - generates a call statement */
3062 /*-----------------------------------------------------------------*/
3064 genCall (iCode * ic)
3068 bool restoreBank = FALSE;
3069 bool swapBanks = FALSE;
3070 bool accuse = FALSE;
3071 bool accPushed = FALSE;
3072 bool resultInF0 = FALSE;
3073 bool assignResultGenerated = FALSE;
3075 D (emitcode (";", "genCall"));
3077 /* if we are calling a not _naked function that is not using
3078 the same register bank then we need to save the
3079 destination registers on the stack */
3080 dtype = operandType (IC_LEFT (ic));
3081 etype = getSpec(dtype);
3082 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
3083 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
3084 IFFUNC_ISISR (currFunc->type))
3088 /* This is unexpected; the bank should have been saved in
3091 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
3097 /* if caller saves & we have not saved then */
3101 /* if send set is not empty then assign */
3102 /* We've saved all the registers we care about;
3103 * therefore, we may clobber any register not used
3104 * in the calling convention (i.e. anything not in
3109 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
3110 genSend(reverseSet(_G.sendSet));
3112 genSend(_G.sendSet);
3119 emitcode ("mov", "psw,#!constbyte",
3120 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3124 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
3125 OP_SYMBOL (IC_LEFT (ic))->rname :
3126 OP_SYMBOL (IC_LEFT (ic))->name));
3130 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
3133 /* if we need assign a result value */
3134 if ((IS_ITEMP (IC_RESULT (ic)) &&
3135 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3136 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3137 OP_SYMBOL (IC_RESULT (ic))->accuse ||
3138 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3139 IS_TRUE_SYMOP (IC_RESULT (ic)))
3141 if (isOperandInFarSpace (IC_RESULT (ic))
3142 && getSize (operandType (IC_RESULT (ic))) <= 2)
3144 int size = getSize (operandType (IC_RESULT (ic)));
3145 bool pushedB = FALSE;
3147 /* Special case for 1 or 2 byte return in far space. */
3152 emitcode ("mov", "b,%s", fReturn[1]);
3156 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
3161 aopPut (IC_RESULT (ic), "a", 0);
3165 aopPut (IC_RESULT (ic), "b", 1);
3167 assignResultGenerated = TRUE;
3168 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3172 bool pushedB = pushB ();
3173 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
3176 accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3177 assignResultGenerated = TRUE;
3178 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3182 /* adjust the stack for parameters if required */
3186 if (options.stack10bit) {
3187 if (ic->parmBytes <= 10) {
3188 emitcode(";","stack adjustment for parms");
3189 for (i=0; i < ic->parmBytes ; i++) {
3190 emitcode("pop","acc");
3194 emitcode ("clr","c");
3195 emitcode ("mov","a,sp");
3196 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
3197 emitcode ("mov","sp,a");
3198 emitcode ("mov","a,esp");
3200 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
3201 emitcode ("mov","esp,a");
3205 if (ic->parmBytes > 3)
3209 emitcode ("push", "acc");
3212 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3213 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3214 !assignResultGenerated)
3216 emitcode ("mov", "F0,c");
3220 emitcode ("mov", "a,%s", spname);
3221 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
3222 emitcode ("mov", "%s,a", spname);
3224 /* unsaveRegisters from xstack needs acc, but */
3225 /* unsaveRegisters from stack needs this popped */
3226 if (accPushed && !options.useXstack)
3228 emitcode ("pop", "acc");
3233 for (i = 0; i < ic->parmBytes; i++)
3234 emitcode ("dec", "%s", spname);
3238 /* if we had saved some registers then unsave them */
3239 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3241 if (accuse && !accPushed && options.useXstack)
3243 /* xstack needs acc, but doesn't touch normal stack */
3244 emitcode ("push", "acc");
3247 unsaveRegisters (ic);
3250 /* if register bank was saved then pop them */
3252 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
3254 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
3257 emitcode ("mov", "c,F0");
3259 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
3260 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3261 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3265 emitcode ("pop", "acc");
3268 /*-----------------------------------------------------------------*/
3269 /* genPcall - generates a call by pointer statement */
3270 /*-----------------------------------------------------------------*/
3272 genPcall (iCode * ic)
3276 symbol *rlbl = newiTempLabel (NULL);
3277 bool restoreBank=FALSE;
3278 bool resultInF0 = FALSE;
3280 D (emitcode (";", "genPcall"));
3282 dtype = operandType (IC_LEFT (ic))->next;
3283 etype = getSpec(dtype);
3284 /* if caller saves & we have not saved then */
3288 /* if we are calling a not _naked function that is not using
3289 the same register bank then we need to save the
3290 destination registers on the stack */
3291 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
3292 IFFUNC_ISISR (currFunc->type) &&
3293 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
3294 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3298 /* push the return address on to the stack */
3299 emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
3300 emitcode ("push", "acc");
3301 emitcode ("mov", "a,#!hil", (rlbl->key + 100));
3302 emitcode ("push", "acc");
3304 if (options.model == MODEL_FLAT24)
3306 emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
3307 emitcode ("push", "acc");
3310 /* now push the function address */
3311 pushSide (IC_LEFT (ic), FPTRSIZE, ic);
3313 /* if send set is not empty then assign */
3316 genSend(reverseSet(_G.sendSet));
3321 emitcode ("ret", "");
3325 /* if we need assign a result value */
3326 if ((IS_ITEMP (IC_RESULT (ic)) &&
3327 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3328 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3329 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3330 IS_TRUE_SYMOP (IC_RESULT (ic)))
3334 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
3337 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3339 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3342 /* adjust the stack for parameters if required */
3346 if (options.stack10bit) {
3347 if (ic->parmBytes <= 10) {
3348 emitcode(";","stack adjustment for parms");
3349 for (i=0; i < ic->parmBytes ; i++) {
3350 emitcode("pop","acc");
3353 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3354 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3356 emitcode ("mov", "F0,c");
3361 emitcode ("clr","c");
3362 emitcode ("mov","a,sp");
3363 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
3364 emitcode ("mov","sp,a");
3365 emitcode ("mov","a,esp");
3367 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
3368 emitcode ("mov","esp,a");
3372 if (ic->parmBytes > 3) {
3373 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3374 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3376 emitcode ("mov", "F0,c");
3380 emitcode ("mov", "a,%s", spname);
3381 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
3382 emitcode ("mov", "%s,a", spname);
3385 for (i = 0; i < ic->parmBytes; i++)
3386 emitcode ("dec", "%s", spname);
3389 /* if register bank was saved then unsave them */
3391 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3393 /* if we had saved some registers then unsave them */
3395 unsaveRegisters (ic);
3397 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3400 emitcode ("mov", "c,F0");
3402 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
3403 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3404 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3408 /*-----------------------------------------------------------------*/
3409 /* resultRemat - result is rematerializable */
3410 /*-----------------------------------------------------------------*/
3412 resultRemat (iCode * ic)
3414 if (SKIP_IC (ic) || ic->op == IFX)
3417 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3419 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3420 if (sym->remat && !POINTER_SET (ic))
3427 /*-----------------------------------------------------------------*/
3428 /* inExcludeList - return 1 if the string is in exclude Reg list */
3429 /*-----------------------------------------------------------------*/
3431 regsCmp(void *p1, void *p2)
3433 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3437 inExcludeList (char *s)
3439 const char *p = setFirstItem(options.excludeRegsSet);
3441 if (p == NULL || STRCASECMP(p, "none") == 0)
3445 return isinSetWith(options.excludeRegsSet, s, regsCmp);
3448 /*-----------------------------------------------------------------*/
3449 /* genFunction - generated code for function entry */
3450 /*-----------------------------------------------------------------*/
3452 genFunction (iCode * ic)
3454 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3456 bool switchedPSW = FALSE;
3457 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3459 D (emitcode (";", "genFunction"));
3462 /* create the function header */
3463 emitcode (";", "-----------------------------------------");
3464 emitcode (";", " function %s", sym->name);
3465 emitcode (";", "-----------------------------------------");
3467 emitcode ("", "%s:", sym->rname);
3468 lineCurr->isLabel = 1;
3469 ftype = operandType (IC_LEFT (ic));
3470 _G.currentFunc = sym;
3472 if (IFFUNC_ISNAKED(ftype))
3474 emitcode(";", "naked function: no prologue.");
3478 if (options.stack_probe)
3479 emitcode ("lcall","__stack_probe");
3481 /* here we need to generate the equates for the
3482 register bank if required */
3483 if (FUNC_REGBANK (ftype) != rbank)
3487 rbank = FUNC_REGBANK (ftype);
3488 for (i = 0; i < ds390_nRegs; i++)
3490 if (regs390[i].print) {
3491 if (strcmp (regs390[i].base, "0") == 0)
3492 emitcode ("", "%s !equ !constbyte",
3494 8 * rbank + regs390[i].offset);
3496 emitcode ("", "%s !equ %s + !constbyte",
3499 8 * rbank + regs390[i].offset);
3504 /* if this is an interrupt service routine then
3505 save acc, b, dpl, dph */
3506 if (IFFUNC_ISISR (sym->type))
3508 if (!inExcludeList ("acc"))
3509 emitcode ("push", "acc");
3510 if (!inExcludeList ("b"))
3511 emitcode ("push", "b");
3512 if (!inExcludeList ("dpl"))
3513 emitcode ("push", "dpl");
3514 if (!inExcludeList ("dph"))
3515 emitcode ("push", "dph");
3516 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3518 emitcode ("push", "dpx");
3519 /* Make sure we're using standard DPTR */
3520 emitcode ("push", "dps");
3521 emitcode ("mov", "dps,#0");
3522 if (options.stack10bit)
3524 /* This ISR could conceivably use DPTR2. Better save it. */
3525 emitcode ("push", "dpl1");
3526 emitcode ("push", "dph1");
3527 emitcode ("push", "dpx1");
3528 emitcode ("push", DP2_RESULT_REG);
3531 /* if this isr has no bank i.e. is going to
3532 run with bank 0 , then we need to save more
3534 if (!FUNC_REGBANK (sym->type))
3538 /* if this function does not call any other
3539 function then we can be economical and
3540 save only those registers that are used */
3541 if (!IFFUNC_HASFCALL(sym->type))
3543 /* if any registers used */
3546 bool bits_pushed = FALSE;
3547 /* save the registers used */
3548 for (i = 0; i < sym->regsUsed->size; i++)
3550 if (bitVectBitValue (sym->regsUsed, i))
3551 bits_pushed = pushReg (i, bits_pushed);
3557 /* this function has a function call. We cannot
3558 determine register usage so we will have to push the
3560 saveRBank (0, ic, FALSE);
3561 if (options.parms_in_bank1)
3563 for (i=0; i < 8 ; i++ )
3565 emitcode ("push","%s",rb1regs[i]);
3572 /* This ISR uses a non-zero bank.
3574 * We assume that the bank is available for our
3577 * However, if this ISR calls a function which uses some
3578 * other bank, we must save that bank entirely.
3580 unsigned long banksToSave = 0;
3582 if (IFFUNC_HASFCALL(sym->type))
3585 #define MAX_REGISTER_BANKS 4
3590 for (i = ic; i; i = i->next)
3592 if (i->op == ENDFUNCTION)
3594 /* we got to the end OK. */
3602 dtype = operandType (IC_LEFT(i));
3604 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3606 /* Mark this bank for saving. */
3607 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3609 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3613 banksToSave |= (1 << FUNC_REGBANK(dtype));
3616 /* And note that we don't need to do it in
3624 /* This is a mess; we have no idea what
3625 * register bank the called function might
3628 * The only thing I can think of to do is
3629 * throw a warning and hope.
3631 werror(W_FUNCPTR_IN_USING_ISR);
3635 if (banksToSave && options.useXstack)
3637 /* Since we aren't passing it an ic,
3638 * saveRBank will assume r0 is available to abuse.
3640 * So switch to our (trashable) bank now, so
3641 * the caller's R0 isn't trashed.
3643 emitcode ("push", "psw");
3644 emitcode ("mov", "psw,#!constbyte",
3645 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3649 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3651 if (banksToSave & (1 << ix))
3653 saveRBank(ix, NULL, FALSE);
3657 // TODO: this needs a closer look
3658 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3663 /* if callee-save to be used for this function
3664 then save the registers being used in this function */
3665 if (IFFUNC_CALLEESAVES(sym->type))
3669 /* if any registers used */
3672 bool bits_pushed = FALSE;
3673 /* save the registers used */
3674 for (i = 0; i < sym->regsUsed->size; i++)
3676 if (bitVectBitValue (sym->regsUsed, i))
3678 bits_pushed = pushReg (i, bits_pushed);
3686 /* set the register bank to the desired value */
3687 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3690 emitcode ("push", "psw");
3691 emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3695 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3696 if (options.stack10bit) {
3697 emitcode ("push","_bpx");
3698 emitcode ("push","_bpx+1");
3699 emitcode ("mov","_bpx,%s",spname);
3700 emitcode ("mov","_bpx+1,esp");
3701 adjustEsp("_bpx+1");
3703 if (options.useXstack)
3705 emitcode ("mov", "r0,%s", spname);
3706 emitcode ("mov", "a,_bp");
3707 emitcode ("movx", "@r0,a");
3708 emitcode ("inc", "%s", spname);
3710 /* set up the stack */
3711 emitcode ("push", "_bp"); /* save the callers stack */
3713 emitcode ("mov", "_bp,%s", spname);
3717 /* adjust the stack for the function */
3720 if (options.stack10bit) {
3721 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
3722 assert (sym->recvSize <= 4);
3723 if (sym->stack <= 8) {
3724 while (i--) emitcode ("push","acc");
3727 emitcode ("mov","a,sp");
3728 emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3729 emitcode ("mov","sp,a");
3730 emitcode ("mov","a,esp");
3732 emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3733 emitcode ("mov","esp,a");
3738 werror (W_STACK_OVERFLOW, sym->name);
3740 if (i > 3 && sym->recvSize < 4) {
3742 emitcode ("mov", "a,sp");
3743 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3744 emitcode ("mov", "sp,a");
3748 emitcode ("inc", "sp");
3755 emitcode ("mov", "a,_spx");
3756 emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3757 emitcode ("mov", "_spx,a");
3760 /* if critical function then turn interrupts off */
3761 if (IFFUNC_ISCRITICAL (ftype))
3763 symbol *tlbl = newiTempLabel (NULL);
3764 emitcode ("setb", "c");
3765 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3766 emitcode ("clr", "c");
3768 emitcode ("push", "psw"); /* save old ea via c in psw */
3772 /*-----------------------------------------------------------------*/
3773 /* genEndFunction - generates epilogue for functions */
3774 /*-----------------------------------------------------------------*/
3776 genEndFunction (iCode * ic)
3778 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3779 lineNode *lnp = lineCurr;
3781 bitVect *regsUsedPrologue;
3782 bitVect *regsUnneeded;
3785 D (emitcode (";", "genEndFunction"));
3787 _G.currentFunc = NULL;
3788 if (IFFUNC_ISNAKED(sym->type))
3790 emitcode(";", "naked function: no epilogue.");
3791 if (options.debug && currFunc)
3792 debugFile->writeEndFunction (currFunc, ic, 0);
3796 if (IFFUNC_ISCRITICAL (sym->type))
3798 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3800 emitcode ("rlc", "a"); /* save c in a */
3801 emitcode ("pop", "psw"); /* restore ea via c in psw */
3802 emitcode ("mov", "ea,c");
3803 emitcode ("rrc", "a"); /* restore c from a */
3807 emitcode ("pop", "psw"); /* restore ea via c in psw */
3808 emitcode ("mov", "ea,c");
3812 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3813 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3815 if (options.stack10bit) {
3817 emitcode ("mov", "sp,_bpx", spname);
3818 emitcode ("mov", "esp,_bpx+1", spname);
3821 emitcode ("mov", "%s,_bp", spname);
3825 /* if use external stack but some variables were
3826 added to the local stack then decrement the
3828 if (options.useXstack && sym->stack) {
3829 emitcode ("mov", "a,sp");
3830 emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3831 emitcode ("mov", "sp,a");
3835 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3836 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3838 if (options.useXstack) {
3839 emitcode ("mov", "r0,%s", spname);
3840 emitcode ("movx", "a,@r0");
3841 emitcode ("mov", "_bp,a");
3842 emitcode ("dec", "%s", spname);
3844 if (options.stack10bit) {
3845 emitcode ("pop", "_bpx+1");
3846 emitcode ("pop", "_bpx");
3848 emitcode ("pop", "_bp");
3853 /* restore the register bank */
3854 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3856 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3857 || !options.useXstack)
3859 /* Special case of ISR using non-zero bank with useXstack
3862 emitcode ("pop", "psw");
3866 if (IFFUNC_ISISR (sym->type))
3869 /* now we need to restore the registers */
3870 /* if this isr has no bank i.e. is going to
3871 run with bank 0 , then we need to save more
3873 if (!FUNC_REGBANK (sym->type))
3876 /* if this function does not call any other
3877 function then we can be economical and
3878 save only those registers that are used */
3879 if (!IFFUNC_HASFCALL(sym->type))
3881 /* if any registers used */
3884 bool bits_popped = FALSE;
3885 /* save the registers used */
3886 for (i = sym->regsUsed->size; i >= 0; i--)
3888 if (bitVectBitValue (sym->regsUsed, i))
3889 bits_popped = popReg (i, bits_popped);
3895 /* this function has a function call. We cannot
3896 determine register usage so we will have to pop the
3898 if (options.parms_in_bank1)
3900 for (i = 7 ; i >= 0 ; i-- )
3902 emitcode ("pop","%s",rb1regs[i]);
3905 unsaveRBank (0, ic, FALSE);
3910 /* This ISR uses a non-zero bank.
3912 * Restore any register banks saved by genFunction
3915 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3918 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3920 if (savedBanks & (1 << ix))
3922 unsaveRBank(ix, NULL, FALSE);
3926 if (options.useXstack)
3928 /* Restore bank AFTER calling unsaveRBank,
3929 * since it can trash r0.
3931 emitcode ("pop", "psw");
3935 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3937 if (options.stack10bit)
3939 emitcode ("pop", DP2_RESULT_REG);
3940 emitcode ("pop", "dpx1");
3941 emitcode ("pop", "dph1");
3942 emitcode ("pop", "dpl1");
3944 emitcode ("pop", "dps");
3945 emitcode ("pop", "dpx");
3947 if (!inExcludeList ("dph"))
3948 emitcode ("pop", "dph");
3949 if (!inExcludeList ("dpl"))
3950 emitcode ("pop", "dpl");
3951 if (!inExcludeList ("b"))
3952 emitcode ("pop", "b");
3953 if (!inExcludeList ("acc"))
3954 emitcode ("pop", "acc");
3956 /* if debug then send end of function */
3957 if (options.debug && currFunc)
3959 debugFile->writeEndFunction (currFunc, ic, 1);
3962 emitcode ("reti", "");
3966 if (IFFUNC_CALLEESAVES(sym->type))
3970 /* if any registers used */
3973 /* save the registers used */
3974 for (i = sym->regsUsed->size; i >= 0; i--)
3976 if (bitVectBitValue (sym->regsUsed, i))
3977 emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
3982 /* if debug then send end of function */
3983 if (options.debug && currFunc)
3985 debugFile->writeEndFunction (currFunc, ic, 1);
3988 emitcode ("ret", "");
3991 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3994 /* If this was an interrupt handler using bank 0 that called another */
3995 /* function, then all registers must be saved; nothing to optimized. */
3996 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3997 && !FUNC_REGBANK(sym->type))
4000 /* There are no push/pops to optimize if not callee-saves or ISR */
4001 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
4004 /* If there were stack parameters, we cannot optimize without also */
4005 /* fixing all of the stack offsets; this is too dificult to consider. */
4006 if (FUNC_HASSTACKPARM(sym->type))
4009 /* Compute the registers actually used */
4010 regsUsed = newBitVect (ds390_nRegs);
4011 regsUsedPrologue = newBitVect (ds390_nRegs);
4014 if (lnp->ic && lnp->ic->op == FUNCTION)
4015 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
4017 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
4019 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
4020 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
4027 if (bitVectBitValue (regsUsedPrologue, DPS_IDX)
4028 && !bitVectBitValue (regsUsed, DPS_IDX))
4030 bitVectUnSetBit (regsUsedPrologue, DPS_IDX);
4033 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
4034 && !bitVectBitValue (regsUsed, CND_IDX))
4036 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
4037 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
4038 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
4039 bitVectUnSetBit (regsUsed, CND_IDX);
4042 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
4044 /* If this was an interrupt handler that called another function */
4045 /* function, then assume working registers may be modified by it. */
4046 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
4048 regsUsed = bitVectSetBit (regsUsed, AP_IDX);
4049 regsUsed = bitVectSetBit (regsUsed, DPX1_IDX);
4050 regsUsed = bitVectSetBit (regsUsed, DPL1_IDX);
4051 regsUsed = bitVectSetBit (regsUsed, DPH1_IDX);
4052 regsUsed = bitVectSetBit (regsUsed, DPX_IDX);
4053 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
4054 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
4055 regsUsed = bitVectSetBit (regsUsed, DPS_IDX);
4056 regsUsed = bitVectSetBit (regsUsed, B_IDX);
4057 regsUsed = bitVectSetBit (regsUsed, A_IDX);
4058 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
4061 /* Remove the unneeded push/pops */
4062 regsUnneeded = newBitVect (ds390_nRegs);
4065 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
4067 if (!strncmp(lnp->line, "push", 4))
4069 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
4070 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4072 connectLine (lnp->prev, lnp->next);
4073 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4076 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
4078 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
4079 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4081 connectLine (lnp->prev, lnp->next);
4082 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4089 for (idx = 0; idx < regsUnneeded->size; idx++)
4090 if (bitVectBitValue (regsUnneeded, idx))
4091 emitcode (";", "eliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
4093 freeBitVect (regsUnneeded);
4094 freeBitVect (regsUsed);
4095 freeBitVect (regsUsedPrologue);
4098 /*-----------------------------------------------------------------*/
4099 /* genJavaNativeRet - generate code for return JavaNative */
4100 /*-----------------------------------------------------------------*/
4101 static void genJavaNativeRet(iCode *ic)
4105 aopOp (IC_LEFT (ic), ic, FALSE,
4106 AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
4107 size = AOP_SIZE (IC_LEFT (ic));
4111 /* it is assigned to GPR0-R3 then push them */
4112 if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
4113 aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
4114 for (i = 0 ; i < size ; i++ ) {
4115 emitcode ("push","%s",
4116 aopGet(IC_LEFT(ic),i,FALSE,TRUE,DP2_RESULT_REG));
4118 for (i = (size-1) ; i >= 0 ; i--) {
4119 emitcode ("pop","a%s",javaRet[i]);
4122 for (i = 0 ; i < size ; i++)
4123 emitcode ("mov","%s,%s",javaRet[i],
4124 aopGet(IC_LEFT(ic),i,FALSE,TRUE,DP2_RESULT_REG));
4126 for (i = size ; i < 4 ; i++ )
4127 emitcode ("mov","%s,#0",javaRet[i]);
4131 /*-----------------------------------------------------------------*/
4132 /* genRet - generate code for return statement */
4133 /*-----------------------------------------------------------------*/
4137 int size, offset = 0, pushed = 0;
4139 D (emitcode (";", "genRet"));
4141 /* if we have no return value then
4142 just generate the "ret" */
4146 /* if this is a JavaNative function then return
4147 value in different register */
4148 if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
4149 genJavaNativeRet(ic);
4152 /* we have something to return then
4153 move the return value into place */
4154 aopOp (IC_LEFT (ic), ic, FALSE,
4155 (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
4156 size = AOP_SIZE (IC_LEFT (ic));
4158 _startLazyDPSEvaluation ();
4160 if (IS_BIT(_G.currentFunc->etype))
4162 movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4169 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
4171 l = aopGet (IC_LEFT (ic), offset++,
4173 emitcode ("push", "%s", l);
4178 /* Since A is the last element of fReturn,
4179 * it is OK to clobber it in the aopGet.
4181 l = aopGet (IC_LEFT (ic), offset,
4182 FALSE, FALSE, NULL);
4183 if (strcmp (fReturn[offset], l))
4184 emitcode ("mov", "%s,%s", fReturn[offset++], l);
4187 _endLazyDPSEvaluation ();
4192 if (strcmp (fReturn[pushed], "a"))
4193 emitcode ("pop", fReturn[pushed]);
4195 emitcode ("pop", "acc");
4197 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
4200 /* generate a jump to the return label
4201 if the next is not the return statement */
4202 if (!(ic->next && ic->next->op == LABEL &&
4203 IC_LABEL (ic->next) == returnLabel))
4205 emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
4209 /*-----------------------------------------------------------------*/
4210 /* genLabel - generates a label */
4211 /*-----------------------------------------------------------------*/
4213 genLabel (iCode * ic)
4215 /* special case never generate */
4216 if (IC_LABEL (ic) == entryLabel)
4219 D (emitcode (";", "genLabel"));
4221 emitLabel (IC_LABEL (ic));
4224 /*-----------------------------------------------------------------*/
4225 /* genGoto - generates a ljmp */
4226 /*-----------------------------------------------------------------*/
4228 genGoto (iCode * ic)
4230 D (emitcode (";", "genGoto"));
4232 emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
4235 /*-----------------------------------------------------------------*/
4236 /* findLabelBackwards: walks back through the iCode chain looking */
4237 /* for the given label. Returns number of iCode instructions */
4238 /* between that label and given ic. */
4239 /* Returns zero if label not found. */
4240 /*-----------------------------------------------------------------*/
4242 findLabelBackwards (iCode * ic, int key)
4251 /* If we have any pushes or pops, we cannot predict the distance.
4252 I don't like this at all, this should be dealt with in the
4254 if (ic->op == IPUSH || ic->op == IPOP) {
4258 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4260 /* printf("findLabelBackwards = %d\n", count); */
4268 /*-----------------------------------------------------------------*/
4269 /* genPlusIncr :- does addition with increment if possible */
4270 /*-----------------------------------------------------------------*/
4272 genPlusIncr (iCode * ic)
4274 unsigned int icount;
4275 unsigned int size = getDataSize (IC_RESULT (ic));
4277 /* will try to generate an increment */
4278 /* if the right side is not a literal
4280 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4283 /* if the literal value of the right hand side
4284 is greater than 4 then it is not worth it */
4285 if ((icount = (unsigned int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4288 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4289 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4291 emitcode("inc","%s",aopGet(IC_RESULT(ic),0,FALSE,FALSE,NULL));
4295 /* if increment 16 bits in register */
4297 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4298 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4299 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4308 /* If the next instruction is a goto and the goto target
4309 * is <= 5 instructions previous to this, we can generate
4310 * jumps straight to that target.
4312 if (ic->next && ic->next->op == GOTO
4313 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4316 D (emitcode (";", "tail increment optimized (range %d)", labelRange));
4317 tlbl = IC_LABEL (ic->next);
4322 tlbl = newiTempLabel (NULL);
4325 l = aopGet (IC_RESULT (ic), LSB, FALSE, FALSE, NULL);
4326 emitcode ("inc", "%s", l);
4328 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4329 IS_AOP_PREG (IC_RESULT (ic)))
4331 emitcode ("cjne", "%s,%s,!tlabel", l, zero, tlbl->key + 100);
4335 emitcode ("clr", "a");
4336 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4339 l = aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE, NULL);
4340 emitcode ("inc", "%s", l);
4343 if (!strcmp(l, "acc"))
4345 emitcode("jnz", "!tlabel", tlbl->key + 100);
4347 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4348 IS_AOP_PREG (IC_RESULT (ic)))
4350 emitcode ("cjne", "%s,%s,!tlabel", l, zero, tlbl->key + 100);
4354 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4357 l = aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE, NULL);
4358 emitcode ("inc", "%s", l);
4362 if (!strcmp(l, "acc"))
4364 emitcode("jnz", "!tlabel", tlbl->key + 100);
4366 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4367 IS_AOP_PREG (IC_RESULT (ic)))
4369 emitcode ("cjne", "%s,%s,!tlabel", l, zero, tlbl->key + 100);
4373 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4376 l = aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE, NULL);
4377 emitcode ("inc", "%s", l);
4387 if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
4388 !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 &&
4389 options.model == MODEL_FLAT24 )
4391 if (IC_RESULT(ic)->isGptr)
4393 emitcode ("mov", "b,%s", aopGet(IC_LEFT (ic), 3, FALSE, FALSE, NULL));
4397 emitcode ("mov", "dpx,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE, NULL));
4399 emitcode ("mov", "dph,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE, NULL));
4401 emitcode ("mov", "dpl,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4405 emitcode ("inc", "dptr");
4409 if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
4410 AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
4413 emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
4415 emitcode ("inc", "dptr");
4416 emitcode ("mov", "dps,#0");
4420 /* if the sizes are greater than 1 then we cannot */
4421 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4422 AOP_SIZE (IC_LEFT (ic)) > 1)
4425 /* we can if the aops of the left & result match or
4426 if they are in registers and the registers are the
4429 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4430 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4431 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4435 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4436 emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
4437 aopPut (IC_RESULT (ic), "a", 0);
4441 _startLazyDPSEvaluation ();
4444 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4446 _endLazyDPSEvaluation ();
4455 /*-----------------------------------------------------------------*/
4456 /* outBitAcc - output a bit in acc */
4457 /*-----------------------------------------------------------------*/
4459 outBitAcc (operand * result)
4461 symbol *tlbl = newiTempLabel (NULL);
4462 /* if the result is a bit */
4463 if (AOP_TYPE (result) == AOP_CRY)
4465 aopPut (result, "a", 0);
4469 emitcode ("jz", "!tlabel", tlbl->key + 100);
4470 emitcode ("mov", "a,%s", one);
4476 /*-----------------------------------------------------------------*/
4477 /* genPlusBits - generates code for addition of two bits */
4478 /*-----------------------------------------------------------------*/
4480 genPlusBits (iCode * ic)
4482 D (emitcode (";", "genPlusBits"));
4484 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4485 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4487 symbol *lbl = newiTempLabel (NULL);
4488 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4489 emitcode ("cpl", "c");
4491 outBitC (IC_RESULT (ic));
4495 emitcode ("clr", "a");
4496 emitcode ("rlc", "a");
4497 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4498 emitcode ("addc", "a,%s", zero);
4499 outAcc (IC_RESULT (ic));
4504 adjustArithmeticResult (iCode * ic)
4506 if (opIsGptr (IC_RESULT (ic)) &&
4507 opIsGptr (IC_LEFT (ic)) &&
4508 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4510 aopPut (IC_RESULT (ic),
4511 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE, NULL),
4515 if (opIsGptr (IC_RESULT (ic)) &&
4516 opIsGptr (IC_RIGHT (ic)) &&
4517 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4519 aopPut (IC_RESULT (ic),
4520 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE, NULL),
4524 if (opIsGptr (IC_RESULT (ic)) &&
4525 IC_LEFT (ic) && AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4526 IC_RIGHT (ic) && AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4527 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4528 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4531 SNPRINTF (buffer, sizeof(buffer),
4532 "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4533 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4537 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
4538 // generates the result if possible. If result is generated, returns TRUE; otherwise
4539 // returns false and caller must deal with fact that result isn't aopOp'd.
4540 bool aopOp3(iCode * ic)
4542 bool dp1InUse, dp2InUse;
4545 // First, generate the right opcode. DPTR may be used if neither left nor result are
4548 // D (emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
4549 // AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
4550 // AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
4551 // AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
4553 // D (emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
4554 // AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
4555 // AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
4556 // AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
4559 // Right uses DPTR unless left or result is an AOP_STR; however,
4560 // if right is an AOP_STR, it must use DPTR regardless.
4561 if ((AOP_IS_STR (IC_LEFT (ic)) || AOP_IS_STR (IC_RESULT (ic)))
4562 && !AOP_IS_STR (IC_RIGHT (ic)))
4571 aopOp (IC_RIGHT(ic), ic, FALSE, useDp2);
4573 // if the right used DPTR, left MUST use DPTR2.
4574 // if the right used DPTR2, left MUST use DPTR.
4575 // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
4576 // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
4577 // enabling us to assign DPTR to result.
4579 if (AOP_USESDPTR (IC_RIGHT (ic)))
4583 else if (AOP_USESDPTR2 (IC_RIGHT (ic)))
4589 if (AOP_IS_STR (IC_RESULT (ic)) && !AOP_IS_STR (IC_LEFT (ic)))
4599 aopOp (IC_LEFT (ic), ic, FALSE, useDp2);
4602 // We've op'd the left & right. So, if left or right are the same operand as result,
4603 // we know aopOp will succeed, and we can just do it & bail.
4604 if (isOperandEqual (IC_LEFT (ic), IC_RESULT (ic)))
4606 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4609 if (isOperandEqual (IC_RIGHT (ic), IC_RESULT (ic)))
4611 // D (emitcode(";", "aopOp3: (left | right) & result equal"));
4612 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4616 // Operands may be equivalent (but not equal) if they share a spill location. If
4617 // so, use the same DPTR or DPTR2.
4618 if (operandsEqu (IC_LEFT (ic), IC_RESULT (ic)))
4620 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4623 if (operandsEqu (IC_RIGHT (ic), IC_RESULT (ic)))
4625 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4629 // Note which dptrs are currently in use.
4630 dp1InUse = AOP_USESDPTR (IC_LEFT (ic)) || AOP_USESDPTR (IC_RIGHT (ic));
4631 dp2InUse = AOP_USESDPTR2 (IC_LEFT (ic)) || AOP_USESDPTR2 (IC_RIGHT (ic));
4633 // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot
4635 if (dp1InUse && AOP_IS_STR (IC_RESULT (ic)))
4640 // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
4641 if (dp2InUse && AOP_IS_DPTRn (IC_RESULT (ic)))
4646 // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck
4647 if (dp1InUse && dp2InUse && isOperandInFarSpace (IC_RESULT (ic)))
4652 aopOp (IC_RESULT (ic), ic, TRUE, dp1InUse);
4654 // Some sanity checking...
4655 if (dp1InUse && AOP_USESDPTR (IC_RESULT (ic)))
4658 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
4659 __FILE__, __LINE__, ic->filename, ic->lineno);
4660 emitcode(";", ">>> unexpected DPTR here.");
4663 if (dp2InUse && AOP_USESDPTR2 (IC_RESULT (ic)))
4666 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
4667 __FILE__, __LINE__, ic->filename, ic->lineno);
4668 emitcode(";", ">>> unexpected DPTR2 here.");
4674 // Macro to aopOp all three operands of an ic. If this cannot be done,
4675 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
4676 // will be set TRUE. The caller must then handle the case specially, noting
4677 // that the IC_RESULT operand is not aopOp'd.
4679 #define AOP_OP_3_NOFATAL(ic, rc) \
4680 do { rc = !aopOp3(ic); } while (0)
4682 // aopOp the left & right operands of an ic.
4683 #define AOP_OP_2(ic) \
4684 aopOp (IC_RIGHT (ic), ic, FALSE, AOP_IS_STR (IC_LEFT (ic))); \
4685 aopOp (IC_LEFT (ic), ic, FALSE, AOP_USESDPTR (IC_RIGHT (ic)));
4687 // convienience macro.
4688 #define AOP_SET_LOCALS(ic) \
4689 left = IC_LEFT(ic); \
4690 right = IC_RIGHT(ic); \
4691 result = IC_RESULT(ic);
4694 // Given an integer value of pushedSize bytes on the stack,
4695 // adjust it to be resultSize bytes, either by discarding
4696 // the most significant bytes or by zero-padding.
4698 // On exit from this macro, pushedSize will have been adjusted to
4699 // equal resultSize, and ACC may be trashed.
4700 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
4701 /* If the pushed data is bigger than the result, \
4702 * simply discard unused bytes. Icky, but works. \
4704 while (pushedSize > resultSize) \
4706 D (emitcode (";", "discarding unused result byte.")); \
4707 emitcode ("pop", "acc"); \
4710 if (pushedSize < resultSize) \
4712 emitcode ("clr", "a"); \
4713 /* Conversly, we haven't pushed enough here. \
4714 * just zero-pad, and all is well. \
4716 while (pushedSize < resultSize) \
4718 emitcode("push", "acc"); \
4722 assert(pushedSize == resultSize);
4724 /*-----------------------------------------------------------------*/
4725 /* genPlus - generates code for addition */
4726 /*-----------------------------------------------------------------*/
4728 genPlus (iCode * ic)
4730 int size, offset = 0;
4733 bool swappedLR = FALSE;
4735 D (emitcode (";", "genPlus"));
4737 /* special cases :- */
4738 if ( AOP_IS_STR (IC_LEFT (ic)) &&
4739 isOperandLiteral (IC_RIGHT (ic)) && OP_SYMBOL (IC_RESULT (ic))->ruonly) {
4740 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
4741 size = (int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4743 while (size--) emitcode ("inc","dptr");
4745 emitcode ("mov", "a,dpl");
4746 emitcode ("add", "a,#!constbyte", size & 0xff);
4747 emitcode ("mov", "dpl,a");
4748 emitcode ("mov", "a,dph");
4749 emitcode ("addc", "a,#!constbyte", (size >> 8) & 0xff);
4750 emitcode ("mov", "dph,a");
4751 emitcode ("mov", "a,dpx");
4752 emitcode ("addc", "a,#!constbyte", (size >> 16) & 0xff);
4753 emitcode ("mov", "dpx,a");
4755 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4758 if ( IS_SYMOP (IC_LEFT (ic)) &&
4759 OP_SYMBOL (IC_LEFT (ic))->remat &&
4760 isOperandInFarSpace (IC_RIGHT (ic))) {
4761 operand *op = IC_RIGHT(ic);
4762 IC_RIGHT(ic) = IC_LEFT(ic);
4766 AOP_OP_3_NOFATAL (ic, pushResult);
4770 D (emitcode (";", "genPlus: must push result: 3 ops in far space"));
4775 /* if literal, literal on the right or
4776 if left requires ACC or right is already
4778 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4779 ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic)))) ||
4780 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4782 operand *t = IC_RIGHT (ic);
4783 IC_RIGHT (ic) = IC_LEFT (ic);
4786 D (emitcode (";", "Swapped plus args."));
4789 /* if both left & right are in bit
4791 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4792 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4798 /* if left in bit space & right literal */
4799 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4800 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4802 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4803 /* if result in bit space */
4804 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4806 if (ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4807 emitcode ("cpl", "c");
4808 outBitC (IC_RESULT (ic));
4812 size = getDataSize (IC_RESULT (ic));
4813 _startLazyDPSEvaluation ();
4816 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4817 emitcode ("addc", "a,%s", zero);
4818 aopPut (IC_RESULT (ic), "a", offset++);
4820 _endLazyDPSEvaluation ();
4825 /* if I can do an increment instead
4826 of add then GOOD for ME */
4827 if (genPlusIncr (ic) == TRUE)
4829 D (emitcode (";", "did genPlusIncr"));
4834 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4836 _startLazyDPSEvaluation ();
4839 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4841 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
4843 emitcode ("add", "a,%s",
4844 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4846 emitcode ("addc", "a,%s",
4847 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4851 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4853 /* right is going to use ACC or we would have taken the
4856 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4858 D(emitcode(";", "+ AOP_ACC special case."););
4859 emitcode("xch", "a, %s", DP2_RESULT_REG);
4861 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4864 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4867 emitcode("add", "a, %s", DP2_RESULT_REG);
4871 emitcode ("add", "a,%s",
4872 aopGet (IC_LEFT(ic), offset, FALSE, FALSE,
4878 emitcode ("addc", "a,%s",
4879 aopGet (IC_LEFT (ic), offset, FALSE, FALSE,
4885 aopPut (IC_RESULT (ic), "a", offset);
4889 emitcode ("push", "acc");
4893 _endLazyDPSEvaluation ();
4897 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4899 size = getDataSize (IC_LEFT (ic));
4900 rSize = getDataSize (IC_RESULT (ic));
4902 ADJUST_PUSHED_RESULT(size, rSize);
4904 _startLazyDPSEvaluation ();
4907 emitcode ("pop", "acc");
4908 aopPut (IC_RESULT (ic), "a", size);
4910 _endLazyDPSEvaluation ();
4913 adjustArithmeticResult (ic);
4916 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4919 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4920 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4924 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4925 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4929 /*-----------------------------------------------------------------*/
4930 /* genMinusDec :- does subtraction with decrement if possible */
4931 /*-----------------------------------------------------------------*/
4933 genMinusDec (iCode * ic)
4935 unsigned int icount;
4936 unsigned int size = getDataSize (IC_RESULT (ic));
4938 /* will try to generate an increment */
4939 /* if the right side is not a literal
4941 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4944 /* if the literal value of the right hand side
4945 is greater than 4 then it is not worth it */
4946 if ((icount = (unsigned int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4949 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4950 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4952 emitcode("dec","%s",aopGet(IC_RESULT(ic),0,FALSE,FALSE,NULL));
4956 /* if decrement 16 bits in register */
4957 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4958 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4959 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4968 /* If the next instruction is a goto and the goto target
4969 * is <= 5 instructions previous to this, we can generate
4970 * jumps straight to that target.
4972 if (ic->next && ic->next->op == GOTO
4973 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4976 D (emitcode (";", "tail decrement optimized (range %d)", labelRange));
4977 tlbl = IC_LABEL (ic->next);
4982 tlbl = newiTempLabel (NULL);
4986 l = aopGet (IC_RESULT (ic), LSB, FALSE, FALSE, NULL);
4987 emitcode ("dec", "%s", l);
4989 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4990 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4991 IS_AOP_PREG (IC_RESULT (ic)))
4993 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4997 emitcode ("mov", "a,#!constbyte",0xff);
4998 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
5000 l = aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE, NULL);
5001 emitcode ("dec", "%s", l);
5004 if (!strcmp(l, "acc"))
5006 emitcode("jnz", "!tlabel", tlbl->key + 100);
5008 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
5009 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
5010 IS_AOP_PREG (IC_RESULT (ic)))
5012 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
5016 emitcode ("mov", "a,#!constbyte",0xff);
5017 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
5019 l = aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE, NULL);
5020 emitcode ("dec", "%s", l);
5024 if (!strcmp(l, "acc"))
5026 emitcode("jnz", "!tlabel", tlbl->key + 100);
5028 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
5029 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
5030 IS_AOP_PREG (IC_RESULT (ic)))
5032 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
5036 emitcode ("mov", "a,#!constbyte",0xff);
5037 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
5039 l = aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE, NULL);
5040 emitcode ("dec", "%s", l);
5049 /* if the sizes are greater than 1 then we cannot */
5050 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
5051 AOP_SIZE (IC_LEFT (ic)) > 1)
5054 /* we can if the aops of the left & result match or
5055 if they are in registers and the registers are the
5058 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
5059 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
5060 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
5064 if (aopGetUsesAcc (IC_LEFT (ic), 0))
5066 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL));
5071 l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL);
5074 _startLazyDPSEvaluation ();
5077 emitcode ("dec", "%s", l);
5079 _endLazyDPSEvaluation ();
5081 if (AOP_NEEDSACC (IC_RESULT (ic)))
5082 aopPut (IC_RESULT (ic), "a", 0);
5090 /*-----------------------------------------------------------------*/
5091 /* addSign - complete with sign */
5092 /*-----------------------------------------------------------------*/
5094 addSign (operand * result, int offset, int sign)
5096 int size = (getDataSize (result) - offset);
5099 _startLazyDPSEvaluation();
5102 emitcode ("rlc", "a");
5103 emitcode ("subb", "a,acc");
5106 aopPut (result, "a", offset++);
5113 aopPut (result, zero, offset++);
5116 _endLazyDPSEvaluation();
5120 /*-----------------------------------------------------------------*/
5121 /* genMinusBits - generates code for subtraction of two bits */
5122 /*-----------------------------------------------------------------*/
5124 genMinusBits (iCode * ic)
5126 symbol *lbl = newiTempLabel (NULL);
5128 D (emitcode (";", "genMinusBits"));
5130 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
5132 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
5133 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
5134 emitcode ("cpl", "c");
5136 outBitC (IC_RESULT (ic));
5140 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
5141 emitcode ("subb", "a,acc");
5142 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
5143 emitcode ("inc", "a");
5145 aopPut (IC_RESULT (ic), "a", 0);
5146 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
5150 /*-----------------------------------------------------------------*/
5151 /* genMinus - generates code for subtraction */
5152 /*-----------------------------------------------------------------*/
5154 genMinus (iCode * ic)
5156 int size, offset = 0;
5161 D (emitcode (";", "genMinus"));
5163 AOP_OP_3_NOFATAL(ic, pushResult);
5167 /* special cases :- */
5168 /* if both left & right are in bit space */
5169 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
5170 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
5176 /* if I can do an decrement instead
5177 of subtract then GOOD for ME */
5178 if (genMinusDec (ic) == TRUE)
5183 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
5185 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
5191 lit = (long) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5196 /* if literal, add a,#-lit, else normal subb */
5197 _startLazyDPSEvaluation ();
5199 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
5200 if (AOP_USESDPTR(IC_RIGHT(ic))) {
5201 emitcode ("mov","b,%s",
5202 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
5203 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
5204 emitcode ("subb","a,b");
5206 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
5207 emitcode ("subb", "a,%s",
5208 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE,
5212 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
5213 /* first add without previous c */
5215 if (!size && lit==-1) {
5216 emitcode ("dec", "a");
5218 emitcode ("add", "a,#!constbyte",
5219 (unsigned int) (lit & 0x0FFL));
5222 emitcode ("addc", "a,#!constbyte",
5223 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5228 emitcode ("push", "acc");
5230 aopPut (IC_RESULT (ic), "a", offset);
5234 _endLazyDPSEvaluation ();
5238 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
5240 size = getDataSize (IC_LEFT (ic));
5241 rSize = getDataSize (IC_RESULT (ic));
5243 ADJUST_PUSHED_RESULT(size, rSize);
5245 _startLazyDPSEvaluation ();
5248 emitcode ("pop", "acc");
5249 aopPut (IC_RESULT (ic), "a", size);
5251 _endLazyDPSEvaluation ();
5254 adjustArithmeticResult (ic);
5257 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5258 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5259 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5263 /*-----------------------------------------------------------------*/
5264 /* genMultbits :- multiplication of bits */
5265 /*-----------------------------------------------------------------*/
5267 genMultbits (operand * left,
5272 D (emitcode (";", "genMultbits"));
5274 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5275 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5276 aopOp(result, ic, TRUE, FALSE);
5280 /*-----------------------------------------------------------------*/
5281 /* genMultOneByte : 8*8=8/16 bit multiplication */
5282 /*-----------------------------------------------------------------*/
5284 genMultOneByte (operand * left,
5291 bool runtimeSign, compiletimeSign;
5292 bool lUnsigned, rUnsigned, pushedB;
5294 /* (if two literals: the value is computed before) */
5295 /* if one literal, literal on the right */
5296 if (AOP_TYPE (left) == AOP_LIT)
5301 /* emitcode (";", "swapped left and right"); */
5303 /* if no literal, unsigned on the right: shorter code */
5304 if ( AOP_TYPE (right) != AOP_LIT
5305 && SPEC_USIGN (getSpec (operandType (left))))
5312 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5313 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5317 if ((lUnsigned && rUnsigned)
5318 /* sorry, I don't know how to get size
5319 without calling aopOp (result,...);
5320 see Feature Request */
5321 /* || size == 1 */ ) /* no, this is not a bug; with a 1 byte result there's
5322 no need to take care about the signedness! */
5324 /* just an unsigned 8 * 8 = 8 multiply
5326 /* emitcode (";","unsigned"); */
5327 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
5328 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
5329 emitcode ("mul", "ab");
5332 aopOp (result, ic, TRUE, FALSE);
5333 size = AOP_SIZE (result);
5335 if (size < 1 || size > 2)
5337 /* this should never happen */
5338 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
5339 size, __FILE__, lineno);
5343 aopPut (result, "a", 0);
5346 aopPut (result, "b", 1);
5352 /* we have to do a signed multiply */
5353 /* emitcode (";", "signed"); */
5355 /* now sign adjust for both left & right */
5357 /* let's see what's needed: */
5358 /* apply negative sign during runtime */
5359 runtimeSign = FALSE;
5360 /* negative sign from literals */
5361 compiletimeSign = FALSE;
5365 if (AOP_TYPE(left) == AOP_LIT)
5367 /* signed literal */
5368 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5370 compiletimeSign = TRUE;
5373 /* signed but not literal */
5379 if (AOP_TYPE(right) == AOP_LIT)
5381 /* signed literal */
5382 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
5384 compiletimeSign ^= TRUE;
5387 /* signed but not literal */
5391 /* initialize F0, which stores the runtime sign */
5394 if (compiletimeSign)
5395 emitcode ("setb", "F0"); /* set sign flag */
5397 emitcode ("clr", "F0"); /* reset sign flag */
5400 /* save the signs of the operands */
5401 if (AOP_TYPE(right) == AOP_LIT)
5403 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
5405 if (!rUnsigned && val < 0)
5406 emitcode ("mov", "b,#!constbyte", -val);
5408 emitcode ("mov", "b,#!constbyte", (unsigned char) val);
5410 else /* ! literal */
5412 if (rUnsigned) /* emitcode (";", "signed"); */
5413 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
5416 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
5417 lbl = newiTempLabel (NULL);
5418 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5419 emitcode ("cpl", "F0"); /* complement sign flag */
5420 emitcode ("cpl", "a"); /* 2's complement */
5421 emitcode ("inc", "a");
5423 emitcode ("mov", "b,a");
5427 if (AOP_TYPE(left) == AOP_LIT)
5429 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5431 if (!lUnsigned && val < 0)
5432 emitcode ("mov", "a,#!constbyte", -val);
5434 emitcode ("mov", "a,#!constbyte", (unsigned char) val);
5436 else /* ! literal */
5438 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
5440 if (!lUnsigned) /* emitcode (";", "signed"); */
5442 lbl = newiTempLabel (NULL);
5443 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5444 emitcode ("cpl", "F0"); /* complement sign flag */
5445 emitcode ("cpl", "a"); /* 2's complement */
5446 emitcode ("inc", "a");
5451 /* now the multiplication */
5452 emitcode ("mul", "ab");
5454 aopOp(result, ic, TRUE, FALSE);
5455 size = AOP_SIZE (result);
5457 if (size < 1 || size > 2)
5459 /* this should never happen */
5460 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
5461 size, __FILE__, lineno);
5465 if (runtimeSign || compiletimeSign)
5467 lbl = newiTempLabel (NULL);
5469 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5470 emitcode ("cpl", "a"); /* lsb 2's complement */
5472 emitcode ("inc", "a"); /* inc doesn't set carry flag */
5475 emitcode ("add", "a,#0x01"); /* this sets carry flag */
5476 emitcode ("xch", "a,b");
5477 emitcode ("cpl", "a"); /* msb 2's complement */
5478 emitcode ("addc", "a,#0x00");
5479 emitcode ("xch", "a,b");
5483 aopPut (result, "a", 0);
5486 aopPut (result, "b", 1);
5491 /*-----------------------------------------------------------------*/
5492 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
5493 /*-----------------------------------------------------------------*/
5494 static void genMultTwoByte (operand *left, operand *right,
5495 operand *result, iCode *ic)
5497 sym_link *retype = getSpec(operandType(right));
5498 sym_link *letype = getSpec(operandType(left));
5499 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5502 if (AOP_TYPE (left) == AOP_LIT) {
5507 /* save EA bit in F1 */
5508 lbl = newiTempLabel(NULL);
5509 emitcode ("setb","F1");
5510 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5511 emitcode ("clr","F1");
5514 /* load up MB with right */
5516 emitcode("clr","F0");
5517 if (AOP_TYPE(right) == AOP_LIT) {
5518 int val=(int) ulFromVal (AOP (right)->aopu.aop_lit);
5520 emitcode("setb","F0");
5523 emitcode ("mov","mb,#!constbyte",val & 0xff);
5524 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5526 lbl = newiTempLabel(NULL);
5527 emitcode ("mov","b,%s",aopGet(right,0,FALSE,FALSE,NULL));
5528 emitcode ("mov","a,%s",aopGet(right,1,FALSE,FALSE,NULL));
5529 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5530 emitcode ("xch", "a,b");
5531 emitcode ("cpl","a");
5532 emitcode ("add", "a,#1");
5533 emitcode ("xch", "a,b");
5534 emitcode ("cpl", "a"); // msb
5535 emitcode ("addc", "a,#0");
5536 emitcode ("setb","F0");
5538 emitcode ("mov","mb,b");
5539 emitcode ("mov","mb,a");
5542 emitcode ("mov","mb,%s",aopGet(right,0,FALSE,FALSE,NULL));
5543 emitcode ("mov","mb,%s",aopGet(right,1,FALSE,FALSE,NULL));
5545 /* load up MA with left */
5547 lbl = newiTempLabel(NULL);
5548 emitcode ("mov","b,%s",aopGet(left,0,FALSE,FALSE,NULL));
5549 emitcode ("mov","a,%s",aopGet(left,1,FALSE,FALSE,NULL));
5550 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5551 emitcode ("xch", "a,b");
5552 emitcode ("cpl","a");
5553 emitcode ("add", "a,#1");
5554 emitcode ("xch", "a,b");
5555 emitcode ("cpl", "a"); // msb
5556 emitcode ("addc","a,#0");
5557 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5558 emitcode ("setb","F0");
5560 emitcode ("mov","ma,b");
5561 emitcode ("mov","ma,a");
5563 emitcode ("mov","ma,%s",aopGet(left,0,FALSE,FALSE,NULL));
5564 emitcode ("mov","ma,%s",aopGet(left,1,FALSE,FALSE,NULL));
5566 /* wait for multiplication to finish */
5567 lbl = newiTempLabel(NULL);
5569 emitcode("mov","a,mcnt1");
5570 emitcode("anl","a,#!constbyte",0x80);
5571 emitcode("jnz","!tlabel",lbl->key+100);
5573 freeAsmop (left, NULL, ic, TRUE);
5574 freeAsmop (right, NULL, ic,TRUE);
5575 aopOp(result, ic, TRUE, FALSE);
5577 /* if unsigned then simple */
5579 emitcode ("mov","a,ma");
5580 if (AOP_SIZE(result) >= 4) aopPut(result,"a",3);
5581 emitcode ("mov","a,ma");
5582 if (AOP_SIZE(result) >= 3) aopPut(result,"a",2);
5583 aopPut(result,"ma",1);
5584 aopPut(result,"ma",0);
5586 emitcode("push","ma");
5587 emitcode("push","ma");
5588 emitcode("push","ma");
5590 /* negate result if needed */
5591 lbl = newiTempLabel(NULL);
5592 emitcode("jnb","F0,!tlabel",lbl->key+100);
5593 emitcode("cpl","a");
5594 emitcode("add","a,#1");
5596 if (AOP_TYPE(result) == AOP_ACC)
5598 D (emitcode(";", "ACC special case."));
5599 /* We know result is the only live aop, and
5600 * it's obviously not a DPTR2, so AP is available.
5602 emitcode("mov", "%s,acc", DP2_RESULT_REG);
5606 aopPut(result,"a",0);
5609 emitcode("pop","acc");
5610 lbl = newiTempLabel(NULL);
5611 emitcode("jnb","F0,!tlabel",lbl->key+100);
5612 emitcode("cpl","a");
5613 emitcode("addc","a,#0");
5615 aopPut(result,"a",1);
5616 emitcode("pop","acc");
5617 if (AOP_SIZE(result) >= 3) {
5618 lbl = newiTempLabel(NULL);
5619 emitcode("jnb","F0,!tlabel",lbl->key+100);
5620 emitcode("cpl","a");
5621 emitcode("addc","a,#0");
5623 aopPut(result,"a",2);
5625 emitcode("pop","acc");
5626 if (AOP_SIZE(result) >= 4) {
5627 lbl = newiTempLabel(NULL);
5628 emitcode("jnb","F0,!tlabel",lbl->key+100);
5629 emitcode("cpl","a");
5630 emitcode("addc","a,#0");
5632 aopPut(result,"a",3);
5634 if (AOP_TYPE(result) == AOP_ACC)
5636 /* We stashed the result away above. */
5637 emitcode("mov", "acc,%s", DP2_RESULT_REG);
5641 freeAsmop (result, NULL, ic, TRUE);
5643 /* restore EA bit in F1 */
5644 lbl = newiTempLabel(NULL);
5645 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5646 emitcode ("setb","EA");
5651 /*-----------------------------------------------------------------*/
5652 /* genMult - generates code for multiplication */
5653 /*-----------------------------------------------------------------*/
5655 genMult (iCode * ic)
5657 operand *left = IC_LEFT (ic);
5658 operand *right = IC_RIGHT (ic);
5659 operand *result = IC_RESULT (ic);
5661 D (emitcode (";", "genMult"));
5663 /* assign the asmops */
5666 /* special cases first */
5668 if (AOP_TYPE (left) == AOP_CRY &&
5669 AOP_TYPE (right) == AOP_CRY)
5671 genMultbits (left, right, result, ic);
5675 /* if both are of size == 1 */
5676 if (AOP_SIZE (left) == 1 &&
5677 AOP_SIZE (right) == 1)
5679 genMultOneByte (left, right, result, ic);
5683 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5684 /* use the ds390 ARITHMETIC accel UNIT */
5685 genMultTwoByte (left, right, result, ic);
5688 /* should have been converted to function call */
5692 freeAsmop (result, NULL, ic, TRUE);
5693 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5694 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5697 /*-----------------------------------------------------------------*/
5698 /* genDivbits :- division of bits */
5699 /*-----------------------------------------------------------------*/
5701 genDivbits (operand * left,
5709 D(emitcode (";", "genDivbits"));
5713 /* the result must be bit */
5714 LOAD_AB_FOR_DIV (left, right, l);
5715 emitcode ("div", "ab");
5716 emitcode ("rrc", "a");
5717 aopOp(result, ic, TRUE, FALSE);
5721 aopPut (result, "c", 0);
5724 /*-----------------------------------------------------------------*/
5725 /* genDivOneByte : 8 bit division */
5726 /*-----------------------------------------------------------------*/
5728 genDivOneByte (operand * left,
5733 bool lUnsigned, rUnsigned, pushedB;
5734 bool runtimeSign, compiletimeSign;
5739 D(emitcode (";", "genDivOneByte"));
5742 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5743 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5747 /* signed or unsigned */
5748 if (lUnsigned && rUnsigned)
5750 /* unsigned is easy */
5751 LOAD_AB_FOR_DIV (left, right, l);
5752 emitcode ("div", "ab");
5755 aopOp (result, ic, TRUE, FALSE);
5756 aopPut (result, "a", 0);
5759 size = AOP_SIZE (result) - 1;
5762 aopPut (result, zero, offset++);
5768 /* signed is a little bit more difficult */
5770 /* now sign adjust for both left & right */
5772 /* let's see what's needed: */
5773 /* apply negative sign during runtime */
5774 runtimeSign = FALSE;
5775 /* negative sign from literals */
5776 compiletimeSign = FALSE;
5780 if (AOP_TYPE(left) == AOP_LIT)
5782 /* signed literal */
5783 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5785 compiletimeSign = TRUE;
5788 /* signed but not literal */
5794 if (AOP_TYPE(right) == AOP_LIT)
5796 /* signed literal */
5797 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
5799 compiletimeSign ^= TRUE;
5802 /* signed but not literal */
5806 /* initialize F0, which stores the runtime sign */
5809 if (compiletimeSign)
5810 emitcode ("setb", "F0"); /* set sign flag */
5812 emitcode ("clr", "F0"); /* reset sign flag */
5815 /* save the signs of the operands */
5816 if (AOP_TYPE(right) == AOP_LIT)
5818 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
5820 if (!rUnsigned && val < 0)
5821 emitcode ("mov", "b,#0x%02x", -val);
5823 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5825 else /* ! literal */
5828 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
5831 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
5832 lbl = newiTempLabel (NULL);
5833 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5834 emitcode ("cpl", "F0"); /* complement sign flag */
5835 emitcode ("cpl", "a"); /* 2's complement */
5836 emitcode ("inc", "a");
5838 emitcode ("mov", "b,a");
5842 if (AOP_TYPE(left) == AOP_LIT)
5844 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5846 if (!lUnsigned && val < 0)
5847 emitcode ("mov", "a,#0x%02x", -val);
5849 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5851 else /* ! literal */
5853 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
5857 lbl = newiTempLabel (NULL);
5858 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5859 emitcode ("cpl", "F0"); /* complement sign flag */
5860 emitcode ("cpl", "a"); /* 2's complement */
5861 emitcode ("inc", "a");
5866 /* now the division */
5867 emitcode ("nop", "; workaround for DS80C390 div bug.");
5868 emitcode ("div", "ab");
5870 if (runtimeSign || compiletimeSign)
5872 lbl = newiTempLabel (NULL);
5874 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5875 emitcode ("cpl", "a"); /* lsb 2's complement */
5876 emitcode ("inc", "a");
5880 aopOp (result, ic, TRUE, FALSE);
5881 size = AOP_SIZE (result) - 1;
5885 /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
5886 then the result will be in b, a */
5887 emitcode ("mov", "b,a"); /* 1 */
5888 /* msb is 0x00 or 0xff depending on the sign */
5891 emitcode ("mov", "c,F0");
5892 emitcode ("subb", "a,acc");
5893 emitcode ("xch", "a,b"); /* 2 */
5895 aopPut (result, "b", offset++); /* write msb's */
5897 else /* compiletimeSign */
5899 aopPut (result, "#0xff", offset++); /* write msb's */
5901 aopPut (result, "a", 0); /* 3: write lsb */
5906 aopOp(result, ic, TRUE, FALSE);
5907 size = AOP_SIZE (result) - 1;
5909 aopPut (result, "a", 0);
5911 aopPut (result, zero, offset++);
5917 /*-----------------------------------------------------------------*/
5918 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
5919 /*-----------------------------------------------------------------*/
5920 static void genDivTwoByte (operand *left, operand *right,
5921 operand *result, iCode *ic)
5923 sym_link *retype = getSpec(operandType(right));
5924 sym_link *letype = getSpec(operandType(left));
5925 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5928 /* save EA bit in F1 */
5929 lbl = newiTempLabel(NULL);
5930 emitcode ("setb","F1");
5931 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5932 emitcode ("clr","F1");
5935 /* load up MA with left */
5937 emitcode("clr","F0");
5938 lbl = newiTempLabel(NULL);
5939 emitcode ("mov","b,%s",aopGet(left,0,FALSE,FALSE,NULL));
5940 emitcode ("mov","a,%s",aopGet(left,1,FALSE,FALSE,NULL));
5941 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5942 emitcode ("xch", "a,b");
5943 emitcode ("cpl","a");
5944 emitcode ("add", "a,#1");
5945 emitcode ("xch", "a,b");
5946 emitcode ("cpl", "a"); // msb
5947 emitcode ("addc","a,#0");
5948 emitcode ("setb","F0");
5950 emitcode ("mov","ma,b");
5951 emitcode ("mov","ma,a");
5953 emitcode ("mov","ma,%s",aopGet(left,0,FALSE,FALSE,NULL));
5954 emitcode ("mov","ma,%s",aopGet(left,1,FALSE,FALSE,NULL));
5957 /* load up MB with right */
5959 if (AOP_TYPE(right) == AOP_LIT) {
5960 int val=(int) ulFromVal (AOP (right)->aopu.aop_lit);
5962 lbl = newiTempLabel(NULL);
5963 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5964 emitcode("setb","F0");
5968 emitcode ("mov","mb,#!constbyte",val & 0xff);
5969 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5971 lbl = newiTempLabel(NULL);
5972 emitcode ("mov","b,%s",aopGet(right,0,FALSE,FALSE,NULL));
5973 emitcode ("mov","a,%s",aopGet(right,1,FALSE,FALSE,NULL));
5974 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5975 emitcode ("xch", "a,b");
5976 emitcode ("cpl","a");
5977 emitcode ("add", "a,#1");
5978 emitcode ("xch", "a,b");
5979 emitcode ("cpl", "a"); // msb
5980 emitcode ("addc", "a,#0");
5981 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5982 emitcode ("setb","F0");
5984 emitcode ("mov","mb,b");
5985 emitcode ("mov","mb,a");
5988 emitcode ("mov","mb,%s",aopGet(right,0,FALSE,FALSE,NULL));
5989 emitcode ("mov","mb,%s",aopGet(right,1,FALSE,FALSE,NULL));
5992 /* wait for multiplication to finish */
5993 lbl = newiTempLabel(NULL);
5995 emitcode("mov","a,mcnt1");
5996 emitcode("anl","a,#!constbyte",0x80);
5997 emitcode("jnz","!tlabel",lbl->key+100);
5999 freeAsmop (left, NULL, ic, TRUE);
6000 freeAsmop (right, NULL, ic,TRUE);
6001 aopOp(result, ic, TRUE, FALSE);
6003 /* if unsigned then simple */
6005 aopPut(result,"ma",1);
6006 aopPut(result,"ma",0);
6008 emitcode("push","ma");
6010 /* negate result if needed */
6011 lbl = newiTempLabel(NULL);
6012 emitcode("jnb","F0,!tlabel",lbl->key+100);
6013 emitcode("cpl","a");
6014 emitcode("add","a,#1");
6016 aopPut(result,"a",0);
6017 emitcode("pop","acc");
6018 lbl = newiTempLabel(NULL);
6019 emitcode("jnb","F0,!tlabel",lbl->key+100);
6020 emitcode("cpl","a");
6021 emitcode("addc","a,#0");
6023 aopPut(result,"a",1);
6025 freeAsmop (result, NULL, ic, TRUE);
6026 /* restore EA bit in F1 */
6027 lbl = newiTempLabel(NULL);
6028 emitcode ("jnb","F1,!tlabel",lbl->key+100);
6029 emitcode ("setb","EA");
6034 /*-----------------------------------------------------------------*/
6035 /* genDiv - generates code for division */
6036 /*-----------------------------------------------------------------*/
6040 operand *left = IC_LEFT (ic);
6041 operand *right = IC_RIGHT (ic);
6042 operand *result = IC_RESULT (ic);
6044 D (emitcode (";", "genDiv"));
6046 /* assign the amsops */
6049 /* special cases first */
6051 if (AOP_TYPE (left) == AOP_CRY &&
6052 AOP_TYPE (right) == AOP_CRY)
6054 genDivbits (left, right, result, ic);
6058 /* if both are of size == 1 */
6059 if (AOP_SIZE (left) == 1 &&
6060 AOP_SIZE (right) == 1)
6062 genDivOneByte (left, right, result, ic);
6066 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
6067 /* use the ds390 ARITHMETIC accel UNIT */
6068 genDivTwoByte (left, right, result, ic);
6071 /* should have been converted to function call */
6074 freeAsmop (result, NULL, ic, TRUE);
6075 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6076 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6079 /*-----------------------------------------------------------------*/
6080 /* genModbits :- modulus of bits */
6081 /*-----------------------------------------------------------------*/
6083 genModbits (operand * left,
6091 D (emitcode (";", "genModbits"));
6095 /* the result must be bit */
6096 LOAD_AB_FOR_DIV (left, right, l);
6097 emitcode ("div", "ab");
6098 emitcode ("mov", "a,b");
6099 emitcode ("rrc", "a");
6100 aopOp(result, ic, TRUE, FALSE);
6104 aopPut (result, "c", 0);
6107 /*-----------------------------------------------------------------*/
6108 /* genModOneByte : 8 bit modulus */
6109 /*-----------------------------------------------------------------*/
6111 genModOneByte (operand * left,
6116 bool lUnsigned, rUnsigned, pushedB;
6117 bool runtimeSign, compiletimeSign;
6122 D (emitcode (";", "genModOneByte"));
6125 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
6126 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
6130 /* signed or unsigned */
6131 if (lUnsigned && rUnsigned)
6133 /* unsigned is easy */
6134 LOAD_AB_FOR_DIV (left, right, l);
6135 emitcode ("div", "ab");
6136 aopOp (result, ic, TRUE, FALSE);
6137 aopPut (result, "b", 0);
6139 for (size = AOP_SIZE (result) - 1; size--;)
6140 aopPut (result, zero, offset++);
6146 /* signed is a little bit more difficult */
6148 /* now sign adjust for both left & right */
6150 /* modulus: sign of the right operand has no influence on the result! */
6151 if (AOP_TYPE(right) == AOP_LIT)
6153 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
6155 if (!rUnsigned && val < 0)
6156 emitcode ("mov", "b,#0x%02x", -val);
6158 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
6160 else /* not literal */
6163 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
6166 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
6167 lbl = newiTempLabel (NULL);
6168 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
6169 emitcode ("cpl", "a"); /* 2's complement */
6170 emitcode ("inc", "a");
6172 emitcode ("mov", "b,a");
6176 /* let's see what's needed: */
6177 /* apply negative sign during runtime */
6178 runtimeSign = FALSE;
6179 /* negative sign from literals */
6180 compiletimeSign = FALSE;
6182 /* sign adjust left side */
6183 if (AOP_TYPE(left) == AOP_LIT)
6185 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
6187 if (!lUnsigned && val < 0)
6189 compiletimeSign = TRUE; /* set sign flag */
6190 emitcode ("mov", "a,#0x%02x", -val);
6193 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
6195 else /* ! literal */
6197 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
6202 emitcode ("clr", "F0"); /* clear sign flag */
6204 lbl = newiTempLabel (NULL);
6205 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
6206 emitcode ("setb", "F0"); /* set sign flag */
6207 emitcode ("cpl", "a"); /* 2's complement */
6208 emitcode ("inc", "a");
6213 /* now the modulus */
6214 emitcode ("nop", "; workaround for DS80C390 div bug.");
6215 emitcode ("div", "ab");
6217 if (runtimeSign || compiletimeSign)
6219 emitcode ("mov", "a,b");
6220 lbl = newiTempLabel (NULL);
6222 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
6223 emitcode ("cpl", "a"); /* lsb 2's complement */
6224 emitcode ("inc", "a");
6228 aopOp (result, ic, TRUE, FALSE);
6229 size = AOP_SIZE (result) - 1;
6233 /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
6234 then the result will be in b, a */
6235 emitcode ("mov", "b,a"); /* 1 */
6236 /* msb is 0x00 or 0xff depending on the sign */
6239 emitcode ("mov", "c,F0");
6240 emitcode ("subb", "a,acc");
6241 emitcode ("xch", "a,b"); /* 2 */
6243 aopPut (result, "b", offset++); /* write msb's */
6245 else /* compiletimeSign */
6247 aopPut (result, "#0xff", offset++); /* write msb's */
6249 aopPut (result, "a", 0); /* 3: write lsb */
6254 aopOp(result, ic, TRUE, FALSE);
6255 size = AOP_SIZE (result) - 1;
6257 aopPut (result, "b", 0);
6259 aopPut (result, zero, offset++);
6265 /*-----------------------------------------------------------------*/
6266 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
6267 /*-----------------------------------------------------------------*/
6268 static void genModTwoByte (operand *left, operand *right,
6269 operand *result, iCode *ic)
6271 sym_link *retype = getSpec(operandType(right));
6272 sym_link *letype = getSpec(operandType(left));
6273 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
6276 /* load up MA with left */
6277 /* save EA bit in F1 */
6278 lbl = newiTempLabel(NULL);
6279 emitcode ("setb","F1");
6280 emitcode ("jbc","EA,!tlabel",lbl->key+100);
6281 emitcode ("clr","F1");
6285 lbl = newiTempLabel(NULL);
6286 emitcode ("mov","b,%s",aopGet(left,0,FALSE,FALSE,NULL));
6287 emitcode ("mov","a,%s",aopGet(left,1,FALSE,FALSE,NULL));
6288 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
6289 emitcode ("xch", "a,b");
6290 emitcode ("cpl","a");
6291 emitcode ("add", "a,#1");
6292 emitcode ("xch", "a,b");
6293 emitcode ("cpl", "a"); // msb
6294 emitcode ("addc","a,#0");
6296 emitcode ("mov","ma,b");
6297 emitcode ("mov","ma,a");
6299 emitcode ("mov","ma,%s",aopGet(left,0,FALSE,FALSE,NULL));
6300 emitcode ("mov","ma,%s",aopGet(left,1,FALSE,FALSE,NULL));
6303 /* load up MB with right */
6305 if (AOP_TYPE(right) == AOP_LIT) {
6306 int val=(int) ulFromVal (AOP (right)->aopu.aop_lit);
6310 emitcode ("mov","mb,#!constbyte",val & 0xff);
6311 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
6313 lbl = newiTempLabel(NULL);
6314 emitcode ("mov","b,%s",aopGet(right,0,FALSE,FALSE,NULL));
6315 emitcode ("mov","a,%s",aopGet(right,1,FALSE,FALSE,NULL));
6316 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
6317 emitcode ("xch", "a,b");
6318 emitcode ("cpl","a");
6319 emitcode ("add", "a,#1");
6320 emitcode ("xch", "a,b");
6321 emitcode ("cpl", "a"); // msb
6322 emitcode ("addc", "a,#0");
6324 emitcode ("mov","mb,b");
6325 emitcode ("mov","mb,a");
6328 emitcode ("mov","mb,%s",aopGet(right,0,FALSE,FALSE,NULL));
6329 emitcode ("mov","mb,%s",aopGet(right,1,FALSE,FALSE,NULL));
6332 /* wait for multiplication to finish */
6333 lbl = newiTempLabel(NULL);
6335 emitcode("mov","a,mcnt1");
6336 emitcode("anl","a,#!constbyte",0x80);
6337 emitcode("jnz","!tlabel",lbl->key+100);
6339 freeAsmop (left, NULL, ic, TRUE);
6340 freeAsmop (right, NULL, ic,TRUE);
6341 aopOp(result, ic, TRUE, FALSE);
6343 aopPut(result,"mb",1);
6344 aopPut(result,"mb",0);
6345 freeAsmop (result, NULL, ic, TRUE);
6347 /* restore EA bit in F1 */
6348 lbl = newiTempLabel(NULL);
6349 emitcode ("jnb","F1,!tlabel",lbl->key+100);
6350 emitcode ("setb","EA");
6354 /*-----------------------------------------------------------------*/
6355 /* genMod - generates code for division */
6356 /*-----------------------------------------------------------------*/
6360 operand *left = IC_LEFT (ic);
6361 operand *right = IC_RIGHT (ic);
6362 operand *result = IC_RESULT (ic);
6364 D (emitcode (";", "genMod"));
6366 /* assign the asmops */
6369 /* special cases first */
6371 if (AOP_TYPE (left) == AOP_CRY &&
6372 AOP_TYPE (right) == AOP_CRY)
6374 genModbits (left, right, result, ic);
6378 /* if both are of size == 1 */
6379 if (AOP_SIZE (left) == 1 &&
6380 AOP_SIZE (right) == 1)
6382 genModOneByte (left, right, result, ic);
6386 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
6387 /* use the ds390 ARITHMETIC accel UNIT */
6388 genModTwoByte (left, right, result, ic);
6392 /* should have been converted to function call */
6396 freeAsmop (result, NULL, ic, TRUE);
6397 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6398 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6401 /*-----------------------------------------------------------------*/
6402 /* genIfxJump :- will create a jump depending on the ifx */
6403 /*-----------------------------------------------------------------*/
6405 genIfxJump (iCode * ic, char *jval, iCode *popIc)
6408 symbol *tlbl = newiTempLabel (NULL);
6411 /* if there is something to be popped then do it first */
6412 popForBranch (popIc, TRUE);
6414 D (emitcode (";", "genIfxJump"));
6416 /* if true label then we jump if condition
6420 jlbl = IC_TRUE (ic);
6421 inst = ((strcmp (jval, "a") == 0 ? "jz" :
6422 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
6426 /* false label is present */
6427 jlbl = IC_FALSE (ic);
6428 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
6429 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
6431 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
6432 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
6434 emitcode (inst, "!tlabel", tlbl->key + 100);
6435 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
6438 /* mark the icode as generated */
6442 /*-----------------------------------------------------------------*/
6443 /* genCmp :- greater or less than comparison */
6444 /*-----------------------------------------------------------------*/
6446 genCmp (operand * left, operand * right,
6447 iCode * ic, iCode * ifx, int sign)
6449 int size, offset = 0;
6450 unsigned long lit = 0L;
6453 D (emitcode (";", "genCmp"));
6455 result = IC_RESULT (ic);
6457 /* if left & right are bit variables */
6458 if (AOP_TYPE (left) == AOP_CRY &&
6459 AOP_TYPE (right) == AOP_CRY)
6461 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6462 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6466 /* subtract right from left if at the
6467 end the carry flag is set then we know that
6468 left is greater than right */
6469 size = max (AOP_SIZE (left), AOP_SIZE (right));
6471 /* if unsigned char cmp with lit, do cjne left,#right,zz */
6472 if ((size == 1) && !sign &&
6473 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
6475 symbol *lbl = newiTempLabel (NULL);
6476 emitcode ("cjne", "%s,%s,!tlabel",
6477 aopGet (left, offset, FALSE, FALSE, NULL),
6478 aopGet (right, offset, FALSE, FALSE, NULL),
6484 if (AOP_TYPE (right) == AOP_LIT)
6486 lit = ulFromVal (AOP (right)->aopu.aop_lit);
6487 /* optimize if(x < 0) or if(x >= 0) */
6496 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
6498 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6499 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6501 aopOp (result, ic, FALSE, FALSE);
6503 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
6505 freeAsmop (result, NULL, ic, TRUE);
6506 genIfxJump (ifx, "acc.7", ic->next);
6511 emitcode ("rlc", "a");
6513 goto release_freedLR;
6521 // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
6522 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
6523 // emitcode (";", "genCmp #2");
6524 if (sign && (size == 0))
6526 // emitcode (";", "genCmp #3");
6527 emitcode ("xrl", "a,#!constbyte",0x80);
6528 if (AOP_TYPE (right) == AOP_LIT)
6530 unsigned long lit = ulFromVal (AOP (right)->aopu.aop_lit);
6531 // emitcode (";", "genCmp #3.1");
6532 emitcode ("subb", "a,#!constbyte",
6533 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
6537 // emitcode (";", "genCmp #3.2");
6539 MOVB (aopGet (right, offset++, FALSE, FALSE, "b"));
6540 saveAccWarn = DEFAULT_ACC_WARNING;
6541 emitcode ("xrl", "b,#!constbyte",0x80);
6542 emitcode ("subb", "a,b");
6549 // emitcode (";", "genCmp #4");
6551 s = aopGet (right, offset++, FALSE, FALSE, "b");
6552 saveAccWarn = DEFAULT_ACC_WARNING;
6554 emitcode ("subb", "a,%s", s);
6561 /* Don't need the left & right operands any more; do need the result. */
6562 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6563 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6565 aopOp (result, ic, FALSE, FALSE);
6569 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6575 /* if the result is used in the next
6576 ifx conditional branch then generate
6577 code a little differently */
6580 genIfxJump (ifx, "c", ic->next);
6586 /* leave the result in acc */
6588 freeAsmop (result, NULL, ic, TRUE);
6591 /*-----------------------------------------------------------------*/
6592 /* genCmpGt :- greater than comparison */
6593 /*-----------------------------------------------------------------*/
6595 genCmpGt (iCode * ic, iCode * ifx)
6597 operand *left, *right;
6598 sym_link *letype, *retype;
6601 D (emitcode (";", "genCmpGt"));
6603 left = IC_LEFT (ic);
6604 right = IC_RIGHT (ic);
6606 letype = getSpec (operandType (left));
6607 retype = getSpec (operandType (right));
6608 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6610 /* assign the left & right amsops */
6613 genCmp (right, left, ic, ifx, sign);
6616 /*-----------------------------------------------------------------*/
6617 /* genCmpLt - less than comparisons */
6618 /*-----------------------------------------------------------------*/
6620 genCmpLt (iCode * ic, iCode * ifx)
6622 operand *left, *right;
6623 sym_link *letype, *retype;
6626 D (emitcode (";", "genCmpLt"));
6628 left = IC_LEFT (ic);
6629 right = IC_RIGHT (ic);
6631 letype = getSpec (operandType (left));
6632 retype = getSpec (operandType (right));
6633 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6635 /* assign the left & right amsops */
6638 genCmp (left, right, ic, ifx, sign);
6641 /*-----------------------------------------------------------------*/
6642 /* gencjneshort - compare and jump if not equal */
6643 /*-----------------------------------------------------------------*/
6645 gencjneshort (operand * left, operand * right, symbol * lbl)
6647 int size = max (AOP_SIZE (left), AOP_SIZE (right));
6649 unsigned long lit = 0L;
6651 D (emitcode (";", "gencjneshort"));
6653 /* if the left side is a literal or
6654 if the right is in a pointer register and left
6656 if ((AOP_TYPE (left) == AOP_LIT) ||
6657 (AOP_TYPE (left) == AOP_IMMD) ||
6658 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6665 if (AOP_TYPE (right) == AOP_LIT)
6666 lit = ulFromVal (AOP (right)->aopu.aop_lit);
6668 if (opIsGptr (left) || opIsGptr (right))
6670 /* We are comparing a generic pointer to something.
6671 * Exclude the generic type byte from the comparison.
6674 D (emitcode (";", "cjneshort: generic ptr special case."););
6678 /* if the right side is a literal then anything goes */
6679 if (AOP_TYPE (right) == AOP_LIT &&
6680 AOP_TYPE (left) != AOP_DIR)
6684 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
6685 emitcode ("cjne", "a,%s,!tlabel",
6686 aopGet (right, offset, FALSE, FALSE, NULL),
6692 /* if the right side is in a register or in direct space or
6693 if the left is a pointer register & right is not */
6694 else if (AOP_TYPE (right) == AOP_REG ||
6695 AOP_TYPE (right) == AOP_DIR ||
6696 AOP_TYPE (right) == AOP_LIT ||
6697 AOP_TYPE (right) == AOP_IMMD ||
6698 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6699 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6703 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
6704 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6705 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6706 emitcode ("jnz", "!tlabel", lbl->key + 100);
6708 emitcode ("cjne", "a,%s,!tlabel",
6709 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG),
6716 /* right is a pointer reg need both a & b */
6719 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
6720 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
6721 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
6727 /*-----------------------------------------------------------------*/
6728 /* gencjne - compare and jump if not equal */
6729 /*-----------------------------------------------------------------*/
6731 gencjne (operand * left, operand * right, symbol * lbl)
6733 symbol *tlbl = newiTempLabel (NULL);
6735 D (emitcode (";", "gencjne"));
6737 gencjneshort (left, right, lbl);
6739 emitcode ("mov", "a,%s", one);
6740 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
6742 emitcode ("clr", "a");
6746 /*-----------------------------------------------------------------*/
6747 /* genCmpEq - generates code for equal to */
6748 /*-----------------------------------------------------------------*/
6750 genCmpEq (iCode * ic, iCode * ifx)
6752 operand *left, *right, *result;
6753 iCode * popIc = ic->next;
6755 D (emitcode (";", "genCmpEq"));
6758 AOP_SET_LOCALS (ic);
6760 /* if literal, literal on the right or
6761 if the right is in a pointer register and left
6763 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6764 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6766 operand *t = IC_RIGHT (ic);
6767 IC_RIGHT (ic) = IC_LEFT (ic);
6771 if (ifx && /* !AOP_SIZE(result) */
6772 OP_SYMBOL (result) &&
6773 OP_SYMBOL (result)->regType == REG_CND)
6776 /* if they are both bit variables */
6777 if (AOP_TYPE (left) == AOP_CRY &&
6778 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6780 if (AOP_TYPE (right) == AOP_LIT)
6782 unsigned long lit = ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6785 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6786 emitcode ("cpl", "c");
6790 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6794 emitcode ("clr", "c");
6796 /* AOP_TYPE(right) == AOP_CRY */
6800 symbol *lbl = newiTempLabel (NULL);
6801 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6802 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6803 emitcode ("cpl", "c");
6806 /* if true label then we jump if condition
6808 tlbl = newiTempLabel (NULL);
6811 emitcode ("jnc", "!tlabel", tlbl->key + 100);
6812 popForBranch (popIc, FALSE);
6813 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6817 emitcode ("jc", "!tlabel", tlbl->key + 100);
6818 popForBranch (popIc, FALSE);
6819 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6825 tlbl = newiTempLabel (NULL);
6826 gencjneshort (left, right, tlbl);
6829 popForBranch (popIc, FALSE);
6830 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6835 symbol *lbl = newiTempLabel (NULL);
6836 emitcode ("sjmp", "!tlabel", lbl->key + 100);
6838 popForBranch (popIc, FALSE);
6839 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6843 /* mark the icode as generated */
6846 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6847 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6851 /* if they are both bit variables */
6852 if (AOP_TYPE (left) == AOP_CRY &&
6853 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6855 if (AOP_TYPE (right) == AOP_LIT)
6857 unsigned long lit = ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6860 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6861 emitcode ("cpl", "c");
6865 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6869 emitcode ("clr", "c");
6871 /* AOP_TYPE(right) == AOP_CRY */
6875 symbol *lbl = newiTempLabel (NULL);
6876 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6877 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6878 emitcode ("cpl", "c");
6882 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6883 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6885 aopOp (result, ic, TRUE, FALSE);
6888 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6895 genIfxJump (ifx, "c", popIc);
6898 /* if the result is used in an arithmetic operation
6899 then put the result in place */
6904 gencjne (left, right, newiTempLabel (NULL));
6906 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6907 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6909 aopOp (result, ic, TRUE, FALSE);
6911 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6913 aopPut (result, "a", 0);
6918 genIfxJump (ifx, "a", popIc);
6921 /* if the result is used in an arithmetic operation
6922 then put the result in place */
6923 if (AOP_TYPE (result) != AOP_CRY)
6925 /* leave the result in acc */
6929 freeAsmop (result, NULL, ic, TRUE);
6932 /*-----------------------------------------------------------------*/
6933 /* ifxForOp - returns the icode containing the ifx for operand */
6934 /*-----------------------------------------------------------------*/
6936 ifxForOp (operand * op, iCode * ic)
6940 /* if true symbol then needs to be assigned */
6941 if (IS_TRUE_SYMOP (op))
6944 /* if this has register type condition and
6945 while skipping ipop's (see bug 1509084),
6946 the next instruction is ifx with the same operand
6947 and live to of the operand is upto the ifx only then */
6948 for (ifxIc = ic->next; ifxIc && ifxIc->op == IPOP; ifxIc = ifxIc->next);
6949 if (ifxIc && ifxIc->op == IFX &&
6950 IC_COND (ifxIc)->key == op->key &&
6951 OP_SYMBOL (op)->liveTo <= ifxIc->seq)
6957 /*-----------------------------------------------------------------*/
6958 /* hasInc - operand is incremented before any other use */
6959 /*-----------------------------------------------------------------*/
6961 hasInc (operand *op, iCode *ic, int osize)
6963 sym_link *type = operandType(op);
6964 sym_link *retype = getSpec (type);
6965 iCode *lic = ic->next;
6968 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6969 if (!IS_SYMOP(op)) return NULL;
6971 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6972 if (IS_AGGREGATE(type->next)) return NULL;
6973 if (osize != (isize = getSize(type->next))) return NULL;
6977 /* if operand of the form op = op + <sizeof *op> */
6978 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6979 isOperandEqual(IC_RESULT(lic),op) &&
6980 isOperandLiteral(IC_RIGHT(lic)) &&
6981 operandLitValue(IC_RIGHT(lic)) == isize)
6985 /* if the operand used or deffed */
6986 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key)
6990 /* if GOTO or IFX */
6991 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6997 /*-----------------------------------------------------------------*/
6998 /* genAndOp - for && operation */
6999 /*-----------------------------------------------------------------*/
7001 genAndOp (iCode * ic)
7003 operand *left, *right, *result;
7006 D (emitcode (";", "genAndOp"));
7008 /* note here that && operations that are in an
7009 if statement are taken away by backPatchLabels
7010 only those used in arthmetic operations remain */
7012 AOP_SET_LOCALS (ic);
7014 /* if both are bit variables */
7015 if (AOP_TYPE (left) == AOP_CRY &&
7016 AOP_TYPE (right) == AOP_CRY)
7018 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7019 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
7020 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7021 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7023 aopOp (result,ic,FALSE, FALSE);
7028 tlbl = newiTempLabel (NULL);
7030 emitcode ("jz", "!tlabel", tlbl->key + 100);
7033 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7034 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7036 aopOp (result,ic,FALSE, FALSE);
7040 freeAsmop (result, NULL, ic, TRUE);
7044 /*-----------------------------------------------------------------*/
7045 /* genOrOp - for || operation */
7046 /*-----------------------------------------------------------------*/
7048 genOrOp (iCode * ic)
7050 operand *left, *right, *result;
7053 D (emitcode (";", "genOrOp"));
7055 /* note here that || operations that are in an
7056 if statement are taken away by backPatchLabels
7057 only those used in arthmetic operations remain */
7059 AOP_SET_LOCALS (ic);
7061 /* if both are bit variables */
7062 if (AOP_TYPE (left) == AOP_CRY &&
7063 AOP_TYPE (right) == AOP_CRY)
7065 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7066 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
7067 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7068 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7070 aopOp (result,ic,FALSE, FALSE);
7076 tlbl = newiTempLabel (NULL);
7078 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7081 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7082 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7084 aopOp (result,ic,FALSE, FALSE);
7089 freeAsmop (result, NULL, ic, TRUE);
7092 /*-----------------------------------------------------------------*/
7093 /* isLiteralBit - test if lit == 2^n */
7094 /*-----------------------------------------------------------------*/
7096 isLiteralBit (unsigned long lit)
7098 unsigned long pw[32] =
7099 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
7100 0x100L, 0x200L, 0x400L, 0x800L,
7101 0x1000L, 0x2000L, 0x4000L, 0x8000L,
7102 0x10000L, 0x20000L, 0x40000L, 0x80000L,
7103 0x100000L, 0x200000L, 0x400000L, 0x800000L,
7104 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
7105 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
7108 for (idx = 0; idx < 32; idx++)
7114 /*-----------------------------------------------------------------*/
7115 /* continueIfTrue - */
7116 /*-----------------------------------------------------------------*/
7118 continueIfTrue (iCode * ic)
7121 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
7125 /*-----------------------------------------------------------------*/
7127 /*-----------------------------------------------------------------*/
7129 jumpIfTrue (iCode * ic)
7132 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
7136 /*-----------------------------------------------------------------*/
7137 /* jmpTrueOrFalse - */
7138 /*-----------------------------------------------------------------*/
7140 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
7142 // ugly but optimized by peephole
7145 symbol *nlbl = newiTempLabel (NULL);
7146 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
7148 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
7153 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
7159 // Generate code to perform a bit-wise logic operation
7160 // on two operands in far space (assumed to already have been
7161 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
7162 // in far space. This requires pushing the result on the stack
7163 // then popping it into the result.
7165 genFarFarLogicOp(iCode *ic, char *logicOp)
7167 int size, resultSize, compSize;
7171 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
7172 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
7173 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
7175 _startLazyDPSEvaluation();
7176 for (size = compSize; (size--); offset++)
7178 MOVA (aopGet (IC_LEFT(ic), offset, FALSE, FALSE, NULL));
7179 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
7180 MOVA (aopGet (IC_RIGHT(ic), offset, FALSE, FALSE, NULL));
7182 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
7183 emitcode ("push", "acc");
7185 _endLazyDPSEvaluation();
7187 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7188 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7189 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
7191 resultSize = AOP_SIZE(IC_RESULT(ic));
7193 ADJUST_PUSHED_RESULT(compSize, resultSize);
7195 _startLazyDPSEvaluation();
7198 emitcode ("pop", "acc");
7199 aopPut (IC_RESULT (ic), "a", compSize);
7201 _endLazyDPSEvaluation();
7202 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
7206 /*-----------------------------------------------------------------*/
7207 /* genAnd - code for and */
7208 /*-----------------------------------------------------------------*/
7210 genAnd (iCode * ic, iCode * ifx)
7212 operand *left, *right, *result;
7213 int size, offset = 0;
7214 unsigned long lit = 0L;
7219 D (emitcode (";", "genAnd"));
7221 AOP_OP_3_NOFATAL (ic, pushResult);
7222 AOP_SET_LOCALS (ic);
7226 genFarFarLogicOp(ic, "anl");
7231 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
7233 AOP_TYPE (left), AOP_TYPE (right));
7234 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
7236 AOP_SIZE (left), AOP_SIZE (right));
7239 /* if left is a literal & right is not then exchange them */
7240 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7241 #ifdef LOGIC_OPS_BROKEN
7242 || AOP_NEEDSACC (left)
7246 operand *tmp = right;
7251 /* if result = right then exchange left and right */
7252 if (sameRegs (AOP (result), AOP (right)))
7254 operand *tmp = right;
7259 /* if right is bit then exchange them */
7260 if (AOP_TYPE (right) == AOP_CRY &&
7261 AOP_TYPE (left) != AOP_CRY)
7263 operand *tmp = right;
7267 if (AOP_TYPE (right) == AOP_LIT)
7268 lit = ulFromVal (AOP (right)->aopu.aop_lit);
7270 size = AOP_SIZE (result);
7273 // result = bit & yy;
7274 if (AOP_TYPE (left) == AOP_CRY)
7276 // c = bit & literal;
7277 if (AOP_TYPE (right) == AOP_LIT)
7281 if (size && sameRegs (AOP (result), AOP (left)))
7284 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7289 if (size && (AOP_TYPE (result) == AOP_CRY))
7291 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
7294 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7299 emitcode ("clr", "c");
7304 if (AOP_TYPE (right) == AOP_CRY)
7307 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7308 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
7313 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
7315 emitcode ("rrc", "a");
7316 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
7324 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7325 genIfxJump (ifx, "c", ic->next);
7329 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7330 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7331 if ((AOP_TYPE (right) == AOP_LIT) &&
7332 (AOP_TYPE (result) == AOP_CRY) &&
7333 (AOP_TYPE (left) != AOP_CRY))
7335 int posbit = isLiteralBit (lit);
7340 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE, NULL));
7344 switch (posbit & 0x07)
7346 case 0: emitcode ("rrc", "a");
7348 case 7: emitcode ("rlc", "a");
7350 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
7359 SNPRINTF (buffer, sizeof(buffer),
7360 "acc.%d", posbit & 0x07);
7361 genIfxJump (ifx, buffer, ic->next);
7365 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
7372 symbol *tlbl = newiTempLabel (NULL);
7373 int sizel = AOP_SIZE (left);
7375 emitcode ("setb", "c");
7378 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
7380 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7382 if ((posbit = isLiteralBit (bytelit)) != 0)
7383 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
7386 if (bytelit != 0x0FFL)
7387 emitcode ("anl", "a,%s",
7388 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG));
7389 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7394 // bit = left & literal
7397 emitcode ("clr", "c");
7400 // if(left & literal)
7404 jmpTrueOrFalse (ifx, tlbl);
7414 /* if left is same as result */
7415 if (sameRegs (AOP (result), AOP (left)))
7417 for (; size--; offset++)
7419 if (AOP_TYPE (right) == AOP_LIT)
7421 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7422 if (bytelit == 0x0FF)
7424 /* dummy read of volatile operand */
7425 if (isOperandVolatile (left, FALSE))
7426 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7430 else if (bytelit == 0)
7432 aopPut (result, zero, offset);
7434 else if (IS_AOP_PREG (result))
7436 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7437 emitcode ("anl", "a,%s",
7438 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG));
7439 aopPut (result, "a", offset);
7442 emitcode ("anl", "%s,%s",
7443 aopGet (left, offset, FALSE, TRUE, NULL),
7444 aopGet (right, offset, FALSE, FALSE, NULL));
7448 if (AOP_TYPE (left) == AOP_ACC)
7451 emitcode("mov", "a,b");
7452 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7454 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7456 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
7457 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7458 emitcode ("anl", "a,b");
7459 aopPut (result, "a", offset);
7461 else if (aopGetUsesAcc (left, offset))
7463 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7464 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7465 aopPut (result, "a", offset);
7469 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7470 if (IS_AOP_PREG (result))
7472 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7473 aopPut (result, "a", offset);
7476 emitcode ("anl", "%s,a", aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7483 // left & result in different registers
7484 if (AOP_TYPE (result) == AOP_CRY)
7487 // if(size), result in bit
7488 // if(!size && ifx), conditional oper: if(left & right)
7489 symbol *tlbl = newiTempLabel (NULL);
7490 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
7492 emitcode ("setb", "c");
7495 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7496 && AOP_TYPE(left)==AOP_ACC)
7499 emitcode("mov", "a,b");
7500 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, NULL));
7502 else if (AOP_TYPE(left)==AOP_ACC)
7506 bool pushedB = pushB ();
7507 emitcode("mov", "b,a");
7508 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7509 emitcode("anl", "a,b");
7514 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7515 emitcode("anl", "a,b");
7518 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7520 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE, NULL));
7521 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7522 emitcode ("anl", "a,b");
7524 else if (aopGetUsesAcc (left, offset))
7526 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7527 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7531 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7532 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE, DP2_RESULT_REG));
7535 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7545 jmpTrueOrFalse (ifx, tlbl);
7551 for (; (size--); offset++)
7554 // result = left & right
7555 if (AOP_TYPE (right) == AOP_LIT)
7557 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7558 if (bytelit == 0x0FF)
7561 aopGet (left, offset, FALSE, FALSE, NULL),
7565 else if (bytelit == 0)
7567 /* dummy read of volatile operand */
7568 if (isOperandVolatile (left, FALSE))
7569 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7570 aopPut (result, zero, offset);
7573 else if (AOP_TYPE (left) == AOP_ACC)
7577 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, NULL));
7578 aopPut (result, "a", offset);
7583 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE, NULL));
7584 aopPut (result, "b", offset);
7589 // faster than result <- left, anl result,right
7590 // and better if result is SFR
7591 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7592 && AOP_TYPE(left)==AOP_ACC)
7595 emitcode("mov", "a,b");
7596 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, NULL));
7598 else if (AOP_TYPE(left)==AOP_ACC)
7602 bool pushedB = pushB ();
7603 emitcode("mov", "b,a");
7604 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7605 emitcode("anl", "a,b");
7610 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7611 emitcode("anl", "a,b");
7614 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7616 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
7617 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7618 emitcode ("anl", "a,b");
7620 else if (aopGetUsesAcc (left, offset))
7622 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7623 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7627 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7628 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE, DP2_RESULT_REG));
7630 aopPut (result, "a", offset);
7636 freeAsmop (result, NULL, ic, TRUE);
7637 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7638 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7641 /*-----------------------------------------------------------------*/
7642 /* genOr - code for or */
7643 /*-----------------------------------------------------------------*/
7645 genOr (iCode * ic, iCode * ifx)
7647 operand *left, *right, *result;
7648 int size, offset = 0;
7649 unsigned long lit = 0L;
7653 D (emitcode (";", "genOr"));
7655 AOP_OP_3_NOFATAL (ic, pushResult);
7656 AOP_SET_LOCALS (ic);
7660 genFarFarLogicOp(ic, "orl");
7666 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
7668 AOP_TYPE (left), AOP_TYPE (right));
7669 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
7671 AOP_SIZE (left), AOP_SIZE (right));
7674 /* if left is a literal & right is not then exchange them */
7675 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7676 #ifdef LOGIC_OPS_BROKEN
7677 || AOP_NEEDSACC (left) // I think this is a net loss now.
7681 operand *tmp = right;
7686 /* if result = right then exchange them */
7687 if (sameRegs (AOP (result), AOP (right)))
7689 operand *tmp = right;
7694 /* if right is bit then exchange them */
7695 if (AOP_TYPE (right) == AOP_CRY &&
7696 AOP_TYPE (left) != AOP_CRY)
7698 operand *tmp = right;
7702 if (AOP_TYPE (right) == AOP_LIT)
7703 lit = ulFromVal (AOP (right)->aopu.aop_lit);
7705 size = AOP_SIZE (result);
7709 if (AOP_TYPE (left) == AOP_CRY)
7711 if (AOP_TYPE (right) == AOP_LIT)
7713 // c = bit | literal;
7716 // lit != 0 => result = 1
7717 if (AOP_TYPE (result) == AOP_CRY)
7720 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7722 continueIfTrue (ifx);
7725 emitcode ("setb", "c");
7729 // lit == 0 => result = left
7730 if (size && sameRegs (AOP (result), AOP (left)))
7732 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7737 if (AOP_TYPE (right) == AOP_CRY)
7740 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7741 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7746 symbol *tlbl = newiTempLabel (NULL);
7747 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
7748 emitcode ("setb", "c");
7749 emitcode ("jb", "%s,!tlabel",
7750 AOP (left)->aopu.aop_dir, tlbl->key + 100);
7752 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7753 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7755 jmpTrueOrFalse (ifx, tlbl);
7770 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7771 genIfxJump (ifx, "c", ic->next);
7775 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7776 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7777 if ((AOP_TYPE (right) == AOP_LIT) &&
7778 (AOP_TYPE (result) == AOP_CRY) &&
7779 (AOP_TYPE (left) != AOP_CRY))
7785 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7787 continueIfTrue (ifx);
7792 // lit = 0, result = boolean(left)
7794 emitcode ("setb", "c");
7798 symbol *tlbl = newiTempLabel (NULL);
7799 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7805 genIfxJump (ifx, "a", ic->next);
7813 /* if left is same as result */
7814 if (sameRegs (AOP (result), AOP (left)))
7816 for (; size--; offset++)
7818 if (AOP_TYPE (right) == AOP_LIT)
7820 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7823 /* dummy read of volatile operand */
7824 if (isOperandVolatile (left, FALSE))
7825 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7829 else if (bytelit == 0x0FF)
7831 aopPut (result, "#0xFF", offset);
7833 else if (IS_AOP_PREG (left))
7835 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7836 emitcode ("orl", "a,%s",
7837 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7838 aopPut (result, "a", offset);
7842 emitcode ("orl", "%s,%s",
7843 aopGet (left, offset, FALSE, TRUE, NULL),
7844 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7849 if (AOP_TYPE (left) == AOP_ACC)
7852 emitcode("mov", "a,b");
7853 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7855 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7857 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE, NULL));
7858 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7859 emitcode ("orl", "a,b");
7860 aopPut (result, "a", offset);
7862 else if (aopGetUsesAcc (left, offset))
7864 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7865 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7866 aopPut (result, "a", offset);
7870 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7871 if (IS_AOP_PREG (left))
7873 emitcode ("orl", "a,%s",
7874 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7875 aopPut (result, "a", offset);
7879 emitcode ("orl", "%s,a",
7880 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7888 // left & result in different registers
7889 if (AOP_TYPE (result) == AOP_CRY)
7892 // if(size), result in bit
7893 // if(!size && ifx), conditional oper: if(left | right)
7894 symbol *tlbl = newiTempLabel (NULL);
7895 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7897 emitcode ("setb", "c");
7900 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7901 && AOP_TYPE(left)==AOP_ACC)
7904 emitcode("mov", "a,b");
7905 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7907 else if (AOP_TYPE(left)==AOP_ACC)
7911 bool pushedB = pushB ();
7912 emitcode("mov", "b,a");
7913 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7914 emitcode("orl", "a,b");
7919 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7920 emitcode("orl", "a,b");
7923 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7925 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
7926 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7927 emitcode ("orl", "a,b");
7929 else if (aopGetUsesAcc (left, offset))
7931 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7932 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7936 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7937 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE, DP2_RESULT_REG));
7940 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7950 jmpTrueOrFalse (ifx, tlbl);
7956 _startLazyDPSEvaluation();
7957 for (; (size--); offset++)
7960 // result = left | right
7961 if (AOP_TYPE (right) == AOP_LIT)
7963 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7967 aopGet (left, offset, FALSE, FALSE, NULL),
7971 else if (bytelit == 0x0FF)
7973 /* dummy read of volatile operand */
7974 if (isOperandVolatile (left, FALSE))
7975 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7976 aopPut (result, "#0xFF", offset);
7980 // faster than result <- left, orl result,right
7981 // and better if result is SFR
7982 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7983 && AOP_TYPE(left)==AOP_ACC)
7986 emitcode("mov", "a,b");
7987 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7989 else if (AOP_TYPE(left)==AOP_ACC)
7993 bool pushedB = pushB ();
7994 emitcode("mov", "b,a");
7995 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7996 emitcode("orl", "a,b");
8001 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8002 emitcode("orl", "a,b");
8005 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
8007 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
8008 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8009 emitcode ("orl", "a,b");
8011 else if (aopGetUsesAcc (left, offset))
8013 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8014 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8018 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
8019 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE, DP2_RESULT_REG));
8021 aopPut (result, "a", offset);
8023 _endLazyDPSEvaluation();
8028 freeAsmop (result, NULL, ic, TRUE);
8029 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
8030 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
8033 /*-----------------------------------------------------------------*/
8034 /* genXor - code for xclusive or */
8035 /*-----------------------------------------------------------------*/
8037 genXor (iCode * ic, iCode * ifx)
8039 operand *left, *right, *result;
8040 int size, offset = 0;
8041 unsigned long lit = 0L;
8045 D (emitcode (";", "genXor"));
8047 AOP_OP_3_NOFATAL (ic, pushResult);
8048 AOP_SET_LOCALS (ic);
8052 genFarFarLogicOp(ic, "xrl");
8057 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
8059 AOP_TYPE (left), AOP_TYPE (right));
8060 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
8062 AOP_SIZE (left), AOP_SIZE (right));
8065 /* if left is a literal & right is not ||
8066 if left needs acc & right does not */
8067 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
8068 #ifdef LOGIC_OPS_BROKEN
8069 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
8073 operand *tmp = right;
8078 /* if result = right then exchange them */
8079 if (sameRegs (AOP (result), AOP (right)))
8081 operand *tmp = right;
8086 /* if right is bit then exchange them */
8087 if (AOP_TYPE (right) == AOP_CRY &&
8088 AOP_TYPE (left) != AOP_CRY)
8090 operand *tmp = right;
8095 if (AOP_TYPE (right) == AOP_LIT)
8096 lit = ulFromVal (AOP (right)->aopu.aop_lit);
8098 size = AOP_SIZE (result);
8102 if (AOP_TYPE (left) == AOP_CRY)
8104 if (AOP_TYPE (right) == AOP_LIT)
8106 // c = bit & literal;
8109 // lit>>1 != 0 => result = 1
8110 if (AOP_TYPE (result) == AOP_CRY)
8113 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
8115 continueIfTrue (ifx);
8118 emitcode ("setb", "c");
8125 // lit == 0, result = left
8126 if (size && sameRegs (AOP (result), AOP (left)))
8128 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
8132 // lit == 1, result = not(left)
8133 if (size && sameRegs (AOP (result), AOP (left)))
8135 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
8140 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
8141 emitcode ("cpl", "c");
8149 symbol *tlbl = newiTempLabel (NULL);
8150 if (AOP_TYPE (right) == AOP_CRY)
8153 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8157 int sizer = AOP_SIZE (right);
8159 // if val>>1 != 0, result = 1
8160 emitcode ("setb", "c");
8163 MOVA (aopGet (right, sizer - 1, FALSE, FALSE, NULL));
8165 // test the msb of the lsb
8166 emitcode ("anl", "a,#!constbyte",0xfe);
8167 emitcode ("jnz", "!tlabel", tlbl->key + 100);
8171 emitcode ("rrc", "a");
8173 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
8174 emitcode ("cpl", "c");
8182 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
8183 genIfxJump (ifx, "c", ic->next);
8187 /* if left is same as result */
8188 if (sameRegs (AOP (result), AOP (left)))
8190 for (; size--; offset++)
8192 if (AOP_TYPE (right) == AOP_LIT)
8194 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
8197 /* dummy read of volatile operand */
8198 if (isOperandVolatile (left, FALSE))
8199 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8203 else if (IS_AOP_PREG (left))
8205 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8206 emitcode ("xrl", "a,%s",
8207 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG));
8208 aopPut (result, "a", offset);
8212 emitcode ("xrl", "%s,%s",
8213 aopGet (left, offset, FALSE, TRUE, NULL),
8214 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8219 if (AOP_TYPE (left) == AOP_ACC)
8222 emitcode("mov", "a,b");
8223 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8225 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
8227 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
8228 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8229 emitcode ("xrl", "a,b");
8230 aopPut (result, "a", offset);
8232 else if (aopGetUsesAcc (left, offset))
8234 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8235 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8236 aopPut (result, "a", offset);
8240 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
8241 if (IS_AOP_PREG (left))
8243 emitcode ("xrl", "a,%s",
8244 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
8245 aopPut (result, "a", offset);
8248 emitcode ("xrl", "%s,a",
8249 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
8256 // left & result in different registers
8257 if (AOP_TYPE (result) == AOP_CRY)
8260 // if(size), result in bit
8261 // if(!size && ifx), conditional oper: if(left ^ right)
8262 symbol *tlbl = newiTempLabel (NULL);
8263 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
8266 emitcode ("setb", "c");
8269 if ((AOP_TYPE (right) == AOP_LIT) &&
8270 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
8272 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8274 else if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
8275 && AOP_TYPE(left)==AOP_ACC)
8278 emitcode("mov", "a,b");
8279 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8281 else if (AOP_TYPE(left)==AOP_ACC)
8285 bool pushedB = pushB ();
8286 emitcode("mov", "b,a");
8287 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8288 emitcode("xrl", "a,b");
8293 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8294 emitcode("xrl", "a,b");
8297 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
8299 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
8300 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8301 emitcode ("xrl", "a,b");
8303 else if (aopGetUsesAcc (left, offset))
8305 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8306 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8310 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
8311 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
8314 emitcode ("jnz", "!tlabel", tlbl->key + 100);
8324 jmpTrueOrFalse (ifx, tlbl);
8328 for (; (size--); offset++)
8331 // result = left ^ right
8332 if (AOP_TYPE (right) == AOP_LIT)
8334 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
8338 aopGet (left, offset, FALSE, FALSE, NULL),
8342 D (emitcode (";", "better literal XOR."));
8343 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8344 emitcode ("xrl", "a, %s",
8345 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8349 // faster than result <- left, anl result,right
8350 // and better if result is SFR
8351 if (AOP_TYPE (left) == AOP_ACC)
8353 emitcode ("xrl", "a,%s",
8354 aopGet (right, offset,
8355 FALSE, FALSE, DP2_RESULT_REG));
8359 char *rOp = aopGet (right, offset, FALSE, FALSE, NULL);
8360 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
8362 emitcode("mov", "b,a");
8366 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8367 emitcode ("xrl", "a,%s", rOp);
8370 aopPut (result, "a", offset);
8376 freeAsmop (result, NULL, ic, TRUE);
8377 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
8378 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
8381 /*-----------------------------------------------------------------*/
8382 /* genInline - write the inline code out */
8383 /*-----------------------------------------------------------------*/
8385 genInline (iCode * ic)
8387 char *buffer, *bp, *bp1;
8388 bool inComment = FALSE;
8390 D (emitcode (";", "genInline"));
8392 _G.inLine += (!options.asmpeep);
8394 buffer = bp = bp1 = Safe_strdup (IC_INLINE (ic));
8396 /* emit each line as a code */
8414 /* Add \n for labels, not dirs such as c:\mydir */
8415 if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
8433 _G.inLine -= (!options.asmpeep);
8436 /*-----------------------------------------------------------------*/
8437 /* genRRC - rotate right with carry */
8438 /*-----------------------------------------------------------------*/
8442 operand *left, *result;
8446 D (emitcode (";", "genRRC"));
8448 /* rotate right with carry */
8449 left = IC_LEFT (ic);
8450 result = IC_RESULT (ic);
8451 aopOp (left, ic, FALSE, FALSE);
8452 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8454 /* move it to the result */
8455 size = AOP_SIZE (result);
8459 _startLazyDPSEvaluation ();
8462 l = aopGet (left, offset, FALSE, FALSE, NULL);
8464 emitcode ("rrc", "a");
8465 if (AOP_SIZE (result) > 1)
8466 aopPut (result, "a", offset--);
8468 _endLazyDPSEvaluation ();
8470 /* now we need to put the carry into the
8471 highest order byte of the result */
8472 if (AOP_SIZE (result) > 1)
8474 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE, NULL);
8477 emitcode ("mov", "acc.7,c");
8478 aopPut (result, "a", AOP_SIZE (result) - 1);
8479 freeAsmop (result, NULL, ic, TRUE);
8480 freeAsmop (left, NULL, ic, TRUE);
8483 /*-----------------------------------------------------------------*/
8484 /* genRLC - generate code for rotate left with carry */
8485 /*-----------------------------------------------------------------*/
8489 operand *left, *result;
8493 D (emitcode (";", "genRLC"));
8495 /* rotate right with carry */
8496 left = IC_LEFT (ic);
8497 result = IC_RESULT (ic);
8498 aopOp (left, ic, FALSE, FALSE);
8499 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8501 /* move it to the result */
8502 size = AOP_SIZE (result);
8506 l = aopGet (left, offset, FALSE, FALSE, NULL);
8508 emitcode ("add", "a,acc");
8509 if (AOP_SIZE (result) > 1)
8511 aopPut (result, "a", offset++);
8514 _startLazyDPSEvaluation ();
8517 l = aopGet (left, offset, FALSE, FALSE, NULL);
8519 emitcode ("rlc", "a");
8520 if (AOP_SIZE (result) > 1)
8521 aopPut (result, "a", offset++);
8523 _endLazyDPSEvaluation ();
8525 /* now we need to put the carry into the
8526 highest order byte of the result */
8527 if (AOP_SIZE (result) > 1)
8529 l = aopGet (result, 0, FALSE, FALSE, NULL);
8532 emitcode ("mov", "acc.0,c");
8533 aopPut (result, "a", 0);
8534 freeAsmop (result, NULL, ic, TRUE);
8535 freeAsmop (left, NULL, ic, TRUE);
8538 /*-----------------------------------------------------------------*/
8539 /* genGetHbit - generates code get highest order bit */
8540 /*-----------------------------------------------------------------*/
8542 genGetHbit (iCode * ic)
8544 operand *left, *result;
8546 D (emitcode (";", "genGetHbit"));
8548 left = IC_LEFT (ic);
8549 result = IC_RESULT (ic);
8550 aopOp (left, ic, FALSE, FALSE);
8551 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8553 /* get the highest order byte into a */
8554 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
8555 if (AOP_TYPE (result) == AOP_CRY)
8557 emitcode ("rlc", "a");
8562 emitcode ("rl", "a");
8563 emitcode ("anl", "a,#0x01");
8568 freeAsmop (result, NULL, ic, TRUE);
8569 freeAsmop (left, NULL, ic, TRUE);
8572 /*-----------------------------------------------------------------*/
8573 /* genSwap - generates code to swap nibbles or bytes */
8574 /*-----------------------------------------------------------------*/
8576 genSwap (iCode * ic)
8578 operand *left, *result;
8580 D(emitcode (";", "genSwap"));
8582 left = IC_LEFT (ic);
8583 result = IC_RESULT (ic);
8584 aopOp (left, ic, FALSE, FALSE);
8585 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8587 _startLazyDPSEvaluation ();
8588 switch (AOP_SIZE (left))
8590 case 1: /* swap nibbles in byte */
8591 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
8592 emitcode ("swap", "a");
8593 aopPut (result, "a", 0);
8595 case 2: /* swap bytes in word */
8596 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
8598 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
8599 aopPut (result, aopGet (left, 1, FALSE, FALSE, NULL), 0);
8600 aopPut (result, "a", 1);
8602 else if (operandsEqu (left, result))
8605 bool pushedB = FALSE, leftInB = FALSE;
8607 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
8608 if (AOP_NEEDSACC (left) || AOP_NEEDSACC (result))
8611 emitcode ("mov", "b,a");
8615 aopPut (result, aopGet (left, 1, FALSE, FALSE, NULL), 0);
8616 aopPut (result, reg, 1);
8623 aopPut (result, aopGet (left, 1, FALSE, FALSE, NULL), 0);
8624 aopPut (result, aopGet (left, 0, FALSE, FALSE, NULL), 1);
8628 wassertl(FALSE, "unsupported SWAP operand size");
8630 _endLazyDPSEvaluation ();
8632 freeAsmop (result, NULL, ic, TRUE);
8633 freeAsmop (left, NULL, ic, TRUE);
8636 /*-----------------------------------------------------------------*/
8637 /* AccRol - rotate left accumulator by known count */
8638 /*-----------------------------------------------------------------*/
8640 AccRol (int shCount)
8642 shCount &= 0x0007; // shCount : 0..7
8649 emitcode ("rl", "a");
8652 emitcode ("rl", "a");
8653 emitcode ("rl", "a");
8656 emitcode ("swap", "a");
8657 emitcode ("rr", "a");
8660 emitcode ("swap", "a");
8663 emitcode ("swap", "a");
8664 emitcode ("rl", "a");
8667 emitcode ("rr", "a");
8668 emitcode ("rr", "a");
8671 emitcode ("rr", "a");
8676 /*-----------------------------------------------------------------*/
8677 /* AccLsh - left shift accumulator by known count */
8678 /*-----------------------------------------------------------------*/
8680 AccLsh (int shCount)
8685 emitcode ("add", "a,acc");
8686 else if (shCount == 2)
8688 emitcode ("add", "a,acc");
8689 emitcode ("add", "a,acc");
8693 /* rotate left accumulator */
8695 /* and kill the lower order bits */
8696 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
8701 /*-----------------------------------------------------------------*/
8702 /* AccRsh - right shift accumulator by known count */
8703 /*-----------------------------------------------------------------*/
8705 AccRsh (int shCount)
8712 emitcode ("rrc", "a");
8716 /* rotate right accumulator */
8717 AccRol (8 - shCount);
8718 /* and kill the higher order bits */
8719 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
8724 #ifdef BETTER_LITERAL_SHIFT
8725 /*-----------------------------------------------------------------*/
8726 /* AccSRsh - signed right shift accumulator by known count */
8727 /*-----------------------------------------------------------------*/
8729 AccSRsh (int shCount)
8736 emitcode ("mov", "c,acc.7");
8737 emitcode ("rrc", "a");
8739 else if (shCount == 2)
8741 emitcode ("mov", "c,acc.7");
8742 emitcode ("rrc", "a");
8743 emitcode ("mov", "c,acc.7");
8744 emitcode ("rrc", "a");
8748 tlbl = newiTempLabel (NULL);
8749 /* rotate right accumulator */
8750 AccRol (8 - shCount);
8751 /* and kill the higher order bits */
8752 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
8753 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8754 emitcode ("orl", "a,#!constbyte",
8755 (unsigned char) ~SRMask[shCount]);
8762 #ifdef BETTER_LITERAL_SHIFT
8763 /*-----------------------------------------------------------------*/
8764 /* shiftR1Left2Result - shift right one byte from left to result */
8765 /*-----------------------------------------------------------------*/
8767 shiftR1Left2Result (operand * left, int offl,
8768 operand * result, int offr,
8769 int shCount, int sign)
8771 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
8772 /* shift right accumulator */
8777 aopPut (result, "a", offr);
8781 #ifdef BETTER_LITERAL_SHIFT
8782 /*-----------------------------------------------------------------*/
8783 /* shiftL1Left2Result - shift left one byte from left to result */
8784 /*-----------------------------------------------------------------*/
8786 shiftL1Left2Result (operand * left, int offl,
8787 operand * result, int offr, int shCount)
8790 l = aopGet (left, offl, FALSE, FALSE, NULL);
8792 /* shift left accumulator */
8794 aopPut (result, "a", offr);
8798 #ifdef BETTER_LITERAL_SHIFT
8799 /*-----------------------------------------------------------------*/
8800 /* movLeft2Result - move byte from left to result */
8801 /*-----------------------------------------------------------------*/
8803 movLeft2Result (operand * left, int offl,
8804 operand * result, int offr, int sign)
8807 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8809 l = aopGet (left, offl, FALSE, FALSE, NULL);
8811 if (*l == '@' && (IS_AOP_PREG (result)))
8813 emitcode ("mov", "a,%s", l);
8814 aopPut (result, "a", offr);
8820 aopPut (result, l, offr);
8824 /* MSB sign in acc.7 ! */
8825 if (getDataSize (left) == offl + 1)
8828 aopPut (result, "a", offr);
8836 #ifdef BETTER_LITERAL_SHIFT
8837 /*-----------------------------------------------------------------*/
8838 /* AccAXRrl1 - right rotate a:x by 1 */
8839 /*-----------------------------------------------------------------*/
8843 emitcode ("mov", "c,acc.0");
8844 emitcode ("xch", "a,%s", x);
8845 emitcode ("rrc", "a");
8846 emitcode ("xch", "a,%s", x);
8847 emitcode ("rrc", "a");
8851 #ifdef BETTER_LITERAL_SHIFT
8853 /*-----------------------------------------------------------------*/
8854 /* AccAXLrl1 - left rotate a:x by 1 */
8855 /*-----------------------------------------------------------------*/
8859 emitcode ("mov", "c,acc.7");
8860 emitcode ("xch", "a,%s", x);
8861 emitcode ("rlc", "a");
8862 emitcode ("xch", "a,%s", x);
8863 emitcode ("rlc", "a");
8867 #ifdef BETTER_LITERAL_SHIFT
8868 /*-----------------------------------------------------------------*/
8869 /* AccAXRsh1 - right shift c->a:x->c by 1 */
8870 /*-----------------------------------------------------------------*/
8874 emitcode ("rrc", "a");
8875 emitcode ("xch", "a,%s", x);
8876 emitcode ("rrc", "a");
8877 emitcode ("xch", "a,%s", x);
8881 #ifdef BETTER_LITERAL_SHIFT
8882 /*-----------------------------------------------------------------*/
8883 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8884 /*-----------------------------------------------------------------*/
8888 emitcode ("xch", "a,%s", x);
8889 emitcode ("add", "a,acc");
8890 emitcode ("xch", "a,%s", x);
8891 emitcode ("rlc", "a");
8895 #ifdef BETTER_LITERAL_SHIFT
8896 /*-----------------------------------------------------------------*/
8897 /* AccAXLsh - left shift a:x by known count (0..7) */
8898 /*-----------------------------------------------------------------*/
8900 AccAXLsh (char *x, int shCount)
8915 case 5: // AAAAABBB:CCCCCDDD
8917 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8919 emitcode ("anl", "a,#!constbyte",
8920 SLMask[shCount]); // BBB00000:CCCCCDDD
8922 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8924 AccRol (shCount); // DDDCCCCC:BBB00000
8926 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8928 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8930 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8932 emitcode ("anl", "a,#!constbyte",
8933 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8935 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8937 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8940 case 6: // AAAAAABB:CCCCCCDD
8941 emitcode ("anl", "a,#!constbyte",
8942 SRMask[shCount]); // 000000BB:CCCCCCDD
8944 AccAXRrl1 (x); // D000000B:BCCCCCCD
8945 AccAXRrl1 (x); // DD000000:BBCCCCCC
8946 emitcode ("xch", "a,%s", x); // BBCCCCCC:DD000000
8948 emitcode ("mov", "c,acc.0"); // c = B
8949 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8950 emitcode("rrc","a");
8951 emitcode("xch","a,%s", x);
8952 emitcode("rrc","a");
8953 emitcode("mov","c,acc.0"); //<< get correct bit
8954 emitcode("xch","a,%s", x);
8956 emitcode("rrc","a");
8957 emitcode("xch","a,%s", x);
8958 emitcode("rrc","a");
8959 emitcode("xch","a,%s", x);
8962 case 7: // a:x <<= 7
8964 emitcode ("anl", "a,#!constbyte",
8965 SRMask[shCount]); // 0000000B:CCCCCCCD
8967 AccAXRrl1 (x); // D0000000:BCCCCCCC
8969 emitcode ("xch", "a,%s", x); // BCCCCCCC:D0000000
8978 #ifdef BETTER_LITERAL_SHIFT
8980 /*-----------------------------------------------------------------*/
8981 /* AccAXRsh - right shift a:x known count (0..7) */
8982 /*-----------------------------------------------------------------*/
8984 AccAXRsh (char *x, int shCount)
8992 AccAXRsh1 (x); // 0->a:x
8997 AccAXRsh1 (x); // 0->a:x
9000 AccAXRsh1 (x); // 0->a:x
9005 case 5: // AAAAABBB:CCCCCDDD = a:x
9007 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
9009 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
9011 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
9013 emitcode ("anl", "a,#!constbyte",
9014 SRMask[shCount]); // 000CCCCC:BBBAAAAA
9016 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
9018 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
9020 emitcode ("anl", "a,#!constbyte",
9021 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
9023 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
9025 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
9027 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
9030 case 6: // AABBBBBB:CCDDDDDD
9032 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDE
9033 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
9035 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
9037 emitcode ("anl", "a,#!constbyte",
9038 SRMask[shCount]); // 000000AA:BBBBBBCC
9041 case 7: // ABBBBBBB:CDDDDDDD
9043 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
9045 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
9047 emitcode ("anl", "a,#!constbyte",
9048 SRMask[shCount]); // 0000000A:BBBBBBBC
9057 #ifdef BETTER_LITERAL_SHIFT
9058 /*-----------------------------------------------------------------*/
9059 /* AccAXRshS - right shift signed a:x known count (0..7) */
9060 /*-----------------------------------------------------------------*/
9062 AccAXRshS (char *x, int shCount)
9070 emitcode ("mov", "c,acc.7");
9071 AccAXRsh1 (x); // s->a:x
9075 emitcode ("mov", "c,acc.7");
9076 AccAXRsh1 (x); // s->a:x
9078 emitcode ("mov", "c,acc.7");
9079 AccAXRsh1 (x); // s->a:x
9084 case 5: // AAAAABBB:CCCCCDDD = a:x
9086 tlbl = newiTempLabel (NULL);
9087 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
9089 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
9091 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
9093 emitcode ("anl", "a,#!constbyte",
9094 SRMask[shCount]); // 000CCCCC:BBBAAAAA
9096 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
9098 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
9100 emitcode ("anl", "a,#!constbyte",
9101 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
9103 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
9105 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
9107 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
9109 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
9110 emitcode ("orl", "a,#!constbyte",
9111 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
9114 break; // SSSSAAAA:BBBCCCCC
9116 case 6: // AABBBBBB:CCDDDDDD
9118 tlbl = newiTempLabel (NULL);
9120 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
9121 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
9123 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
9125 emitcode ("anl", "a,#!constbyte",
9126 SRMask[shCount]); // 000000AA:BBBBBBCC
9128 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
9129 emitcode ("orl", "a,#!constbyte",
9130 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
9134 case 7: // ABBBBBBB:CDDDDDDD
9136 tlbl = newiTempLabel (NULL);
9138 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
9140 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
9142 emitcode ("anl", "a,#!constbyte",
9143 SRMask[shCount]); // 0000000A:BBBBBBBC
9145 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
9146 emitcode ("orl", "a,#!constbyte",
9147 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
9157 #ifdef BETTER_LITERAL_SHIFT
9159 _loadLeftIntoAx(char **lsb,
9165 // Get the initial value from left into a pair of registers.
9166 // MSB must be in A, LSB can be any register.
9168 // If the result is held in registers, it is an optimization
9169 // if the LSB can be held in the register which will hold the,
9170 // result LSB since this saves us from having to copy it into
9171 // the result following AccAXLsh.
9173 // If the result is addressed indirectly, this is not a gain.
9174 if (AOP_NEEDSACC(result))
9178 _startLazyDPSEvaluation();
9179 if (AOP_TYPE(left) == AOP_DPTR2)
9182 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE, NULL));
9183 // get LSB in DP2_RESULT_REG.
9184 leftByte = aopGet (left, offl, FALSE, FALSE, DP2_RESULT_REG);
9185 assert(!strcmp(leftByte, DP2_RESULT_REG));
9189 // get LSB into DP2_RESULT_REG
9190 leftByte = aopGet (left, offl, FALSE, FALSE, NULL);
9191 if (strcmp(leftByte, DP2_RESULT_REG))
9194 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
9197 leftByte = aopGet (left, offl + MSB16, FALSE, FALSE, NULL);
9198 assert(strcmp(leftByte, DP2_RESULT_REG));
9201 _endLazyDPSEvaluation();
9202 *lsb = DP2_RESULT_REG;
9206 if (sameRegs (AOP (result), AOP (left)) &&
9207 ((offl + MSB16) == offr))
9209 /* don't crash result[offr] */
9210 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
9211 emitcode ("xch", "a,%s",
9212 aopGet (left, offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
9216 movLeft2Result (left, offl, result, offr, 0);
9217 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE, NULL));
9219 *lsb = aopGet (result, offr, FALSE, FALSE, DP2_RESULT_REG);
9220 assert(strcmp(*lsb,"a"));
9225 _storeAxResults(char *lsb,
9229 _startLazyDPSEvaluation();
9230 if (AOP_NEEDSACC(result))
9232 /* We have to explicitly update the result LSB.
9234 emitcode ("xch","a,%s", lsb);
9235 aopPut (result, "a", offr);
9236 emitcode ("mov","a,%s", lsb);
9238 if (getDataSize (result) > 1)
9240 aopPut (result, "a", offr + MSB16);
9242 _endLazyDPSEvaluation();
9245 /*-----------------------------------------------------------------*/
9246 /* shiftL2Left2Result - shift left two bytes from left to result */
9247 /*-----------------------------------------------------------------*/
9249 shiftL2Left2Result (operand * left, int offl,
9250 operand * result, int offr, int shCount)
9254 _loadLeftIntoAx(&lsb, left, result, offl, offr);
9256 AccAXLsh (lsb, shCount);
9258 _storeAxResults(lsb, result, offr);
9262 #ifdef BETTER_LITERAL_SHIFT
9263 /*-----------------------------------------------------------------*/
9264 /* shiftR2Left2Result - shift right two bytes from left to result */
9265 /*-----------------------------------------------------------------*/
9267 shiftR2Left2Result (operand * left, int offl,
9268 operand * result, int offr,
9269 int shCount, int sign)
9273 _loadLeftIntoAx(&lsb, left, result, offl, offr);
9275 /* a:x >> shCount (x = lsb(result)) */
9278 AccAXRshS(lsb, shCount);
9282 AccAXRsh(lsb, shCount);
9285 _storeAxResults(lsb, result, offr);
9289 /*-----------------------------------------------------------------*/
9290 /* shiftLLeftOrResult - shift left one byte from left, or to result */
9291 /*-----------------------------------------------------------------*/
9293 shiftLLeftOrResult (operand * left, int offl,
9294 operand * result, int offr, int shCount)
9296 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
9297 /* shift left accumulator */
9299 /* or with result */
9300 emitcode ("orl", "a,%s",
9301 aopGet (result, offr, FALSE, FALSE, DP2_RESULT_REG));
9302 /* back to result */
9303 aopPut (result, "a", offr);
9308 /*-----------------------------------------------------------------*/
9309 /* shiftRLeftOrResult - shift right one byte from left,or to result */
9310 /*-----------------------------------------------------------------*/
9312 shiftRLeftOrResult (operand * left, int offl,
9313 operand * result, int offr, int shCount)
9315 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
9316 /* shift right accumulator */
9318 /* or with result */
9319 emitcode ("orl", "a,%s",
9320 aopGet (result, offr, FALSE, FALSE, DP2_RESULT_REG));
9321 /* back to result */
9322 aopPut (result, "a", offr);
9326 #ifdef BETTER_LITERAL_SHIFT
9327 /*-----------------------------------------------------------------*/
9328 /* genlshOne - left shift a one byte quantity by known count */
9329 /*-----------------------------------------------------------------*/
9331 genlshOne (operand * result, operand * left, int shCount)
9333 D (emitcode (";", "genlshOne"));
9335 shiftL1Left2Result (left, LSB, result, LSB, shCount);
9339 #ifdef BETTER_LITERAL_SHIFT
9340 /*-----------------------------------------------------------------*/
9341 /* genlshTwo - left shift two bytes by known amount != 0 */
9342 /*-----------------------------------------------------------------*/
9344 genlshTwo (operand * result, operand * left, int shCount)
9348 D (emitcode (";", "genlshTwo"));
9350 size = getDataSize (result);
9352 /* if shCount >= 8 */
9357 _startLazyDPSEvaluation();
9363 _endLazyDPSEvaluation();
9364 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
9365 aopPut (result, zero, LSB);
9369 movLeft2Result (left, LSB, result, MSB16, 0);
9370 aopPut (result, zero, LSB);
9371 _endLazyDPSEvaluation();
9376 aopPut (result, zero, LSB);
9377 _endLazyDPSEvaluation();
9381 /* 1 <= shCount <= 7 */
9385 shiftL1Left2Result (left, LSB, result, LSB, shCount);
9387 shiftL2Left2Result (left, LSB, result, LSB, shCount);
9394 /*-----------------------------------------------------------------*/
9395 /* shiftLLong - shift left one long from left to result */
9396 /* offl = LSB or MSB16 */
9397 /*-----------------------------------------------------------------*/
9399 shiftLLong (operand * left, operand * result, int offr)
9402 int size = AOP_SIZE (result);
9404 if (size >= LSB + offr)
9406 l = aopGet (left, LSB, FALSE, FALSE, NULL);
9408 emitcode ("add", "a,acc");
9409 if (sameRegs (AOP (left), AOP (result)) &&
9410 size >= MSB16 + offr && offr != LSB)
9411 emitcode ("xch", "a,%s",
9412 aopGet (left, LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
9414 aopPut (result, "a", LSB + offr);
9417 if (size >= MSB16 + offr)
9419 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
9421 l = aopGet (left, MSB16, FALSE, FALSE, TRUE);
9424 emitcode ("rlc", "a");
9425 if (sameRegs (AOP (left), AOP (result)) &&
9426 size >= MSB24 + offr && offr != LSB)
9427 emitcode ("xch", "a,%s",
9428 aopGet (left, MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
9430 aopPut (result, "a", MSB16 + offr);
9433 if (size >= MSB24 + offr)
9435 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
9437 l = aopGet (left, MSB24, FALSE, FALSE, NULL);
9440 emitcode ("rlc", "a");
9441 if (sameRegs (AOP (left), AOP (result)) &&
9442 size >= MSB32 + offr && offr != LSB)
9443 emitcode ("xch", "a,%s",
9444 aopGet (left, MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
9446 aopPut (result, "a", MSB24 + offr);
9449 if (size > MSB32 + offr)
9451 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
9453 l = aopGet (left, MSB32, FALSE, FALSE, NULL);
9456 emitcode ("rlc", "a");
9457 aopPut (result, "a", MSB32 + offr);
9460 aopPut (result, zero, LSB);
9466 /*-----------------------------------------------------------------*/
9467 /* genlshFour - shift four byte by a known amount != 0 */
9468 /*-----------------------------------------------------------------*/
9470 genlshFour (operand * result, operand * left, int shCount)
9474 D (emitcode (";", "genlshFour"));
9476 size = AOP_SIZE (result);
9478 /* if shifting more that 3 bytes */
9483 /* lowest order of left goes to the highest
9484 order of the destination */
9485 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
9487 movLeft2Result (left, LSB, result, MSB32, 0);
9488 aopPut (result, zero, LSB);
9489 aopPut (result, zero, MSB16);
9490 aopPut (result, zero, MSB24);
9494 /* more than two bytes */
9495 else if (shCount >= 16)
9497 /* lower order two bytes goes to higher order two bytes */
9499 /* if some more remaining */
9501 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
9504 movLeft2Result (left, MSB16, result, MSB32, 0);
9505 movLeft2Result (left, LSB, result, MSB24, 0);
9507 aopPut (result, zero, MSB16);
9508 aopPut (result, zero, LSB);
9512 /* if more than 1 byte */
9513 else if (shCount >= 8)
9515 /* lower order three bytes goes to higher order three bytes */
9520 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
9522 movLeft2Result (left, LSB, result, MSB16, 0);
9528 movLeft2Result (left, MSB24, result, MSB32, 0);
9529 movLeft2Result (left, MSB16, result, MSB24, 0);
9530 movLeft2Result (left, LSB, result, MSB16, 0);
9531 aopPut (result, zero, LSB);
9533 else if (shCount == 1)
9534 shiftLLong (left, result, MSB16);
9537 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
9538 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
9539 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
9540 aopPut (result, zero, LSB);
9545 /* 1 <= shCount <= 7 */
9546 else if (shCount <= 2)
9548 shiftLLong (left, result, LSB);
9550 shiftLLong (result, result, LSB);
9552 /* 3 <= shCount <= 7, optimize */
9555 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
9556 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
9557 shiftL2Left2Result (left, LSB, result, LSB, shCount);
9562 #ifdef BETTER_LITERAL_SHIFT
9563 /*-----------------------------------------------------------------*/
9564 /* genLeftShiftLiteral - left shifting by known count */
9565 /*-----------------------------------------------------------------*/
9567 genLeftShiftLiteral (operand * left,
9572 int shCount = (int) ulFromVal (AOP (right)->aopu.aop_lit);
9575 size = getSize (operandType (result));
9577 D (emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
9579 /* We only handle certain easy cases so far. */
9581 && (shCount < (size * 8))
9585 D(emitcode (";", "genLeftShiftLiteral wimping out"););
9589 freeAsmop (right, NULL, ic, TRUE);
9591 aopOp(left, ic, FALSE, FALSE);
9592 aopOp(result, ic, FALSE, AOP_USESDPTR(left));
9595 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
9597 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
9598 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
9600 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
9603 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
9605 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
9606 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
9608 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
9614 emitcode ("; shift left ", "result %d, left %d", size,
9618 /* I suppose that the left size >= result size */
9621 _startLazyDPSEvaluation();
9624 movLeft2Result (left, size, result, size, 0);
9626 _endLazyDPSEvaluation();
9628 else if (shCount >= (size * 8))
9630 _startLazyDPSEvaluation();
9633 aopPut (result, zero, size);
9635 _endLazyDPSEvaluation();
9642 genlshOne (result, left, shCount);
9646 genlshTwo (result, left, shCount);
9650 genlshFour (result, left, shCount);
9654 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9655 "*** ack! mystery literal shift!\n");
9659 freeAsmop (result, NULL, ic, TRUE);
9660 freeAsmop (left, NULL, ic, TRUE);
9665 /*-----------------------------------------------------------------*/
9666 /* genLeftShift - generates code for left shifting */
9667 /*-----------------------------------------------------------------*/
9669 genLeftShift (iCode * ic)
9671 operand *left, *right, *result;
9674 symbol *tlbl, *tlbl1;
9677 D (emitcode (";", "genLeftShift"));
9679 right = IC_RIGHT (ic);
9680 left = IC_LEFT (ic);
9681 result = IC_RESULT (ic);
9683 aopOp (right, ic, FALSE, FALSE);
9686 #ifdef BETTER_LITERAL_SHIFT
9687 /* if the shift count is known then do it
9688 as efficiently as possible */
9689 if (AOP_TYPE (right) == AOP_LIT)
9691 if (genLeftShiftLiteral (left, right, result, ic))
9698 /* shift count is unknown then we have to form
9699 a loop get the loop count in B : Note: we take
9700 only the lower order byte since shifting
9701 more that 32 bits make no sense anyway, ( the
9702 largest size of an object can be only 32 bits ) */
9705 if (AOP_TYPE (right) == AOP_LIT)
9707 /* Really should be handled by genLeftShiftLiteral,
9708 * but since I'm too lazy to fix that today, at least we can make
9709 * some small improvement.
9711 emitcode("mov", "b,#!constbyte",
9712 ((int) ulFromVal (AOP (right)->aopu.aop_lit)) + 1);
9716 MOVB (aopGet (right, 0, FALSE, FALSE, "b"));
9717 emitcode ("inc", "b");
9719 freeAsmop (right, NULL, ic, TRUE);
9720 aopOp (left, ic, FALSE, FALSE);
9721 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9723 /* now move the left to the result if they are not the same */
9724 if (!sameRegs (AOP (left), AOP (result)) &&
9725 AOP_SIZE (result) > 1)
9728 size = AOP_SIZE (result);
9730 _startLazyDPSEvaluation ();
9733 l = aopGet (left, offset, FALSE, TRUE, NULL);
9734 if (*l == '@' && (IS_AOP_PREG (result)))
9737 emitcode ("mov", "a,%s", l);
9738 aopPut (result, "a", offset);
9741 aopPut (result, l, offset);
9744 _endLazyDPSEvaluation ();
9747 tlbl = newiTempLabel (NULL);
9748 size = AOP_SIZE (result);
9750 tlbl1 = newiTempLabel (NULL);
9752 /* if it is only one byte then */
9755 symbol *tlbl1 = newiTempLabel (NULL);
9757 l = aopGet (left, 0, FALSE, FALSE, NULL);
9759 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9761 emitcode ("add", "a,acc");
9763 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9765 aopPut (result, "a", 0);
9769 reAdjustPreg (AOP (result));
9771 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9773 l = aopGet (result, offset, FALSE, FALSE, NULL);
9775 emitcode ("add", "a,acc");
9776 aopPut (result, "a", offset++);
9777 _startLazyDPSEvaluation ();
9780 l = aopGet (result, offset, FALSE, FALSE, NULL);
9782 emitcode ("rlc", "a");
9783 aopPut (result, "a", offset++);
9785 _endLazyDPSEvaluation ();
9786 reAdjustPreg (AOP (result));
9789 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9792 freeAsmop (result, NULL, ic, TRUE);
9793 freeAsmop (left, NULL, ic, TRUE);
9796 #ifdef BETTER_LITERAL_SHIFT
9797 /*-----------------------------------------------------------------*/
9798 /* genrshOne - right shift a one byte quantity by known count */
9799 /*-----------------------------------------------------------------*/
9801 genrshOne (operand * result, operand * left,
9802 int shCount, int sign)
9804 D (emitcode (";", "genrshOne"));
9806 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9810 #ifdef BETTER_LITERAL_SHIFT
9811 /*-----------------------------------------------------------------*/
9812 /* genrshTwo - right shift two bytes by known amount != 0 */
9813 /*-----------------------------------------------------------------*/
9815 genrshTwo (operand * result, operand * left,
9816 int shCount, int sign)
9818 D (emitcode (";", "genrshTwo"));
9820 /* if shCount >= 8 */
9824 _startLazyDPSEvaluation();
9826 shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
9828 movLeft2Result (left, MSB16, result, LSB, sign);
9829 addSign (result, MSB16, sign);
9830 _endLazyDPSEvaluation();
9833 /* 1 <= shCount <= 7 */
9835 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9839 /*-----------------------------------------------------------------*/
9840 /* shiftRLong - shift right one long from left to result */
9841 /* offl = LSB or MSB16 */
9842 /*-----------------------------------------------------------------*/
9844 shiftRLong (operand * left, int offl,
9845 operand * result, int sign)
9847 bool overlapping = regsInCommon (left, result) || operandsEqu(left, result);
9849 if (overlapping && offl>1)
9851 // we are in big trouble, but this shouldn't happen
9852 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9855 MOVA (aopGet (left, MSB32, FALSE, FALSE, NULL));
9862 emitcode ("rlc", "a");
9863 emitcode ("subb", "a,acc");
9864 emitcode ("xch", "a,%s",
9865 aopGet(left, MSB32, FALSE, FALSE, DP2_RESULT_REG));
9869 aopPut (result, zero, MSB32);
9875 emitcode ("clr", "c");
9879 emitcode ("mov", "c,acc.7");
9882 emitcode ("rrc", "a");
9884 if (overlapping && offl==MSB16)
9886 emitcode ("xch", "a,%s", aopGet (left, MSB24, FALSE, FALSE, DP2_RESULT_REG));
9890 aopPut (result, "a", MSB32 - offl);
9891 MOVA (aopGet (left, MSB24, FALSE, FALSE, NULL));
9894 emitcode ("rrc", "a");
9896 if (overlapping && offl==MSB16)
9898 emitcode ("xch", "a,%s", aopGet (left, MSB16, FALSE, FALSE, DP2_RESULT_REG));
9902 aopPut (result, "a", MSB24 - offl);
9903 MOVA (aopGet (left, MSB16, FALSE, FALSE, NULL));
9906 emitcode ("rrc", "a");
9909 aopPut (result, "a", MSB16 - offl);
9913 if (overlapping && offl==MSB16)
9915 emitcode ("xch", "a,%s", aopGet (left, LSB, FALSE, FALSE, DP2_RESULT_REG));
9919 aopPut (result, "a", MSB16 - offl);
9920 MOVA (aopGet (left, LSB, FALSE, FALSE, NULL));
9922 emitcode ("rrc", "a");
9923 aopPut (result, "a", LSB);
9927 /*-----------------------------------------------------------------*/
9928 /* genrshFour - shift four byte by a known amount != 0 */
9929 /*-----------------------------------------------------------------*/
9931 genrshFour (operand * result, operand * left,
9932 int shCount, int sign)
9934 D (emitcode (";", "genrshFour"));
9936 /* if shifting more that 3 bytes */
9940 _startLazyDPSEvaluation();
9942 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9944 movLeft2Result (left, MSB32, result, LSB, sign);
9945 addSign (result, MSB16, sign);
9946 _endLazyDPSEvaluation();
9948 else if (shCount >= 16)
9951 _startLazyDPSEvaluation();
9953 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9956 movLeft2Result (left, MSB24, result, LSB, 0);
9957 movLeft2Result (left, MSB32, result, MSB16, sign);
9959 addSign (result, MSB24, sign);
9960 _endLazyDPSEvaluation();
9962 else if (shCount >= 8)
9965 _startLazyDPSEvaluation();
9968 shiftRLong (left, MSB16, result, sign);
9970 else if (shCount == 0)
9972 movLeft2Result (left, MSB16, result, LSB, 0);
9973 movLeft2Result (left, MSB24, result, MSB16, 0);
9974 movLeft2Result (left, MSB32, result, MSB24, sign);
9975 addSign (result, MSB32, sign);
9979 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9980 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9981 /* the last shift is signed */
9982 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9983 addSign (result, MSB32, sign);
9985 _endLazyDPSEvaluation();
9989 /* 1 <= shCount <= 7 */
9992 shiftRLong (left, LSB, result, sign);
9994 shiftRLong (result, LSB, result, sign);
9998 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9999 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
10000 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
10005 #ifdef BETTER_LITERAL_SHIFT
10006 /*-----------------------------------------------------------------*/
10007 /* genRightShiftLiteral - right shifting by known count */
10008 /*-----------------------------------------------------------------*/
10010 genRightShiftLiteral (operand * left,
10016 int shCount = (int) ulFromVal (AOP (right)->aopu.aop_lit);
10019 size = getSize (operandType (result));
10021 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
10023 /* We only handle certain easy cases so far. */
10025 && (shCount < (size * 8))
10030 D(emitcode (";", "genRightShiftLiteral wimping out"););
10034 freeAsmop (right, NULL, ic, TRUE);
10036 aopOp (left, ic, FALSE, FALSE);
10037 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
10040 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
10044 /* test the LEFT size !!! */
10046 /* I suppose that the left size >= result size */
10049 size = getDataSize (result);
10050 _startLazyDPSEvaluation();
10052 movLeft2Result (left, size, result, size, 0);
10053 _endLazyDPSEvaluation();
10055 else if (shCount >= (size * 8))
10059 /* get sign in acc.7 */
10060 MOVA (aopGet (left, size - 1, FALSE, FALSE, NULL));
10062 addSign (result, LSB, sign);
10069 genrshOne (result, left, shCount, sign);
10073 genrshTwo (result, left, shCount, sign);
10077 genrshFour (result, left, shCount, sign);
10084 freeAsmop (result, NULL, ic, TRUE);
10085 freeAsmop (left, NULL, ic, TRUE);
10091 /*-----------------------------------------------------------------*/
10092 /* genSignedRightShift - right shift of signed number */
10093 /*-----------------------------------------------------------------*/
10095 genSignedRightShift (iCode * ic)
10097 operand *right, *left, *result;
10100 symbol *tlbl, *tlbl1;
10103 D (emitcode (";", "genSignedRightShift"));
10105 /* we do it the hard way put the shift count in b
10106 and loop thru preserving the sign */
10108 right = IC_RIGHT (ic);
10109 left = IC_LEFT (ic);
10110 result = IC_RESULT (ic);
10112 aopOp (right, ic, FALSE, FALSE);
10114 #ifdef BETTER_LITERAL_SHIFT
10115 if (AOP_TYPE (right) == AOP_LIT)
10117 if (genRightShiftLiteral (left, right, result, ic, 1))
10123 /* shift count is unknown then we have to form
10124 a loop get the loop count in B : Note: we take
10125 only the lower order byte since shifting
10126 more that 32 bits make no sense anyway, ( the
10127 largest size of an object can be only 32 bits ) */
10129 pushedB = pushB ();
10130 if (AOP_TYPE (right) == AOP_LIT)
10132 /* Really should be handled by genRightShiftLiteral,
10133 * but since I'm too lazy to fix that today, at least we can make
10134 * some small improvement.
10136 emitcode("mov", "b,#!constbyte",
10137 ((int) ulFromVal (AOP (right)->aopu.aop_lit)) + 1);
10141 MOVB (aopGet (right, 0, FALSE, FALSE, "b"));
10142 emitcode ("inc", "b");
10144 freeAsmop (right, NULL, ic, TRUE);
10145 aopOp (left, ic, FALSE, FALSE);
10146 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
10148 /* now move the left to the result if they are not the
10150 if (!sameRegs (AOP (left), AOP (result)) &&
10151 AOP_SIZE (result) > 1)
10154 size = AOP_SIZE (result);
10156 _startLazyDPSEvaluation ();
10159 l = aopGet (left, offset, FALSE, TRUE, NULL);
10160 if (*l == '@' && IS_AOP_PREG (result))
10163 emitcode ("mov", "a,%s", l);
10164 aopPut (result, "a", offset);
10167 aopPut (result, l, offset);
10170 _endLazyDPSEvaluation ();
10173 /* mov the highest order bit to OVR */
10174 tlbl = newiTempLabel (NULL);
10175 tlbl1 = newiTempLabel (NULL);
10177 size = AOP_SIZE (result);
10179 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
10180 emitcode ("rlc", "a");
10181 emitcode ("mov", "ov,c");
10182 /* if it is only one byte then */
10185 l = aopGet (left, 0, FALSE, FALSE, NULL);
10187 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
10189 emitcode ("mov", "c,ov");
10190 emitcode ("rrc", "a");
10192 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
10194 aopPut (result, "a", 0);
10198 reAdjustPreg (AOP (result));
10199 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
10201 emitcode ("mov", "c,ov");
10202 _startLazyDPSEvaluation ();
10205 l = aopGet (result, offset, FALSE, FALSE, NULL);
10207 emitcode ("rrc", "a");
10208 aopPut (result, "a", offset--);
10210 _endLazyDPSEvaluation ();
10211 reAdjustPreg (AOP (result));
10213 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
10217 freeAsmop (result, NULL, ic, TRUE);
10218 freeAsmop (left, NULL, ic, TRUE);
10221 /*-----------------------------------------------------------------*/
10222 /* genRightShift - generate code for right shifting */
10223 /*-----------------------------------------------------------------*/
10225 genRightShift (iCode * ic)
10227 operand *right, *left, *result;
10231 symbol *tlbl, *tlbl1;
10234 D (emitcode (";", "genRightShift"));
10236 /* if signed then we do it the hard way preserve the
10237 sign bit moving it inwards */
10238 letype = getSpec (operandType (IC_LEFT (ic)));
10240 if (!SPEC_USIGN (letype))
10242 genSignedRightShift (ic);
10246 /* signed & unsigned types are treated the same : i.e. the
10247 signed is NOT propagated inwards : quoting from the
10248 ANSI - standard : "for E1 >> E2, is equivalent to division
10249 by 2**E2 if unsigned or if it has a non-negative value,
10250 otherwise the result is implementation defined ", MY definition
10251 is that the sign does not get propagated */
10253 right = IC_RIGHT (ic);
10254 left = IC_LEFT (ic);
10255 result = IC_RESULT (ic);
10257 aopOp (right, ic, FALSE, FALSE);
10259 #ifdef BETTER_LITERAL_SHIFT
10260 /* if the shift count is known then do it
10261 as efficiently as possible */
10262 if (AOP_TYPE (right) == AOP_LIT)
10264 if (genRightShiftLiteral (left, right, result, ic, 0))
10271 /* shift count is unknown then we have to form
10272 a loop get the loop count in B : Note: we take
10273 only the lower order byte since shifting
10274 more that 32 bits make no sense anyway, ( the
10275 largest size of an object can be only 32 bits ) */
10277 pushedB = pushB ();
10278 if (AOP_TYPE (right) == AOP_LIT)
10280 /* Really should be handled by genRightShiftLiteral,
10281 * but since I'm too lazy to fix that today, at least we can make
10282 * some small improvement.
10284 emitcode("mov", "b,#!constbyte",
10285 ((int) ulFromVal (AOP (right)->aopu.aop_lit)) + 1);
10289 MOVB (aopGet (right, 0, FALSE, FALSE, "b"));
10290 emitcode ("inc", "b");
10292 freeAsmop (right, NULL, ic, TRUE);
10293 aopOp (left, ic, FALSE, FALSE);
10294 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
10296 /* now move the left to the result if they are not the
10298 if (!sameRegs (AOP (left), AOP (result)) &&
10299 AOP_SIZE (result) > 1)
10301 size = AOP_SIZE (result);
10303 _startLazyDPSEvaluation ();
10306 l = aopGet (left, offset, FALSE, TRUE, NULL);
10307 if (*l == '@' && IS_AOP_PREG (result))
10310 emitcode ("mov", "a,%s", l);
10311 aopPut (result, "a", offset);
10314 aopPut (result, l, offset);
10317 _endLazyDPSEvaluation ();
10320 tlbl = newiTempLabel (NULL);
10321 tlbl1 = newiTempLabel (NULL);
10322 size = AOP_SIZE (result);
10325 /* if it is only one byte then */
10328 l = aopGet (left, 0, FALSE, FALSE, NULL);
10330 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
10333 emitcode ("rrc", "a");
10335 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
10337 aopPut (result, "a", 0);
10341 reAdjustPreg (AOP (result));
10342 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
10345 _startLazyDPSEvaluation ();
10348 l = aopGet (result, offset, FALSE, FALSE, NULL);
10350 emitcode ("rrc", "a");
10351 aopPut (result, "a", offset--);
10353 _endLazyDPSEvaluation ();
10354 reAdjustPreg (AOP (result));
10357 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
10361 freeAsmop (result, NULL, ic, TRUE);
10362 freeAsmop (left, NULL, ic, TRUE);
10365 /*-----------------------------------------------------------------*/
10366 /* emitPtrByteGet - emits code to get a byte into A through a */
10367 /* pointer register (R0, R1, or DPTR). The */
10368 /* original value of A can be preserved in B. */
10369 /*-----------------------------------------------------------------*/
10371 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
10378 emitcode ("mov", "b,a");
10379 emitcode ("mov", "a,@%s", rname);
10384 emitcode ("mov", "b,a");
10385 emitcode ("movx", "a,@%s", rname);
10390 emitcode ("mov", "b,a");
10391 emitcode ("movx", "a,@dptr");
10396 emitcode ("mov", "b,a");
10397 emitcode ("clr", "a");
10398 emitcode ("movc", "a,@a+dptr");
10404 emitcode ("push", "b");
10405 emitcode ("push", "acc");
10407 emitcode ("lcall", "__gptrget");
10409 emitcode ("pop", "b");
10414 /*-----------------------------------------------------------------*/
10415 /* emitPtrByteSet - emits code to set a byte from src through a */
10416 /* pointer register (R0, R1, or DPTR). */
10417 /*-----------------------------------------------------------------*/
10419 emitPtrByteSet (char *rname, int p_type, char *src)
10428 emitcode ("mov", "@%s,a", rname);
10431 emitcode ("mov", "@%s,%s", rname, src);
10436 emitcode ("movx", "@%s,a", rname);
10441 emitcode ("movx", "@dptr,a");
10446 emitcode ("lcall", "__gptrput");
10451 /*-----------------------------------------------------------------*/
10452 /* genUnpackBits - generates code for unpacking bits */
10453 /*-----------------------------------------------------------------*/
10455 genUnpackBits (operand * result, char *rname, int ptype)
10457 int offset = 0; /* result byte offset */
10458 int rsize; /* result size */
10459 int rlen = 0; /* remaining bitfield length */
10460 sym_link *etype; /* bitfield type information */
10461 int blen; /* bitfield length */
10462 int bstr; /* bitfield starting bit within byte */
10464 D(emitcode (";", "genUnpackBits"));
10466 etype = getSpec (operandType (result));
10467 rsize = getSize (operandType (result));
10468 blen = SPEC_BLEN (etype);
10469 bstr = SPEC_BSTR (etype);
10471 /* If the bitfield length is less than a byte */
10474 emitPtrByteGet (rname, ptype, FALSE);
10476 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
10477 if (!SPEC_USIGN (etype))
10479 /* signed bitfield */
10480 symbol *tlbl = newiTempLabel (NULL);
10482 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
10483 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
10486 aopPut (result, "a", offset++);
10490 /* Bit field did not fit in a byte. Copy all
10491 but the partial byte at the end. */
10492 for (rlen=blen;rlen>=8;rlen-=8)
10494 emitPtrByteGet (rname, ptype, FALSE);
10495 aopPut (result, "a", offset++);
10497 emitcode ("inc", "%s", rname);
10500 /* Handle the partial byte at the end */
10503 emitPtrByteGet (rname, ptype, FALSE);
10504 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
10505 if (!SPEC_USIGN (etype))
10507 /* signed bitfield */
10508 symbol *tlbl = newiTempLabel (NULL);
10510 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
10511 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
10514 aopPut (result, "a", offset++);
10518 if (offset < rsize)
10522 if (SPEC_USIGN (etype))
10526 /* signed bitfield: sign extension with 0x00 or 0xff */
10527 emitcode ("rlc", "a");
10528 emitcode ("subb", "a,acc");
10534 aopPut (result, source, offset++);
10539 /*-----------------------------------------------------------------*/
10540 /* genDataPointerGet - generates code when ptr offset is known */
10541 /*-----------------------------------------------------------------*/
10543 genDataPointerGet (operand * left,
10549 int size, offset = 0;
10550 aopOp (result, ic, TRUE, FALSE);
10552 /* get the string representation of the name */
10553 l = aopGet (left, 0, FALSE, TRUE, NULL);
10554 size = AOP_SIZE (result);
10555 _startLazyDPSEvaluation ();
10560 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l + 1, offset);
10564 SNPRINTF (buffer, sizeof(buffer), "%s", l + 1);
10566 aopPut (result, buffer, offset++);
10568 _endLazyDPSEvaluation ();
10570 freeAsmop (result, NULL, ic, TRUE);
10571 freeAsmop (left, NULL, ic, TRUE);
10574 /*-----------------------------------------------------------------*/
10575 /* genNearPointerGet - emitcode for near pointer fetch */
10576 /*-----------------------------------------------------------------*/
10578 genNearPointerGet (operand * left,
10586 sym_link *rtype, *retype, *letype;
10587 sym_link *ltype = operandType (left);
10590 rtype = operandType (result);
10591 retype = getSpec (rtype);
10592 letype = getSpec (ltype);
10594 aopOp (left, ic, FALSE, FALSE);
10596 /* if left is rematerialisable and
10597 result is not bitfield variable type and
10598 the left is pointer to data space i.e
10599 lower 128 bytes of space */
10600 if (AOP_TYPE (left) == AOP_IMMD &&
10601 !IS_BITFIELD (retype) &&
10602 !IS_BITFIELD (letype) &&
10603 DCL_TYPE (ltype) == POINTER)
10605 genDataPointerGet (left, result, ic);
10609 /* if the value is already in a pointer register
10610 then don't need anything more */
10611 if (!AOP_INPREG (AOP (left)))
10613 /* otherwise get a free pointer register */
10614 aop = newAsmop (0);
10615 preg = getFreePtr (ic, &aop, FALSE);
10616 emitcode ("mov", "%s,%s",
10618 aopGet (left, 0, FALSE, TRUE, DP2_RESULT_REG));
10619 rname = preg->name;
10622 rname = aopGet (left, 0, FALSE, FALSE, DP2_RESULT_REG);
10624 freeAsmop (left, NULL, ic, TRUE);
10625 aopOp (result, ic, FALSE, FALSE);
10627 /* if bitfield then unpack the bits */
10628 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10629 genUnpackBits (result, rname, POINTER);
10632 /* we have can just get the values */
10633 int size = AOP_SIZE (result);
10638 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
10641 emitcode ("mov", "a,@%s", rname);
10642 aopPut (result, "a", offset);
10646 SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
10647 aopPut (result, buffer, offset);
10651 emitcode ("inc", "%s", rname);
10655 /* now some housekeeping stuff */
10656 if (aop) /* we had to allocate for this iCode */
10658 if (pi) { /* post increment present */
10659 aopPut (left, rname, 0);
10661 freeAsmop (NULL, aop, ic, TRUE);
10665 /* we did not allocate which means left
10666 already in a pointer register, then
10667 if size > 0 && this could be used again
10668 we have to point it back to where it
10670 if (AOP_SIZE (result) > 1 &&
10671 !OP_SYMBOL (left)->remat &&
10672 (OP_SYMBOL (left)->liveTo > ic->seq ||
10676 int size = AOP_SIZE (result) - 1;
10678 emitcode ("dec", "%s", rname);
10683 freeAsmop (result, NULL, ic, TRUE);
10684 if (pi) pi->generated = 1;
10687 /*-----------------------------------------------------------------*/
10688 /* genPagedPointerGet - emitcode for paged pointer fetch */
10689 /*-----------------------------------------------------------------*/
10691 genPagedPointerGet (operand * left,
10699 sym_link *rtype, *retype, *letype;
10701 rtype = operandType (result);
10702 retype = getSpec (rtype);
10703 letype = getSpec (operandType (left));
10704 aopOp (left, ic, FALSE, FALSE);
10706 /* if the value is already in a pointer register
10707 then don't need anything more */
10708 if (!AOP_INPREG (AOP (left)))
10710 /* otherwise get a free pointer register */
10711 aop = newAsmop (0);
10712 preg = getFreePtr (ic, &aop, FALSE);
10713 emitcode ("mov", "%s,%s",
10715 aopGet (left, 0, FALSE, TRUE, NULL));
10716 rname = preg->name;
10719 rname = aopGet (left, 0, FALSE, FALSE, NULL);
10721 freeAsmop (left, NULL, ic, TRUE);
10722 aopOp (result, ic, FALSE, FALSE);
10724 /* if bitfield then unpack the bits */
10725 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10726 genUnpackBits (result, rname, PPOINTER);
10729 /* we have can just get the values */
10730 int size = AOP_SIZE (result);
10736 emitcode ("movx", "a,@%s", rname);
10737 aopPut (result, "a", offset);
10742 emitcode ("inc", "%s", rname);
10746 /* now some housekeeping stuff */
10747 if (aop) /* we had to allocate for this iCode */
10750 aopPut (left, rname, 0);
10751 freeAsmop (NULL, aop, ic, TRUE);
10755 /* we did not allocate which means left
10756 already in a pointer register, then
10757 if size > 0 && this could be used again
10758 we have to point it back to where it
10760 if (AOP_SIZE (result) > 1 &&
10761 !OP_SYMBOL (left)->remat &&
10762 (OP_SYMBOL (left)->liveTo > ic->seq ||
10766 int size = AOP_SIZE (result) - 1;
10768 emitcode ("dec", "%s", rname);
10773 freeAsmop (result, NULL, ic, TRUE);
10774 if (pi) pi->generated = 1;
10777 /*-----------------------------------------------------------------*/
10778 /* genFarPointerGet - get value from far space */
10779 /*-----------------------------------------------------------------*/
10781 genFarPointerGet (operand * left,
10782 operand * result, iCode * ic, iCode *pi)
10784 int size, offset, dopi=1;
10785 sym_link *retype = getSpec (operandType (result));
10786 sym_link *letype = getSpec (operandType (left));
10787 D (emitcode (";", "genFarPointerGet"););
10789 aopOp (left, ic, FALSE, FALSE);
10791 /* if the operand is already in dptr
10792 then we do nothing else we move the value to dptr */
10793 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
10795 /* if this is rematerializable */
10796 if (AOP_TYPE (left) == AOP_IMMD)
10798 emitcode ("mov", "dptr,%s", aopGet (left, 0, TRUE, FALSE, NULL));
10802 /* we need to get it byte by byte */
10803 _startLazyDPSEvaluation ();
10804 if (AOP_TYPE (left) != AOP_DPTR)
10806 emitcode ("mov", "dpl,%s", aopGet (left, 0, FALSE, FALSE, NULL));
10807 emitcode ("mov", "dph,%s", aopGet (left, 1, FALSE, FALSE, NULL));
10808 if (options.model == MODEL_FLAT24)
10809 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10813 /* We need to generate a load to DPTR indirect through DPTR. */
10814 D (emitcode (";", "genFarPointerGet -- indirection special case."););
10815 emitcode ("push", "%s", aopGet (left, 0, FALSE, TRUE, NULL));
10816 emitcode ("push", "%s", aopGet (left, 1, FALSE, TRUE, NULL));
10817 if (options.model == MODEL_FLAT24)
10818 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10819 emitcode ("pop", "dph");
10820 emitcode ("pop", "dpl");
10823 _endLazyDPSEvaluation ();
10826 /* so dptr now contains the address */
10827 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10829 /* if bit then unpack */
10830 if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
10831 if (AOP_INDPTRn(left)) {
10832 genSetDPTR(AOP(left)->aopu.dptr);
10834 genUnpackBits (result, "dptr", FPOINTER);
10835 if (AOP_INDPTRn(left)) {
10840 size = AOP_SIZE (result);
10843 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10845 genSetDPTR(AOP(left)->aopu.dptr);
10846 emitcode ("movx", "a,@dptr");
10847 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10848 emitcode ("inc", "dptr");
10850 aopPut (result, "a", offset++);
10853 _startLazyDPSEvaluation ();
10855 if (AOP_INDPTRn(left)) {
10856 genSetDPTR(AOP(left)->aopu.dptr);
10862 emitcode ("movx", "a,@dptr");
10863 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10864 emitcode ("inc", "dptr");
10866 aopPut (result, "a", offset++);
10868 _endLazyDPSEvaluation ();
10871 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10872 if (!AOP_INDPTRn(left)) {
10873 _startLazyDPSEvaluation ();
10874 aopPut (left, "dpl", 0);
10875 aopPut (left, "dph", 1);
10876 if (options.model == MODEL_FLAT24)
10877 aopPut (left, "dpx", 2);
10878 _endLazyDPSEvaluation ();
10881 } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) &&
10882 AOP_SIZE(result) > 1 &&
10884 (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
10886 size = AOP_SIZE (result) - 1;
10887 if (AOP_INDPTRn(left)) {
10888 genSetDPTR(AOP(left)->aopu.dptr);
10890 while (size--) emitcode ("lcall","__decdptr");
10891 if (AOP_INDPTRn(left)) {
10896 freeAsmop (result, NULL, ic, TRUE);
10897 freeAsmop (left, NULL, ic, TRUE);
10900 /*-----------------------------------------------------------------*/
10901 /* genCodePointerGet - get value from code space */
10902 /*-----------------------------------------------------------------*/
10904 genCodePointerGet (operand * left,
10905 operand * result, iCode * ic, iCode *pi)
10907 int size, offset, dopi=1;
10908 sym_link *retype = getSpec (operandType (result));
10910 aopOp (left, ic, FALSE, FALSE);
10912 /* if the operand is already in dptr
10913 then we do nothing else we move the value to dptr */
10914 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
10916 /* if this is rematerializable */
10917 if (AOP_TYPE (left) == AOP_IMMD)
10919 emitcode ("mov", "dptr,%s", aopGet (left, 0, TRUE, FALSE, NULL));
10922 { /* we need to get it byte by byte */
10923 _startLazyDPSEvaluation ();
10924 if (AOP_TYPE (left) != AOP_DPTR)
10926 emitcode ("mov", "dpl,%s", aopGet (left, 0, FALSE, FALSE, NULL));
10927 emitcode ("mov", "dph,%s", aopGet (left, 1, FALSE, FALSE, NULL));
10928 if (options.model == MODEL_FLAT24)
10929 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10933 /* We need to generate a load to DPTR indirect through DPTR. */
10934 D (emitcode (";", "gencodePointerGet -- indirection special case."););
10935 emitcode ("push", "%s", aopGet (left, 0, FALSE, TRUE, NULL));
10936 emitcode ("push", "%s", aopGet (left, 1, FALSE, TRUE, NULL));
10937 if (options.model == MODEL_FLAT24)
10938 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10939 emitcode ("pop", "dph");
10940 emitcode ("pop", "dpl");
10943 _endLazyDPSEvaluation ();
10946 /* so dptr now contains the address */
10947 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10949 /* if bit then unpack */
10950 if (IS_BITFIELD (retype)) {
10951 if (AOP_INDPTRn(left)) {
10952 genSetDPTR(AOP(left)->aopu.dptr);
10954 genUnpackBits (result, "dptr", CPOINTER);
10955 if (AOP_INDPTRn(left)) {
10960 size = AOP_SIZE (result);
10962 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10964 genSetDPTR(AOP(left)->aopu.dptr);
10965 emitcode ("clr", "a");
10966 emitcode ("movc", "a,@a+dptr");
10967 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10968 emitcode ("inc", "dptr");
10970 aopPut (result, "a", offset++);
10973 _startLazyDPSEvaluation ();
10976 if (AOP_INDPTRn(left)) {
10977 genSetDPTR(AOP(left)->aopu.dptr);
10983 emitcode ("clr", "a");
10984 emitcode ("movc", "a,@a+dptr");
10985 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10986 emitcode ("inc", "dptr");
10987 aopPut (result, "a", offset++);
10989 _endLazyDPSEvaluation ();
10992 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10993 if (!AOP_INDPTRn(left)) {
10994 _startLazyDPSEvaluation ();
10996 aopPut (left, "dpl", 0);
10997 aopPut (left, "dph", 1);
10998 if (options.model == MODEL_FLAT24)
10999 aopPut (left, "dpx", 2);
11001 _endLazyDPSEvaluation ();
11004 } else if (IS_SYMOP(left) &&
11005 (OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
11006 AOP_SIZE(result) > 1 &&
11007 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
11009 size = AOP_SIZE (result) - 1;
11010 if (AOP_INDPTRn(left)) {
11011 genSetDPTR(AOP(left)->aopu.dptr);
11013 while (size--) emitcode ("lcall","__decdptr");
11014 if (AOP_INDPTRn(left)) {
11019 freeAsmop (result, NULL, ic, TRUE);
11020 freeAsmop (left, NULL, ic, TRUE);
11023 /*-----------------------------------------------------------------*/
11024 /* genGenPointerGet - get value from generic pointer space */
11025 /*-----------------------------------------------------------------*/
11027 genGenPointerGet (operand * left,
11028 operand * result, iCode * ic, iCode * pi)
11032 sym_link *retype = getSpec (operandType (result));
11033 sym_link *letype = getSpec (operandType (left));
11035 D (emitcode (";", "genGenPointerGet"));
11037 aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
11039 pushedB = pushB ();
11040 /* if the operand is already in dptr
11041 then we do nothing else we move the value to dptr */
11042 if (AOP_TYPE (left) != AOP_STR)
11044 /* if this is rematerializable */
11045 if (AOP_TYPE (left) == AOP_IMMD)
11047 emitcode ("mov", "dptr,%s", aopGet (left, 0, TRUE, FALSE, NULL));
11048 if (AOP(left)->aopu.aop_immd.from_cast_remat)
11050 MOVB (aopGet (left, AOP_SIZE(left)-1, FALSE, FALSE, NULL));
11054 emitcode ("mov", "b,#%d", pointerCode (retype));
11058 { /* we need to get it byte by byte */
11059 _startLazyDPSEvaluation ();
11060 emitcode ("mov", "dpl,%s", aopGet (left,0,FALSE,FALSE,NULL));
11061 emitcode ("mov", "dph,%s", aopGet (left,1,FALSE,FALSE,NULL));
11062 if (options.model == MODEL_FLAT24) {
11063 emitcode ("mov", "dpx,%s", aopGet (left,2,FALSE,FALSE,NULL));
11064 emitcode ("mov", "b,%s", aopGet (left,3,FALSE,FALSE,NULL));
11066 emitcode ("mov", "b,%s", aopGet (left,2,FALSE,FALSE,NULL));
11068 _endLazyDPSEvaluation ();
11072 /* so dptr-b now contains the address */
11073 aopOp (result, ic, FALSE, TRUE);
11075 /* if bit then unpack */
11076 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11078 genUnpackBits (result, "dptr", GPOINTER);
11082 size = AOP_SIZE (result);
11089 // Get two bytes at a time, results in _AP & A.
11090 // dptr will be incremented ONCE by __gptrgetWord.
11092 // Note: any change here must be coordinated
11093 // with the implementation of __gptrgetWord
11094 // in device/lib/_gptrget.c
11095 emitcode ("lcall", "__gptrgetWord");
11096 aopPut (result, "a", offset++);
11097 aopPut (result, DP2_RESULT_REG, offset++);
11102 // Only one byte to get.
11103 emitcode ("lcall", "__gptrget");
11104 aopPut (result, "a", offset++);
11107 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
11109 emitcode ("inc", "dptr");
11114 if (pi && AOP_TYPE (left) != AOP_IMMD) {
11115 _startLazyDPSEvaluation ();
11117 aopPut (left, "dpl", 0);
11118 aopPut (left, "dph", 1);
11119 if (options.model == MODEL_FLAT24) {
11120 aopPut (left, "dpx", 2);
11121 aopPut (left, "b", 3);
11122 } else aopPut (left, "b", 2);
11124 _endLazyDPSEvaluation ();
11127 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
11128 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
11130 size = AOP_SIZE (result) - 1;
11131 while (size--) emitcode ("lcall","__decdptr");
11135 freeAsmop (result, NULL, ic, TRUE);
11136 freeAsmop (left, NULL, ic, TRUE);
11139 /*-----------------------------------------------------------------*/
11140 /* genPointerGet - generate code for pointer get */
11141 /*-----------------------------------------------------------------*/
11143 genPointerGet (iCode * ic, iCode *pi)
11145 operand *left, *result;
11146 sym_link *type, *etype;
11149 D (emitcode (";", "genPointerGet"));
11151 left = IC_LEFT (ic);
11152 result = IC_RESULT (ic);
11154 /* depending on the type of pointer we need to
11155 move it to the correct pointer register */
11156 type = operandType (left);
11157 etype = getSpec (type);
11158 /* if left is of type of pointer then it is simple */
11159 if (IS_PTR (type) && !IS_FUNC (type->next))
11161 p_type = DCL_TYPE (type);
11165 /* we have to go by the storage class */
11166 p_type = PTR_TYPE (SPEC_OCLS (etype));
11169 /* special case when cast remat */
11170 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
11171 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
11173 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
11174 type = operandType (left);
11175 p_type = DCL_TYPE (type);
11177 /* now that we have the pointer type we assign
11178 the pointer values */
11184 genNearPointerGet (left, result, ic, pi);
11188 genPagedPointerGet (left, result, ic, pi);
11192 genFarPointerGet (left, result, ic, pi);
11196 genCodePointerGet (left, result, ic, pi);
11200 genGenPointerGet (left, result, ic, pi);
11206 /*-----------------------------------------------------------------*/
11207 /* genPackBits - generates code for packed bit storage */
11208 /*-----------------------------------------------------------------*/
11210 genPackBits (sym_link * etype,
11212 char *rname, int p_type)
11214 int offset = 0; /* source byte offset */
11215 int rlen = 0; /* remaining bitfield length */
11216 int blen; /* bitfield length */
11217 int bstr; /* bitfield starting bit within byte */
11218 int litval; /* source literal value (if AOP_LIT) */
11219 unsigned char mask; /* bitmask within current byte */
11221 D(emitcode (";", "genPackBits"));
11223 blen = SPEC_BLEN (etype);
11224 bstr = SPEC_BSTR (etype);
11226 /* If the bitfield length is less than a byte */
11229 mask = ((unsigned char) (0xFF << (blen + bstr)) |
11230 (unsigned char) (0xFF >> (8 - bstr)));
11232 if (AOP_TYPE (right) == AOP_LIT)
11234 /* Case with a bitfield length <8 and literal source
11236 litval = (int) ulFromVal (AOP (right)->aopu.aop_lit);
11238 litval &= (~mask) & 0xff;
11239 emitPtrByteGet (rname, p_type, FALSE);
11240 if ((mask|litval)!=0xff)
11241 emitcode ("anl","a,#!constbyte", mask);
11243 emitcode ("orl","a,#!constbyte", litval);
11247 if ((blen==1) && (p_type!=GPOINTER))
11249 /* Case with a bitfield length == 1 and no generic pointer
11251 if (AOP_TYPE (right) == AOP_CRY)
11252 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
11255 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
11256 emitcode ("rrc","a");
11258 emitPtrByteGet (rname, p_type, FALSE);
11259 emitcode ("mov","acc.%d,c",bstr);
11264 /* Case with a bitfield length < 8 and arbitrary source
11266 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
11267 /* shift and mask source value */
11269 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
11271 pushedB = pushB ();
11272 /* transfer A to B and get next byte */
11273 emitPtrByteGet (rname, p_type, TRUE);
11275 emitcode ("anl", "a,#!constbyte", mask);
11276 emitcode ("orl", "a,b");
11277 if (p_type == GPOINTER)
11278 emitcode ("pop", "b");
11284 emitPtrByteSet (rname, p_type, "a");
11288 /* Bit length is greater than 7 bits. In this case, copy */
11289 /* all except the partial byte at the end */
11290 for (rlen=blen;rlen>=8;rlen-=8)
11292 emitPtrByteSet (rname, p_type,
11293 aopGet (right, offset++, FALSE, TRUE, NULL) );
11295 emitcode ("inc", "%s", rname);
11298 /* If there was a partial byte at the end */
11301 mask = (((unsigned char) -1 << rlen) & 0xff);
11303 if (AOP_TYPE (right) == AOP_LIT)
11305 /* Case with partial byte and literal source
11307 litval = (int) ulFromVal (AOP (right)->aopu.aop_lit);
11308 litval >>= (blen-rlen);
11309 litval &= (~mask) & 0xff;
11310 emitPtrByteGet (rname, p_type, FALSE);
11311 if ((mask|litval)!=0xff)
11312 emitcode ("anl","a,#!constbyte", mask);
11314 emitcode ("orl","a,#!constbyte", litval);
11319 /* Case with partial byte and arbitrary source
11321 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11322 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
11324 pushedB = pushB ();
11325 /* transfer A to B and get next byte */
11326 emitPtrByteGet (rname, p_type, TRUE);
11328 emitcode ("anl", "a,#!constbyte", mask);
11329 emitcode ("orl", "a,b");
11330 if (p_type == GPOINTER)
11331 emitcode ("pop", "b");
11335 emitPtrByteSet (rname, p_type, "a");
11340 /*-----------------------------------------------------------------*/
11341 /* genDataPointerSet - remat pointer to data space */
11342 /*-----------------------------------------------------------------*/
11344 genDataPointerSet (operand * right,
11348 int size, offset = 0;
11349 char *l, buffer[256];
11351 D (emitcode (";", "genDataPointerSet"));
11353 aopOp (right, ic, FALSE, FALSE);
11355 l = aopGet (result, 0, FALSE, TRUE, NULL);
11356 size = AOP_SIZE (right);
11360 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l + 1, offset);
11362 SNPRINTF (buffer, sizeof(buffer), "%s", l + 1);
11363 emitcode ("mov", "%s,%s", buffer,
11364 aopGet (right, offset++, FALSE, FALSE, NULL));
11367 freeAsmop (right, NULL, ic, TRUE);
11368 freeAsmop (result, NULL, ic, TRUE);
11371 /*-----------------------------------------------------------------*/
11372 /* genNearPointerSet - emitcode for near pointer put */
11373 /*-----------------------------------------------------------------*/
11375 genNearPointerSet (operand * right,
11382 sym_link *retype, *letype;
11383 sym_link *ptype = operandType (result);
11385 D (emitcode (";", "genNearPointerSet"));
11387 retype = getSpec (operandType (right));
11388 letype = getSpec (ptype);
11390 aopOp (result, ic, FALSE, FALSE);
11392 /* if the result is rematerializable &
11393 in data space & not a bit variable */
11394 if (AOP_TYPE (result) == AOP_IMMD &&
11395 DCL_TYPE (ptype) == POINTER &&
11396 !IS_BITVAR (retype) &&
11397 !IS_BITVAR (letype))
11399 genDataPointerSet (right, result, ic);
11403 /* if the value is already in a pointer register
11404 then don't need anything more */
11405 if (!AOP_INPREG (AOP (result)))
11407 /* otherwise get a free pointer register */
11410 aop = newAsmop (0);
11411 preg = getFreePtr (ic, &aop, FALSE);
11412 emitcode ("mov", "%s,%s",
11414 aopGet (result, 0, FALSE, TRUE, NULL));
11415 rname = preg->name;
11419 rname = aopGet (result, 0, FALSE, FALSE, NULL);
11422 aopOp (right, ic, FALSE, FALSE);
11424 /* if bitfield then unpack the bits */
11425 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11426 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
11429 /* we can just get the values */
11430 int size = AOP_SIZE (right);
11435 l = aopGet (right, offset, FALSE, TRUE, NULL);
11436 if ((*l == '@') || (strcmp (l, "acc") == 0))
11439 emitcode ("mov", "@%s,a", rname);
11442 emitcode ("mov", "@%s,%s", rname, l);
11444 emitcode ("inc", "%s", rname);
11449 /* now some housekeeping stuff */
11450 if (aop) /* we had to allocate for this iCode */
11453 aopPut (result, rname, 0);
11454 freeAsmop (NULL, aop, ic, TRUE);
11458 /* we did not allocate which means left
11459 already in a pointer register, then
11460 if size > 0 && this could be used again
11461 we have to point it back to where it
11463 if (AOP_SIZE (right) > 1 &&
11464 !OP_SYMBOL (result)->remat &&
11465 (OP_SYMBOL (result)->liveTo > ic->seq ||
11469 int size = AOP_SIZE (right) - 1;
11471 emitcode ("dec", "%s", rname);
11478 freeAsmop (right, NULL, ic, TRUE);
11479 freeAsmop (result, NULL, ic, TRUE);
11482 /*-----------------------------------------------------------------*/
11483 /* genPagedPointerSet - emitcode for Paged pointer put */
11484 /*-----------------------------------------------------------------*/
11486 genPagedPointerSet (operand * right,
11493 sym_link *retype, *letype;
11495 D (emitcode (";", "genPagedPointerSet"));
11497 retype = getSpec (operandType (right));
11498 letype = getSpec (operandType (result));
11500 aopOp (result, ic, FALSE, FALSE);
11502 /* if the value is already in a pointer register
11503 then don't need anything more */
11504 if (!AOP_INPREG (AOP (result)))
11506 /* otherwise get a free pointer register */
11509 aop = newAsmop (0);
11510 preg = getFreePtr (ic, &aop, FALSE);
11511 emitcode ("mov", "%s,%s",
11513 aopGet (result, 0, FALSE, TRUE, NULL));
11514 rname = preg->name;
11518 rname = aopGet (result, 0, FALSE, FALSE, NULL);
11521 aopOp (right, ic, FALSE, FALSE);
11523 /* if bitfield then unpack the bits */
11524 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11525 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
11528 /* we can just get the values */
11529 int size = AOP_SIZE (right);
11534 l = aopGet (right, offset, FALSE, TRUE, NULL);
11536 emitcode ("movx", "@%s,a", rname);
11538 emitcode ("inc", "%s", rname);
11543 /* now some housekeeping stuff */
11547 aopPut (result, rname, 0);
11548 /* we had to allocate for this iCode */
11549 freeAsmop (NULL, aop, ic, TRUE);
11553 /* we did not allocate which means left
11554 already in a pointer register, then
11555 if size > 0 && this could be used again
11556 we have to point it back to where it
11558 if (AOP_SIZE (right) > 1 &&
11559 !OP_SYMBOL (result)->remat &&
11560 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth) &&
11563 int size = AOP_SIZE (right) - 1;
11565 emitcode ("dec", "%s", rname);
11572 freeAsmop (right, NULL, ic, TRUE);
11573 freeAsmop (result, NULL, ic, TRUE);
11576 /*-----------------------------------------------------------------*/
11577 /* genFarPointerSet - set value from far space */
11578 /*-----------------------------------------------------------------*/
11580 genFarPointerSet (operand * right,
11581 operand * result, iCode * ic, iCode *pi)
11583 int size, offset, dopi=1;
11584 sym_link *retype = getSpec (operandType (right));
11585 sym_link *letype = getSpec (operandType (result));
11587 aopOp (result, ic, FALSE, FALSE);
11589 /* if the operand is already in dptr
11590 then we do nothing else we move the value to dptr */
11591 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
11593 /* if this is remateriazable */
11594 if (AOP_TYPE (result) == AOP_IMMD)
11595 emitcode ("mov", "dptr,%s",
11596 aopGet (result, 0, TRUE, FALSE, NULL));
11599 /* we need to get it byte by byte */
11600 _startLazyDPSEvaluation ();
11601 if (AOP_TYPE (result) != AOP_DPTR)
11603 emitcode ("mov", "dpl,%s", aopGet (result, 0, FALSE, FALSE, NULL));
11604 emitcode ("mov", "dph,%s", aopGet (result, 1, FALSE, FALSE, NULL));
11605 if (options.model == MODEL_FLAT24)
11606 emitcode ("mov", "dpx,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11610 /* We need to generate a load to DPTR indirect through DPTR. */
11611 D (emitcode (";", "genFarPointerSet -- indirection special case."););
11613 emitcode ("push", "%s", aopGet (result, 0, FALSE, TRUE, NULL));
11614 emitcode ("push", "%s", aopGet (result, 1, FALSE, TRUE, NULL));
11615 if (options.model == MODEL_FLAT24)
11616 emitcode ("mov", "dpx,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11617 emitcode ("pop", "dph");
11618 emitcode ("pop", "dpl");
11621 _endLazyDPSEvaluation ();
11624 /* so dptr now contains the address */
11625 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
11627 /* if bit then unpack */
11628 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11630 if (AOP_INDPTRn(result)) {
11631 genSetDPTR(AOP(result)->aopu.dptr);
11633 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
11634 if (AOP_INDPTRn(result)) {
11638 size = AOP_SIZE (right);
11640 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
11642 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11644 genSetDPTR(AOP(result)->aopu.dptr);
11645 emitcode ("movx", "@dptr,a");
11646 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
11647 emitcode ("inc", "dptr");
11651 _startLazyDPSEvaluation ();
11653 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11655 if (AOP_INDPTRn(result)) {
11656 genSetDPTR(AOP(result)->aopu.dptr);
11662 emitcode ("movx", "@dptr,a");
11663 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
11664 emitcode ("inc", "dptr");
11666 _endLazyDPSEvaluation ();
11670 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
11671 if (!AOP_INDPTRn(result)) {
11672 _startLazyDPSEvaluation ();
11674 aopPut (result,"dpl",0);
11675 aopPut (result,"dph",1);
11676 if (options.model == MODEL_FLAT24)
11677 aopPut (result,"dpx",2);
11679 _endLazyDPSEvaluation ();
11682 } else if (IS_SYMOP (result) &&
11683 (OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
11684 AOP_SIZE(right) > 1 &&
11685 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
11687 size = AOP_SIZE (right) - 1;
11688 if (AOP_INDPTRn(result)) {
11689 genSetDPTR(AOP(result)->aopu.dptr);
11691 while (size--) emitcode ("lcall","__decdptr");
11692 if (AOP_INDPTRn(result)) {
11696 freeAsmop (result, NULL, ic, TRUE);
11697 freeAsmop (right, NULL, ic, TRUE);
11700 /*-----------------------------------------------------------------*/
11701 /* genGenPointerSet - set value from generic pointer space */
11702 /*-----------------------------------------------------------------*/
11704 genGenPointerSet (operand * right,
11705 operand * result, iCode * ic, iCode * pi)
11709 sym_link *retype = getSpec (operandType (right));
11710 sym_link *letype = getSpec (operandType (result));
11712 aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
11714 pushedB = pushB ();
11715 /* if the operand is already in dptr
11716 then we do nothing else we move the value to dptr */
11717 if (AOP_TYPE (result) != AOP_STR)
11719 _startLazyDPSEvaluation ();
11720 /* if this is remateriazable */
11721 if (AOP_TYPE (result) == AOP_IMMD)
11723 emitcode ("mov", "dptr,%s", aopGet (result, 0, TRUE, FALSE, NULL));
11724 if (AOP(result)->aopu.aop_immd.from_cast_remat)
11726 MOVB (aopGet (result, AOP_SIZE(result)-1, FALSE, FALSE, NULL));
11731 "b,%s + 1", aopGet (result, 0, TRUE, FALSE, NULL));
11735 { /* we need to get it byte by byte */
11736 emitcode ("mov", "dpl,%s", aopGet (result, 0, FALSE, FALSE, NULL));
11737 emitcode ("mov", "dph,%s", aopGet (result, 1, FALSE, FALSE, NULL));
11738 if (options.model == MODEL_FLAT24) {
11739 emitcode ("mov", "dpx,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11740 emitcode ("mov", "b,%s", aopGet (result, 3, FALSE, FALSE, NULL));
11742 emitcode ("mov", "b,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11745 _endLazyDPSEvaluation ();
11747 /* so dptr + b now contains the address */
11748 aopOp (right, ic, FALSE, TRUE);
11750 /* if bit then unpack */
11751 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11753 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
11757 size = AOP_SIZE (right);
11760 _startLazyDPSEvaluation ();
11765 // Set two bytes at a time, passed in _AP & A.
11766 // dptr will be incremented ONCE by __gptrputWord.
11768 // Note: any change here must be coordinated
11769 // with the implementation of __gptrputWord
11770 // in device/lib/_gptrput.c
11771 emitcode("mov", "_ap, %s",
11772 aopGet (right, offset++, FALSE, FALSE, NULL));
11773 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11777 emitcode ("lcall", "__gptrputWord");
11782 // Only one byte to put.
11783 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11787 emitcode ("lcall", "__gptrput");
11790 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
11792 emitcode ("inc", "dptr");
11795 _endLazyDPSEvaluation ();
11798 if (pi && AOP_TYPE (result) != AOP_IMMD) {
11799 _startLazyDPSEvaluation ();
11801 aopPut (result, "dpl",0);
11802 aopPut (result, "dph",1);
11803 if (options.model == MODEL_FLAT24) {
11804 aopPut (result, "dpx",2);
11805 aopPut (result, "b",3);
11807 aopPut (result, "b",2);
11809 _endLazyDPSEvaluation ();
11812 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
11813 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
11815 size = AOP_SIZE (right) - 1;
11816 while (size--) emitcode ("lcall","__decdptr");
11820 freeAsmop (result, NULL, ic, TRUE);
11821 freeAsmop (right, NULL, ic, TRUE);
11824 /*-----------------------------------------------------------------*/
11825 /* genPointerSet - stores the value into a pointer location */
11826 /*-----------------------------------------------------------------*/
11828 genPointerSet (iCode * ic, iCode *pi)
11830 operand *right, *result;
11831 sym_link *type, *etype;
11834 D (emitcode (";", "genPointerSet"));
11836 right = IC_RIGHT (ic);
11837 result = IC_RESULT (ic);
11839 /* depending on the type of pointer we need to
11840 move it to the correct pointer register */
11841 type = operandType (result);
11842 etype = getSpec (type);
11843 /* if left is of type of pointer then it is simple */
11844 if (IS_PTR (type) && !IS_FUNC (type->next))
11846 p_type = DCL_TYPE (type);
11850 /* we have to go by the storage class */
11851 p_type = PTR_TYPE (SPEC_OCLS (etype));
11854 /* special case when cast remat */
11855 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
11856 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
11857 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
11858 type = operandType (result);
11859 p_type = DCL_TYPE (type);
11862 /* now that we have the pointer type we assign
11863 the pointer values */
11869 genNearPointerSet (right, result, ic, pi);
11873 genPagedPointerSet (right, result, ic, pi);
11877 genFarPointerSet (right, result, ic, pi);
11881 genGenPointerSet (right, result, ic, pi);
11885 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11886 "genPointerSet: illegal pointer type");
11890 /*-----------------------------------------------------------------*/
11891 /* genIfx - generate code for Ifx statement */
11892 /*-----------------------------------------------------------------*/
11894 genIfx (iCode * ic, iCode * popIc)
11896 operand *cond = IC_COND (ic);
11900 D (emitcode (";", "genIfx"));
11902 aopOp (cond, ic, FALSE, FALSE);
11904 /* get the value into acc */
11905 if (AOP_TYPE (cond) != AOP_CRY)
11912 if (AOP(cond)->aopu.aop_dir)
11913 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
11916 /* the result is now in the accumulator or a directly addressable bit */
11917 freeAsmop (cond, NULL, ic, TRUE);
11919 /* if the condition is a bit variable */
11921 genIfxJump (ic, dup, popIc);
11922 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
11923 genIfxJump (ic, SPIL_LOC (cond)->rname, popIc);
11924 else if (isbit && !IS_ITEMP (cond))
11925 genIfxJump (ic, OP_SYMBOL (cond)->rname, popIc);
11927 genIfxJump (ic, "a", popIc);
11932 /*-----------------------------------------------------------------*/
11933 /* genAddrOf - generates code for address of */
11934 /*-----------------------------------------------------------------*/
11936 genAddrOf (iCode * ic)
11938 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
11941 D (emitcode (";", "genAddrOf"));
11943 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11945 /* if the operand is on the stack then we
11946 need to get the stack offset of this
11950 /* if 10 bit stack */
11951 if (options.stack10bit) {
11955 tsprintf(buff, sizeof(buff),
11956 "#!constbyte",(options.stack_loc >> 16) & 0xff);
11957 /* if it has an offset then we need to compute it */
11958 /* emitcode ("subb", "a,#!constbyte", */
11959 /* -((sym->stack < 0) ? */
11960 /* ((short) (sym->stack - _G.nRegsSaved)) : */
11961 /* ((short) sym->stack)) & 0xff); */
11962 /* emitcode ("mov","b,a"); */
11963 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
11964 /* ((short) (sym->stack - _G.nRegsSaved)) : */
11965 /* ((short) sym->stack)) >> 8) & 0xff); */
11967 emitcode ("mov", "a,_bpx");
11968 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
11969 ((char) (sym->stack - _G.nRegsSaved)) :
11970 ((char) sym->stack )) & 0xff);
11971 emitcode ("mov", "b,a");
11972 emitcode ("mov", "a,_bpx+1");
11974 offset = (((sym->stack < 0) ?
11975 ((short) (sym->stack - _G.nRegsSaved)) :
11976 ((short) sym->stack )) >> 8) & 0xff;
11978 emitcode ("addc","a,#!constbyte", offset);
11980 aopPut (IC_RESULT (ic), "b", 0);
11981 aopPut (IC_RESULT (ic), "a", 1);
11982 aopPut (IC_RESULT (ic), buff, 2);
11984 /* we can just move _bp */
11985 aopPut (IC_RESULT (ic), "_bpx", 0);
11986 aopPut (IC_RESULT (ic), "_bpx+1", 1);
11987 aopPut (IC_RESULT (ic), buff, 2);
11990 /* if it has an offset then we need to compute it */
11993 emitcode ("mov", "a,_bp");
11994 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
11995 aopPut (IC_RESULT (ic), "a", 0);
11999 /* we can just move _bp */
12000 aopPut (IC_RESULT (ic), "_bp", 0);
12002 /* fill the result with zero */
12003 size = AOP_SIZE (IC_RESULT (ic)) - 1;
12006 if (options.stack10bit && size < (FPTRSIZE - 1)) {
12008 "*** warning: pointer to stack var truncated.\n");
12014 aopPut (IC_RESULT (ic), zero, offset++);
12020 /* object not on stack then we need the name */
12021 size = getDataSize (IC_RESULT (ic));
12026 char s[SDCC_NAME_MAX];
12031 tsprintf(s, sizeof(s), "#!his",sym->rname);
12034 tsprintf(s, sizeof(s), "#!hihis",sym->rname);
12037 tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
12039 default: /* should not need this (just in case) */
12040 SNPRINTF (s, sizeof(s), "#(%s >> %d)", sym->rname, offset * 8);
12045 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
12047 aopPut (IC_RESULT (ic), s, offset++);
12049 if (opIsGptr (IC_RESULT (ic)))
12052 SNPRINTF (buffer, sizeof(buffer), "#0x%02x",
12053 pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
12054 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
12058 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
12062 #if 0 // obsolete, and buggy for != xdata
12063 /*-----------------------------------------------------------------*/
12064 /* genArrayInit - generates code for address of */
12065 /*-----------------------------------------------------------------*/
12067 genArrayInit (iCode * ic)
12069 literalList *iLoop;
12071 int elementSize = 0, eIndex;
12072 unsigned val, lastVal;
12074 operand *left=IC_LEFT(ic);
12076 D (emitcode (";", "genArrayInit"));
12078 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
12080 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
12082 // Load immediate value into DPTR.
12083 emitcode("mov", "dptr, %s",
12084 aopGet (IC_LEFT(ic), 0, TRUE, FALSE, NULL));
12086 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
12089 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12090 "Unexpected operand to genArrayInit.\n");
12093 // a regression because of SDCCcse.c:1.52
12094 emitcode ("mov", "dpl,%s", aopGet (left, 0, FALSE, FALSE, NULL));
12095 emitcode ("mov", "dph,%s", aopGet (left, 1, FALSE, FALSE, NULL));
12096 if (options.model == MODEL_FLAT24)
12097 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
12101 type = operandType(IC_LEFT(ic));
12103 if (type && type->next)
12105 elementSize = getSize(type->next);
12109 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12110 "can't determine element size in genArrayInit.\n");
12114 iLoop = IC_ARRAYILIST(ic);
12119 bool firstpass = TRUE;
12121 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
12122 iLoop->count, (int)iLoop->literalValue, elementSize);
12128 symbol *tlbl = NULL;
12130 count = ix > 256 ? 256 : ix;
12134 tlbl = newiTempLabel (NULL);
12135 if (firstpass || (count & 0xff))
12137 emitcode("mov", "b, #!constbyte", count & 0xff);
12145 for (eIndex = 0; eIndex < elementSize; eIndex++)
12147 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
12148 if (val != lastVal)
12150 emitcode("mov", "a, #!constbyte", val);
12154 emitcode("movx", "@dptr, a");
12155 emitcode("inc", "dptr");
12160 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
12166 iLoop = iLoop->next;
12169 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
12173 /*-----------------------------------------------------------------*/
12174 /* genFarFarAssign - assignment when both are in far space */
12175 /*-----------------------------------------------------------------*/
12177 genFarFarAssign (operand * result, operand * right, iCode * ic)
12179 int size = AOP_SIZE (right);
12181 symbol *rSym = NULL;
12185 /* quick & easy case. */
12186 D (emitcode(";","genFarFarAssign (1 byte case)"));
12187 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
12188 freeAsmop (right, NULL, ic, FALSE);
12189 /* now assign DPTR to result */
12191 aopOp(result, ic, FALSE, FALSE);
12193 aopPut (result, "a", 0);
12194 freeAsmop(result, NULL, ic, FALSE);
12198 /* See if we've got an underlying symbol to abuse. */
12199 if (IS_SYMOP(result) && OP_SYMBOL(result))
12201 if (IS_TRUE_SYMOP(result))
12203 rSym = OP_SYMBOL(result);
12205 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
12207 rSym = OP_SYMBOL(result)->usl.spillLoc;
12211 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
12213 /* We can use the '390 auto-toggle feature to good effect here. */
12215 D (emitcode(";", "genFarFarAssign (390 auto-toggle fun)"));
12216 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12217 emitcode ("mov", "dptr,#%s", rSym->rname);
12218 /* DP2 = result, DP1 = right, DP1 is current. */
12221 emitcode("movx", "a,@dptr");
12222 emitcode("movx", "@dptr,a");
12225 emitcode("inc", "dptr");
12226 emitcode("inc", "dptr");
12229 emitcode("mov", "dps,#0");
12230 freeAsmop (right, NULL, ic, FALSE);
12232 some alternative code for processors without auto-toggle
12233 no time to test now, so later well put in...kpb
12234 D (emitcode(";", "genFarFarAssign (dual-dptr fun)"));
12235 emitcode("mov", "dps,#1"); /* Select DPTR2. */
12236 emitcode ("mov", "dptr,#%s", rSym->rname);
12237 /* DP2 = result, DP1 = right, DP1 is current. */
12241 emitcode("movx", "a,@dptr");
12243 emitcode("inc", "dptr");
12244 emitcode("inc", "dps");
12245 emitcode("movx", "@dptr,a");
12247 emitcode("inc", "dptr");
12248 emitcode("inc", "dps");
12250 emitcode("mov", "dps,#0");
12251 freeAsmop (right, NULL, ic, FALSE);
12256 D (emitcode (";", "genFarFarAssign"));
12257 aopOp (result, ic, TRUE, TRUE);
12259 _startLazyDPSEvaluation ();
12264 aopGet (right, offset, FALSE, FALSE, NULL), offset);
12267 _endLazyDPSEvaluation ();
12268 freeAsmop (result, NULL, ic, FALSE);
12269 freeAsmop (right, NULL, ic, FALSE);
12273 /*-----------------------------------------------------------------*/
12274 /* genAssign - generate code for assignment */
12275 /*-----------------------------------------------------------------*/
12277 genAssign (iCode * ic)
12279 operand *result, *right;
12281 unsigned long lit = 0L;
12283 D (emitcode (";", "genAssign"));
12285 result = IC_RESULT (ic);
12286 right = IC_RIGHT (ic);
12288 /* if they are the same */
12289 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
12292 aopOp (right, ic, FALSE, FALSE);
12294 emitcode (";", "genAssign: resultIsFar = %s",
12295 isOperandInFarSpace (result) ?
12298 /* special case both in far space */
12299 if ((AOP_TYPE (right) == AOP_DPTR ||
12300 AOP_TYPE (right) == AOP_DPTR2) &&
12301 /* IS_TRUE_SYMOP(result) && */
12302 isOperandInFarSpace (result))
12304 genFarFarAssign (result, right, ic);
12308 aopOp (result, ic, TRUE, FALSE);
12310 /* if they are the same registers */
12311 if (sameRegs (AOP (right), AOP (result)))
12314 /* if the result is a bit */
12315 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
12317 /* if the right size is a literal then
12318 we know what the value is */
12319 if (AOP_TYPE (right) == AOP_LIT)
12321 if (((int) operandLitValue (right)))
12322 aopPut (result, one, 0);
12324 aopPut (result, zero, 0);
12328 /* the right is also a bit variable */
12329 if (AOP_TYPE (right) == AOP_CRY)
12331 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
12332 aopPut (result, "c", 0);
12336 /* we need to or */
12338 aopPut (result, "a", 0);
12342 /* bit variables done */
12344 size = getDataSize (result);
12346 if (AOP_TYPE (right) == AOP_LIT)
12347 lit = ulFromVal (AOP (right)->aopu.aop_lit);
12350 (AOP_TYPE (result) != AOP_REG) &&
12351 (AOP_TYPE (right) == AOP_LIT) &&
12352 !IS_FLOAT (operandType (right)))
12354 _startLazyDPSEvaluation ();
12355 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
12358 aopGet (right, offset, FALSE, FALSE, NULL),
12363 /* And now fill the rest with zeros. */
12366 emitcode ("clr", "a");
12370 aopPut (result, "a", offset++);
12372 _endLazyDPSEvaluation ();
12376 _startLazyDPSEvaluation ();
12380 aopGet (right, offset, FALSE, FALSE, NULL),
12384 _endLazyDPSEvaluation ();
12386 adjustArithmeticResult (ic);
12389 freeAsmop (result, NULL, ic, TRUE);
12390 freeAsmop (right, NULL, ic, TRUE);
12393 /*-----------------------------------------------------------------*/
12394 /* genJumpTab - generates code for jump table */
12395 /*-----------------------------------------------------------------*/
12397 genJumpTab (iCode * ic)
12402 D (emitcode (";", "genJumpTab"));
12404 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
12405 /* get the condition into accumulator */
12406 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE, NULL);
12408 /* multiply by four! */
12409 emitcode ("add", "a,acc");
12410 emitcode ("add", "a,acc");
12411 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
12413 jtab = newiTempLabel (NULL);
12414 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
12415 emitcode ("jmp", "@a+dptr");
12417 /* now generate the jump labels */
12418 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
12419 jtab = setNextItem (IC_JTLABELS (ic)))
12420 emitcode ("ljmp", "!tlabel", jtab->key + 100);
12424 /*-----------------------------------------------------------------*/
12425 /* genCast - gen code for casting */
12426 /*-----------------------------------------------------------------*/
12428 genCast (iCode * ic)
12430 operand *result = IC_RESULT (ic);
12431 sym_link *ctype = operandType (IC_LEFT (ic));
12432 sym_link *rtype = operandType (IC_RIGHT (ic));
12433 operand *right = IC_RIGHT (ic);
12436 D (emitcode (";", "genCast"));
12438 /* if they are equivalent then do nothing */
12439 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
12442 aopOp (right, ic, FALSE, AOP_IS_STR (result));
12443 aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR));
12445 /* if the result is a bit (and not a bitfield) */
12446 if (IS_BIT (OP_SYMBOL (result)->type))
12448 /* if the right size is a literal then
12449 we know what the value is */
12450 if (AOP_TYPE (right) == AOP_LIT)
12452 if (((int) operandLitValue (right)))
12453 aopPut (result, one, 0);
12455 aopPut (result, zero, 0);
12460 /* the right is also a bit variable */
12461 if (AOP_TYPE (right) == AOP_CRY)
12463 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
12464 aopPut (result, "c", 0);
12468 /* we need to or */
12470 aopPut (result, "a", 0);
12474 /* if they are the same size : or less */
12475 if (AOP_SIZE (result) <= AOP_SIZE (right))
12478 /* if they are in the same place */
12479 if (sameRegs (AOP (right), AOP (result)))
12482 /* if they in different places then copy */
12483 size = AOP_SIZE (result);
12485 _startLazyDPSEvaluation ();
12489 aopGet (right, offset, FALSE, FALSE, NULL),
12493 _endLazyDPSEvaluation ();
12497 /* if the result is of type pointer */
12498 if (IS_PTR (ctype))
12502 sym_link *type = operandType (right);
12504 /* pointer to generic pointer */
12505 if (IS_GENPTR (ctype))
12509 p_type = DCL_TYPE (type);
12513 #if OLD_CAST_BEHAVIOR
12514 /* KV: we are converting a non-pointer type to
12515 * a generic pointer. This (ifdef'd out) code
12516 * says that the resulting generic pointer
12517 * should have the same class as the storage
12518 * location of the non-pointer variable.
12520 * For example, converting an int (which happens
12521 * to be stored in DATA space) to a pointer results
12522 * in a DATA generic pointer; if the original int
12523 * in XDATA space, so will be the resulting pointer.
12525 * I don't like that behavior, and thus this change:
12526 * all such conversions will be forced to XDATA and
12527 * throw a warning. If you want some non-XDATA
12528 * type, or you want to suppress the warning, you
12529 * must go through an intermediate cast, like so:
12531 * char _generic *gp = (char _xdata *)(intVar);
12533 sym_link *etype = getSpec (type);
12535 /* we have to go by the storage class */
12536 if (SPEC_OCLS (etype) != generic)
12538 p_type = PTR_TYPE (SPEC_OCLS (etype));
12543 /* Converting unknown class (i.e. register variable)
12544 * to generic pointer. This is not good, but
12545 * we'll make a guess (and throw a warning).
12548 werror (W_INT_TO_GEN_PTR_CAST);
12552 /* the first two bytes are known */
12553 size = GPTRSIZE - 1;
12555 _startLazyDPSEvaluation ();
12559 aopGet (right, offset, FALSE, FALSE, NULL),
12563 _endLazyDPSEvaluation ();
12565 /* the last byte depending on type */
12567 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
12572 // pointerTypeToGPByte will have bitched.
12576 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%x", gpVal);
12577 aopPut (result, gpValStr, GPTRSIZE - 1);
12582 /* just copy the pointers */
12583 size = AOP_SIZE (result);
12585 _startLazyDPSEvaluation ();
12589 aopGet (right, offset, FALSE, FALSE, NULL),
12593 _endLazyDPSEvaluation ();
12597 /* so we now know that the size of destination is greater
12598 than the size of the source */
12599 /* we move to result for the size of source */
12600 size = AOP_SIZE (right);
12602 _startLazyDPSEvaluation ();
12606 aopGet (right, offset, FALSE, FALSE, NULL),
12610 _endLazyDPSEvaluation ();
12612 /* now depending on the sign of the source && destination */
12613 size = AOP_SIZE (result) - AOP_SIZE (right);
12614 /* if unsigned or not an integral type */
12615 /* also, if the source is a bit, we don't need to sign extend, because
12616 * it can't possibly have set the sign bit.
12618 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
12622 aopPut (result, zero, offset++);
12627 /* we need to extend the sign :{ */
12628 MOVA (aopGet (right, AOP_SIZE (right) - 1,
12629 FALSE, FALSE, NULL));
12630 emitcode ("rlc", "a");
12631 emitcode ("subb", "a,acc");
12633 aopPut (result, "a", offset++);
12636 /* we are done hurray !!!! */
12639 freeAsmop (right, NULL, ic, TRUE);
12640 freeAsmop (result, NULL, ic, TRUE);
12644 /*-----------------------------------------------------------------*/
12645 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
12646 /*-----------------------------------------------------------------*/
12647 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
12649 operand *from , *to , *count;
12654 /* we know it has to be 3 parameters */
12655 assert (nparms == 3);
12657 rsave = newBitVect(16);
12658 /* save DPTR if it needs to be saved */
12659 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12660 if (bitVectBitValue(ic->rMask,i))
12661 rsave = bitVectSetBit(rsave,i);
12663 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12664 ds390_rUmaskForOp (IC_RESULT(ic))));
12671 aopOp (from, ic->next, FALSE, FALSE);
12673 /* get from into DPTR1 */
12674 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12675 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12676 if (options.model == MODEL_FLAT24) {
12677 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12680 freeAsmop (from, NULL, ic, FALSE);
12681 aopOp (to, ic, FALSE, FALSE);
12682 /* get "to" into DPTR */
12683 /* if the operand is already in dptr
12684 then we do nothing else we move the value to dptr */
12685 if (AOP_TYPE (to) != AOP_STR) {
12686 /* if already in DPTR then we need to push */
12687 if (AOP_TYPE(to) == AOP_DPTR) {
12688 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12689 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12690 if (options.model == MODEL_FLAT24)
12691 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12692 emitcode ("pop", "dph");
12693 emitcode ("pop", "dpl");
12695 _startLazyDPSEvaluation ();
12696 /* if this is remateriazable */
12697 if (AOP_TYPE (to) == AOP_IMMD) {
12698 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12699 } else { /* we need to get it byte by byte */
12700 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12701 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12702 if (options.model == MODEL_FLAT24) {
12703 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12706 _endLazyDPSEvaluation ();
12709 freeAsmop (to, NULL, ic, FALSE);
12710 _G.dptrInUse = _G.dptr1InUse = 1;
12711 aopOp (count, ic->next->next, FALSE,FALSE);
12712 lbl =newiTempLabel(NULL);
12714 /* now for the actual copy */
12715 if (AOP_TYPE(count) == AOP_LIT &&
12716 (int) ulFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12717 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12719 emitcode ("lcall","__bi_memcpyc2x_s");
12721 emitcode ("lcall","__bi_memcpyx2x_s");
12723 freeAsmop (count, NULL, ic, FALSE);
12725 symbol *lbl1 = newiTempLabel(NULL);
12727 emitcode (";"," Auto increment but no djnz");
12728 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
12729 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
12730 freeAsmop (count, NULL, ic, FALSE);
12731 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12734 emitcode ("clr","a");
12735 emitcode ("movc", "a,@a+dptr");
12737 emitcode ("movx", "a,@dptr");
12738 emitcode ("movx", "@dptr,a");
12739 emitcode ("inc", "dptr");
12740 emitcode ("inc", "dptr");
12741 emitcode ("mov","a,b");
12742 emitcode ("orl","a,_ap");
12743 emitcode ("jz","!tlabel",lbl1->key+100);
12744 emitcode ("mov","a,_ap");
12745 emitcode ("add","a,#!constbyte",0xFF);
12746 emitcode ("mov","_ap,a");
12747 emitcode ("mov","a,b");
12748 emitcode ("addc","a,#!constbyte",0xFF);
12749 emitcode ("mov","b,a");
12750 emitcode ("sjmp","!tlabel",lbl->key+100);
12753 emitcode ("mov", "dps,#0");
12754 _G.dptrInUse = _G.dptr1InUse = 0;
12755 unsavermask(rsave);
12759 /*-----------------------------------------------------------------*/
12760 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
12761 /*-----------------------------------------------------------------*/
12762 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
12764 operand *from , *to , *count;
12769 /* we know it has to be 3 parameters */
12770 assert (nparms == 3);
12772 rsave = newBitVect(16);
12773 /* save DPTR if it needs to be saved */
12774 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12775 if (bitVectBitValue(ic->rMask,i))
12776 rsave = bitVectSetBit(rsave,i);
12778 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12779 ds390_rUmaskForOp (IC_RESULT(ic))));
12786 aopOp (from, ic->next, FALSE, FALSE);
12788 /* get from into DPTR1 */
12789 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12790 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12791 if (options.model == MODEL_FLAT24) {
12792 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12795 freeAsmop (from, NULL, ic, FALSE);
12796 aopOp (to, ic, FALSE, FALSE);
12797 /* get "to" into DPTR */
12798 /* if the operand is already in dptr
12799 then we do nothing else we move the value to dptr */
12800 if (AOP_TYPE (to) != AOP_STR) {
12801 /* if already in DPTR then we need to push */
12802 if (AOP_TYPE(to) == AOP_DPTR) {
12803 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12804 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12805 if (options.model == MODEL_FLAT24)
12806 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12807 emitcode ("pop", "dph");
12808 emitcode ("pop", "dpl");
12810 _startLazyDPSEvaluation ();
12811 /* if this is remateriazable */
12812 if (AOP_TYPE (to) == AOP_IMMD) {
12813 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12814 } else { /* we need to get it byte by byte */
12815 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12816 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12817 if (options.model == MODEL_FLAT24) {
12818 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12821 _endLazyDPSEvaluation ();
12824 freeAsmop (to, NULL, ic, FALSE);
12825 _G.dptrInUse = _G.dptr1InUse = 1;
12826 aopOp (count, ic->next->next, FALSE,FALSE);
12827 lbl =newiTempLabel(NULL);
12828 lbl2 =newiTempLabel(NULL);
12830 /* now for the actual compare */
12831 if (AOP_TYPE(count) == AOP_LIT &&
12832 (int) ulFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12833 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12835 emitcode("lcall","__bi_memcmpc2x_s");
12837 emitcode("lcall","__bi_memcmpx2x_s");
12838 freeAsmop (count, NULL, ic, FALSE);
12839 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12840 aopPut(IC_RESULT(ic),"a",0);
12841 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12843 symbol *lbl1 = newiTempLabel(NULL);
12845 emitcode("push","ar0");
12846 emitcode (";"," Auto increment but no djnz");
12847 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
12848 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
12849 freeAsmop (count, NULL, ic, FALSE);
12850 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12853 emitcode ("clr","a");
12854 emitcode ("movc", "a,@a+dptr");
12856 emitcode ("movx", "a,@dptr");
12857 emitcode ("mov","r0,a");
12858 emitcode ("movx", "a,@dptr");
12859 emitcode ("clr","c");
12860 emitcode ("subb","a,r0");
12861 emitcode ("jnz","!tlabel",lbl2->key+100);
12862 emitcode ("inc", "dptr");
12863 emitcode ("inc", "dptr");
12864 emitcode ("mov","a,b");
12865 emitcode ("orl","a,_ap");
12866 emitcode ("jz","!tlabel",lbl1->key+100);
12867 emitcode ("mov","a,_ap");
12868 emitcode ("add","a,#!constbyte",0xFF);
12869 emitcode ("mov","_ap,a");
12870 emitcode ("mov","a,b");
12871 emitcode ("addc","a,#!constbyte",0xFF);
12872 emitcode ("mov","b,a");
12873 emitcode ("sjmp","!tlabel",lbl->key+100);
12875 emitcode ("clr","a");
12877 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12878 aopPut(IC_RESULT(ic),"a",0);
12879 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12880 emitcode("pop","ar0");
12881 emitcode ("mov", "dps,#0");
12883 _G.dptrInUse = _G.dptr1InUse = 0;
12884 unsavermask(rsave);
12888 /*-----------------------------------------------------------------*/
12889 /* genInp - gen code for __builtin_inp read data from a mem mapped */
12890 /* port, first parameter output area second parameter pointer to */
12891 /* port third parameter count */
12892 /*-----------------------------------------------------------------*/
12893 static void genInp( iCode *ic, int nparms, operand **parms)
12895 operand *from , *to , *count;
12900 /* we know it has to be 3 parameters */
12901 assert (nparms == 3);
12903 rsave = newBitVect(16);
12904 /* save DPTR if it needs to be saved */
12905 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12906 if (bitVectBitValue(ic->rMask,i))
12907 rsave = bitVectSetBit(rsave,i);
12909 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12910 ds390_rUmaskForOp (IC_RESULT(ic))));
12917 aopOp (from, ic->next, FALSE, FALSE);
12919 /* get from into DPTR1 */
12920 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12921 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12922 if (options.model == MODEL_FLAT24) {
12923 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12926 freeAsmop (from, NULL, ic, FALSE);
12927 aopOp (to, ic, FALSE, FALSE);
12928 /* get "to" into DPTR */
12929 /* if the operand is already in dptr
12930 then we do nothing else we move the value to dptr */
12931 if (AOP_TYPE (to) != AOP_STR) {
12932 /* if already in DPTR then we need to push */
12933 if (AOP_TYPE(to) == AOP_DPTR) {
12934 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12935 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12936 if (options.model == MODEL_FLAT24)
12937 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12938 emitcode ("pop", "dph");
12939 emitcode ("pop", "dpl");
12941 _startLazyDPSEvaluation ();
12942 /* if this is remateriazable */
12943 if (AOP_TYPE (to) == AOP_IMMD) {
12944 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12945 } else { /* we need to get it byte by byte */
12946 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12947 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12948 if (options.model == MODEL_FLAT24) {
12949 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12952 _endLazyDPSEvaluation ();
12955 freeAsmop (to, NULL, ic, FALSE);
12957 _G.dptrInUse = _G.dptr1InUse = 1;
12958 aopOp (count, ic->next->next, FALSE,FALSE);
12959 lbl =newiTempLabel(NULL);
12961 /* now for the actual copy */
12962 if (AOP_TYPE(count) == AOP_LIT &&
12963 (int) ulFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12964 emitcode (";","OH JOY auto increment with djnz (very fast)");
12965 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
12966 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12967 freeAsmop (count, NULL, ic, FALSE);
12969 emitcode ("movx", "a,@dptr"); /* read data from port */
12970 emitcode ("dec","dps"); /* switch to DPTR */
12971 emitcode ("movx", "@dptr,a"); /* save into location */
12972 emitcode ("inc", "dptr"); /* point to next area */
12973 emitcode ("inc","dps"); /* switch to DPTR2 */
12974 emitcode ("djnz","b,!tlabel",lbl->key+100);
12976 symbol *lbl1 = newiTempLabel(NULL);
12978 emitcode (";"," Auto increment but no djnz");
12979 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
12980 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
12981 freeAsmop (count, NULL, ic, FALSE);
12982 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
12984 emitcode ("movx", "a,@dptr");
12985 emitcode ("dec","dps"); /* switch to DPTR */
12986 emitcode ("movx", "@dptr,a");
12987 emitcode ("inc", "dptr");
12988 emitcode ("inc","dps"); /* switch to DPTR2 */
12989 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
12990 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
12991 emitcode ("mov","a,b");
12992 emitcode ("orl","a,_ap");
12993 emitcode ("jz","!tlabel",lbl1->key+100);
12994 emitcode ("mov","a,_ap");
12995 emitcode ("add","a,#!constbyte",0xFF);
12996 emitcode ("mov","_ap,a");
12997 emitcode ("mov","a,b");
12998 emitcode ("addc","a,#!constbyte",0xFF);
12999 emitcode ("mov","b,a");
13000 emitcode ("sjmp","!tlabel",lbl->key+100);
13003 emitcode ("mov", "dps,#0");
13004 _G.dptrInUse = _G.dptr1InUse = 0;
13005 unsavermask(rsave);
13009 /*-----------------------------------------------------------------*/
13010 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
13011 /* port, first parameter output area second parameter pointer to */
13012 /* port third parameter count */
13013 /*-----------------------------------------------------------------*/
13014 static void genOutp( iCode *ic, int nparms, operand **parms)
13016 operand *from , *to , *count;
13021 /* we know it has to be 3 parameters */
13022 assert (nparms == 3);
13024 rsave = newBitVect(16);
13025 /* save DPTR if it needs to be saved */
13026 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
13027 if (bitVectBitValue(ic->rMask,i))
13028 rsave = bitVectSetBit(rsave,i);
13030 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
13031 ds390_rUmaskForOp (IC_RESULT(ic))));
13038 aopOp (from, ic->next, FALSE, FALSE);
13040 /* get from into DPTR1 */
13041 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
13042 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
13043 if (options.model == MODEL_FLAT24) {
13044 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
13047 freeAsmop (from, NULL, ic, FALSE);
13048 aopOp (to, ic, FALSE, FALSE);
13049 /* get "to" into DPTR */
13050 /* if the operand is already in dptr
13051 then we do nothing else we move the value to dptr */
13052 if (AOP_TYPE (to) != AOP_STR) {
13053 /* if already in DPTR then we need to push */
13054 if (AOP_TYPE(to) == AOP_DPTR) {
13055 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
13056 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
13057 if (options.model == MODEL_FLAT24)
13058 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
13059 emitcode ("pop", "dph");
13060 emitcode ("pop", "dpl");
13062 _startLazyDPSEvaluation ();
13063 /* if this is remateriazable */
13064 if (AOP_TYPE (to) == AOP_IMMD) {
13065 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
13066 } else { /* we need to get it byte by byte */
13067 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
13068 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
13069 if (options.model == MODEL_FLAT24) {
13070 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
13073 _endLazyDPSEvaluation ();
13076 freeAsmop (to, NULL, ic, FALSE);
13078 _G.dptrInUse = _G.dptr1InUse = 1;
13079 aopOp (count, ic->next->next, FALSE,FALSE);
13080 lbl =newiTempLabel(NULL);
13082 /* now for the actual copy */
13083 if (AOP_TYPE(count) == AOP_LIT &&
13084 (int) ulFromVal (AOP(count)->aopu.aop_lit) <= 256) {
13085 emitcode (";","OH JOY auto increment with djnz (very fast)");
13086 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
13087 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
13089 emitcode ("movx", "a,@dptr"); /* read data from port */
13090 emitcode ("inc","dps"); /* switch to DPTR2 */
13091 emitcode ("movx", "@dptr,a"); /* save into location */
13092 emitcode ("inc", "dptr"); /* point to next area */
13093 emitcode ("dec","dps"); /* switch to DPTR */
13094 emitcode ("djnz","b,!tlabel",lbl->key+100);
13095 freeAsmop (count, NULL, ic, FALSE);
13097 symbol *lbl1 = newiTempLabel(NULL);
13099 emitcode (";"," Auto increment but no djnz");
13100 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
13101 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
13102 freeAsmop (count, NULL, ic, FALSE);
13103 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
13105 emitcode ("movx", "a,@dptr");
13106 emitcode ("inc", "dptr");
13107 emitcode ("inc","dps"); /* switch to DPTR2 */
13108 emitcode ("movx", "@dptr,a");
13109 emitcode ("dec","dps"); /* switch to DPTR */
13110 emitcode ("mov","a,b");
13111 emitcode ("orl","a,_ap");
13112 emitcode ("jz","!tlabel",lbl1->key+100);
13113 emitcode ("mov","a,_ap");
13114 emitcode ("add","a,#!constbyte",0xFF);
13115 emitcode ("mov","_ap,a");
13116 emitcode ("mov","a,b");
13117 emitcode ("addc","a,#!constbyte",0xFF);
13118 emitcode ("mov","b,a");
13119 emitcode ("sjmp","!tlabel",lbl->key+100);
13122 emitcode ("mov", "dps,#0");
13123 _G.dptrInUse = _G.dptr1InUse = 0;
13124 unsavermask(rsave);
13128 /*-----------------------------------------------------------------*/
13129 /* genSwapW - swap lower & high order bytes */
13130 /*-----------------------------------------------------------------*/
13131 static void genSwapW(iCode *ic, int nparms, operand **parms)
13135 assert (nparms==1);
13138 dest=IC_RESULT(ic);
13140 assert(getSize(operandType(src))==2);
13142 aopOp (src, ic, FALSE, FALSE);
13143 emitcode ("mov","a,%s",aopGet(src,0,FALSE,FALSE,NULL));
13145 MOVB(aopGet(src,1,FALSE,FALSE,"b"));
13147 freeAsmop (src, NULL, ic, FALSE);
13149 aopOp (dest,ic, FALSE, FALSE);
13150 aopPut(dest,"b",0);
13151 aopPut(dest,"a",1);
13152 freeAsmop (dest, NULL, ic, FALSE);
13155 /*-----------------------------------------------------------------*/
13156 /* genMemsetX - gencode for memSetX data */
13157 /*-----------------------------------------------------------------*/
13158 static void genMemsetX(iCode *ic, int nparms, operand **parms)
13160 operand *to , *val , *count;
13166 /* we know it has to be 3 parameters */
13167 assert (nparms == 3);
13173 /* save DPTR if it needs to be saved */
13174 rsave = newBitVect(16);
13175 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
13176 if (bitVectBitValue(ic->rMask,i))
13177 rsave = bitVectSetBit(rsave,i);
13179 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
13180 ds390_rUmaskForOp (IC_RESULT(ic))));
13183 aopOp (to, ic, FALSE, FALSE);
13184 /* get "to" into DPTR */
13185 /* if the operand is already in dptr
13186 then we do nothing else we move the value to dptr */
13187 if (AOP_TYPE (to) != AOP_STR) {
13188 /* if already in DPTR then we need to push */
13189 if (AOP_TYPE(to) == AOP_DPTR) {
13190 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
13191 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
13192 if (options.model == MODEL_FLAT24)
13193 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
13194 emitcode ("pop", "dph");
13195 emitcode ("pop", "dpl");
13197 _startLazyDPSEvaluation ();
13198 /* if this is remateriazable */
13199 if (AOP_TYPE (to) == AOP_IMMD) {
13200 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
13201 } else { /* we need to get it byte by byte */
13202 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
13203 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
13204 if (options.model == MODEL_FLAT24) {
13205 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
13208 _endLazyDPSEvaluation ();
13211 freeAsmop (to, NULL, ic, FALSE);
13213 aopOp (val, ic->next->next, FALSE,FALSE);
13214 aopOp (count, ic->next->next, FALSE,FALSE);
13215 lbl =newiTempLabel(NULL);
13216 /* now for the actual copy */
13217 if (AOP_TYPE(count) == AOP_LIT &&
13218 (int) ulFromVal (AOP(count)->aopu.aop_lit) <= 256) {
13219 l = aopGet(val, 0, FALSE, FALSE, NULL);
13220 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
13223 emitcode ("movx", "@dptr,a");
13224 emitcode ("inc", "dptr");
13225 emitcode ("djnz","b,!tlabel",lbl->key+100);
13227 symbol *lbl1 = newiTempLabel(NULL);
13229 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
13230 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
13232 MOVA (aopGet(val, 0, FALSE, FALSE, NULL));
13233 emitcode ("movx", "@dptr,a");
13234 emitcode ("inc", "dptr");
13235 emitcode ("mov","a,b");
13236 emitcode ("orl","a,_ap");
13237 emitcode ("jz","!tlabel",lbl1->key+100);
13238 emitcode ("mov","a,_ap");
13239 emitcode ("add","a,#!constbyte",0xFF);
13240 emitcode ("mov","_ap,a");
13241 emitcode ("mov","a,b");
13242 emitcode ("addc","a,#!constbyte",0xFF);
13243 emitcode ("mov","b,a");
13244 emitcode ("sjmp","!tlabel",lbl->key+100);
13247 freeAsmop (count, NULL, ic, FALSE);
13248 unsavermask(rsave);
13251 /*-----------------------------------------------------------------*/
13252 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
13253 /*-----------------------------------------------------------------*/
13254 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
13257 operand *pnum, *result;
13260 assert (nparms==1);
13261 /* save registers that need to be saved */
13262 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13263 ds390_rUmaskForOp (IC_RESULT(ic))));
13266 aopOp (pnum, ic, FALSE, FALSE);
13267 emitcode ("mov","a,%s",aopGet(pnum,0,FALSE,FALSE,DP2_RESULT_REG));
13268 freeAsmop (pnum, NULL, ic, FALSE);
13269 emitcode ("lcall","NatLib_LoadPrimitive");
13270 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
13271 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
13272 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
13273 for (i = (size-1) ; i >= 0 ; i-- ) {
13274 emitcode ("push","a%s",javaRet[i]);
13276 for (i=0; i < size ; i++ ) {
13277 emitcode ("pop","a%s",
13278 aopGet(result,i,FALSE,FALSE,DP2_RESULT_REG));
13281 for (i = 0 ; i < size ; i++ ) {
13282 aopPut(result,javaRet[i],i);
13285 freeAsmop (result, NULL, ic, FALSE);
13286 unsavermask(rsave);
13289 /*-----------------------------------------------------------------*/
13290 /* genNatLibLoadPointer - calls TINI api function to load pointer */
13291 /*-----------------------------------------------------------------*/
13292 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
13295 operand *pnum, *result;
13299 assert (nparms==1);
13300 /* save registers that need to be saved */
13301 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13302 ds390_rUmaskForOp (IC_RESULT(ic))));
13305 aopOp (pnum, ic, FALSE, FALSE);
13306 emitcode ("mov","a,%s",aopGet(pnum,0,FALSE,FALSE,DP2_RESULT_REG));
13307 freeAsmop (pnum, NULL, ic, FALSE);
13308 emitcode ("lcall","NatLib_LoadPointer");
13309 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
13310 if (AOP_TYPE(result)!=AOP_STR) {
13311 for (i = 0 ; i < size ; i++ ) {
13312 aopPut(result,fReturn[i],i);
13315 freeAsmop (result, NULL, ic, FALSE);
13316 unsavermask(rsave);
13319 /*-----------------------------------------------------------------*/
13320 /* genNatLibInstallStateBlock - */
13321 /*-----------------------------------------------------------------*/
13322 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
13323 operand **parms, const char *name)
13326 operand *psb, *handle;
13327 assert (nparms==2);
13329 /* save registers that need to be saved */
13330 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13331 ds390_rUmaskForOp (IC_RESULT(ic))));
13335 /* put pointer to state block into DPTR1 */
13336 aopOp (psb, ic, FALSE, FALSE);
13337 if (AOP_TYPE (psb) == AOP_IMMD) {
13338 emitcode ("mov","dps,#1");
13339 emitcode ("mov", "dptr,%s",
13340 aopGet (psb, 0, TRUE, FALSE, DP2_RESULT_REG));
13341 emitcode ("mov","dps,#0");
13343 emitcode ("mov","dpl1,%s",aopGet(psb,0,FALSE,FALSE,DP2_RESULT_REG));
13344 emitcode ("mov","dph1,%s",aopGet(psb,1,FALSE,FALSE,DP2_RESULT_REG));
13345 emitcode ("mov","dpx1,%s",aopGet(psb,2,FALSE,FALSE,DP2_RESULT_REG));
13347 freeAsmop (psb, NULL, ic, FALSE);
13349 /* put libraryID into DPTR */
13350 emitcode ("mov","dptr,#LibraryID");
13352 /* put handle into r3:r2 */
13353 aopOp (handle, ic, FALSE, FALSE);
13354 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13355 emitcode ("push","%s",aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13356 emitcode ("push","%s",aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13357 emitcode ("pop","ar3");
13358 emitcode ("pop","ar2");
13360 emitcode ("mov","r2,%s",aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13361 emitcode ("mov","r3,%s",aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13363 freeAsmop (psb, NULL, ic, FALSE);
13365 /* make the call */
13366 emitcode ("lcall","NatLib_Install%sStateBlock",name);
13368 /* put return value into place*/
13370 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
13372 aopPut(IC_RESULT(ic),"a",0);
13373 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13374 unsavermask(rsave);
13377 /*-----------------------------------------------------------------*/
13378 /* genNatLibRemoveStateBlock - */
13379 /*-----------------------------------------------------------------*/
13380 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
13386 /* save registers that need to be saved */
13387 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13388 ds390_rUmaskForOp (IC_RESULT(ic))));
13390 /* put libraryID into DPTR */
13391 emitcode ("mov","dptr,#LibraryID");
13392 /* make the call */
13393 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
13394 unsavermask(rsave);
13397 /*-----------------------------------------------------------------*/
13398 /* genNatLibGetStateBlock - */
13399 /*-----------------------------------------------------------------*/
13400 static void genNatLibGetStateBlock(iCode *ic,int nparms,
13401 operand **parms,const char *name)
13404 symbol *lbl = newiTempLabel(NULL);
13407 /* save registers that need to be saved */
13408 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13409 ds390_rUmaskForOp (IC_RESULT(ic))));
13411 /* put libraryID into DPTR */
13412 emitcode ("mov","dptr,#LibraryID");
13413 /* make the call */
13414 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
13415 emitcode ("jnz","!tlabel",lbl->key+100);
13417 /* put return value into place */
13418 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
13419 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
13420 emitcode ("push","ar3");
13421 emitcode ("push","ar2");
13422 emitcode ("pop","%s",
13423 aopGet(IC_RESULT(ic),0,FALSE,TRUE,DP2_RESULT_REG));
13424 emitcode ("pop","%s",
13425 aopGet(IC_RESULT(ic),1,FALSE,TRUE,DP2_RESULT_REG));
13427 aopPut(IC_RESULT(ic),"r2",0);
13428 aopPut(IC_RESULT(ic),"r3",1);
13430 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13432 unsavermask(rsave);
13435 /*-----------------------------------------------------------------*/
13436 /* genMMMalloc - */
13437 /*-----------------------------------------------------------------*/
13438 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
13439 int size, const char *name)
13444 symbol *lbl = newiTempLabel(NULL);
13446 assert (nparms == 1);
13447 /* save registers that need to be saved */
13448 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13449 ds390_rUmaskForOp (IC_RESULT(ic))));
13452 aopOp (bsize,ic,FALSE,FALSE);
13454 /* put the size in R4-R2 */
13455 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
13456 emitcode("push","%s",aopGet(bsize,0,FALSE,TRUE,DP2_RESULT_REG));
13457 emitcode("push","%s",aopGet(bsize,1,FALSE,TRUE,DP2_RESULT_REG));
13459 emitcode("push","%s",aopGet(bsize,2,FALSE,TRUE,DP2_RESULT_REG));
13460 emitcode("pop","ar4");
13462 emitcode("pop","ar3");
13463 emitcode("pop","ar2");
13465 emitcode ("mov","r2,%s",aopGet(bsize,0,FALSE,TRUE,DP2_RESULT_REG));
13466 emitcode ("mov","r3,%s",aopGet(bsize,1,FALSE,TRUE,DP2_RESULT_REG));
13468 emitcode("mov","r4,%s",aopGet(bsize,2,FALSE,TRUE,DP2_RESULT_REG));
13471 freeAsmop (bsize, NULL, ic, FALSE);
13473 /* make the call */
13474 emitcode ("lcall","MM_%s",name);
13475 emitcode ("jz","!tlabel",lbl->key+100);
13476 emitcode ("mov","r2,#!constbyte",0xff);
13477 emitcode ("mov","r3,#!constbyte",0xff);
13479 /* we don't care about the pointer : we just save the handle */
13480 rsym = OP_SYMBOL(IC_RESULT(ic));
13481 if (rsym->liveFrom != rsym->liveTo) {
13482 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
13483 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
13484 emitcode ("push","ar3");
13485 emitcode ("push","ar2");
13486 emitcode ("pop","%s",
13487 aopGet(IC_RESULT(ic),0,FALSE,TRUE,DP2_RESULT_REG));
13488 emitcode ("pop","%s",
13489 aopGet(IC_RESULT(ic),1,FALSE,TRUE,DP2_RESULT_REG));
13491 aopPut(IC_RESULT(ic),"r2",0);
13492 aopPut(IC_RESULT(ic),"r3",1);
13494 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13496 unsavermask(rsave);
13499 /*-----------------------------------------------------------------*/
13501 /*-----------------------------------------------------------------*/
13502 static void genMMDeref (iCode *ic,int nparms, operand **parms)
13507 assert (nparms == 1);
13508 /* save registers that need to be saved */
13509 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13510 ds390_rUmaskForOp (IC_RESULT(ic))));
13513 aopOp (handle,ic,FALSE,FALSE);
13515 /* put the size in R4-R2 */
13516 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13517 emitcode("push","%s",
13518 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13519 emitcode("push","%s",
13520 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13521 emitcode("pop","ar3");
13522 emitcode("pop","ar2");
13524 emitcode ("mov","r2,%s",
13525 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13526 emitcode ("mov","r3,%s",
13527 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13529 freeAsmop (handle, NULL, ic, FALSE);
13531 /* make the call */
13532 emitcode ("lcall","MM_Deref");
13535 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13536 if (rsym->liveFrom != rsym->liveTo) {
13537 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13538 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
13539 _startLazyDPSEvaluation ();
13541 aopPut(IC_RESULT(ic),"dpl",0);
13542 aopPut(IC_RESULT(ic),"dph",1);
13543 aopPut(IC_RESULT(ic),"dpx",2);
13545 _endLazyDPSEvaluation ();
13550 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13551 unsavermask(rsave);
13554 /*-----------------------------------------------------------------*/
13555 /* genMMUnrestrictedPersist - */
13556 /*-----------------------------------------------------------------*/
13557 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
13562 assert (nparms == 1);
13563 /* save registers that need to be saved */
13564 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13565 ds390_rUmaskForOp (IC_RESULT(ic))));
13568 aopOp (handle,ic,FALSE,FALSE);
13570 /* put the size in R3-R2 */
13571 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13572 emitcode("push","%s",
13573 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13574 emitcode("push","%s",
13575 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13576 emitcode("pop","ar3");
13577 emitcode("pop","ar2");
13579 emitcode ("mov","r2,%s",
13580 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13581 emitcode ("mov","r3,%s",
13582 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13584 freeAsmop (handle, NULL, ic, FALSE);
13586 /* make the call */
13587 emitcode ("lcall","MM_UnrestrictedPersist");
13590 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13591 if (rsym->liveFrom != rsym->liveTo) {
13592 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13593 aopPut(IC_RESULT(ic),"a",0);
13594 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13597 unsavermask(rsave);
13600 /*-----------------------------------------------------------------*/
13601 /* genSystemExecJavaProcess - */
13602 /*-----------------------------------------------------------------*/
13603 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
13606 operand *handle, *pp;
13608 assert (nparms==2);
13609 /* save registers that need to be saved */
13610 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13611 ds390_rUmaskForOp (IC_RESULT(ic))));
13616 /* put the handle in R3-R2 */
13617 aopOp (handle,ic,FALSE,FALSE);
13618 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13619 emitcode("push","%s",
13620 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13621 emitcode("push","%s",
13622 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13623 emitcode("pop","ar3");
13624 emitcode("pop","ar2");
13626 emitcode ("mov","r2,%s",
13627 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13628 emitcode ("mov","r3,%s",
13629 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13631 freeAsmop (handle, NULL, ic, FALSE);
13633 /* put pointer in DPTR */
13634 aopOp (pp,ic,FALSE,FALSE);
13635 if (AOP_TYPE(pp) == AOP_IMMD) {
13636 emitcode ("mov", "dptr,%s",
13637 aopGet (pp, 0, TRUE, FALSE, NULL));
13638 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
13639 emitcode ("mov","dpl,%s",aopGet(pp,0,FALSE,FALSE,NULL));
13640 emitcode ("mov","dph,%s",aopGet(pp,1,FALSE,FALSE,NULL));
13641 emitcode ("mov","dpx,%s",aopGet(pp,2,FALSE,FALSE,NULL));
13643 freeAsmop (handle, NULL, ic, FALSE);
13645 /* make the call */
13646 emitcode ("lcall","System_ExecJavaProcess");
13648 /* put result in place */
13650 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13651 if (rsym->liveFrom != rsym->liveTo) {
13652 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13653 aopPut(IC_RESULT(ic),"a",0);
13654 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13658 unsavermask(rsave);
13661 /*-----------------------------------------------------------------*/
13662 /* genSystemRTCRegisters - */
13663 /*-----------------------------------------------------------------*/
13664 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
13670 assert (nparms==1);
13671 /* save registers that need to be saved */
13672 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13673 ds390_rUmaskForOp (IC_RESULT(ic))));
13676 /* put pointer in DPTR */
13677 aopOp (pp,ic,FALSE,FALSE);
13678 if (AOP_TYPE (pp) == AOP_IMMD) {
13679 emitcode ("mov","dps,#1");
13680 emitcode ("mov", "dptr,%s",
13681 aopGet (pp, 0, TRUE, FALSE, NULL));
13682 emitcode ("mov","dps,#0");
13684 emitcode ("mov","dpl1,%s",
13685 aopGet(pp,0,FALSE,FALSE,DP2_RESULT_REG));
13686 emitcode ("mov","dph1,%s",
13687 aopGet(pp,1,FALSE,FALSE,DP2_RESULT_REG));
13688 emitcode ("mov","dpx1,%s",
13689 aopGet(pp,2,FALSE,FALSE,DP2_RESULT_REG));
13691 freeAsmop (pp, NULL, ic, FALSE);
13693 /* make the call */
13694 emitcode ("lcall","System_%sRTCRegisters",name);
13696 unsavermask(rsave);
13699 /*-----------------------------------------------------------------*/
13700 /* genSystemThreadSleep - */
13701 /*-----------------------------------------------------------------*/
13702 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
13707 assert (nparms==1);
13708 /* save registers that need to be saved */
13709 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13710 ds390_rUmaskForOp (IC_RESULT(ic))));
13713 aopOp(to,ic,FALSE,FALSE);
13714 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
13715 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
13716 emitcode ("push","%s",
13717 aopGet(to,0,FALSE,TRUE,DP2_RESULT_REG));
13718 emitcode ("push","%s",
13719 aopGet(to,1,FALSE,TRUE,DP2_RESULT_REG));
13720 emitcode ("push","%s",
13721 aopGet(to,2,FALSE,TRUE,DP2_RESULT_REG));
13722 emitcode ("push","%s",
13723 aopGet(to,3,FALSE,TRUE,DP2_RESULT_REG));
13724 emitcode ("pop","ar3");
13725 emitcode ("pop","ar2");
13726 emitcode ("pop","ar1");
13727 emitcode ("pop","ar0");
13729 emitcode ("mov","r0,%s",
13730 aopGet(to,0,FALSE,TRUE,DP2_RESULT_REG));
13731 emitcode ("mov","r1,%s",
13732 aopGet(to,1,FALSE,TRUE,DP2_RESULT_REG));
13733 emitcode ("mov","r2,%s",
13734 aopGet(to,2,FALSE,TRUE,DP2_RESULT_REG));
13735 emitcode ("mov","r3,%s",
13736 aopGet(to,3,FALSE,TRUE,DP2_RESULT_REG));
13738 freeAsmop (to, NULL, ic, FALSE);
13740 /* suspend in acc */
13742 aopOp(s,ic,FALSE,FALSE);
13743 emitcode ("mov","a,%s",
13744 aopGet(s,0,FALSE,TRUE,NULL));
13745 freeAsmop (s, NULL, ic, FALSE);
13747 /* make the call */
13748 emitcode ("lcall","System_%s",name);
13750 unsavermask(rsave);
13753 /*-----------------------------------------------------------------*/
13754 /* genSystemThreadResume - */
13755 /*-----------------------------------------------------------------*/
13756 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
13761 assert (nparms==2);
13762 /* save registers that need to be saved */
13763 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13764 ds390_rUmaskForOp (IC_RESULT(ic))));
13770 aopOp(pid,ic,FALSE,FALSE);
13771 emitcode ("mov","r0,%s",
13772 aopGet(pid,0,FALSE,TRUE,DP2_RESULT_REG));
13773 freeAsmop (pid, NULL, ic, FALSE);
13776 aopOp(tid,ic,FALSE,FALSE);
13777 emitcode ("mov","a,%s",
13778 aopGet(tid,0,FALSE,TRUE,DP2_RESULT_REG));
13779 freeAsmop (tid, NULL, ic, FALSE);
13781 emitcode ("lcall","System_ThreadResume");
13783 /* put result into place */
13785 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13786 if (rsym->liveFrom != rsym->liveTo) {
13787 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13788 aopPut(IC_RESULT(ic),"a",0);
13789 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13792 unsavermask(rsave);
13795 /*-----------------------------------------------------------------*/
13796 /* genSystemProcessResume - */
13797 /*-----------------------------------------------------------------*/
13798 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
13803 assert (nparms==1);
13804 /* save registers that need to be saved */
13805 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13806 ds390_rUmaskForOp (IC_RESULT(ic))));
13811 aopOp(pid,ic,FALSE,FALSE);
13812 emitcode ("mov","a,%s",
13813 aopGet(pid,0,FALSE,TRUE,DP2_RESULT_REG));
13814 freeAsmop (pid, NULL, ic, FALSE);
13816 emitcode ("lcall","System_ProcessResume");
13818 unsavermask(rsave);
13821 /*-----------------------------------------------------------------*/
13823 /*-----------------------------------------------------------------*/
13824 static void genSystem (iCode *ic,int nparms,char *name)
13826 assert(nparms == 0);
13828 emitcode ("lcall","System_%s",name);
13831 /*-----------------------------------------------------------------*/
13832 /* genSystemPoll - */
13833 /*-----------------------------------------------------------------*/
13834 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
13839 assert (nparms==1);
13840 /* save registers that need to be saved */
13841 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13842 ds390_rUmaskForOp (IC_RESULT(ic))));
13845 aopOp (fp,ic,FALSE,FALSE);
13846 if (AOP_TYPE (fp) == AOP_IMMD) {
13847 emitcode ("mov", "dptr,%s",
13848 aopGet (fp, 0, TRUE, FALSE, DP2_RESULT_REG));
13849 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
13850 emitcode ("mov","dpl,%s",
13851 aopGet(fp,0,FALSE,FALSE,DP2_RESULT_REG));
13852 emitcode ("mov","dph,%s",
13853 aopGet(fp,1,FALSE,FALSE,DP2_RESULT_REG));
13854 emitcode ("mov","dpx,%s",
13855 aopGet(fp,2,FALSE,FALSE,DP2_RESULT_REG));
13857 freeAsmop (fp, NULL, ic, FALSE);
13859 emitcode ("lcall","System_%sPoll",name);
13861 /* put result into place */
13863 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13864 if (rsym->liveFrom != rsym->liveTo) {
13865 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13866 aopPut(IC_RESULT(ic),"a",0);
13867 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13870 unsavermask(rsave);
13873 /*-----------------------------------------------------------------*/
13874 /* genSystemGetCurrentID - */
13875 /*-----------------------------------------------------------------*/
13876 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
13878 assert (nparms==0);
13880 emitcode ("lcall","System_GetCurrent%sId",name);
13881 /* put result into place */
13883 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13884 if (rsym->liveFrom != rsym->liveTo) {
13885 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13886 aopPut(IC_RESULT(ic),"a",0);
13887 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13892 /*-----------------------------------------------------------------*/
13893 /* genDjnz - generate decrement & jump if not zero instrucion */
13894 /*-----------------------------------------------------------------*/
13896 genDjnz (iCode * ic, iCode * ifx)
13898 symbol *lbl, *lbl1;
13902 /* if the if condition has a false label
13903 then we cannot save */
13904 if (IC_FALSE (ifx))
13907 /* if the minus is not of the form a = a - 1 */
13908 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
13909 !IS_OP_LITERAL (IC_RIGHT (ic)))
13912 if (operandLitValue (IC_RIGHT (ic)) != 1)
13915 /* if the size of this greater than one then no
13917 if (getSize (operandType (IC_RESULT (ic))) > 1)
13920 /* otherwise we can save BIG */
13922 D (emitcode (";", "genDjnz"));
13924 lbl = newiTempLabel (NULL);
13925 lbl1 = newiTempLabel (NULL);
13927 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
13929 if (AOP_NEEDSACC(IC_RESULT(ic)))
13931 /* If the result is accessed indirectly via
13932 * the accumulator, we must explicitly write
13933 * it back after the decrement.
13935 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE, NULL);
13937 if (strcmp(rByte, "a"))
13939 /* Something is hopelessly wrong */
13940 fprintf(stderr, "*** warning: internal error at %s:%d\n",
13941 __FILE__, __LINE__);
13942 /* We can just give up; the generated code will be inefficient,
13943 * but what the hey.
13945 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13948 emitcode ("dec", "%s", rByte);
13949 aopPut (IC_RESULT (ic), rByte, 0);
13950 emitcode ("jnz", "!tlabel", lbl->key + 100);
13952 else if (IS_AOP_PREG (IC_RESULT (ic)))
13954 emitcode ("dec", "%s",
13955 aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL));
13956 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL));
13957 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13958 ifx->generated = 1;
13959 emitcode ("jnz", "!tlabel", lbl->key + 100);
13963 emitcode ("djnz", "%s,!tlabel", aopGet (IC_RESULT (ic), 0, FALSE, TRUE, NULL),
13966 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
13968 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
13971 if (!ifx->generated)
13972 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13973 ifx->generated = 1;
13977 /*-----------------------------------------------------------------*/
13978 /* genReceive - generate code for a receive iCode */
13979 /*-----------------------------------------------------------------*/
13981 genReceive (iCode * ic)
13983 int size = getSize (operandType (IC_RESULT (ic)));
13987 D (emitcode (";", "genReceive"));
13989 if (ic->argreg == 1)
13991 /* first parameter */
13992 if (AOP_IS_STR(IC_RESULT(ic)))
13994 /* Nothing to do: it's already in the proper place. */
14001 useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
14002 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
14003 IS_TRUE_SYMOP (IC_RESULT (ic)));
14006 aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
14009 /* Sanity checking... */
14010 if (AOP_USESDPTR(IC_RESULT(ic)))
14012 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
14013 "genReceive got unexpected DPTR.");
14015 assignResultValue (IC_RESULT (ic), NULL);
14018 else if (ic->argreg > 12)
14019 { /* bit parameters */
14020 if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
14022 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
14023 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
14024 outBitC(IC_RESULT (ic));
14029 /* second receive onwards */
14030 /* this gets a little tricky since unused receives will be
14031 eliminated, we have saved the reg in the type field . and
14032 we use that to figure out which register to use */
14033 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
14034 rb1off = ic->argreg;
14037 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
14040 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
14043 /*-----------------------------------------------------------------*/
14044 /* genDummyRead - generate code for dummy read of volatiles */
14045 /*-----------------------------------------------------------------*/
14047 genDummyRead (iCode * ic)
14052 D (emitcode(";", "genDummyRead"));
14054 op = IC_RIGHT (ic);
14055 if (op && IS_SYMOP (op))
14057 aopOp (op, ic, FALSE, FALSE);
14059 /* if the result is a bit */
14060 if (AOP_TYPE (op) == AOP_CRY)
14061 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
14064 /* bit variables done */
14066 size = AOP_SIZE (op);
14070 MOVA (aopGet (op, offset, FALSE, FALSE, FALSE));
14075 freeAsmop (op, NULL, ic, TRUE);
14079 if (op && IS_SYMOP (op))
14081 aopOp (op, ic, FALSE, FALSE);
14083 /* if the result is a bit */
14084 if (AOP_TYPE (op) == AOP_CRY)
14085 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
14088 /* bit variables done */
14090 size = AOP_SIZE (op);
14094 MOVA (aopGet (op, offset, FALSE, FALSE, FALSE));
14099 freeAsmop (op, NULL, ic, TRUE);
14103 /*-----------------------------------------------------------------*/
14104 /* genCritical - generate code for start of a critical sequence */
14105 /*-----------------------------------------------------------------*/
14107 genCritical (iCode *ic)
14109 symbol *tlbl = newiTempLabel (NULL);
14111 D (emitcode(";", "genCritical"));
14113 if (IC_RESULT (ic))
14115 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
14116 aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
14117 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
14118 aopPut (IC_RESULT (ic), zero, 0);
14120 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
14124 emitcode ("setb", "c");
14125 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
14126 emitcode ("clr", "c");
14128 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
14132 /*-----------------------------------------------------------------*/
14133 /* genEndCritical - generate code for end of a critical sequence */
14134 /*-----------------------------------------------------------------*/
14136 genEndCritical (iCode *ic)
14138 D(emitcode(";", "genEndCritical"));
14142 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
14143 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
14145 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
14146 emitcode ("mov", "ea,c");
14150 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE, FALSE));
14151 emitcode ("rrc", "a");
14152 emitcode ("mov", "ea,c");
14154 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
14158 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
14159 emitcode ("mov", "ea,c");
14165 /*-----------------------------------------------------------------*/
14166 /* genBuiltIn - calls the appropriate function to generating code */
14167 /* for a built in function */
14168 /*-----------------------------------------------------------------*/
14169 static void genBuiltIn (iCode *ic)
14171 operand *bi_parms[MAX_BUILTIN_ARGS];
14176 /* get all the arguments for a built in function */
14177 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
14179 /* which function is it */
14180 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
14181 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
14182 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
14183 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
14184 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
14185 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
14186 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
14187 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
14188 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
14189 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
14190 genMemsetX(bi_iCode,nbi_parms,bi_parms);
14191 } else if (strcmp(bif->name,"__builtin_inp")==0) {
14192 genInp(bi_iCode,nbi_parms,bi_parms);
14193 } else if (strcmp(bif->name,"__builtin_outp")==0) {
14194 genOutp(bi_iCode,nbi_parms,bi_parms);
14195 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
14196 genSwapW(bi_iCode,nbi_parms,bi_parms);
14197 /* JavaNative builtIns */
14198 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
14199 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
14200 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
14201 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
14202 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
14203 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
14204 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
14205 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
14206 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
14207 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
14208 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
14209 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
14210 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
14211 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
14212 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
14213 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
14214 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
14215 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
14216 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
14217 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
14218 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
14219 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
14220 } else if (strcmp(bif->name,"MM_Malloc")==0) {
14221 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
14222 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
14223 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
14224 } else if (strcmp(bif->name,"MM_Free")==0) {
14225 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
14226 } else if (strcmp(bif->name,"MM_Deref")==0) {
14227 genMMDeref(bi_iCode,nbi_parms,bi_parms);
14228 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
14229 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
14230 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
14231 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
14232 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
14233 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
14234 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
14235 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
14236 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
14237 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
14238 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
14239 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
14240 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
14241 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
14242 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
14243 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
14244 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
14245 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
14246 } else if (strcmp(bif->name,"System_SaveThread")==0) {
14247 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
14248 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
14249 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
14250 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
14251 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
14252 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
14253 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
14254 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
14255 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
14256 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
14257 genSystem(bi_iCode,nbi_parms,"ProcessYield");
14258 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
14259 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
14260 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
14261 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
14262 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
14263 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
14264 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
14265 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
14266 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
14267 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
14269 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
14275 /*-----------------------------------------------------------------*/
14276 /* gen390Code - generate code for Dallas 390 based controllers */
14277 /*-----------------------------------------------------------------*/
14279 gen390Code (iCode * lic)
14284 _G.currentFunc = NULL;
14285 lineHead = lineCurr = NULL;
14286 dptrn[1][0] = "dpl1";
14287 dptrn[1][1] = "dph1";
14288 dptrn[1][2] = "dpx1";
14290 if (options.model == MODEL_FLAT24) {
14291 fReturnSizeDS390 = 5;
14292 fReturn = fReturn24;
14294 fReturnSizeDS390 = 4;
14295 fReturn = fReturn16;
14296 options.stack10bit=0;
14299 /* print the allocation information */
14300 if (allocInfo && currFunc)
14301 printAllocInfo (currFunc, codeOutBuf);
14303 /* if debug information required */
14304 if (options.debug && currFunc)
14306 debugFile->writeFunction (currFunc, lic);
14308 /* stack pointer name */
14309 if (options.useXstack)
14315 for (ic = lic; ic; ic = ic->next)
14317 _G.current_iCode = ic;
14319 if (ic->lineno && cln != ic->lineno)
14323 debugFile->writeCLine (ic);
14325 if (!options.noCcodeInAsm) {
14326 emitcode (";", "%s:%d: %s", ic->filename, ic->lineno,
14327 printCLine(ic->filename, ic->lineno));
14331 if (options.iCodeInAsm) {
14332 const char *iLine = printILine(ic);
14333 emitcode(";", "ic:%d: %s", ic->key, iLine);
14336 /* if the result is marked as
14337 spilt and rematerializable or code for
14338 this has already been generated then
14340 if (resultRemat (ic) || ic->generated)
14343 /* depending on the operation */
14364 iCode *ifxIc, *popIc;
14365 bool CommonRegs = FALSE;
14367 /* IPOP happens only when trying to restore a
14368 spilt live range, if there is an ifx statement
14369 following this pop (or several) then the if statement might
14370 be using some of the registers being popped which
14371 would destory the contents of the register so
14372 we need to check for this condition and handle it */
14373 for (ifxIc = ic->next; ifxIc && ifxIc->op == IPOP; ifxIc = ifxIc->next);
14374 for (popIc = ic; popIc && popIc->op == IPOP; popIc = popIc->next)
14375 CommonRegs |= (ifxIc && ifxIc->op == IFX && !ifxIc->generated &&
14376 regsInCommon (IC_LEFT (popIc), IC_COND (ifxIc)));
14378 genIfx (ifxIc, ic);
14397 genEndFunction (ic);
14417 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
14434 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
14438 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
14445 /* note these two are xlated by algebraic equivalence
14446 during parsing SDCC.y */
14447 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
14448 "got '>=' or '<=' shouldn't have come here");
14452 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
14464 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
14468 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
14472 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
14496 genRightShift (ic);
14499 case GET_VALUE_AT_ADDRESS:
14501 hasInc (IC_LEFT (ic), ic,
14502 getSize (operandType (IC_RESULT (ic)))));
14506 if (POINTER_SET (ic))
14508 hasInc (IC_RESULT (ic), ic,
14509 getSize (operandType (IC_RIGHT (ic)))));
14535 if (ic->builtinSEND)
14538 addSet (&_G.sendSet, ic);
14541 case DUMMY_READ_VOLATILE:
14550 genEndCritical (ic);
14557 #if 0 // obsolete, and buggy for != xdata
14564 /* This should never happen, right? */
14565 fprintf(stderr, "*** Probable error: unsupported op 0x%x (%c) in %s @ %d\n",
14566 ic->op, ic->op, __FILE__, __LINE__);
14572 /* now we are ready to call the
14573 peep hole optimizer */
14574 if (!options.nopeep)
14575 peepHole (&lineHead);
14577 /* now do the actual printing */
14578 printLine (lineHead, codeOutBuf);