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_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
650 size = getSize (OP_SYMBOL (op)->type);
655 else if (ic->op == JUMPTABLE)
658 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
661 size = getSize (OP_SYMBOL (op)->type);
669 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
672 size = getSize (OP_SYMBOL (op)->type);
677 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
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 - rematerialzes 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)) {
908 sym_link *from_type = operandType(IC_RIGHT(ic));
909 aop->aopu.aop_immd.from_cast_remat = 1;
910 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
911 ptr_type = pointerTypeToGPByte (DCL_TYPE(from_type), NULL, NULL);
915 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
920 SNPRINTF (buffer, sizeof(buffer),
922 OP_SYMBOL (IC_LEFT (ic))->rname,
923 val >= 0 ? '+' : '-',
924 abs (val) & 0xffffff);
928 if (IS_ASSIGN_ICODE(ic) && isOperandLiteral(IC_RIGHT(ic)))
930 SNPRINTF(buffer, sizeof(buffer),
931 "0x%x",(int) operandLitValue (IC_RIGHT (ic)));
935 strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
939 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
940 /* set immd2 field if required */
941 if (aop->aopu.aop_immd.from_cast_remat)
943 tsprintf(buffer, sizeof(buffer), "#!constbyte",ptr_type);
944 aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
950 /*-----------------------------------------------------------------*/
951 /* aopHasRegs - returns true if aop has regs between from-to */
952 /*-----------------------------------------------------------------*/
953 static int aopHasRegs(asmop *aop, int from, int to)
957 if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
959 for (; size < aop->size ; size++) {
961 for (reg = from ; reg <= to ; reg++)
962 if (aop->aopu.aop_reg[size] == REG_WITH_INDEX(reg)) return 1;
967 /*-----------------------------------------------------------------*/
968 /* regsInCommon - two operands have some registers in common */
969 /*-----------------------------------------------------------------*/
971 regsInCommon (operand * op1, operand * op2)
976 /* if they have registers in common */
977 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
980 sym1 = OP_SYMBOL (op1);
981 sym2 = OP_SYMBOL (op2);
983 if (sym1->nRegs == 0 || sym2->nRegs == 0)
986 for (i = 0; i < sym1->nRegs; i++)
992 for (j = 0; j < sym2->nRegs; j++)
997 if (sym2->regs[j] == sym1->regs[i])
1005 /*-----------------------------------------------------------------*/
1006 /* operandsEqu - equivalent */
1007 /*-----------------------------------------------------------------*/
1009 operandsEqu (operand * op1, operand * op2)
1011 symbol *sym1, *sym2;
1013 /* if they're not symbols */
1014 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
1017 sym1 = OP_SYMBOL (op1);
1018 sym2 = OP_SYMBOL (op2);
1020 /* if both are itemps & one is spilt
1021 and the other is not then false */
1022 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
1023 sym1->isspilt != sym2->isspilt)
1026 /* if they are the same */
1030 /* if they have the same rname */
1031 if (sym1->rname[0] && sym2->rname[0] &&
1032 strcmp (sym1->rname, sym2->rname) == 0 &&
1033 !(IS_PARM (op2) && IS_ITEMP (op1)))
1036 /* if left is a tmp & right is not */
1037 if (IS_ITEMP (op1) &&
1040 (sym1->usl.spillLoc == sym2))
1043 if (IS_ITEMP (op2) &&
1047 (sym2->usl.spillLoc == sym1))
1050 /* are they spilt to the same location */
1051 if (IS_ITEMP (op2) &&
1055 (sym1->usl.spillLoc == sym2->usl.spillLoc))
1061 /*-----------------------------------------------------------------*/
1062 /* sameRegs - two asmops have the same registers */
1063 /*-----------------------------------------------------------------*/
1065 sameRegs (asmop * aop1, asmop * aop2)
1071 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
1078 if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
1081 if (aop1->type != aop2->type)
1084 if (aop1->size != aop2->size)
1087 for (i = 0; i < aop1->size; i++)
1088 if (aop1->aopu.aop_reg[i] != aop2->aopu.aop_reg[i])
1094 /*-----------------------------------------------------------------*/
1095 /* aopOp - allocates an asmop for an operand : */
1096 /*-----------------------------------------------------------------*/
1098 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
1107 /* if this a literal */
1108 if (IS_OP_LITERAL (op))
1110 op->aop = aop = newAsmop (AOP_LIT);
1111 aop->aopu.aop_lit = op->operand.valOperand;
1112 aop->size = getSize (operandType (op));
1116 /* if already has a asmop then continue */
1119 if ((op->aop->type == AOP_DPTR && useDP2)
1120 || (op->aop->type == AOP_DPTR2 && !useDP2))
1124 op->aop->allocated++;
1129 /* if the underlying symbol has a aop */
1130 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
1132 op->aop = OP_SYMBOL (op)->aop;
1133 if ((op->aop->type == AOP_DPTR && useDP2)
1134 || (op->aop->type == AOP_DPTR2 && !useDP2))
1138 op->aop->allocated++;
1143 /* if this is a true symbol */
1144 if (IS_TRUE_SYMOP (op))
1146 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
1150 /* this is a temporary : this has
1156 e) can be a return use only */
1158 sym = OP_SYMBOL (op);
1160 /* if the type is a conditional */
1161 if (sym->regType == REG_CND)
1163 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
1168 /* if it is spilt then two situations
1170 b) has a spill location */
1171 if (sym->isspilt || sym->nRegs == 0)
1174 /* rematerialize it NOW */
1177 sym->aop = op->aop = aop =
1179 aop->size = getSize (sym->type);
1186 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
1187 aop->size = getSize (sym->type);
1188 for (i = 0; i < 2; i++)
1189 aop->aopu.aop_str[i] = accUse[i];
1199 /* a AOP_STR uses DPTR, but DPTR is already in use;
1202 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
1205 aop = op->aop = sym->aop = newAsmop (AOP_STR);
1206 aop->size = getSize (sym->type);
1207 for (i = 0; i < fReturnSizeDS390; i++)
1208 aop->aopu.aop_str[i] = fReturn[i];
1212 if (sym->dptr) { /* has been allocated to a DPTRn */
1213 aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
1214 aop->size = getSize (sym->type);
1215 aop->aopu.dptr = sym->dptr;
1219 if (sym->usl.spillLoc)
1221 asmop *oldAsmOp = NULL;
1223 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1225 /* force a new aop if sizes differ */
1226 oldAsmOp = sym->usl.spillLoc->aop;
1227 sym->usl.spillLoc->aop = NULL;
1229 sym->aop = op->aop = aop =
1230 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
1231 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1233 /* Don't reuse the new aop, go with the last one */
1234 sym->usl.spillLoc->aop = oldAsmOp;
1236 aop->size = getSize (sym->type);
1240 /* else must be a dummy iTemp */
1241 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1242 aop->size = getSize (sym->type);
1246 /* if the type is a bit register */
1247 if (sym->regType == REG_BIT)
1249 sym->aop = op->aop = aop = newAsmop (AOP_CRY);
1250 aop->size = sym->nRegs;//1???
1251 aop->aopu.aop_reg[0] = sym->regs[0];
1252 aop->aopu.aop_dir = sym->regs[0]->name;
1256 /* must be in a register */
1257 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1258 aop->size = sym->nRegs;
1259 for (i = 0; i < sym->nRegs; i++)
1260 aop->aopu.aop_reg[i] = sym->regs[i];
1263 /*-----------------------------------------------------------------*/
1264 /* freeAsmop - free up the asmop given to an operand */
1265 /*----------------------------------------------------------------*/
1267 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1284 /* depending on the asmop type only three cases need work
1285 AOP_R0, AOP_R1 & AOP_STK */
1293 emitcode ("pop", "ar0");
1297 bitVectUnSetBit (ic->rUsed, R0_IDX);
1305 emitcode ("pop", "ar1");
1309 bitVectUnSetBit (ic->rUsed, R1_IDX);
1315 int stk = aop->aopu.aop_stk + aop->size;
1316 bitVectUnSetBit (ic->rUsed, R0_IDX);
1317 bitVectUnSetBit (ic->rUsed, R1_IDX);
1319 getFreePtr (ic, &aop, FALSE);
1321 if (options.stack10bit)
1323 /* I'm not sure what to do here yet... */
1326 "*** Warning: probably generating bad code for "
1327 "10 bit stack mode.\n");
1332 emitcode ("mov", "a,_bp");
1333 emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
1334 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1338 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1343 emitcode ("pop", "acc");
1344 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1347 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1350 freeAsmop (op, NULL, ic, TRUE);
1353 emitcode ("pop", "ar1");
1358 emitcode ("pop", "ar0");
1363 if (_G.dptr1InUse) {
1364 emitcode ("pop","dpx1");
1365 emitcode ("pop","dph1");
1366 emitcode ("pop","dpl1");
1371 emitcode ("pop","dpx");
1372 emitcode ("pop","dph");
1373 emitcode ("pop","dpl");
1379 /* all other cases just dealloc */
1385 OP_SYMBOL (op)->aop = NULL;
1386 /* if the symbol has a spill */
1388 SPIL_LOC (op)->aop = NULL;
1393 #define DEFAULT_ACC_WARNING 0
1394 static int saveAccWarn = DEFAULT_ACC_WARNING;
1397 /*-----------------------------------------------------------------*/
1398 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
1399 /* clobber the accumulator */
1400 /*-----------------------------------------------------------------*/
1402 aopGetUsesAcc (operand * oper, int offset)
1404 asmop * aop = AOP (oper);
1406 if (offset > (aop->size - 1))
1426 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1437 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1443 /* Error case --- will have been caught already */
1449 /*-------------------------------------------------------------------*/
1450 /* aopGet - for fetching value of the aop */
1452 /* Set saveAcc to NULL if you are sure it is OK to clobber the value */
1453 /* in the accumulator. Set it to the name of a free register */
1454 /* if acc must be preserved; the register will be used to preserve */
1455 /* acc temporarily and to return the result byte. */
1456 /*-------------------------------------------------------------------*/
1458 aopGet (operand * oper,
1464 asmop * aop = AOP (oper);
1466 /* offset is greater than
1468 if (offset > (aop->size - 1) &&
1469 aop->type != AOP_LIT)
1472 /* depending on type */
1480 /* if we need to increment it */
1481 while (offset > aop->coff)
1483 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1487 while (offset < aop->coff)
1489 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1496 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1497 return (dname ? "acc" : "a");
1499 SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1500 return Safe_strdup(buffer);
1503 assert(offset <= 3);
1504 return dptrn[aop->aopu.dptr][offset];
1509 if (aop->type == AOP_DPTR2)
1517 // if (aop->type != AOP_DPTR2)
1519 // if (saveAccWarn) { fprintf(stderr, "saveAcc for DPTR...\n"); }
1520 // emitcode(";", "spanky: saveAcc for DPTR");
1523 emitcode ("xch", "a, %s", saveAcc);
1528 while (offset > aop->coff)
1530 emitcode ("inc", "dptr");
1534 while (offset < aop->coff)
1536 emitcode ("lcall", "__decdptr");
1543 emitcode ("clr", "a");
1544 emitcode ("movc", "a,@a+dptr");
1548 emitcode ("movx", "a,@dptr");
1551 if (aop->type == AOP_DPTR2)
1559 emitcode ("xch", "a, %s", saveAcc);
1560 // if (strcmp(saveAcc, "_ap"))
1562 // emitcode(";", "spiffy: non _ap return from aopGet.");
1567 return (dname ? "acc" : "a");
1570 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1572 SNPRINTF(buffer, sizeof(buffer),
1573 "%s",aop->aopu.aop_immd.aop_immd2);
1577 SNPRINTF(buffer, sizeof(buffer),
1578 "#%s", aop->aopu.aop_immd.aop_immd1);
1584 tsprintf(buffer, sizeof(buffer),
1585 "#!his",aop->aopu.aop_immd.aop_immd1);
1588 tsprintf(buffer, sizeof(buffer),
1589 "#!hihis",aop->aopu.aop_immd.aop_immd1);
1592 tsprintf(buffer, sizeof(buffer),
1593 "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1595 default: /* should not need this (just in case) */
1596 SNPRINTF (buffer, sizeof(buffer),
1598 aop->aopu.aop_immd.aop_immd1,
1604 SNPRINTF (buffer, sizeof(buffer),
1606 aop->aopu.aop_immd.aop_immd1);
1608 return Safe_strdup(buffer);
1611 if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
1613 SNPRINTF (buffer, sizeof(buffer),
1615 aop->aopu.aop_dir, offset * 8);
1619 SNPRINTF (buffer, sizeof(buffer),
1626 SNPRINTF (buffer, sizeof(buffer),
1631 return Safe_strdup(buffer);
1635 return aop->aopu.aop_reg[offset]->dname;
1637 return aop->aopu.aop_reg[offset]->name;
1640 emitcode ("clr", "a");
1641 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1642 emitcode ("rlc", "a");
1643 return (dname ? "acc" : "a");
1646 if (!offset && dname)
1648 return aop->aopu.aop_str[offset];
1651 return aopLiteral (aop->aopu.aop_lit, offset);
1655 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1659 return aop->aopu.aop_str[offset];
1663 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1664 "aopget got unsupported aop->type");
1667 return NULL; // not reached, but makes compiler happy.
1670 /*-----------------------------------------------------------------*/
1671 /* aopPut - puts a string for a aop and indicates if acc is in use */
1672 /*-----------------------------------------------------------------*/
1674 aopPut (operand * result, const char *s, int offset)
1676 bool bvolatile = isOperandVolatile (result, FALSE);
1677 bool accuse = FALSE;
1678 asmop * aop = AOP (result);
1680 if (aop->size && offset > (aop->size - 1))
1682 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1683 "aopPut got offset > aop->size");
1687 /* will assign value to value */
1688 /* depending on where it is ofcourse */
1692 MOVA (s); /* read s in case it was volatile */
1697 if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1699 SNPRINTF (buffer, sizeof(buffer),
1701 aop->aopu.aop_dir, offset * 8);
1705 SNPRINTF (buffer, sizeof(buffer),
1707 aop->aopu.aop_dir, offset);
1711 SNPRINTF (buffer, sizeof(buffer),
1716 if (strcmp (buffer, s) || bvolatile)
1718 emitcode ("mov", "%s,%s", buffer, s);
1720 if (!strcmp (buffer, "acc"))
1727 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1728 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1731 strcmp (s, "r0") == 0 ||
1732 strcmp (s, "r1") == 0 ||
1733 strcmp (s, "r2") == 0 ||
1734 strcmp (s, "r3") == 0 ||
1735 strcmp (s, "r4") == 0 ||
1736 strcmp (s, "r5") == 0 ||
1737 strcmp (s, "r6") == 0 ||
1738 strcmp (s, "r7") == 0)
1740 emitcode ("mov", "%s,%s",
1741 aop->aopu.aop_reg[offset]->dname, s);
1745 emitcode ("mov", "%s,%s",
1746 aop->aopu.aop_reg[offset]->name, s);
1752 emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1758 if (aop->type == AOP_DPTR2)
1766 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1767 "aopPut writing to code space");
1771 while (offset > aop->coff)
1774 emitcode ("inc", "dptr");
1777 while (offset < aop->coff)
1780 emitcode ("lcall", "__decdptr");
1785 /* if not in accumulator */
1788 emitcode ("movx", "@dptr,a");
1790 if (aop->type == AOP_DPTR2)
1798 while (offset > aop->coff)
1801 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1803 while (offset < aop->coff)
1806 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1813 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1818 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1820 else if (strcmp (s, "r0") == 0 ||
1821 strcmp (s, "r1") == 0 ||
1822 strcmp (s, "r2") == 0 ||
1823 strcmp (s, "r3") == 0 ||
1824 strcmp (s, "r4") == 0 ||
1825 strcmp (s, "r5") == 0 ||
1826 strcmp (s, "r6") == 0 ||
1827 strcmp (s, "r7") == 0)
1830 SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1831 emitcode ("mov", "@%s,%s",
1832 aop->aopu.aop_ptr->name, buffer);
1836 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1841 if (strcmp (s, "a") == 0)
1842 emitcode ("push", "acc");
1846 emitcode ("push", "acc");
1848 emitcode ("push", s);
1854 /* if not bit variable */
1855 if (!aop->aopu.aop_dir)
1857 /* inefficient: move carry into A and use jz/jnz */
1858 emitcode ("clr", "a");
1859 emitcode ("rlc", "a");
1865 emitcode ("clr", "%s", aop->aopu.aop_dir);
1867 emitcode ("setb", "%s", aop->aopu.aop_dir);
1868 else if (!strcmp (s, "c"))
1869 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1870 else if (strcmp (s, aop->aopu.aop_dir))
1873 /* set C, if a >= 1 */
1874 emitcode ("add", "a,#!constbyte",0xff);
1875 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1882 if (strcmp (aop->aopu.aop_str[offset], s) || bvolatile)
1883 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1889 if (!offset && (strcmp (s, "acc") == 0) && !bvolatile)
1892 if (strcmp (aop->aopu.aop_str[offset], s) && !bvolatile)
1893 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1897 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1898 "aopPut got unsupported aop->type");
1906 /*--------------------------------------------------------------------*/
1907 /* reAdjustPreg - points a register back to where it should (coff==0) */
1908 /*--------------------------------------------------------------------*/
1910 reAdjustPreg (asmop * aop)
1912 if ((aop->coff==0) || (aop->size <= 1))
1920 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1924 if (aop->type == AOP_DPTR2)
1931 emitcode ("lcall", "__decdptr");
1934 if (aop->type == AOP_DPTR2)
1943 /*-----------------------------------------------------------------*/
1944 /* opIsGptr: returns non-zero if the passed operand is */
1945 /* a generic pointer type. */
1946 /*-----------------------------------------------------------------*/
1948 opIsGptr (operand * op)
1950 sym_link *type = operandType (op);
1952 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1959 /*-----------------------------------------------------------------*/
1960 /* getDataSize - get the operand data size */
1961 /*-----------------------------------------------------------------*/
1963 getDataSize (operand * op)
1966 size = AOP_SIZE (op);
1967 if (size == GPTRSIZE)
1969 sym_link *type = operandType (op);
1970 if (IS_GENPTR (type))
1972 /* generic pointer; arithmetic operations
1973 * should ignore the high byte (pointer type).
1981 /*-----------------------------------------------------------------*/
1982 /* outAcc - output Acc */
1983 /*-----------------------------------------------------------------*/
1985 outAcc (operand * result)
1988 size = getDataSize (result);
1991 aopPut (result, "a", 0);
1994 /* unsigned or positive */
1997 aopPut (result, zero, offset++);
2002 /*-----------------------------------------------------------------*/
2003 /* outBitC - output a bit C */
2004 /*-----------------------------------------------------------------*/
2006 outBitC (operand * result)
2008 /* if the result is bit */
2009 if (AOP_TYPE (result) == AOP_CRY)
2011 aopPut (result, "c", 0);
2015 emitcode ("clr", "a");
2016 emitcode ("rlc", "a");
2021 /*-----------------------------------------------------------------*/
2022 /* toBoolean - emit code for orl a,operator(sizeop) */
2023 /*-----------------------------------------------------------------*/
2025 toBoolean (operand * oper)
2027 int size = AOP_SIZE (oper) - 1;
2031 /* The generic part of a generic pointer should
2032 * not participate in it's truth value.
2034 * i.e. 0x10000000 is zero.
2036 if (opIsGptr (oper))
2038 D (emitcode (";", "toBoolean: generic ptr special case."));
2042 _startLazyDPSEvaluation ();
2043 MOVA (aopGet (oper, 0, FALSE, FALSE, NULL));
2044 if (AOP_NEEDSACC (oper) && size && (AOP (oper)->type != AOP_ACC))
2047 emitcode("mov", "b,a");
2050 MOVA (aopGet (oper, offset++, FALSE, FALSE, NULL));
2051 emitcode ("orl", "b,a");
2053 MOVA (aopGet (oper, offset++, FALSE, FALSE, NULL));
2054 emitcode ("orl", "a,b");
2061 emitcode ("orl", "a,%s",
2062 aopGet (oper, offset++, FALSE, FALSE, NULL));
2065 _endLazyDPSEvaluation ();
2069 /*-----------------------------------------------------------------*/
2070 /* genNot - generate code for ! operation */
2071 /*-----------------------------------------------------------------*/
2077 D (emitcode (";", "genNot"));
2079 /* assign asmOps to operand & result */
2080 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2081 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
2083 /* if in bit space then a special case */
2084 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2086 /* if left==result then cpl bit */
2087 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2089 emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2093 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2094 emitcode ("cpl", "c");
2095 outBitC (IC_RESULT (ic));
2100 toBoolean (IC_LEFT (ic));
2102 /* set C, if a == 0 */
2103 tlbl = newiTempLabel (NULL);
2104 emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
2106 outBitC (IC_RESULT (ic));
2109 /* release the aops */
2110 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2111 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2115 /*-----------------------------------------------------------------*/
2116 /* genCpl - generate code for complement */
2117 /*-----------------------------------------------------------------*/
2124 sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
2126 D(emitcode (";", "genCpl"));
2128 /* assign asmOps to operand & result */
2129 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2130 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
2132 /* special case if in bit space */
2133 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2137 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
2138 (SPEC_USIGN (letype) && IS_CHAR (letype)))
2140 /* promotion rules are responsible for this strange result:
2141 bit -> int -> ~int -> bit
2142 uchar -> int -> ~int -> bit
2144 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
2148 tlbl=newiTempLabel(NULL);
2149 l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE, NULL);
2150 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
2151 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
2152 IS_AOP_PREG (IC_LEFT (ic)))
2154 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
2159 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
2162 outBitC (IC_RESULT(ic));
2166 size = AOP_SIZE (IC_RESULT (ic));
2167 _startLazyDPSEvaluation ();
2170 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL);
2172 emitcode ("cpl", "a");
2173 aopPut (IC_RESULT (ic), "a", offset++);
2175 _endLazyDPSEvaluation ();
2179 /* release the aops */
2180 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2181 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2184 /*-----------------------------------------------------------------*/
2185 /* genUminusFloat - unary minus for floating points */
2186 /*-----------------------------------------------------------------*/
2188 genUminusFloat (operand * op, operand * result)
2190 int size, offset = 0;
2193 D (emitcode (";", "genUminusFloat"));
2195 /* for this we just copy and then flip the bit */
2197 _startLazyDPSEvaluation ();
2198 size = AOP_SIZE (op) - 1;
2203 aopGet (op, offset, FALSE, FALSE, NULL),
2208 l = aopGet (op, offset, FALSE, FALSE, NULL);
2211 emitcode ("cpl", "acc.7");
2212 aopPut (result, "a", offset);
2213 _endLazyDPSEvaluation ();
2216 /*-----------------------------------------------------------------*/
2217 /* genUminus - unary minus code generation */
2218 /*-----------------------------------------------------------------*/
2220 genUminus (iCode * ic)
2225 D (emitcode (";", "genUminus"));
2228 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2229 aopOp (IC_RESULT (ic), ic, TRUE, (AOP_TYPE(IC_LEFT (ic)) == AOP_DPTR));
2231 /* if both in bit space then special
2233 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2234 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2237 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2238 emitcode ("cpl", "c");
2239 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2243 optype = operandType (IC_LEFT (ic));
2245 /* if float then do float stuff */
2246 if (IS_FLOAT (optype))
2248 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2252 /* otherwise subtract from zero */
2253 size = AOP_SIZE (IC_LEFT (ic));
2255 _startLazyDPSEvaluation ();
2258 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL);
2259 if (!strcmp (l, "a"))
2263 emitcode ("cpl", "a");
2264 emitcode ("addc", "a,#0");
2270 emitcode ("clr", "a");
2271 emitcode ("subb", "a,%s", l);
2273 aopPut (IC_RESULT (ic), "a", offset++);
2275 _endLazyDPSEvaluation ();
2277 /* if any remaining bytes in the result */
2278 /* we just need to propagate the sign */
2279 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2281 emitcode ("rlc", "a");
2282 emitcode ("subb", "a,acc");
2284 aopPut (IC_RESULT (ic), "a", offset++);
2288 /* release the aops */
2289 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2290 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2293 /*-----------------------------------------------------------------*/
2294 /* savermask - saves registers in the mask */
2295 /*-----------------------------------------------------------------*/
2296 static void savermask(bitVect *rs_mask)
2300 if (options.useXstack)
2302 if (bitVectBitValue (rs_mask, R0_IDX))
2303 emitcode ("mov", "b,r0");
2304 emitcode ("mov", "r0,%s", spname);
2305 for (i = 0; i < ds390_nRegs; i++)
2307 if (bitVectBitValue (rs_mask, i))
2310 emitcode ("mov", "a,b");
2312 emitcode ("mov", "a,%s", REG_WITH_INDEX (i)->name);
2313 emitcode ("movx", "@r0,a");
2314 emitcode ("inc", "r0");
2317 emitcode ("mov", "%s,r0", spname);
2318 if (bitVectBitValue (rs_mask, R0_IDX))
2319 emitcode ("mov", "r0,b");
2323 bool bits_pushed = FALSE;
2324 for (i = 0; i < ds390_nRegs; i++)
2326 if (bitVectBitValue (rs_mask, i))
2328 bits_pushed = pushReg (i, bits_pushed);
2334 /*-----------------------------------------------------------------*/
2335 /* saveRegisters - will look for a call and save the registers */
2336 /*-----------------------------------------------------------------*/
2338 saveRegisters (iCode * lic)
2344 for (ic = lic; ic; ic = ic->next)
2345 if (ic->op == CALL || ic->op == PCALL)
2350 fprintf (stderr, "found parameter push with no function call\n");
2354 /* if the registers have been saved already or don't need to be then
2357 || (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))) && !TARGET_IS_DS400) )
2360 /* special case if DPTR alive across a function call then must save it
2361 even though callee saves */
2362 if (IS_SYMOP(IC_LEFT(ic)) &&
2363 IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type))
2366 rsave = newBitVect(ic->rMask->size);
2367 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2368 if (bitVectBitValue(ic->rMask,i))
2369 rsave = bitVectSetBit(rsave,i);
2371 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2375 /* save the registers in use at this time but skip the
2376 ones for the result */
2377 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2378 ds390_rUmaskForOp (IC_RESULT(ic)));
2384 /*-----------------------------------------------------------------*/
2385 /* usavermask - restore registers with mask */
2386 /*-----------------------------------------------------------------*/
2387 static void unsavermask(bitVect *rs_mask)
2391 if (options.useXstack)
2393 emitcode ("mov", "r0,%s", spname);
2394 for (i = ds390_nRegs; i >= 0; i--)
2396 if (bitVectBitValue (rs_mask, i))
2398 regs * reg = REG_WITH_INDEX (i);
2399 emitcode ("dec", "r0");
2400 emitcode ("movx", "a,@r0");
2403 emitcode ("push", "acc");
2407 emitcode ("mov", "%s,a", reg->name);
2411 emitcode ("mov", "%s,r0", spname);
2412 if (bitVectBitValue (rs_mask, R0_IDX))
2414 emitcode ("pop", "ar0");
2419 bool bits_popped = FALSE;
2420 for (i = ds390_nRegs; i >= 0; i--)
2422 if (bitVectBitValue (rs_mask, i))
2424 bits_popped = popReg (i, bits_popped);
2430 /*-----------------------------------------------------------------*/
2431 /* unsaveRegisters - pop the pushed registers */
2432 /*-----------------------------------------------------------------*/
2434 unsaveRegisters (iCode * ic)
2438 if (IS_SYMOP(IC_LEFT (ic)) &&
2439 IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2441 rsave = newBitVect(ic->rMask->size);
2442 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2443 if (bitVectBitValue(ic->rMask,i))
2444 rsave = bitVectSetBit(rsave,i);
2446 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2448 /* restore the registers in use at this time but skip the
2449 ones for the result */
2450 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2451 ds390_rUmaskForOp (IC_RESULT(ic)));
2457 /*-----------------------------------------------------------------*/
2459 /*-----------------------------------------------------------------*/
2461 pushSide (operand * oper, int size)
2464 _startLazyDPSEvaluation ();
2467 char *l = aopGet (oper, offset++, FALSE, TRUE, NULL);
2468 if (AOP_TYPE (oper) != AOP_REG &&
2469 AOP_TYPE (oper) != AOP_DIR &&
2473 emitcode ("push", "acc");
2477 emitcode ("push", "%s", l);
2480 _endLazyDPSEvaluation ();
2483 /*-----------------------------------------------------------------*/
2484 /* assignResultValue - also indicates if acc is in use afterwards */
2485 /*-----------------------------------------------------------------*/
2487 assignResultValue (operand * oper, operand * func)
2490 unsigned size = AOP_SIZE (oper);
2491 bool accuse = FALSE;
2492 bool pushedA = FALSE;
2494 if (func && IS_BIT (OP_SYM_ETYPE (func)))
2500 if (size == fReturnSizeDS390)
2502 /* I don't think this case can ever happen... */
2503 /* ACC is the last part of this. If writing the result
2504 * uses ACC, we must preserve it.
2506 if (AOP_NEEDSACC(oper))
2508 emitcode(";", "assignResultValue special case for ACC.");
2509 emitcode("push", "acc");
2515 _startLazyDPSEvaluation ();
2518 accuse |= aopPut (oper, fReturn[offset], offset);
2521 _endLazyDPSEvaluation ();
2525 emitcode ("pop", "acc");
2526 accuse |= aopPut (oper, "a", offset);
2532 /*-----------------------------------------------------------------*/
2533 /* genXpush - pushes onto the external stack */
2534 /*-----------------------------------------------------------------*/
2536 genXpush (iCode * ic)
2538 asmop *aop = newAsmop (0);
2540 int size, offset = 0;
2542 D (emitcode (";", "genXpush"));
2544 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2545 r = getFreePtr (ic, &aop, FALSE);
2547 size = AOP_SIZE (IC_LEFT (ic));
2551 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
2552 emitcode ("mov", "%s,_spx", r->name);
2553 emitcode ("inc", "_spx"); // allocate space first
2554 emitcode ("movx", "@%s,a", r->name);
2558 // allocate space first
2559 emitcode ("mov", "%s,_spx", r->name);
2561 emitcode ("add", "a,#%d", size);
2562 emitcode ("mov", "_spx,a");
2564 _startLazyDPSEvaluation ();
2567 MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE, NULL));
2568 emitcode ("movx", "@%s,a", r->name);
2569 emitcode ("inc", "%s", r->name);
2571 _endLazyDPSEvaluation ();
2574 freeAsmop (NULL, aop, ic, TRUE);
2575 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2578 /*-----------------------------------------------------------------*/
2579 /* genIpush - generate code for pushing this gets a little complex */
2580 /*-----------------------------------------------------------------*/
2582 genIpush (iCode * ic)
2584 int size, offset = 0;
2588 D (emitcode (";", "genIpush"));
2590 /* if this is not a parm push : ie. it is spill push
2591 and spill push is always done on the local stack */
2595 /* and the item is spilt then do nothing */
2596 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2599 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2600 size = AOP_SIZE (IC_LEFT (ic));
2601 /* push it on the stack */
2602 _startLazyDPSEvaluation ();
2605 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE, NULL);
2611 emitcode ("push", "%s", l);
2613 _endLazyDPSEvaluation ();
2617 /* this is a parameter push: in this case we call
2618 the routine to find the call and save those
2619 registers that need to be saved */
2622 /* if use external stack then call the external
2623 stack pushing routine */
2624 if (options.useXstack)
2630 /* then do the push */
2631 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2633 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2634 size = AOP_SIZE (IC_LEFT (ic));
2636 _startLazyDPSEvaluation ();
2639 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE, NULL);
2640 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2641 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2644 if (strcmp (l, prev) || *l == '@')
2646 emitcode ("push", "acc");
2650 emitcode ("push", "%s", l);
2654 _endLazyDPSEvaluation ();
2656 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2659 /*-----------------------------------------------------------------*/
2660 /* genIpop - recover the registers: can happen only for spilling */
2661 /*-----------------------------------------------------------------*/
2663 genIpop (iCode * ic)
2667 D (emitcode (";", "genIpop"));
2669 /* if the temp was not pushed then */
2670 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2673 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2674 size = AOP_SIZE (IC_LEFT (ic));
2675 offset = (size - 1);
2676 _startLazyDPSEvaluation ();
2679 emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2680 FALSE, TRUE, NULL));
2682 _endLazyDPSEvaluation ();
2684 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2687 /*-----------------------------------------------------------------*/
2688 /* saveRBank - saves an entire register bank on the stack */
2689 /*-----------------------------------------------------------------*/
2691 saveRBank (int bank, iCode * ic, bool pushPsw)
2694 int count = 8 + (ds390_nBitRegs/8) + (pushPsw ? 1 : 0);
2698 if (options.useXstack)
2702 /* Assume r0 is available for use. */
2703 r = REG_WITH_INDEX (R0_IDX);;
2708 r = getFreePtr (ic, &aop, FALSE);
2710 // allocate space first
2711 emitcode ("mov", "%s,_spx", r->name);
2713 emitcode ("add", "a,#%d", count);
2714 emitcode ("mov", "_spx,a");
2717 for (i = 0; i < 8; i++) /* only R0-R7 needs saving */
2719 if (options.useXstack)
2721 emitcode ("mov", "a,(%s+%d)",
2722 regs390[i].base, 8 * bank + regs390[i].offset);
2723 emitcode ("movx", "@%s,a", r->name);
2725 emitcode ("inc", "%s", r->name);
2728 emitcode ("push", "(%s+%d)",
2729 regs390[i].base, 8 * bank + regs390[i].offset);
2732 if (ds390_nBitRegs > 0)
2734 if (options.useXstack)
2736 emitcode ("mov", "a,bits");
2737 emitcode ("movx", "@%s,a", r->name);
2739 emitcode ("inc", "%s", r->name);
2743 emitcode ("push", "bits");
2750 if (options.useXstack)
2752 emitcode ("mov", "a,psw");
2753 emitcode ("movx", "@%s,a", r->name);
2757 emitcode ("push", "psw");
2760 emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2765 freeAsmop (NULL, aop, ic, TRUE);
2774 /*-----------------------------------------------------------------*/
2775 /* unsaveRBank - restores the register bank from stack */
2776 /*-----------------------------------------------------------------*/
2778 unsaveRBank (int bank, iCode * ic, bool popPsw)
2784 if (options.useXstack)
2788 /* Assume r0 is available for use. */
2789 r = REG_WITH_INDEX (R0_IDX);;
2794 r = getFreePtr (ic, &aop, FALSE);
2796 emitcode ("mov", "%s,_spx", r->name);
2801 if (options.useXstack)
2803 emitcode ("dec", "%s", r->name);
2804 emitcode ("movx", "a,@%s", r->name);
2805 emitcode ("mov", "psw,a");
2809 emitcode ("pop", "psw");
2813 if (ds390_nBitRegs > 0)
2815 if (options.useXstack)
2817 emitcode ("dec", "%s", r->name);
2818 emitcode ("movx", "a,@%s", r->name);
2819 emitcode ("mov", "bits,a");
2823 emitcode ("pop", "bits");
2827 for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2829 if (options.useXstack)
2831 emitcode ("dec", "%s", r->name);
2832 emitcode ("movx", "a,@%s", r->name);
2833 emitcode ("mov", "(%s+%d),a",
2834 regs390[i].base, 8 * bank + regs390[i].offset);
2838 emitcode ("pop", "(%s+%d)",
2839 regs390[i].base, 8 * bank + regs390[i].offset);
2843 if (options.useXstack)
2845 emitcode ("mov", "_spx,%s", r->name);
2850 freeAsmop (NULL, aop, ic, TRUE);
2854 /*-----------------------------------------------------------------*/
2855 /* genSend - gen code for SEND */
2856 /*-----------------------------------------------------------------*/
2857 static void genSend(set *sendSet)
2862 static int rb1_count = 0;
2864 /* first we do all bit parameters */
2865 for (sic = setFirstItem (sendSet); sic;
2866 sic = setNextItem (sendSet))
2868 if (sic->argreg > 12)
2870 int bit = sic->argreg-13;
2872 aopOp (IC_LEFT (sic), sic, FALSE,
2873 (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2875 /* if left is a literal then
2876 we know what the value is */
2877 if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2879 if (((int) operandLitValue (IC_LEFT (sic))))
2880 emitcode ("setb", "b[%d]", bit);
2882 emitcode ("clr", "b[%d]", bit);
2884 else if (AOP_TYPE (IC_LEFT (sic)) == AOP_CRY)
2886 char *l = AOP (IC_LEFT (sic))->aopu.aop_dir;
2887 if (strcmp (l, "c"))
2888 emitcode ("mov", "c,%s", l);
2889 emitcode ("mov", "b[%d],c", bit);
2894 toBoolean (IC_LEFT (sic));
2895 /* set C, if a >= 1 */
2896 emitcode ("add", "a,#0xff");
2897 emitcode ("mov", "b[%d],c", bit);
2902 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2908 saveRegisters (setFirstItem (sendSet));
2909 emitcode ("mov", "bits,b");
2912 /* then we do all other parameters */
2913 for (sic = setFirstItem (sendSet); sic;
2914 sic = setNextItem (sendSet))
2916 if (sic->argreg <= 12)
2918 int size, offset = 0;
2920 size = getSize (operandType (IC_LEFT (sic)));
2921 D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2922 if (sendCount == 0) { /* first parameter */
2923 // we know that dpl(hxb) is the result, so
2925 _startLazyDPSEvaluation ();
2927 aopOp (IC_LEFT (sic), sic, FALSE,
2928 (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2930 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2934 char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE, NULL);
2935 if (strcmp (l, fReturn[offset]))
2937 emitcode ("mov", "%s,%s", fReturn[offset], l);
2941 _endLazyDPSEvaluation ();
2942 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2944 } else { /* if more parameter in registers */
2945 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2947 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (IC_LEFT (sic), offset++,
2948 FALSE, FALSE, NULL));
2950 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2958 adjustEsp(const char *reg)
2960 emitcode ("anl","%s,#3", reg);
2961 if (TARGET_IS_DS400)
2963 emitcode ("orl","%s,#!constbyte",
2965 (options.stack_loc >> 8) & 0xff);
2969 /*-----------------------------------------------------------------*/
2970 /* selectRegBank - emit code to select the register bank */
2971 /*-----------------------------------------------------------------*/
2973 selectRegBank (short bank, bool keepFlags)
2975 /* if f.e. result is in carry */
2978 emitcode ("anl", "psw,#0xE7");
2980 emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2984 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2988 /*-----------------------------------------------------------------*/
2989 /* genCall - generates a call statement */
2990 /*-----------------------------------------------------------------*/
2992 genCall (iCode * ic)
2996 bool restoreBank = FALSE;
2997 bool swapBanks = FALSE;
2998 bool accuse = FALSE;
2999 bool accPushed = FALSE;
3000 bool resultInF0 = FALSE;
3001 bool assignResultGenerated = FALSE;
3003 D (emitcode (";", "genCall"));
3005 /* if we are calling a not _naked function that is not using
3006 the same register bank then we need to save the
3007 destination registers on the stack */
3008 dtype = operandType (IC_LEFT (ic));
3009 etype = getSpec(dtype);
3010 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
3011 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
3012 IFFUNC_ISISR (currFunc->type))
3016 /* This is unexpected; the bank should have been saved in
3019 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
3025 /* if caller saves & we have not saved then */
3029 /* if send set is not empty then assign */
3030 /* We've saved all the registers we care about;
3031 * therefore, we may clobber any register not used
3032 * in the calling convention (i.e. anything not in
3037 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
3038 genSend(reverseSet(_G.sendSet));
3040 genSend(_G.sendSet);
3047 emitcode ("mov", "psw,#!constbyte",
3048 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3052 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
3053 OP_SYMBOL (IC_LEFT (ic))->rname :
3054 OP_SYMBOL (IC_LEFT (ic))->name));
3058 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
3061 /* if we need assign a result value */
3062 if ((IS_ITEMP (IC_RESULT (ic)) &&
3063 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3064 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3065 OP_SYMBOL (IC_RESULT (ic))->accuse ||
3066 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3067 IS_TRUE_SYMOP (IC_RESULT (ic)))
3069 if (isOperandInFarSpace (IC_RESULT (ic))
3070 && getSize (operandType (IC_RESULT (ic))) <= 2)
3072 int size = getSize (operandType (IC_RESULT (ic)));
3073 bool pushedB = FALSE;
3075 /* Special case for 1 or 2 byte return in far space. */
3080 emitcode ("mov", "b,%s", fReturn[1]);
3084 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
3089 aopPut (IC_RESULT (ic), "a", 0);
3093 aopPut (IC_RESULT (ic), "b", 1);
3095 assignResultGenerated = TRUE;
3096 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3100 bool pushedB = pushB ();
3101 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
3104 accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3105 assignResultGenerated = TRUE;
3106 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3110 /* adjust the stack for parameters if required */
3114 if (options.stack10bit) {
3115 if (ic->parmBytes <= 10) {
3116 emitcode(";","stack adjustment for parms");
3117 for (i=0; i < ic->parmBytes ; i++) {
3118 emitcode("pop","acc");
3122 emitcode ("clr","c");
3123 emitcode ("mov","a,sp");
3124 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
3125 emitcode ("mov","sp,a");
3126 emitcode ("mov","a,esp");
3128 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
3129 emitcode ("mov","esp,a");
3133 if (ic->parmBytes > 3)
3137 emitcode ("push", "acc");
3140 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3141 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3142 !assignResultGenerated)
3144 emitcode ("mov", "F0,c");
3148 emitcode ("mov", "a,%s", spname);
3149 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
3150 emitcode ("mov", "%s,a", spname);
3152 /* unsaveRegisters from xstack needs acc, but */
3153 /* unsaveRegisters from stack needs this popped */
3154 if (accPushed && !options.useXstack)
3156 emitcode ("pop", "acc");
3161 for (i = 0; i < ic->parmBytes; i++)
3162 emitcode ("dec", "%s", spname);
3166 /* if we had saved some registers then unsave them */
3167 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3169 if (accuse && !accPushed && options.useXstack)
3171 /* xstack needs acc, but doesn't touch normal stack */
3172 emitcode ("push", "acc");
3175 unsaveRegisters (ic);
3178 /* if register bank was saved then pop them */
3180 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
3182 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
3185 emitcode ("mov", "c,F0");
3187 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
3188 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3189 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3193 emitcode ("pop", "acc");
3196 /*-----------------------------------------------------------------*/
3197 /* genPcall - generates a call by pointer statement */
3198 /*-----------------------------------------------------------------*/
3200 genPcall (iCode * ic)
3204 symbol *rlbl = newiTempLabel (NULL);
3205 bool restoreBank=FALSE;
3206 bool resultInF0 = FALSE;
3208 D (emitcode (";", "genPcall"));
3210 dtype = operandType (IC_LEFT (ic))->next;
3211 etype = getSpec(dtype);
3212 /* if caller saves & we have not saved then */
3216 /* if we are calling a not _naked function that is not using
3217 the same register bank then we need to save the
3218 destination registers on the stack */
3219 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
3220 IFFUNC_ISISR (currFunc->type) &&
3221 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
3222 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3226 /* push the return address on to the stack */
3227 emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
3228 emitcode ("push", "acc");
3229 emitcode ("mov", "a,#!hil", (rlbl->key + 100));
3230 emitcode ("push", "acc");
3232 if (options.model == MODEL_FLAT24)
3234 emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
3235 emitcode ("push", "acc");
3238 /* now push the calling address */
3239 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3241 pushSide (IC_LEFT (ic), FPTRSIZE);
3243 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3245 /* if send set is not empty the assign */
3248 genSend(reverseSet(_G.sendSet));
3253 emitcode ("ret", "");
3257 /* if we need assign a result value */
3258 if ((IS_ITEMP (IC_RESULT (ic)) &&
3259 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3260 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3261 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3262 IS_TRUE_SYMOP (IC_RESULT (ic)))
3266 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
3269 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3271 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3274 /* adjust the stack for parameters if required */
3278 if (options.stack10bit) {
3279 if (ic->parmBytes <= 10) {
3280 emitcode(";","stack adjustment for parms");
3281 for (i=0; i < ic->parmBytes ; i++) {
3282 emitcode("pop","acc");
3285 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3286 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3288 emitcode ("mov", "F0,c");
3293 emitcode ("clr","c");
3294 emitcode ("mov","a,sp");
3295 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
3296 emitcode ("mov","sp,a");
3297 emitcode ("mov","a,esp");
3299 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
3300 emitcode ("mov","esp,a");
3304 if (ic->parmBytes > 3) {
3305 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3306 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3308 emitcode ("mov", "F0,c");
3312 emitcode ("mov", "a,%s", spname);
3313 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
3314 emitcode ("mov", "%s,a", spname);
3317 for (i = 0; i < ic->parmBytes; i++)
3318 emitcode ("dec", "%s", spname);
3321 /* if register bank was saved then unsave them */
3323 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3325 /* if we had saved some registers then unsave them */
3327 unsaveRegisters (ic);
3329 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3332 emitcode ("mov", "c,F0");
3334 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
3335 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3336 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3340 /*-----------------------------------------------------------------*/
3341 /* resultRemat - result is rematerializable */
3342 /*-----------------------------------------------------------------*/
3344 resultRemat (iCode * ic)
3346 if (SKIP_IC (ic) || ic->op == IFX)
3349 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3351 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3352 if (sym->remat && !POINTER_SET (ic))
3359 /*-----------------------------------------------------------------*/
3360 /* inExcludeList - return 1 if the string is in exclude Reg list */
3361 /*-----------------------------------------------------------------*/
3363 regsCmp(void *p1, void *p2)
3365 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3369 inExcludeList (char *s)
3371 const char *p = setFirstItem(options.excludeRegsSet);
3373 if (p == NULL || STRCASECMP(p, "none") == 0)
3377 return isinSetWith(options.excludeRegsSet, s, regsCmp);
3380 /*-----------------------------------------------------------------*/
3381 /* genFunction - generated code for function entry */
3382 /*-----------------------------------------------------------------*/
3384 genFunction (iCode * ic)
3386 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3388 bool switchedPSW = FALSE;
3389 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3391 D (emitcode (";", "genFunction"));
3394 /* create the function header */
3395 emitcode (";", "-----------------------------------------");
3396 emitcode (";", " function %s", sym->name);
3397 emitcode (";", "-----------------------------------------");
3399 emitcode ("", "%s:", sym->rname);
3400 lineCurr->isLabel = 1;
3401 ftype = operandType (IC_LEFT (ic));
3402 _G.currentFunc = sym;
3404 if (IFFUNC_ISNAKED(ftype))
3406 emitcode(";", "naked function: no prologue.");
3410 if (options.stack_probe)
3411 emitcode ("lcall","__stack_probe");
3413 /* here we need to generate the equates for the
3414 register bank if required */
3415 if (FUNC_REGBANK (ftype) != rbank)
3419 rbank = FUNC_REGBANK (ftype);
3420 for (i = 0; i < ds390_nRegs; i++)
3422 if (regs390[i].print) {
3423 if (strcmp (regs390[i].base, "0") == 0)
3424 emitcode ("", "%s !equ !constbyte",
3426 8 * rbank + regs390[i].offset);
3428 emitcode ("", "%s !equ %s + !constbyte",
3431 8 * rbank + regs390[i].offset);
3436 /* if this is an interrupt service routine then
3437 save acc, b, dpl, dph */
3438 if (IFFUNC_ISISR (sym->type))
3440 if (!inExcludeList ("acc"))
3441 emitcode ("push", "acc");
3442 if (!inExcludeList ("b"))
3443 emitcode ("push", "b");
3444 if (!inExcludeList ("dpl"))
3445 emitcode ("push", "dpl");
3446 if (!inExcludeList ("dph"))
3447 emitcode ("push", "dph");
3448 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3450 emitcode ("push", "dpx");
3451 /* Make sure we're using standard DPTR */
3452 emitcode ("push", "dps");
3453 emitcode ("mov", "dps,#0");
3454 if (options.stack10bit)
3456 /* This ISR could conceivably use DPTR2. Better save it. */
3457 emitcode ("push", "dpl1");
3458 emitcode ("push", "dph1");
3459 emitcode ("push", "dpx1");
3460 emitcode ("push", DP2_RESULT_REG);
3463 /* if this isr has no bank i.e. is going to
3464 run with bank 0 , then we need to save more
3466 if (!FUNC_REGBANK (sym->type))
3470 /* if this function does not call any other
3471 function then we can be economical and
3472 save only those registers that are used */
3473 if (!IFFUNC_HASFCALL(sym->type))
3475 /* if any registers used */
3478 bool bits_pushed = FALSE;
3479 /* save the registers used */
3480 for (i = 0; i < sym->regsUsed->size; i++)
3482 if (bitVectBitValue (sym->regsUsed, i))
3483 bits_pushed = pushReg (i, bits_pushed);
3489 /* this function has a function call. We cannot
3490 determine register usage so we will have to push the
3492 saveRBank (0, ic, FALSE);
3493 if (options.parms_in_bank1) {
3494 for (i=0; i < 8 ; i++ ) {
3495 emitcode ("push","%s",rb1regs[i]);
3502 /* This ISR uses a non-zero bank.
3504 * We assume that the bank is available for our
3507 * However, if this ISR calls a function which uses some
3508 * other bank, we must save that bank entirely.
3510 unsigned long banksToSave = 0;
3512 if (IFFUNC_HASFCALL(sym->type))
3515 #define MAX_REGISTER_BANKS 4
3520 for (i = ic; i; i = i->next)
3522 if (i->op == ENDFUNCTION)
3524 /* we got to the end OK. */
3532 dtype = operandType (IC_LEFT(i));
3534 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3536 /* Mark this bank for saving. */
3537 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3539 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3543 banksToSave |= (1 << FUNC_REGBANK(dtype));
3546 /* And note that we don't need to do it in
3554 /* This is a mess; we have no idea what
3555 * register bank the called function might
3558 * The only thing I can think of to do is
3559 * throw a warning and hope.
3561 werror(W_FUNCPTR_IN_USING_ISR);
3565 if (banksToSave && options.useXstack)
3567 /* Since we aren't passing it an ic,
3568 * saveRBank will assume r0 is available to abuse.
3570 * So switch to our (trashable) bank now, so
3571 * the caller's R0 isn't trashed.
3573 emitcode ("push", "psw");
3574 emitcode ("mov", "psw,#!constbyte",
3575 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3579 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3581 if (banksToSave & (1 << ix))
3583 saveRBank(ix, NULL, FALSE);
3587 // TODO: this needs a closer look
3588 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3593 /* if callee-save to be used for this function
3594 then save the registers being used in this function */
3595 if (IFFUNC_CALLEESAVES(sym->type))
3599 /* if any registers used */
3602 bool bits_pushed = FALSE;
3603 /* save the registers used */
3604 for (i = 0; i < sym->regsUsed->size; i++)
3606 if (bitVectBitValue (sym->regsUsed, i))
3608 bits_pushed = pushReg (i, bits_pushed);
3616 /* set the register bank to the desired value */
3617 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3620 emitcode ("push", "psw");
3621 emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3625 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3626 if (options.stack10bit) {
3627 emitcode ("push","_bpx");
3628 emitcode ("push","_bpx+1");
3629 emitcode ("mov","_bpx,%s",spname);
3630 emitcode ("mov","_bpx+1,esp");
3631 adjustEsp("_bpx+1");
3633 if (options.useXstack)
3635 emitcode ("mov", "r0,%s", spname);
3636 emitcode ("mov", "a,_bp");
3637 emitcode ("movx", "@r0,a");
3638 emitcode ("inc", "%s", spname);
3640 /* set up the stack */
3641 emitcode ("push", "_bp"); /* save the callers stack */
3643 emitcode ("mov", "_bp,%s", spname);
3647 /* adjust the stack for the function */
3650 if (options.stack10bit) {
3651 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
3652 assert (sym->recvSize <= 4);
3653 if (sym->stack <= 8) {
3654 while (i--) emitcode ("push","acc");
3657 emitcode ("mov","a,sp");
3658 emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3659 emitcode ("mov","sp,a");
3660 emitcode ("mov","a,esp");
3662 emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3663 emitcode ("mov","esp,a");
3668 werror (W_STACK_OVERFLOW, sym->name);
3670 if (i > 3 && sym->recvSize < 4) {
3672 emitcode ("mov", "a,sp");
3673 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3674 emitcode ("mov", "sp,a");
3678 emitcode ("inc", "sp");
3685 emitcode ("mov", "a,_spx");
3686 emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3687 emitcode ("mov", "_spx,a");
3690 /* if critical function then turn interrupts off */
3691 if (IFFUNC_ISCRITICAL (ftype))
3693 symbol *tlbl = newiTempLabel (NULL);
3694 emitcode ("setb", "c");
3695 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3696 emitcode ("clr", "c");
3698 emitcode ("push", "psw"); /* save old ea via c in psw */
3702 /*-----------------------------------------------------------------*/
3703 /* genEndFunction - generates epilogue for functions */
3704 /*-----------------------------------------------------------------*/
3706 genEndFunction (iCode * ic)
3708 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3709 lineNode *lnp = lineCurr;
3711 bitVect *regsUsedPrologue;
3712 bitVect *regsUnneeded;
3715 D (emitcode (";", "genEndFunction"));
3717 _G.currentFunc = NULL;
3718 if (IFFUNC_ISNAKED(sym->type))
3720 emitcode(";", "naked function: no epilogue.");
3721 if (options.debug && currFunc)
3722 debugFile->writeEndFunction (currFunc, ic, 0);
3726 if (IFFUNC_ISCRITICAL (sym->type))
3728 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3730 emitcode ("rlc", "a"); /* save c in a */
3731 emitcode ("pop", "psw"); /* restore ea via c in psw */
3732 emitcode ("mov", "ea,c");
3733 emitcode ("rrc", "a"); /* restore c from a */
3737 emitcode ("pop", "psw"); /* restore ea via c in psw */
3738 emitcode ("mov", "ea,c");
3742 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3743 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3745 if (options.stack10bit) {
3747 emitcode ("mov", "sp,_bpx", spname);
3748 emitcode ("mov", "esp,_bpx+1", spname);
3751 emitcode ("mov", "%s,_bp", spname);
3755 /* if use external stack but some variables were
3756 added to the local stack then decrement the
3758 if (options.useXstack && sym->stack) {
3759 emitcode ("mov", "a,sp");
3760 emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3761 emitcode ("mov", "sp,a");
3765 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3766 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3768 if (options.useXstack) {
3769 emitcode ("mov", "r0,%s", spname);
3770 emitcode ("movx", "a,@r0");
3771 emitcode ("mov", "_bp,a");
3772 emitcode ("dec", "%s", spname);
3774 if (options.stack10bit) {
3775 emitcode ("pop", "_bpx+1");
3776 emitcode ("pop", "_bpx");
3778 emitcode ("pop", "_bp");
3783 /* restore the register bank */
3784 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3786 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3787 || !options.useXstack)
3789 /* Special case of ISR using non-zero bank with useXstack
3792 emitcode ("pop", "psw");
3796 if (IFFUNC_ISISR (sym->type))
3799 /* now we need to restore the registers */
3800 /* if this isr has no bank i.e. is going to
3801 run with bank 0 , then we need to save more
3803 if (!FUNC_REGBANK (sym->type))
3806 /* if this function does not call any other
3807 function then we can be economical and
3808 save only those registers that are used */
3809 if (!IFFUNC_HASFCALL(sym->type))
3811 /* if any registers used */
3814 bool bits_popped = FALSE;
3815 /* save the registers used */
3816 for (i = sym->regsUsed->size; i >= 0; i--)
3818 if (bitVectBitValue (sym->regsUsed, i))
3819 bits_popped = popReg (i, bits_popped);
3825 /* this function has a function call. We cannot
3826 determine register usage so we will have to pop the
3828 if (options.parms_in_bank1) {
3829 for (i = 7 ; i >= 0 ; i-- ) {
3830 emitcode ("pop","%s",rb1regs[i]);
3833 unsaveRBank (0, ic, FALSE);
3838 /* This ISR uses a non-zero bank.
3840 * Restore any register banks saved by genFunction
3843 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3846 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3848 if (savedBanks & (1 << ix))
3850 unsaveRBank(ix, NULL, FALSE);
3854 if (options.useXstack)
3856 /* Restore bank AFTER calling unsaveRBank,
3857 * since it can trash r0.
3859 emitcode ("pop", "psw");
3863 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3865 if (options.stack10bit)
3867 emitcode ("pop", DP2_RESULT_REG);
3868 emitcode ("pop", "dpx1");
3869 emitcode ("pop", "dph1");
3870 emitcode ("pop", "dpl1");
3872 emitcode ("pop", "dps");
3873 emitcode ("pop", "dpx");
3875 if (!inExcludeList ("dph"))
3876 emitcode ("pop", "dph");
3877 if (!inExcludeList ("dpl"))
3878 emitcode ("pop", "dpl");
3879 if (!inExcludeList ("b"))
3880 emitcode ("pop", "b");
3881 if (!inExcludeList ("acc"))
3882 emitcode ("pop", "acc");
3884 /* if debug then send end of function */
3885 if (options.debug && currFunc)
3887 debugFile->writeEndFunction (currFunc, ic, 1);
3890 emitcode ("reti", "");
3894 if (IFFUNC_CALLEESAVES(sym->type))
3898 /* if any registers used */
3901 /* save the registers used */
3902 for (i = sym->regsUsed->size; i >= 0; i--)
3904 if (bitVectBitValue (sym->regsUsed, i))
3905 emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
3910 /* if debug then send end of function */
3911 if (options.debug && currFunc)
3913 debugFile->writeEndFunction (currFunc, ic, 1);
3916 emitcode ("ret", "");
3919 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3922 /* If this was an interrupt handler using bank 0 that called another */
3923 /* function, then all registers must be saved; nothing to optimized. */
3924 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3925 && !FUNC_REGBANK(sym->type))
3928 /* There are no push/pops to optimize if not callee-saves or ISR */
3929 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3932 /* If there were stack parameters, we cannot optimize without also */
3933 /* fixing all of the stack offsets; this is too dificult to consider. */
3934 if (FUNC_HASSTACKPARM(sym->type))
3937 /* Compute the registers actually used */
3938 regsUsed = newBitVect (ds390_nRegs);
3939 regsUsedPrologue = newBitVect (ds390_nRegs);
3942 if (lnp->ic && lnp->ic->op == FUNCTION)
3943 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3945 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3947 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3948 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3955 if (bitVectBitValue (regsUsedPrologue, DPS_IDX)
3956 && !bitVectBitValue (regsUsed, DPS_IDX))
3958 bitVectUnSetBit (regsUsedPrologue, DPS_IDX);
3961 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3962 && !bitVectBitValue (regsUsed, CND_IDX))
3964 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3965 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3966 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3967 bitVectUnSetBit (regsUsed, CND_IDX);
3970 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3972 /* If this was an interrupt handler that called another function */
3973 /* function, then assume working registers may be modified by it. */
3974 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3976 regsUsed = bitVectSetBit (regsUsed, AP_IDX);
3977 regsUsed = bitVectSetBit (regsUsed, DPX1_IDX);
3978 regsUsed = bitVectSetBit (regsUsed, DPL1_IDX);
3979 regsUsed = bitVectSetBit (regsUsed, DPH1_IDX);
3980 regsUsed = bitVectSetBit (regsUsed, DPX_IDX);
3981 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3982 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3983 regsUsed = bitVectSetBit (regsUsed, DPS_IDX);
3984 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3985 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3986 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3989 /* Remove the unneeded push/pops */
3990 regsUnneeded = newBitVect (ds390_nRegs);
3993 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3995 if (!strncmp(lnp->line, "push", 4))
3997 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3998 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4000 connectLine (lnp->prev, lnp->next);
4001 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4004 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
4006 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
4007 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4009 connectLine (lnp->prev, lnp->next);
4010 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4017 for (idx = 0; idx < regsUnneeded->size; idx++)
4018 if (bitVectBitValue (regsUnneeded, idx))
4019 emitcode (";", "eliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
4021 freeBitVect (regsUnneeded);
4022 freeBitVect (regsUsed);
4023 freeBitVect (regsUsedPrologue);
4026 /*-----------------------------------------------------------------*/
4027 /* genJavaNativeRet - generate code for return JavaNative */
4028 /*-----------------------------------------------------------------*/
4029 static void genJavaNativeRet(iCode *ic)
4033 aopOp (IC_LEFT (ic), ic, FALSE,
4034 AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
4035 size = AOP_SIZE (IC_LEFT (ic));
4039 /* it is assigned to GPR0-R3 then push them */
4040 if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
4041 aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
4042 for (i = 0 ; i < size ; i++ ) {
4043 emitcode ("push","%s",
4044 aopGet(IC_LEFT(ic),i,FALSE,TRUE,DP2_RESULT_REG));
4046 for (i = (size-1) ; i >= 0 ; i--) {
4047 emitcode ("pop","a%s",javaRet[i]);
4050 for (i = 0 ; i < size ; i++)
4051 emitcode ("mov","%s,%s",javaRet[i],
4052 aopGet(IC_LEFT(ic),i,FALSE,TRUE,DP2_RESULT_REG));
4054 for (i = size ; i < 4 ; i++ )
4055 emitcode ("mov","%s,#0",javaRet[i]);
4059 /*-----------------------------------------------------------------*/
4060 /* genRet - generate code for return statement */
4061 /*-----------------------------------------------------------------*/
4065 int size, offset = 0, pushed = 0;
4067 D (emitcode (";", "genRet"));
4069 /* if we have no return value then
4070 just generate the "ret" */
4074 /* if this is a JavaNative function then return
4075 value in different register */
4076 if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
4077 genJavaNativeRet(ic);
4080 /* we have something to return then
4081 move the return value into place */
4082 aopOp (IC_LEFT (ic), ic, FALSE,
4083 (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
4084 size = AOP_SIZE (IC_LEFT (ic));
4086 _startLazyDPSEvaluation ();
4088 if (IS_BIT(_G.currentFunc->etype))
4090 movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4097 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
4099 l = aopGet (IC_LEFT (ic), offset++,
4101 emitcode ("push", "%s", l);
4106 /* Since A is the last element of fReturn,
4107 * it is OK to clobber it in the aopGet.
4109 l = aopGet (IC_LEFT (ic), offset,
4110 FALSE, FALSE, NULL);
4111 if (strcmp (fReturn[offset], l))
4112 emitcode ("mov", "%s,%s", fReturn[offset++], l);
4115 _endLazyDPSEvaluation ();
4120 if (strcmp (fReturn[pushed], "a"))
4121 emitcode ("pop", fReturn[pushed]);
4123 emitcode ("pop", "acc");
4125 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
4128 /* generate a jump to the return label
4129 if the next is not the return statement */
4130 if (!(ic->next && ic->next->op == LABEL &&
4131 IC_LABEL (ic->next) == returnLabel))
4133 emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
4137 /*-----------------------------------------------------------------*/
4138 /* genLabel - generates a label */
4139 /*-----------------------------------------------------------------*/
4141 genLabel (iCode * ic)
4143 /* special case never generate */
4144 if (IC_LABEL (ic) == entryLabel)
4147 D (emitcode (";", "genLabel"));
4149 emitLabel (IC_LABEL (ic));
4152 /*-----------------------------------------------------------------*/
4153 /* genGoto - generates a ljmp */
4154 /*-----------------------------------------------------------------*/
4156 genGoto (iCode * ic)
4158 D (emitcode (";", "genGoto"));
4160 emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
4163 /*-----------------------------------------------------------------*/
4164 /* findLabelBackwards: walks back through the iCode chain looking */
4165 /* for the given label. Returns number of iCode instructions */
4166 /* between that label and given ic. */
4167 /* Returns zero if label not found. */
4168 /*-----------------------------------------------------------------*/
4170 findLabelBackwards (iCode * ic, int key)
4179 /* If we have any pushes or pops, we cannot predict the distance.
4180 I don't like this at all, this should be dealt with in the
4182 if (ic->op == IPUSH || ic->op == IPOP) {
4186 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4188 /* printf("findLabelBackwards = %d\n", count); */
4196 /*-----------------------------------------------------------------*/
4197 /* genPlusIncr :- does addition with increment if possible */
4198 /*-----------------------------------------------------------------*/
4200 genPlusIncr (iCode * ic)
4202 unsigned int icount;
4203 unsigned int size = getDataSize (IC_RESULT (ic));
4205 /* will try to generate an increment */
4206 /* if the right side is not a literal
4208 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4211 /* if the literal value of the right hand side
4212 is greater than 4 then it is not worth it */
4213 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4216 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4217 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4219 emitcode("inc","%s",aopGet(IC_RESULT(ic),0,FALSE,FALSE,NULL));
4223 /* if increment 16 bits in register */
4225 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4226 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4227 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4236 /* If the next instruction is a goto and the goto target
4237 * is <= 5 instructions previous to this, we can generate
4238 * jumps straight to that target.
4240 if (ic->next && ic->next->op == GOTO
4241 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4244 D (emitcode (";", "tail increment optimized (range %d)", labelRange));
4245 tlbl = IC_LABEL (ic->next);
4250 tlbl = newiTempLabel (NULL);
4253 l = aopGet (IC_RESULT (ic), LSB, FALSE, FALSE, NULL);
4254 emitcode ("inc", "%s", l);
4256 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4257 IS_AOP_PREG (IC_RESULT (ic)))
4259 emitcode ("cjne", "%s,%s,!tlabel", l, zero, tlbl->key + 100);
4263 emitcode ("clr", "a");
4264 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4267 l = aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE, NULL);
4268 emitcode ("inc", "%s", l);
4271 if (!strcmp(l, "acc"))
4273 emitcode("jnz", "!tlabel", tlbl->key + 100);
4275 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4276 IS_AOP_PREG (IC_RESULT (ic)))
4278 emitcode ("cjne", "%s,%s,!tlabel", l, zero, tlbl->key + 100);
4282 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4285 l = aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE, NULL);
4286 emitcode ("inc", "%s", l);
4290 if (!strcmp(l, "acc"))
4292 emitcode("jnz", "!tlabel", tlbl->key + 100);
4294 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4295 IS_AOP_PREG (IC_RESULT (ic)))
4297 emitcode ("cjne", "%s,%s,!tlabel", l, zero, tlbl->key + 100);
4301 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4304 l = aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE, NULL);
4305 emitcode ("inc", "%s", l);
4315 if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
4316 !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 &&
4317 options.model == MODEL_FLAT24 )
4319 if (IC_RESULT(ic)->isGptr)
4321 emitcode ("mov", "b,%s", aopGet(IC_LEFT (ic), 3, FALSE, FALSE, NULL));
4325 emitcode ("mov", "dpx,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE, NULL));
4327 emitcode ("mov", "dph,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE, NULL));
4329 emitcode ("mov", "dpl,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4333 emitcode ("inc", "dptr");
4337 if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
4338 AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
4340 emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
4342 emitcode ("inc", "dptr");
4343 emitcode ("mov", "dps,#0");
4347 /* if the sizes are greater than 1 then we cannot */
4348 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4349 AOP_SIZE (IC_LEFT (ic)) > 1)
4352 /* we can if the aops of the left & result match or
4353 if they are in registers and the registers are the
4356 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4357 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4358 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4362 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4363 emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
4364 aopPut (IC_RESULT (ic), "a", 0);
4368 _startLazyDPSEvaluation ();
4371 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4373 _endLazyDPSEvaluation ();
4382 /*-----------------------------------------------------------------*/
4383 /* outBitAcc - output a bit in acc */
4384 /*-----------------------------------------------------------------*/
4386 outBitAcc (operand * result)
4388 symbol *tlbl = newiTempLabel (NULL);
4389 /* if the result is a bit */
4390 if (AOP_TYPE (result) == AOP_CRY)
4392 aopPut (result, "a", 0);
4396 emitcode ("jz", "!tlabel", tlbl->key + 100);
4397 emitcode ("mov", "a,%s", one);
4403 /*-----------------------------------------------------------------*/
4404 /* genPlusBits - generates code for addition of two bits */
4405 /*-----------------------------------------------------------------*/
4407 genPlusBits (iCode * ic)
4409 D (emitcode (";", "genPlusBits"));
4411 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4413 symbol *lbl = newiTempLabel (NULL);
4414 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4415 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4416 emitcode ("cpl", "c");
4418 outBitC (IC_RESULT (ic));
4422 emitcode ("clr", "a");
4423 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4424 emitcode ("rlc", "a");
4425 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4426 emitcode ("addc", "a,%s", zero);
4427 outAcc (IC_RESULT (ic));
4432 adjustArithmeticResult (iCode * ic)
4434 if (opIsGptr (IC_RESULT (ic)) &&
4435 opIsGptr (IC_LEFT (ic)) &&
4436 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4438 aopPut (IC_RESULT (ic),
4439 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE, NULL),
4443 if (opIsGptr (IC_RESULT (ic)) &&
4444 opIsGptr (IC_RIGHT (ic)) &&
4445 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4447 aopPut (IC_RESULT (ic),
4448 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE, NULL),
4452 if (opIsGptr (IC_RESULT (ic)) &&
4453 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4454 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4455 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4456 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4459 SNPRINTF (buffer, sizeof(buffer),
4460 "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4461 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4465 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
4466 // generates the result if possible. If result is generated, returns TRUE; otherwise
4467 // returns false and caller must deal with fact that result isn't aopOp'd.
4468 bool aopOp3(iCode * ic)
4470 bool dp1InUse, dp2InUse;
4473 // First, generate the right opcode. DPTR may be used if neither left nor result are
4476 // D (emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
4477 // AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
4478 // AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
4479 // AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
4481 // D (emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
4482 // AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
4483 // AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
4484 // AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
4487 // Right uses DPTR unless left or result is an AOP_STR; however,
4488 // if right is an AOP_STR, it must use DPTR regardless.
4489 if ((AOP_IS_STR (IC_LEFT (ic)) || AOP_IS_STR (IC_RESULT (ic)))
4490 && !AOP_IS_STR (IC_RIGHT (ic)))
4499 aopOp (IC_RIGHT(ic), ic, FALSE, useDp2);
4501 // if the right used DPTR, left MUST use DPTR2.
4502 // if the right used DPTR2, left MUST use DPTR.
4503 // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
4504 // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
4505 // enabling us to assign DPTR to result.
4507 if (AOP_USESDPTR (IC_RIGHT (ic)))
4511 else if (AOP_USESDPTR2 (IC_RIGHT (ic)))
4517 if (AOP_IS_STR (IC_RESULT (ic)) && !AOP_IS_STR (IC_LEFT (ic)))
4527 aopOp (IC_LEFT (ic), ic, FALSE, useDp2);
4530 // We've op'd the left & right. So, if left or right are the same operand as result,
4531 // we know aopOp will succeed, and we can just do it & bail.
4532 if (isOperandEqual (IC_LEFT (ic), IC_RESULT (ic)))
4534 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4537 if (isOperandEqual (IC_RIGHT (ic), IC_RESULT (ic)))
4539 // D (emitcode(";", "aopOp3: (left | right) & result equal"));
4540 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4544 // Operands may be equivalent (but not equal) if they share a spill location. If
4545 // so, use the same DPTR or DPTR2.
4546 if (operandsEqu (IC_LEFT (ic), IC_RESULT (ic)))
4548 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4551 if (operandsEqu (IC_RIGHT (ic), IC_RESULT (ic)))
4553 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4557 // Note which dptrs are currently in use.
4558 dp1InUse = AOP_USESDPTR (IC_LEFT (ic)) || AOP_USESDPTR (IC_RIGHT (ic));
4559 dp2InUse = AOP_USESDPTR2 (IC_LEFT (ic)) || AOP_USESDPTR2 (IC_RIGHT (ic));
4561 // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot
4563 if (dp1InUse && AOP_IS_STR (IC_RESULT (ic)))
4568 // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
4569 if (dp2InUse && AOP_IS_DPTRn (IC_RESULT (ic)))
4574 // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck
4575 if (dp1InUse && dp2InUse && isOperandInFarSpace (IC_RESULT (ic)))
4580 aopOp (IC_RESULT (ic), ic, TRUE, dp1InUse);
4582 // Some sanity checking...
4583 if (dp1InUse && AOP_USESDPTR (IC_RESULT (ic)))
4586 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
4587 __FILE__, __LINE__, ic->filename, ic->lineno);
4588 emitcode(";", ">>> unexpected DPTR here.");
4591 if (dp2InUse && AOP_USESDPTR2 (IC_RESULT (ic)))
4594 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
4595 __FILE__, __LINE__, ic->filename, ic->lineno);
4596 emitcode(";", ">>> unexpected DPTR2 here.");
4602 // Macro to aopOp all three operands of an ic. If this cannot be done,
4603 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
4604 // will be set TRUE. The caller must then handle the case specially, noting
4605 // that the IC_RESULT operand is not aopOp'd.
4607 #define AOP_OP_3_NOFATAL(ic, rc) \
4608 do { rc = !aopOp3(ic); } while (0)
4610 // aopOp the left & right operands of an ic.
4611 #define AOP_OP_2(ic) \
4612 aopOp (IC_RIGHT (ic), ic, FALSE, AOP_IS_STR (IC_LEFT (ic))); \
4613 aopOp (IC_LEFT (ic), ic, FALSE, AOP_USESDPTR (IC_RIGHT (ic)));
4615 // convienience macro.
4616 #define AOP_SET_LOCALS(ic) \
4617 left = IC_LEFT(ic); \
4618 right = IC_RIGHT(ic); \
4619 result = IC_RESULT(ic);
4622 // Given an integer value of pushedSize bytes on the stack,
4623 // adjust it to be resultSize bytes, either by discarding
4624 // the most significant bytes or by zero-padding.
4626 // On exit from this macro, pushedSize will have been adjusted to
4627 // equal resultSize, and ACC may be trashed.
4628 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
4629 /* If the pushed data is bigger than the result, \
4630 * simply discard unused bytes. Icky, but works. \
4632 while (pushedSize > resultSize) \
4634 D (emitcode (";", "discarding unused result byte.")); \
4635 emitcode ("pop", "acc"); \
4638 if (pushedSize < resultSize) \
4640 emitcode ("clr", "a"); \
4641 /* Conversly, we haven't pushed enough here. \
4642 * just zero-pad, and all is well. \
4644 while (pushedSize < resultSize) \
4646 emitcode("push", "acc"); \
4650 assert(pushedSize == resultSize);
4652 /*-----------------------------------------------------------------*/
4653 /* genPlus - generates code for addition */
4654 /*-----------------------------------------------------------------*/
4656 genPlus (iCode * ic)
4658 int size, offset = 0;
4661 bool swappedLR = FALSE;
4663 D (emitcode (";", "genPlus"));
4665 /* special cases :- */
4666 if ( AOP_IS_STR (IC_LEFT (ic)) &&
4667 isOperandLiteral (IC_RIGHT (ic)) && OP_SYMBOL (IC_RESULT (ic))->ruonly) {
4668 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
4669 size = (int)floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4671 while (size--) emitcode ("inc","dptr");
4673 emitcode ("mov", "a,dpl");
4674 emitcode ("add", "a,#!constbyte", size & 0xff);
4675 emitcode ("mov", "dpl,a");
4676 emitcode ("mov", "a,dph");
4677 emitcode ("addc", "a,#!constbyte", (size >> 8) & 0xff);
4678 emitcode ("mov", "dph,a");
4679 emitcode ("mov", "a,dpx");
4680 emitcode ("addc", "a,#!constbyte", (size >> 16) & 0xff);
4681 emitcode ("mov", "dpx,a");
4683 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4686 if ( IS_SYMOP (IC_LEFT (ic)) &&
4687 OP_SYMBOL (IC_LEFT (ic))->remat &&
4688 isOperandInFarSpace (IC_RIGHT (ic))) {
4689 operand *op = IC_RIGHT(ic);
4690 IC_RIGHT(ic) = IC_LEFT(ic);
4694 AOP_OP_3_NOFATAL (ic, pushResult);
4698 D (emitcode (";", "genPlus: must push result: 3 ops in far space"));
4703 /* if literal, literal on the right or
4704 if left requires ACC or right is already
4706 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4707 ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic)))) ||
4708 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4710 operand *t = IC_RIGHT (ic);
4711 IC_RIGHT (ic) = IC_LEFT (ic);
4714 D (emitcode (";", "Swapped plus args."));
4717 /* if both left & right are in bit
4719 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4720 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4726 /* if left in bit space & right literal */
4727 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4728 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4730 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4731 /* if result in bit space */
4732 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4734 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4735 emitcode ("cpl", "c");
4736 outBitC (IC_RESULT (ic));
4740 size = getDataSize (IC_RESULT (ic));
4741 _startLazyDPSEvaluation ();
4744 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4745 emitcode ("addc", "a,%s", zero);
4746 aopPut (IC_RESULT (ic), "a", offset++);
4748 _endLazyDPSEvaluation ();
4753 /* if I can do an increment instead
4754 of add then GOOD for ME */
4755 if (genPlusIncr (ic) == TRUE)
4757 D (emitcode (";", "did genPlusIncr"));
4762 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4764 _startLazyDPSEvaluation ();
4767 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4769 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
4771 emitcode ("add", "a,%s",
4772 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4774 emitcode ("addc", "a,%s",
4775 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4779 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4781 /* right is going to use ACC or we would have taken the
4784 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4786 D(emitcode(";", "+ AOP_ACC special case."););
4787 emitcode("xch", "a, %s", DP2_RESULT_REG);
4789 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4792 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4795 emitcode("add", "a, %s", DP2_RESULT_REG);
4799 emitcode ("add", "a,%s",
4800 aopGet (IC_LEFT(ic), offset, FALSE, FALSE,
4806 emitcode ("addc", "a,%s",
4807 aopGet (IC_LEFT (ic), offset, FALSE, FALSE,
4813 aopPut (IC_RESULT (ic), "a", offset);
4817 emitcode ("push", "acc");
4821 _endLazyDPSEvaluation ();
4825 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4827 size = getDataSize (IC_LEFT (ic));
4828 rSize = getDataSize (IC_RESULT (ic));
4830 ADJUST_PUSHED_RESULT(size, rSize);
4832 _startLazyDPSEvaluation ();
4835 emitcode ("pop", "acc");
4836 aopPut (IC_RESULT (ic), "a", size);
4838 _endLazyDPSEvaluation ();
4841 adjustArithmeticResult (ic);
4844 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4847 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4848 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4852 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4853 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4857 /*-----------------------------------------------------------------*/
4858 /* genMinusDec :- does subtraction with decrement if possible */
4859 /*-----------------------------------------------------------------*/
4861 genMinusDec (iCode * ic)
4863 unsigned int icount;
4864 unsigned int size = getDataSize (IC_RESULT (ic));
4866 /* will try to generate an increment */
4867 /* if the right side is not a literal
4869 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4872 /* if the literal value of the right hand side
4873 is greater than 4 then it is not worth it */
4874 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4877 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4878 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4880 emitcode("dec","%s",aopGet(IC_RESULT(ic),0,FALSE,FALSE,NULL));
4884 /* if decrement 16 bits in register */
4885 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4886 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4887 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4896 /* If the next instruction is a goto and the goto target
4897 * is <= 5 instructions previous to this, we can generate
4898 * jumps straight to that target.
4900 if (ic->next && ic->next->op == GOTO
4901 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4904 D (emitcode (";", "tail decrement optimized (range %d)", labelRange));
4905 tlbl = IC_LABEL (ic->next);
4910 tlbl = newiTempLabel (NULL);
4914 l = aopGet (IC_RESULT (ic), LSB, FALSE, FALSE, NULL);
4915 emitcode ("dec", "%s", l);
4917 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4918 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4919 IS_AOP_PREG (IC_RESULT (ic)))
4921 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4925 emitcode ("mov", "a,#!constbyte",0xff);
4926 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4928 l = aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE, NULL);
4929 emitcode ("dec", "%s", l);
4932 if (!strcmp(l, "acc"))
4934 emitcode("jnz", "!tlabel", tlbl->key + 100);
4936 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4937 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4938 IS_AOP_PREG (IC_RESULT (ic)))
4940 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4944 emitcode ("mov", "a,#!constbyte",0xff);
4945 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4947 l = aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE, NULL);
4948 emitcode ("dec", "%s", l);
4952 if (!strcmp(l, "acc"))
4954 emitcode("jnz", "!tlabel", tlbl->key + 100);
4956 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4957 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4958 IS_AOP_PREG (IC_RESULT (ic)))
4960 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4964 emitcode ("mov", "a,#!constbyte",0xff);
4965 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4967 l = aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE, NULL);
4968 emitcode ("dec", "%s", l);
4977 /* if the sizes are greater than 1 then we cannot */
4978 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4979 AOP_SIZE (IC_LEFT (ic)) > 1)
4982 /* we can if the aops of the left & result match or
4983 if they are in registers and the registers are the
4986 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4987 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4988 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4992 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4994 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL));
4999 l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL);
5002 _startLazyDPSEvaluation ();
5005 emitcode ("dec", "%s", l);
5007 _endLazyDPSEvaluation ();
5009 if (AOP_NEEDSACC (IC_RESULT (ic)))
5010 aopPut (IC_RESULT (ic), "a", 0);
5018 /*-----------------------------------------------------------------*/
5019 /* addSign - complete with sign */
5020 /*-----------------------------------------------------------------*/
5022 addSign (operand * result, int offset, int sign)
5024 int size = (getDataSize (result) - offset);
5027 _startLazyDPSEvaluation();
5030 emitcode ("rlc", "a");
5031 emitcode ("subb", "a,acc");
5034 aopPut (result, "a", offset++);
5041 aopPut (result, zero, offset++);
5044 _endLazyDPSEvaluation();
5048 /*-----------------------------------------------------------------*/
5049 /* genMinusBits - generates code for subtraction of two bits */
5050 /*-----------------------------------------------------------------*/
5052 genMinusBits (iCode * ic)
5054 symbol *lbl = newiTempLabel (NULL);
5056 D (emitcode (";", "genMinusBits"));
5058 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
5060 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
5061 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
5062 emitcode ("cpl", "c");
5064 outBitC (IC_RESULT (ic));
5068 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
5069 emitcode ("subb", "a,acc");
5070 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
5071 emitcode ("inc", "a");
5073 aopPut (IC_RESULT (ic), "a", 0);
5074 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
5078 /*-----------------------------------------------------------------*/
5079 /* genMinus - generates code for subtraction */
5080 /*-----------------------------------------------------------------*/
5082 genMinus (iCode * ic)
5084 int size, offset = 0;
5089 D (emitcode (";", "genMinus"));
5091 AOP_OP_3_NOFATAL(ic, pushResult);
5095 /* special cases :- */
5096 /* if both left & right are in bit space */
5097 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
5098 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
5104 /* if I can do an decrement instead
5105 of subtract then GOOD for ME */
5106 if (genMinusDec (ic) == TRUE)
5111 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
5113 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
5119 lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5124 /* if literal, add a,#-lit, else normal subb */
5125 _startLazyDPSEvaluation ();
5127 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
5128 if (AOP_USESDPTR(IC_RIGHT(ic))) {
5129 emitcode ("mov","b,%s",
5130 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
5131 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
5132 emitcode ("subb","a,b");
5134 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
5135 emitcode ("subb", "a,%s",
5136 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE,
5140 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
5141 /* first add without previous c */
5143 if (!size && lit==-1) {
5144 emitcode ("dec", "a");
5146 emitcode ("add", "a,#!constbyte",
5147 (unsigned int) (lit & 0x0FFL));
5150 emitcode ("addc", "a,#!constbyte",
5151 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5156 emitcode ("push", "acc");
5158 aopPut (IC_RESULT (ic), "a", offset);
5162 _endLazyDPSEvaluation ();
5166 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
5168 size = getDataSize (IC_LEFT (ic));
5169 rSize = getDataSize (IC_RESULT (ic));
5171 ADJUST_PUSHED_RESULT(size, rSize);
5173 _startLazyDPSEvaluation ();
5176 emitcode ("pop", "acc");
5177 aopPut (IC_RESULT (ic), "a", size);
5179 _endLazyDPSEvaluation ();
5182 adjustArithmeticResult (ic);
5185 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5186 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5187 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5191 /*-----------------------------------------------------------------*/
5192 /* genMultbits :- multiplication of bits */
5193 /*-----------------------------------------------------------------*/
5195 genMultbits (operand * left,
5200 D (emitcode (";", "genMultbits"));
5202 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5203 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5204 aopOp(result, ic, TRUE, FALSE);
5208 /*-----------------------------------------------------------------*/
5209 /* genMultOneByte : 8*8=8/16 bit multiplication */
5210 /*-----------------------------------------------------------------*/
5212 genMultOneByte (operand * left,
5219 bool runtimeSign, compiletimeSign;
5220 bool lUnsigned, rUnsigned, pushedB;
5222 /* (if two literals: the value is computed before) */
5223 /* if one literal, literal on the right */
5224 if (AOP_TYPE (left) == AOP_LIT)
5229 /* emitcode (";", "swapped left and right"); */
5231 /* if no literal, unsigned on the right: shorter code */
5232 if ( AOP_TYPE (right) != AOP_LIT
5233 && SPEC_USIGN (getSpec (operandType (left))))
5240 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5241 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5245 if ((lUnsigned && rUnsigned)
5246 /* sorry, I don't know how to get size
5247 without calling aopOp (result,...);
5248 see Feature Request */
5249 /* || size == 1 */ ) /* no, this is not a bug; with a 1 byte result there's
5250 no need to take care about the signedness! */
5252 /* just an unsigned 8 * 8 = 8 multiply
5254 /* emitcode (";","unsigned"); */
5255 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
5256 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
5257 emitcode ("mul", "ab");
5260 aopOp (result, ic, TRUE, FALSE);
5261 size = AOP_SIZE (result);
5263 if (size < 1 || size > 2)
5265 /* this should never happen */
5266 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
5267 size, __FILE__, lineno);
5271 aopPut (result, "a", 0);
5274 aopPut (result, "b", 1);
5280 /* we have to do a signed multiply */
5281 /* emitcode (";", "signed"); */
5283 /* now sign adjust for both left & right */
5285 /* let's see what's needed: */
5286 /* apply negative sign during runtime */
5287 runtimeSign = FALSE;
5288 /* negative sign from literals */
5289 compiletimeSign = FALSE;
5293 if (AOP_TYPE(left) == AOP_LIT)
5295 /* signed literal */
5296 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5298 compiletimeSign = TRUE;
5301 /* signed but not literal */
5307 if (AOP_TYPE(right) == AOP_LIT)
5309 /* signed literal */
5310 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5312 compiletimeSign ^= TRUE;
5315 /* signed but not literal */
5319 /* initialize F0, which stores the runtime sign */
5322 if (compiletimeSign)
5323 emitcode ("setb", "F0"); /* set sign flag */
5325 emitcode ("clr", "F0"); /* reset sign flag */
5328 /* save the signs of the operands */
5329 if (AOP_TYPE(right) == AOP_LIT)
5331 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5333 if (!rUnsigned && val < 0)
5334 emitcode ("mov", "b,#!constbyte", -val);
5336 emitcode ("mov", "b,#!constbyte", (unsigned char) val);
5338 else /* ! literal */
5340 if (rUnsigned) /* emitcode (";", "signed"); */
5341 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
5344 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
5345 lbl = newiTempLabel (NULL);
5346 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5347 emitcode ("cpl", "F0"); /* complement sign flag */
5348 emitcode ("cpl", "a"); /* 2's complement */
5349 emitcode ("inc", "a");
5351 emitcode ("mov", "b,a");
5355 if (AOP_TYPE(left) == AOP_LIT)
5357 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5359 if (!lUnsigned && val < 0)
5360 emitcode ("mov", "a,#!constbyte", -val);
5362 emitcode ("mov", "a,#!constbyte", (unsigned char) val);
5364 else /* ! literal */
5366 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
5368 if (!lUnsigned) /* emitcode (";", "signed"); */
5370 lbl = newiTempLabel (NULL);
5371 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5372 emitcode ("cpl", "F0"); /* complement sign flag */
5373 emitcode ("cpl", "a"); /* 2's complement */
5374 emitcode ("inc", "a");
5379 /* now the multiplication */
5380 emitcode ("mul", "ab");
5382 aopOp(result, ic, TRUE, FALSE);
5383 size = AOP_SIZE (result);
5385 if (size < 1 || size > 2)
5387 /* this should never happen */
5388 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
5389 size, __FILE__, lineno);
5393 if (runtimeSign || compiletimeSign)
5395 lbl = newiTempLabel (NULL);
5397 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5398 emitcode ("cpl", "a"); /* lsb 2's complement */
5400 emitcode ("inc", "a"); /* inc doesn't set carry flag */
5403 emitcode ("add", "a,#1"); /* this sets carry flag */
5404 emitcode ("xch", "a,b");
5405 emitcode ("cpl", "a"); /* msb 2's complement */
5406 emitcode ("addc", "a,#0");
5407 emitcode ("xch", "a,b");
5411 aopPut (result, "a", 0);
5414 aopPut (result, "b", 1);
5419 /*-----------------------------------------------------------------*/
5420 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
5421 /*-----------------------------------------------------------------*/
5422 static void genMultTwoByte (operand *left, operand *right,
5423 operand *result, iCode *ic)
5425 sym_link *retype = getSpec(operandType(right));
5426 sym_link *letype = getSpec(operandType(left));
5427 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5430 if (AOP_TYPE (left) == AOP_LIT) {
5435 /* save EA bit in F1 */
5436 lbl = newiTempLabel(NULL);
5437 emitcode ("setb","F1");
5438 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5439 emitcode ("clr","F1");
5442 /* load up MB with right */
5444 emitcode("clr","F0");
5445 if (AOP_TYPE(right) == AOP_LIT) {
5446 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5448 emitcode("setb","F0");
5451 emitcode ("mov","mb,#!constbyte",val & 0xff);
5452 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5454 lbl = newiTempLabel(NULL);
5455 emitcode ("mov","b,%s",aopGet(right,0,FALSE,FALSE,NULL));
5456 emitcode ("mov","a,%s",aopGet(right,1,FALSE,FALSE,NULL));
5457 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5458 emitcode ("xch", "a,b");
5459 emitcode ("cpl","a");
5460 emitcode ("add", "a,#1");
5461 emitcode ("xch", "a,b");
5462 emitcode ("cpl", "a"); // msb
5463 emitcode ("addc", "a,#0");
5464 emitcode ("setb","F0");
5466 emitcode ("mov","mb,b");
5467 emitcode ("mov","mb,a");
5470 emitcode ("mov","mb,%s",aopGet(right,0,FALSE,FALSE,NULL));
5471 emitcode ("mov","mb,%s",aopGet(right,1,FALSE,FALSE,NULL));
5473 /* load up MA with left */
5475 lbl = newiTempLabel(NULL);
5476 emitcode ("mov","b,%s",aopGet(left,0,FALSE,FALSE,NULL));
5477 emitcode ("mov","a,%s",aopGet(left,1,FALSE,FALSE,NULL));
5478 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5479 emitcode ("xch", "a,b");
5480 emitcode ("cpl","a");
5481 emitcode ("add", "a,#1");
5482 emitcode ("xch", "a,b");
5483 emitcode ("cpl", "a"); // msb
5484 emitcode ("addc","a,#0");
5485 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5486 emitcode ("setb","F0");
5488 emitcode ("mov","ma,b");
5489 emitcode ("mov","ma,a");
5491 emitcode ("mov","ma,%s",aopGet(left,0,FALSE,FALSE,NULL));
5492 emitcode ("mov","ma,%s",aopGet(left,1,FALSE,FALSE,NULL));
5494 /* wait for multiplication to finish */
5495 lbl = newiTempLabel(NULL);
5497 emitcode("mov","a,mcnt1");
5498 emitcode("anl","a,#!constbyte",0x80);
5499 emitcode("jnz","!tlabel",lbl->key+100);
5501 freeAsmop (left, NULL, ic, TRUE);
5502 freeAsmop (right, NULL, ic,TRUE);
5503 aopOp(result, ic, TRUE, FALSE);
5505 /* if unsigned then simple */
5507 emitcode ("mov","a,ma");
5508 if (AOP_SIZE(result) >= 4) aopPut(result,"a",3);
5509 emitcode ("mov","a,ma");
5510 if (AOP_SIZE(result) >= 3) aopPut(result,"a",2);
5511 aopPut(result,"ma",1);
5512 aopPut(result,"ma",0);
5514 emitcode("push","ma");
5515 emitcode("push","ma");
5516 emitcode("push","ma");
5518 /* negate result if needed */
5519 lbl = newiTempLabel(NULL);
5520 emitcode("jnb","F0,!tlabel",lbl->key+100);
5521 emitcode("cpl","a");
5522 emitcode("add","a,#1");
5524 if (AOP_TYPE(result) == AOP_ACC)
5526 D (emitcode(";", "ACC special case."));
5527 /* We know result is the only live aop, and
5528 * it's obviously not a DPTR2, so AP is available.
5530 emitcode("mov", "%s,acc", DP2_RESULT_REG);
5534 aopPut(result,"a",0);
5537 emitcode("pop","acc");
5538 lbl = newiTempLabel(NULL);
5539 emitcode("jnb","F0,!tlabel",lbl->key+100);
5540 emitcode("cpl","a");
5541 emitcode("addc","a,#0");
5543 aopPut(result,"a",1);
5544 emitcode("pop","acc");
5545 if (AOP_SIZE(result) >= 3) {
5546 lbl = newiTempLabel(NULL);
5547 emitcode("jnb","F0,!tlabel",lbl->key+100);
5548 emitcode("cpl","a");
5549 emitcode("addc","a,#0");
5551 aopPut(result,"a",2);
5553 emitcode("pop","acc");
5554 if (AOP_SIZE(result) >= 4) {
5555 lbl = newiTempLabel(NULL);
5556 emitcode("jnb","F0,!tlabel",lbl->key+100);
5557 emitcode("cpl","a");
5558 emitcode("addc","a,#0");
5560 aopPut(result,"a",3);
5562 if (AOP_TYPE(result) == AOP_ACC)
5564 /* We stashed the result away above. */
5565 emitcode("mov", "acc,%s", DP2_RESULT_REG);
5569 freeAsmop (result, NULL, ic, TRUE);
5571 /* restore EA bit in F1 */
5572 lbl = newiTempLabel(NULL);
5573 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5574 emitcode ("setb","EA");
5579 /*-----------------------------------------------------------------*/
5580 /* genMult - generates code for multiplication */
5581 /*-----------------------------------------------------------------*/
5583 genMult (iCode * ic)
5585 operand *left = IC_LEFT (ic);
5586 operand *right = IC_RIGHT (ic);
5587 operand *result = IC_RESULT (ic);
5589 D (emitcode (";", "genMult"));
5591 /* assign the asmops */
5594 /* special cases first */
5596 if (AOP_TYPE (left) == AOP_CRY &&
5597 AOP_TYPE (right) == AOP_CRY)
5599 genMultbits (left, right, result, ic);
5603 /* if both are of size == 1 */
5604 if (AOP_SIZE (left) == 1 &&
5605 AOP_SIZE (right) == 1)
5607 genMultOneByte (left, right, result, ic);
5611 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5612 /* use the ds390 ARITHMETIC accel UNIT */
5613 genMultTwoByte (left, right, result, ic);
5616 /* should have been converted to function call */
5620 freeAsmop (result, NULL, ic, TRUE);
5621 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5622 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5625 /*-----------------------------------------------------------------*/
5626 /* genDivbits :- division of bits */
5627 /*-----------------------------------------------------------------*/
5629 genDivbits (operand * left,
5637 D(emitcode (";", "genDivbits"));
5641 /* the result must be bit */
5642 LOAD_AB_FOR_DIV (left, right, l);
5643 emitcode ("div", "ab");
5644 emitcode ("rrc", "a");
5645 aopOp(result, ic, TRUE, FALSE);
5649 aopPut (result, "c", 0);
5652 /*-----------------------------------------------------------------*/
5653 /* genDivOneByte : 8 bit division */
5654 /*-----------------------------------------------------------------*/
5656 genDivOneByte (operand * left,
5661 bool lUnsigned, rUnsigned, pushedB;
5662 bool runtimeSign, compiletimeSign;
5667 D(emitcode (";", "genDivOneByte"));
5670 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5671 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5675 /* signed or unsigned */
5676 if (lUnsigned && rUnsigned)
5678 /* unsigned is easy */
5679 LOAD_AB_FOR_DIV (left, right, l);
5680 emitcode ("div", "ab");
5683 aopOp (result, ic, TRUE, FALSE);
5684 aopPut (result, "a", 0);
5687 size = AOP_SIZE (result) - 1;
5690 aopPut (result, zero, offset++);
5696 /* signed is a little bit more difficult */
5698 /* now sign adjust for both left & right */
5700 /* let's see what's needed: */
5701 /* apply negative sign during runtime */
5702 runtimeSign = FALSE;
5703 /* negative sign from literals */
5704 compiletimeSign = FALSE;
5708 if (AOP_TYPE(left) == AOP_LIT)
5710 /* signed literal */
5711 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5713 compiletimeSign = TRUE;
5716 /* signed but not literal */
5722 if (AOP_TYPE(right) == AOP_LIT)
5724 /* signed literal */
5725 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5727 compiletimeSign ^= TRUE;
5730 /* signed but not literal */
5734 /* initialize F0, which stores the runtime sign */
5737 if (compiletimeSign)
5738 emitcode ("setb", "F0"); /* set sign flag */
5740 emitcode ("clr", "F0"); /* reset sign flag */
5743 /* save the signs of the operands */
5744 if (AOP_TYPE(right) == AOP_LIT)
5746 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5748 if (!rUnsigned && val < 0)
5749 emitcode ("mov", "b,#0x%02x", -val);
5751 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5753 else /* ! literal */
5756 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
5759 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
5760 lbl = newiTempLabel (NULL);
5761 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5762 emitcode ("cpl", "F0"); /* complement sign flag */
5763 emitcode ("cpl", "a"); /* 2's complement */
5764 emitcode ("inc", "a");
5766 emitcode ("mov", "b,a");
5770 if (AOP_TYPE(left) == AOP_LIT)
5772 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5774 if (!lUnsigned && val < 0)
5775 emitcode ("mov", "a,#0x%02x", -val);
5777 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5779 else /* ! literal */
5781 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
5785 lbl = newiTempLabel (NULL);
5786 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5787 emitcode ("cpl", "F0"); /* complement sign flag */
5788 emitcode ("cpl", "a"); /* 2's complement */
5789 emitcode ("inc", "a");
5794 /* now the division */
5795 emitcode ("nop", "; workaround for DS80C390 div bug.");
5796 emitcode ("div", "ab");
5798 if (runtimeSign || compiletimeSign)
5800 lbl = newiTempLabel (NULL);
5802 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5803 emitcode ("cpl", "a"); /* lsb 2's complement */
5804 emitcode ("inc", "a");
5808 aopOp (result, ic, TRUE, FALSE);
5809 size = AOP_SIZE (result) - 1;
5813 /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
5814 then the result will be in b, a */
5815 emitcode ("mov", "b,a"); /* 1 */
5816 /* msb is 0x00 or 0xff depending on the sign */
5819 emitcode ("mov", "c,F0");
5820 emitcode ("subb", "a,acc");
5821 emitcode ("xch", "a,b"); /* 2 */
5823 aopPut (result, "b", offset++); /* write msb's */
5825 else /* compiletimeSign */
5827 aopPut (result, "#0xff", offset++); /* write msb's */
5829 aopPut (result, "a", 0); /* 3: write lsb */
5834 aopOp(result, ic, TRUE, FALSE);
5835 size = AOP_SIZE (result) - 1;
5837 aopPut (result, "a", 0);
5839 aopPut (result, zero, offset++);
5845 /*-----------------------------------------------------------------*/
5846 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
5847 /*-----------------------------------------------------------------*/
5848 static void genDivTwoByte (operand *left, operand *right,
5849 operand *result, iCode *ic)
5851 sym_link *retype = getSpec(operandType(right));
5852 sym_link *letype = getSpec(operandType(left));
5853 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5856 /* save EA bit in F1 */
5857 lbl = newiTempLabel(NULL);
5858 emitcode ("setb","F1");
5859 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5860 emitcode ("clr","F1");
5863 /* load up MA with left */
5865 emitcode("clr","F0");
5866 lbl = newiTempLabel(NULL);
5867 emitcode ("mov","b,%s",aopGet(left,0,FALSE,FALSE,NULL));
5868 emitcode ("mov","a,%s",aopGet(left,1,FALSE,FALSE,NULL));
5869 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5870 emitcode ("xch", "a,b");
5871 emitcode ("cpl","a");
5872 emitcode ("add", "a,#1");
5873 emitcode ("xch", "a,b");
5874 emitcode ("cpl", "a"); // msb
5875 emitcode ("addc","a,#0");
5876 emitcode ("setb","F0");
5878 emitcode ("mov","ma,b");
5879 emitcode ("mov","ma,a");
5881 emitcode ("mov","ma,%s",aopGet(left,0,FALSE,FALSE,NULL));
5882 emitcode ("mov","ma,%s",aopGet(left,1,FALSE,FALSE,NULL));
5885 /* load up MB with right */
5887 if (AOP_TYPE(right) == AOP_LIT) {
5888 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5890 lbl = newiTempLabel(NULL);
5891 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5892 emitcode("setb","F0");
5896 emitcode ("mov","mb,#!constbyte",val & 0xff);
5897 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5899 lbl = newiTempLabel(NULL);
5900 emitcode ("mov","b,%s",aopGet(right,0,FALSE,FALSE,NULL));
5901 emitcode ("mov","a,%s",aopGet(right,1,FALSE,FALSE,NULL));
5902 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5903 emitcode ("xch", "a,b");
5904 emitcode ("cpl","a");
5905 emitcode ("add", "a,#1");
5906 emitcode ("xch", "a,b");
5907 emitcode ("cpl", "a"); // msb
5908 emitcode ("addc", "a,#0");
5909 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5910 emitcode ("setb","F0");
5912 emitcode ("mov","mb,b");
5913 emitcode ("mov","mb,a");
5916 emitcode ("mov","mb,%s",aopGet(right,0,FALSE,FALSE,NULL));
5917 emitcode ("mov","mb,%s",aopGet(right,1,FALSE,FALSE,NULL));
5920 /* wait for multiplication to finish */
5921 lbl = newiTempLabel(NULL);
5923 emitcode("mov","a,mcnt1");
5924 emitcode("anl","a,#!constbyte",0x80);
5925 emitcode("jnz","!tlabel",lbl->key+100);
5927 freeAsmop (left, NULL, ic, TRUE);
5928 freeAsmop (right, NULL, ic,TRUE);
5929 aopOp(result, ic, TRUE, FALSE);
5931 /* if unsigned then simple */
5933 aopPut(result,"ma",1);
5934 aopPut(result,"ma",0);
5936 emitcode("push","ma");
5938 /* negate result if needed */
5939 lbl = newiTempLabel(NULL);
5940 emitcode("jnb","F0,!tlabel",lbl->key+100);
5941 emitcode("cpl","a");
5942 emitcode("add","a,#1");
5944 aopPut(result,"a",0);
5945 emitcode("pop","acc");
5946 lbl = newiTempLabel(NULL);
5947 emitcode("jnb","F0,!tlabel",lbl->key+100);
5948 emitcode("cpl","a");
5949 emitcode("addc","a,#0");
5951 aopPut(result,"a",1);
5953 freeAsmop (result, NULL, ic, TRUE);
5954 /* restore EA bit in F1 */
5955 lbl = newiTempLabel(NULL);
5956 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5957 emitcode ("setb","EA");
5962 /*-----------------------------------------------------------------*/
5963 /* genDiv - generates code for division */
5964 /*-----------------------------------------------------------------*/
5968 operand *left = IC_LEFT (ic);
5969 operand *right = IC_RIGHT (ic);
5970 operand *result = IC_RESULT (ic);
5972 D (emitcode (";", "genDiv"));
5974 /* assign the amsops */
5977 /* special cases first */
5979 if (AOP_TYPE (left) == AOP_CRY &&
5980 AOP_TYPE (right) == AOP_CRY)
5982 genDivbits (left, right, result, ic);
5986 /* if both are of size == 1 */
5987 if (AOP_SIZE (left) == 1 &&
5988 AOP_SIZE (right) == 1)
5990 genDivOneByte (left, right, result, ic);
5994 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5995 /* use the ds390 ARITHMETIC accel UNIT */
5996 genDivTwoByte (left, right, result, ic);
5999 /* should have been converted to function call */
6002 freeAsmop (result, NULL, ic, TRUE);
6003 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6004 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6007 /*-----------------------------------------------------------------*/
6008 /* genModbits :- modulus of bits */
6009 /*-----------------------------------------------------------------*/
6011 genModbits (operand * left,
6019 D (emitcode (";", "genModbits"));
6023 /* the result must be bit */
6024 LOAD_AB_FOR_DIV (left, right, l);
6025 emitcode ("div", "ab");
6026 emitcode ("mov", "a,b");
6027 emitcode ("rrc", "a");
6028 aopOp(result, ic, TRUE, FALSE);
6032 aopPut (result, "c", 0);
6035 /*-----------------------------------------------------------------*/
6036 /* genModOneByte : 8 bit modulus */
6037 /*-----------------------------------------------------------------*/
6039 genModOneByte (operand * left,
6044 bool lUnsigned, rUnsigned, pushedB;
6045 bool runtimeSign, compiletimeSign;
6050 D (emitcode (";", "genModOneByte"));
6053 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
6054 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
6058 /* signed or unsigned */
6059 if (lUnsigned && rUnsigned)
6061 /* unsigned is easy */
6062 LOAD_AB_FOR_DIV (left, right, l);
6063 emitcode ("div", "ab");
6064 aopOp (result, ic, TRUE, FALSE);
6065 aopPut (result, "b", 0);
6067 for (size = AOP_SIZE (result) - 1; size--;)
6068 aopPut (result, zero, offset++);
6074 /* signed is a little bit more difficult */
6076 /* now sign adjust for both left & right */
6078 /* modulus: sign of the right operand has no influence on the result! */
6079 if (AOP_TYPE(right) == AOP_LIT)
6081 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
6083 if (!rUnsigned && val < 0)
6084 emitcode ("mov", "b,#0x%02x", -val);
6086 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
6088 else /* not literal */
6091 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
6094 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
6095 lbl = newiTempLabel (NULL);
6096 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
6097 emitcode ("cpl", "a"); /* 2's complement */
6098 emitcode ("inc", "a");
6100 emitcode ("mov", "b,a");
6104 /* let's see what's needed: */
6105 /* apply negative sign during runtime */
6106 runtimeSign = FALSE;
6107 /* negative sign from literals */
6108 compiletimeSign = FALSE;
6110 /* sign adjust left side */
6111 if (AOP_TYPE(left) == AOP_LIT)
6113 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
6115 if (!lUnsigned && val < 0)
6117 compiletimeSign = TRUE; /* set sign flag */
6118 emitcode ("mov", "a,#0x%02x", -val);
6121 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
6123 else /* ! literal */
6125 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
6130 emitcode ("clr", "F0"); /* clear sign flag */
6132 lbl = newiTempLabel (NULL);
6133 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
6134 emitcode ("setb", "F0"); /* set sign flag */
6135 emitcode ("cpl", "a"); /* 2's complement */
6136 emitcode ("inc", "a");
6141 /* now the modulus */
6142 emitcode ("nop", "; workaround for DS80C390 div bug.");
6143 emitcode ("div", "ab");
6145 if (runtimeSign || compiletimeSign)
6147 emitcode ("mov", "a,b");
6148 lbl = newiTempLabel (NULL);
6150 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
6151 emitcode ("cpl", "a"); /* lsb 2's complement */
6152 emitcode ("inc", "a");
6156 aopOp (result, ic, TRUE, FALSE);
6157 size = AOP_SIZE (result) - 1;
6161 /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
6162 then the result will be in b, a */
6163 emitcode ("mov", "b,a"); /* 1 */
6164 /* msb is 0x00 or 0xff depending on the sign */
6167 emitcode ("mov", "c,F0");
6168 emitcode ("subb", "a,acc");
6169 emitcode ("xch", "a,b"); /* 2 */
6171 aopPut (result, "b", offset++); /* write msb's */
6173 else /* compiletimeSign */
6175 aopPut (result, "#0xff", offset++); /* write msb's */
6177 aopPut (result, "a", 0); /* 3: write lsb */
6182 aopOp(result, ic, TRUE, FALSE);
6183 size = AOP_SIZE (result) - 1;
6185 aopPut (result, "b", 0);
6187 aopPut (result, zero, offset++);
6193 /*-----------------------------------------------------------------*/
6194 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
6195 /*-----------------------------------------------------------------*/
6196 static void genModTwoByte (operand *left, operand *right,
6197 operand *result, iCode *ic)
6199 sym_link *retype = getSpec(operandType(right));
6200 sym_link *letype = getSpec(operandType(left));
6201 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
6204 /* load up MA with left */
6205 /* save EA bit in F1 */
6206 lbl = newiTempLabel(NULL);
6207 emitcode ("setb","F1");
6208 emitcode ("jbc","EA,!tlabel",lbl->key+100);
6209 emitcode ("clr","F1");
6213 lbl = newiTempLabel(NULL);
6214 emitcode ("mov","b,%s",aopGet(left,0,FALSE,FALSE,NULL));
6215 emitcode ("mov","a,%s",aopGet(left,1,FALSE,FALSE,NULL));
6216 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
6217 emitcode ("xch", "a,b");
6218 emitcode ("cpl","a");
6219 emitcode ("add", "a,#1");
6220 emitcode ("xch", "a,b");
6221 emitcode ("cpl", "a"); // msb
6222 emitcode ("addc","a,#0");
6224 emitcode ("mov","ma,b");
6225 emitcode ("mov","ma,a");
6227 emitcode ("mov","ma,%s",aopGet(left,0,FALSE,FALSE,NULL));
6228 emitcode ("mov","ma,%s",aopGet(left,1,FALSE,FALSE,NULL));
6231 /* load up MB with right */
6233 if (AOP_TYPE(right) == AOP_LIT) {
6234 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
6238 emitcode ("mov","mb,#!constbyte",val & 0xff);
6239 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
6241 lbl = newiTempLabel(NULL);
6242 emitcode ("mov","b,%s",aopGet(right,0,FALSE,FALSE,NULL));
6243 emitcode ("mov","a,%s",aopGet(right,1,FALSE,FALSE,NULL));
6244 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
6245 emitcode ("xch", "a,b");
6246 emitcode ("cpl","a");
6247 emitcode ("add", "a,#1");
6248 emitcode ("xch", "a,b");
6249 emitcode ("cpl", "a"); // msb
6250 emitcode ("addc", "a,#0");
6252 emitcode ("mov","mb,b");
6253 emitcode ("mov","mb,a");
6256 emitcode ("mov","mb,%s",aopGet(right,0,FALSE,FALSE,NULL));
6257 emitcode ("mov","mb,%s",aopGet(right,1,FALSE,FALSE,NULL));
6260 /* wait for multiplication to finish */
6261 lbl = newiTempLabel(NULL);
6263 emitcode("mov","a,mcnt1");
6264 emitcode("anl","a,#!constbyte",0x80);
6265 emitcode("jnz","!tlabel",lbl->key+100);
6267 freeAsmop (left, NULL, ic, TRUE);
6268 freeAsmop (right, NULL, ic,TRUE);
6269 aopOp(result, ic, TRUE, FALSE);
6271 aopPut(result,"mb",1);
6272 aopPut(result,"mb",0);
6273 freeAsmop (result, NULL, ic, TRUE);
6275 /* restore EA bit in F1 */
6276 lbl = newiTempLabel(NULL);
6277 emitcode ("jnb","F1,!tlabel",lbl->key+100);
6278 emitcode ("setb","EA");
6282 /*-----------------------------------------------------------------*/
6283 /* genMod - generates code for division */
6284 /*-----------------------------------------------------------------*/
6288 operand *left = IC_LEFT (ic);
6289 operand *right = IC_RIGHT (ic);
6290 operand *result = IC_RESULT (ic);
6292 D (emitcode (";", "genMod"));
6294 /* assign the asmops */
6297 /* special cases first */
6299 if (AOP_TYPE (left) == AOP_CRY &&
6300 AOP_TYPE (right) == AOP_CRY)
6302 genModbits (left, right, result, ic);
6306 /* if both are of size == 1 */
6307 if (AOP_SIZE (left) == 1 &&
6308 AOP_SIZE (right) == 1)
6310 genModOneByte (left, right, result, ic);
6314 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
6315 /* use the ds390 ARITHMETIC accel UNIT */
6316 genModTwoByte (left, right, result, ic);
6320 /* should have been converted to function call */
6324 freeAsmop (result, NULL, ic, TRUE);
6325 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6326 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6329 /*-----------------------------------------------------------------*/
6330 /* genIfxJump :- will create a jump depending on the ifx */
6331 /*-----------------------------------------------------------------*/
6333 genIfxJump (iCode * ic, char *jval)
6336 symbol *tlbl = newiTempLabel (NULL);
6339 D (emitcode (";", "genIfxJump"));
6341 /* if true label then we jump if condition
6345 jlbl = IC_TRUE (ic);
6346 inst = ((strcmp (jval, "a") == 0 ? "jz" :
6347 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
6351 /* false label is present */
6352 jlbl = IC_FALSE (ic);
6353 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
6354 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
6356 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
6357 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
6359 emitcode (inst, "!tlabel", tlbl->key + 100);
6360 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
6363 /* mark the icode as generated */
6367 /*-----------------------------------------------------------------*/
6368 /* genCmp :- greater or less than comparison */
6369 /*-----------------------------------------------------------------*/
6371 genCmp (operand * left, operand * right,
6372 iCode * ic, iCode * ifx, int sign)
6374 int size, offset = 0;
6375 unsigned long lit = 0L;
6378 D (emitcode (";", "genCmp"));
6380 result = IC_RESULT (ic);
6382 /* if left & right are bit variables */
6383 if (AOP_TYPE (left) == AOP_CRY &&
6384 AOP_TYPE (right) == AOP_CRY)
6386 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6387 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6391 /* subtract right from left if at the
6392 end the carry flag is set then we know that
6393 left is greater than right */
6394 size = max (AOP_SIZE (left), AOP_SIZE (right));
6396 /* if unsigned char cmp with lit, do cjne left,#right,zz */
6397 if ((size == 1) && !sign &&
6398 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
6400 symbol *lbl = newiTempLabel (NULL);
6401 emitcode ("cjne", "%s,%s,!tlabel",
6402 aopGet (left, offset, FALSE, FALSE, NULL),
6403 aopGet (right, offset, FALSE, FALSE, NULL),
6409 if (AOP_TYPE (right) == AOP_LIT)
6411 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6412 /* optimize if(x < 0) or if(x >= 0) */
6421 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
6423 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6424 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6426 aopOp (result, ic, FALSE, FALSE);
6428 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
6430 freeAsmop (result, NULL, ic, TRUE);
6431 genIfxJump (ifx, "acc.7");
6436 emitcode ("rlc", "a");
6438 goto release_freedLR;
6446 // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
6447 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
6448 // emitcode (";", "genCmp #2");
6449 if (sign && (size == 0))
6451 // emitcode (";", "genCmp #3");
6452 emitcode ("xrl", "a,#!constbyte",0x80);
6453 if (AOP_TYPE (right) == AOP_LIT)
6455 unsigned long lit = (unsigned long)
6456 floatFromVal (AOP (right)->aopu.aop_lit);
6457 // emitcode (";", "genCmp #3.1");
6458 emitcode ("subb", "a,#!constbyte",
6459 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
6463 // emitcode (";", "genCmp #3.2");
6465 MOVB (aopGet (right, offset++, FALSE, FALSE, "b"));
6466 saveAccWarn = DEFAULT_ACC_WARNING;
6467 emitcode ("xrl", "b,#!constbyte",0x80);
6468 emitcode ("subb", "a,b");
6475 // emitcode (";", "genCmp #4");
6477 s = aopGet (right, offset++, FALSE, FALSE, "b");
6478 saveAccWarn = DEFAULT_ACC_WARNING;
6480 emitcode ("subb", "a,%s", s);
6487 /* Don't need the left & right operands any more; do need the result. */
6488 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6489 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6491 aopOp (result, ic, FALSE, FALSE);
6495 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6501 /* if the result is used in the next
6502 ifx conditional branch then generate
6503 code a little differently */
6506 genIfxJump (ifx, "c");
6512 /* leave the result in acc */
6514 freeAsmop (result, NULL, ic, TRUE);
6517 /*-----------------------------------------------------------------*/
6518 /* genCmpGt :- greater than comparison */
6519 /*-----------------------------------------------------------------*/
6521 genCmpGt (iCode * ic, iCode * ifx)
6523 operand *left, *right;
6524 sym_link *letype, *retype;
6527 D (emitcode (";", "genCmpGt"));
6529 left = IC_LEFT (ic);
6530 right = IC_RIGHT (ic);
6532 letype = getSpec (operandType (left));
6533 retype = getSpec (operandType (right));
6534 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6536 /* assign the left & right amsops */
6539 genCmp (right, left, ic, ifx, sign);
6542 /*-----------------------------------------------------------------*/
6543 /* genCmpLt - less than comparisons */
6544 /*-----------------------------------------------------------------*/
6546 genCmpLt (iCode * ic, iCode * ifx)
6548 operand *left, *right;
6549 sym_link *letype, *retype;
6552 D (emitcode (";", "genCmpLt"));
6554 left = IC_LEFT (ic);
6555 right = IC_RIGHT (ic);
6557 letype = getSpec (operandType (left));
6558 retype = getSpec (operandType (right));
6559 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6561 /* assign the left & right amsops */
6564 genCmp (left, right, ic, ifx, sign);
6567 /*-----------------------------------------------------------------*/
6568 /* gencjneshort - compare and jump if not equal */
6569 /*-----------------------------------------------------------------*/
6571 gencjneshort (operand * left, operand * right, symbol * lbl)
6573 int size = max (AOP_SIZE (left), AOP_SIZE (right));
6575 unsigned long lit = 0L;
6577 D (emitcode (";", "gencjneshort"));
6579 /* if the left side is a literal or
6580 if the right is in a pointer register and left
6582 if ((AOP_TYPE (left) == AOP_LIT) ||
6583 (AOP_TYPE (left) == AOP_IMMD) ||
6584 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6591 if (AOP_TYPE (right) == AOP_LIT)
6592 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6594 if (opIsGptr (left) || opIsGptr (right))
6596 /* We are comparing a generic pointer to something.
6597 * Exclude the generic type byte from the comparison.
6600 D (emitcode (";", "cjneshort: generic ptr special case."););
6604 /* if the right side is a literal then anything goes */
6605 if (AOP_TYPE (right) == AOP_LIT &&
6606 AOP_TYPE (left) != AOP_DIR)
6610 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
6611 emitcode ("cjne", "a,%s,!tlabel",
6612 aopGet (right, offset, FALSE, FALSE, NULL),
6618 /* if the right side is in a register or in direct space or
6619 if the left is a pointer register & right is not */
6620 else if (AOP_TYPE (right) == AOP_REG ||
6621 AOP_TYPE (right) == AOP_DIR ||
6622 AOP_TYPE (right) == AOP_LIT ||
6623 AOP_TYPE (right) == AOP_IMMD ||
6624 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6625 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6629 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
6630 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6631 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6632 emitcode ("jnz", "!tlabel", lbl->key + 100);
6634 emitcode ("cjne", "a,%s,!tlabel",
6635 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG),
6642 /* right is a pointer reg need both a & b */
6645 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
6646 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
6647 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
6653 /*-----------------------------------------------------------------*/
6654 /* gencjne - compare and jump if not equal */
6655 /*-----------------------------------------------------------------*/
6657 gencjne (operand * left, operand * right, symbol * lbl)
6659 symbol *tlbl = newiTempLabel (NULL);
6661 D (emitcode (";", "gencjne"));
6663 gencjneshort (left, right, lbl);
6665 emitcode ("mov", "a,%s", one);
6666 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
6668 emitcode ("clr", "a");
6672 /*-----------------------------------------------------------------*/
6673 /* genCmpEq - generates code for equal to */
6674 /*-----------------------------------------------------------------*/
6676 genCmpEq (iCode * ic, iCode * ifx)
6678 operand *left, *right, *result;
6680 D (emitcode (";", "genCmpEq"));
6683 AOP_SET_LOCALS (ic);
6685 /* if literal, literal on the right or
6686 if the right is in a pointer register and left
6688 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6689 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6691 operand *t = IC_RIGHT (ic);
6692 IC_RIGHT (ic) = IC_LEFT (ic);
6696 if (ifx && /* !AOP_SIZE(result) */
6697 OP_SYMBOL (result) &&
6698 OP_SYMBOL (result)->regType == REG_CND)
6701 /* if they are both bit variables */
6702 if (AOP_TYPE (left) == AOP_CRY &&
6703 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6705 if (AOP_TYPE (right) == AOP_LIT)
6707 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6710 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6711 emitcode ("cpl", "c");
6715 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6719 emitcode ("clr", "c");
6721 /* AOP_TYPE(right) == AOP_CRY */
6725 symbol *lbl = newiTempLabel (NULL);
6726 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6727 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6728 emitcode ("cpl", "c");
6731 /* if true label then we jump if condition
6733 tlbl = newiTempLabel (NULL);
6736 emitcode ("jnc", "!tlabel", tlbl->key + 100);
6737 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6741 emitcode ("jc", "!tlabel", tlbl->key + 100);
6742 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6748 tlbl = newiTempLabel (NULL);
6749 gencjneshort (left, right, tlbl);
6752 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6757 symbol *lbl = newiTempLabel (NULL);
6758 emitcode ("sjmp", "!tlabel", lbl->key + 100);
6760 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6764 /* mark the icode as generated */
6767 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6768 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6772 /* if they are both bit variables */
6773 if (AOP_TYPE (left) == AOP_CRY &&
6774 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6776 if (AOP_TYPE (right) == AOP_LIT)
6778 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6781 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6782 emitcode ("cpl", "c");
6786 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6790 emitcode ("clr", "c");
6792 /* AOP_TYPE(right) == AOP_CRY */
6796 symbol *lbl = newiTempLabel (NULL);
6797 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6798 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6799 emitcode ("cpl", "c");
6803 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6804 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6806 aopOp (result, ic, TRUE, FALSE);
6809 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6816 genIfxJump (ifx, "c");
6819 /* if the result is used in an arithmetic operation
6820 then put the result in place */
6825 gencjne (left, right, newiTempLabel (NULL));
6827 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6828 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6830 aopOp (result, ic, TRUE, FALSE);
6832 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6834 aopPut (result, "a", 0);
6839 genIfxJump (ifx, "a");
6842 /* if the result is used in an arithmetic operation
6843 then put the result in place */
6844 if (AOP_TYPE (result) != AOP_CRY)
6846 /* leave the result in acc */
6850 freeAsmop (result, NULL, ic, TRUE);
6853 /*-----------------------------------------------------------------*/
6854 /* ifxForOp - returns the icode containing the ifx for operand */
6855 /*-----------------------------------------------------------------*/
6857 ifxForOp (operand * op, iCode * ic)
6859 /* if true symbol then needs to be assigned */
6860 if (IS_TRUE_SYMOP (op))
6863 /* if this has register type condition and
6864 the next instruction is ifx with the same operand
6865 and live to of the operand is upto the ifx only then */
6867 ic->next->op == IFX &&
6868 IC_COND (ic->next)->key == op->key &&
6869 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6875 /*-----------------------------------------------------------------*/
6876 /* hasInc - operand is incremented before any other use */
6877 /*-----------------------------------------------------------------*/
6879 hasInc (operand *op, iCode *ic, int osize)
6881 sym_link *type = operandType(op);
6882 sym_link *retype = getSpec (type);
6883 iCode *lic = ic->next;
6886 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6887 if (!IS_SYMOP(op)) return NULL;
6889 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6890 if (IS_AGGREGATE(type->next)) return NULL;
6891 if (osize != (isize = getSize(type->next))) return NULL;
6894 /* if operand of the form op = op + <sizeof *op> */
6895 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6896 isOperandEqual(IC_RESULT(lic),op) &&
6897 isOperandLiteral(IC_RIGHT(lic)) &&
6898 operandLitValue(IC_RIGHT(lic)) == isize) {
6901 /* if the operand used or deffed */
6902 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6905 /* if GOTO or IFX */
6906 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6912 /*-----------------------------------------------------------------*/
6913 /* genAndOp - for && operation */
6914 /*-----------------------------------------------------------------*/
6916 genAndOp (iCode * ic)
6918 operand *left, *right, *result;
6921 D (emitcode (";", "genAndOp"));
6923 /* note here that && operations that are in an
6924 if statement are taken away by backPatchLabels
6925 only those used in arthmetic operations remain */
6927 AOP_SET_LOCALS (ic);
6929 /* if both are bit variables */
6930 if (AOP_TYPE (left) == AOP_CRY &&
6931 AOP_TYPE (right) == AOP_CRY)
6933 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6934 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6935 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6936 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6938 aopOp (result,ic,FALSE, FALSE);
6943 tlbl = newiTempLabel (NULL);
6945 emitcode ("jz", "!tlabel", tlbl->key + 100);
6948 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6949 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6951 aopOp (result,ic,FALSE, FALSE);
6955 freeAsmop (result, NULL, ic, TRUE);
6959 /*-----------------------------------------------------------------*/
6960 /* genOrOp - for || operation */
6961 /*-----------------------------------------------------------------*/
6963 genOrOp (iCode * ic)
6965 operand *left, *right, *result;
6968 D (emitcode (";", "genOrOp"));
6970 /* note here that || operations that are in an
6971 if statement are taken away by backPatchLabels
6972 only those used in arthmetic operations remain */
6974 AOP_SET_LOCALS (ic);
6976 /* if both are bit variables */
6977 if (AOP_TYPE (left) == AOP_CRY &&
6978 AOP_TYPE (right) == AOP_CRY)
6980 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6981 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6982 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6983 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6985 aopOp (result,ic,FALSE, FALSE);
6991 tlbl = newiTempLabel (NULL);
6993 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6996 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6997 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6999 aopOp (result,ic,FALSE, FALSE);
7004 freeAsmop (result, NULL, ic, TRUE);
7007 /*-----------------------------------------------------------------*/
7008 /* isLiteralBit - test if lit == 2^n */
7009 /*-----------------------------------------------------------------*/
7011 isLiteralBit (unsigned long lit)
7013 unsigned long pw[32] =
7014 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
7015 0x100L, 0x200L, 0x400L, 0x800L,
7016 0x1000L, 0x2000L, 0x4000L, 0x8000L,
7017 0x10000L, 0x20000L, 0x40000L, 0x80000L,
7018 0x100000L, 0x200000L, 0x400000L, 0x800000L,
7019 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
7020 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
7023 for (idx = 0; idx < 32; idx++)
7029 /*-----------------------------------------------------------------*/
7030 /* continueIfTrue - */
7031 /*-----------------------------------------------------------------*/
7033 continueIfTrue (iCode * ic)
7036 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
7040 /*-----------------------------------------------------------------*/
7042 /*-----------------------------------------------------------------*/
7044 jumpIfTrue (iCode * ic)
7047 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
7051 /*-----------------------------------------------------------------*/
7052 /* jmpTrueOrFalse - */
7053 /*-----------------------------------------------------------------*/
7055 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
7057 // ugly but optimized by peephole
7060 symbol *nlbl = newiTempLabel (NULL);
7061 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
7063 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
7068 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
7074 // Generate code to perform a bit-wise logic operation
7075 // on two operands in far space (assumed to already have been
7076 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
7077 // in far space. This requires pushing the result on the stack
7078 // then popping it into the result.
7080 genFarFarLogicOp(iCode *ic, char *logicOp)
7082 int size, resultSize, compSize;
7086 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
7087 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
7088 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
7090 _startLazyDPSEvaluation();
7091 for (size = compSize; (size--); offset++)
7093 MOVA (aopGet (IC_LEFT(ic), offset, FALSE, FALSE, NULL));
7094 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
7095 MOVA (aopGet (IC_RIGHT(ic), offset, FALSE, FALSE, NULL));
7097 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
7098 emitcode ("push", "acc");
7100 _endLazyDPSEvaluation();
7102 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7103 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7104 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
7106 resultSize = AOP_SIZE(IC_RESULT(ic));
7108 ADJUST_PUSHED_RESULT(compSize, resultSize);
7110 _startLazyDPSEvaluation();
7113 emitcode ("pop", "acc");
7114 aopPut (IC_RESULT (ic), "a", compSize);
7116 _endLazyDPSEvaluation();
7117 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
7121 /*-----------------------------------------------------------------*/
7122 /* genAnd - code for and */
7123 /*-----------------------------------------------------------------*/
7125 genAnd (iCode * ic, iCode * ifx)
7127 operand *left, *right, *result;
7128 int size, offset = 0;
7129 unsigned long lit = 0L;
7134 D (emitcode (";", "genAnd"));
7136 AOP_OP_3_NOFATAL (ic, pushResult);
7137 AOP_SET_LOCALS (ic);
7141 genFarFarLogicOp(ic, "anl");
7146 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
7148 AOP_TYPE (left), AOP_TYPE (right));
7149 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
7151 AOP_SIZE (left), AOP_SIZE (right));
7154 /* if left is a literal & right is not then exchange them */
7155 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7156 #ifdef LOGIC_OPS_BROKEN
7157 || AOP_NEEDSACC (left)
7161 operand *tmp = right;
7166 /* if result = right then exchange left and right */
7167 if (sameRegs (AOP (result), AOP (right)))
7169 operand *tmp = right;
7174 /* if right is bit then exchange them */
7175 if (AOP_TYPE (right) == AOP_CRY &&
7176 AOP_TYPE (left) != AOP_CRY)
7178 operand *tmp = right;
7182 if (AOP_TYPE (right) == AOP_LIT)
7183 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7185 size = AOP_SIZE (result);
7188 // result = bit & yy;
7189 if (AOP_TYPE (left) == AOP_CRY)
7191 // c = bit & literal;
7192 if (AOP_TYPE (right) == AOP_LIT)
7196 if (size && sameRegs (AOP (result), AOP (left)))
7199 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7204 if (size && (AOP_TYPE (result) == AOP_CRY))
7206 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
7209 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7214 emitcode ("clr", "c");
7219 if (AOP_TYPE (right) == AOP_CRY)
7222 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7223 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
7228 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
7230 emitcode ("rrc", "a");
7231 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
7239 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7240 genIfxJump (ifx, "c");
7244 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7245 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7246 if ((AOP_TYPE (right) == AOP_LIT) &&
7247 (AOP_TYPE (result) == AOP_CRY) &&
7248 (AOP_TYPE (left) != AOP_CRY))
7250 int posbit = isLiteralBit (lit);
7255 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE, NULL));
7259 switch (posbit & 0x07)
7261 case 0: emitcode ("rrc", "a");
7263 case 7: emitcode ("rlc", "a");
7265 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
7274 SNPRINTF (buffer, sizeof(buffer),
7275 "acc.%d", posbit & 0x07);
7276 genIfxJump (ifx, buffer);
7280 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
7287 symbol *tlbl = newiTempLabel (NULL);
7288 int sizel = AOP_SIZE (left);
7290 emitcode ("setb", "c");
7293 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
7295 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7297 if ((posbit = isLiteralBit (bytelit)) != 0)
7298 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
7301 if (bytelit != 0x0FFL)
7302 emitcode ("anl", "a,%s",
7303 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG));
7304 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7309 // bit = left & literal
7312 emitcode ("clr", "c");
7315 // if(left & literal)
7319 jmpTrueOrFalse (ifx, tlbl);
7329 /* if left is same as result */
7330 if (sameRegs (AOP (result), AOP (left)))
7332 for (; size--; offset++)
7334 if (AOP_TYPE (right) == AOP_LIT)
7336 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7337 if (bytelit == 0x0FF)
7339 /* dummy read of volatile operand */
7340 if (isOperandVolatile (left, FALSE))
7341 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7345 else if (bytelit == 0)
7347 aopPut (result, zero, offset);
7349 else if (IS_AOP_PREG (result))
7351 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7352 emitcode ("anl", "a,%s",
7353 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG));
7354 aopPut (result, "a", offset);
7357 emitcode ("anl", "%s,%s",
7358 aopGet (left, offset, FALSE, TRUE, NULL),
7359 aopGet (right, offset, FALSE, FALSE, NULL));
7363 if (AOP_TYPE (left) == AOP_ACC)
7366 emitcode("mov", "a,b");
7367 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7369 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7371 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
7372 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7373 emitcode ("anl", "a,b");
7374 aopPut (result, "a", offset);
7376 else if (aopGetUsesAcc (left, offset))
7378 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7379 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7380 aopPut (result, "a", offset);
7384 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7385 if (IS_AOP_PREG (result))
7387 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7388 aopPut (result, "a", offset);
7391 emitcode ("anl", "%s,a", aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7398 // left & result in different registers
7399 if (AOP_TYPE (result) == AOP_CRY)
7402 // if(size), result in bit
7403 // if(!size && ifx), conditional oper: if(left & right)
7404 symbol *tlbl = newiTempLabel (NULL);
7405 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
7407 emitcode ("setb", "c");
7410 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7411 && AOP_TYPE(left)==AOP_ACC)
7414 emitcode("mov", "a,b");
7415 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, NULL));
7417 else if (AOP_TYPE(left)==AOP_ACC)
7421 bool pushedB = pushB ();
7422 emitcode("mov", "b,a");
7423 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7424 emitcode("anl", "a,b");
7429 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7430 emitcode("anl", "a,b");
7433 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7435 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE, NULL));
7436 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7437 emitcode ("anl", "a,b");
7439 else if (aopGetUsesAcc (left, offset))
7441 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7442 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7446 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7447 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE, DP2_RESULT_REG));
7450 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7460 jmpTrueOrFalse (ifx, tlbl);
7466 for (; (size--); offset++)
7469 // result = left & right
7470 if (AOP_TYPE (right) == AOP_LIT)
7472 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7473 if (bytelit == 0x0FF)
7476 aopGet (left, offset, FALSE, FALSE, NULL),
7480 else if (bytelit == 0)
7482 /* dummy read of volatile operand */
7483 if (isOperandVolatile (left, FALSE))
7484 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7485 aopPut (result, zero, offset);
7488 else if (AOP_TYPE (left) == AOP_ACC)
7492 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, NULL));
7493 aopPut (result, "a", offset);
7498 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE, NULL));
7499 aopPut (result, "b", offset);
7504 // faster than result <- left, anl result,right
7505 // and better if result is SFR
7506 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7507 && AOP_TYPE(left)==AOP_ACC)
7510 emitcode("mov", "a,b");
7511 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, NULL));
7513 else if (AOP_TYPE(left)==AOP_ACC)
7517 bool pushedB = pushB ();
7518 emitcode("mov", "b,a");
7519 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7520 emitcode("anl", "a,b");
7525 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7526 emitcode("anl", "a,b");
7529 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7531 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
7532 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7533 emitcode ("anl", "a,b");
7535 else if (aopGetUsesAcc (left, offset))
7537 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7538 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7542 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7543 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE, DP2_RESULT_REG));
7545 aopPut (result, "a", offset);
7551 freeAsmop (result, NULL, ic, TRUE);
7552 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7553 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7556 /*-----------------------------------------------------------------*/
7557 /* genOr - code for or */
7558 /*-----------------------------------------------------------------*/
7560 genOr (iCode * ic, iCode * ifx)
7562 operand *left, *right, *result;
7563 int size, offset = 0;
7564 unsigned long lit = 0L;
7568 D (emitcode (";", "genOr"));
7570 AOP_OP_3_NOFATAL (ic, pushResult);
7571 AOP_SET_LOCALS (ic);
7575 genFarFarLogicOp(ic, "orl");
7581 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
7583 AOP_TYPE (left), AOP_TYPE (right));
7584 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
7586 AOP_SIZE (left), AOP_SIZE (right));
7589 /* if left is a literal & right is not then exchange them */
7590 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7591 #ifdef LOGIC_OPS_BROKEN
7592 || AOP_NEEDSACC (left) // I think this is a net loss now.
7596 operand *tmp = right;
7601 /* if result = right then exchange them */
7602 if (sameRegs (AOP (result), AOP (right)))
7604 operand *tmp = right;
7609 /* if right is bit then exchange them */
7610 if (AOP_TYPE (right) == AOP_CRY &&
7611 AOP_TYPE (left) != AOP_CRY)
7613 operand *tmp = right;
7617 if (AOP_TYPE (right) == AOP_LIT)
7618 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7620 size = AOP_SIZE (result);
7624 if (AOP_TYPE (left) == AOP_CRY)
7626 if (AOP_TYPE (right) == AOP_LIT)
7628 // c = bit | literal;
7631 // lit != 0 => result = 1
7632 if (AOP_TYPE (result) == AOP_CRY)
7635 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7637 continueIfTrue (ifx);
7640 emitcode ("setb", "c");
7644 // lit == 0 => result = left
7645 if (size && sameRegs (AOP (result), AOP (left)))
7647 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7652 if (AOP_TYPE (right) == AOP_CRY)
7655 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7656 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7661 symbol *tlbl = newiTempLabel (NULL);
7662 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
7663 emitcode ("setb", "c");
7664 emitcode ("jb", "%s,!tlabel",
7665 AOP (left)->aopu.aop_dir, tlbl->key + 100);
7667 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7668 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7670 jmpTrueOrFalse (ifx, tlbl);
7685 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7686 genIfxJump (ifx, "c");
7690 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7691 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7692 if ((AOP_TYPE (right) == AOP_LIT) &&
7693 (AOP_TYPE (result) == AOP_CRY) &&
7694 (AOP_TYPE (left) != AOP_CRY))
7700 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7702 continueIfTrue (ifx);
7707 // lit = 0, result = boolean(left)
7709 emitcode ("setb", "c");
7713 symbol *tlbl = newiTempLabel (NULL);
7714 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7720 genIfxJump (ifx, "a");
7728 /* if left is same as result */
7729 if (sameRegs (AOP (result), AOP (left)))
7731 for (; size--; offset++)
7733 if (AOP_TYPE (right) == AOP_LIT)
7735 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7738 /* dummy read of volatile operand */
7739 if (isOperandVolatile (left, FALSE))
7740 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7744 else if (bytelit == 0x0FF)
7746 aopPut (result, "#0xFF", offset);
7748 else if (IS_AOP_PREG (left))
7750 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7751 emitcode ("orl", "a,%s",
7752 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7753 aopPut (result, "a", offset);
7757 emitcode ("orl", "%s,%s",
7758 aopGet (left, offset, FALSE, TRUE, NULL),
7759 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7764 if (AOP_TYPE (left) == AOP_ACC)
7767 emitcode("mov", "a,b");
7768 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7770 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7772 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE, NULL));
7773 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7774 emitcode ("orl", "a,b");
7775 aopPut (result, "a", offset);
7777 else if (aopGetUsesAcc (left, offset))
7779 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7780 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7781 aopPut (result, "a", offset);
7785 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7786 if (IS_AOP_PREG (left))
7788 emitcode ("orl", "a,%s",
7789 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7790 aopPut (result, "a", offset);
7794 emitcode ("orl", "%s,a",
7795 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7803 // left & result in different registers
7804 if (AOP_TYPE (result) == AOP_CRY)
7807 // if(size), result in bit
7808 // if(!size && ifx), conditional oper: if(left | right)
7809 symbol *tlbl = newiTempLabel (NULL);
7810 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7812 emitcode ("setb", "c");
7815 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7816 && AOP_TYPE(left)==AOP_ACC)
7819 emitcode("mov", "a,b");
7820 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7822 else if (AOP_TYPE(left)==AOP_ACC)
7826 bool pushedB = pushB ();
7827 emitcode("mov", "b,a");
7828 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7829 emitcode("orl", "a,b");
7834 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7835 emitcode("orl", "a,b");
7838 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7840 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
7841 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7842 emitcode ("orl", "a,b");
7844 else if (aopGetUsesAcc (left, offset))
7846 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7847 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7851 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7852 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE, DP2_RESULT_REG));
7855 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7865 jmpTrueOrFalse (ifx, tlbl);
7871 _startLazyDPSEvaluation();
7872 for (; (size--); offset++)
7875 // result = left | right
7876 if (AOP_TYPE (right) == AOP_LIT)
7878 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7882 aopGet (left, offset, FALSE, FALSE, NULL),
7886 else if (bytelit == 0x0FF)
7888 /* dummy read of volatile operand */
7889 if (isOperandVolatile (left, FALSE))
7890 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7891 aopPut (result, "#0xFF", offset);
7895 // faster than result <- left, orl result,right
7896 // and better if result is SFR
7897 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7898 && AOP_TYPE(left)==AOP_ACC)
7901 emitcode("mov", "a,b");
7902 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7904 else if (AOP_TYPE(left)==AOP_ACC)
7908 bool pushedB = pushB ();
7909 emitcode("mov", "b,a");
7910 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7911 emitcode("orl", "a,b");
7916 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7917 emitcode("orl", "a,b");
7920 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7922 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
7923 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7924 emitcode ("orl", "a,b");
7926 else if (aopGetUsesAcc (left, offset))
7928 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7929 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7933 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7934 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE, DP2_RESULT_REG));
7936 aopPut (result, "a", offset);
7938 _endLazyDPSEvaluation();
7943 freeAsmop (result, NULL, ic, TRUE);
7944 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7945 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7948 /*-----------------------------------------------------------------*/
7949 /* genXor - code for xclusive or */
7950 /*-----------------------------------------------------------------*/
7952 genXor (iCode * ic, iCode * ifx)
7954 operand *left, *right, *result;
7955 int size, offset = 0;
7956 unsigned long lit = 0L;
7960 D (emitcode (";", "genXor"));
7962 AOP_OP_3_NOFATAL (ic, pushResult);
7963 AOP_SET_LOCALS (ic);
7967 genFarFarLogicOp(ic, "xrl");
7972 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
7974 AOP_TYPE (left), AOP_TYPE (right));
7975 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
7977 AOP_SIZE (left), AOP_SIZE (right));
7980 /* if left is a literal & right is not ||
7981 if left needs acc & right does not */
7982 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7983 #ifdef LOGIC_OPS_BROKEN
7984 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
7988 operand *tmp = right;
7993 /* if result = right then exchange them */
7994 if (sameRegs (AOP (result), AOP (right)))
7996 operand *tmp = right;
8001 /* if right is bit then exchange them */
8002 if (AOP_TYPE (right) == AOP_CRY &&
8003 AOP_TYPE (left) != AOP_CRY)
8005 operand *tmp = right;
8009 if (AOP_TYPE (right) == AOP_LIT)
8010 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8012 size = AOP_SIZE (result);
8016 if (AOP_TYPE (left) == AOP_CRY)
8018 if (AOP_TYPE (right) == AOP_LIT)
8020 // c = bit & literal;
8023 // lit>>1 != 0 => result = 1
8024 if (AOP_TYPE (result) == AOP_CRY)
8027 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
8029 continueIfTrue (ifx);
8032 emitcode ("setb", "c");
8039 // lit == 0, result = left
8040 if (size && sameRegs (AOP (result), AOP (left)))
8042 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
8046 // lit == 1, result = not(left)
8047 if (size && sameRegs (AOP (result), AOP (left)))
8049 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
8054 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
8055 emitcode ("cpl", "c");
8063 symbol *tlbl = newiTempLabel (NULL);
8064 if (AOP_TYPE (right) == AOP_CRY)
8067 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8071 int sizer = AOP_SIZE (right);
8073 // if val>>1 != 0, result = 1
8074 emitcode ("setb", "c");
8077 MOVA (aopGet (right, sizer - 1, FALSE, FALSE, NULL));
8079 // test the msb of the lsb
8080 emitcode ("anl", "a,#!constbyte",0xfe);
8081 emitcode ("jnz", "!tlabel", tlbl->key + 100);
8085 emitcode ("rrc", "a");
8087 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
8088 emitcode ("cpl", "c");
8096 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
8097 genIfxJump (ifx, "c");
8101 /* if left is same as result */
8102 if (sameRegs (AOP (result), AOP (left)))
8104 for (; size--; offset++)
8106 if (AOP_TYPE (right) == AOP_LIT)
8108 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
8111 /* dummy read of volatile operand */
8112 if (isOperandVolatile (left, FALSE))
8113 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8117 else if (IS_AOP_PREG (left))
8119 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8120 emitcode ("xrl", "a,%s",
8121 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG));
8122 aopPut (result, "a", offset);
8126 emitcode ("xrl", "%s,%s",
8127 aopGet (left, offset, FALSE, TRUE, NULL),
8128 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8133 if (AOP_TYPE (left) == AOP_ACC)
8136 emitcode("mov", "a,b");
8137 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8139 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
8141 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
8142 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8143 emitcode ("xrl", "a,b");
8144 aopPut (result, "a", offset);
8146 else if (aopGetUsesAcc (left, offset))
8148 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8149 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8150 aopPut (result, "a", offset);
8154 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
8155 if (IS_AOP_PREG (left))
8157 emitcode ("xrl", "a,%s",
8158 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
8159 aopPut (result, "a", offset);
8162 emitcode ("xrl", "%s,a",
8163 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
8170 // left & result in different registers
8171 if (AOP_TYPE (result) == AOP_CRY)
8174 // if(size), result in bit
8175 // if(!size && ifx), conditional oper: if(left ^ right)
8176 symbol *tlbl = newiTempLabel (NULL);
8177 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
8180 emitcode ("setb", "c");
8183 if ((AOP_TYPE (right) == AOP_LIT) &&
8184 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
8186 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8188 else if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
8189 && AOP_TYPE(left)==AOP_ACC)
8192 emitcode("mov", "a,b");
8193 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8195 else if (AOP_TYPE(left)==AOP_ACC)
8199 bool pushedB = pushB ();
8200 emitcode("mov", "b,a");
8201 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8202 emitcode("xrl", "a,b");
8207 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8208 emitcode("xrl", "a,b");
8211 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
8213 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
8214 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8215 emitcode ("xrl", "a,b");
8217 else if (aopGetUsesAcc (left, offset))
8219 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8220 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8224 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
8225 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
8228 emitcode ("jnz", "!tlabel", tlbl->key + 100);
8238 jmpTrueOrFalse (ifx, tlbl);
8242 for (; (size--); offset++)
8245 // result = left ^ right
8246 if (AOP_TYPE (right) == AOP_LIT)
8248 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
8252 aopGet (left, offset, FALSE, FALSE, NULL),
8256 D (emitcode (";", "better literal XOR."));
8257 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8258 emitcode ("xrl", "a, %s",
8259 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8263 // faster than result <- left, anl result,right
8264 // and better if result is SFR
8265 if (AOP_TYPE (left) == AOP_ACC)
8267 emitcode ("xrl", "a,%s",
8268 aopGet (right, offset,
8269 FALSE, FALSE, DP2_RESULT_REG));
8273 char *rOp = aopGet (right, offset, FALSE, FALSE, NULL);
8274 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
8276 emitcode("mov", "b,a");
8280 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8281 emitcode ("xrl", "a,%s", rOp);
8284 aopPut (result, "a", offset);
8290 freeAsmop (result, NULL, ic, TRUE);
8291 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
8292 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
8295 /*-----------------------------------------------------------------*/
8296 /* genInline - write the inline code out */
8297 /*-----------------------------------------------------------------*/
8299 genInline (iCode * ic)
8301 char *buffer, *bp, *bp1;
8303 D (emitcode (";", "genInline"));
8305 _G.inLine += (!options.asmpeep);
8307 buffer = bp = bp1 = Safe_strdup(IC_INLINE(ic));
8309 /* emit each line as a code */
8320 /* Add \n for labels, not dirs such as c:\mydir */
8321 if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
8335 /* emitcode("",buffer); */
8336 _G.inLine -= (!options.asmpeep);
8339 /*-----------------------------------------------------------------*/
8340 /* genRRC - rotate right with carry */
8341 /*-----------------------------------------------------------------*/
8345 operand *left, *result;
8349 D (emitcode (";", "genRRC"));
8351 /* rotate right with carry */
8352 left = IC_LEFT (ic);
8353 result = IC_RESULT (ic);
8354 aopOp (left, ic, FALSE, FALSE);
8355 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8357 /* move it to the result */
8358 size = AOP_SIZE (result);
8362 _startLazyDPSEvaluation ();
8365 l = aopGet (left, offset, FALSE, FALSE, NULL);
8367 emitcode ("rrc", "a");
8368 if (AOP_SIZE (result) > 1)
8369 aopPut (result, "a", offset--);
8371 _endLazyDPSEvaluation ();
8373 /* now we need to put the carry into the
8374 highest order byte of the result */
8375 if (AOP_SIZE (result) > 1)
8377 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE, NULL);
8380 emitcode ("mov", "acc.7,c");
8381 aopPut (result, "a", AOP_SIZE (result) - 1);
8382 freeAsmop (result, NULL, ic, TRUE);
8383 freeAsmop (left, NULL, ic, TRUE);
8386 /*-----------------------------------------------------------------*/
8387 /* genRLC - generate code for rotate left with carry */
8388 /*-----------------------------------------------------------------*/
8392 operand *left, *result;
8396 D (emitcode (";", "genRLC"));
8398 /* rotate right with carry */
8399 left = IC_LEFT (ic);
8400 result = IC_RESULT (ic);
8401 aopOp (left, ic, FALSE, FALSE);
8402 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8404 /* move it to the result */
8405 size = AOP_SIZE (result);
8409 l = aopGet (left, offset, FALSE, FALSE, NULL);
8411 emitcode ("add", "a,acc");
8412 if (AOP_SIZE (result) > 1)
8414 aopPut (result, "a", offset++);
8417 _startLazyDPSEvaluation ();
8420 l = aopGet (left, offset, FALSE, FALSE, NULL);
8422 emitcode ("rlc", "a");
8423 if (AOP_SIZE (result) > 1)
8424 aopPut (result, "a", offset++);
8426 _endLazyDPSEvaluation ();
8428 /* now we need to put the carry into the
8429 highest order byte of the result */
8430 if (AOP_SIZE (result) > 1)
8432 l = aopGet (result, 0, FALSE, FALSE, NULL);
8435 emitcode ("mov", "acc.0,c");
8436 aopPut (result, "a", 0);
8437 freeAsmop (result, NULL, ic, TRUE);
8438 freeAsmop (left, NULL, ic, TRUE);
8441 /*-----------------------------------------------------------------*/
8442 /* genGetHbit - generates code get highest order bit */
8443 /*-----------------------------------------------------------------*/
8445 genGetHbit (iCode * ic)
8447 operand *left, *result;
8449 D (emitcode (";", "genGetHbit"));
8451 left = IC_LEFT (ic);
8452 result = IC_RESULT (ic);
8453 aopOp (left, ic, FALSE, FALSE);
8454 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8456 /* get the highest order byte into a */
8457 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
8458 if (AOP_TYPE (result) == AOP_CRY)
8460 emitcode ("rlc", "a");
8465 emitcode ("rl", "a");
8466 emitcode ("anl", "a,#1");
8471 freeAsmop (result, NULL, ic, TRUE);
8472 freeAsmop (left, NULL, ic, TRUE);
8475 /*-----------------------------------------------------------------*/
8476 /* genSwap - generates code to swap nibbles or bytes */
8477 /*-----------------------------------------------------------------*/
8479 genSwap (iCode * ic)
8481 operand *left, *result;
8483 D(emitcode (";", "genSwap"));
8485 left = IC_LEFT (ic);
8486 result = IC_RESULT (ic);
8487 aopOp (left, ic, FALSE, FALSE);
8488 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8490 _startLazyDPSEvaluation ();
8491 switch (AOP_SIZE (left))
8493 case 1: /* swap nibbles in byte */
8494 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
8495 emitcode ("swap", "a");
8496 aopPut (result, "a", 0);
8498 case 2: /* swap bytes in word */
8499 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
8501 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
8502 aopPut (result, aopGet (left, 1, FALSE, FALSE, NULL), 0);
8503 aopPut (result, "a", 1);
8505 else if (operandsEqu (left, result))
8508 bool pushedB = FALSE, leftInB = FALSE;
8510 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
8511 if (AOP_NEEDSACC (left) || AOP_NEEDSACC (result))
8514 emitcode ("mov", "b,a");
8518 aopPut (result, aopGet (left, 1, FALSE, FALSE, NULL), 0);
8519 aopPut (result, reg, 1);
8526 aopPut (result, aopGet (left, 1, FALSE, FALSE, NULL), 0);
8527 aopPut (result, aopGet (left, 0, FALSE, FALSE, NULL), 1);
8531 wassertl(FALSE, "unsupported SWAP operand size");
8533 _endLazyDPSEvaluation ();
8535 freeAsmop (result, NULL, ic, TRUE);
8536 freeAsmop (left, NULL, ic, TRUE);
8539 /*-----------------------------------------------------------------*/
8540 /* AccRol - rotate left accumulator by known count */
8541 /*-----------------------------------------------------------------*/
8543 AccRol (int shCount)
8545 shCount &= 0x0007; // shCount : 0..7
8552 emitcode ("rl", "a");
8555 emitcode ("rl", "a");
8556 emitcode ("rl", "a");
8559 emitcode ("swap", "a");
8560 emitcode ("rr", "a");
8563 emitcode ("swap", "a");
8566 emitcode ("swap", "a");
8567 emitcode ("rl", "a");
8570 emitcode ("rr", "a");
8571 emitcode ("rr", "a");
8574 emitcode ("rr", "a");
8579 /*-----------------------------------------------------------------*/
8580 /* AccLsh - left shift accumulator by known count */
8581 /*-----------------------------------------------------------------*/
8583 AccLsh (int shCount)
8588 emitcode ("add", "a,acc");
8589 else if (shCount == 2)
8591 emitcode ("add", "a,acc");
8592 emitcode ("add", "a,acc");
8596 /* rotate left accumulator */
8598 /* and kill the lower order bits */
8599 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
8604 /*-----------------------------------------------------------------*/
8605 /* AccRsh - right shift accumulator by known count */
8606 /*-----------------------------------------------------------------*/
8608 AccRsh (int shCount)
8615 emitcode ("rrc", "a");
8619 /* rotate right accumulator */
8620 AccRol (8 - shCount);
8621 /* and kill the higher order bits */
8622 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
8627 #ifdef BETTER_LITERAL_SHIFT
8628 /*-----------------------------------------------------------------*/
8629 /* AccSRsh - signed right shift accumulator by known count */
8630 /*-----------------------------------------------------------------*/
8632 AccSRsh (int shCount)
8639 emitcode ("mov", "c,acc.7");
8640 emitcode ("rrc", "a");
8642 else if (shCount == 2)
8644 emitcode ("mov", "c,acc.7");
8645 emitcode ("rrc", "a");
8646 emitcode ("mov", "c,acc.7");
8647 emitcode ("rrc", "a");
8651 tlbl = newiTempLabel (NULL);
8652 /* rotate right accumulator */
8653 AccRol (8 - shCount);
8654 /* and kill the higher order bits */
8655 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
8656 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8657 emitcode ("orl", "a,#!constbyte",
8658 (unsigned char) ~SRMask[shCount]);
8665 #ifdef BETTER_LITERAL_SHIFT
8666 /*-----------------------------------------------------------------*/
8667 /* shiftR1Left2Result - shift right one byte from left to result */
8668 /*-----------------------------------------------------------------*/
8670 shiftR1Left2Result (operand * left, int offl,
8671 operand * result, int offr,
8672 int shCount, int sign)
8674 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
8675 /* shift right accumulator */
8680 aopPut (result, "a", offr);
8684 #ifdef BETTER_LITERAL_SHIFT
8685 /*-----------------------------------------------------------------*/
8686 /* shiftL1Left2Result - shift left one byte from left to result */
8687 /*-----------------------------------------------------------------*/
8689 shiftL1Left2Result (operand * left, int offl,
8690 operand * result, int offr, int shCount)
8693 l = aopGet (left, offl, FALSE, FALSE, NULL);
8695 /* shift left accumulator */
8697 aopPut (result, "a", offr);
8701 #ifdef BETTER_LITERAL_SHIFT
8702 /*-----------------------------------------------------------------*/
8703 /* movLeft2Result - move byte from left to result */
8704 /*-----------------------------------------------------------------*/
8706 movLeft2Result (operand * left, int offl,
8707 operand * result, int offr, int sign)
8710 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8712 l = aopGet (left, offl, FALSE, FALSE, NULL);
8714 if (*l == '@' && (IS_AOP_PREG (result)))
8716 emitcode ("mov", "a,%s", l);
8717 aopPut (result, "a", offr);
8723 aopPut (result, l, offr);
8727 /* MSB sign in acc.7 ! */
8728 if (getDataSize (left) == offl + 1)
8731 aopPut (result, "a", offr);
8739 #ifdef BETTER_LITERAL_SHIFT
8740 /*-----------------------------------------------------------------*/
8741 /* AccAXRrl1 - right rotate a:x by 1 */
8742 /*-----------------------------------------------------------------*/
8746 emitcode ("mov", "c,acc.0");
8747 emitcode ("xch", "a,%s", x);
8748 emitcode ("rrc", "a");
8749 emitcode ("xch", "a,%s", x);
8750 emitcode ("rrc", "a");
8754 #ifdef BETTER_LITERAL_SHIFT
8756 /*-----------------------------------------------------------------*/
8757 /* AccAXLrl1 - left rotate a:x by 1 */
8758 /*-----------------------------------------------------------------*/
8762 emitcode ("mov", "c,acc.7");
8763 emitcode ("xch", "a,%s", x);
8764 emitcode ("rlc", "a");
8765 emitcode ("xch", "a,%s", x);
8766 emitcode ("rlc", "a");
8770 #ifdef BETTER_LITERAL_SHIFT
8771 /*-----------------------------------------------------------------*/
8772 /* AccAXRsh1 - right shift c->a:x->c by 1 */
8773 /*-----------------------------------------------------------------*/
8777 emitcode ("rrc", "a");
8778 emitcode ("xch", "a,%s", x);
8779 emitcode ("rrc", "a");
8780 emitcode ("xch", "a,%s", x);
8784 #ifdef BETTER_LITERAL_SHIFT
8785 /*-----------------------------------------------------------------*/
8786 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8787 /*-----------------------------------------------------------------*/
8791 emitcode ("xch", "a,%s", x);
8792 emitcode ("add", "a,acc");
8793 emitcode ("xch", "a,%s", x);
8794 emitcode ("rlc", "a");
8798 #ifdef BETTER_LITERAL_SHIFT
8799 /*-----------------------------------------------------------------*/
8800 /* AccAXLsh - left shift a:x by known count (0..7) */
8801 /*-----------------------------------------------------------------*/
8803 AccAXLsh (char *x, int shCount)
8818 case 5: // AAAAABBB:CCCCCDDD
8820 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8822 emitcode ("anl", "a,#!constbyte",
8823 SLMask[shCount]); // BBB00000:CCCCCDDD
8825 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8827 AccRol (shCount); // DDDCCCCC:BBB00000
8829 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8831 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8833 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8835 emitcode ("anl", "a,#!constbyte",
8836 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8838 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8840 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8843 case 6: // AAAAAABB:CCCCCCDD
8844 emitcode ("anl", "a,#!constbyte",
8845 SRMask[shCount]); // 000000BB:CCCCCCDD
8847 AccAXRrl1 (x); // D000000B:BCCCCCCD
8848 AccAXRrl1 (x); // DD000000:BBCCCCCC
8849 emitcode ("xch", "a,%s", x); // BBCCCCCC:DD000000
8851 emitcode ("mov", "c,acc.0"); // c = B
8852 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8853 emitcode("rrc","a");
8854 emitcode("xch","a,%s", x);
8855 emitcode("rrc","a");
8856 emitcode("mov","c,acc.0"); //<< get correct bit
8857 emitcode("xch","a,%s", x);
8859 emitcode("rrc","a");
8860 emitcode("xch","a,%s", x);
8861 emitcode("rrc","a");
8862 emitcode("xch","a,%s", x);
8865 case 7: // a:x <<= 7
8867 emitcode ("anl", "a,#!constbyte",
8868 SRMask[shCount]); // 0000000B:CCCCCCCD
8870 AccAXRrl1 (x); // D0000000:BCCCCCCC
8872 emitcode ("xch", "a,%s", x); // BCCCCCCC:D0000000
8881 #ifdef BETTER_LITERAL_SHIFT
8883 /*-----------------------------------------------------------------*/
8884 /* AccAXRsh - right shift a:x known count (0..7) */
8885 /*-----------------------------------------------------------------*/
8887 AccAXRsh (char *x, int shCount)
8895 AccAXRsh1 (x); // 0->a:x
8900 AccAXRsh1 (x); // 0->a:x
8903 AccAXRsh1 (x); // 0->a:x
8908 case 5: // AAAAABBB:CCCCCDDD = a:x
8910 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8912 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8914 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8916 emitcode ("anl", "a,#!constbyte",
8917 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8919 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8921 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8923 emitcode ("anl", "a,#!constbyte",
8924 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8926 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8928 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8930 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8933 case 6: // AABBBBBB:CCDDDDDD
8935 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDE
8936 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8938 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8940 emitcode ("anl", "a,#!constbyte",
8941 SRMask[shCount]); // 000000AA:BBBBBBCC
8944 case 7: // ABBBBBBB:CDDDDDDD
8946 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8948 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8950 emitcode ("anl", "a,#!constbyte",
8951 SRMask[shCount]); // 0000000A:BBBBBBBC
8960 #ifdef BETTER_LITERAL_SHIFT
8961 /*-----------------------------------------------------------------*/
8962 /* AccAXRshS - right shift signed a:x known count (0..7) */
8963 /*-----------------------------------------------------------------*/
8965 AccAXRshS (char *x, int shCount)
8973 emitcode ("mov", "c,acc.7");
8974 AccAXRsh1 (x); // s->a:x
8978 emitcode ("mov", "c,acc.7");
8979 AccAXRsh1 (x); // s->a:x
8981 emitcode ("mov", "c,acc.7");
8982 AccAXRsh1 (x); // s->a:x
8987 case 5: // AAAAABBB:CCCCCDDD = a:x
8989 tlbl = newiTempLabel (NULL);
8990 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8992 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8994 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8996 emitcode ("anl", "a,#!constbyte",
8997 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8999 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
9001 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
9003 emitcode ("anl", "a,#!constbyte",
9004 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
9006 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
9008 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
9010 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
9012 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
9013 emitcode ("orl", "a,#!constbyte",
9014 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
9017 break; // SSSSAAAA:BBBCCCCC
9019 case 6: // AABBBBBB:CCDDDDDD
9021 tlbl = newiTempLabel (NULL);
9023 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
9024 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
9026 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
9028 emitcode ("anl", "a,#!constbyte",
9029 SRMask[shCount]); // 000000AA:BBBBBBCC
9031 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
9032 emitcode ("orl", "a,#!constbyte",
9033 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
9037 case 7: // ABBBBBBB:CDDDDDDD
9039 tlbl = newiTempLabel (NULL);
9041 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
9043 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
9045 emitcode ("anl", "a,#!constbyte",
9046 SRMask[shCount]); // 0000000A:BBBBBBBC
9048 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
9049 emitcode ("orl", "a,#!constbyte",
9050 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
9060 #ifdef BETTER_LITERAL_SHIFT
9062 _loadLeftIntoAx(char **lsb,
9068 // Get the initial value from left into a pair of registers.
9069 // MSB must be in A, LSB can be any register.
9071 // If the result is held in registers, it is an optimization
9072 // if the LSB can be held in the register which will hold the,
9073 // result LSB since this saves us from having to copy it into
9074 // the result following AccAXLsh.
9076 // If the result is addressed indirectly, this is not a gain.
9077 if (AOP_NEEDSACC(result))
9081 _startLazyDPSEvaluation();
9082 if (AOP_TYPE(left) == AOP_DPTR2)
9085 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE, NULL));
9086 // get LSB in DP2_RESULT_REG.
9087 leftByte = aopGet (left, offl, FALSE, FALSE, DP2_RESULT_REG);
9088 assert(!strcmp(leftByte, DP2_RESULT_REG));
9092 // get LSB into DP2_RESULT_REG
9093 leftByte = aopGet (left, offl, FALSE, FALSE, NULL);
9094 if (strcmp(leftByte, DP2_RESULT_REG))
9097 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
9100 leftByte = aopGet (left, offl + MSB16, FALSE, FALSE, NULL);
9101 assert(strcmp(leftByte, DP2_RESULT_REG));
9104 _endLazyDPSEvaluation();
9105 *lsb = DP2_RESULT_REG;
9109 if (sameRegs (AOP (result), AOP (left)) &&
9110 ((offl + MSB16) == offr))
9112 /* don't crash result[offr] */
9113 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
9114 emitcode ("xch", "a,%s",
9115 aopGet (left, offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
9119 movLeft2Result (left, offl, result, offr, 0);
9120 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE, NULL));
9122 *lsb = aopGet (result, offr, FALSE, FALSE, DP2_RESULT_REG);
9123 assert(strcmp(*lsb,"a"));
9128 _storeAxResults(char *lsb,
9132 _startLazyDPSEvaluation();
9133 if (AOP_NEEDSACC(result))
9135 /* We have to explicitly update the result LSB.
9137 emitcode ("xch","a,%s", lsb);
9138 aopPut (result, "a", offr);
9139 emitcode ("mov","a,%s", lsb);
9141 if (getDataSize (result) > 1)
9143 aopPut (result, "a", offr + MSB16);
9145 _endLazyDPSEvaluation();
9148 /*-----------------------------------------------------------------*/
9149 /* shiftL2Left2Result - shift left two bytes from left to result */
9150 /*-----------------------------------------------------------------*/
9152 shiftL2Left2Result (operand * left, int offl,
9153 operand * result, int offr, int shCount)
9157 _loadLeftIntoAx(&lsb, left, result, offl, offr);
9159 AccAXLsh (lsb, shCount);
9161 _storeAxResults(lsb, result, offr);
9165 #ifdef BETTER_LITERAL_SHIFT
9166 /*-----------------------------------------------------------------*/
9167 /* shiftR2Left2Result - shift right two bytes from left to result */
9168 /*-----------------------------------------------------------------*/
9170 shiftR2Left2Result (operand * left, int offl,
9171 operand * result, int offr,
9172 int shCount, int sign)
9176 _loadLeftIntoAx(&lsb, left, result, offl, offr);
9178 /* a:x >> shCount (x = lsb(result)) */
9181 AccAXRshS(lsb, shCount);
9185 AccAXRsh(lsb, shCount);
9188 _storeAxResults(lsb, result, offr);
9192 /*-----------------------------------------------------------------*/
9193 /* shiftLLeftOrResult - shift left one byte from left, or to result */
9194 /*-----------------------------------------------------------------*/
9196 shiftLLeftOrResult (operand * left, int offl,
9197 operand * result, int offr, int shCount)
9199 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
9200 /* shift left accumulator */
9202 /* or with result */
9203 emitcode ("orl", "a,%s",
9204 aopGet (result, offr, FALSE, FALSE, DP2_RESULT_REG));
9205 /* back to result */
9206 aopPut (result, "a", offr);
9211 /*-----------------------------------------------------------------*/
9212 /* shiftRLeftOrResult - shift right one byte from left,or to result */
9213 /*-----------------------------------------------------------------*/
9215 shiftRLeftOrResult (operand * left, int offl,
9216 operand * result, int offr, int shCount)
9218 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
9219 /* shift right accumulator */
9221 /* or with result */
9222 emitcode ("orl", "a,%s",
9223 aopGet (result, offr, FALSE, FALSE, DP2_RESULT_REG));
9224 /* back to result */
9225 aopPut (result, "a", offr);
9229 #ifdef BETTER_LITERAL_SHIFT
9230 /*-----------------------------------------------------------------*/
9231 /* genlshOne - left shift a one byte quantity by known count */
9232 /*-----------------------------------------------------------------*/
9234 genlshOne (operand * result, operand * left, int shCount)
9236 D (emitcode (";", "genlshOne"));
9238 shiftL1Left2Result (left, LSB, result, LSB, shCount);
9242 #ifdef BETTER_LITERAL_SHIFT
9243 /*-----------------------------------------------------------------*/
9244 /* genlshTwo - left shift two bytes by known amount != 0 */
9245 /*-----------------------------------------------------------------*/
9247 genlshTwo (operand * result, operand * left, int shCount)
9251 D (emitcode (";", "genlshTwo"));
9253 size = getDataSize (result);
9255 /* if shCount >= 8 */
9260 _startLazyDPSEvaluation();
9266 _endLazyDPSEvaluation();
9267 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
9268 aopPut (result, zero, LSB);
9272 movLeft2Result (left, LSB, result, MSB16, 0);
9273 aopPut (result, zero, LSB);
9274 _endLazyDPSEvaluation();
9279 aopPut (result, zero, LSB);
9280 _endLazyDPSEvaluation();
9284 /* 1 <= shCount <= 7 */
9288 shiftL1Left2Result (left, LSB, result, LSB, shCount);
9290 shiftL2Left2Result (left, LSB, result, LSB, shCount);
9297 /*-----------------------------------------------------------------*/
9298 /* shiftLLong - shift left one long from left to result */
9299 /* offl = LSB or MSB16 */
9300 /*-----------------------------------------------------------------*/
9302 shiftLLong (operand * left, operand * result, int offr)
9305 int size = AOP_SIZE (result);
9307 if (size >= LSB + offr)
9309 l = aopGet (left, LSB, FALSE, FALSE, NULL);
9311 emitcode ("add", "a,acc");
9312 if (sameRegs (AOP (left), AOP (result)) &&
9313 size >= MSB16 + offr && offr != LSB)
9314 emitcode ("xch", "a,%s",
9315 aopGet (left, LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
9317 aopPut (result, "a", LSB + offr);
9320 if (size >= MSB16 + offr)
9322 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
9324 l = aopGet (left, MSB16, FALSE, FALSE, TRUE);
9327 emitcode ("rlc", "a");
9328 if (sameRegs (AOP (left), AOP (result)) &&
9329 size >= MSB24 + offr && offr != LSB)
9330 emitcode ("xch", "a,%s",
9331 aopGet (left, MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
9333 aopPut (result, "a", MSB16 + offr);
9336 if (size >= MSB24 + offr)
9338 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
9340 l = aopGet (left, MSB24, FALSE, FALSE, NULL);
9343 emitcode ("rlc", "a");
9344 if (sameRegs (AOP (left), AOP (result)) &&
9345 size >= MSB32 + offr && offr != LSB)
9346 emitcode ("xch", "a,%s",
9347 aopGet (left, MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
9349 aopPut (result, "a", MSB24 + offr);
9352 if (size > MSB32 + offr)
9354 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
9356 l = aopGet (left, MSB32, FALSE, FALSE, NULL);
9359 emitcode ("rlc", "a");
9360 aopPut (result, "a", MSB32 + offr);
9363 aopPut (result, zero, LSB);
9369 /*-----------------------------------------------------------------*/
9370 /* genlshFour - shift four byte by a known amount != 0 */
9371 /*-----------------------------------------------------------------*/
9373 genlshFour (operand * result, operand * left, int shCount)
9377 D (emitcode (";", "genlshFour"));
9379 size = AOP_SIZE (result);
9381 /* if shifting more that 3 bytes */
9386 /* lowest order of left goes to the highest
9387 order of the destination */
9388 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
9390 movLeft2Result (left, LSB, result, MSB32, 0);
9391 aopPut (result, zero, LSB);
9392 aopPut (result, zero, MSB16);
9393 aopPut (result, zero, MSB24);
9397 /* more than two bytes */
9398 else if (shCount >= 16)
9400 /* lower order two bytes goes to higher order two bytes */
9402 /* if some more remaining */
9404 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
9407 movLeft2Result (left, MSB16, result, MSB32, 0);
9408 movLeft2Result (left, LSB, result, MSB24, 0);
9410 aopPut (result, zero, MSB16);
9411 aopPut (result, zero, LSB);
9415 /* if more than 1 byte */
9416 else if (shCount >= 8)
9418 /* lower order three bytes goes to higher order three bytes */
9423 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
9425 movLeft2Result (left, LSB, result, MSB16, 0);
9431 movLeft2Result (left, MSB24, result, MSB32, 0);
9432 movLeft2Result (left, MSB16, result, MSB24, 0);
9433 movLeft2Result (left, LSB, result, MSB16, 0);
9434 aopPut (result, zero, LSB);
9436 else if (shCount == 1)
9437 shiftLLong (left, result, MSB16);
9440 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
9441 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
9442 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
9443 aopPut (result, zero, LSB);
9448 /* 1 <= shCount <= 7 */
9449 else if (shCount <= 2)
9451 shiftLLong (left, result, LSB);
9453 shiftLLong (result, result, LSB);
9455 /* 3 <= shCount <= 7, optimize */
9458 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
9459 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
9460 shiftL2Left2Result (left, LSB, result, LSB, shCount);
9465 #ifdef BETTER_LITERAL_SHIFT
9466 /*-----------------------------------------------------------------*/
9467 /* genLeftShiftLiteral - left shifting by known count */
9468 /*-----------------------------------------------------------------*/
9470 genLeftShiftLiteral (operand * left,
9475 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9478 size = getSize (operandType (result));
9480 D (emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
9482 /* We only handle certain easy cases so far. */
9484 && (shCount < (size * 8))
9488 D(emitcode (";", "genLeftShiftLiteral wimping out"););
9492 freeAsmop (right, NULL, ic, TRUE);
9494 aopOp(left, ic, FALSE, FALSE);
9495 aopOp(result, ic, FALSE, AOP_USESDPTR(left));
9498 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
9500 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
9501 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
9503 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
9506 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
9508 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
9509 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
9511 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
9517 emitcode ("; shift left ", "result %d, left %d", size,
9521 /* I suppose that the left size >= result size */
9524 _startLazyDPSEvaluation();
9527 movLeft2Result (left, size, result, size, 0);
9529 _endLazyDPSEvaluation();
9531 else if (shCount >= (size * 8))
9533 _startLazyDPSEvaluation();
9536 aopPut (result, zero, size);
9538 _endLazyDPSEvaluation();
9545 genlshOne (result, left, shCount);
9549 genlshTwo (result, left, shCount);
9553 genlshFour (result, left, shCount);
9557 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9558 "*** ack! mystery literal shift!\n");
9562 freeAsmop (result, NULL, ic, TRUE);
9563 freeAsmop (left, NULL, ic, TRUE);
9568 /*-----------------------------------------------------------------*/
9569 /* genLeftShift - generates code for left shifting */
9570 /*-----------------------------------------------------------------*/
9572 genLeftShift (iCode * ic)
9574 operand *left, *right, *result;
9577 symbol *tlbl, *tlbl1;
9580 D (emitcode (";", "genLeftShift"));
9582 right = IC_RIGHT (ic);
9583 left = IC_LEFT (ic);
9584 result = IC_RESULT (ic);
9586 aopOp (right, ic, FALSE, FALSE);
9589 #ifdef BETTER_LITERAL_SHIFT
9590 /* if the shift count is known then do it
9591 as efficiently as possible */
9592 if (AOP_TYPE (right) == AOP_LIT)
9594 if (genLeftShiftLiteral (left, right, result, ic))
9601 /* shift count is unknown then we have to form
9602 a loop get the loop count in B : Note: we take
9603 only the lower order byte since shifting
9604 more that 32 bits make no sense anyway, ( the
9605 largest size of an object can be only 32 bits ) */
9608 if (AOP_TYPE (right) == AOP_LIT)
9610 /* Really should be handled by genLeftShiftLiteral,
9611 * but since I'm too lazy to fix that today, at least we can make
9612 * some small improvement.
9614 emitcode("mov", "b,#!constbyte",
9615 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9619 MOVB (aopGet (right, 0, FALSE, FALSE, "b"));
9620 emitcode ("inc", "b");
9622 freeAsmop (right, NULL, ic, TRUE);
9623 aopOp (left, ic, FALSE, FALSE);
9624 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9626 /* now move the left to the result if they are not the same */
9627 if (!sameRegs (AOP (left), AOP (result)) &&
9628 AOP_SIZE (result) > 1)
9631 size = AOP_SIZE (result);
9633 _startLazyDPSEvaluation ();
9636 l = aopGet (left, offset, FALSE, TRUE, NULL);
9637 if (*l == '@' && (IS_AOP_PREG (result)))
9640 emitcode ("mov", "a,%s", l);
9641 aopPut (result, "a", offset);
9644 aopPut (result, l, offset);
9647 _endLazyDPSEvaluation ();
9650 tlbl = newiTempLabel (NULL);
9651 size = AOP_SIZE (result);
9653 tlbl1 = newiTempLabel (NULL);
9655 /* if it is only one byte then */
9658 symbol *tlbl1 = newiTempLabel (NULL);
9660 l = aopGet (left, 0, FALSE, FALSE, NULL);
9662 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9664 emitcode ("add", "a,acc");
9666 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9668 aopPut (result, "a", 0);
9672 reAdjustPreg (AOP (result));
9674 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9676 l = aopGet (result, offset, FALSE, FALSE, NULL);
9678 emitcode ("add", "a,acc");
9679 aopPut (result, "a", offset++);
9680 _startLazyDPSEvaluation ();
9683 l = aopGet (result, offset, FALSE, FALSE, NULL);
9685 emitcode ("rlc", "a");
9686 aopPut (result, "a", offset++);
9688 _endLazyDPSEvaluation ();
9689 reAdjustPreg (AOP (result));
9692 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9695 freeAsmop (result, NULL, ic, TRUE);
9696 freeAsmop (left, NULL, ic, TRUE);
9699 #ifdef BETTER_LITERAL_SHIFT
9700 /*-----------------------------------------------------------------*/
9701 /* genrshOne - right shift a one byte quantity by known count */
9702 /*-----------------------------------------------------------------*/
9704 genrshOne (operand * result, operand * left,
9705 int shCount, int sign)
9707 D (emitcode (";", "genrshOne"));
9709 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9713 #ifdef BETTER_LITERAL_SHIFT
9714 /*-----------------------------------------------------------------*/
9715 /* genrshTwo - right shift two bytes by known amount != 0 */
9716 /*-----------------------------------------------------------------*/
9718 genrshTwo (operand * result, operand * left,
9719 int shCount, int sign)
9721 D (emitcode (";", "genrshTwo"));
9723 /* if shCount >= 8 */
9727 _startLazyDPSEvaluation();
9729 shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
9731 movLeft2Result (left, MSB16, result, LSB, sign);
9732 addSign (result, MSB16, sign);
9733 _endLazyDPSEvaluation();
9736 /* 1 <= shCount <= 7 */
9738 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9742 /*-----------------------------------------------------------------*/
9743 /* shiftRLong - shift right one long from left to result */
9744 /* offl = LSB or MSB16 */
9745 /*-----------------------------------------------------------------*/
9747 shiftRLong (operand * left, int offl,
9748 operand * result, int sign)
9750 bool overlapping = regsInCommon (left, result) || operandsEqu(left, result);
9752 if (overlapping && offl>1)
9754 // we are in big trouble, but this shouldn't happen
9755 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9758 MOVA (aopGet (left, MSB32, FALSE, FALSE, NULL));
9765 emitcode ("rlc", "a");
9766 emitcode ("subb", "a,acc");
9767 emitcode ("xch", "a,%s",
9768 aopGet(left, MSB32, FALSE, FALSE, DP2_RESULT_REG));
9772 aopPut (result, zero, MSB32);
9778 emitcode ("clr", "c");
9782 emitcode ("mov", "c,acc.7");
9785 emitcode ("rrc", "a");
9787 if (overlapping && offl==MSB16)
9789 emitcode ("xch", "a,%s", aopGet (left, MSB24, FALSE, FALSE, DP2_RESULT_REG));
9793 aopPut (result, "a", MSB32 - offl);
9794 MOVA (aopGet (left, MSB24, FALSE, FALSE, NULL));
9797 emitcode ("rrc", "a");
9799 if (overlapping && offl==MSB16)
9801 emitcode ("xch", "a,%s", aopGet (left, MSB16, FALSE, FALSE, DP2_RESULT_REG));
9805 aopPut (result, "a", MSB24 - offl);
9806 MOVA (aopGet (left, MSB16, FALSE, FALSE, NULL));
9809 emitcode ("rrc", "a");
9812 aopPut (result, "a", MSB16 - offl);
9816 if (overlapping && offl==MSB16)
9818 emitcode ("xch", "a,%s", aopGet (left, LSB, FALSE, FALSE, DP2_RESULT_REG));
9822 aopPut (result, "a", MSB16 - offl);
9823 MOVA (aopGet (left, LSB, FALSE, FALSE, NULL));
9825 emitcode ("rrc", "a");
9826 aopPut (result, "a", LSB);
9830 /*-----------------------------------------------------------------*/
9831 /* genrshFour - shift four byte by a known amount != 0 */
9832 /*-----------------------------------------------------------------*/
9834 genrshFour (operand * result, operand * left,
9835 int shCount, int sign)
9837 D (emitcode (";", "genrshFour"));
9839 /* if shifting more that 3 bytes */
9843 _startLazyDPSEvaluation();
9845 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9847 movLeft2Result (left, MSB32, result, LSB, sign);
9848 addSign (result, MSB16, sign);
9849 _endLazyDPSEvaluation();
9851 else if (shCount >= 16)
9854 _startLazyDPSEvaluation();
9856 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9859 movLeft2Result (left, MSB24, result, LSB, 0);
9860 movLeft2Result (left, MSB32, result, MSB16, sign);
9862 addSign (result, MSB24, sign);
9863 _endLazyDPSEvaluation();
9865 else if (shCount >= 8)
9868 _startLazyDPSEvaluation();
9871 shiftRLong (left, MSB16, result, sign);
9873 else if (shCount == 0)
9875 movLeft2Result (left, MSB16, result, LSB, 0);
9876 movLeft2Result (left, MSB24, result, MSB16, 0);
9877 movLeft2Result (left, MSB32, result, MSB24, sign);
9878 addSign (result, MSB32, sign);
9882 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9883 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9884 /* the last shift is signed */
9885 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9886 addSign (result, MSB32, sign);
9888 _endLazyDPSEvaluation();
9892 /* 1 <= shCount <= 7 */
9895 shiftRLong (left, LSB, result, sign);
9897 shiftRLong (result, LSB, result, sign);
9901 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9902 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9903 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9908 #ifdef BETTER_LITERAL_SHIFT
9909 /*-----------------------------------------------------------------*/
9910 /* genRightShiftLiteral - right shifting by known count */
9911 /*-----------------------------------------------------------------*/
9913 genRightShiftLiteral (operand * left,
9919 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9922 size = getSize (operandType (result));
9924 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
9926 /* We only handle certain easy cases so far. */
9928 && (shCount < (size * 8))
9933 D(emitcode (";", "genRightShiftLiteral wimping out"););
9937 freeAsmop (right, NULL, ic, TRUE);
9939 aopOp (left, ic, FALSE, FALSE);
9940 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9943 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9947 /* test the LEFT size !!! */
9949 /* I suppose that the left size >= result size */
9952 size = getDataSize (result);
9953 _startLazyDPSEvaluation();
9955 movLeft2Result (left, size, result, size, 0);
9956 _endLazyDPSEvaluation();
9958 else if (shCount >= (size * 8))
9962 /* get sign in acc.7 */
9963 MOVA (aopGet (left, size - 1, FALSE, FALSE, NULL));
9965 addSign (result, LSB, sign);
9972 genrshOne (result, left, shCount, sign);
9976 genrshTwo (result, left, shCount, sign);
9980 genrshFour (result, left, shCount, sign);
9987 freeAsmop (result, NULL, ic, TRUE);
9988 freeAsmop (left, NULL, ic, TRUE);
9994 /*-----------------------------------------------------------------*/
9995 /* genSignedRightShift - right shift of signed number */
9996 /*-----------------------------------------------------------------*/
9998 genSignedRightShift (iCode * ic)
10000 operand *right, *left, *result;
10003 symbol *tlbl, *tlbl1;
10006 D (emitcode (";", "genSignedRightShift"));
10008 /* we do it the hard way put the shift count in b
10009 and loop thru preserving the sign */
10011 right = IC_RIGHT (ic);
10012 left = IC_LEFT (ic);
10013 result = IC_RESULT (ic);
10015 aopOp (right, ic, FALSE, FALSE);
10017 #ifdef BETTER_LITERAL_SHIFT
10018 if (AOP_TYPE (right) == AOP_LIT)
10020 if (genRightShiftLiteral (left, right, result, ic, 1))
10026 /* shift count is unknown then we have to form
10027 a loop get the loop count in B : Note: we take
10028 only the lower order byte since shifting
10029 more that 32 bits make no sense anyway, ( the
10030 largest size of an object can be only 32 bits ) */
10032 pushedB = pushB ();
10033 if (AOP_TYPE (right) == AOP_LIT)
10035 /* Really should be handled by genRightShiftLiteral,
10036 * but since I'm too lazy to fix that today, at least we can make
10037 * some small improvement.
10039 emitcode("mov", "b,#!constbyte",
10040 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
10044 MOVB (aopGet (right, 0, FALSE, FALSE, "b"));
10045 emitcode ("inc", "b");
10047 freeAsmop (right, NULL, ic, TRUE);
10048 aopOp (left, ic, FALSE, FALSE);
10049 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
10051 /* now move the left to the result if they are not the
10053 if (!sameRegs (AOP (left), AOP (result)) &&
10054 AOP_SIZE (result) > 1)
10057 size = AOP_SIZE (result);
10059 _startLazyDPSEvaluation ();
10062 l = aopGet (left, offset, FALSE, TRUE, NULL);
10063 if (*l == '@' && IS_AOP_PREG (result))
10066 emitcode ("mov", "a,%s", l);
10067 aopPut (result, "a", offset);
10070 aopPut (result, l, offset);
10073 _endLazyDPSEvaluation ();
10076 /* mov the highest order bit to OVR */
10077 tlbl = newiTempLabel (NULL);
10078 tlbl1 = newiTempLabel (NULL);
10080 size = AOP_SIZE (result);
10082 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
10083 emitcode ("rlc", "a");
10084 emitcode ("mov", "ov,c");
10085 /* if it is only one byte then */
10088 l = aopGet (left, 0, FALSE, FALSE, NULL);
10090 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
10092 emitcode ("mov", "c,ov");
10093 emitcode ("rrc", "a");
10095 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
10097 aopPut (result, "a", 0);
10101 reAdjustPreg (AOP (result));
10102 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
10104 emitcode ("mov", "c,ov");
10105 _startLazyDPSEvaluation ();
10108 l = aopGet (result, offset, FALSE, FALSE, NULL);
10110 emitcode ("rrc", "a");
10111 aopPut (result, "a", offset--);
10113 _endLazyDPSEvaluation ();
10114 reAdjustPreg (AOP (result));
10116 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
10120 freeAsmop (result, NULL, ic, TRUE);
10121 freeAsmop (left, NULL, ic, TRUE);
10124 /*-----------------------------------------------------------------*/
10125 /* genRightShift - generate code for right shifting */
10126 /*-----------------------------------------------------------------*/
10128 genRightShift (iCode * ic)
10130 operand *right, *left, *result;
10134 symbol *tlbl, *tlbl1;
10137 D (emitcode (";", "genRightShift"));
10139 /* if signed then we do it the hard way preserve the
10140 sign bit moving it inwards */
10141 letype = getSpec (operandType (IC_LEFT (ic)));
10143 if (!SPEC_USIGN (letype))
10145 genSignedRightShift (ic);
10149 /* signed & unsigned types are treated the same : i.e. the
10150 signed is NOT propagated inwards : quoting from the
10151 ANSI - standard : "for E1 >> E2, is equivalent to division
10152 by 2**E2 if unsigned or if it has a non-negative value,
10153 otherwise the result is implementation defined ", MY definition
10154 is that the sign does not get propagated */
10156 right = IC_RIGHT (ic);
10157 left = IC_LEFT (ic);
10158 result = IC_RESULT (ic);
10160 aopOp (right, ic, FALSE, FALSE);
10162 #ifdef BETTER_LITERAL_SHIFT
10163 /* if the shift count is known then do it
10164 as efficiently as possible */
10165 if (AOP_TYPE (right) == AOP_LIT)
10167 if (genRightShiftLiteral (left, right, result, ic, 0))
10174 /* shift count is unknown then we have to form
10175 a loop get the loop count in B : Note: we take
10176 only the lower order byte since shifting
10177 more that 32 bits make no sense anyway, ( the
10178 largest size of an object can be only 32 bits ) */
10180 pushedB = pushB ();
10181 if (AOP_TYPE (right) == AOP_LIT)
10183 /* Really should be handled by genRightShiftLiteral,
10184 * but since I'm too lazy to fix that today, at least we can make
10185 * some small improvement.
10187 emitcode("mov", "b,#!constbyte",
10188 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
10192 MOVB (aopGet (right, 0, FALSE, FALSE, "b"));
10193 emitcode ("inc", "b");
10195 freeAsmop (right, NULL, ic, TRUE);
10196 aopOp (left, ic, FALSE, FALSE);
10197 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
10199 /* now move the left to the result if they are not the
10201 if (!sameRegs (AOP (left), AOP (result)) &&
10202 AOP_SIZE (result) > 1)
10204 size = AOP_SIZE (result);
10206 _startLazyDPSEvaluation ();
10209 l = aopGet (left, offset, FALSE, TRUE, NULL);
10210 if (*l == '@' && IS_AOP_PREG (result))
10213 emitcode ("mov", "a,%s", l);
10214 aopPut (result, "a", offset);
10217 aopPut (result, l, offset);
10220 _endLazyDPSEvaluation ();
10223 tlbl = newiTempLabel (NULL);
10224 tlbl1 = newiTempLabel (NULL);
10225 size = AOP_SIZE (result);
10228 /* if it is only one byte then */
10231 l = aopGet (left, 0, FALSE, FALSE, NULL);
10233 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
10236 emitcode ("rrc", "a");
10238 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
10240 aopPut (result, "a", 0);
10244 reAdjustPreg (AOP (result));
10245 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
10248 _startLazyDPSEvaluation ();
10251 l = aopGet (result, offset, FALSE, FALSE, NULL);
10253 emitcode ("rrc", "a");
10254 aopPut (result, "a", offset--);
10256 _endLazyDPSEvaluation ();
10257 reAdjustPreg (AOP (result));
10260 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
10264 freeAsmop (result, NULL, ic, TRUE);
10265 freeAsmop (left, NULL, ic, TRUE);
10268 /*-----------------------------------------------------------------*/
10269 /* emitPtrByteGet - emits code to get a byte into A through a */
10270 /* pointer register (R0, R1, or DPTR). The */
10271 /* original value of A can be preserved in B. */
10272 /*-----------------------------------------------------------------*/
10274 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
10281 emitcode ("mov", "b,a");
10282 emitcode ("mov", "a,@%s", rname);
10287 emitcode ("mov", "b,a");
10288 emitcode ("movx", "a,@%s", rname);
10293 emitcode ("mov", "b,a");
10294 emitcode ("movx", "a,@dptr");
10299 emitcode ("mov", "b,a");
10300 emitcode ("clr", "a");
10301 emitcode ("movc", "a,@a+dptr");
10307 emitcode ("push", "b");
10308 emitcode ("push", "acc");
10310 emitcode ("lcall", "__gptrget");
10312 emitcode ("pop", "b");
10317 /*-----------------------------------------------------------------*/
10318 /* emitPtrByteSet - emits code to set a byte from src through a */
10319 /* pointer register (R0, R1, or DPTR). */
10320 /*-----------------------------------------------------------------*/
10322 emitPtrByteSet (char *rname, int p_type, char *src)
10331 emitcode ("mov", "@%s,a", rname);
10334 emitcode ("mov", "@%s,%s", rname, src);
10339 emitcode ("movx", "@%s,a", rname);
10344 emitcode ("movx", "@dptr,a");
10349 emitcode ("lcall", "__gptrput");
10354 /*-----------------------------------------------------------------*/
10355 /* genUnpackBits - generates code for unpacking bits */
10356 /*-----------------------------------------------------------------*/
10358 genUnpackBits (operand * result, char *rname, int ptype)
10360 int offset = 0; /* result byte offset */
10361 int rsize; /* result size */
10362 int rlen = 0; /* remaining bitfield length */
10363 sym_link *etype; /* bitfield type information */
10364 int blen; /* bitfield length */
10365 int bstr; /* bitfield starting bit within byte */
10367 D(emitcode (";", "genUnpackBits"));
10369 etype = getSpec (operandType (result));
10370 rsize = getSize (operandType (result));
10371 blen = SPEC_BLEN (etype);
10372 bstr = SPEC_BSTR (etype);
10374 /* If the bitfield length is less than a byte */
10377 emitPtrByteGet (rname, ptype, FALSE);
10379 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
10380 if (!SPEC_USIGN (etype))
10382 /* signed bitfield */
10383 symbol *tlbl = newiTempLabel (NULL);
10385 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
10386 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
10389 aopPut (result, "a", offset++);
10393 /* Bit field did not fit in a byte. Copy all
10394 but the partial byte at the end. */
10395 for (rlen=blen;rlen>=8;rlen-=8)
10397 emitPtrByteGet (rname, ptype, FALSE);
10398 aopPut (result, "a", offset++);
10400 emitcode ("inc", "%s", rname);
10403 /* Handle the partial byte at the end */
10406 emitPtrByteGet (rname, ptype, FALSE);
10407 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
10408 if (!SPEC_USIGN (etype))
10410 /* signed bitfield */
10411 symbol *tlbl = newiTempLabel (NULL);
10413 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
10414 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
10417 aopPut (result, "a", offset++);
10421 if (offset < rsize)
10425 if (SPEC_USIGN (etype))
10429 /* signed bitfield: sign extension with 0x00 or 0xff */
10430 emitcode ("rlc", "a");
10431 emitcode ("subb", "a,acc");
10437 aopPut (result, source, offset++);
10442 /*-----------------------------------------------------------------*/
10443 /* genDataPointerGet - generates code when ptr offset is known */
10444 /*-----------------------------------------------------------------*/
10446 genDataPointerGet (operand * left,
10452 int size, offset = 0;
10453 aopOp (result, ic, TRUE, FALSE);
10455 /* get the string representation of the name */
10456 l = aopGet (left, 0, FALSE, TRUE, NULL);
10457 size = AOP_SIZE (result);
10458 _startLazyDPSEvaluation ();
10463 SNPRINTF (buffer, sizeof(buffer),
10464 "(%s + %d)", l + 1, offset);
10468 SNPRINTF (buffer, sizeof(buffer),
10471 aopPut (result, buffer, offset++);
10473 _endLazyDPSEvaluation ();
10475 freeAsmop (result, NULL, ic, TRUE);
10476 freeAsmop (left, NULL, ic, TRUE);
10479 /*-----------------------------------------------------------------*/
10480 /* genNearPointerGet - emitcode for near pointer fetch */
10481 /*-----------------------------------------------------------------*/
10483 genNearPointerGet (operand * left,
10491 sym_link *rtype, *retype, *letype;
10492 sym_link *ltype = operandType (left);
10495 rtype = operandType (result);
10496 retype = getSpec (rtype);
10497 letype = getSpec (ltype);
10499 aopOp (left, ic, FALSE, FALSE);
10501 /* if left is rematerialisable and
10502 result is not bitfield variable type and
10503 the left is pointer to data space i.e
10504 lower 128 bytes of space */
10505 if (AOP_TYPE (left) == AOP_IMMD &&
10506 !IS_BITFIELD (retype) &&
10507 !IS_BITFIELD (letype) &&
10508 DCL_TYPE (ltype) == POINTER)
10510 genDataPointerGet (left, result, ic);
10514 /* if the value is already in a pointer register
10515 then don't need anything more */
10516 if (!AOP_INPREG (AOP (left)))
10518 /* otherwise get a free pointer register */
10519 aop = newAsmop (0);
10520 preg = getFreePtr (ic, &aop, FALSE);
10521 emitcode ("mov", "%s,%s",
10523 aopGet (left, 0, FALSE, TRUE, DP2_RESULT_REG));
10524 rname = preg->name;
10527 rname = aopGet (left, 0, FALSE, FALSE, DP2_RESULT_REG);
10529 freeAsmop (left, NULL, ic, TRUE);
10530 aopOp (result, ic, FALSE, FALSE);
10532 /* if bitfield then unpack the bits */
10533 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10534 genUnpackBits (result, rname, POINTER);
10537 /* we have can just get the values */
10538 int size = AOP_SIZE (result);
10543 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
10546 emitcode ("mov", "a,@%s", rname);
10547 aopPut (result, "a", offset);
10551 SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
10552 aopPut (result, buffer, offset);
10556 emitcode ("inc", "%s", rname);
10560 /* now some housekeeping stuff */
10561 if (aop) /* we had to allocate for this iCode */
10563 if (pi) { /* post increment present */
10564 aopPut (left, rname, 0);
10566 freeAsmop (NULL, aop, ic, TRUE);
10570 /* we did not allocate which means left
10571 already in a pointer register, then
10572 if size > 0 && this could be used again
10573 we have to point it back to where it
10575 if (AOP_SIZE (result) > 1 &&
10576 !OP_SYMBOL (left)->remat &&
10577 (OP_SYMBOL (left)->liveTo > ic->seq ||
10581 int size = AOP_SIZE (result) - 1;
10583 emitcode ("dec", "%s", rname);
10588 freeAsmop (result, NULL, ic, TRUE);
10589 if (pi) pi->generated = 1;
10592 /*-----------------------------------------------------------------*/
10593 /* genPagedPointerGet - emitcode for paged pointer fetch */
10594 /*-----------------------------------------------------------------*/
10596 genPagedPointerGet (operand * left,
10604 sym_link *rtype, *retype, *letype;
10606 rtype = operandType (result);
10607 retype = getSpec (rtype);
10608 letype = getSpec (operandType (left));
10609 aopOp (left, ic, FALSE, FALSE);
10611 /* if the value is already in a pointer register
10612 then don't need anything more */
10613 if (!AOP_INPREG (AOP (left)))
10615 /* otherwise get a free pointer register */
10616 aop = newAsmop (0);
10617 preg = getFreePtr (ic, &aop, FALSE);
10618 emitcode ("mov", "%s,%s",
10620 aopGet (left, 0, FALSE, TRUE, NULL));
10621 rname = preg->name;
10624 rname = aopGet (left, 0, FALSE, FALSE, NULL);
10626 freeAsmop (left, NULL, ic, TRUE);
10627 aopOp (result, ic, FALSE, FALSE);
10629 /* if bitfield then unpack the bits */
10630 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10631 genUnpackBits (result, rname, PPOINTER);
10634 /* we have can just get the values */
10635 int size = AOP_SIZE (result);
10641 emitcode ("movx", "a,@%s", rname);
10642 aopPut (result, "a", offset);
10647 emitcode ("inc", "%s", rname);
10651 /* now some housekeeping stuff */
10652 if (aop) /* we had to allocate for this iCode */
10655 aopPut (left, rname, 0);
10656 freeAsmop (NULL, aop, ic, TRUE);
10660 /* we did not allocate which means left
10661 already in a pointer register, then
10662 if size > 0 && this could be used again
10663 we have to point it back to where it
10665 if (AOP_SIZE (result) > 1 &&
10666 !OP_SYMBOL (left)->remat &&
10667 (OP_SYMBOL (left)->liveTo > ic->seq ||
10671 int size = AOP_SIZE (result) - 1;
10673 emitcode ("dec", "%s", rname);
10678 freeAsmop (result, NULL, ic, TRUE);
10679 if (pi) pi->generated = 1;
10682 /*-----------------------------------------------------------------*/
10683 /* genFarPointerGet - get value from far space */
10684 /*-----------------------------------------------------------------*/
10686 genFarPointerGet (operand * left,
10687 operand * result, iCode * ic, iCode *pi)
10689 int size, offset, dopi=1;
10690 sym_link *retype = getSpec (operandType (result));
10691 sym_link *letype = getSpec (operandType (left));
10692 D (emitcode (";", "genFarPointerGet"););
10694 aopOp (left, ic, FALSE, FALSE);
10696 /* if the operand is already in dptr
10697 then we do nothing else we move the value to dptr */
10698 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
10700 /* if this is rematerializable */
10701 if (AOP_TYPE (left) == AOP_IMMD)
10703 emitcode ("mov", "dptr,%s", aopGet (left, 0, TRUE, FALSE, NULL));
10707 /* we need to get it byte by byte */
10708 _startLazyDPSEvaluation ();
10709 if (AOP_TYPE (left) != AOP_DPTR)
10711 emitcode ("mov", "dpl,%s", aopGet (left, 0, FALSE, FALSE, NULL));
10712 emitcode ("mov", "dph,%s", aopGet (left, 1, FALSE, FALSE, NULL));
10713 if (options.model == MODEL_FLAT24)
10714 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10718 /* We need to generate a load to DPTR indirect through DPTR. */
10719 D (emitcode (";", "genFarPointerGet -- indirection special case."););
10720 emitcode ("push", "%s", aopGet (left, 0, FALSE, TRUE, NULL));
10721 emitcode ("push", "%s", aopGet (left, 1, FALSE, TRUE, NULL));
10722 if (options.model == MODEL_FLAT24)
10723 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10724 emitcode ("pop", "dph");
10725 emitcode ("pop", "dpl");
10728 _endLazyDPSEvaluation ();
10731 /* so dptr now contains the address */
10732 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10734 /* if bit then unpack */
10735 if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
10736 if (AOP_INDPTRn(left)) {
10737 genSetDPTR(AOP(left)->aopu.dptr);
10739 genUnpackBits (result, "dptr", FPOINTER);
10740 if (AOP_INDPTRn(left)) {
10745 size = AOP_SIZE (result);
10748 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10750 genSetDPTR(AOP(left)->aopu.dptr);
10751 emitcode ("movx", "a,@dptr");
10752 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10753 emitcode ("inc", "dptr");
10755 aopPut (result, "a", offset++);
10758 _startLazyDPSEvaluation ();
10760 if (AOP_INDPTRn(left)) {
10761 genSetDPTR(AOP(left)->aopu.dptr);
10767 emitcode ("movx", "a,@dptr");
10768 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10769 emitcode ("inc", "dptr");
10771 aopPut (result, "a", offset++);
10773 _endLazyDPSEvaluation ();
10776 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10777 if (!AOP_INDPTRn(left)) {
10778 _startLazyDPSEvaluation ();
10779 aopPut (left, "dpl", 0);
10780 aopPut (left, "dph", 1);
10781 if (options.model == MODEL_FLAT24)
10782 aopPut (left, "dpx", 2);
10783 _endLazyDPSEvaluation ();
10786 } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) &&
10787 AOP_SIZE(result) > 1 &&
10789 (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
10791 size = AOP_SIZE (result) - 1;
10792 if (AOP_INDPTRn(left)) {
10793 genSetDPTR(AOP(left)->aopu.dptr);
10795 while (size--) emitcode ("lcall","__decdptr");
10796 if (AOP_INDPTRn(left)) {
10801 freeAsmop (result, NULL, ic, TRUE);
10802 freeAsmop (left, NULL, ic, TRUE);
10805 /*-----------------------------------------------------------------*/
10806 /* genCodePointerGet - get value from code space */
10807 /*-----------------------------------------------------------------*/
10809 genCodePointerGet (operand * left,
10810 operand * result, iCode * ic, iCode *pi)
10812 int size, offset, dopi=1;
10813 sym_link *retype = getSpec (operandType (result));
10815 aopOp (left, ic, FALSE, FALSE);
10817 /* if the operand is already in dptr
10818 then we do nothing else we move the value to dptr */
10819 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
10821 /* if this is rematerializable */
10822 if (AOP_TYPE (left) == AOP_IMMD)
10824 emitcode ("mov", "dptr,%s", aopGet (left, 0, TRUE, FALSE, NULL));
10827 { /* we need to get it byte by byte */
10828 _startLazyDPSEvaluation ();
10829 if (AOP_TYPE (left) != AOP_DPTR)
10831 emitcode ("mov", "dpl,%s", aopGet (left, 0, FALSE, FALSE, NULL));
10832 emitcode ("mov", "dph,%s", aopGet (left, 1, FALSE, FALSE, NULL));
10833 if (options.model == MODEL_FLAT24)
10834 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10838 /* We need to generate a load to DPTR indirect through DPTR. */
10839 D (emitcode (";", "gencodePointerGet -- indirection special case."););
10840 emitcode ("push", "%s", aopGet (left, 0, FALSE, TRUE, NULL));
10841 emitcode ("push", "%s", aopGet (left, 1, FALSE, TRUE, NULL));
10842 if (options.model == MODEL_FLAT24)
10843 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10844 emitcode ("pop", "dph");
10845 emitcode ("pop", "dpl");
10848 _endLazyDPSEvaluation ();
10851 /* so dptr now contains the address */
10852 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10854 /* if bit then unpack */
10855 if (IS_BITFIELD (retype)) {
10856 if (AOP_INDPTRn(left)) {
10857 genSetDPTR(AOP(left)->aopu.dptr);
10859 genUnpackBits (result, "dptr", CPOINTER);
10860 if (AOP_INDPTRn(left)) {
10865 size = AOP_SIZE (result);
10867 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10869 genSetDPTR(AOP(left)->aopu.dptr);
10870 emitcode ("clr", "a");
10871 emitcode ("movc", "a,@a+dptr");
10872 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10873 emitcode ("inc", "dptr");
10875 aopPut (result, "a", offset++);
10878 _startLazyDPSEvaluation ();
10881 if (AOP_INDPTRn(left)) {
10882 genSetDPTR(AOP(left)->aopu.dptr);
10888 emitcode ("clr", "a");
10889 emitcode ("movc", "a,@a+dptr");
10890 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10891 emitcode ("inc", "dptr");
10892 aopPut (result, "a", offset++);
10894 _endLazyDPSEvaluation ();
10897 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10898 if (!AOP_INDPTRn(left)) {
10899 _startLazyDPSEvaluation ();
10901 aopPut (left, "dpl", 0);
10902 aopPut (left, "dph", 1);
10903 if (options.model == MODEL_FLAT24)
10904 aopPut (left, "dpx", 2);
10906 _endLazyDPSEvaluation ();
10909 } else if (IS_SYMOP(left) &&
10910 (OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
10911 AOP_SIZE(result) > 1 &&
10912 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10914 size = AOP_SIZE (result) - 1;
10915 if (AOP_INDPTRn(left)) {
10916 genSetDPTR(AOP(left)->aopu.dptr);
10918 while (size--) emitcode ("lcall","__decdptr");
10919 if (AOP_INDPTRn(left)) {
10924 freeAsmop (result, NULL, ic, TRUE);
10925 freeAsmop (left, NULL, ic, TRUE);
10928 /*-----------------------------------------------------------------*/
10929 /* genGenPointerGet - get value from generic pointer space */
10930 /*-----------------------------------------------------------------*/
10932 genGenPointerGet (operand * left,
10933 operand * result, iCode * ic, iCode * pi)
10937 sym_link *retype = getSpec (operandType (result));
10938 sym_link *letype = getSpec (operandType (left));
10940 D (emitcode (";", "genGenPointerGet"));
10942 aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
10944 pushedB = pushB ();
10945 /* if the operand is already in dptr
10946 then we do nothing else we move the value to dptr */
10947 if (AOP_TYPE (left) != AOP_STR)
10949 /* if this is rematerializable */
10950 if (AOP_TYPE (left) == AOP_IMMD)
10952 emitcode ("mov", "dptr,%s", aopGet (left, 0, TRUE, FALSE, NULL));
10953 if (AOP(left)->aopu.aop_immd.from_cast_remat)
10955 MOVB (aopGet (left, AOP_SIZE(left)-1, FALSE, FALSE, NULL));
10959 emitcode ("mov", "b,#%d", pointerCode (retype));
10963 { /* we need to get it byte by byte */
10964 _startLazyDPSEvaluation ();
10965 emitcode ("mov", "dpl,%s", aopGet (left,0,FALSE,FALSE,NULL));
10966 emitcode ("mov", "dph,%s", aopGet (left,1,FALSE,FALSE,NULL));
10967 if (options.model == MODEL_FLAT24) {
10968 emitcode ("mov", "dpx,%s", aopGet (left,2,FALSE,FALSE,NULL));
10969 emitcode ("mov", "b,%s", aopGet (left,3,FALSE,FALSE,NULL));
10971 emitcode ("mov", "b,%s", aopGet (left,2,FALSE,FALSE,NULL));
10973 _endLazyDPSEvaluation ();
10977 /* so dptr-b now contains the address */
10978 aopOp (result, ic, FALSE, TRUE);
10980 /* if bit then unpack */
10981 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10983 genUnpackBits (result, "dptr", GPOINTER);
10987 size = AOP_SIZE (result);
10994 // Get two bytes at a time, results in _AP & A.
10995 // dptr will be incremented ONCE by __gptrgetWord.
10997 // Note: any change here must be coordinated
10998 // with the implementation of __gptrgetWord
10999 // in device/lib/_gptrget.c
11000 emitcode ("lcall", "__gptrgetWord");
11001 aopPut (result, "a", offset++);
11002 aopPut (result, DP2_RESULT_REG, offset++);
11007 // Only one byte to get.
11008 emitcode ("lcall", "__gptrget");
11009 aopPut (result, "a", offset++);
11012 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
11014 emitcode ("inc", "dptr");
11019 if (pi && AOP_TYPE (left) != AOP_IMMD) {
11020 _startLazyDPSEvaluation ();
11022 aopPut (left, "dpl", 0);
11023 aopPut (left, "dph", 1);
11024 if (options.model == MODEL_FLAT24) {
11025 aopPut (left, "dpx", 2);
11026 aopPut (left, "b", 3);
11027 } else aopPut (left, "b", 2);
11029 _endLazyDPSEvaluation ();
11032 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
11033 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
11035 size = AOP_SIZE (result) - 1;
11036 while (size--) emitcode ("lcall","__decdptr");
11040 freeAsmop (result, NULL, ic, TRUE);
11041 freeAsmop (left, NULL, ic, TRUE);
11044 /*-----------------------------------------------------------------*/
11045 /* genPointerGet - generate code for pointer get */
11046 /*-----------------------------------------------------------------*/
11048 genPointerGet (iCode * ic, iCode *pi)
11050 operand *left, *result;
11051 sym_link *type, *etype;
11054 D (emitcode (";", "genPointerGet"));
11056 left = IC_LEFT (ic);
11057 result = IC_RESULT (ic);
11059 /* depending on the type of pointer we need to
11060 move it to the correct pointer register */
11061 type = operandType (left);
11062 etype = getSpec (type);
11063 /* if left is of type of pointer then it is simple */
11064 if (IS_PTR (type) && !IS_FUNC (type->next))
11065 p_type = DCL_TYPE (type);
11068 /* we have to go by the storage class */
11069 p_type = PTR_TYPE (SPEC_OCLS (etype));
11072 /* special case when cast remat */
11073 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
11074 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
11076 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
11077 type = operandType (left);
11078 p_type = DCL_TYPE (type);
11080 /* now that we have the pointer type we assign
11081 the pointer values */
11087 genNearPointerGet (left, result, ic, pi);
11091 genPagedPointerGet (left, result, ic, pi);
11095 genFarPointerGet (left, result, ic, pi);
11099 genCodePointerGet (left, result, ic, pi);
11103 genGenPointerGet (left, result, ic, pi);
11109 /*-----------------------------------------------------------------*/
11110 /* genPackBits - generates code for packed bit storage */
11111 /*-----------------------------------------------------------------*/
11113 genPackBits (sym_link * etype,
11115 char *rname, int p_type)
11117 int offset = 0; /* source byte offset */
11118 int rlen = 0; /* remaining bitfield length */
11119 int blen; /* bitfield length */
11120 int bstr; /* bitfield starting bit within byte */
11121 int litval; /* source literal value (if AOP_LIT) */
11122 unsigned char mask; /* bitmask within current byte */
11124 D(emitcode (";", "genPackBits"));
11126 blen = SPEC_BLEN (etype);
11127 bstr = SPEC_BSTR (etype);
11129 /* If the bitfield length is less than a byte */
11132 mask = ((unsigned char) (0xFF << (blen + bstr)) |
11133 (unsigned char) (0xFF >> (8 - bstr)));
11135 if (AOP_TYPE (right) == AOP_LIT)
11137 /* Case with a bitfield length <8 and literal source
11139 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
11141 litval &= (~mask) & 0xff;
11142 emitPtrByteGet (rname, p_type, FALSE);
11143 if ((mask|litval)!=0xff)
11144 emitcode ("anl","a,#!constbyte", mask);
11146 emitcode ("orl","a,#!constbyte", litval);
11150 if ((blen==1) && (p_type!=GPOINTER))
11152 /* Case with a bitfield length == 1 and no generic pointer
11154 if (AOP_TYPE (right) == AOP_CRY)
11155 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
11158 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
11159 emitcode ("rrc","a");
11161 emitPtrByteGet (rname, p_type, FALSE);
11162 emitcode ("mov","acc.%d,c",bstr);
11167 /* Case with a bitfield length < 8 and arbitrary source
11169 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
11170 /* shift and mask source value */
11172 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
11174 pushedB = pushB ();
11175 /* transfer A to B and get next byte */
11176 emitPtrByteGet (rname, p_type, TRUE);
11178 emitcode ("anl", "a,#!constbyte", mask);
11179 emitcode ("orl", "a,b");
11180 if (p_type == GPOINTER)
11181 emitcode ("pop", "b");
11187 emitPtrByteSet (rname, p_type, "a");
11191 /* Bit length is greater than 7 bits. In this case, copy */
11192 /* all except the partial byte at the end */
11193 for (rlen=blen;rlen>=8;rlen-=8)
11195 emitPtrByteSet (rname, p_type,
11196 aopGet (right, offset++, FALSE, TRUE, NULL) );
11198 emitcode ("inc", "%s", rname);
11201 /* If there was a partial byte at the end */
11204 mask = (((unsigned char) -1 << rlen) & 0xff);
11206 if (AOP_TYPE (right) == AOP_LIT)
11208 /* Case with partial byte and literal source
11210 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
11211 litval >>= (blen-rlen);
11212 litval &= (~mask) & 0xff;
11213 emitPtrByteGet (rname, p_type, FALSE);
11214 if ((mask|litval)!=0xff)
11215 emitcode ("anl","a,#!constbyte", mask);
11217 emitcode ("orl","a,#!constbyte", litval);
11222 /* Case with partial byte and arbitrary source
11224 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11225 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
11227 pushedB = pushB ();
11228 /* transfer A to B and get next byte */
11229 emitPtrByteGet (rname, p_type, TRUE);
11231 emitcode ("anl", "a,#!constbyte", mask);
11232 emitcode ("orl", "a,b");
11233 if (p_type == GPOINTER)
11234 emitcode ("pop", "b");
11238 emitPtrByteSet (rname, p_type, "a");
11243 /*-----------------------------------------------------------------*/
11244 /* genDataPointerSet - remat pointer to data space */
11245 /*-----------------------------------------------------------------*/
11247 genDataPointerSet (operand * right,
11251 int size, offset = 0;
11252 char *l, buffer[256];
11254 D (emitcode (";", "genDataPointerSet"));
11256 aopOp (right, ic, FALSE, FALSE);
11258 l = aopGet (result, 0, FALSE, TRUE, NULL);
11259 size = AOP_SIZE (right);
11263 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l + 1, offset);
11265 SNPRINTF (buffer, sizeof(buffer), "%s", l + 1);
11266 emitcode ("mov", "%s,%s", buffer,
11267 aopGet (right, offset++, FALSE, FALSE, NULL));
11270 freeAsmop (result, NULL, ic, TRUE);
11271 freeAsmop (right, NULL, ic, TRUE);
11274 /*-----------------------------------------------------------------*/
11275 /* genNearPointerSet - emitcode for near pointer put */
11276 /*-----------------------------------------------------------------*/
11278 genNearPointerSet (operand * right,
11285 sym_link *retype, *letype;
11286 sym_link *ptype = operandType (result);
11288 D (emitcode (";", "genNearPointerSet"));
11290 retype = getSpec (operandType (right));
11291 letype = getSpec (ptype);
11293 aopOp (result, ic, FALSE, FALSE);
11295 /* if the result is rematerializable &
11296 in data space & not a bit variable */
11297 if (AOP_TYPE (result) == AOP_IMMD &&
11298 DCL_TYPE (ptype) == POINTER &&
11299 !IS_BITVAR (retype) &&
11300 !IS_BITVAR (letype))
11302 genDataPointerSet (right, result, ic);
11306 /* if the value is already in a pointer register
11307 then don't need anything more */
11308 if (!AOP_INPREG (AOP (result)))
11310 /* otherwise get a free pointer register */
11313 aop = newAsmop (0);
11314 preg = getFreePtr (ic, &aop, FALSE);
11315 emitcode ("mov", "%s,%s",
11317 aopGet (result, 0, FALSE, TRUE, NULL));
11318 rname = preg->name;
11322 rname = aopGet (result, 0, FALSE, FALSE, NULL);
11325 aopOp (right, ic, FALSE, FALSE);
11327 /* if bitfield then unpack the bits */
11328 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11329 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
11332 /* we can just get the values */
11333 int size = AOP_SIZE (right);
11338 l = aopGet (right, offset, FALSE, TRUE, NULL);
11339 if ((*l == '@') || (strcmp (l, "acc") == 0))
11342 emitcode ("mov", "@%s,a", rname);
11345 emitcode ("mov", "@%s,%s", rname, l);
11347 emitcode ("inc", "%s", rname);
11352 /* now some housekeeping stuff */
11353 if (aop) /* we had to allocate for this iCode */
11356 aopPut (result, rname, 0);
11357 freeAsmop (NULL, aop, ic, TRUE);
11361 /* we did not allocate which means left
11362 already in a pointer register, then
11363 if size > 0 && this could be used again
11364 we have to point it back to where it
11366 if (AOP_SIZE (right) > 1 &&
11367 !OP_SYMBOL (result)->remat &&
11368 (OP_SYMBOL (result)->liveTo > ic->seq ||
11372 int size = AOP_SIZE (right) - 1;
11374 emitcode ("dec", "%s", rname);
11379 if (pi) pi->generated = 1;
11380 freeAsmop (result, NULL, ic, TRUE);
11381 freeAsmop (right, NULL, ic, TRUE);
11384 /*-----------------------------------------------------------------*/
11385 /* genPagedPointerSet - emitcode for Paged pointer put */
11386 /*-----------------------------------------------------------------*/
11388 genPagedPointerSet (operand * right,
11395 sym_link *retype, *letype;
11397 D (emitcode (";", "genPagedPointerSet"));
11399 retype = getSpec (operandType (right));
11400 letype = getSpec (operandType (result));
11402 aopOp (result, ic, FALSE, FALSE);
11404 /* if the value is already in a pointer register
11405 then don't need anything more */
11406 if (!AOP_INPREG (AOP (result)))
11408 /* otherwise get a free pointer register */
11411 aop = newAsmop (0);
11412 preg = getFreePtr (ic, &aop, FALSE);
11413 emitcode ("mov", "%s,%s",
11415 aopGet (result, 0, FALSE, TRUE, NULL));
11416 rname = preg->name;
11419 rname = aopGet (result, 0, FALSE, FALSE, NULL);
11421 aopOp (right, ic, FALSE, FALSE);
11423 /* if bitfield then unpack the bits */
11424 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11425 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
11428 /* we have can just get the values */
11429 int size = AOP_SIZE (right);
11434 l = aopGet (right, offset, FALSE, TRUE, NULL);
11436 emitcode ("movx", "@%s,a", rname);
11439 emitcode ("inc", "%s", rname);
11445 /* now some housekeeping stuff */
11449 aopPut (result, rname, 0);
11450 /* we had to allocate for this iCode */
11451 freeAsmop (NULL, aop, ic, TRUE);
11455 /* we did not allocate which means left
11456 already in a pointer register, then
11457 if size > 0 && this could be used again
11458 we have to point it back to where it
11460 if (AOP_SIZE (right) > 1 &&
11461 !OP_SYMBOL (result)->remat &&
11462 (OP_SYMBOL (result)->liveTo > ic->seq ||
11466 int size = AOP_SIZE (right) - 1;
11468 emitcode ("dec", "%s", rname);
11473 if (pi) pi->generated = 1;
11474 freeAsmop (result, NULL, ic, TRUE);
11475 freeAsmop (right, NULL, ic, TRUE);
11478 /*-----------------------------------------------------------------*/
11479 /* genFarPointerSet - set value from far space */
11480 /*-----------------------------------------------------------------*/
11482 genFarPointerSet (operand * right,
11483 operand * result, iCode * ic, iCode *pi)
11485 int size, offset, dopi=1;
11486 sym_link *retype = getSpec (operandType (right));
11487 sym_link *letype = getSpec (operandType (result));
11489 aopOp (result, ic, FALSE, FALSE);
11491 /* if the operand is already in dptr
11492 then we do nothing else we move the value to dptr */
11493 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
11495 /* if this is remateriazable */
11496 if (AOP_TYPE (result) == AOP_IMMD)
11497 emitcode ("mov", "dptr,%s",
11498 aopGet (result, 0, TRUE, FALSE, NULL));
11501 /* we need to get it byte by byte */
11502 _startLazyDPSEvaluation ();
11503 if (AOP_TYPE (result) != AOP_DPTR)
11505 emitcode ("mov", "dpl,%s", aopGet (result, 0, FALSE, FALSE, NULL));
11506 emitcode ("mov", "dph,%s", aopGet (result, 1, FALSE, FALSE, NULL));
11507 if (options.model == MODEL_FLAT24)
11508 emitcode ("mov", "dpx,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11512 /* We need to generate a load to DPTR indirect through DPTR. */
11513 D (emitcode (";", "genFarPointerSet -- indirection special case."););
11515 emitcode ("push", "%s", aopGet (result, 0, FALSE, TRUE, NULL));
11516 emitcode ("push", "%s", aopGet (result, 1, FALSE, TRUE, NULL));
11517 if (options.model == MODEL_FLAT24)
11518 emitcode ("mov", "dpx,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11519 emitcode ("pop", "dph");
11520 emitcode ("pop", "dpl");
11523 _endLazyDPSEvaluation ();
11526 /* so dptr now contains the address */
11527 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
11529 /* if bit then unpack */
11530 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11532 if (AOP_INDPTRn(result)) {
11533 genSetDPTR(AOP(result)->aopu.dptr);
11535 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
11536 if (AOP_INDPTRn(result)) {
11540 size = AOP_SIZE (right);
11542 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
11544 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11546 genSetDPTR(AOP(result)->aopu.dptr);
11547 emitcode ("movx", "@dptr,a");
11548 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
11549 emitcode ("inc", "dptr");
11553 _startLazyDPSEvaluation ();
11555 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11557 if (AOP_INDPTRn(result)) {
11558 genSetDPTR(AOP(result)->aopu.dptr);
11564 emitcode ("movx", "@dptr,a");
11565 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
11566 emitcode ("inc", "dptr");
11568 _endLazyDPSEvaluation ();
11572 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
11573 if (!AOP_INDPTRn(result)) {
11574 _startLazyDPSEvaluation ();
11576 aopPut (result,"dpl",0);
11577 aopPut (result,"dph",1);
11578 if (options.model == MODEL_FLAT24)
11579 aopPut (result,"dpx",2);
11581 _endLazyDPSEvaluation ();
11584 } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
11585 AOP_SIZE(right) > 1 &&
11586 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
11588 size = AOP_SIZE (right) - 1;
11589 if (AOP_INDPTRn(result)) {
11590 genSetDPTR(AOP(result)->aopu.dptr);
11592 while (size--) emitcode ("lcall","__decdptr");
11593 if (AOP_INDPTRn(result)) {
11597 freeAsmop (result, NULL, ic, TRUE);
11598 freeAsmop (right, NULL, ic, TRUE);
11601 /*-----------------------------------------------------------------*/
11602 /* genGenPointerSet - set value from generic pointer space */
11603 /*-----------------------------------------------------------------*/
11605 genGenPointerSet (operand * right,
11606 operand * result, iCode * ic, iCode *pi)
11610 sym_link *retype = getSpec (operandType (right));
11611 sym_link *letype = getSpec (operandType (result));
11613 aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
11615 pushedB = pushB ();
11616 /* if the operand is already in dptr
11617 then we do nothing else we move the value to dptr */
11618 if (AOP_TYPE (result) != AOP_STR)
11620 _startLazyDPSEvaluation ();
11621 /* if this is remateriazable */
11622 if (AOP_TYPE (result) == AOP_IMMD)
11624 emitcode ("mov", "dptr,%s", aopGet (result, 0, TRUE, FALSE, NULL));
11625 if (AOP(result)->aopu.aop_immd.from_cast_remat)
11627 MOVB (aopGet (result, AOP_SIZE(result)-1, FALSE, FALSE, NULL));
11632 "b,%s + 1", aopGet (result, 0, TRUE, FALSE, NULL));
11636 { /* we need to get it byte by byte */
11637 emitcode ("mov", "dpl,%s", aopGet (result, 0, FALSE, FALSE, NULL));
11638 emitcode ("mov", "dph,%s", aopGet (result, 1, FALSE, FALSE, NULL));
11639 if (options.model == MODEL_FLAT24) {
11640 emitcode ("mov", "dpx,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11641 emitcode ("mov", "b,%s", aopGet (result, 3, FALSE, FALSE, NULL));
11643 emitcode ("mov", "b,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11646 _endLazyDPSEvaluation ();
11648 /* so dptr + b now contains the address */
11649 aopOp (right, ic, FALSE, TRUE);
11651 /* if bit then unpack */
11652 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11654 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
11658 size = AOP_SIZE (right);
11661 _startLazyDPSEvaluation ();
11666 // Set two bytes at a time, passed in _AP & A.
11667 // dptr will be incremented ONCE by __gptrputWord.
11669 // Note: any change here must be coordinated
11670 // with the implementation of __gptrputWord
11671 // in device/lib/_gptrput.c
11672 emitcode("mov", "_ap, %s",
11673 aopGet (right, offset++, FALSE, FALSE, NULL));
11674 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11678 emitcode ("lcall", "__gptrputWord");
11683 // Only one byte to put.
11684 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11688 emitcode ("lcall", "__gptrput");
11691 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
11693 emitcode ("inc", "dptr");
11696 _endLazyDPSEvaluation ();
11699 if (pi && AOP_TYPE (result) != AOP_IMMD) {
11700 _startLazyDPSEvaluation ();
11702 aopPut (result, "dpl",0);
11703 aopPut (result, "dph",1);
11704 if (options.model == MODEL_FLAT24) {
11705 aopPut (result, "dpx",2);
11706 aopPut (result, "b",3);
11708 aopPut (result, "b",2);
11710 _endLazyDPSEvaluation ();
11713 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
11714 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
11716 size = AOP_SIZE (right) - 1;
11717 while (size--) emitcode ("lcall","__decdptr");
11721 freeAsmop (result, NULL, ic, TRUE);
11722 freeAsmop (right, NULL, ic, TRUE);
11725 /*-----------------------------------------------------------------*/
11726 /* genPointerSet - stores the value into a pointer location */
11727 /*-----------------------------------------------------------------*/
11729 genPointerSet (iCode * ic, iCode *pi)
11731 operand *right, *result;
11732 sym_link *type, *etype;
11735 D (emitcode (";", "genPointerSet"));
11737 right = IC_RIGHT (ic);
11738 result = IC_RESULT (ic);
11740 /* depending on the type of pointer we need to
11741 move it to the correct pointer register */
11742 type = operandType (result);
11743 etype = getSpec (type);
11744 /* if left is of type of pointer then it is simple */
11745 if (IS_PTR (type) && !IS_FUNC (type->next))
11747 p_type = DCL_TYPE (type);
11751 /* we have to go by the storage class */
11752 p_type = PTR_TYPE (SPEC_OCLS (etype));
11755 /* special case when cast remat */
11756 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
11757 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
11758 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
11759 type = operandType (result);
11760 p_type = DCL_TYPE (type);
11763 /* now that we have the pointer type we assign
11764 the pointer values */
11770 genNearPointerSet (right, result, ic, pi);
11774 genPagedPointerSet (right, result, ic, pi);
11778 genFarPointerSet (right, result, ic, pi);
11782 genGenPointerSet (right, result, ic, pi);
11786 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11787 "genPointerSet: illegal pointer type");
11791 /*-----------------------------------------------------------------*/
11792 /* genIfx - generate code for Ifx statement */
11793 /*-----------------------------------------------------------------*/
11795 genIfx (iCode * ic, iCode * popIc)
11797 operand *cond = IC_COND (ic);
11801 D (emitcode (";", "genIfx"));
11803 aopOp (cond, ic, FALSE, FALSE);
11805 /* get the value into acc */
11806 if (AOP_TYPE (cond) != AOP_CRY)
11813 if (AOP(cond)->aopu.aop_dir)
11814 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
11817 /* the result is now in the accumulator or a directly addressable bit */
11818 freeAsmop (cond, NULL, ic, TRUE);
11820 /* if there was something to be popped then do it */
11824 /* if the condition is a bit variable */
11826 genIfxJump (ic, dup);
11827 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
11828 genIfxJump (ic, SPIL_LOC (cond)->rname);
11829 else if (isbit && !IS_ITEMP (cond))
11830 genIfxJump (ic, OP_SYMBOL (cond)->rname);
11832 genIfxJump (ic, "a");
11837 /*-----------------------------------------------------------------*/
11838 /* genAddrOf - generates code for address of */
11839 /*-----------------------------------------------------------------*/
11841 genAddrOf (iCode * ic)
11843 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
11846 D (emitcode (";", "genAddrOf"));
11848 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11850 /* if the operand is on the stack then we
11851 need to get the stack offset of this
11856 /* if 10 bit stack */
11857 if (options.stack10bit) {
11861 tsprintf(buff, sizeof(buff),
11862 "#!constbyte",(options.stack_loc >> 16) & 0xff);
11863 /* if it has an offset then we need to compute it */
11864 /* emitcode ("subb", "a,#!constbyte", */
11865 /* -((sym->stack < 0) ? */
11866 /* ((short) (sym->stack - _G.nRegsSaved)) : */
11867 /* ((short) sym->stack)) & 0xff); */
11868 /* emitcode ("mov","b,a"); */
11869 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
11870 /* ((short) (sym->stack - _G.nRegsSaved)) : */
11871 /* ((short) sym->stack)) >> 8) & 0xff); */
11873 emitcode ("mov", "a,_bpx");
11874 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
11875 ((char) (sym->stack - _G.nRegsSaved)) :
11876 ((char) sym->stack )) & 0xff);
11877 emitcode ("mov", "b,a");
11878 emitcode ("mov", "a,_bpx+1");
11880 offset = (((sym->stack < 0) ?
11881 ((short) (sym->stack - _G.nRegsSaved)) :
11882 ((short) sym->stack )) >> 8) & 0xff;
11884 emitcode ("addc","a,#!constbyte", offset);
11886 aopPut (IC_RESULT (ic), "b", 0);
11887 aopPut (IC_RESULT (ic), "a", 1);
11888 aopPut (IC_RESULT (ic), buff, 2);
11890 /* we can just move _bp */
11891 aopPut (IC_RESULT (ic), "_bpx", 0);
11892 aopPut (IC_RESULT (ic), "_bpx+1", 1);
11893 aopPut (IC_RESULT (ic), buff, 2);
11896 /* if it has an offset then we need to compute it */
11899 emitcode ("mov", "a,_bp");
11900 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
11901 aopPut (IC_RESULT (ic), "a", 0);
11905 /* we can just move _bp */
11906 aopPut (IC_RESULT (ic), "_bp", 0);
11908 /* fill the result with zero */
11909 size = AOP_SIZE (IC_RESULT (ic)) - 1;
11912 if (options.stack10bit && size < (FPTRSIZE - 1)) {
11914 "*** warning: pointer to stack var truncated.\n");
11920 aopPut (IC_RESULT (ic), zero, offset++);
11926 /* object not on stack then we need the name */
11927 size = AOP_SIZE (IC_RESULT (ic));
11932 char s[SDCC_NAME_MAX];
11936 tsprintf(s, sizeof(s), "#!his",sym->rname);
11939 tsprintf(s, sizeof(s), "#!hihis",sym->rname);
11942 tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
11944 default: /* should not need this (just in case) */
11945 SNPRINTF (s, sizeof(s), "#(%s >> %d)",
11952 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11955 aopPut (IC_RESULT (ic), s, offset++);
11959 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11963 #if 0 // obsolete, and buggy for != xdata
11964 /*-----------------------------------------------------------------*/
11965 /* genArrayInit - generates code for address of */
11966 /*-----------------------------------------------------------------*/
11968 genArrayInit (iCode * ic)
11970 literalList *iLoop;
11972 int elementSize = 0, eIndex;
11973 unsigned val, lastVal;
11975 operand *left=IC_LEFT(ic);
11977 D (emitcode (";", "genArrayInit"));
11979 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
11981 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
11983 // Load immediate value into DPTR.
11984 emitcode("mov", "dptr, %s",
11985 aopGet (IC_LEFT(ic), 0, TRUE, FALSE, NULL));
11987 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
11990 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11991 "Unexpected operand to genArrayInit.\n");
11994 // a regression because of SDCCcse.c:1.52
11995 emitcode ("mov", "dpl,%s", aopGet (left, 0, FALSE, FALSE, NULL));
11996 emitcode ("mov", "dph,%s", aopGet (left, 1, FALSE, FALSE, NULL));
11997 if (options.model == MODEL_FLAT24)
11998 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
12002 type = operandType(IC_LEFT(ic));
12004 if (type && type->next)
12006 elementSize = getSize(type->next);
12010 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12011 "can't determine element size in genArrayInit.\n");
12015 iLoop = IC_ARRAYILIST(ic);
12020 bool firstpass = TRUE;
12022 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
12023 iLoop->count, (int)iLoop->literalValue, elementSize);
12029 symbol *tlbl = NULL;
12031 count = ix > 256 ? 256 : ix;
12035 tlbl = newiTempLabel (NULL);
12036 if (firstpass || (count & 0xff))
12038 emitcode("mov", "b, #!constbyte", count & 0xff);
12046 for (eIndex = 0; eIndex < elementSize; eIndex++)
12048 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
12049 if (val != lastVal)
12051 emitcode("mov", "a, #!constbyte", val);
12055 emitcode("movx", "@dptr, a");
12056 emitcode("inc", "dptr");
12061 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
12067 iLoop = iLoop->next;
12070 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
12074 /*-----------------------------------------------------------------*/
12075 /* genFarFarAssign - assignment when both are in far space */
12076 /*-----------------------------------------------------------------*/
12078 genFarFarAssign (operand * result, operand * right, iCode * ic)
12080 int size = AOP_SIZE (right);
12082 symbol *rSym = NULL;
12086 /* quick & easy case. */
12087 D (emitcode(";","genFarFarAssign (1 byte case)"));
12088 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
12089 freeAsmop (right, NULL, ic, FALSE);
12090 /* now assign DPTR to result */
12092 aopOp(result, ic, FALSE, FALSE);
12094 aopPut (result, "a", 0);
12095 freeAsmop(result, NULL, ic, FALSE);
12099 /* See if we've got an underlying symbol to abuse. */
12100 if (IS_SYMOP(result) && OP_SYMBOL(result))
12102 if (IS_TRUE_SYMOP(result))
12104 rSym = OP_SYMBOL(result);
12106 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
12108 rSym = OP_SYMBOL(result)->usl.spillLoc;
12112 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
12114 /* We can use the '390 auto-toggle feature to good effect here. */
12116 D (emitcode(";", "genFarFarAssign (390 auto-toggle fun)"));
12117 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12118 emitcode ("mov", "dptr,#%s", rSym->rname);
12119 /* DP2 = result, DP1 = right, DP1 is current. */
12122 emitcode("movx", "a,@dptr");
12123 emitcode("movx", "@dptr,a");
12126 emitcode("inc", "dptr");
12127 emitcode("inc", "dptr");
12130 emitcode("mov", "dps,#0");
12131 freeAsmop (right, NULL, ic, FALSE);
12133 some alternative code for processors without auto-toggle
12134 no time to test now, so later well put in...kpb
12135 D (emitcode(";", "genFarFarAssign (dual-dptr fun)"));
12136 emitcode("mov", "dps,#1"); /* Select DPTR2. */
12137 emitcode ("mov", "dptr,#%s", rSym->rname);
12138 /* DP2 = result, DP1 = right, DP1 is current. */
12142 emitcode("movx", "a,@dptr");
12144 emitcode("inc", "dptr");
12145 emitcode("inc", "dps");
12146 emitcode("movx", "@dptr,a");
12148 emitcode("inc", "dptr");
12149 emitcode("inc", "dps");
12151 emitcode("mov", "dps,#0");
12152 freeAsmop (right, NULL, ic, FALSE);
12157 D (emitcode (";", "genFarFarAssign"));
12158 aopOp (result, ic, TRUE, TRUE);
12160 _startLazyDPSEvaluation ();
12165 aopGet (right, offset, FALSE, FALSE, NULL), offset);
12168 _endLazyDPSEvaluation ();
12169 freeAsmop (result, NULL, ic, FALSE);
12170 freeAsmop (right, NULL, ic, FALSE);
12174 /*-----------------------------------------------------------------*/
12175 /* genAssign - generate code for assignment */
12176 /*-----------------------------------------------------------------*/
12178 genAssign (iCode * ic)
12180 operand *result, *right;
12182 unsigned long lit = 0L;
12184 D (emitcode (";", "genAssign"));
12186 result = IC_RESULT (ic);
12187 right = IC_RIGHT (ic);
12189 /* if they are the same */
12190 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
12193 aopOp (right, ic, FALSE, FALSE);
12195 emitcode (";", "genAssign: resultIsFar = %s",
12196 isOperandInFarSpace (result) ?
12199 /* special case both in far space */
12200 if ((AOP_TYPE (right) == AOP_DPTR ||
12201 AOP_TYPE (right) == AOP_DPTR2) &&
12202 /* IS_TRUE_SYMOP(result) && */
12203 isOperandInFarSpace (result))
12205 genFarFarAssign (result, right, ic);
12209 aopOp (result, ic, TRUE, FALSE);
12211 /* if they are the same registers */
12212 if (sameRegs (AOP (right), AOP (result)))
12215 /* if the result is a bit */
12216 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
12218 /* if the right size is a literal then
12219 we know what the value is */
12220 if (AOP_TYPE (right) == AOP_LIT)
12222 if (((int) operandLitValue (right)))
12223 aopPut (result, one, 0);
12225 aopPut (result, zero, 0);
12229 /* the right is also a bit variable */
12230 if (AOP_TYPE (right) == AOP_CRY)
12232 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
12233 aopPut (result, "c", 0);
12237 /* we need to or */
12239 aopPut (result, "a", 0);
12243 /* bit variables done */
12245 size = AOP_SIZE (result);
12247 if (AOP_TYPE (right) == AOP_LIT)
12248 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
12251 (AOP_TYPE (result) != AOP_REG) &&
12252 (AOP_TYPE (right) == AOP_LIT) &&
12253 !IS_FLOAT (operandType (right)))
12255 _startLazyDPSEvaluation ();
12256 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
12259 aopGet (right, offset, FALSE, FALSE, NULL),
12264 /* And now fill the rest with zeros. */
12267 emitcode ("clr", "a");
12271 aopPut (result, "a", offset++);
12273 _endLazyDPSEvaluation ();
12277 _startLazyDPSEvaluation ();
12281 aopGet (right, offset, FALSE, FALSE, NULL),
12285 _endLazyDPSEvaluation ();
12289 freeAsmop (result, NULL, ic, TRUE);
12290 freeAsmop (right, NULL, ic, TRUE);
12293 /*-----------------------------------------------------------------*/
12294 /* genJumpTab - generates code for jump table */
12295 /*-----------------------------------------------------------------*/
12297 genJumpTab (iCode * ic)
12302 D (emitcode (";", "genJumpTab"));
12304 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
12305 /* get the condition into accumulator */
12306 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE, NULL);
12308 /* multiply by four! */
12309 emitcode ("add", "a,acc");
12310 emitcode ("add", "a,acc");
12311 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
12313 jtab = newiTempLabel (NULL);
12314 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
12315 emitcode ("jmp", "@a+dptr");
12317 /* now generate the jump labels */
12318 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
12319 jtab = setNextItem (IC_JTLABELS (ic)))
12320 emitcode ("ljmp", "!tlabel", jtab->key + 100);
12324 /*-----------------------------------------------------------------*/
12325 /* genCast - gen code for casting */
12326 /*-----------------------------------------------------------------*/
12328 genCast (iCode * ic)
12330 operand *result = IC_RESULT (ic);
12331 sym_link *ctype = operandType (IC_LEFT (ic));
12332 sym_link *rtype = operandType (IC_RIGHT (ic));
12333 operand *right = IC_RIGHT (ic);
12336 D (emitcode (";", "genCast"));
12338 /* if they are equivalent then do nothing */
12339 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
12342 aopOp (right, ic, FALSE, AOP_IS_STR (result));
12343 aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR));
12345 /* if the result is a bit (and not a bitfield) */
12346 if (IS_BIT (OP_SYMBOL (result)->type))
12348 /* if the right size is a literal then
12349 we know what the value is */
12350 if (AOP_TYPE (right) == AOP_LIT)
12352 if (((int) operandLitValue (right)))
12353 aopPut (result, one, 0);
12355 aopPut (result, zero, 0);
12360 /* the right is also a bit variable */
12361 if (AOP_TYPE (right) == AOP_CRY)
12363 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
12364 aopPut (result, "c", 0);
12368 /* we need to or */
12370 aopPut (result, "a", 0);
12374 /* if they are the same size : or less */
12375 if (AOP_SIZE (result) <= AOP_SIZE (right))
12378 /* if they are in the same place */
12379 if (sameRegs (AOP (right), AOP (result)))
12382 /* if they in different places then copy */
12383 size = AOP_SIZE (result);
12385 _startLazyDPSEvaluation ();
12389 aopGet (right, offset, FALSE, FALSE, NULL),
12393 _endLazyDPSEvaluation ();
12397 /* if the result is of type pointer */
12398 if (IS_PTR (ctype))
12402 sym_link *type = operandType (right);
12404 /* pointer to generic pointer */
12405 if (IS_GENPTR (ctype))
12409 p_type = DCL_TYPE (type);
12413 #if OLD_CAST_BEHAVIOR
12414 /* KV: we are converting a non-pointer type to
12415 * a generic pointer. This (ifdef'd out) code
12416 * says that the resulting generic pointer
12417 * should have the same class as the storage
12418 * location of the non-pointer variable.
12420 * For example, converting an int (which happens
12421 * to be stored in DATA space) to a pointer results
12422 * in a DATA generic pointer; if the original int
12423 * in XDATA space, so will be the resulting pointer.
12425 * I don't like that behavior, and thus this change:
12426 * all such conversions will be forced to XDATA and
12427 * throw a warning. If you want some non-XDATA
12428 * type, or you want to suppress the warning, you
12429 * must go through an intermediate cast, like so:
12431 * char _generic *gp = (char _xdata *)(intVar);
12433 sym_link *etype = getSpec (type);
12435 /* we have to go by the storage class */
12436 if (SPEC_OCLS (etype) != generic)
12438 p_type = PTR_TYPE (SPEC_OCLS (etype));
12443 /* Converting unknown class (i.e. register variable)
12444 * to generic pointer. This is not good, but
12445 * we'll make a guess (and throw a warning).
12448 werror (W_INT_TO_GEN_PTR_CAST);
12452 /* the first two bytes are known */
12453 size = GPTRSIZE - 1;
12455 _startLazyDPSEvaluation ();
12459 aopGet (right, offset, FALSE, FALSE, NULL),
12463 _endLazyDPSEvaluation ();
12465 /* the last byte depending on type */
12467 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
12472 // pointerTypeToGPByte will have bitched.
12476 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%x", gpVal);
12477 aopPut (result, gpValStr, GPTRSIZE - 1);
12482 /* just copy the pointers */
12483 size = AOP_SIZE (result);
12485 _startLazyDPSEvaluation ();
12489 aopGet (right, offset, FALSE, FALSE, NULL),
12493 _endLazyDPSEvaluation ();
12497 /* so we now know that the size of destination is greater
12498 than the size of the source */
12499 /* we move to result for the size of source */
12500 size = AOP_SIZE (right);
12502 _startLazyDPSEvaluation ();
12506 aopGet (right, offset, FALSE, FALSE, NULL),
12510 _endLazyDPSEvaluation ();
12512 /* now depending on the sign of the source && destination */
12513 size = AOP_SIZE (result) - AOP_SIZE (right);
12514 /* if unsigned or not an integral type */
12515 /* also, if the source is a bit, we don't need to sign extend, because
12516 * it can't possibly have set the sign bit.
12518 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
12522 aopPut (result, zero, offset++);
12527 /* we need to extend the sign :{ */
12528 MOVA (aopGet (right, AOP_SIZE (right) - 1,
12529 FALSE, FALSE, NULL));
12530 emitcode ("rlc", "a");
12531 emitcode ("subb", "a,acc");
12533 aopPut (result, "a", offset++);
12536 /* we are done hurray !!!! */
12539 freeAsmop (right, NULL, ic, TRUE);
12540 freeAsmop (result, NULL, ic, TRUE);
12544 /*-----------------------------------------------------------------*/
12545 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
12546 /*-----------------------------------------------------------------*/
12547 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
12549 operand *from , *to , *count;
12554 /* we know it has to be 3 parameters */
12555 assert (nparms == 3);
12557 rsave = newBitVect(16);
12558 /* save DPTR if it needs to be saved */
12559 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12560 if (bitVectBitValue(ic->rMask,i))
12561 rsave = bitVectSetBit(rsave,i);
12563 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12564 ds390_rUmaskForOp (IC_RESULT(ic))));
12571 aopOp (from, ic->next, FALSE, FALSE);
12573 /* get from into DPTR1 */
12574 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12575 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12576 if (options.model == MODEL_FLAT24) {
12577 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12580 freeAsmop (from, NULL, ic, FALSE);
12581 aopOp (to, ic, FALSE, FALSE);
12582 /* get "to" into DPTR */
12583 /* if the operand is already in dptr
12584 then we do nothing else we move the value to dptr */
12585 if (AOP_TYPE (to) != AOP_STR) {
12586 /* if already in DPTR then we need to push */
12587 if (AOP_TYPE(to) == AOP_DPTR) {
12588 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12589 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12590 if (options.model == MODEL_FLAT24)
12591 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12592 emitcode ("pop", "dph");
12593 emitcode ("pop", "dpl");
12595 _startLazyDPSEvaluation ();
12596 /* if this is remateriazable */
12597 if (AOP_TYPE (to) == AOP_IMMD) {
12598 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12599 } else { /* we need to get it byte by byte */
12600 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12601 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12602 if (options.model == MODEL_FLAT24) {
12603 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12606 _endLazyDPSEvaluation ();
12609 freeAsmop (to, NULL, ic, FALSE);
12610 _G.dptrInUse = _G.dptr1InUse = 1;
12611 aopOp (count, ic->next->next, FALSE,FALSE);
12612 lbl =newiTempLabel(NULL);
12614 /* now for the actual copy */
12615 if (AOP_TYPE(count) == AOP_LIT &&
12616 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12617 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12619 emitcode ("lcall","__bi_memcpyc2x_s");
12621 emitcode ("lcall","__bi_memcpyx2x_s");
12623 freeAsmop (count, NULL, ic, FALSE);
12625 symbol *lbl1 = newiTempLabel(NULL);
12627 emitcode (";"," Auto increment but no djnz");
12628 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
12629 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
12630 freeAsmop (count, NULL, ic, FALSE);
12631 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12634 emitcode ("clr","a");
12635 emitcode ("movc", "a,@a+dptr");
12637 emitcode ("movx", "a,@dptr");
12638 emitcode ("movx", "@dptr,a");
12639 emitcode ("inc", "dptr");
12640 emitcode ("inc", "dptr");
12641 emitcode ("mov","a,b");
12642 emitcode ("orl","a,_ap");
12643 emitcode ("jz","!tlabel",lbl1->key+100);
12644 emitcode ("mov","a,_ap");
12645 emitcode ("add","a,#!constbyte",0xFF);
12646 emitcode ("mov","_ap,a");
12647 emitcode ("mov","a,b");
12648 emitcode ("addc","a,#!constbyte",0xFF);
12649 emitcode ("mov","b,a");
12650 emitcode ("sjmp","!tlabel",lbl->key+100);
12653 emitcode ("mov", "dps,#0");
12654 _G.dptrInUse = _G.dptr1InUse = 0;
12655 unsavermask(rsave);
12659 /*-----------------------------------------------------------------*/
12660 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
12661 /*-----------------------------------------------------------------*/
12662 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
12664 operand *from , *to , *count;
12669 /* we know it has to be 3 parameters */
12670 assert (nparms == 3);
12672 rsave = newBitVect(16);
12673 /* save DPTR if it needs to be saved */
12674 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12675 if (bitVectBitValue(ic->rMask,i))
12676 rsave = bitVectSetBit(rsave,i);
12678 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12679 ds390_rUmaskForOp (IC_RESULT(ic))));
12686 aopOp (from, ic->next, FALSE, FALSE);
12688 /* get from into DPTR1 */
12689 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12690 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12691 if (options.model == MODEL_FLAT24) {
12692 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12695 freeAsmop (from, NULL, ic, FALSE);
12696 aopOp (to, ic, FALSE, FALSE);
12697 /* get "to" into DPTR */
12698 /* if the operand is already in dptr
12699 then we do nothing else we move the value to dptr */
12700 if (AOP_TYPE (to) != AOP_STR) {
12701 /* if already in DPTR then we need to push */
12702 if (AOP_TYPE(to) == AOP_DPTR) {
12703 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12704 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12705 if (options.model == MODEL_FLAT24)
12706 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12707 emitcode ("pop", "dph");
12708 emitcode ("pop", "dpl");
12710 _startLazyDPSEvaluation ();
12711 /* if this is remateriazable */
12712 if (AOP_TYPE (to) == AOP_IMMD) {
12713 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12714 } else { /* we need to get it byte by byte */
12715 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12716 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12717 if (options.model == MODEL_FLAT24) {
12718 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12721 _endLazyDPSEvaluation ();
12724 freeAsmop (to, NULL, ic, FALSE);
12725 _G.dptrInUse = _G.dptr1InUse = 1;
12726 aopOp (count, ic->next->next, FALSE,FALSE);
12727 lbl =newiTempLabel(NULL);
12728 lbl2 =newiTempLabel(NULL);
12730 /* now for the actual compare */
12731 if (AOP_TYPE(count) == AOP_LIT &&
12732 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12733 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12735 emitcode("lcall","__bi_memcmpc2x_s");
12737 emitcode("lcall","__bi_memcmpx2x_s");
12738 freeAsmop (count, NULL, ic, FALSE);
12739 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12740 aopPut(IC_RESULT(ic),"a",0);
12741 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12743 symbol *lbl1 = newiTempLabel(NULL);
12745 emitcode("push","ar0");
12746 emitcode (";"," Auto increment but no djnz");
12747 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
12748 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
12749 freeAsmop (count, NULL, ic, FALSE);
12750 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12753 emitcode ("clr","a");
12754 emitcode ("movc", "a,@a+dptr");
12756 emitcode ("movx", "a,@dptr");
12757 emitcode ("mov","r0,a");
12758 emitcode ("movx", "a,@dptr");
12759 emitcode ("clr","c");
12760 emitcode ("subb","a,r0");
12761 emitcode ("jnz","!tlabel",lbl2->key+100);
12762 emitcode ("inc", "dptr");
12763 emitcode ("inc", "dptr");
12764 emitcode ("mov","a,b");
12765 emitcode ("orl","a,_ap");
12766 emitcode ("jz","!tlabel",lbl1->key+100);
12767 emitcode ("mov","a,_ap");
12768 emitcode ("add","a,#!constbyte",0xFF);
12769 emitcode ("mov","_ap,a");
12770 emitcode ("mov","a,b");
12771 emitcode ("addc","a,#!constbyte",0xFF);
12772 emitcode ("mov","b,a");
12773 emitcode ("sjmp","!tlabel",lbl->key+100);
12775 emitcode ("clr","a");
12777 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12778 aopPut(IC_RESULT(ic),"a",0);
12779 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12780 emitcode("pop","ar0");
12781 emitcode ("mov", "dps,#0");
12783 _G.dptrInUse = _G.dptr1InUse = 0;
12784 unsavermask(rsave);
12788 /*-----------------------------------------------------------------*/
12789 /* genInp - gen code for __builtin_inp read data from a mem mapped */
12790 /* port, first parameter output area second parameter pointer to */
12791 /* port third parameter count */
12792 /*-----------------------------------------------------------------*/
12793 static void genInp( iCode *ic, int nparms, operand **parms)
12795 operand *from , *to , *count;
12800 /* we know it has to be 3 parameters */
12801 assert (nparms == 3);
12803 rsave = newBitVect(16);
12804 /* save DPTR if it needs to be saved */
12805 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12806 if (bitVectBitValue(ic->rMask,i))
12807 rsave = bitVectSetBit(rsave,i);
12809 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12810 ds390_rUmaskForOp (IC_RESULT(ic))));
12817 aopOp (from, ic->next, FALSE, FALSE);
12819 /* get from into DPTR1 */
12820 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12821 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12822 if (options.model == MODEL_FLAT24) {
12823 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12826 freeAsmop (from, NULL, ic, FALSE);
12827 aopOp (to, ic, FALSE, FALSE);
12828 /* get "to" into DPTR */
12829 /* if the operand is already in dptr
12830 then we do nothing else we move the value to dptr */
12831 if (AOP_TYPE (to) != AOP_STR) {
12832 /* if already in DPTR then we need to push */
12833 if (AOP_TYPE(to) == AOP_DPTR) {
12834 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12835 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12836 if (options.model == MODEL_FLAT24)
12837 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12838 emitcode ("pop", "dph");
12839 emitcode ("pop", "dpl");
12841 _startLazyDPSEvaluation ();
12842 /* if this is remateriazable */
12843 if (AOP_TYPE (to) == AOP_IMMD) {
12844 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12845 } else { /* we need to get it byte by byte */
12846 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12847 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12848 if (options.model == MODEL_FLAT24) {
12849 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12852 _endLazyDPSEvaluation ();
12855 freeAsmop (to, NULL, ic, FALSE);
12857 _G.dptrInUse = _G.dptr1InUse = 1;
12858 aopOp (count, ic->next->next, FALSE,FALSE);
12859 lbl =newiTempLabel(NULL);
12861 /* now for the actual copy */
12862 if (AOP_TYPE(count) == AOP_LIT &&
12863 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12864 emitcode (";","OH JOY auto increment with djnz (very fast)");
12865 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
12866 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12867 freeAsmop (count, NULL, ic, FALSE);
12869 emitcode ("movx", "a,@dptr"); /* read data from port */
12870 emitcode ("dec","dps"); /* switch to DPTR */
12871 emitcode ("movx", "@dptr,a"); /* save into location */
12872 emitcode ("inc", "dptr"); /* point to next area */
12873 emitcode ("inc","dps"); /* switch to DPTR2 */
12874 emitcode ("djnz","b,!tlabel",lbl->key+100);
12876 symbol *lbl1 = newiTempLabel(NULL);
12878 emitcode (";"," Auto increment but no djnz");
12879 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
12880 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
12881 freeAsmop (count, NULL, ic, FALSE);
12882 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
12884 emitcode ("movx", "a,@dptr");
12885 emitcode ("dec","dps"); /* switch to DPTR */
12886 emitcode ("movx", "@dptr,a");
12887 emitcode ("inc", "dptr");
12888 emitcode ("inc","dps"); /* switch to DPTR2 */
12889 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
12890 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
12891 emitcode ("mov","a,b");
12892 emitcode ("orl","a,_ap");
12893 emitcode ("jz","!tlabel",lbl1->key+100);
12894 emitcode ("mov","a,_ap");
12895 emitcode ("add","a,#!constbyte",0xFF);
12896 emitcode ("mov","_ap,a");
12897 emitcode ("mov","a,b");
12898 emitcode ("addc","a,#!constbyte",0xFF);
12899 emitcode ("mov","b,a");
12900 emitcode ("sjmp","!tlabel",lbl->key+100);
12903 emitcode ("mov", "dps,#0");
12904 _G.dptrInUse = _G.dptr1InUse = 0;
12905 unsavermask(rsave);
12909 /*-----------------------------------------------------------------*/
12910 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
12911 /* port, first parameter output area second parameter pointer to */
12912 /* port third parameter count */
12913 /*-----------------------------------------------------------------*/
12914 static void genOutp( iCode *ic, int nparms, operand **parms)
12916 operand *from , *to , *count;
12921 /* we know it has to be 3 parameters */
12922 assert (nparms == 3);
12924 rsave = newBitVect(16);
12925 /* save DPTR if it needs to be saved */
12926 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12927 if (bitVectBitValue(ic->rMask,i))
12928 rsave = bitVectSetBit(rsave,i);
12930 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12931 ds390_rUmaskForOp (IC_RESULT(ic))));
12938 aopOp (from, ic->next, FALSE, FALSE);
12940 /* get from into DPTR1 */
12941 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12942 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12943 if (options.model == MODEL_FLAT24) {
12944 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12947 freeAsmop (from, NULL, ic, FALSE);
12948 aopOp (to, ic, FALSE, FALSE);
12949 /* get "to" into DPTR */
12950 /* if the operand is already in dptr
12951 then we do nothing else we move the value to dptr */
12952 if (AOP_TYPE (to) != AOP_STR) {
12953 /* if already in DPTR then we need to push */
12954 if (AOP_TYPE(to) == AOP_DPTR) {
12955 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12956 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12957 if (options.model == MODEL_FLAT24)
12958 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12959 emitcode ("pop", "dph");
12960 emitcode ("pop", "dpl");
12962 _startLazyDPSEvaluation ();
12963 /* if this is remateriazable */
12964 if (AOP_TYPE (to) == AOP_IMMD) {
12965 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12966 } else { /* we need to get it byte by byte */
12967 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12968 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12969 if (options.model == MODEL_FLAT24) {
12970 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12973 _endLazyDPSEvaluation ();
12976 freeAsmop (to, NULL, ic, FALSE);
12978 _G.dptrInUse = _G.dptr1InUse = 1;
12979 aopOp (count, ic->next->next, FALSE,FALSE);
12980 lbl =newiTempLabel(NULL);
12982 /* now for the actual copy */
12983 if (AOP_TYPE(count) == AOP_LIT &&
12984 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12985 emitcode (";","OH JOY auto increment with djnz (very fast)");
12986 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
12987 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12989 emitcode ("movx", "a,@dptr"); /* read data from port */
12990 emitcode ("inc","dps"); /* switch to DPTR2 */
12991 emitcode ("movx", "@dptr,a"); /* save into location */
12992 emitcode ("inc", "dptr"); /* point to next area */
12993 emitcode ("dec","dps"); /* switch to DPTR */
12994 emitcode ("djnz","b,!tlabel",lbl->key+100);
12995 freeAsmop (count, NULL, ic, FALSE);
12997 symbol *lbl1 = newiTempLabel(NULL);
12999 emitcode (";"," Auto increment but no djnz");
13000 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
13001 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
13002 freeAsmop (count, NULL, ic, FALSE);
13003 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
13005 emitcode ("movx", "a,@dptr");
13006 emitcode ("inc", "dptr");
13007 emitcode ("inc","dps"); /* switch to DPTR2 */
13008 emitcode ("movx", "@dptr,a");
13009 emitcode ("dec","dps"); /* switch to DPTR */
13010 emitcode ("mov","a,b");
13011 emitcode ("orl","a,_ap");
13012 emitcode ("jz","!tlabel",lbl1->key+100);
13013 emitcode ("mov","a,_ap");
13014 emitcode ("add","a,#!constbyte",0xFF);
13015 emitcode ("mov","_ap,a");
13016 emitcode ("mov","a,b");
13017 emitcode ("addc","a,#!constbyte",0xFF);
13018 emitcode ("mov","b,a");
13019 emitcode ("sjmp","!tlabel",lbl->key+100);
13022 emitcode ("mov", "dps,#0");
13023 _G.dptrInUse = _G.dptr1InUse = 0;
13024 unsavermask(rsave);
13028 /*-----------------------------------------------------------------*/
13029 /* genSwapW - swap lower & high order bytes */
13030 /*-----------------------------------------------------------------*/
13031 static void genSwapW(iCode *ic, int nparms, operand **parms)
13035 assert (nparms==1);
13038 dest=IC_RESULT(ic);
13040 assert(getSize(operandType(src))==2);
13042 aopOp (src, ic, FALSE, FALSE);
13043 emitcode ("mov","a,%s",aopGet(src,0,FALSE,FALSE,NULL));
13045 MOVB(aopGet(src,1,FALSE,FALSE,"b"));
13047 freeAsmop (src, NULL, ic, FALSE);
13049 aopOp (dest,ic, FALSE, FALSE);
13050 aopPut(dest,"b",0);
13051 aopPut(dest,"a",1);
13052 freeAsmop (dest, NULL, ic, FALSE);
13055 /*-----------------------------------------------------------------*/
13056 /* genMemsetX - gencode for memSetX data */
13057 /*-----------------------------------------------------------------*/
13058 static void genMemsetX(iCode *ic, int nparms, operand **parms)
13060 operand *to , *val , *count;
13066 /* we know it has to be 3 parameters */
13067 assert (nparms == 3);
13073 /* save DPTR if it needs to be saved */
13074 rsave = newBitVect(16);
13075 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
13076 if (bitVectBitValue(ic->rMask,i))
13077 rsave = bitVectSetBit(rsave,i);
13079 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
13080 ds390_rUmaskForOp (IC_RESULT(ic))));
13083 aopOp (to, ic, FALSE, FALSE);
13084 /* get "to" into DPTR */
13085 /* if the operand is already in dptr
13086 then we do nothing else we move the value to dptr */
13087 if (AOP_TYPE (to) != AOP_STR) {
13088 /* if already in DPTR then we need to push */
13089 if (AOP_TYPE(to) == AOP_DPTR) {
13090 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
13091 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
13092 if (options.model == MODEL_FLAT24)
13093 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
13094 emitcode ("pop", "dph");
13095 emitcode ("pop", "dpl");
13097 _startLazyDPSEvaluation ();
13098 /* if this is remateriazable */
13099 if (AOP_TYPE (to) == AOP_IMMD) {
13100 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
13101 } else { /* we need to get it byte by byte */
13102 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
13103 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
13104 if (options.model == MODEL_FLAT24) {
13105 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
13108 _endLazyDPSEvaluation ();
13111 freeAsmop (to, NULL, ic, FALSE);
13113 aopOp (val, ic->next->next, FALSE,FALSE);
13114 aopOp (count, ic->next->next, FALSE,FALSE);
13115 lbl =newiTempLabel(NULL);
13116 /* now for the actual copy */
13117 if (AOP_TYPE(count) == AOP_LIT &&
13118 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
13119 l = aopGet(val, 0, FALSE, FALSE, NULL);
13120 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
13123 emitcode ("movx", "@dptr,a");
13124 emitcode ("inc", "dptr");
13125 emitcode ("djnz","b,!tlabel",lbl->key+100);
13127 symbol *lbl1 = newiTempLabel(NULL);
13129 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
13130 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
13132 MOVA (aopGet(val, 0, FALSE, FALSE, NULL));
13133 emitcode ("movx", "@dptr,a");
13134 emitcode ("inc", "dptr");
13135 emitcode ("mov","a,b");
13136 emitcode ("orl","a,_ap");
13137 emitcode ("jz","!tlabel",lbl1->key+100);
13138 emitcode ("mov","a,_ap");
13139 emitcode ("add","a,#!constbyte",0xFF);
13140 emitcode ("mov","_ap,a");
13141 emitcode ("mov","a,b");
13142 emitcode ("addc","a,#!constbyte",0xFF);
13143 emitcode ("mov","b,a");
13144 emitcode ("sjmp","!tlabel",lbl->key+100);
13147 freeAsmop (count, NULL, ic, FALSE);
13148 unsavermask(rsave);
13151 /*-----------------------------------------------------------------*/
13152 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
13153 /*-----------------------------------------------------------------*/
13154 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
13157 operand *pnum, *result;
13160 assert (nparms==1);
13161 /* save registers that need to be saved */
13162 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13163 ds390_rUmaskForOp (IC_RESULT(ic))));
13166 aopOp (pnum, ic, FALSE, FALSE);
13167 emitcode ("mov","a,%s",aopGet(pnum,0,FALSE,FALSE,DP2_RESULT_REG));
13168 freeAsmop (pnum, NULL, ic, FALSE);
13169 emitcode ("lcall","NatLib_LoadPrimitive");
13170 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
13171 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
13172 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
13173 for (i = (size-1) ; i >= 0 ; i-- ) {
13174 emitcode ("push","a%s",javaRet[i]);
13176 for (i=0; i < size ; i++ ) {
13177 emitcode ("pop","a%s",
13178 aopGet(result,i,FALSE,FALSE,DP2_RESULT_REG));
13181 for (i = 0 ; i < size ; i++ ) {
13182 aopPut(result,javaRet[i],i);
13185 freeAsmop (result, NULL, ic, FALSE);
13186 unsavermask(rsave);
13189 /*-----------------------------------------------------------------*/
13190 /* genNatLibLoadPointer - calls TINI api function to load pointer */
13191 /*-----------------------------------------------------------------*/
13192 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
13195 operand *pnum, *result;
13199 assert (nparms==1);
13200 /* save registers that need to be saved */
13201 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13202 ds390_rUmaskForOp (IC_RESULT(ic))));
13205 aopOp (pnum, ic, FALSE, FALSE);
13206 emitcode ("mov","a,%s",aopGet(pnum,0,FALSE,FALSE,DP2_RESULT_REG));
13207 freeAsmop (pnum, NULL, ic, FALSE);
13208 emitcode ("lcall","NatLib_LoadPointer");
13209 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
13210 if (AOP_TYPE(result)!=AOP_STR) {
13211 for (i = 0 ; i < size ; i++ ) {
13212 aopPut(result,fReturn[i],i);
13215 freeAsmop (result, NULL, ic, FALSE);
13216 unsavermask(rsave);
13219 /*-----------------------------------------------------------------*/
13220 /* genNatLibInstallStateBlock - */
13221 /*-----------------------------------------------------------------*/
13222 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
13223 operand **parms, const char *name)
13226 operand *psb, *handle;
13227 assert (nparms==2);
13229 /* save registers that need to be saved */
13230 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13231 ds390_rUmaskForOp (IC_RESULT(ic))));
13235 /* put pointer to state block into DPTR1 */
13236 aopOp (psb, ic, FALSE, FALSE);
13237 if (AOP_TYPE (psb) == AOP_IMMD) {
13238 emitcode ("mov","dps,#1");
13239 emitcode ("mov", "dptr,%s",
13240 aopGet (psb, 0, TRUE, FALSE, DP2_RESULT_REG));
13241 emitcode ("mov","dps,#0");
13243 emitcode ("mov","dpl1,%s",aopGet(psb,0,FALSE,FALSE,DP2_RESULT_REG));
13244 emitcode ("mov","dph1,%s",aopGet(psb,1,FALSE,FALSE,DP2_RESULT_REG));
13245 emitcode ("mov","dpx1,%s",aopGet(psb,2,FALSE,FALSE,DP2_RESULT_REG));
13247 freeAsmop (psb, NULL, ic, FALSE);
13249 /* put libraryID into DPTR */
13250 emitcode ("mov","dptr,#LibraryID");
13252 /* put handle into r3:r2 */
13253 aopOp (handle, ic, FALSE, FALSE);
13254 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13255 emitcode ("push","%s",aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13256 emitcode ("push","%s",aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13257 emitcode ("pop","ar3");
13258 emitcode ("pop","ar2");
13260 emitcode ("mov","r2,%s",aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13261 emitcode ("mov","r3,%s",aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13263 freeAsmop (psb, NULL, ic, FALSE);
13265 /* make the call */
13266 emitcode ("lcall","NatLib_Install%sStateBlock",name);
13268 /* put return value into place*/
13270 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
13272 aopPut(IC_RESULT(ic),"a",0);
13273 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13274 unsavermask(rsave);
13277 /*-----------------------------------------------------------------*/
13278 /* genNatLibRemoveStateBlock - */
13279 /*-----------------------------------------------------------------*/
13280 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
13286 /* save registers that need to be saved */
13287 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13288 ds390_rUmaskForOp (IC_RESULT(ic))));
13290 /* put libraryID into DPTR */
13291 emitcode ("mov","dptr,#LibraryID");
13292 /* make the call */
13293 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
13294 unsavermask(rsave);
13297 /*-----------------------------------------------------------------*/
13298 /* genNatLibGetStateBlock - */
13299 /*-----------------------------------------------------------------*/
13300 static void genNatLibGetStateBlock(iCode *ic,int nparms,
13301 operand **parms,const char *name)
13304 symbol *lbl = newiTempLabel(NULL);
13307 /* save registers that need to be saved */
13308 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13309 ds390_rUmaskForOp (IC_RESULT(ic))));
13311 /* put libraryID into DPTR */
13312 emitcode ("mov","dptr,#LibraryID");
13313 /* make the call */
13314 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
13315 emitcode ("jnz","!tlabel",lbl->key+100);
13317 /* put return value into place */
13318 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
13319 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
13320 emitcode ("push","ar3");
13321 emitcode ("push","ar2");
13322 emitcode ("pop","%s",
13323 aopGet(IC_RESULT(ic),0,FALSE,TRUE,DP2_RESULT_REG));
13324 emitcode ("pop","%s",
13325 aopGet(IC_RESULT(ic),1,FALSE,TRUE,DP2_RESULT_REG));
13327 aopPut(IC_RESULT(ic),"r2",0);
13328 aopPut(IC_RESULT(ic),"r3",1);
13330 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13332 unsavermask(rsave);
13335 /*-----------------------------------------------------------------*/
13336 /* genMMMalloc - */
13337 /*-----------------------------------------------------------------*/
13338 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
13339 int size, const char *name)
13344 symbol *lbl = newiTempLabel(NULL);
13346 assert (nparms == 1);
13347 /* save registers that need to be saved */
13348 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13349 ds390_rUmaskForOp (IC_RESULT(ic))));
13352 aopOp (bsize,ic,FALSE,FALSE);
13354 /* put the size in R4-R2 */
13355 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
13356 emitcode("push","%s",aopGet(bsize,0,FALSE,TRUE,DP2_RESULT_REG));
13357 emitcode("push","%s",aopGet(bsize,1,FALSE,TRUE,DP2_RESULT_REG));
13359 emitcode("push","%s",aopGet(bsize,2,FALSE,TRUE,DP2_RESULT_REG));
13360 emitcode("pop","ar4");
13362 emitcode("pop","ar3");
13363 emitcode("pop","ar2");
13365 emitcode ("mov","r2,%s",aopGet(bsize,0,FALSE,TRUE,DP2_RESULT_REG));
13366 emitcode ("mov","r3,%s",aopGet(bsize,1,FALSE,TRUE,DP2_RESULT_REG));
13368 emitcode("mov","r4,%s",aopGet(bsize,2,FALSE,TRUE,DP2_RESULT_REG));
13371 freeAsmop (bsize, NULL, ic, FALSE);
13373 /* make the call */
13374 emitcode ("lcall","MM_%s",name);
13375 emitcode ("jz","!tlabel",lbl->key+100);
13376 emitcode ("mov","r2,#!constbyte",0xff);
13377 emitcode ("mov","r3,#!constbyte",0xff);
13379 /* we don't care about the pointer : we just save the handle */
13380 rsym = OP_SYMBOL(IC_RESULT(ic));
13381 if (rsym->liveFrom != rsym->liveTo) {
13382 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
13383 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
13384 emitcode ("push","ar3");
13385 emitcode ("push","ar2");
13386 emitcode ("pop","%s",
13387 aopGet(IC_RESULT(ic),0,FALSE,TRUE,DP2_RESULT_REG));
13388 emitcode ("pop","%s",
13389 aopGet(IC_RESULT(ic),1,FALSE,TRUE,DP2_RESULT_REG));
13391 aopPut(IC_RESULT(ic),"r2",0);
13392 aopPut(IC_RESULT(ic),"r3",1);
13394 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13396 unsavermask(rsave);
13399 /*-----------------------------------------------------------------*/
13401 /*-----------------------------------------------------------------*/
13402 static void genMMDeref (iCode *ic,int nparms, operand **parms)
13407 assert (nparms == 1);
13408 /* save registers that need to be saved */
13409 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13410 ds390_rUmaskForOp (IC_RESULT(ic))));
13413 aopOp (handle,ic,FALSE,FALSE);
13415 /* put the size in R4-R2 */
13416 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13417 emitcode("push","%s",
13418 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13419 emitcode("push","%s",
13420 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13421 emitcode("pop","ar3");
13422 emitcode("pop","ar2");
13424 emitcode ("mov","r2,%s",
13425 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13426 emitcode ("mov","r3,%s",
13427 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13429 freeAsmop (handle, NULL, ic, FALSE);
13431 /* make the call */
13432 emitcode ("lcall","MM_Deref");
13435 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13436 if (rsym->liveFrom != rsym->liveTo) {
13437 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13438 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
13439 _startLazyDPSEvaluation ();
13441 aopPut(IC_RESULT(ic),"dpl",0);
13442 aopPut(IC_RESULT(ic),"dph",1);
13443 aopPut(IC_RESULT(ic),"dpx",2);
13445 _endLazyDPSEvaluation ();
13450 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13451 unsavermask(rsave);
13454 /*-----------------------------------------------------------------*/
13455 /* genMMUnrestrictedPersist - */
13456 /*-----------------------------------------------------------------*/
13457 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
13462 assert (nparms == 1);
13463 /* save registers that need to be saved */
13464 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13465 ds390_rUmaskForOp (IC_RESULT(ic))));
13468 aopOp (handle,ic,FALSE,FALSE);
13470 /* put the size in R3-R2 */
13471 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13472 emitcode("push","%s",
13473 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13474 emitcode("push","%s",
13475 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13476 emitcode("pop","ar3");
13477 emitcode("pop","ar2");
13479 emitcode ("mov","r2,%s",
13480 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13481 emitcode ("mov","r3,%s",
13482 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13484 freeAsmop (handle, NULL, ic, FALSE);
13486 /* make the call */
13487 emitcode ("lcall","MM_UnrestrictedPersist");
13490 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13491 if (rsym->liveFrom != rsym->liveTo) {
13492 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13493 aopPut(IC_RESULT(ic),"a",0);
13494 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13497 unsavermask(rsave);
13500 /*-----------------------------------------------------------------*/
13501 /* genSystemExecJavaProcess - */
13502 /*-----------------------------------------------------------------*/
13503 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
13506 operand *handle, *pp;
13508 assert (nparms==2);
13509 /* save registers that need to be saved */
13510 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13511 ds390_rUmaskForOp (IC_RESULT(ic))));
13516 /* put the handle in R3-R2 */
13517 aopOp (handle,ic,FALSE,FALSE);
13518 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13519 emitcode("push","%s",
13520 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13521 emitcode("push","%s",
13522 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13523 emitcode("pop","ar3");
13524 emitcode("pop","ar2");
13526 emitcode ("mov","r2,%s",
13527 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13528 emitcode ("mov","r3,%s",
13529 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13531 freeAsmop (handle, NULL, ic, FALSE);
13533 /* put pointer in DPTR */
13534 aopOp (pp,ic,FALSE,FALSE);
13535 if (AOP_TYPE(pp) == AOP_IMMD) {
13536 emitcode ("mov", "dptr,%s",
13537 aopGet (pp, 0, TRUE, FALSE, NULL));
13538 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
13539 emitcode ("mov","dpl,%s",aopGet(pp,0,FALSE,FALSE,NULL));
13540 emitcode ("mov","dph,%s",aopGet(pp,1,FALSE,FALSE,NULL));
13541 emitcode ("mov","dpx,%s",aopGet(pp,2,FALSE,FALSE,NULL));
13543 freeAsmop (handle, NULL, ic, FALSE);
13545 /* make the call */
13546 emitcode ("lcall","System_ExecJavaProcess");
13548 /* put result in place */
13550 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13551 if (rsym->liveFrom != rsym->liveTo) {
13552 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13553 aopPut(IC_RESULT(ic),"a",0);
13554 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13558 unsavermask(rsave);
13561 /*-----------------------------------------------------------------*/
13562 /* genSystemRTCRegisters - */
13563 /*-----------------------------------------------------------------*/
13564 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
13570 assert (nparms==1);
13571 /* save registers that need to be saved */
13572 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13573 ds390_rUmaskForOp (IC_RESULT(ic))));
13576 /* put pointer in DPTR */
13577 aopOp (pp,ic,FALSE,FALSE);
13578 if (AOP_TYPE (pp) == AOP_IMMD) {
13579 emitcode ("mov","dps,#1");
13580 emitcode ("mov", "dptr,%s",
13581 aopGet (pp, 0, TRUE, FALSE, NULL));
13582 emitcode ("mov","dps,#0");
13584 emitcode ("mov","dpl1,%s",
13585 aopGet(pp,0,FALSE,FALSE,DP2_RESULT_REG));
13586 emitcode ("mov","dph1,%s",
13587 aopGet(pp,1,FALSE,FALSE,DP2_RESULT_REG));
13588 emitcode ("mov","dpx1,%s",
13589 aopGet(pp,2,FALSE,FALSE,DP2_RESULT_REG));
13591 freeAsmop (pp, NULL, ic, FALSE);
13593 /* make the call */
13594 emitcode ("lcall","System_%sRTCRegisters",name);
13596 unsavermask(rsave);
13599 /*-----------------------------------------------------------------*/
13600 /* genSystemThreadSleep - */
13601 /*-----------------------------------------------------------------*/
13602 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
13607 assert (nparms==1);
13608 /* save registers that need to be saved */
13609 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13610 ds390_rUmaskForOp (IC_RESULT(ic))));
13613 aopOp(to,ic,FALSE,FALSE);
13614 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
13615 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
13616 emitcode ("push","%s",
13617 aopGet(to,0,FALSE,TRUE,DP2_RESULT_REG));
13618 emitcode ("push","%s",
13619 aopGet(to,1,FALSE,TRUE,DP2_RESULT_REG));
13620 emitcode ("push","%s",
13621 aopGet(to,2,FALSE,TRUE,DP2_RESULT_REG));
13622 emitcode ("push","%s",
13623 aopGet(to,3,FALSE,TRUE,DP2_RESULT_REG));
13624 emitcode ("pop","ar3");
13625 emitcode ("pop","ar2");
13626 emitcode ("pop","ar1");
13627 emitcode ("pop","ar0");
13629 emitcode ("mov","r0,%s",
13630 aopGet(to,0,FALSE,TRUE,DP2_RESULT_REG));
13631 emitcode ("mov","r1,%s",
13632 aopGet(to,1,FALSE,TRUE,DP2_RESULT_REG));
13633 emitcode ("mov","r2,%s",
13634 aopGet(to,2,FALSE,TRUE,DP2_RESULT_REG));
13635 emitcode ("mov","r3,%s",
13636 aopGet(to,3,FALSE,TRUE,DP2_RESULT_REG));
13638 freeAsmop (to, NULL, ic, FALSE);
13640 /* suspend in acc */
13642 aopOp(s,ic,FALSE,FALSE);
13643 emitcode ("mov","a,%s",
13644 aopGet(s,0,FALSE,TRUE,NULL));
13645 freeAsmop (s, NULL, ic, FALSE);
13647 /* make the call */
13648 emitcode ("lcall","System_%s",name);
13650 unsavermask(rsave);
13653 /*-----------------------------------------------------------------*/
13654 /* genSystemThreadResume - */
13655 /*-----------------------------------------------------------------*/
13656 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
13661 assert (nparms==2);
13662 /* save registers that need to be saved */
13663 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13664 ds390_rUmaskForOp (IC_RESULT(ic))));
13670 aopOp(pid,ic,FALSE,FALSE);
13671 emitcode ("mov","r0,%s",
13672 aopGet(pid,0,FALSE,TRUE,DP2_RESULT_REG));
13673 freeAsmop (pid, NULL, ic, FALSE);
13676 aopOp(tid,ic,FALSE,FALSE);
13677 emitcode ("mov","a,%s",
13678 aopGet(tid,0,FALSE,TRUE,DP2_RESULT_REG));
13679 freeAsmop (tid, NULL, ic, FALSE);
13681 emitcode ("lcall","System_ThreadResume");
13683 /* put result into place */
13685 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13686 if (rsym->liveFrom != rsym->liveTo) {
13687 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13688 aopPut(IC_RESULT(ic),"a",0);
13689 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13692 unsavermask(rsave);
13695 /*-----------------------------------------------------------------*/
13696 /* genSystemProcessResume - */
13697 /*-----------------------------------------------------------------*/
13698 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
13703 assert (nparms==1);
13704 /* save registers that need to be saved */
13705 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13706 ds390_rUmaskForOp (IC_RESULT(ic))));
13711 aopOp(pid,ic,FALSE,FALSE);
13712 emitcode ("mov","a,%s",
13713 aopGet(pid,0,FALSE,TRUE,DP2_RESULT_REG));
13714 freeAsmop (pid, NULL, ic, FALSE);
13716 emitcode ("lcall","System_ProcessResume");
13718 unsavermask(rsave);
13721 /*-----------------------------------------------------------------*/
13723 /*-----------------------------------------------------------------*/
13724 static void genSystem (iCode *ic,int nparms,char *name)
13726 assert(nparms == 0);
13728 emitcode ("lcall","System_%s",name);
13731 /*-----------------------------------------------------------------*/
13732 /* genSystemPoll - */
13733 /*-----------------------------------------------------------------*/
13734 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
13739 assert (nparms==1);
13740 /* save registers that need to be saved */
13741 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13742 ds390_rUmaskForOp (IC_RESULT(ic))));
13745 aopOp (fp,ic,FALSE,FALSE);
13746 if (AOP_TYPE (fp) == AOP_IMMD) {
13747 emitcode ("mov", "dptr,%s",
13748 aopGet (fp, 0, TRUE, FALSE, DP2_RESULT_REG));
13749 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
13750 emitcode ("mov","dpl,%s",
13751 aopGet(fp,0,FALSE,FALSE,DP2_RESULT_REG));
13752 emitcode ("mov","dph,%s",
13753 aopGet(fp,1,FALSE,FALSE,DP2_RESULT_REG));
13754 emitcode ("mov","dpx,%s",
13755 aopGet(fp,2,FALSE,FALSE,DP2_RESULT_REG));
13757 freeAsmop (fp, NULL, ic, FALSE);
13759 emitcode ("lcall","System_%sPoll",name);
13761 /* put result into place */
13763 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13764 if (rsym->liveFrom != rsym->liveTo) {
13765 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13766 aopPut(IC_RESULT(ic),"a",0);
13767 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13770 unsavermask(rsave);
13773 /*-----------------------------------------------------------------*/
13774 /* genSystemGetCurrentID - */
13775 /*-----------------------------------------------------------------*/
13776 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
13778 assert (nparms==0);
13780 emitcode ("lcall","System_GetCurrent%sId",name);
13781 /* put result into place */
13783 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13784 if (rsym->liveFrom != rsym->liveTo) {
13785 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13786 aopPut(IC_RESULT(ic),"a",0);
13787 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13792 /*-----------------------------------------------------------------*/
13793 /* genDjnz - generate decrement & jump if not zero instrucion */
13794 /*-----------------------------------------------------------------*/
13796 genDjnz (iCode * ic, iCode * ifx)
13798 symbol *lbl, *lbl1;
13802 /* if the if condition has a false label
13803 then we cannot save */
13804 if (IC_FALSE (ifx))
13807 /* if the minus is not of the form a = a - 1 */
13808 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
13809 !IS_OP_LITERAL (IC_RIGHT (ic)))
13812 if (operandLitValue (IC_RIGHT (ic)) != 1)
13815 /* if the size of this greater than one then no
13817 if (getSize (operandType (IC_RESULT (ic))) > 1)
13820 /* otherwise we can save BIG */
13822 D (emitcode (";", "genDjnz"));
13824 lbl = newiTempLabel (NULL);
13825 lbl1 = newiTempLabel (NULL);
13827 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
13829 if (AOP_NEEDSACC(IC_RESULT(ic)))
13831 /* If the result is accessed indirectly via
13832 * the accumulator, we must explicitly write
13833 * it back after the decrement.
13835 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE, NULL);
13837 if (strcmp(rByte, "a"))
13839 /* Something is hopelessly wrong */
13840 fprintf(stderr, "*** warning: internal error at %s:%d\n",
13841 __FILE__, __LINE__);
13842 /* We can just give up; the generated code will be inefficient,
13843 * but what the hey.
13845 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13848 emitcode ("dec", "%s", rByte);
13849 aopPut (IC_RESULT (ic), rByte, 0);
13850 emitcode ("jnz", "!tlabel", lbl->key + 100);
13852 else if (IS_AOP_PREG (IC_RESULT (ic)))
13854 emitcode ("dec", "%s",
13855 aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL));
13856 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL));
13857 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13858 ifx->generated = 1;
13859 emitcode ("jnz", "!tlabel", lbl->key + 100);
13863 emitcode ("djnz", "%s,!tlabel", aopGet (IC_RESULT (ic), 0, FALSE, TRUE, NULL),
13866 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
13868 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
13871 if (!ifx->generated)
13872 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13873 ifx->generated = 1;
13877 /*-----------------------------------------------------------------*/
13878 /* genReceive - generate code for a receive iCode */
13879 /*-----------------------------------------------------------------*/
13881 genReceive (iCode * ic)
13883 int size = getSize (operandType (IC_RESULT (ic)));
13887 D (emitcode (";", "genReceive"));
13889 if (ic->argreg == 1)
13891 /* first parameter */
13892 if (AOP_IS_STR(IC_RESULT(ic)))
13894 /* Nothing to do: it's already in the proper place. */
13901 useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
13902 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
13903 IS_TRUE_SYMOP (IC_RESULT (ic)));
13906 aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
13909 /* Sanity checking... */
13910 if (AOP_USESDPTR(IC_RESULT(ic)))
13912 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
13913 "genReceive got unexpected DPTR.");
13915 assignResultValue (IC_RESULT (ic), NULL);
13918 else if (ic->argreg > 12)
13919 { /* bit parameters */
13920 if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
13922 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
13923 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
13924 outBitC(IC_RESULT (ic));
13929 /* second receive onwards */
13930 /* this gets a little tricky since unused receives will be
13931 eliminated, we have saved the reg in the type field . and
13932 we use that to figure out which register to use */
13933 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
13934 rb1off = ic->argreg;
13937 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
13940 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13943 /*-----------------------------------------------------------------*/
13944 /* genDummyRead - generate code for dummy read of volatiles */
13945 /*-----------------------------------------------------------------*/
13947 genDummyRead (iCode * ic)
13952 D (emitcode(";", "genDummyRead"));
13954 op = IC_RIGHT (ic);
13955 if (op && IS_SYMOP (op))
13957 aopOp (op, ic, FALSE, FALSE);
13959 /* if the result is a bit */
13960 if (AOP_TYPE (op) == AOP_CRY)
13961 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13964 /* bit variables done */
13966 size = AOP_SIZE (op);
13970 MOVA (aopGet (op, offset, FALSE, FALSE, FALSE));
13975 freeAsmop (op, NULL, ic, TRUE);
13979 if (op && IS_SYMOP (op))
13981 aopOp (op, ic, FALSE, FALSE);
13983 /* if the result is a bit */
13984 if (AOP_TYPE (op) == AOP_CRY)
13985 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13988 /* bit variables done */
13990 size = AOP_SIZE (op);
13994 MOVA (aopGet (op, offset, FALSE, FALSE, FALSE));
13999 freeAsmop (op, NULL, ic, TRUE);
14003 /*-----------------------------------------------------------------*/
14004 /* genCritical - generate code for start of a critical sequence */
14005 /*-----------------------------------------------------------------*/
14007 genCritical (iCode *ic)
14009 symbol *tlbl = newiTempLabel (NULL);
14011 D (emitcode(";", "genCritical"));
14013 if (IC_RESULT (ic))
14015 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
14016 aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
14017 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
14018 aopPut (IC_RESULT (ic), zero, 0);
14020 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
14024 emitcode ("setb", "c");
14025 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
14026 emitcode ("clr", "c");
14028 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
14032 /*-----------------------------------------------------------------*/
14033 /* genEndCritical - generate code for end of a critical sequence */
14034 /*-----------------------------------------------------------------*/
14036 genEndCritical (iCode *ic)
14038 D(emitcode(";", "genEndCritical"));
14042 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
14043 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
14045 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
14046 emitcode ("mov", "ea,c");
14050 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE, FALSE));
14051 emitcode ("rrc", "a");
14052 emitcode ("mov", "ea,c");
14054 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
14058 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
14059 emitcode ("mov", "ea,c");
14065 /*-----------------------------------------------------------------*/
14066 /* genBuiltIn - calls the appropriate function to generating code */
14067 /* for a built in function */
14068 /*-----------------------------------------------------------------*/
14069 static void genBuiltIn (iCode *ic)
14071 operand *bi_parms[MAX_BUILTIN_ARGS];
14076 /* get all the arguments for a built in function */
14077 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
14079 /* which function is it */
14080 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
14081 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
14082 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
14083 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
14084 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
14085 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
14086 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
14087 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
14088 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
14089 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
14090 genMemsetX(bi_iCode,nbi_parms,bi_parms);
14091 } else if (strcmp(bif->name,"__builtin_inp")==0) {
14092 genInp(bi_iCode,nbi_parms,bi_parms);
14093 } else if (strcmp(bif->name,"__builtin_outp")==0) {
14094 genOutp(bi_iCode,nbi_parms,bi_parms);
14095 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
14096 genSwapW(bi_iCode,nbi_parms,bi_parms);
14097 /* JavaNative builtIns */
14098 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
14099 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
14100 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
14101 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
14102 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
14103 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
14104 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
14105 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
14106 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
14107 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
14108 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
14109 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
14110 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
14111 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
14112 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
14113 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
14114 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
14115 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
14116 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
14117 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
14118 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
14119 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
14120 } else if (strcmp(bif->name,"MM_Malloc")==0) {
14121 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
14122 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
14123 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
14124 } else if (strcmp(bif->name,"MM_Free")==0) {
14125 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
14126 } else if (strcmp(bif->name,"MM_Deref")==0) {
14127 genMMDeref(bi_iCode,nbi_parms,bi_parms);
14128 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
14129 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
14130 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
14131 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
14132 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
14133 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
14134 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
14135 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
14136 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
14137 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
14138 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
14139 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
14140 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
14141 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
14142 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
14143 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
14144 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
14145 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
14146 } else if (strcmp(bif->name,"System_SaveThread")==0) {
14147 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
14148 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
14149 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
14150 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
14151 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
14152 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
14153 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
14154 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
14155 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
14156 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
14157 genSystem(bi_iCode,nbi_parms,"ProcessYield");
14158 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
14159 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
14160 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
14161 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
14162 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
14163 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
14164 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
14165 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
14166 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
14167 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
14169 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
14175 /*-----------------------------------------------------------------*/
14176 /* gen390Code - generate code for Dallas 390 based controllers */
14177 /*-----------------------------------------------------------------*/
14179 gen390Code (iCode * lic)
14184 _G.currentFunc = NULL;
14185 lineHead = lineCurr = NULL;
14186 dptrn[1][0] = "dpl1";
14187 dptrn[1][1] = "dph1";
14188 dptrn[1][2] = "dpx1";
14190 if (options.model == MODEL_FLAT24) {
14191 fReturnSizeDS390 = 5;
14192 fReturn = fReturn24;
14194 fReturnSizeDS390 = 4;
14195 fReturn = fReturn16;
14196 options.stack10bit=0;
14199 /* print the allocation information */
14200 if (allocInfo && currFunc)
14201 printAllocInfo (currFunc, codeOutBuf);
14203 /* if debug information required */
14204 if (options.debug && currFunc)
14206 debugFile->writeFunction (currFunc, lic);
14208 /* stack pointer name */
14209 if (options.useXstack)
14215 for (ic = lic; ic; ic = ic->next)
14217 _G.current_iCode = ic;
14219 if (ic->lineno && cln != ic->lineno)
14223 debugFile->writeCLine (ic);
14225 if (!options.noCcodeInAsm) {
14226 emitcode (";", "%s:%d: %s", ic->filename, ic->lineno,
14227 printCLine(ic->filename, ic->lineno));
14231 if (options.iCodeInAsm) {
14232 char *iLine = printILine(ic);
14233 emitcode(";", "ic:%d: %s", ic->key, iLine);
14236 /* if the result is marked as
14237 spilt and rematerializable or code for
14238 this has already been generated then
14240 if (resultRemat (ic) || ic->generated)
14243 /* depending on the operation */
14263 /* IPOP happens only when trying to restore a
14264 spilt live range, if there is an ifx statement
14265 following this pop then the if statement might
14266 be using some of the registers being popped which
14267 would destory the contents of the register so
14268 we need to check for this condition and handle it */
14270 ic->next->op == IFX &&
14271 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
14272 genIfx (ic->next, ic);
14290 genEndFunction (ic);
14310 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
14327 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
14331 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
14338 /* note these two are xlated by algebraic equivalence
14339 during parsing SDCC.y */
14340 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
14341 "got '>=' or '<=' shouldn't have come here");
14345 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
14357 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
14361 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
14365 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
14389 genRightShift (ic);
14392 case GET_VALUE_AT_ADDRESS:
14394 hasInc (IC_LEFT (ic), ic,
14395 getSize (operandType (IC_RESULT (ic)))));
14399 if (POINTER_SET (ic))
14401 hasInc (IC_RESULT (ic), ic,
14402 getSize (operandType (IC_RIGHT (ic)))));
14428 if (ic->builtinSEND)
14431 addSet (&_G.sendSet, ic);
14434 case DUMMY_READ_VOLATILE:
14443 genEndCritical (ic);
14450 #if 0 // obsolete, and buggy for != xdata
14457 /* This should never happen, right? */
14458 fprintf(stderr, "*** Probable error: unsupported op 0x%x (%c) in %s @ %d\n",
14459 ic->op, ic->op, __FILE__, __LINE__);
14465 /* now we are ready to call the
14466 peep hole optimizer */
14467 if (!options.nopeep)
14468 peepHole (&lineHead);
14470 /* now do the actual printing */
14471 printLine (lineHead, codeOutBuf);