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, iCode * ic)
2464 int nPushed = _G.r0Pushed + _G.r1Pushed;
2466 aopOp (oper, ic, FALSE, FALSE);
2468 if (nPushed != _G.r0Pushed + _G.r1Pushed)
2470 while (offset < size)
2472 char *l = aopGet (oper, offset, FALSE, TRUE, NULL);
2473 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2475 freeAsmop (oper, NULL, ic, TRUE);
2477 while (offset < size)
2479 emitcode ("push", "%s", fReturn[offset++]);
2484 _startLazyDPSEvaluation ();
2487 char *l = aopGet (oper, offset++, FALSE, TRUE, NULL);
2488 if (AOP_TYPE (oper) != AOP_REG &&
2489 AOP_TYPE (oper) != AOP_DIR &&
2493 emitcode ("push", "acc");
2497 emitcode ("push", "%s", l);
2500 _endLazyDPSEvaluation ();
2501 freeAsmop (oper, NULL, ic, TRUE);
2504 /*-----------------------------------------------------------------*/
2505 /* assignResultValue - also indicates if acc is in use afterwards */
2506 /*-----------------------------------------------------------------*/
2508 assignResultValue (operand * oper, operand * func)
2511 unsigned size = AOP_SIZE (oper);
2512 bool accuse = FALSE;
2513 bool pushedA = FALSE;
2515 if (func && IS_BIT (OP_SYM_ETYPE (func)))
2521 if (size == fReturnSizeDS390)
2523 /* I don't think this case can ever happen... */
2524 /* ACC is the last part of this. If writing the result
2525 * uses ACC, we must preserve it.
2527 if (AOP_NEEDSACC(oper))
2529 emitcode(";", "assignResultValue special case for ACC.");
2530 emitcode("push", "acc");
2536 _startLazyDPSEvaluation ();
2539 accuse |= aopPut (oper, fReturn[offset], offset);
2542 _endLazyDPSEvaluation ();
2546 emitcode ("pop", "acc");
2547 accuse |= aopPut (oper, "a", offset);
2553 /*-----------------------------------------------------------------*/
2554 /* genXpush - pushes onto the external stack */
2555 /*-----------------------------------------------------------------*/
2557 genXpush (iCode * ic)
2559 asmop *aop = newAsmop (0);
2561 int size, offset = 0;
2563 D (emitcode (";", "genXpush"));
2565 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2566 r = getFreePtr (ic, &aop, FALSE);
2568 size = AOP_SIZE (IC_LEFT (ic));
2572 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
2573 emitcode ("mov", "%s,_spx", r->name);
2574 emitcode ("inc", "_spx"); // allocate space first
2575 emitcode ("movx", "@%s,a", r->name);
2579 // allocate space first
2580 emitcode ("mov", "%s,_spx", r->name);
2582 emitcode ("add", "a,#%d", size);
2583 emitcode ("mov", "_spx,a");
2585 _startLazyDPSEvaluation ();
2588 MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE, NULL));
2589 emitcode ("movx", "@%s,a", r->name);
2590 emitcode ("inc", "%s", r->name);
2592 _endLazyDPSEvaluation ();
2595 freeAsmop (NULL, aop, ic, TRUE);
2596 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2599 /*-----------------------------------------------------------------*/
2600 /* genIpush - generate code for pushing this gets a little complex */
2601 /*-----------------------------------------------------------------*/
2603 genIpush (iCode * ic)
2605 int size, offset = 0;
2609 D (emitcode (";", "genIpush"));
2611 /* if this is not a parm push : ie. it is spill push
2612 and spill push is always done on the local stack */
2616 /* and the item is spilt then do nothing */
2617 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2620 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2621 size = AOP_SIZE (IC_LEFT (ic));
2622 /* push it on the stack */
2623 _startLazyDPSEvaluation ();
2626 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE, NULL);
2632 emitcode ("push", "%s", l);
2634 _endLazyDPSEvaluation ();
2638 /* this is a parameter push: in this case we call
2639 the routine to find the call and save those
2640 registers that need to be saved */
2643 /* if use external stack then call the external
2644 stack pushing routine */
2645 if (options.useXstack)
2651 /* then do the push */
2652 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2654 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2655 size = AOP_SIZE (IC_LEFT (ic));
2657 _startLazyDPSEvaluation ();
2660 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE, NULL);
2661 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2662 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2665 if (strcmp (l, prev) || *l == '@')
2667 emitcode ("push", "acc");
2671 emitcode ("push", "%s", l);
2675 _endLazyDPSEvaluation ();
2677 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2680 /*-----------------------------------------------------------------*/
2681 /* genIpop - recover the registers: can happen only for spilling */
2682 /*-----------------------------------------------------------------*/
2684 genIpop (iCode * ic)
2688 D (emitcode (";", "genIpop"));
2690 /* if the temp was not pushed then */
2691 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2694 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2695 size = AOP_SIZE (IC_LEFT (ic));
2696 offset = (size - 1);
2697 _startLazyDPSEvaluation ();
2700 emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2701 FALSE, TRUE, NULL));
2703 _endLazyDPSEvaluation ();
2705 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2708 /*-----------------------------------------------------------------*/
2709 /* saveRBank - saves an entire register bank on the stack */
2710 /*-----------------------------------------------------------------*/
2712 saveRBank (int bank, iCode * ic, bool pushPsw)
2715 int count = 8 + (ds390_nBitRegs/8) + (pushPsw ? 1 : 0);
2719 if (options.useXstack)
2723 /* Assume r0 is available for use. */
2724 r = REG_WITH_INDEX (R0_IDX);;
2729 r = getFreePtr (ic, &aop, FALSE);
2731 // allocate space first
2732 emitcode ("mov", "%s,_spx", r->name);
2734 emitcode ("add", "a,#%d", count);
2735 emitcode ("mov", "_spx,a");
2738 for (i = 0; i < 8; i++) /* only R0-R7 needs saving */
2740 if (options.useXstack)
2742 emitcode ("mov", "a,(%s+%d)",
2743 regs390[i].base, 8 * bank + regs390[i].offset);
2744 emitcode ("movx", "@%s,a", r->name);
2746 emitcode ("inc", "%s", r->name);
2749 emitcode ("push", "(%s+%d)",
2750 regs390[i].base, 8 * bank + regs390[i].offset);
2753 if (ds390_nBitRegs > 0)
2755 if (options.useXstack)
2757 emitcode ("mov", "a,bits");
2758 emitcode ("movx", "@%s,a", r->name);
2760 emitcode ("inc", "%s", r->name);
2764 emitcode ("push", "bits");
2771 if (options.useXstack)
2773 emitcode ("mov", "a,psw");
2774 emitcode ("movx", "@%s,a", r->name);
2778 emitcode ("push", "psw");
2781 emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2786 freeAsmop (NULL, aop, ic, TRUE);
2795 /*-----------------------------------------------------------------*/
2796 /* unsaveRBank - restores the register bank from stack */
2797 /*-----------------------------------------------------------------*/
2799 unsaveRBank (int bank, iCode * ic, bool popPsw)
2805 if (options.useXstack)
2809 /* Assume r0 is available for use. */
2810 r = REG_WITH_INDEX (R0_IDX);;
2815 r = getFreePtr (ic, &aop, FALSE);
2817 emitcode ("mov", "%s,_spx", r->name);
2822 if (options.useXstack)
2824 emitcode ("dec", "%s", r->name);
2825 emitcode ("movx", "a,@%s", r->name);
2826 emitcode ("mov", "psw,a");
2830 emitcode ("pop", "psw");
2834 if (ds390_nBitRegs > 0)
2836 if (options.useXstack)
2838 emitcode ("dec", "%s", r->name);
2839 emitcode ("movx", "a,@%s", r->name);
2840 emitcode ("mov", "bits,a");
2844 emitcode ("pop", "bits");
2848 for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2850 if (options.useXstack)
2852 emitcode ("dec", "%s", r->name);
2853 emitcode ("movx", "a,@%s", r->name);
2854 emitcode ("mov", "(%s+%d),a",
2855 regs390[i].base, 8 * bank + regs390[i].offset);
2859 emitcode ("pop", "(%s+%d)",
2860 regs390[i].base, 8 * bank + regs390[i].offset);
2864 if (options.useXstack)
2866 emitcode ("mov", "_spx,%s", r->name);
2871 freeAsmop (NULL, aop, ic, TRUE);
2875 /*-----------------------------------------------------------------*/
2876 /* genSend - gen code for SEND */
2877 /*-----------------------------------------------------------------*/
2878 static void genSend(set *sendSet)
2883 static int rb1_count = 0;
2885 /* first we do all bit parameters */
2886 for (sic = setFirstItem (sendSet); sic;
2887 sic = setNextItem (sendSet))
2889 if (sic->argreg > 12)
2891 int bit = sic->argreg-13;
2893 aopOp (IC_LEFT (sic), sic, FALSE,
2894 (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2896 /* if left is a literal then
2897 we know what the value is */
2898 if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2900 if (((int) operandLitValue (IC_LEFT (sic))))
2901 emitcode ("setb", "b[%d]", bit);
2903 emitcode ("clr", "b[%d]", bit);
2905 else if (AOP_TYPE (IC_LEFT (sic)) == AOP_CRY)
2907 char *l = AOP (IC_LEFT (sic))->aopu.aop_dir;
2908 if (strcmp (l, "c"))
2909 emitcode ("mov", "c,%s", l);
2910 emitcode ("mov", "b[%d],c", bit);
2915 toBoolean (IC_LEFT (sic));
2916 /* set C, if a >= 1 */
2917 emitcode ("add", "a,#0xff");
2918 emitcode ("mov", "b[%d],c", bit);
2923 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2929 saveRegisters (setFirstItem (sendSet));
2930 emitcode ("mov", "bits,b");
2933 /* then we do all other parameters */
2934 for (sic = setFirstItem (sendSet); sic;
2935 sic = setNextItem (sendSet))
2937 if (sic->argreg <= 12)
2939 int size, offset = 0;
2941 size = getSize (operandType (IC_LEFT (sic)));
2942 D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2943 if (sendCount == 0) { /* first parameter */
2944 // we know that dpl(hxb) is the result, so
2946 _startLazyDPSEvaluation ();
2948 aopOp (IC_LEFT (sic), sic, FALSE,
2949 (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2951 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2955 char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE, NULL);
2956 if (strcmp (l, fReturn[offset]))
2958 emitcode ("mov", "%s,%s", fReturn[offset], l);
2962 _endLazyDPSEvaluation ();
2963 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2965 } else { /* if more parameter in registers */
2966 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2968 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (IC_LEFT (sic), offset++,
2969 FALSE, FALSE, NULL));
2971 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2979 adjustEsp(const char *reg)
2981 emitcode ("anl","%s,#3", reg);
2982 if (TARGET_IS_DS400)
2984 emitcode ("orl","%s,#!constbyte",
2986 (options.stack_loc >> 8) & 0xff);
2990 /*-----------------------------------------------------------------*/
2991 /* selectRegBank - emit code to select the register bank */
2992 /*-----------------------------------------------------------------*/
2994 selectRegBank (short bank, bool keepFlags)
2996 /* if f.e. result is in carry */
2999 emitcode ("anl", "psw,#0xE7");
3001 emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
3005 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
3009 /*-----------------------------------------------------------------*/
3010 /* genCall - generates a call statement */
3011 /*-----------------------------------------------------------------*/
3013 genCall (iCode * ic)
3017 bool restoreBank = FALSE;
3018 bool swapBanks = FALSE;
3019 bool accuse = FALSE;
3020 bool accPushed = FALSE;
3021 bool resultInF0 = FALSE;
3022 bool assignResultGenerated = FALSE;
3024 D (emitcode (";", "genCall"));
3026 /* if we are calling a not _naked function that is not using
3027 the same register bank then we need to save the
3028 destination registers on the stack */
3029 dtype = operandType (IC_LEFT (ic));
3030 etype = getSpec(dtype);
3031 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
3032 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
3033 IFFUNC_ISISR (currFunc->type))
3037 /* This is unexpected; the bank should have been saved in
3040 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
3046 /* if caller saves & we have not saved then */
3050 /* if send set is not empty then assign */
3051 /* We've saved all the registers we care about;
3052 * therefore, we may clobber any register not used
3053 * in the calling convention (i.e. anything not in
3058 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
3059 genSend(reverseSet(_G.sendSet));
3061 genSend(_G.sendSet);
3068 emitcode ("mov", "psw,#!constbyte",
3069 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3073 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
3074 OP_SYMBOL (IC_LEFT (ic))->rname :
3075 OP_SYMBOL (IC_LEFT (ic))->name));
3079 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
3082 /* if we need assign a result value */
3083 if ((IS_ITEMP (IC_RESULT (ic)) &&
3084 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3085 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3086 OP_SYMBOL (IC_RESULT (ic))->accuse ||
3087 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3088 IS_TRUE_SYMOP (IC_RESULT (ic)))
3090 if (isOperandInFarSpace (IC_RESULT (ic))
3091 && getSize (operandType (IC_RESULT (ic))) <= 2)
3093 int size = getSize (operandType (IC_RESULT (ic)));
3094 bool pushedB = FALSE;
3096 /* Special case for 1 or 2 byte return in far space. */
3101 emitcode ("mov", "b,%s", fReturn[1]);
3105 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
3110 aopPut (IC_RESULT (ic), "a", 0);
3114 aopPut (IC_RESULT (ic), "b", 1);
3116 assignResultGenerated = TRUE;
3117 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3121 bool pushedB = pushB ();
3122 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
3125 accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3126 assignResultGenerated = TRUE;
3127 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3131 /* adjust the stack for parameters if required */
3135 if (options.stack10bit) {
3136 if (ic->parmBytes <= 10) {
3137 emitcode(";","stack adjustment for parms");
3138 for (i=0; i < ic->parmBytes ; i++) {
3139 emitcode("pop","acc");
3143 emitcode ("clr","c");
3144 emitcode ("mov","a,sp");
3145 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
3146 emitcode ("mov","sp,a");
3147 emitcode ("mov","a,esp");
3149 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
3150 emitcode ("mov","esp,a");
3154 if (ic->parmBytes > 3)
3158 emitcode ("push", "acc");
3161 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3162 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3163 !assignResultGenerated)
3165 emitcode ("mov", "F0,c");
3169 emitcode ("mov", "a,%s", spname);
3170 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
3171 emitcode ("mov", "%s,a", spname);
3173 /* unsaveRegisters from xstack needs acc, but */
3174 /* unsaveRegisters from stack needs this popped */
3175 if (accPushed && !options.useXstack)
3177 emitcode ("pop", "acc");
3182 for (i = 0; i < ic->parmBytes; i++)
3183 emitcode ("dec", "%s", spname);
3187 /* if we had saved some registers then unsave them */
3188 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3190 if (accuse && !accPushed && options.useXstack)
3192 /* xstack needs acc, but doesn't touch normal stack */
3193 emitcode ("push", "acc");
3196 unsaveRegisters (ic);
3199 /* if register bank was saved then pop them */
3201 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
3203 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
3206 emitcode ("mov", "c,F0");
3208 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
3209 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3210 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3214 emitcode ("pop", "acc");
3217 /*-----------------------------------------------------------------*/
3218 /* genPcall - generates a call by pointer statement */
3219 /*-----------------------------------------------------------------*/
3221 genPcall (iCode * ic)
3225 symbol *rlbl = newiTempLabel (NULL);
3226 bool restoreBank=FALSE;
3227 bool resultInF0 = FALSE;
3229 D (emitcode (";", "genPcall"));
3231 dtype = operandType (IC_LEFT (ic))->next;
3232 etype = getSpec(dtype);
3233 /* if caller saves & we have not saved then */
3237 /* if we are calling a not _naked function that is not using
3238 the same register bank then we need to save the
3239 destination registers on the stack */
3240 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
3241 IFFUNC_ISISR (currFunc->type) &&
3242 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
3243 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3247 /* push the return address on to the stack */
3248 emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
3249 emitcode ("push", "acc");
3250 emitcode ("mov", "a,#!hil", (rlbl->key + 100));
3251 emitcode ("push", "acc");
3253 if (options.model == MODEL_FLAT24)
3255 emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
3256 emitcode ("push", "acc");
3259 /* now push the function address */
3260 pushSide (IC_LEFT (ic), FPTRSIZE, ic);
3262 /* if send set is not empty then assign */
3265 genSend(reverseSet(_G.sendSet));
3270 emitcode ("ret", "");
3274 /* if we need assign a result value */
3275 if ((IS_ITEMP (IC_RESULT (ic)) &&
3276 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3277 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3278 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3279 IS_TRUE_SYMOP (IC_RESULT (ic)))
3283 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
3286 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3288 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3291 /* adjust the stack for parameters if required */
3295 if (options.stack10bit) {
3296 if (ic->parmBytes <= 10) {
3297 emitcode(";","stack adjustment for parms");
3298 for (i=0; i < ic->parmBytes ; i++) {
3299 emitcode("pop","acc");
3302 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3303 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3305 emitcode ("mov", "F0,c");
3310 emitcode ("clr","c");
3311 emitcode ("mov","a,sp");
3312 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
3313 emitcode ("mov","sp,a");
3314 emitcode ("mov","a,esp");
3316 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
3317 emitcode ("mov","esp,a");
3321 if (ic->parmBytes > 3) {
3322 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3323 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3325 emitcode ("mov", "F0,c");
3329 emitcode ("mov", "a,%s", spname);
3330 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
3331 emitcode ("mov", "%s,a", spname);
3334 for (i = 0; i < ic->parmBytes; i++)
3335 emitcode ("dec", "%s", spname);
3338 /* if register bank was saved then unsave them */
3340 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3342 /* if we had saved some registers then unsave them */
3344 unsaveRegisters (ic);
3346 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3349 emitcode ("mov", "c,F0");
3351 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
3352 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3353 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3357 /*-----------------------------------------------------------------*/
3358 /* resultRemat - result is rematerializable */
3359 /*-----------------------------------------------------------------*/
3361 resultRemat (iCode * ic)
3363 if (SKIP_IC (ic) || ic->op == IFX)
3366 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3368 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3369 if (sym->remat && !POINTER_SET (ic))
3376 /*-----------------------------------------------------------------*/
3377 /* inExcludeList - return 1 if the string is in exclude Reg list */
3378 /*-----------------------------------------------------------------*/
3380 regsCmp(void *p1, void *p2)
3382 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3386 inExcludeList (char *s)
3388 const char *p = setFirstItem(options.excludeRegsSet);
3390 if (p == NULL || STRCASECMP(p, "none") == 0)
3394 return isinSetWith(options.excludeRegsSet, s, regsCmp);
3397 /*-----------------------------------------------------------------*/
3398 /* genFunction - generated code for function entry */
3399 /*-----------------------------------------------------------------*/
3401 genFunction (iCode * ic)
3403 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3405 bool switchedPSW = FALSE;
3406 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3408 D (emitcode (";", "genFunction"));
3411 /* create the function header */
3412 emitcode (";", "-----------------------------------------");
3413 emitcode (";", " function %s", sym->name);
3414 emitcode (";", "-----------------------------------------");
3416 emitcode ("", "%s:", sym->rname);
3417 lineCurr->isLabel = 1;
3418 ftype = operandType (IC_LEFT (ic));
3419 _G.currentFunc = sym;
3421 if (IFFUNC_ISNAKED(ftype))
3423 emitcode(";", "naked function: no prologue.");
3427 if (options.stack_probe)
3428 emitcode ("lcall","__stack_probe");
3430 /* here we need to generate the equates for the
3431 register bank if required */
3432 if (FUNC_REGBANK (ftype) != rbank)
3436 rbank = FUNC_REGBANK (ftype);
3437 for (i = 0; i < ds390_nRegs; i++)
3439 if (regs390[i].print) {
3440 if (strcmp (regs390[i].base, "0") == 0)
3441 emitcode ("", "%s !equ !constbyte",
3443 8 * rbank + regs390[i].offset);
3445 emitcode ("", "%s !equ %s + !constbyte",
3448 8 * rbank + regs390[i].offset);
3453 /* if this is an interrupt service routine then
3454 save acc, b, dpl, dph */
3455 if (IFFUNC_ISISR (sym->type))
3457 if (!inExcludeList ("acc"))
3458 emitcode ("push", "acc");
3459 if (!inExcludeList ("b"))
3460 emitcode ("push", "b");
3461 if (!inExcludeList ("dpl"))
3462 emitcode ("push", "dpl");
3463 if (!inExcludeList ("dph"))
3464 emitcode ("push", "dph");
3465 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3467 emitcode ("push", "dpx");
3468 /* Make sure we're using standard DPTR */
3469 emitcode ("push", "dps");
3470 emitcode ("mov", "dps,#0");
3471 if (options.stack10bit)
3473 /* This ISR could conceivably use DPTR2. Better save it. */
3474 emitcode ("push", "dpl1");
3475 emitcode ("push", "dph1");
3476 emitcode ("push", "dpx1");
3477 emitcode ("push", DP2_RESULT_REG);
3480 /* if this isr has no bank i.e. is going to
3481 run with bank 0 , then we need to save more
3483 if (!FUNC_REGBANK (sym->type))
3487 /* if this function does not call any other
3488 function then we can be economical and
3489 save only those registers that are used */
3490 if (!IFFUNC_HASFCALL(sym->type))
3492 /* if any registers used */
3495 bool bits_pushed = FALSE;
3496 /* save the registers used */
3497 for (i = 0; i < sym->regsUsed->size; i++)
3499 if (bitVectBitValue (sym->regsUsed, i))
3500 bits_pushed = pushReg (i, bits_pushed);
3506 /* this function has a function call. We cannot
3507 determine register usage so we will have to push the
3509 saveRBank (0, ic, FALSE);
3510 if (options.parms_in_bank1) {
3511 for (i=0; i < 8 ; i++ ) {
3512 emitcode ("push","%s",rb1regs[i]);
3519 /* This ISR uses a non-zero bank.
3521 * We assume that the bank is available for our
3524 * However, if this ISR calls a function which uses some
3525 * other bank, we must save that bank entirely.
3527 unsigned long banksToSave = 0;
3529 if (IFFUNC_HASFCALL(sym->type))
3532 #define MAX_REGISTER_BANKS 4
3537 for (i = ic; i; i = i->next)
3539 if (i->op == ENDFUNCTION)
3541 /* we got to the end OK. */
3549 dtype = operandType (IC_LEFT(i));
3551 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3553 /* Mark this bank for saving. */
3554 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3556 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3560 banksToSave |= (1 << FUNC_REGBANK(dtype));
3563 /* And note that we don't need to do it in
3571 /* This is a mess; we have no idea what
3572 * register bank the called function might
3575 * The only thing I can think of to do is
3576 * throw a warning and hope.
3578 werror(W_FUNCPTR_IN_USING_ISR);
3582 if (banksToSave && options.useXstack)
3584 /* Since we aren't passing it an ic,
3585 * saveRBank will assume r0 is available to abuse.
3587 * So switch to our (trashable) bank now, so
3588 * the caller's R0 isn't trashed.
3590 emitcode ("push", "psw");
3591 emitcode ("mov", "psw,#!constbyte",
3592 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3596 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3598 if (banksToSave & (1 << ix))
3600 saveRBank(ix, NULL, FALSE);
3604 // TODO: this needs a closer look
3605 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3610 /* if callee-save to be used for this function
3611 then save the registers being used in this function */
3612 if (IFFUNC_CALLEESAVES(sym->type))
3616 /* if any registers used */
3619 bool bits_pushed = FALSE;
3620 /* save the registers used */
3621 for (i = 0; i < sym->regsUsed->size; i++)
3623 if (bitVectBitValue (sym->regsUsed, i))
3625 bits_pushed = pushReg (i, bits_pushed);
3633 /* set the register bank to the desired value */
3634 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3637 emitcode ("push", "psw");
3638 emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3642 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3643 if (options.stack10bit) {
3644 emitcode ("push","_bpx");
3645 emitcode ("push","_bpx+1");
3646 emitcode ("mov","_bpx,%s",spname);
3647 emitcode ("mov","_bpx+1,esp");
3648 adjustEsp("_bpx+1");
3650 if (options.useXstack)
3652 emitcode ("mov", "r0,%s", spname);
3653 emitcode ("mov", "a,_bp");
3654 emitcode ("movx", "@r0,a");
3655 emitcode ("inc", "%s", spname);
3657 /* set up the stack */
3658 emitcode ("push", "_bp"); /* save the callers stack */
3660 emitcode ("mov", "_bp,%s", spname);
3664 /* adjust the stack for the function */
3667 if (options.stack10bit) {
3668 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
3669 assert (sym->recvSize <= 4);
3670 if (sym->stack <= 8) {
3671 while (i--) emitcode ("push","acc");
3674 emitcode ("mov","a,sp");
3675 emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3676 emitcode ("mov","sp,a");
3677 emitcode ("mov","a,esp");
3679 emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3680 emitcode ("mov","esp,a");
3685 werror (W_STACK_OVERFLOW, sym->name);
3687 if (i > 3 && sym->recvSize < 4) {
3689 emitcode ("mov", "a,sp");
3690 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3691 emitcode ("mov", "sp,a");
3695 emitcode ("inc", "sp");
3702 emitcode ("mov", "a,_spx");
3703 emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3704 emitcode ("mov", "_spx,a");
3707 /* if critical function then turn interrupts off */
3708 if (IFFUNC_ISCRITICAL (ftype))
3710 symbol *tlbl = newiTempLabel (NULL);
3711 emitcode ("setb", "c");
3712 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3713 emitcode ("clr", "c");
3715 emitcode ("push", "psw"); /* save old ea via c in psw */
3719 /*-----------------------------------------------------------------*/
3720 /* genEndFunction - generates epilogue for functions */
3721 /*-----------------------------------------------------------------*/
3723 genEndFunction (iCode * ic)
3725 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3726 lineNode *lnp = lineCurr;
3728 bitVect *regsUsedPrologue;
3729 bitVect *regsUnneeded;
3732 D (emitcode (";", "genEndFunction"));
3734 _G.currentFunc = NULL;
3735 if (IFFUNC_ISNAKED(sym->type))
3737 emitcode(";", "naked function: no epilogue.");
3738 if (options.debug && currFunc)
3739 debugFile->writeEndFunction (currFunc, ic, 0);
3743 if (IFFUNC_ISCRITICAL (sym->type))
3745 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3747 emitcode ("rlc", "a"); /* save c in a */
3748 emitcode ("pop", "psw"); /* restore ea via c in psw */
3749 emitcode ("mov", "ea,c");
3750 emitcode ("rrc", "a"); /* restore c from a */
3754 emitcode ("pop", "psw"); /* restore ea via c in psw */
3755 emitcode ("mov", "ea,c");
3759 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3760 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3762 if (options.stack10bit) {
3764 emitcode ("mov", "sp,_bpx", spname);
3765 emitcode ("mov", "esp,_bpx+1", spname);
3768 emitcode ("mov", "%s,_bp", spname);
3772 /* if use external stack but some variables were
3773 added to the local stack then decrement the
3775 if (options.useXstack && sym->stack) {
3776 emitcode ("mov", "a,sp");
3777 emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3778 emitcode ("mov", "sp,a");
3782 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3783 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3785 if (options.useXstack) {
3786 emitcode ("mov", "r0,%s", spname);
3787 emitcode ("movx", "a,@r0");
3788 emitcode ("mov", "_bp,a");
3789 emitcode ("dec", "%s", spname);
3791 if (options.stack10bit) {
3792 emitcode ("pop", "_bpx+1");
3793 emitcode ("pop", "_bpx");
3795 emitcode ("pop", "_bp");
3800 /* restore the register bank */
3801 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3803 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3804 || !options.useXstack)
3806 /* Special case of ISR using non-zero bank with useXstack
3809 emitcode ("pop", "psw");
3813 if (IFFUNC_ISISR (sym->type))
3816 /* now we need to restore the registers */
3817 /* if this isr has no bank i.e. is going to
3818 run with bank 0 , then we need to save more
3820 if (!FUNC_REGBANK (sym->type))
3823 /* if this function does not call any other
3824 function then we can be economical and
3825 save only those registers that are used */
3826 if (!IFFUNC_HASFCALL(sym->type))
3828 /* if any registers used */
3831 bool bits_popped = FALSE;
3832 /* save the registers used */
3833 for (i = sym->regsUsed->size; i >= 0; i--)
3835 if (bitVectBitValue (sym->regsUsed, i))
3836 bits_popped = popReg (i, bits_popped);
3842 /* this function has a function call. We cannot
3843 determine register usage so we will have to pop the
3845 if (options.parms_in_bank1) {
3846 for (i = 7 ; i >= 0 ; i-- ) {
3847 emitcode ("pop","%s",rb1regs[i]);
3850 unsaveRBank (0, ic, FALSE);
3855 /* This ISR uses a non-zero bank.
3857 * Restore any register banks saved by genFunction
3860 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3863 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3865 if (savedBanks & (1 << ix))
3867 unsaveRBank(ix, NULL, FALSE);
3871 if (options.useXstack)
3873 /* Restore bank AFTER calling unsaveRBank,
3874 * since it can trash r0.
3876 emitcode ("pop", "psw");
3880 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3882 if (options.stack10bit)
3884 emitcode ("pop", DP2_RESULT_REG);
3885 emitcode ("pop", "dpx1");
3886 emitcode ("pop", "dph1");
3887 emitcode ("pop", "dpl1");
3889 emitcode ("pop", "dps");
3890 emitcode ("pop", "dpx");
3892 if (!inExcludeList ("dph"))
3893 emitcode ("pop", "dph");
3894 if (!inExcludeList ("dpl"))
3895 emitcode ("pop", "dpl");
3896 if (!inExcludeList ("b"))
3897 emitcode ("pop", "b");
3898 if (!inExcludeList ("acc"))
3899 emitcode ("pop", "acc");
3901 /* if debug then send end of function */
3902 if (options.debug && currFunc)
3904 debugFile->writeEndFunction (currFunc, ic, 1);
3907 emitcode ("reti", "");
3911 if (IFFUNC_CALLEESAVES(sym->type))
3915 /* if any registers used */
3918 /* save the registers used */
3919 for (i = sym->regsUsed->size; i >= 0; i--)
3921 if (bitVectBitValue (sym->regsUsed, i))
3922 emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
3927 /* if debug then send end of function */
3928 if (options.debug && currFunc)
3930 debugFile->writeEndFunction (currFunc, ic, 1);
3933 emitcode ("ret", "");
3936 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3939 /* If this was an interrupt handler using bank 0 that called another */
3940 /* function, then all registers must be saved; nothing to optimized. */
3941 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3942 && !FUNC_REGBANK(sym->type))
3945 /* There are no push/pops to optimize if not callee-saves or ISR */
3946 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3949 /* If there were stack parameters, we cannot optimize without also */
3950 /* fixing all of the stack offsets; this is too dificult to consider. */
3951 if (FUNC_HASSTACKPARM(sym->type))
3954 /* Compute the registers actually used */
3955 regsUsed = newBitVect (ds390_nRegs);
3956 regsUsedPrologue = newBitVect (ds390_nRegs);
3959 if (lnp->ic && lnp->ic->op == FUNCTION)
3960 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3962 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3964 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3965 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3972 if (bitVectBitValue (regsUsedPrologue, DPS_IDX)
3973 && !bitVectBitValue (regsUsed, DPS_IDX))
3975 bitVectUnSetBit (regsUsedPrologue, DPS_IDX);
3978 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3979 && !bitVectBitValue (regsUsed, CND_IDX))
3981 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3982 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3983 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3984 bitVectUnSetBit (regsUsed, CND_IDX);
3987 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3989 /* If this was an interrupt handler that called another function */
3990 /* function, then assume working registers may be modified by it. */
3991 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3993 regsUsed = bitVectSetBit (regsUsed, AP_IDX);
3994 regsUsed = bitVectSetBit (regsUsed, DPX1_IDX);
3995 regsUsed = bitVectSetBit (regsUsed, DPL1_IDX);
3996 regsUsed = bitVectSetBit (regsUsed, DPH1_IDX);
3997 regsUsed = bitVectSetBit (regsUsed, DPX_IDX);
3998 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3999 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
4000 regsUsed = bitVectSetBit (regsUsed, DPS_IDX);
4001 regsUsed = bitVectSetBit (regsUsed, B_IDX);
4002 regsUsed = bitVectSetBit (regsUsed, A_IDX);
4003 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
4006 /* Remove the unneeded push/pops */
4007 regsUnneeded = newBitVect (ds390_nRegs);
4010 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
4012 if (!strncmp(lnp->line, "push", 4))
4014 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
4015 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4017 connectLine (lnp->prev, lnp->next);
4018 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4021 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
4023 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
4024 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4026 connectLine (lnp->prev, lnp->next);
4027 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4034 for (idx = 0; idx < regsUnneeded->size; idx++)
4035 if (bitVectBitValue (regsUnneeded, idx))
4036 emitcode (";", "eliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
4038 freeBitVect (regsUnneeded);
4039 freeBitVect (regsUsed);
4040 freeBitVect (regsUsedPrologue);
4043 /*-----------------------------------------------------------------*/
4044 /* genJavaNativeRet - generate code for return JavaNative */
4045 /*-----------------------------------------------------------------*/
4046 static void genJavaNativeRet(iCode *ic)
4050 aopOp (IC_LEFT (ic), ic, FALSE,
4051 AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
4052 size = AOP_SIZE (IC_LEFT (ic));
4056 /* it is assigned to GPR0-R3 then push them */
4057 if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
4058 aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
4059 for (i = 0 ; i < size ; i++ ) {
4060 emitcode ("push","%s",
4061 aopGet(IC_LEFT(ic),i,FALSE,TRUE,DP2_RESULT_REG));
4063 for (i = (size-1) ; i >= 0 ; i--) {
4064 emitcode ("pop","a%s",javaRet[i]);
4067 for (i = 0 ; i < size ; i++)
4068 emitcode ("mov","%s,%s",javaRet[i],
4069 aopGet(IC_LEFT(ic),i,FALSE,TRUE,DP2_RESULT_REG));
4071 for (i = size ; i < 4 ; i++ )
4072 emitcode ("mov","%s,#0",javaRet[i]);
4076 /*-----------------------------------------------------------------*/
4077 /* genRet - generate code for return statement */
4078 /*-----------------------------------------------------------------*/
4082 int size, offset = 0, pushed = 0;
4084 D (emitcode (";", "genRet"));
4086 /* if we have no return value then
4087 just generate the "ret" */
4091 /* if this is a JavaNative function then return
4092 value in different register */
4093 if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
4094 genJavaNativeRet(ic);
4097 /* we have something to return then
4098 move the return value into place */
4099 aopOp (IC_LEFT (ic), ic, FALSE,
4100 (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
4101 size = AOP_SIZE (IC_LEFT (ic));
4103 _startLazyDPSEvaluation ();
4105 if (IS_BIT(_G.currentFunc->etype))
4107 movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4114 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
4116 l = aopGet (IC_LEFT (ic), offset++,
4118 emitcode ("push", "%s", l);
4123 /* Since A is the last element of fReturn,
4124 * it is OK to clobber it in the aopGet.
4126 l = aopGet (IC_LEFT (ic), offset,
4127 FALSE, FALSE, NULL);
4128 if (strcmp (fReturn[offset], l))
4129 emitcode ("mov", "%s,%s", fReturn[offset++], l);
4132 _endLazyDPSEvaluation ();
4137 if (strcmp (fReturn[pushed], "a"))
4138 emitcode ("pop", fReturn[pushed]);
4140 emitcode ("pop", "acc");
4142 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
4145 /* generate a jump to the return label
4146 if the next is not the return statement */
4147 if (!(ic->next && ic->next->op == LABEL &&
4148 IC_LABEL (ic->next) == returnLabel))
4150 emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
4154 /*-----------------------------------------------------------------*/
4155 /* genLabel - generates a label */
4156 /*-----------------------------------------------------------------*/
4158 genLabel (iCode * ic)
4160 /* special case never generate */
4161 if (IC_LABEL (ic) == entryLabel)
4164 D (emitcode (";", "genLabel"));
4166 emitLabel (IC_LABEL (ic));
4169 /*-----------------------------------------------------------------*/
4170 /* genGoto - generates a ljmp */
4171 /*-----------------------------------------------------------------*/
4173 genGoto (iCode * ic)
4175 D (emitcode (";", "genGoto"));
4177 emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
4180 /*-----------------------------------------------------------------*/
4181 /* findLabelBackwards: walks back through the iCode chain looking */
4182 /* for the given label. Returns number of iCode instructions */
4183 /* between that label and given ic. */
4184 /* Returns zero if label not found. */
4185 /*-----------------------------------------------------------------*/
4187 findLabelBackwards (iCode * ic, int key)
4196 /* If we have any pushes or pops, we cannot predict the distance.
4197 I don't like this at all, this should be dealt with in the
4199 if (ic->op == IPUSH || ic->op == IPOP) {
4203 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4205 /* printf("findLabelBackwards = %d\n", count); */
4213 /*-----------------------------------------------------------------*/
4214 /* genPlusIncr :- does addition with increment if possible */
4215 /*-----------------------------------------------------------------*/
4217 genPlusIncr (iCode * ic)
4219 unsigned int icount;
4220 unsigned int size = getDataSize (IC_RESULT (ic));
4222 /* will try to generate an increment */
4223 /* if the right side is not a literal
4225 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4228 /* if the literal value of the right hand side
4229 is greater than 4 then it is not worth it */
4230 if ((icount = (unsigned int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4233 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4234 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4236 emitcode("inc","%s",aopGet(IC_RESULT(ic),0,FALSE,FALSE,NULL));
4240 /* if increment 16 bits in register */
4242 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4243 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4244 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4253 /* If the next instruction is a goto and the goto target
4254 * is <= 5 instructions previous to this, we can generate
4255 * jumps straight to that target.
4257 if (ic->next && ic->next->op == GOTO
4258 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4261 D (emitcode (";", "tail increment optimized (range %d)", labelRange));
4262 tlbl = IC_LABEL (ic->next);
4267 tlbl = newiTempLabel (NULL);
4270 l = aopGet (IC_RESULT (ic), LSB, FALSE, FALSE, NULL);
4271 emitcode ("inc", "%s", l);
4273 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4274 IS_AOP_PREG (IC_RESULT (ic)))
4276 emitcode ("cjne", "%s,%s,!tlabel", l, zero, tlbl->key + 100);
4280 emitcode ("clr", "a");
4281 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4284 l = aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE, NULL);
4285 emitcode ("inc", "%s", l);
4288 if (!strcmp(l, "acc"))
4290 emitcode("jnz", "!tlabel", tlbl->key + 100);
4292 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4293 IS_AOP_PREG (IC_RESULT (ic)))
4295 emitcode ("cjne", "%s,%s,!tlabel", l, zero, tlbl->key + 100);
4299 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4302 l = aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE, NULL);
4303 emitcode ("inc", "%s", l);
4307 if (!strcmp(l, "acc"))
4309 emitcode("jnz", "!tlabel", tlbl->key + 100);
4311 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4312 IS_AOP_PREG (IC_RESULT (ic)))
4314 emitcode ("cjne", "%s,%s,!tlabel", l, zero, tlbl->key + 100);
4318 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4321 l = aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE, NULL);
4322 emitcode ("inc", "%s", l);
4332 if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
4333 !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 &&
4334 options.model == MODEL_FLAT24 )
4336 if (IC_RESULT(ic)->isGptr)
4338 emitcode ("mov", "b,%s", aopGet(IC_LEFT (ic), 3, FALSE, FALSE, NULL));
4342 emitcode ("mov", "dpx,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE, NULL));
4344 emitcode ("mov", "dph,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE, NULL));
4346 emitcode ("mov", "dpl,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4350 emitcode ("inc", "dptr");
4354 if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
4355 AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
4357 emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
4359 emitcode ("inc", "dptr");
4360 emitcode ("mov", "dps,#0");
4364 /* if the sizes are greater than 1 then we cannot */
4365 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4366 AOP_SIZE (IC_LEFT (ic)) > 1)
4369 /* we can if the aops of the left & result match or
4370 if they are in registers and the registers are the
4373 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4374 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4375 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4379 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4380 emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
4381 aopPut (IC_RESULT (ic), "a", 0);
4385 _startLazyDPSEvaluation ();
4388 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4390 _endLazyDPSEvaluation ();
4399 /*-----------------------------------------------------------------*/
4400 /* outBitAcc - output a bit in acc */
4401 /*-----------------------------------------------------------------*/
4403 outBitAcc (operand * result)
4405 symbol *tlbl = newiTempLabel (NULL);
4406 /* if the result is a bit */
4407 if (AOP_TYPE (result) == AOP_CRY)
4409 aopPut (result, "a", 0);
4413 emitcode ("jz", "!tlabel", tlbl->key + 100);
4414 emitcode ("mov", "a,%s", one);
4420 /*-----------------------------------------------------------------*/
4421 /* genPlusBits - generates code for addition of two bits */
4422 /*-----------------------------------------------------------------*/
4424 genPlusBits (iCode * ic)
4426 D (emitcode (";", "genPlusBits"));
4428 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4430 symbol *lbl = newiTempLabel (NULL);
4431 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4432 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4433 emitcode ("cpl", "c");
4435 outBitC (IC_RESULT (ic));
4439 emitcode ("clr", "a");
4440 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4441 emitcode ("rlc", "a");
4442 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4443 emitcode ("addc", "a,%s", zero);
4444 outAcc (IC_RESULT (ic));
4449 adjustArithmeticResult (iCode * ic)
4451 if (opIsGptr (IC_RESULT (ic)) &&
4452 opIsGptr (IC_LEFT (ic)) &&
4453 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4455 aopPut (IC_RESULT (ic),
4456 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE, NULL),
4460 if (opIsGptr (IC_RESULT (ic)) &&
4461 opIsGptr (IC_RIGHT (ic)) &&
4462 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4464 aopPut (IC_RESULT (ic),
4465 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE, NULL),
4469 if (opIsGptr (IC_RESULT (ic)) &&
4470 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4471 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4472 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4473 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4476 SNPRINTF (buffer, sizeof(buffer),
4477 "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4478 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4482 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
4483 // generates the result if possible. If result is generated, returns TRUE; otherwise
4484 // returns false and caller must deal with fact that result isn't aopOp'd.
4485 bool aopOp3(iCode * ic)
4487 bool dp1InUse, dp2InUse;
4490 // First, generate the right opcode. DPTR may be used if neither left nor result are
4493 // D (emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
4494 // AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
4495 // AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
4496 // AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
4498 // D (emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
4499 // AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
4500 // AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
4501 // AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
4504 // Right uses DPTR unless left or result is an AOP_STR; however,
4505 // if right is an AOP_STR, it must use DPTR regardless.
4506 if ((AOP_IS_STR (IC_LEFT (ic)) || AOP_IS_STR (IC_RESULT (ic)))
4507 && !AOP_IS_STR (IC_RIGHT (ic)))
4516 aopOp (IC_RIGHT(ic), ic, FALSE, useDp2);
4518 // if the right used DPTR, left MUST use DPTR2.
4519 // if the right used DPTR2, left MUST use DPTR.
4520 // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
4521 // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
4522 // enabling us to assign DPTR to result.
4524 if (AOP_USESDPTR (IC_RIGHT (ic)))
4528 else if (AOP_USESDPTR2 (IC_RIGHT (ic)))
4534 if (AOP_IS_STR (IC_RESULT (ic)) && !AOP_IS_STR (IC_LEFT (ic)))
4544 aopOp (IC_LEFT (ic), ic, FALSE, useDp2);
4547 // We've op'd the left & right. So, if left or right are the same operand as result,
4548 // we know aopOp will succeed, and we can just do it & bail.
4549 if (isOperandEqual (IC_LEFT (ic), IC_RESULT (ic)))
4551 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4554 if (isOperandEqual (IC_RIGHT (ic), IC_RESULT (ic)))
4556 // D (emitcode(";", "aopOp3: (left | right) & result equal"));
4557 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4561 // Operands may be equivalent (but not equal) if they share a spill location. If
4562 // so, use the same DPTR or DPTR2.
4563 if (operandsEqu (IC_LEFT (ic), IC_RESULT (ic)))
4565 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4568 if (operandsEqu (IC_RIGHT (ic), IC_RESULT (ic)))
4570 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4574 // Note which dptrs are currently in use.
4575 dp1InUse = AOP_USESDPTR (IC_LEFT (ic)) || AOP_USESDPTR (IC_RIGHT (ic));
4576 dp2InUse = AOP_USESDPTR2 (IC_LEFT (ic)) || AOP_USESDPTR2 (IC_RIGHT (ic));
4578 // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot
4580 if (dp1InUse && AOP_IS_STR (IC_RESULT (ic)))
4585 // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
4586 if (dp2InUse && AOP_IS_DPTRn (IC_RESULT (ic)))
4591 // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck
4592 if (dp1InUse && dp2InUse && isOperandInFarSpace (IC_RESULT (ic)))
4597 aopOp (IC_RESULT (ic), ic, TRUE, dp1InUse);
4599 // Some sanity checking...
4600 if (dp1InUse && AOP_USESDPTR (IC_RESULT (ic)))
4603 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
4604 __FILE__, __LINE__, ic->filename, ic->lineno);
4605 emitcode(";", ">>> unexpected DPTR here.");
4608 if (dp2InUse && AOP_USESDPTR2 (IC_RESULT (ic)))
4611 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
4612 __FILE__, __LINE__, ic->filename, ic->lineno);
4613 emitcode(";", ">>> unexpected DPTR2 here.");
4619 // Macro to aopOp all three operands of an ic. If this cannot be done,
4620 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
4621 // will be set TRUE. The caller must then handle the case specially, noting
4622 // that the IC_RESULT operand is not aopOp'd.
4624 #define AOP_OP_3_NOFATAL(ic, rc) \
4625 do { rc = !aopOp3(ic); } while (0)
4627 // aopOp the left & right operands of an ic.
4628 #define AOP_OP_2(ic) \
4629 aopOp (IC_RIGHT (ic), ic, FALSE, AOP_IS_STR (IC_LEFT (ic))); \
4630 aopOp (IC_LEFT (ic), ic, FALSE, AOP_USESDPTR (IC_RIGHT (ic)));
4632 // convienience macro.
4633 #define AOP_SET_LOCALS(ic) \
4634 left = IC_LEFT(ic); \
4635 right = IC_RIGHT(ic); \
4636 result = IC_RESULT(ic);
4639 // Given an integer value of pushedSize bytes on the stack,
4640 // adjust it to be resultSize bytes, either by discarding
4641 // the most significant bytes or by zero-padding.
4643 // On exit from this macro, pushedSize will have been adjusted to
4644 // equal resultSize, and ACC may be trashed.
4645 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
4646 /* If the pushed data is bigger than the result, \
4647 * simply discard unused bytes. Icky, but works. \
4649 while (pushedSize > resultSize) \
4651 D (emitcode (";", "discarding unused result byte.")); \
4652 emitcode ("pop", "acc"); \
4655 if (pushedSize < resultSize) \
4657 emitcode ("clr", "a"); \
4658 /* Conversly, we haven't pushed enough here. \
4659 * just zero-pad, and all is well. \
4661 while (pushedSize < resultSize) \
4663 emitcode("push", "acc"); \
4667 assert(pushedSize == resultSize);
4669 /*-----------------------------------------------------------------*/
4670 /* genPlus - generates code for addition */
4671 /*-----------------------------------------------------------------*/
4673 genPlus (iCode * ic)
4675 int size, offset = 0;
4678 bool swappedLR = FALSE;
4680 D (emitcode (";", "genPlus"));
4682 /* special cases :- */
4683 if ( AOP_IS_STR (IC_LEFT (ic)) &&
4684 isOperandLiteral (IC_RIGHT (ic)) && OP_SYMBOL (IC_RESULT (ic))->ruonly) {
4685 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
4686 size = (int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4688 while (size--) emitcode ("inc","dptr");
4690 emitcode ("mov", "a,dpl");
4691 emitcode ("add", "a,#!constbyte", size & 0xff);
4692 emitcode ("mov", "dpl,a");
4693 emitcode ("mov", "a,dph");
4694 emitcode ("addc", "a,#!constbyte", (size >> 8) & 0xff);
4695 emitcode ("mov", "dph,a");
4696 emitcode ("mov", "a,dpx");
4697 emitcode ("addc", "a,#!constbyte", (size >> 16) & 0xff);
4698 emitcode ("mov", "dpx,a");
4700 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4703 if ( IS_SYMOP (IC_LEFT (ic)) &&
4704 OP_SYMBOL (IC_LEFT (ic))->remat &&
4705 isOperandInFarSpace (IC_RIGHT (ic))) {
4706 operand *op = IC_RIGHT(ic);
4707 IC_RIGHT(ic) = IC_LEFT(ic);
4711 AOP_OP_3_NOFATAL (ic, pushResult);
4715 D (emitcode (";", "genPlus: must push result: 3 ops in far space"));
4720 /* if literal, literal on the right or
4721 if left requires ACC or right is already
4723 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4724 ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic)))) ||
4725 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4727 operand *t = IC_RIGHT (ic);
4728 IC_RIGHT (ic) = IC_LEFT (ic);
4731 D (emitcode (";", "Swapped plus args."));
4734 /* if both left & right are in bit
4736 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4737 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4743 /* if left in bit space & right literal */
4744 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4745 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4747 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4748 /* if result in bit space */
4749 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4751 if (ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4752 emitcode ("cpl", "c");
4753 outBitC (IC_RESULT (ic));
4757 size = getDataSize (IC_RESULT (ic));
4758 _startLazyDPSEvaluation ();
4761 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4762 emitcode ("addc", "a,%s", zero);
4763 aopPut (IC_RESULT (ic), "a", offset++);
4765 _endLazyDPSEvaluation ();
4770 /* if I can do an increment instead
4771 of add then GOOD for ME */
4772 if (genPlusIncr (ic) == TRUE)
4774 D (emitcode (";", "did genPlusIncr"));
4779 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4781 _startLazyDPSEvaluation ();
4784 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4786 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
4788 emitcode ("add", "a,%s",
4789 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4791 emitcode ("addc", "a,%s",
4792 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4796 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4798 /* right is going to use ACC or we would have taken the
4801 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4803 D(emitcode(";", "+ AOP_ACC special case."););
4804 emitcode("xch", "a, %s", DP2_RESULT_REG);
4806 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4809 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4812 emitcode("add", "a, %s", DP2_RESULT_REG);
4816 emitcode ("add", "a,%s",
4817 aopGet (IC_LEFT(ic), offset, FALSE, FALSE,
4823 emitcode ("addc", "a,%s",
4824 aopGet (IC_LEFT (ic), offset, FALSE, FALSE,
4830 aopPut (IC_RESULT (ic), "a", offset);
4834 emitcode ("push", "acc");
4838 _endLazyDPSEvaluation ();
4842 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4844 size = getDataSize (IC_LEFT (ic));
4845 rSize = getDataSize (IC_RESULT (ic));
4847 ADJUST_PUSHED_RESULT(size, rSize);
4849 _startLazyDPSEvaluation ();
4852 emitcode ("pop", "acc");
4853 aopPut (IC_RESULT (ic), "a", size);
4855 _endLazyDPSEvaluation ();
4858 adjustArithmeticResult (ic);
4861 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4864 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4865 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4869 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4870 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4874 /*-----------------------------------------------------------------*/
4875 /* genMinusDec :- does subtraction with decrement if possible */
4876 /*-----------------------------------------------------------------*/
4878 genMinusDec (iCode * ic)
4880 unsigned int icount;
4881 unsigned int size = getDataSize (IC_RESULT (ic));
4883 /* will try to generate an increment */
4884 /* if the right side is not a literal
4886 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4889 /* if the literal value of the right hand side
4890 is greater than 4 then it is not worth it */
4891 if ((icount = (unsigned int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4894 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4895 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4897 emitcode("dec","%s",aopGet(IC_RESULT(ic),0,FALSE,FALSE,NULL));
4901 /* if decrement 16 bits in register */
4902 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4903 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4904 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4913 /* If the next instruction is a goto and the goto target
4914 * is <= 5 instructions previous to this, we can generate
4915 * jumps straight to that target.
4917 if (ic->next && ic->next->op == GOTO
4918 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4921 D (emitcode (";", "tail decrement optimized (range %d)", labelRange));
4922 tlbl = IC_LABEL (ic->next);
4927 tlbl = newiTempLabel (NULL);
4931 l = aopGet (IC_RESULT (ic), LSB, FALSE, FALSE, NULL);
4932 emitcode ("dec", "%s", l);
4934 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4935 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4936 IS_AOP_PREG (IC_RESULT (ic)))
4938 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4942 emitcode ("mov", "a,#!constbyte",0xff);
4943 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4945 l = aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE, NULL);
4946 emitcode ("dec", "%s", l);
4949 if (!strcmp(l, "acc"))
4951 emitcode("jnz", "!tlabel", tlbl->key + 100);
4953 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4954 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4955 IS_AOP_PREG (IC_RESULT (ic)))
4957 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4961 emitcode ("mov", "a,#!constbyte",0xff);
4962 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4964 l = aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE, NULL);
4965 emitcode ("dec", "%s", l);
4969 if (!strcmp(l, "acc"))
4971 emitcode("jnz", "!tlabel", tlbl->key + 100);
4973 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4974 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4975 IS_AOP_PREG (IC_RESULT (ic)))
4977 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4981 emitcode ("mov", "a,#!constbyte",0xff);
4982 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4984 l = aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE, NULL);
4985 emitcode ("dec", "%s", l);
4994 /* if the sizes are greater than 1 then we cannot */
4995 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4996 AOP_SIZE (IC_LEFT (ic)) > 1)
4999 /* we can if the aops of the left & result match or
5000 if they are in registers and the registers are the
5003 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
5004 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
5005 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
5009 if (aopGetUsesAcc (IC_LEFT (ic), 0))
5011 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL));
5016 l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL);
5019 _startLazyDPSEvaluation ();
5022 emitcode ("dec", "%s", l);
5024 _endLazyDPSEvaluation ();
5026 if (AOP_NEEDSACC (IC_RESULT (ic)))
5027 aopPut (IC_RESULT (ic), "a", 0);
5035 /*-----------------------------------------------------------------*/
5036 /* addSign - complete with sign */
5037 /*-----------------------------------------------------------------*/
5039 addSign (operand * result, int offset, int sign)
5041 int size = (getDataSize (result) - offset);
5044 _startLazyDPSEvaluation();
5047 emitcode ("rlc", "a");
5048 emitcode ("subb", "a,acc");
5051 aopPut (result, "a", offset++);
5058 aopPut (result, zero, offset++);
5061 _endLazyDPSEvaluation();
5065 /*-----------------------------------------------------------------*/
5066 /* genMinusBits - generates code for subtraction of two bits */
5067 /*-----------------------------------------------------------------*/
5069 genMinusBits (iCode * ic)
5071 symbol *lbl = newiTempLabel (NULL);
5073 D (emitcode (";", "genMinusBits"));
5075 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
5077 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
5078 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
5079 emitcode ("cpl", "c");
5081 outBitC (IC_RESULT (ic));
5085 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
5086 emitcode ("subb", "a,acc");
5087 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
5088 emitcode ("inc", "a");
5090 aopPut (IC_RESULT (ic), "a", 0);
5091 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
5095 /*-----------------------------------------------------------------*/
5096 /* genMinus - generates code for subtraction */
5097 /*-----------------------------------------------------------------*/
5099 genMinus (iCode * ic)
5101 int size, offset = 0;
5106 D (emitcode (";", "genMinus"));
5108 AOP_OP_3_NOFATAL(ic, pushResult);
5112 /* special cases :- */
5113 /* if both left & right are in bit space */
5114 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
5115 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
5121 /* if I can do an decrement instead
5122 of subtract then GOOD for ME */
5123 if (genMinusDec (ic) == TRUE)
5128 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
5130 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
5136 lit = (long) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5141 /* if literal, add a,#-lit, else normal subb */
5142 _startLazyDPSEvaluation ();
5144 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
5145 if (AOP_USESDPTR(IC_RIGHT(ic))) {
5146 emitcode ("mov","b,%s",
5147 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
5148 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
5149 emitcode ("subb","a,b");
5151 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
5152 emitcode ("subb", "a,%s",
5153 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE,
5157 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
5158 /* first add without previous c */
5160 if (!size && lit==-1) {
5161 emitcode ("dec", "a");
5163 emitcode ("add", "a,#!constbyte",
5164 (unsigned int) (lit & 0x0FFL));
5167 emitcode ("addc", "a,#!constbyte",
5168 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5173 emitcode ("push", "acc");
5175 aopPut (IC_RESULT (ic), "a", offset);
5179 _endLazyDPSEvaluation ();
5183 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
5185 size = getDataSize (IC_LEFT (ic));
5186 rSize = getDataSize (IC_RESULT (ic));
5188 ADJUST_PUSHED_RESULT(size, rSize);
5190 _startLazyDPSEvaluation ();
5193 emitcode ("pop", "acc");
5194 aopPut (IC_RESULT (ic), "a", size);
5196 _endLazyDPSEvaluation ();
5199 adjustArithmeticResult (ic);
5202 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5203 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5204 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5208 /*-----------------------------------------------------------------*/
5209 /* genMultbits :- multiplication of bits */
5210 /*-----------------------------------------------------------------*/
5212 genMultbits (operand * left,
5217 D (emitcode (";", "genMultbits"));
5219 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5220 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5221 aopOp(result, ic, TRUE, FALSE);
5225 /*-----------------------------------------------------------------*/
5226 /* genMultOneByte : 8*8=8/16 bit multiplication */
5227 /*-----------------------------------------------------------------*/
5229 genMultOneByte (operand * left,
5236 bool runtimeSign, compiletimeSign;
5237 bool lUnsigned, rUnsigned, pushedB;
5239 /* (if two literals: the value is computed before) */
5240 /* if one literal, literal on the right */
5241 if (AOP_TYPE (left) == AOP_LIT)
5246 /* emitcode (";", "swapped left and right"); */
5248 /* if no literal, unsigned on the right: shorter code */
5249 if ( AOP_TYPE (right) != AOP_LIT
5250 && SPEC_USIGN (getSpec (operandType (left))))
5257 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5258 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5262 if ((lUnsigned && rUnsigned)
5263 /* sorry, I don't know how to get size
5264 without calling aopOp (result,...);
5265 see Feature Request */
5266 /* || size == 1 */ ) /* no, this is not a bug; with a 1 byte result there's
5267 no need to take care about the signedness! */
5269 /* just an unsigned 8 * 8 = 8 multiply
5271 /* emitcode (";","unsigned"); */
5272 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
5273 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
5274 emitcode ("mul", "ab");
5277 aopOp (result, ic, TRUE, FALSE);
5278 size = AOP_SIZE (result);
5280 if (size < 1 || size > 2)
5282 /* this should never happen */
5283 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
5284 size, __FILE__, lineno);
5288 aopPut (result, "a", 0);
5291 aopPut (result, "b", 1);
5297 /* we have to do a signed multiply */
5298 /* emitcode (";", "signed"); */
5300 /* now sign adjust for both left & right */
5302 /* let's see what's needed: */
5303 /* apply negative sign during runtime */
5304 runtimeSign = FALSE;
5305 /* negative sign from literals */
5306 compiletimeSign = FALSE;
5310 if (AOP_TYPE(left) == AOP_LIT)
5312 /* signed literal */
5313 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5315 compiletimeSign = TRUE;
5318 /* signed but not literal */
5324 if (AOP_TYPE(right) == AOP_LIT)
5326 /* signed literal */
5327 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
5329 compiletimeSign ^= TRUE;
5332 /* signed but not literal */
5336 /* initialize F0, which stores the runtime sign */
5339 if (compiletimeSign)
5340 emitcode ("setb", "F0"); /* set sign flag */
5342 emitcode ("clr", "F0"); /* reset sign flag */
5345 /* save the signs of the operands */
5346 if (AOP_TYPE(right) == AOP_LIT)
5348 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
5350 if (!rUnsigned && val < 0)
5351 emitcode ("mov", "b,#!constbyte", -val);
5353 emitcode ("mov", "b,#!constbyte", (unsigned char) val);
5355 else /* ! literal */
5357 if (rUnsigned) /* emitcode (";", "signed"); */
5358 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
5361 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
5362 lbl = newiTempLabel (NULL);
5363 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5364 emitcode ("cpl", "F0"); /* complement sign flag */
5365 emitcode ("cpl", "a"); /* 2's complement */
5366 emitcode ("inc", "a");
5368 emitcode ("mov", "b,a");
5372 if (AOP_TYPE(left) == AOP_LIT)
5374 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5376 if (!lUnsigned && val < 0)
5377 emitcode ("mov", "a,#!constbyte", -val);
5379 emitcode ("mov", "a,#!constbyte", (unsigned char) val);
5381 else /* ! literal */
5383 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
5385 if (!lUnsigned) /* emitcode (";", "signed"); */
5387 lbl = newiTempLabel (NULL);
5388 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5389 emitcode ("cpl", "F0"); /* complement sign flag */
5390 emitcode ("cpl", "a"); /* 2's complement */
5391 emitcode ("inc", "a");
5396 /* now the multiplication */
5397 emitcode ("mul", "ab");
5399 aopOp(result, ic, TRUE, FALSE);
5400 size = AOP_SIZE (result);
5402 if (size < 1 || size > 2)
5404 /* this should never happen */
5405 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
5406 size, __FILE__, lineno);
5410 if (runtimeSign || compiletimeSign)
5412 lbl = newiTempLabel (NULL);
5414 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5415 emitcode ("cpl", "a"); /* lsb 2's complement */
5417 emitcode ("inc", "a"); /* inc doesn't set carry flag */
5420 emitcode ("add", "a,#1"); /* this sets carry flag */
5421 emitcode ("xch", "a,b");
5422 emitcode ("cpl", "a"); /* msb 2's complement */
5423 emitcode ("addc", "a,#0");
5424 emitcode ("xch", "a,b");
5428 aopPut (result, "a", 0);
5431 aopPut (result, "b", 1);
5436 /*-----------------------------------------------------------------*/
5437 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
5438 /*-----------------------------------------------------------------*/
5439 static void genMultTwoByte (operand *left, operand *right,
5440 operand *result, iCode *ic)
5442 sym_link *retype = getSpec(operandType(right));
5443 sym_link *letype = getSpec(operandType(left));
5444 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5447 if (AOP_TYPE (left) == AOP_LIT) {
5452 /* save EA bit in F1 */
5453 lbl = newiTempLabel(NULL);
5454 emitcode ("setb","F1");
5455 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5456 emitcode ("clr","F1");
5459 /* load up MB with right */
5461 emitcode("clr","F0");
5462 if (AOP_TYPE(right) == AOP_LIT) {
5463 int val=(int) ulFromVal (AOP (right)->aopu.aop_lit);
5465 emitcode("setb","F0");
5468 emitcode ("mov","mb,#!constbyte",val & 0xff);
5469 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5471 lbl = newiTempLabel(NULL);
5472 emitcode ("mov","b,%s",aopGet(right,0,FALSE,FALSE,NULL));
5473 emitcode ("mov","a,%s",aopGet(right,1,FALSE,FALSE,NULL));
5474 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5475 emitcode ("xch", "a,b");
5476 emitcode ("cpl","a");
5477 emitcode ("add", "a,#1");
5478 emitcode ("xch", "a,b");
5479 emitcode ("cpl", "a"); // msb
5480 emitcode ("addc", "a,#0");
5481 emitcode ("setb","F0");
5483 emitcode ("mov","mb,b");
5484 emitcode ("mov","mb,a");
5487 emitcode ("mov","mb,%s",aopGet(right,0,FALSE,FALSE,NULL));
5488 emitcode ("mov","mb,%s",aopGet(right,1,FALSE,FALSE,NULL));
5490 /* load up MA with left */
5492 lbl = newiTempLabel(NULL);
5493 emitcode ("mov","b,%s",aopGet(left,0,FALSE,FALSE,NULL));
5494 emitcode ("mov","a,%s",aopGet(left,1,FALSE,FALSE,NULL));
5495 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5496 emitcode ("xch", "a,b");
5497 emitcode ("cpl","a");
5498 emitcode ("add", "a,#1");
5499 emitcode ("xch", "a,b");
5500 emitcode ("cpl", "a"); // msb
5501 emitcode ("addc","a,#0");
5502 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5503 emitcode ("setb","F0");
5505 emitcode ("mov","ma,b");
5506 emitcode ("mov","ma,a");
5508 emitcode ("mov","ma,%s",aopGet(left,0,FALSE,FALSE,NULL));
5509 emitcode ("mov","ma,%s",aopGet(left,1,FALSE,FALSE,NULL));
5511 /* wait for multiplication to finish */
5512 lbl = newiTempLabel(NULL);
5514 emitcode("mov","a,mcnt1");
5515 emitcode("anl","a,#!constbyte",0x80);
5516 emitcode("jnz","!tlabel",lbl->key+100);
5518 freeAsmop (left, NULL, ic, TRUE);
5519 freeAsmop (right, NULL, ic,TRUE);
5520 aopOp(result, ic, TRUE, FALSE);
5522 /* if unsigned then simple */
5524 emitcode ("mov","a,ma");
5525 if (AOP_SIZE(result) >= 4) aopPut(result,"a",3);
5526 emitcode ("mov","a,ma");
5527 if (AOP_SIZE(result) >= 3) aopPut(result,"a",2);
5528 aopPut(result,"ma",1);
5529 aopPut(result,"ma",0);
5531 emitcode("push","ma");
5532 emitcode("push","ma");
5533 emitcode("push","ma");
5535 /* negate result if needed */
5536 lbl = newiTempLabel(NULL);
5537 emitcode("jnb","F0,!tlabel",lbl->key+100);
5538 emitcode("cpl","a");
5539 emitcode("add","a,#1");
5541 if (AOP_TYPE(result) == AOP_ACC)
5543 D (emitcode(";", "ACC special case."));
5544 /* We know result is the only live aop, and
5545 * it's obviously not a DPTR2, so AP is available.
5547 emitcode("mov", "%s,acc", DP2_RESULT_REG);
5551 aopPut(result,"a",0);
5554 emitcode("pop","acc");
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",1);
5561 emitcode("pop","acc");
5562 if (AOP_SIZE(result) >= 3) {
5563 lbl = newiTempLabel(NULL);
5564 emitcode("jnb","F0,!tlabel",lbl->key+100);
5565 emitcode("cpl","a");
5566 emitcode("addc","a,#0");
5568 aopPut(result,"a",2);
5570 emitcode("pop","acc");
5571 if (AOP_SIZE(result) >= 4) {
5572 lbl = newiTempLabel(NULL);
5573 emitcode("jnb","F0,!tlabel",lbl->key+100);
5574 emitcode("cpl","a");
5575 emitcode("addc","a,#0");
5577 aopPut(result,"a",3);
5579 if (AOP_TYPE(result) == AOP_ACC)
5581 /* We stashed the result away above. */
5582 emitcode("mov", "acc,%s", DP2_RESULT_REG);
5586 freeAsmop (result, NULL, ic, TRUE);
5588 /* restore EA bit in F1 */
5589 lbl = newiTempLabel(NULL);
5590 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5591 emitcode ("setb","EA");
5596 /*-----------------------------------------------------------------*/
5597 /* genMult - generates code for multiplication */
5598 /*-----------------------------------------------------------------*/
5600 genMult (iCode * ic)
5602 operand *left = IC_LEFT (ic);
5603 operand *right = IC_RIGHT (ic);
5604 operand *result = IC_RESULT (ic);
5606 D (emitcode (";", "genMult"));
5608 /* assign the asmops */
5611 /* special cases first */
5613 if (AOP_TYPE (left) == AOP_CRY &&
5614 AOP_TYPE (right) == AOP_CRY)
5616 genMultbits (left, right, result, ic);
5620 /* if both are of size == 1 */
5621 if (AOP_SIZE (left) == 1 &&
5622 AOP_SIZE (right) == 1)
5624 genMultOneByte (left, right, result, ic);
5628 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5629 /* use the ds390 ARITHMETIC accel UNIT */
5630 genMultTwoByte (left, right, result, ic);
5633 /* should have been converted to function call */
5637 freeAsmop (result, NULL, ic, TRUE);
5638 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5639 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5642 /*-----------------------------------------------------------------*/
5643 /* genDivbits :- division of bits */
5644 /*-----------------------------------------------------------------*/
5646 genDivbits (operand * left,
5654 D(emitcode (";", "genDivbits"));
5658 /* the result must be bit */
5659 LOAD_AB_FOR_DIV (left, right, l);
5660 emitcode ("div", "ab");
5661 emitcode ("rrc", "a");
5662 aopOp(result, ic, TRUE, FALSE);
5666 aopPut (result, "c", 0);
5669 /*-----------------------------------------------------------------*/
5670 /* genDivOneByte : 8 bit division */
5671 /*-----------------------------------------------------------------*/
5673 genDivOneByte (operand * left,
5678 bool lUnsigned, rUnsigned, pushedB;
5679 bool runtimeSign, compiletimeSign;
5684 D(emitcode (";", "genDivOneByte"));
5687 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5688 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5692 /* signed or unsigned */
5693 if (lUnsigned && rUnsigned)
5695 /* unsigned is easy */
5696 LOAD_AB_FOR_DIV (left, right, l);
5697 emitcode ("div", "ab");
5700 aopOp (result, ic, TRUE, FALSE);
5701 aopPut (result, "a", 0);
5704 size = AOP_SIZE (result) - 1;
5707 aopPut (result, zero, offset++);
5713 /* signed is a little bit more difficult */
5715 /* now sign adjust for both left & right */
5717 /* let's see what's needed: */
5718 /* apply negative sign during runtime */
5719 runtimeSign = FALSE;
5720 /* negative sign from literals */
5721 compiletimeSign = FALSE;
5725 if (AOP_TYPE(left) == AOP_LIT)
5727 /* signed literal */
5728 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5730 compiletimeSign = TRUE;
5733 /* signed but not literal */
5739 if (AOP_TYPE(right) == AOP_LIT)
5741 /* signed literal */
5742 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
5744 compiletimeSign ^= TRUE;
5747 /* signed but not literal */
5751 /* initialize F0, which stores the runtime sign */
5754 if (compiletimeSign)
5755 emitcode ("setb", "F0"); /* set sign flag */
5757 emitcode ("clr", "F0"); /* reset sign flag */
5760 /* save the signs of the operands */
5761 if (AOP_TYPE(right) == AOP_LIT)
5763 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
5765 if (!rUnsigned && val < 0)
5766 emitcode ("mov", "b,#0x%02x", -val);
5768 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5770 else /* ! literal */
5773 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
5776 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
5777 lbl = newiTempLabel (NULL);
5778 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5779 emitcode ("cpl", "F0"); /* complement sign flag */
5780 emitcode ("cpl", "a"); /* 2's complement */
5781 emitcode ("inc", "a");
5783 emitcode ("mov", "b,a");
5787 if (AOP_TYPE(left) == AOP_LIT)
5789 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5791 if (!lUnsigned && val < 0)
5792 emitcode ("mov", "a,#0x%02x", -val);
5794 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5796 else /* ! literal */
5798 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
5802 lbl = newiTempLabel (NULL);
5803 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5804 emitcode ("cpl", "F0"); /* complement sign flag */
5805 emitcode ("cpl", "a"); /* 2's complement */
5806 emitcode ("inc", "a");
5811 /* now the division */
5812 emitcode ("nop", "; workaround for DS80C390 div bug.");
5813 emitcode ("div", "ab");
5815 if (runtimeSign || compiletimeSign)
5817 lbl = newiTempLabel (NULL);
5819 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5820 emitcode ("cpl", "a"); /* lsb 2's complement */
5821 emitcode ("inc", "a");
5825 aopOp (result, ic, TRUE, FALSE);
5826 size = AOP_SIZE (result) - 1;
5830 /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
5831 then the result will be in b, a */
5832 emitcode ("mov", "b,a"); /* 1 */
5833 /* msb is 0x00 or 0xff depending on the sign */
5836 emitcode ("mov", "c,F0");
5837 emitcode ("subb", "a,acc");
5838 emitcode ("xch", "a,b"); /* 2 */
5840 aopPut (result, "b", offset++); /* write msb's */
5842 else /* compiletimeSign */
5844 aopPut (result, "#0xff", offset++); /* write msb's */
5846 aopPut (result, "a", 0); /* 3: write lsb */
5851 aopOp(result, ic, TRUE, FALSE);
5852 size = AOP_SIZE (result) - 1;
5854 aopPut (result, "a", 0);
5856 aopPut (result, zero, offset++);
5862 /*-----------------------------------------------------------------*/
5863 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
5864 /*-----------------------------------------------------------------*/
5865 static void genDivTwoByte (operand *left, operand *right,
5866 operand *result, iCode *ic)
5868 sym_link *retype = getSpec(operandType(right));
5869 sym_link *letype = getSpec(operandType(left));
5870 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5873 /* save EA bit in F1 */
5874 lbl = newiTempLabel(NULL);
5875 emitcode ("setb","F1");
5876 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5877 emitcode ("clr","F1");
5880 /* load up MA with left */
5882 emitcode("clr","F0");
5883 lbl = newiTempLabel(NULL);
5884 emitcode ("mov","b,%s",aopGet(left,0,FALSE,FALSE,NULL));
5885 emitcode ("mov","a,%s",aopGet(left,1,FALSE,FALSE,NULL));
5886 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5887 emitcode ("xch", "a,b");
5888 emitcode ("cpl","a");
5889 emitcode ("add", "a,#1");
5890 emitcode ("xch", "a,b");
5891 emitcode ("cpl", "a"); // msb
5892 emitcode ("addc","a,#0");
5893 emitcode ("setb","F0");
5895 emitcode ("mov","ma,b");
5896 emitcode ("mov","ma,a");
5898 emitcode ("mov","ma,%s",aopGet(left,0,FALSE,FALSE,NULL));
5899 emitcode ("mov","ma,%s",aopGet(left,1,FALSE,FALSE,NULL));
5902 /* load up MB with right */
5904 if (AOP_TYPE(right) == AOP_LIT) {
5905 int val=(int) ulFromVal (AOP (right)->aopu.aop_lit);
5907 lbl = newiTempLabel(NULL);
5908 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5909 emitcode("setb","F0");
5913 emitcode ("mov","mb,#!constbyte",val & 0xff);
5914 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5916 lbl = newiTempLabel(NULL);
5917 emitcode ("mov","b,%s",aopGet(right,0,FALSE,FALSE,NULL));
5918 emitcode ("mov","a,%s",aopGet(right,1,FALSE,FALSE,NULL));
5919 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5920 emitcode ("xch", "a,b");
5921 emitcode ("cpl","a");
5922 emitcode ("add", "a,#1");
5923 emitcode ("xch", "a,b");
5924 emitcode ("cpl", "a"); // msb
5925 emitcode ("addc", "a,#0");
5926 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5927 emitcode ("setb","F0");
5929 emitcode ("mov","mb,b");
5930 emitcode ("mov","mb,a");
5933 emitcode ("mov","mb,%s",aopGet(right,0,FALSE,FALSE,NULL));
5934 emitcode ("mov","mb,%s",aopGet(right,1,FALSE,FALSE,NULL));
5937 /* wait for multiplication to finish */
5938 lbl = newiTempLabel(NULL);
5940 emitcode("mov","a,mcnt1");
5941 emitcode("anl","a,#!constbyte",0x80);
5942 emitcode("jnz","!tlabel",lbl->key+100);
5944 freeAsmop (left, NULL, ic, TRUE);
5945 freeAsmop (right, NULL, ic,TRUE);
5946 aopOp(result, ic, TRUE, FALSE);
5948 /* if unsigned then simple */
5950 aopPut(result,"ma",1);
5951 aopPut(result,"ma",0);
5953 emitcode("push","ma");
5955 /* negate result if needed */
5956 lbl = newiTempLabel(NULL);
5957 emitcode("jnb","F0,!tlabel",lbl->key+100);
5958 emitcode("cpl","a");
5959 emitcode("add","a,#1");
5961 aopPut(result,"a",0);
5962 emitcode("pop","acc");
5963 lbl = newiTempLabel(NULL);
5964 emitcode("jnb","F0,!tlabel",lbl->key+100);
5965 emitcode("cpl","a");
5966 emitcode("addc","a,#0");
5968 aopPut(result,"a",1);
5970 freeAsmop (result, NULL, ic, TRUE);
5971 /* restore EA bit in F1 */
5972 lbl = newiTempLabel(NULL);
5973 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5974 emitcode ("setb","EA");
5979 /*-----------------------------------------------------------------*/
5980 /* genDiv - generates code for division */
5981 /*-----------------------------------------------------------------*/
5985 operand *left = IC_LEFT (ic);
5986 operand *right = IC_RIGHT (ic);
5987 operand *result = IC_RESULT (ic);
5989 D (emitcode (";", "genDiv"));
5991 /* assign the amsops */
5994 /* special cases first */
5996 if (AOP_TYPE (left) == AOP_CRY &&
5997 AOP_TYPE (right) == AOP_CRY)
5999 genDivbits (left, right, result, ic);
6003 /* if both are of size == 1 */
6004 if (AOP_SIZE (left) == 1 &&
6005 AOP_SIZE (right) == 1)
6007 genDivOneByte (left, right, result, ic);
6011 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
6012 /* use the ds390 ARITHMETIC accel UNIT */
6013 genDivTwoByte (left, right, result, ic);
6016 /* should have been converted to function call */
6019 freeAsmop (result, NULL, ic, TRUE);
6020 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6021 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6024 /*-----------------------------------------------------------------*/
6025 /* genModbits :- modulus of bits */
6026 /*-----------------------------------------------------------------*/
6028 genModbits (operand * left,
6036 D (emitcode (";", "genModbits"));
6040 /* the result must be bit */
6041 LOAD_AB_FOR_DIV (left, right, l);
6042 emitcode ("div", "ab");
6043 emitcode ("mov", "a,b");
6044 emitcode ("rrc", "a");
6045 aopOp(result, ic, TRUE, FALSE);
6049 aopPut (result, "c", 0);
6052 /*-----------------------------------------------------------------*/
6053 /* genModOneByte : 8 bit modulus */
6054 /*-----------------------------------------------------------------*/
6056 genModOneByte (operand * left,
6061 bool lUnsigned, rUnsigned, pushedB;
6062 bool runtimeSign, compiletimeSign;
6067 D (emitcode (";", "genModOneByte"));
6070 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
6071 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
6075 /* signed or unsigned */
6076 if (lUnsigned && rUnsigned)
6078 /* unsigned is easy */
6079 LOAD_AB_FOR_DIV (left, right, l);
6080 emitcode ("div", "ab");
6081 aopOp (result, ic, TRUE, FALSE);
6082 aopPut (result, "b", 0);
6084 for (size = AOP_SIZE (result) - 1; size--;)
6085 aopPut (result, zero, offset++);
6091 /* signed is a little bit more difficult */
6093 /* now sign adjust for both left & right */
6095 /* modulus: sign of the right operand has no influence on the result! */
6096 if (AOP_TYPE(right) == AOP_LIT)
6098 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
6100 if (!rUnsigned && val < 0)
6101 emitcode ("mov", "b,#0x%02x", -val);
6103 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
6105 else /* not literal */
6108 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
6111 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
6112 lbl = newiTempLabel (NULL);
6113 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
6114 emitcode ("cpl", "a"); /* 2's complement */
6115 emitcode ("inc", "a");
6117 emitcode ("mov", "b,a");
6121 /* let's see what's needed: */
6122 /* apply negative sign during runtime */
6123 runtimeSign = FALSE;
6124 /* negative sign from literals */
6125 compiletimeSign = FALSE;
6127 /* sign adjust left side */
6128 if (AOP_TYPE(left) == AOP_LIT)
6130 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
6132 if (!lUnsigned && val < 0)
6134 compiletimeSign = TRUE; /* set sign flag */
6135 emitcode ("mov", "a,#0x%02x", -val);
6138 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
6140 else /* ! literal */
6142 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
6147 emitcode ("clr", "F0"); /* clear sign flag */
6149 lbl = newiTempLabel (NULL);
6150 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
6151 emitcode ("setb", "F0"); /* set sign flag */
6152 emitcode ("cpl", "a"); /* 2's complement */
6153 emitcode ("inc", "a");
6158 /* now the modulus */
6159 emitcode ("nop", "; workaround for DS80C390 div bug.");
6160 emitcode ("div", "ab");
6162 if (runtimeSign || compiletimeSign)
6164 emitcode ("mov", "a,b");
6165 lbl = newiTempLabel (NULL);
6167 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
6168 emitcode ("cpl", "a"); /* lsb 2's complement */
6169 emitcode ("inc", "a");
6173 aopOp (result, ic, TRUE, FALSE);
6174 size = AOP_SIZE (result) - 1;
6178 /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
6179 then the result will be in b, a */
6180 emitcode ("mov", "b,a"); /* 1 */
6181 /* msb is 0x00 or 0xff depending on the sign */
6184 emitcode ("mov", "c,F0");
6185 emitcode ("subb", "a,acc");
6186 emitcode ("xch", "a,b"); /* 2 */
6188 aopPut (result, "b", offset++); /* write msb's */
6190 else /* compiletimeSign */
6192 aopPut (result, "#0xff", offset++); /* write msb's */
6194 aopPut (result, "a", 0); /* 3: write lsb */
6199 aopOp(result, ic, TRUE, FALSE);
6200 size = AOP_SIZE (result) - 1;
6202 aopPut (result, "b", 0);
6204 aopPut (result, zero, offset++);
6210 /*-----------------------------------------------------------------*/
6211 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
6212 /*-----------------------------------------------------------------*/
6213 static void genModTwoByte (operand *left, operand *right,
6214 operand *result, iCode *ic)
6216 sym_link *retype = getSpec(operandType(right));
6217 sym_link *letype = getSpec(operandType(left));
6218 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
6221 /* load up MA with left */
6222 /* save EA bit in F1 */
6223 lbl = newiTempLabel(NULL);
6224 emitcode ("setb","F1");
6225 emitcode ("jbc","EA,!tlabel",lbl->key+100);
6226 emitcode ("clr","F1");
6230 lbl = newiTempLabel(NULL);
6231 emitcode ("mov","b,%s",aopGet(left,0,FALSE,FALSE,NULL));
6232 emitcode ("mov","a,%s",aopGet(left,1,FALSE,FALSE,NULL));
6233 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
6234 emitcode ("xch", "a,b");
6235 emitcode ("cpl","a");
6236 emitcode ("add", "a,#1");
6237 emitcode ("xch", "a,b");
6238 emitcode ("cpl", "a"); // msb
6239 emitcode ("addc","a,#0");
6241 emitcode ("mov","ma,b");
6242 emitcode ("mov","ma,a");
6244 emitcode ("mov","ma,%s",aopGet(left,0,FALSE,FALSE,NULL));
6245 emitcode ("mov","ma,%s",aopGet(left,1,FALSE,FALSE,NULL));
6248 /* load up MB with right */
6250 if (AOP_TYPE(right) == AOP_LIT) {
6251 int val=(int) ulFromVal (AOP (right)->aopu.aop_lit);
6255 emitcode ("mov","mb,#!constbyte",val & 0xff);
6256 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
6258 lbl = newiTempLabel(NULL);
6259 emitcode ("mov","b,%s",aopGet(right,0,FALSE,FALSE,NULL));
6260 emitcode ("mov","a,%s",aopGet(right,1,FALSE,FALSE,NULL));
6261 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
6262 emitcode ("xch", "a,b");
6263 emitcode ("cpl","a");
6264 emitcode ("add", "a,#1");
6265 emitcode ("xch", "a,b");
6266 emitcode ("cpl", "a"); // msb
6267 emitcode ("addc", "a,#0");
6269 emitcode ("mov","mb,b");
6270 emitcode ("mov","mb,a");
6273 emitcode ("mov","mb,%s",aopGet(right,0,FALSE,FALSE,NULL));
6274 emitcode ("mov","mb,%s",aopGet(right,1,FALSE,FALSE,NULL));
6277 /* wait for multiplication to finish */
6278 lbl = newiTempLabel(NULL);
6280 emitcode("mov","a,mcnt1");
6281 emitcode("anl","a,#!constbyte",0x80);
6282 emitcode("jnz","!tlabel",lbl->key+100);
6284 freeAsmop (left, NULL, ic, TRUE);
6285 freeAsmop (right, NULL, ic,TRUE);
6286 aopOp(result, ic, TRUE, FALSE);
6288 aopPut(result,"mb",1);
6289 aopPut(result,"mb",0);
6290 freeAsmop (result, NULL, ic, TRUE);
6292 /* restore EA bit in F1 */
6293 lbl = newiTempLabel(NULL);
6294 emitcode ("jnb","F1,!tlabel",lbl->key+100);
6295 emitcode ("setb","EA");
6299 /*-----------------------------------------------------------------*/
6300 /* genMod - generates code for division */
6301 /*-----------------------------------------------------------------*/
6305 operand *left = IC_LEFT (ic);
6306 operand *right = IC_RIGHT (ic);
6307 operand *result = IC_RESULT (ic);
6309 D (emitcode (";", "genMod"));
6311 /* assign the asmops */
6314 /* special cases first */
6316 if (AOP_TYPE (left) == AOP_CRY &&
6317 AOP_TYPE (right) == AOP_CRY)
6319 genModbits (left, right, result, ic);
6323 /* if both are of size == 1 */
6324 if (AOP_SIZE (left) == 1 &&
6325 AOP_SIZE (right) == 1)
6327 genModOneByte (left, right, result, ic);
6331 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
6332 /* use the ds390 ARITHMETIC accel UNIT */
6333 genModTwoByte (left, right, result, ic);
6337 /* should have been converted to function call */
6341 freeAsmop (result, NULL, ic, TRUE);
6342 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6343 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6346 /*-----------------------------------------------------------------*/
6347 /* genIfxJump :- will create a jump depending on the ifx */
6348 /*-----------------------------------------------------------------*/
6350 genIfxJump (iCode * ic, char *jval)
6353 symbol *tlbl = newiTempLabel (NULL);
6356 D (emitcode (";", "genIfxJump"));
6358 /* if true label then we jump if condition
6362 jlbl = IC_TRUE (ic);
6363 inst = ((strcmp (jval, "a") == 0 ? "jz" :
6364 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
6368 /* false label is present */
6369 jlbl = IC_FALSE (ic);
6370 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
6371 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
6373 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
6374 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
6376 emitcode (inst, "!tlabel", tlbl->key + 100);
6377 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
6380 /* mark the icode as generated */
6384 /*-----------------------------------------------------------------*/
6385 /* genCmp :- greater or less than comparison */
6386 /*-----------------------------------------------------------------*/
6388 genCmp (operand * left, operand * right,
6389 iCode * ic, iCode * ifx, int sign)
6391 int size, offset = 0;
6392 unsigned long lit = 0L;
6395 D (emitcode (";", "genCmp"));
6397 result = IC_RESULT (ic);
6399 /* if left & right are bit variables */
6400 if (AOP_TYPE (left) == AOP_CRY &&
6401 AOP_TYPE (right) == AOP_CRY)
6403 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6404 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6408 /* subtract right from left if at the
6409 end the carry flag is set then we know that
6410 left is greater than right */
6411 size = max (AOP_SIZE (left), AOP_SIZE (right));
6413 /* if unsigned char cmp with lit, do cjne left,#right,zz */
6414 if ((size == 1) && !sign &&
6415 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
6417 symbol *lbl = newiTempLabel (NULL);
6418 emitcode ("cjne", "%s,%s,!tlabel",
6419 aopGet (left, offset, FALSE, FALSE, NULL),
6420 aopGet (right, offset, FALSE, FALSE, NULL),
6426 if (AOP_TYPE (right) == AOP_LIT)
6428 lit = ulFromVal (AOP (right)->aopu.aop_lit);
6429 /* optimize if(x < 0) or if(x >= 0) */
6438 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
6440 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6441 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6443 aopOp (result, ic, FALSE, FALSE);
6445 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
6447 freeAsmop (result, NULL, ic, TRUE);
6448 genIfxJump (ifx, "acc.7");
6453 emitcode ("rlc", "a");
6455 goto release_freedLR;
6463 // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
6464 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
6465 // emitcode (";", "genCmp #2");
6466 if (sign && (size == 0))
6468 // emitcode (";", "genCmp #3");
6469 emitcode ("xrl", "a,#!constbyte",0x80);
6470 if (AOP_TYPE (right) == AOP_LIT)
6472 unsigned long lit = ulFromVal (AOP (right)->aopu.aop_lit);
6473 // emitcode (";", "genCmp #3.1");
6474 emitcode ("subb", "a,#!constbyte",
6475 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
6479 // emitcode (";", "genCmp #3.2");
6481 MOVB (aopGet (right, offset++, FALSE, FALSE, "b"));
6482 saveAccWarn = DEFAULT_ACC_WARNING;
6483 emitcode ("xrl", "b,#!constbyte",0x80);
6484 emitcode ("subb", "a,b");
6491 // emitcode (";", "genCmp #4");
6493 s = aopGet (right, offset++, FALSE, FALSE, "b");
6494 saveAccWarn = DEFAULT_ACC_WARNING;
6496 emitcode ("subb", "a,%s", s);
6503 /* Don't need the left & right operands any more; do need the result. */
6504 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6505 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6507 aopOp (result, ic, FALSE, FALSE);
6511 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6517 /* if the result is used in the next
6518 ifx conditional branch then generate
6519 code a little differently */
6522 genIfxJump (ifx, "c");
6528 /* leave the result in acc */
6530 freeAsmop (result, NULL, ic, TRUE);
6533 /*-----------------------------------------------------------------*/
6534 /* genCmpGt :- greater than comparison */
6535 /*-----------------------------------------------------------------*/
6537 genCmpGt (iCode * ic, iCode * ifx)
6539 operand *left, *right;
6540 sym_link *letype, *retype;
6543 D (emitcode (";", "genCmpGt"));
6545 left = IC_LEFT (ic);
6546 right = IC_RIGHT (ic);
6548 letype = getSpec (operandType (left));
6549 retype = getSpec (operandType (right));
6550 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6552 /* assign the left & right amsops */
6555 genCmp (right, left, ic, ifx, sign);
6558 /*-----------------------------------------------------------------*/
6559 /* genCmpLt - less than comparisons */
6560 /*-----------------------------------------------------------------*/
6562 genCmpLt (iCode * ic, iCode * ifx)
6564 operand *left, *right;
6565 sym_link *letype, *retype;
6568 D (emitcode (";", "genCmpLt"));
6570 left = IC_LEFT (ic);
6571 right = IC_RIGHT (ic);
6573 letype = getSpec (operandType (left));
6574 retype = getSpec (operandType (right));
6575 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6577 /* assign the left & right amsops */
6580 genCmp (left, right, ic, ifx, sign);
6583 /*-----------------------------------------------------------------*/
6584 /* gencjneshort - compare and jump if not equal */
6585 /*-----------------------------------------------------------------*/
6587 gencjneshort (operand * left, operand * right, symbol * lbl)
6589 int size = max (AOP_SIZE (left), AOP_SIZE (right));
6591 unsigned long lit = 0L;
6593 D (emitcode (";", "gencjneshort"));
6595 /* if the left side is a literal or
6596 if the right is in a pointer register and left
6598 if ((AOP_TYPE (left) == AOP_LIT) ||
6599 (AOP_TYPE (left) == AOP_IMMD) ||
6600 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6607 if (AOP_TYPE (right) == AOP_LIT)
6608 lit = ulFromVal (AOP (right)->aopu.aop_lit);
6610 if (opIsGptr (left) || opIsGptr (right))
6612 /* We are comparing a generic pointer to something.
6613 * Exclude the generic type byte from the comparison.
6616 D (emitcode (";", "cjneshort: generic ptr special case."););
6620 /* if the right side is a literal then anything goes */
6621 if (AOP_TYPE (right) == AOP_LIT &&
6622 AOP_TYPE (left) != AOP_DIR)
6626 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
6627 emitcode ("cjne", "a,%s,!tlabel",
6628 aopGet (right, offset, FALSE, FALSE, NULL),
6634 /* if the right side is in a register or in direct space or
6635 if the left is a pointer register & right is not */
6636 else if (AOP_TYPE (right) == AOP_REG ||
6637 AOP_TYPE (right) == AOP_DIR ||
6638 AOP_TYPE (right) == AOP_LIT ||
6639 AOP_TYPE (right) == AOP_IMMD ||
6640 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6641 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6645 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
6646 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6647 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6648 emitcode ("jnz", "!tlabel", lbl->key + 100);
6650 emitcode ("cjne", "a,%s,!tlabel",
6651 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG),
6658 /* right is a pointer reg need both a & b */
6661 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
6662 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
6663 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
6669 /*-----------------------------------------------------------------*/
6670 /* gencjne - compare and jump if not equal */
6671 /*-----------------------------------------------------------------*/
6673 gencjne (operand * left, operand * right, symbol * lbl)
6675 symbol *tlbl = newiTempLabel (NULL);
6677 D (emitcode (";", "gencjne"));
6679 gencjneshort (left, right, lbl);
6681 emitcode ("mov", "a,%s", one);
6682 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
6684 emitcode ("clr", "a");
6688 /*-----------------------------------------------------------------*/
6689 /* genCmpEq - generates code for equal to */
6690 /*-----------------------------------------------------------------*/
6692 genCmpEq (iCode * ic, iCode * ifx)
6694 operand *left, *right, *result;
6696 D (emitcode (";", "genCmpEq"));
6699 AOP_SET_LOCALS (ic);
6701 /* if literal, literal on the right or
6702 if the right is in a pointer register and left
6704 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6705 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6707 operand *t = IC_RIGHT (ic);
6708 IC_RIGHT (ic) = IC_LEFT (ic);
6712 if (ifx && /* !AOP_SIZE(result) */
6713 OP_SYMBOL (result) &&
6714 OP_SYMBOL (result)->regType == REG_CND)
6717 /* if they are both bit variables */
6718 if (AOP_TYPE (left) == AOP_CRY &&
6719 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6721 if (AOP_TYPE (right) == AOP_LIT)
6723 unsigned long lit = ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6726 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6727 emitcode ("cpl", "c");
6731 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6735 emitcode ("clr", "c");
6737 /* AOP_TYPE(right) == AOP_CRY */
6741 symbol *lbl = newiTempLabel (NULL);
6742 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6743 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6744 emitcode ("cpl", "c");
6747 /* if true label then we jump if condition
6749 tlbl = newiTempLabel (NULL);
6752 emitcode ("jnc", "!tlabel", tlbl->key + 100);
6753 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6757 emitcode ("jc", "!tlabel", tlbl->key + 100);
6758 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6764 tlbl = newiTempLabel (NULL);
6765 gencjneshort (left, right, tlbl);
6768 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6773 symbol *lbl = newiTempLabel (NULL);
6774 emitcode ("sjmp", "!tlabel", lbl->key + 100);
6776 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6780 /* mark the icode as generated */
6783 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6784 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6788 /* if they are both bit variables */
6789 if (AOP_TYPE (left) == AOP_CRY &&
6790 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6792 if (AOP_TYPE (right) == AOP_LIT)
6794 unsigned long lit = ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6797 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6798 emitcode ("cpl", "c");
6802 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6806 emitcode ("clr", "c");
6808 /* AOP_TYPE(right) == AOP_CRY */
6812 symbol *lbl = newiTempLabel (NULL);
6813 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6814 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6815 emitcode ("cpl", "c");
6819 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6820 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6822 aopOp (result, ic, TRUE, FALSE);
6825 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6832 genIfxJump (ifx, "c");
6835 /* if the result is used in an arithmetic operation
6836 then put the result in place */
6841 gencjne (left, right, newiTempLabel (NULL));
6843 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6844 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6846 aopOp (result, ic, TRUE, FALSE);
6848 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6850 aopPut (result, "a", 0);
6855 genIfxJump (ifx, "a");
6858 /* if the result is used in an arithmetic operation
6859 then put the result in place */
6860 if (AOP_TYPE (result) != AOP_CRY)
6862 /* leave the result in acc */
6866 freeAsmop (result, NULL, ic, TRUE);
6869 /*-----------------------------------------------------------------*/
6870 /* ifxForOp - returns the icode containing the ifx for operand */
6871 /*-----------------------------------------------------------------*/
6873 ifxForOp (operand * op, iCode * ic)
6875 /* if true symbol then needs to be assigned */
6876 if (IS_TRUE_SYMOP (op))
6879 /* if this has register type condition and
6880 the next instruction is ifx with the same operand
6881 and live to of the operand is upto the ifx only then */
6883 ic->next->op == IFX &&
6884 IC_COND (ic->next)->key == op->key &&
6885 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6891 /*-----------------------------------------------------------------*/
6892 /* hasInc - operand is incremented before any other use */
6893 /*-----------------------------------------------------------------*/
6895 hasInc (operand *op, iCode *ic, int osize)
6897 sym_link *type = operandType(op);
6898 sym_link *retype = getSpec (type);
6899 iCode *lic = ic->next;
6902 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6903 if (!IS_SYMOP(op)) return NULL;
6905 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6906 if (IS_AGGREGATE(type->next)) return NULL;
6907 if (osize != (isize = getSize(type->next))) return NULL;
6910 /* if operand of the form op = op + <sizeof *op> */
6911 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6912 isOperandEqual(IC_RESULT(lic),op) &&
6913 isOperandLiteral(IC_RIGHT(lic)) &&
6914 operandLitValue(IC_RIGHT(lic)) == isize) {
6917 /* if the operand used or deffed */
6918 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6921 /* if GOTO or IFX */
6922 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6928 /*-----------------------------------------------------------------*/
6929 /* genAndOp - for && operation */
6930 /*-----------------------------------------------------------------*/
6932 genAndOp (iCode * ic)
6934 operand *left, *right, *result;
6937 D (emitcode (";", "genAndOp"));
6939 /* note here that && operations that are in an
6940 if statement are taken away by backPatchLabels
6941 only those used in arthmetic operations remain */
6943 AOP_SET_LOCALS (ic);
6945 /* if both are bit variables */
6946 if (AOP_TYPE (left) == AOP_CRY &&
6947 AOP_TYPE (right) == AOP_CRY)
6949 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6950 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6951 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6952 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6954 aopOp (result,ic,FALSE, FALSE);
6959 tlbl = newiTempLabel (NULL);
6961 emitcode ("jz", "!tlabel", tlbl->key + 100);
6964 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6965 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6967 aopOp (result,ic,FALSE, FALSE);
6971 freeAsmop (result, NULL, ic, TRUE);
6975 /*-----------------------------------------------------------------*/
6976 /* genOrOp - for || operation */
6977 /*-----------------------------------------------------------------*/
6979 genOrOp (iCode * ic)
6981 operand *left, *right, *result;
6984 D (emitcode (";", "genOrOp"));
6986 /* note here that || operations that are in an
6987 if statement are taken away by backPatchLabels
6988 only those used in arthmetic operations remain */
6990 AOP_SET_LOCALS (ic);
6992 /* if both are bit variables */
6993 if (AOP_TYPE (left) == AOP_CRY &&
6994 AOP_TYPE (right) == AOP_CRY)
6996 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6997 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6998 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6999 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7001 aopOp (result,ic,FALSE, FALSE);
7007 tlbl = newiTempLabel (NULL);
7009 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7012 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7013 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7015 aopOp (result,ic,FALSE, FALSE);
7020 freeAsmop (result, NULL, ic, TRUE);
7023 /*-----------------------------------------------------------------*/
7024 /* isLiteralBit - test if lit == 2^n */
7025 /*-----------------------------------------------------------------*/
7027 isLiteralBit (unsigned long lit)
7029 unsigned long pw[32] =
7030 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
7031 0x100L, 0x200L, 0x400L, 0x800L,
7032 0x1000L, 0x2000L, 0x4000L, 0x8000L,
7033 0x10000L, 0x20000L, 0x40000L, 0x80000L,
7034 0x100000L, 0x200000L, 0x400000L, 0x800000L,
7035 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
7036 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
7039 for (idx = 0; idx < 32; idx++)
7045 /*-----------------------------------------------------------------*/
7046 /* continueIfTrue - */
7047 /*-----------------------------------------------------------------*/
7049 continueIfTrue (iCode * ic)
7052 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
7056 /*-----------------------------------------------------------------*/
7058 /*-----------------------------------------------------------------*/
7060 jumpIfTrue (iCode * ic)
7063 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
7067 /*-----------------------------------------------------------------*/
7068 /* jmpTrueOrFalse - */
7069 /*-----------------------------------------------------------------*/
7071 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
7073 // ugly but optimized by peephole
7076 symbol *nlbl = newiTempLabel (NULL);
7077 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
7079 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
7084 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
7090 // Generate code to perform a bit-wise logic operation
7091 // on two operands in far space (assumed to already have been
7092 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
7093 // in far space. This requires pushing the result on the stack
7094 // then popping it into the result.
7096 genFarFarLogicOp(iCode *ic, char *logicOp)
7098 int size, resultSize, compSize;
7102 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
7103 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
7104 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
7106 _startLazyDPSEvaluation();
7107 for (size = compSize; (size--); offset++)
7109 MOVA (aopGet (IC_LEFT(ic), offset, FALSE, FALSE, NULL));
7110 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
7111 MOVA (aopGet (IC_RIGHT(ic), offset, FALSE, FALSE, NULL));
7113 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
7114 emitcode ("push", "acc");
7116 _endLazyDPSEvaluation();
7118 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7119 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7120 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
7122 resultSize = AOP_SIZE(IC_RESULT(ic));
7124 ADJUST_PUSHED_RESULT(compSize, resultSize);
7126 _startLazyDPSEvaluation();
7129 emitcode ("pop", "acc");
7130 aopPut (IC_RESULT (ic), "a", compSize);
7132 _endLazyDPSEvaluation();
7133 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
7137 /*-----------------------------------------------------------------*/
7138 /* genAnd - code for and */
7139 /*-----------------------------------------------------------------*/
7141 genAnd (iCode * ic, iCode * ifx)
7143 operand *left, *right, *result;
7144 int size, offset = 0;
7145 unsigned long lit = 0L;
7150 D (emitcode (";", "genAnd"));
7152 AOP_OP_3_NOFATAL (ic, pushResult);
7153 AOP_SET_LOCALS (ic);
7157 genFarFarLogicOp(ic, "anl");
7162 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
7164 AOP_TYPE (left), AOP_TYPE (right));
7165 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
7167 AOP_SIZE (left), AOP_SIZE (right));
7170 /* if left is a literal & right is not then exchange them */
7171 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7172 #ifdef LOGIC_OPS_BROKEN
7173 || AOP_NEEDSACC (left)
7177 operand *tmp = right;
7182 /* if result = right then exchange left and right */
7183 if (sameRegs (AOP (result), AOP (right)))
7185 operand *tmp = right;
7190 /* if right is bit then exchange them */
7191 if (AOP_TYPE (right) == AOP_CRY &&
7192 AOP_TYPE (left) != AOP_CRY)
7194 operand *tmp = right;
7198 if (AOP_TYPE (right) == AOP_LIT)
7199 lit = ulFromVal (AOP (right)->aopu.aop_lit);
7201 size = AOP_SIZE (result);
7204 // result = bit & yy;
7205 if (AOP_TYPE (left) == AOP_CRY)
7207 // c = bit & literal;
7208 if (AOP_TYPE (right) == AOP_LIT)
7212 if (size && sameRegs (AOP (result), AOP (left)))
7215 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7220 if (size && (AOP_TYPE (result) == AOP_CRY))
7222 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
7225 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7230 emitcode ("clr", "c");
7235 if (AOP_TYPE (right) == AOP_CRY)
7238 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7239 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
7244 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
7246 emitcode ("rrc", "a");
7247 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
7255 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7256 genIfxJump (ifx, "c");
7260 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7261 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7262 if ((AOP_TYPE (right) == AOP_LIT) &&
7263 (AOP_TYPE (result) == AOP_CRY) &&
7264 (AOP_TYPE (left) != AOP_CRY))
7266 int posbit = isLiteralBit (lit);
7271 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE, NULL));
7275 switch (posbit & 0x07)
7277 case 0: emitcode ("rrc", "a");
7279 case 7: emitcode ("rlc", "a");
7281 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
7290 SNPRINTF (buffer, sizeof(buffer),
7291 "acc.%d", posbit & 0x07);
7292 genIfxJump (ifx, buffer);
7296 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
7303 symbol *tlbl = newiTempLabel (NULL);
7304 int sizel = AOP_SIZE (left);
7306 emitcode ("setb", "c");
7309 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
7311 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7313 if ((posbit = isLiteralBit (bytelit)) != 0)
7314 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
7317 if (bytelit != 0x0FFL)
7318 emitcode ("anl", "a,%s",
7319 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG));
7320 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7325 // bit = left & literal
7328 emitcode ("clr", "c");
7331 // if(left & literal)
7335 jmpTrueOrFalse (ifx, tlbl);
7345 /* if left is same as result */
7346 if (sameRegs (AOP (result), AOP (left)))
7348 for (; size--; offset++)
7350 if (AOP_TYPE (right) == AOP_LIT)
7352 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7353 if (bytelit == 0x0FF)
7355 /* dummy read of volatile operand */
7356 if (isOperandVolatile (left, FALSE))
7357 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7361 else if (bytelit == 0)
7363 aopPut (result, zero, offset);
7365 else if (IS_AOP_PREG (result))
7367 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7368 emitcode ("anl", "a,%s",
7369 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG));
7370 aopPut (result, "a", offset);
7373 emitcode ("anl", "%s,%s",
7374 aopGet (left, offset, FALSE, TRUE, NULL),
7375 aopGet (right, offset, FALSE, FALSE, NULL));
7379 if (AOP_TYPE (left) == AOP_ACC)
7382 emitcode("mov", "a,b");
7383 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7385 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7387 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
7388 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7389 emitcode ("anl", "a,b");
7390 aopPut (result, "a", offset);
7392 else if (aopGetUsesAcc (left, offset))
7394 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7395 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7396 aopPut (result, "a", offset);
7400 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7401 if (IS_AOP_PREG (result))
7403 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7404 aopPut (result, "a", offset);
7407 emitcode ("anl", "%s,a", aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7414 // left & result in different registers
7415 if (AOP_TYPE (result) == AOP_CRY)
7418 // if(size), result in bit
7419 // if(!size && ifx), conditional oper: if(left & right)
7420 symbol *tlbl = newiTempLabel (NULL);
7421 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
7423 emitcode ("setb", "c");
7426 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7427 && AOP_TYPE(left)==AOP_ACC)
7430 emitcode("mov", "a,b");
7431 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, NULL));
7433 else if (AOP_TYPE(left)==AOP_ACC)
7437 bool pushedB = pushB ();
7438 emitcode("mov", "b,a");
7439 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7440 emitcode("anl", "a,b");
7445 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7446 emitcode("anl", "a,b");
7449 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7451 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE, NULL));
7452 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7453 emitcode ("anl", "a,b");
7455 else if (aopGetUsesAcc (left, offset))
7457 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7458 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7462 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7463 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE, DP2_RESULT_REG));
7466 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7476 jmpTrueOrFalse (ifx, tlbl);
7482 for (; (size--); offset++)
7485 // result = left & right
7486 if (AOP_TYPE (right) == AOP_LIT)
7488 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7489 if (bytelit == 0x0FF)
7492 aopGet (left, offset, FALSE, FALSE, NULL),
7496 else if (bytelit == 0)
7498 /* dummy read of volatile operand */
7499 if (isOperandVolatile (left, FALSE))
7500 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7501 aopPut (result, zero, offset);
7504 else if (AOP_TYPE (left) == AOP_ACC)
7508 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, NULL));
7509 aopPut (result, "a", offset);
7514 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE, NULL));
7515 aopPut (result, "b", offset);
7520 // faster than result <- left, anl result,right
7521 // and better if result is SFR
7522 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7523 && AOP_TYPE(left)==AOP_ACC)
7526 emitcode("mov", "a,b");
7527 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, NULL));
7529 else if (AOP_TYPE(left)==AOP_ACC)
7533 bool pushedB = pushB ();
7534 emitcode("mov", "b,a");
7535 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7536 emitcode("anl", "a,b");
7541 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7542 emitcode("anl", "a,b");
7545 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7547 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
7548 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7549 emitcode ("anl", "a,b");
7551 else if (aopGetUsesAcc (left, offset))
7553 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7554 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7558 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7559 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE, DP2_RESULT_REG));
7561 aopPut (result, "a", offset);
7567 freeAsmop (result, NULL, ic, TRUE);
7568 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7569 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7572 /*-----------------------------------------------------------------*/
7573 /* genOr - code for or */
7574 /*-----------------------------------------------------------------*/
7576 genOr (iCode * ic, iCode * ifx)
7578 operand *left, *right, *result;
7579 int size, offset = 0;
7580 unsigned long lit = 0L;
7584 D (emitcode (";", "genOr"));
7586 AOP_OP_3_NOFATAL (ic, pushResult);
7587 AOP_SET_LOCALS (ic);
7591 genFarFarLogicOp(ic, "orl");
7597 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
7599 AOP_TYPE (left), AOP_TYPE (right));
7600 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
7602 AOP_SIZE (left), AOP_SIZE (right));
7605 /* if left is a literal & right is not then exchange them */
7606 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7607 #ifdef LOGIC_OPS_BROKEN
7608 || AOP_NEEDSACC (left) // I think this is a net loss now.
7612 operand *tmp = right;
7617 /* if result = right then exchange them */
7618 if (sameRegs (AOP (result), AOP (right)))
7620 operand *tmp = right;
7625 /* if right is bit then exchange them */
7626 if (AOP_TYPE (right) == AOP_CRY &&
7627 AOP_TYPE (left) != AOP_CRY)
7629 operand *tmp = right;
7633 if (AOP_TYPE (right) == AOP_LIT)
7634 lit = ulFromVal (AOP (right)->aopu.aop_lit);
7636 size = AOP_SIZE (result);
7640 if (AOP_TYPE (left) == AOP_CRY)
7642 if (AOP_TYPE (right) == AOP_LIT)
7644 // c = bit | literal;
7647 // lit != 0 => result = 1
7648 if (AOP_TYPE (result) == AOP_CRY)
7651 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7653 continueIfTrue (ifx);
7656 emitcode ("setb", "c");
7660 // lit == 0 => result = left
7661 if (size && sameRegs (AOP (result), AOP (left)))
7663 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7668 if (AOP_TYPE (right) == AOP_CRY)
7671 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7672 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7677 symbol *tlbl = newiTempLabel (NULL);
7678 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
7679 emitcode ("setb", "c");
7680 emitcode ("jb", "%s,!tlabel",
7681 AOP (left)->aopu.aop_dir, tlbl->key + 100);
7683 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7684 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7686 jmpTrueOrFalse (ifx, tlbl);
7701 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7702 genIfxJump (ifx, "c");
7706 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7707 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7708 if ((AOP_TYPE (right) == AOP_LIT) &&
7709 (AOP_TYPE (result) == AOP_CRY) &&
7710 (AOP_TYPE (left) != AOP_CRY))
7716 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7718 continueIfTrue (ifx);
7723 // lit = 0, result = boolean(left)
7725 emitcode ("setb", "c");
7729 symbol *tlbl = newiTempLabel (NULL);
7730 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7736 genIfxJump (ifx, "a");
7744 /* if left is same as result */
7745 if (sameRegs (AOP (result), AOP (left)))
7747 for (; size--; offset++)
7749 if (AOP_TYPE (right) == AOP_LIT)
7751 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7754 /* dummy read of volatile operand */
7755 if (isOperandVolatile (left, FALSE))
7756 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7760 else if (bytelit == 0x0FF)
7762 aopPut (result, "#0xFF", offset);
7764 else if (IS_AOP_PREG (left))
7766 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7767 emitcode ("orl", "a,%s",
7768 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7769 aopPut (result, "a", offset);
7773 emitcode ("orl", "%s,%s",
7774 aopGet (left, offset, FALSE, TRUE, NULL),
7775 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7780 if (AOP_TYPE (left) == AOP_ACC)
7783 emitcode("mov", "a,b");
7784 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7786 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7788 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE, NULL));
7789 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7790 emitcode ("orl", "a,b");
7791 aopPut (result, "a", offset);
7793 else if (aopGetUsesAcc (left, offset))
7795 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7796 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7797 aopPut (result, "a", offset);
7801 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7802 if (IS_AOP_PREG (left))
7804 emitcode ("orl", "a,%s",
7805 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7806 aopPut (result, "a", offset);
7810 emitcode ("orl", "%s,a",
7811 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7819 // left & result in different registers
7820 if (AOP_TYPE (result) == AOP_CRY)
7823 // if(size), result in bit
7824 // if(!size && ifx), conditional oper: if(left | right)
7825 symbol *tlbl = newiTempLabel (NULL);
7826 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7828 emitcode ("setb", "c");
7831 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7832 && AOP_TYPE(left)==AOP_ACC)
7835 emitcode("mov", "a,b");
7836 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7838 else if (AOP_TYPE(left)==AOP_ACC)
7842 bool pushedB = pushB ();
7843 emitcode("mov", "b,a");
7844 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7845 emitcode("orl", "a,b");
7850 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7851 emitcode("orl", "a,b");
7854 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7856 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
7857 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7858 emitcode ("orl", "a,b");
7860 else if (aopGetUsesAcc (left, offset))
7862 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7863 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7867 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7868 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE, DP2_RESULT_REG));
7871 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7881 jmpTrueOrFalse (ifx, tlbl);
7887 _startLazyDPSEvaluation();
7888 for (; (size--); offset++)
7891 // result = left | right
7892 if (AOP_TYPE (right) == AOP_LIT)
7894 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7898 aopGet (left, offset, FALSE, FALSE, NULL),
7902 else if (bytelit == 0x0FF)
7904 /* dummy read of volatile operand */
7905 if (isOperandVolatile (left, FALSE))
7906 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7907 aopPut (result, "#0xFF", offset);
7911 // faster than result <- left, orl result,right
7912 // and better if result is SFR
7913 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7914 && AOP_TYPE(left)==AOP_ACC)
7917 emitcode("mov", "a,b");
7918 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7920 else if (AOP_TYPE(left)==AOP_ACC)
7924 bool pushedB = pushB ();
7925 emitcode("mov", "b,a");
7926 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7927 emitcode("orl", "a,b");
7932 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7933 emitcode("orl", "a,b");
7936 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7938 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
7939 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7940 emitcode ("orl", "a,b");
7942 else if (aopGetUsesAcc (left, offset))
7944 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7945 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7949 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7950 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE, DP2_RESULT_REG));
7952 aopPut (result, "a", offset);
7954 _endLazyDPSEvaluation();
7959 freeAsmop (result, NULL, ic, TRUE);
7960 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7961 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7964 /*-----------------------------------------------------------------*/
7965 /* genXor - code for xclusive or */
7966 /*-----------------------------------------------------------------*/
7968 genXor (iCode * ic, iCode * ifx)
7970 operand *left, *right, *result;
7971 int size, offset = 0;
7972 unsigned long lit = 0L;
7976 D (emitcode (";", "genXor"));
7978 AOP_OP_3_NOFATAL (ic, pushResult);
7979 AOP_SET_LOCALS (ic);
7983 genFarFarLogicOp(ic, "xrl");
7988 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
7990 AOP_TYPE (left), AOP_TYPE (right));
7991 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
7993 AOP_SIZE (left), AOP_SIZE (right));
7996 /* if left is a literal & right is not ||
7997 if left needs acc & right does not */
7998 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7999 #ifdef LOGIC_OPS_BROKEN
8000 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
8004 operand *tmp = right;
8009 /* if result = right then exchange them */
8010 if (sameRegs (AOP (result), AOP (right)))
8012 operand *tmp = right;
8017 /* if right is bit then exchange them */
8018 if (AOP_TYPE (right) == AOP_CRY &&
8019 AOP_TYPE (left) != AOP_CRY)
8021 operand *tmp = right;
8025 if (AOP_TYPE (right) == AOP_LIT)
8026 lit = ulFromVal (AOP (right)->aopu.aop_lit);
8028 size = AOP_SIZE (result);
8032 if (AOP_TYPE (left) == AOP_CRY)
8034 if (AOP_TYPE (right) == AOP_LIT)
8036 // c = bit & literal;
8039 // lit>>1 != 0 => result = 1
8040 if (AOP_TYPE (result) == AOP_CRY)
8043 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
8045 continueIfTrue (ifx);
8048 emitcode ("setb", "c");
8055 // lit == 0, result = left
8056 if (size && sameRegs (AOP (result), AOP (left)))
8058 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
8062 // lit == 1, result = not(left)
8063 if (size && sameRegs (AOP (result), AOP (left)))
8065 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
8070 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
8071 emitcode ("cpl", "c");
8079 symbol *tlbl = newiTempLabel (NULL);
8080 if (AOP_TYPE (right) == AOP_CRY)
8083 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8087 int sizer = AOP_SIZE (right);
8089 // if val>>1 != 0, result = 1
8090 emitcode ("setb", "c");
8093 MOVA (aopGet (right, sizer - 1, FALSE, FALSE, NULL));
8095 // test the msb of the lsb
8096 emitcode ("anl", "a,#!constbyte",0xfe);
8097 emitcode ("jnz", "!tlabel", tlbl->key + 100);
8101 emitcode ("rrc", "a");
8103 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
8104 emitcode ("cpl", "c");
8112 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
8113 genIfxJump (ifx, "c");
8117 /* if left is same as result */
8118 if (sameRegs (AOP (result), AOP (left)))
8120 for (; size--; offset++)
8122 if (AOP_TYPE (right) == AOP_LIT)
8124 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
8127 /* dummy read of volatile operand */
8128 if (isOperandVolatile (left, FALSE))
8129 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8133 else if (IS_AOP_PREG (left))
8135 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8136 emitcode ("xrl", "a,%s",
8137 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG));
8138 aopPut (result, "a", offset);
8142 emitcode ("xrl", "%s,%s",
8143 aopGet (left, offset, FALSE, TRUE, NULL),
8144 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8149 if (AOP_TYPE (left) == AOP_ACC)
8152 emitcode("mov", "a,b");
8153 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8155 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
8157 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
8158 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8159 emitcode ("xrl", "a,b");
8160 aopPut (result, "a", offset);
8162 else if (aopGetUsesAcc (left, offset))
8164 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8165 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8166 aopPut (result, "a", offset);
8170 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
8171 if (IS_AOP_PREG (left))
8173 emitcode ("xrl", "a,%s",
8174 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
8175 aopPut (result, "a", offset);
8178 emitcode ("xrl", "%s,a",
8179 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
8186 // left & result in different registers
8187 if (AOP_TYPE (result) == AOP_CRY)
8190 // if(size), result in bit
8191 // if(!size && ifx), conditional oper: if(left ^ right)
8192 symbol *tlbl = newiTempLabel (NULL);
8193 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
8196 emitcode ("setb", "c");
8199 if ((AOP_TYPE (right) == AOP_LIT) &&
8200 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
8202 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8204 else if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
8205 && AOP_TYPE(left)==AOP_ACC)
8208 emitcode("mov", "a,b");
8209 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8211 else if (AOP_TYPE(left)==AOP_ACC)
8215 bool pushedB = pushB ();
8216 emitcode("mov", "b,a");
8217 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8218 emitcode("xrl", "a,b");
8223 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8224 emitcode("xrl", "a,b");
8227 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
8229 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
8230 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8231 emitcode ("xrl", "a,b");
8233 else if (aopGetUsesAcc (left, offset))
8235 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8236 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8240 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
8241 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
8244 emitcode ("jnz", "!tlabel", tlbl->key + 100);
8254 jmpTrueOrFalse (ifx, tlbl);
8258 for (; (size--); offset++)
8261 // result = left ^ right
8262 if (AOP_TYPE (right) == AOP_LIT)
8264 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
8268 aopGet (left, offset, FALSE, FALSE, NULL),
8272 D (emitcode (";", "better literal XOR."));
8273 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8274 emitcode ("xrl", "a, %s",
8275 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8279 // faster than result <- left, anl result,right
8280 // and better if result is SFR
8281 if (AOP_TYPE (left) == AOP_ACC)
8283 emitcode ("xrl", "a,%s",
8284 aopGet (right, offset,
8285 FALSE, FALSE, DP2_RESULT_REG));
8289 char *rOp = aopGet (right, offset, FALSE, FALSE, NULL);
8290 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
8292 emitcode("mov", "b,a");
8296 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8297 emitcode ("xrl", "a,%s", rOp);
8300 aopPut (result, "a", offset);
8306 freeAsmop (result, NULL, ic, TRUE);
8307 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
8308 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
8311 /*-----------------------------------------------------------------*/
8312 /* genInline - write the inline code out */
8313 /*-----------------------------------------------------------------*/
8315 genInline (iCode * ic)
8317 char *buffer, *bp, *bp1;
8318 bool inComment = FALSE;
8320 D (emitcode (";", "genInline"));
8322 _G.inLine += (!options.asmpeep);
8324 buffer = bp = bp1 = Safe_strdup (IC_INLINE(ic));
8326 /* emit each line as a code */
8344 /* Add \n for labels, not dirs such as c:\mydir */
8345 if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
8363 _G.inLine -= (!options.asmpeep);
8366 /*-----------------------------------------------------------------*/
8367 /* genRRC - rotate right with carry */
8368 /*-----------------------------------------------------------------*/
8372 operand *left, *result;
8376 D (emitcode (";", "genRRC"));
8378 /* rotate right with carry */
8379 left = IC_LEFT (ic);
8380 result = IC_RESULT (ic);
8381 aopOp (left, ic, FALSE, FALSE);
8382 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8384 /* move it to the result */
8385 size = AOP_SIZE (result);
8389 _startLazyDPSEvaluation ();
8392 l = aopGet (left, offset, FALSE, FALSE, NULL);
8394 emitcode ("rrc", "a");
8395 if (AOP_SIZE (result) > 1)
8396 aopPut (result, "a", offset--);
8398 _endLazyDPSEvaluation ();
8400 /* now we need to put the carry into the
8401 highest order byte of the result */
8402 if (AOP_SIZE (result) > 1)
8404 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE, NULL);
8407 emitcode ("mov", "acc.7,c");
8408 aopPut (result, "a", AOP_SIZE (result) - 1);
8409 freeAsmop (result, NULL, ic, TRUE);
8410 freeAsmop (left, NULL, ic, TRUE);
8413 /*-----------------------------------------------------------------*/
8414 /* genRLC - generate code for rotate left with carry */
8415 /*-----------------------------------------------------------------*/
8419 operand *left, *result;
8423 D (emitcode (";", "genRLC"));
8425 /* rotate right with carry */
8426 left = IC_LEFT (ic);
8427 result = IC_RESULT (ic);
8428 aopOp (left, ic, FALSE, FALSE);
8429 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8431 /* move it to the result */
8432 size = AOP_SIZE (result);
8436 l = aopGet (left, offset, FALSE, FALSE, NULL);
8438 emitcode ("add", "a,acc");
8439 if (AOP_SIZE (result) > 1)
8441 aopPut (result, "a", offset++);
8444 _startLazyDPSEvaluation ();
8447 l = aopGet (left, offset, FALSE, FALSE, NULL);
8449 emitcode ("rlc", "a");
8450 if (AOP_SIZE (result) > 1)
8451 aopPut (result, "a", offset++);
8453 _endLazyDPSEvaluation ();
8455 /* now we need to put the carry into the
8456 highest order byte of the result */
8457 if (AOP_SIZE (result) > 1)
8459 l = aopGet (result, 0, FALSE, FALSE, NULL);
8462 emitcode ("mov", "acc.0,c");
8463 aopPut (result, "a", 0);
8464 freeAsmop (result, NULL, ic, TRUE);
8465 freeAsmop (left, NULL, ic, TRUE);
8468 /*-----------------------------------------------------------------*/
8469 /* genGetHbit - generates code get highest order bit */
8470 /*-----------------------------------------------------------------*/
8472 genGetHbit (iCode * ic)
8474 operand *left, *result;
8476 D (emitcode (";", "genGetHbit"));
8478 left = IC_LEFT (ic);
8479 result = IC_RESULT (ic);
8480 aopOp (left, ic, FALSE, FALSE);
8481 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8483 /* get the highest order byte into a */
8484 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
8485 if (AOP_TYPE (result) == AOP_CRY)
8487 emitcode ("rlc", "a");
8492 emitcode ("rl", "a");
8493 emitcode ("anl", "a,#1");
8498 freeAsmop (result, NULL, ic, TRUE);
8499 freeAsmop (left, NULL, ic, TRUE);
8502 /*-----------------------------------------------------------------*/
8503 /* genSwap - generates code to swap nibbles or bytes */
8504 /*-----------------------------------------------------------------*/
8506 genSwap (iCode * ic)
8508 operand *left, *result;
8510 D(emitcode (";", "genSwap"));
8512 left = IC_LEFT (ic);
8513 result = IC_RESULT (ic);
8514 aopOp (left, ic, FALSE, FALSE);
8515 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8517 _startLazyDPSEvaluation ();
8518 switch (AOP_SIZE (left))
8520 case 1: /* swap nibbles in byte */
8521 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
8522 emitcode ("swap", "a");
8523 aopPut (result, "a", 0);
8525 case 2: /* swap bytes in word */
8526 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
8528 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
8529 aopPut (result, aopGet (left, 1, FALSE, FALSE, NULL), 0);
8530 aopPut (result, "a", 1);
8532 else if (operandsEqu (left, result))
8535 bool pushedB = FALSE, leftInB = FALSE;
8537 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
8538 if (AOP_NEEDSACC (left) || AOP_NEEDSACC (result))
8541 emitcode ("mov", "b,a");
8545 aopPut (result, aopGet (left, 1, FALSE, FALSE, NULL), 0);
8546 aopPut (result, reg, 1);
8553 aopPut (result, aopGet (left, 1, FALSE, FALSE, NULL), 0);
8554 aopPut (result, aopGet (left, 0, FALSE, FALSE, NULL), 1);
8558 wassertl(FALSE, "unsupported SWAP operand size");
8560 _endLazyDPSEvaluation ();
8562 freeAsmop (result, NULL, ic, TRUE);
8563 freeAsmop (left, NULL, ic, TRUE);
8566 /*-----------------------------------------------------------------*/
8567 /* AccRol - rotate left accumulator by known count */
8568 /*-----------------------------------------------------------------*/
8570 AccRol (int shCount)
8572 shCount &= 0x0007; // shCount : 0..7
8579 emitcode ("rl", "a");
8582 emitcode ("rl", "a");
8583 emitcode ("rl", "a");
8586 emitcode ("swap", "a");
8587 emitcode ("rr", "a");
8590 emitcode ("swap", "a");
8593 emitcode ("swap", "a");
8594 emitcode ("rl", "a");
8597 emitcode ("rr", "a");
8598 emitcode ("rr", "a");
8601 emitcode ("rr", "a");
8606 /*-----------------------------------------------------------------*/
8607 /* AccLsh - left shift accumulator by known count */
8608 /*-----------------------------------------------------------------*/
8610 AccLsh (int shCount)
8615 emitcode ("add", "a,acc");
8616 else if (shCount == 2)
8618 emitcode ("add", "a,acc");
8619 emitcode ("add", "a,acc");
8623 /* rotate left accumulator */
8625 /* and kill the lower order bits */
8626 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
8631 /*-----------------------------------------------------------------*/
8632 /* AccRsh - right shift accumulator by known count */
8633 /*-----------------------------------------------------------------*/
8635 AccRsh (int shCount)
8642 emitcode ("rrc", "a");
8646 /* rotate right accumulator */
8647 AccRol (8 - shCount);
8648 /* and kill the higher order bits */
8649 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
8654 #ifdef BETTER_LITERAL_SHIFT
8655 /*-----------------------------------------------------------------*/
8656 /* AccSRsh - signed right shift accumulator by known count */
8657 /*-----------------------------------------------------------------*/
8659 AccSRsh (int shCount)
8666 emitcode ("mov", "c,acc.7");
8667 emitcode ("rrc", "a");
8669 else if (shCount == 2)
8671 emitcode ("mov", "c,acc.7");
8672 emitcode ("rrc", "a");
8673 emitcode ("mov", "c,acc.7");
8674 emitcode ("rrc", "a");
8678 tlbl = newiTempLabel (NULL);
8679 /* rotate right accumulator */
8680 AccRol (8 - shCount);
8681 /* and kill the higher order bits */
8682 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
8683 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8684 emitcode ("orl", "a,#!constbyte",
8685 (unsigned char) ~SRMask[shCount]);
8692 #ifdef BETTER_LITERAL_SHIFT
8693 /*-----------------------------------------------------------------*/
8694 /* shiftR1Left2Result - shift right one byte from left to result */
8695 /*-----------------------------------------------------------------*/
8697 shiftR1Left2Result (operand * left, int offl,
8698 operand * result, int offr,
8699 int shCount, int sign)
8701 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
8702 /* shift right accumulator */
8707 aopPut (result, "a", offr);
8711 #ifdef BETTER_LITERAL_SHIFT
8712 /*-----------------------------------------------------------------*/
8713 /* shiftL1Left2Result - shift left one byte from left to result */
8714 /*-----------------------------------------------------------------*/
8716 shiftL1Left2Result (operand * left, int offl,
8717 operand * result, int offr, int shCount)
8720 l = aopGet (left, offl, FALSE, FALSE, NULL);
8722 /* shift left accumulator */
8724 aopPut (result, "a", offr);
8728 #ifdef BETTER_LITERAL_SHIFT
8729 /*-----------------------------------------------------------------*/
8730 /* movLeft2Result - move byte from left to result */
8731 /*-----------------------------------------------------------------*/
8733 movLeft2Result (operand * left, int offl,
8734 operand * result, int offr, int sign)
8737 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8739 l = aopGet (left, offl, FALSE, FALSE, NULL);
8741 if (*l == '@' && (IS_AOP_PREG (result)))
8743 emitcode ("mov", "a,%s", l);
8744 aopPut (result, "a", offr);
8750 aopPut (result, l, offr);
8754 /* MSB sign in acc.7 ! */
8755 if (getDataSize (left) == offl + 1)
8758 aopPut (result, "a", offr);
8766 #ifdef BETTER_LITERAL_SHIFT
8767 /*-----------------------------------------------------------------*/
8768 /* AccAXRrl1 - right rotate a:x by 1 */
8769 /*-----------------------------------------------------------------*/
8773 emitcode ("mov", "c,acc.0");
8774 emitcode ("xch", "a,%s", x);
8775 emitcode ("rrc", "a");
8776 emitcode ("xch", "a,%s", x);
8777 emitcode ("rrc", "a");
8781 #ifdef BETTER_LITERAL_SHIFT
8783 /*-----------------------------------------------------------------*/
8784 /* AccAXLrl1 - left rotate a:x by 1 */
8785 /*-----------------------------------------------------------------*/
8789 emitcode ("mov", "c,acc.7");
8790 emitcode ("xch", "a,%s", x);
8791 emitcode ("rlc", "a");
8792 emitcode ("xch", "a,%s", x);
8793 emitcode ("rlc", "a");
8797 #ifdef BETTER_LITERAL_SHIFT
8798 /*-----------------------------------------------------------------*/
8799 /* AccAXRsh1 - right shift c->a:x->c by 1 */
8800 /*-----------------------------------------------------------------*/
8804 emitcode ("rrc", "a");
8805 emitcode ("xch", "a,%s", x);
8806 emitcode ("rrc", "a");
8807 emitcode ("xch", "a,%s", x);
8811 #ifdef BETTER_LITERAL_SHIFT
8812 /*-----------------------------------------------------------------*/
8813 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8814 /*-----------------------------------------------------------------*/
8818 emitcode ("xch", "a,%s", x);
8819 emitcode ("add", "a,acc");
8820 emitcode ("xch", "a,%s", x);
8821 emitcode ("rlc", "a");
8825 #ifdef BETTER_LITERAL_SHIFT
8826 /*-----------------------------------------------------------------*/
8827 /* AccAXLsh - left shift a:x by known count (0..7) */
8828 /*-----------------------------------------------------------------*/
8830 AccAXLsh (char *x, int shCount)
8845 case 5: // AAAAABBB:CCCCCDDD
8847 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8849 emitcode ("anl", "a,#!constbyte",
8850 SLMask[shCount]); // BBB00000:CCCCCDDD
8852 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8854 AccRol (shCount); // DDDCCCCC:BBB00000
8856 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8858 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8860 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8862 emitcode ("anl", "a,#!constbyte",
8863 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8865 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8867 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8870 case 6: // AAAAAABB:CCCCCCDD
8871 emitcode ("anl", "a,#!constbyte",
8872 SRMask[shCount]); // 000000BB:CCCCCCDD
8874 AccAXRrl1 (x); // D000000B:BCCCCCCD
8875 AccAXRrl1 (x); // DD000000:BBCCCCCC
8876 emitcode ("xch", "a,%s", x); // BBCCCCCC:DD000000
8878 emitcode ("mov", "c,acc.0"); // c = B
8879 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8880 emitcode("rrc","a");
8881 emitcode("xch","a,%s", x);
8882 emitcode("rrc","a");
8883 emitcode("mov","c,acc.0"); //<< get correct bit
8884 emitcode("xch","a,%s", x);
8886 emitcode("rrc","a");
8887 emitcode("xch","a,%s", x);
8888 emitcode("rrc","a");
8889 emitcode("xch","a,%s", x);
8892 case 7: // a:x <<= 7
8894 emitcode ("anl", "a,#!constbyte",
8895 SRMask[shCount]); // 0000000B:CCCCCCCD
8897 AccAXRrl1 (x); // D0000000:BCCCCCCC
8899 emitcode ("xch", "a,%s", x); // BCCCCCCC:D0000000
8908 #ifdef BETTER_LITERAL_SHIFT
8910 /*-----------------------------------------------------------------*/
8911 /* AccAXRsh - right shift a:x known count (0..7) */
8912 /*-----------------------------------------------------------------*/
8914 AccAXRsh (char *x, int shCount)
8922 AccAXRsh1 (x); // 0->a:x
8927 AccAXRsh1 (x); // 0->a:x
8930 AccAXRsh1 (x); // 0->a:x
8935 case 5: // AAAAABBB:CCCCCDDD = a:x
8937 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8939 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8941 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8943 emitcode ("anl", "a,#!constbyte",
8944 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8946 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8948 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8950 emitcode ("anl", "a,#!constbyte",
8951 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8953 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8955 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8957 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8960 case 6: // AABBBBBB:CCDDDDDD
8962 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDE
8963 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8965 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8967 emitcode ("anl", "a,#!constbyte",
8968 SRMask[shCount]); // 000000AA:BBBBBBCC
8971 case 7: // ABBBBBBB:CDDDDDDD
8973 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8975 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8977 emitcode ("anl", "a,#!constbyte",
8978 SRMask[shCount]); // 0000000A:BBBBBBBC
8987 #ifdef BETTER_LITERAL_SHIFT
8988 /*-----------------------------------------------------------------*/
8989 /* AccAXRshS - right shift signed a:x known count (0..7) */
8990 /*-----------------------------------------------------------------*/
8992 AccAXRshS (char *x, int shCount)
9000 emitcode ("mov", "c,acc.7");
9001 AccAXRsh1 (x); // s->a:x
9005 emitcode ("mov", "c,acc.7");
9006 AccAXRsh1 (x); // s->a:x
9008 emitcode ("mov", "c,acc.7");
9009 AccAXRsh1 (x); // s->a:x
9014 case 5: // AAAAABBB:CCCCCDDD = a:x
9016 tlbl = newiTempLabel (NULL);
9017 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
9019 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
9021 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
9023 emitcode ("anl", "a,#!constbyte",
9024 SRMask[shCount]); // 000CCCCC:BBBAAAAA
9026 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
9028 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
9030 emitcode ("anl", "a,#!constbyte",
9031 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
9033 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
9035 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
9037 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
9039 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
9040 emitcode ("orl", "a,#!constbyte",
9041 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
9044 break; // SSSSAAAA:BBBCCCCC
9046 case 6: // AABBBBBB:CCDDDDDD
9048 tlbl = newiTempLabel (NULL);
9050 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
9051 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
9053 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
9055 emitcode ("anl", "a,#!constbyte",
9056 SRMask[shCount]); // 000000AA:BBBBBBCC
9058 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
9059 emitcode ("orl", "a,#!constbyte",
9060 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
9064 case 7: // ABBBBBBB:CDDDDDDD
9066 tlbl = newiTempLabel (NULL);
9068 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
9070 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
9072 emitcode ("anl", "a,#!constbyte",
9073 SRMask[shCount]); // 0000000A:BBBBBBBC
9075 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
9076 emitcode ("orl", "a,#!constbyte",
9077 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
9087 #ifdef BETTER_LITERAL_SHIFT
9089 _loadLeftIntoAx(char **lsb,
9095 // Get the initial value from left into a pair of registers.
9096 // MSB must be in A, LSB can be any register.
9098 // If the result is held in registers, it is an optimization
9099 // if the LSB can be held in the register which will hold the,
9100 // result LSB since this saves us from having to copy it into
9101 // the result following AccAXLsh.
9103 // If the result is addressed indirectly, this is not a gain.
9104 if (AOP_NEEDSACC(result))
9108 _startLazyDPSEvaluation();
9109 if (AOP_TYPE(left) == AOP_DPTR2)
9112 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE, NULL));
9113 // get LSB in DP2_RESULT_REG.
9114 leftByte = aopGet (left, offl, FALSE, FALSE, DP2_RESULT_REG);
9115 assert(!strcmp(leftByte, DP2_RESULT_REG));
9119 // get LSB into DP2_RESULT_REG
9120 leftByte = aopGet (left, offl, FALSE, FALSE, NULL);
9121 if (strcmp(leftByte, DP2_RESULT_REG))
9124 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
9127 leftByte = aopGet (left, offl + MSB16, FALSE, FALSE, NULL);
9128 assert(strcmp(leftByte, DP2_RESULT_REG));
9131 _endLazyDPSEvaluation();
9132 *lsb = DP2_RESULT_REG;
9136 if (sameRegs (AOP (result), AOP (left)) &&
9137 ((offl + MSB16) == offr))
9139 /* don't crash result[offr] */
9140 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
9141 emitcode ("xch", "a,%s",
9142 aopGet (left, offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
9146 movLeft2Result (left, offl, result, offr, 0);
9147 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE, NULL));
9149 *lsb = aopGet (result, offr, FALSE, FALSE, DP2_RESULT_REG);
9150 assert(strcmp(*lsb,"a"));
9155 _storeAxResults(char *lsb,
9159 _startLazyDPSEvaluation();
9160 if (AOP_NEEDSACC(result))
9162 /* We have to explicitly update the result LSB.
9164 emitcode ("xch","a,%s", lsb);
9165 aopPut (result, "a", offr);
9166 emitcode ("mov","a,%s", lsb);
9168 if (getDataSize (result) > 1)
9170 aopPut (result, "a", offr + MSB16);
9172 _endLazyDPSEvaluation();
9175 /*-----------------------------------------------------------------*/
9176 /* shiftL2Left2Result - shift left two bytes from left to result */
9177 /*-----------------------------------------------------------------*/
9179 shiftL2Left2Result (operand * left, int offl,
9180 operand * result, int offr, int shCount)
9184 _loadLeftIntoAx(&lsb, left, result, offl, offr);
9186 AccAXLsh (lsb, shCount);
9188 _storeAxResults(lsb, result, offr);
9192 #ifdef BETTER_LITERAL_SHIFT
9193 /*-----------------------------------------------------------------*/
9194 /* shiftR2Left2Result - shift right two bytes from left to result */
9195 /*-----------------------------------------------------------------*/
9197 shiftR2Left2Result (operand * left, int offl,
9198 operand * result, int offr,
9199 int shCount, int sign)
9203 _loadLeftIntoAx(&lsb, left, result, offl, offr);
9205 /* a:x >> shCount (x = lsb(result)) */
9208 AccAXRshS(lsb, shCount);
9212 AccAXRsh(lsb, shCount);
9215 _storeAxResults(lsb, result, offr);
9219 /*-----------------------------------------------------------------*/
9220 /* shiftLLeftOrResult - shift left one byte from left, or to result */
9221 /*-----------------------------------------------------------------*/
9223 shiftLLeftOrResult (operand * left, int offl,
9224 operand * result, int offr, int shCount)
9226 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
9227 /* shift left accumulator */
9229 /* or with result */
9230 emitcode ("orl", "a,%s",
9231 aopGet (result, offr, FALSE, FALSE, DP2_RESULT_REG));
9232 /* back to result */
9233 aopPut (result, "a", offr);
9238 /*-----------------------------------------------------------------*/
9239 /* shiftRLeftOrResult - shift right one byte from left,or to result */
9240 /*-----------------------------------------------------------------*/
9242 shiftRLeftOrResult (operand * left, int offl,
9243 operand * result, int offr, int shCount)
9245 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
9246 /* shift right accumulator */
9248 /* or with result */
9249 emitcode ("orl", "a,%s",
9250 aopGet (result, offr, FALSE, FALSE, DP2_RESULT_REG));
9251 /* back to result */
9252 aopPut (result, "a", offr);
9256 #ifdef BETTER_LITERAL_SHIFT
9257 /*-----------------------------------------------------------------*/
9258 /* genlshOne - left shift a one byte quantity by known count */
9259 /*-----------------------------------------------------------------*/
9261 genlshOne (operand * result, operand * left, int shCount)
9263 D (emitcode (";", "genlshOne"));
9265 shiftL1Left2Result (left, LSB, result, LSB, shCount);
9269 #ifdef BETTER_LITERAL_SHIFT
9270 /*-----------------------------------------------------------------*/
9271 /* genlshTwo - left shift two bytes by known amount != 0 */
9272 /*-----------------------------------------------------------------*/
9274 genlshTwo (operand * result, operand * left, int shCount)
9278 D (emitcode (";", "genlshTwo"));
9280 size = getDataSize (result);
9282 /* if shCount >= 8 */
9287 _startLazyDPSEvaluation();
9293 _endLazyDPSEvaluation();
9294 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
9295 aopPut (result, zero, LSB);
9299 movLeft2Result (left, LSB, result, MSB16, 0);
9300 aopPut (result, zero, LSB);
9301 _endLazyDPSEvaluation();
9306 aopPut (result, zero, LSB);
9307 _endLazyDPSEvaluation();
9311 /* 1 <= shCount <= 7 */
9315 shiftL1Left2Result (left, LSB, result, LSB, shCount);
9317 shiftL2Left2Result (left, LSB, result, LSB, shCount);
9324 /*-----------------------------------------------------------------*/
9325 /* shiftLLong - shift left one long from left to result */
9326 /* offl = LSB or MSB16 */
9327 /*-----------------------------------------------------------------*/
9329 shiftLLong (operand * left, operand * result, int offr)
9332 int size = AOP_SIZE (result);
9334 if (size >= LSB + offr)
9336 l = aopGet (left, LSB, FALSE, FALSE, NULL);
9338 emitcode ("add", "a,acc");
9339 if (sameRegs (AOP (left), AOP (result)) &&
9340 size >= MSB16 + offr && offr != LSB)
9341 emitcode ("xch", "a,%s",
9342 aopGet (left, LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
9344 aopPut (result, "a", LSB + offr);
9347 if (size >= MSB16 + offr)
9349 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
9351 l = aopGet (left, MSB16, FALSE, FALSE, TRUE);
9354 emitcode ("rlc", "a");
9355 if (sameRegs (AOP (left), AOP (result)) &&
9356 size >= MSB24 + offr && offr != LSB)
9357 emitcode ("xch", "a,%s",
9358 aopGet (left, MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
9360 aopPut (result, "a", MSB16 + offr);
9363 if (size >= MSB24 + offr)
9365 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
9367 l = aopGet (left, MSB24, FALSE, FALSE, NULL);
9370 emitcode ("rlc", "a");
9371 if (sameRegs (AOP (left), AOP (result)) &&
9372 size >= MSB32 + offr && offr != LSB)
9373 emitcode ("xch", "a,%s",
9374 aopGet (left, MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
9376 aopPut (result, "a", MSB24 + offr);
9379 if (size > MSB32 + offr)
9381 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
9383 l = aopGet (left, MSB32, FALSE, FALSE, NULL);
9386 emitcode ("rlc", "a");
9387 aopPut (result, "a", MSB32 + offr);
9390 aopPut (result, zero, LSB);
9396 /*-----------------------------------------------------------------*/
9397 /* genlshFour - shift four byte by a known amount != 0 */
9398 /*-----------------------------------------------------------------*/
9400 genlshFour (operand * result, operand * left, int shCount)
9404 D (emitcode (";", "genlshFour"));
9406 size = AOP_SIZE (result);
9408 /* if shifting more that 3 bytes */
9413 /* lowest order of left goes to the highest
9414 order of the destination */
9415 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
9417 movLeft2Result (left, LSB, result, MSB32, 0);
9418 aopPut (result, zero, LSB);
9419 aopPut (result, zero, MSB16);
9420 aopPut (result, zero, MSB24);
9424 /* more than two bytes */
9425 else if (shCount >= 16)
9427 /* lower order two bytes goes to higher order two bytes */
9429 /* if some more remaining */
9431 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
9434 movLeft2Result (left, MSB16, result, MSB32, 0);
9435 movLeft2Result (left, LSB, result, MSB24, 0);
9437 aopPut (result, zero, MSB16);
9438 aopPut (result, zero, LSB);
9442 /* if more than 1 byte */
9443 else if (shCount >= 8)
9445 /* lower order three bytes goes to higher order three bytes */
9450 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
9452 movLeft2Result (left, LSB, result, MSB16, 0);
9458 movLeft2Result (left, MSB24, result, MSB32, 0);
9459 movLeft2Result (left, MSB16, result, MSB24, 0);
9460 movLeft2Result (left, LSB, result, MSB16, 0);
9461 aopPut (result, zero, LSB);
9463 else if (shCount == 1)
9464 shiftLLong (left, result, MSB16);
9467 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
9468 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
9469 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
9470 aopPut (result, zero, LSB);
9475 /* 1 <= shCount <= 7 */
9476 else if (shCount <= 2)
9478 shiftLLong (left, result, LSB);
9480 shiftLLong (result, result, LSB);
9482 /* 3 <= shCount <= 7, optimize */
9485 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
9486 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
9487 shiftL2Left2Result (left, LSB, result, LSB, shCount);
9492 #ifdef BETTER_LITERAL_SHIFT
9493 /*-----------------------------------------------------------------*/
9494 /* genLeftShiftLiteral - left shifting by known count */
9495 /*-----------------------------------------------------------------*/
9497 genLeftShiftLiteral (operand * left,
9502 int shCount = (int) ulFromVal (AOP (right)->aopu.aop_lit);
9505 size = getSize (operandType (result));
9507 D (emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
9509 /* We only handle certain easy cases so far. */
9511 && (shCount < (size * 8))
9515 D(emitcode (";", "genLeftShiftLiteral wimping out"););
9519 freeAsmop (right, NULL, ic, TRUE);
9521 aopOp(left, ic, FALSE, FALSE);
9522 aopOp(result, ic, FALSE, AOP_USESDPTR(left));
9525 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
9527 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
9528 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
9530 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
9533 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
9535 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
9536 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
9538 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
9544 emitcode ("; shift left ", "result %d, left %d", size,
9548 /* I suppose that the left size >= result size */
9551 _startLazyDPSEvaluation();
9554 movLeft2Result (left, size, result, size, 0);
9556 _endLazyDPSEvaluation();
9558 else if (shCount >= (size * 8))
9560 _startLazyDPSEvaluation();
9563 aopPut (result, zero, size);
9565 _endLazyDPSEvaluation();
9572 genlshOne (result, left, shCount);
9576 genlshTwo (result, left, shCount);
9580 genlshFour (result, left, shCount);
9584 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9585 "*** ack! mystery literal shift!\n");
9589 freeAsmop (result, NULL, ic, TRUE);
9590 freeAsmop (left, NULL, ic, TRUE);
9595 /*-----------------------------------------------------------------*/
9596 /* genLeftShift - generates code for left shifting */
9597 /*-----------------------------------------------------------------*/
9599 genLeftShift (iCode * ic)
9601 operand *left, *right, *result;
9604 symbol *tlbl, *tlbl1;
9607 D (emitcode (";", "genLeftShift"));
9609 right = IC_RIGHT (ic);
9610 left = IC_LEFT (ic);
9611 result = IC_RESULT (ic);
9613 aopOp (right, ic, FALSE, FALSE);
9616 #ifdef BETTER_LITERAL_SHIFT
9617 /* if the shift count is known then do it
9618 as efficiently as possible */
9619 if (AOP_TYPE (right) == AOP_LIT)
9621 if (genLeftShiftLiteral (left, right, result, ic))
9628 /* shift count is unknown then we have to form
9629 a loop get the loop count in B : Note: we take
9630 only the lower order byte since shifting
9631 more that 32 bits make no sense anyway, ( the
9632 largest size of an object can be only 32 bits ) */
9635 if (AOP_TYPE (right) == AOP_LIT)
9637 /* Really should be handled by genLeftShiftLiteral,
9638 * but since I'm too lazy to fix that today, at least we can make
9639 * some small improvement.
9641 emitcode("mov", "b,#!constbyte",
9642 ((int) ulFromVal (AOP (right)->aopu.aop_lit)) + 1);
9646 MOVB (aopGet (right, 0, FALSE, FALSE, "b"));
9647 emitcode ("inc", "b");
9649 freeAsmop (right, NULL, ic, TRUE);
9650 aopOp (left, ic, FALSE, FALSE);
9651 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9653 /* now move the left to the result if they are not the same */
9654 if (!sameRegs (AOP (left), AOP (result)) &&
9655 AOP_SIZE (result) > 1)
9658 size = AOP_SIZE (result);
9660 _startLazyDPSEvaluation ();
9663 l = aopGet (left, offset, FALSE, TRUE, NULL);
9664 if (*l == '@' && (IS_AOP_PREG (result)))
9667 emitcode ("mov", "a,%s", l);
9668 aopPut (result, "a", offset);
9671 aopPut (result, l, offset);
9674 _endLazyDPSEvaluation ();
9677 tlbl = newiTempLabel (NULL);
9678 size = AOP_SIZE (result);
9680 tlbl1 = newiTempLabel (NULL);
9682 /* if it is only one byte then */
9685 symbol *tlbl1 = newiTempLabel (NULL);
9687 l = aopGet (left, 0, FALSE, FALSE, NULL);
9689 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9691 emitcode ("add", "a,acc");
9693 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9695 aopPut (result, "a", 0);
9699 reAdjustPreg (AOP (result));
9701 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9703 l = aopGet (result, offset, FALSE, FALSE, NULL);
9705 emitcode ("add", "a,acc");
9706 aopPut (result, "a", offset++);
9707 _startLazyDPSEvaluation ();
9710 l = aopGet (result, offset, FALSE, FALSE, NULL);
9712 emitcode ("rlc", "a");
9713 aopPut (result, "a", offset++);
9715 _endLazyDPSEvaluation ();
9716 reAdjustPreg (AOP (result));
9719 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9722 freeAsmop (result, NULL, ic, TRUE);
9723 freeAsmop (left, NULL, ic, TRUE);
9726 #ifdef BETTER_LITERAL_SHIFT
9727 /*-----------------------------------------------------------------*/
9728 /* genrshOne - right shift a one byte quantity by known count */
9729 /*-----------------------------------------------------------------*/
9731 genrshOne (operand * result, operand * left,
9732 int shCount, int sign)
9734 D (emitcode (";", "genrshOne"));
9736 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9740 #ifdef BETTER_LITERAL_SHIFT
9741 /*-----------------------------------------------------------------*/
9742 /* genrshTwo - right shift two bytes by known amount != 0 */
9743 /*-----------------------------------------------------------------*/
9745 genrshTwo (operand * result, operand * left,
9746 int shCount, int sign)
9748 D (emitcode (";", "genrshTwo"));
9750 /* if shCount >= 8 */
9754 _startLazyDPSEvaluation();
9756 shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
9758 movLeft2Result (left, MSB16, result, LSB, sign);
9759 addSign (result, MSB16, sign);
9760 _endLazyDPSEvaluation();
9763 /* 1 <= shCount <= 7 */
9765 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9769 /*-----------------------------------------------------------------*/
9770 /* shiftRLong - shift right one long from left to result */
9771 /* offl = LSB or MSB16 */
9772 /*-----------------------------------------------------------------*/
9774 shiftRLong (operand * left, int offl,
9775 operand * result, int sign)
9777 bool overlapping = regsInCommon (left, result) || operandsEqu(left, result);
9779 if (overlapping && offl>1)
9781 // we are in big trouble, but this shouldn't happen
9782 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9785 MOVA (aopGet (left, MSB32, FALSE, FALSE, NULL));
9792 emitcode ("rlc", "a");
9793 emitcode ("subb", "a,acc");
9794 emitcode ("xch", "a,%s",
9795 aopGet(left, MSB32, FALSE, FALSE, DP2_RESULT_REG));
9799 aopPut (result, zero, MSB32);
9805 emitcode ("clr", "c");
9809 emitcode ("mov", "c,acc.7");
9812 emitcode ("rrc", "a");
9814 if (overlapping && offl==MSB16)
9816 emitcode ("xch", "a,%s", aopGet (left, MSB24, FALSE, FALSE, DP2_RESULT_REG));
9820 aopPut (result, "a", MSB32 - offl);
9821 MOVA (aopGet (left, MSB24, FALSE, FALSE, NULL));
9824 emitcode ("rrc", "a");
9826 if (overlapping && offl==MSB16)
9828 emitcode ("xch", "a,%s", aopGet (left, MSB16, FALSE, FALSE, DP2_RESULT_REG));
9832 aopPut (result, "a", MSB24 - offl);
9833 MOVA (aopGet (left, MSB16, FALSE, FALSE, NULL));
9836 emitcode ("rrc", "a");
9839 aopPut (result, "a", MSB16 - offl);
9843 if (overlapping && offl==MSB16)
9845 emitcode ("xch", "a,%s", aopGet (left, LSB, FALSE, FALSE, DP2_RESULT_REG));
9849 aopPut (result, "a", MSB16 - offl);
9850 MOVA (aopGet (left, LSB, FALSE, FALSE, NULL));
9852 emitcode ("rrc", "a");
9853 aopPut (result, "a", LSB);
9857 /*-----------------------------------------------------------------*/
9858 /* genrshFour - shift four byte by a known amount != 0 */
9859 /*-----------------------------------------------------------------*/
9861 genrshFour (operand * result, operand * left,
9862 int shCount, int sign)
9864 D (emitcode (";", "genrshFour"));
9866 /* if shifting more that 3 bytes */
9870 _startLazyDPSEvaluation();
9872 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9874 movLeft2Result (left, MSB32, result, LSB, sign);
9875 addSign (result, MSB16, sign);
9876 _endLazyDPSEvaluation();
9878 else if (shCount >= 16)
9881 _startLazyDPSEvaluation();
9883 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9886 movLeft2Result (left, MSB24, result, LSB, 0);
9887 movLeft2Result (left, MSB32, result, MSB16, sign);
9889 addSign (result, MSB24, sign);
9890 _endLazyDPSEvaluation();
9892 else if (shCount >= 8)
9895 _startLazyDPSEvaluation();
9898 shiftRLong (left, MSB16, result, sign);
9900 else if (shCount == 0)
9902 movLeft2Result (left, MSB16, result, LSB, 0);
9903 movLeft2Result (left, MSB24, result, MSB16, 0);
9904 movLeft2Result (left, MSB32, result, MSB24, sign);
9905 addSign (result, MSB32, sign);
9909 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9910 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9911 /* the last shift is signed */
9912 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9913 addSign (result, MSB32, sign);
9915 _endLazyDPSEvaluation();
9919 /* 1 <= shCount <= 7 */
9922 shiftRLong (left, LSB, result, sign);
9924 shiftRLong (result, LSB, result, sign);
9928 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9929 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9930 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9935 #ifdef BETTER_LITERAL_SHIFT
9936 /*-----------------------------------------------------------------*/
9937 /* genRightShiftLiteral - right shifting by known count */
9938 /*-----------------------------------------------------------------*/
9940 genRightShiftLiteral (operand * left,
9946 int shCount = (int) ulFromVal (AOP (right)->aopu.aop_lit);
9949 size = getSize (operandType (result));
9951 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
9953 /* We only handle certain easy cases so far. */
9955 && (shCount < (size * 8))
9960 D(emitcode (";", "genRightShiftLiteral wimping out"););
9964 freeAsmop (right, NULL, ic, TRUE);
9966 aopOp (left, ic, FALSE, FALSE);
9967 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9970 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9974 /* test the LEFT size !!! */
9976 /* I suppose that the left size >= result size */
9979 size = getDataSize (result);
9980 _startLazyDPSEvaluation();
9982 movLeft2Result (left, size, result, size, 0);
9983 _endLazyDPSEvaluation();
9985 else if (shCount >= (size * 8))
9989 /* get sign in acc.7 */
9990 MOVA (aopGet (left, size - 1, FALSE, FALSE, NULL));
9992 addSign (result, LSB, sign);
9999 genrshOne (result, left, shCount, sign);
10003 genrshTwo (result, left, shCount, sign);
10007 genrshFour (result, left, shCount, sign);
10014 freeAsmop (result, NULL, ic, TRUE);
10015 freeAsmop (left, NULL, ic, TRUE);
10021 /*-----------------------------------------------------------------*/
10022 /* genSignedRightShift - right shift of signed number */
10023 /*-----------------------------------------------------------------*/
10025 genSignedRightShift (iCode * ic)
10027 operand *right, *left, *result;
10030 symbol *tlbl, *tlbl1;
10033 D (emitcode (";", "genSignedRightShift"));
10035 /* we do it the hard way put the shift count in b
10036 and loop thru preserving the sign */
10038 right = IC_RIGHT (ic);
10039 left = IC_LEFT (ic);
10040 result = IC_RESULT (ic);
10042 aopOp (right, ic, FALSE, FALSE);
10044 #ifdef BETTER_LITERAL_SHIFT
10045 if (AOP_TYPE (right) == AOP_LIT)
10047 if (genRightShiftLiteral (left, right, result, ic, 1))
10053 /* shift count is unknown then we have to form
10054 a loop get the loop count in B : Note: we take
10055 only the lower order byte since shifting
10056 more that 32 bits make no sense anyway, ( the
10057 largest size of an object can be only 32 bits ) */
10059 pushedB = pushB ();
10060 if (AOP_TYPE (right) == AOP_LIT)
10062 /* Really should be handled by genRightShiftLiteral,
10063 * but since I'm too lazy to fix that today, at least we can make
10064 * some small improvement.
10066 emitcode("mov", "b,#!constbyte",
10067 ((int) ulFromVal (AOP (right)->aopu.aop_lit)) + 1);
10071 MOVB (aopGet (right, 0, FALSE, FALSE, "b"));
10072 emitcode ("inc", "b");
10074 freeAsmop (right, NULL, ic, TRUE);
10075 aopOp (left, ic, FALSE, FALSE);
10076 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
10078 /* now move the left to the result if they are not the
10080 if (!sameRegs (AOP (left), AOP (result)) &&
10081 AOP_SIZE (result) > 1)
10084 size = AOP_SIZE (result);
10086 _startLazyDPSEvaluation ();
10089 l = aopGet (left, offset, FALSE, TRUE, NULL);
10090 if (*l == '@' && IS_AOP_PREG (result))
10093 emitcode ("mov", "a,%s", l);
10094 aopPut (result, "a", offset);
10097 aopPut (result, l, offset);
10100 _endLazyDPSEvaluation ();
10103 /* mov the highest order bit to OVR */
10104 tlbl = newiTempLabel (NULL);
10105 tlbl1 = newiTempLabel (NULL);
10107 size = AOP_SIZE (result);
10109 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
10110 emitcode ("rlc", "a");
10111 emitcode ("mov", "ov,c");
10112 /* if it is only one byte then */
10115 l = aopGet (left, 0, FALSE, FALSE, NULL);
10117 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
10119 emitcode ("mov", "c,ov");
10120 emitcode ("rrc", "a");
10122 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
10124 aopPut (result, "a", 0);
10128 reAdjustPreg (AOP (result));
10129 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
10131 emitcode ("mov", "c,ov");
10132 _startLazyDPSEvaluation ();
10135 l = aopGet (result, offset, FALSE, FALSE, NULL);
10137 emitcode ("rrc", "a");
10138 aopPut (result, "a", offset--);
10140 _endLazyDPSEvaluation ();
10141 reAdjustPreg (AOP (result));
10143 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
10147 freeAsmop (result, NULL, ic, TRUE);
10148 freeAsmop (left, NULL, ic, TRUE);
10151 /*-----------------------------------------------------------------*/
10152 /* genRightShift - generate code for right shifting */
10153 /*-----------------------------------------------------------------*/
10155 genRightShift (iCode * ic)
10157 operand *right, *left, *result;
10161 symbol *tlbl, *tlbl1;
10164 D (emitcode (";", "genRightShift"));
10166 /* if signed then we do it the hard way preserve the
10167 sign bit moving it inwards */
10168 letype = getSpec (operandType (IC_LEFT (ic)));
10170 if (!SPEC_USIGN (letype))
10172 genSignedRightShift (ic);
10176 /* signed & unsigned types are treated the same : i.e. the
10177 signed is NOT propagated inwards : quoting from the
10178 ANSI - standard : "for E1 >> E2, is equivalent to division
10179 by 2**E2 if unsigned or if it has a non-negative value,
10180 otherwise the result is implementation defined ", MY definition
10181 is that the sign does not get propagated */
10183 right = IC_RIGHT (ic);
10184 left = IC_LEFT (ic);
10185 result = IC_RESULT (ic);
10187 aopOp (right, ic, FALSE, FALSE);
10189 #ifdef BETTER_LITERAL_SHIFT
10190 /* if the shift count is known then do it
10191 as efficiently as possible */
10192 if (AOP_TYPE (right) == AOP_LIT)
10194 if (genRightShiftLiteral (left, right, result, ic, 0))
10201 /* shift count is unknown then we have to form
10202 a loop get the loop count in B : Note: we take
10203 only the lower order byte since shifting
10204 more that 32 bits make no sense anyway, ( the
10205 largest size of an object can be only 32 bits ) */
10207 pushedB = pushB ();
10208 if (AOP_TYPE (right) == AOP_LIT)
10210 /* Really should be handled by genRightShiftLiteral,
10211 * but since I'm too lazy to fix that today, at least we can make
10212 * some small improvement.
10214 emitcode("mov", "b,#!constbyte",
10215 ((int) ulFromVal (AOP (right)->aopu.aop_lit)) + 1);
10219 MOVB (aopGet (right, 0, FALSE, FALSE, "b"));
10220 emitcode ("inc", "b");
10222 freeAsmop (right, NULL, ic, TRUE);
10223 aopOp (left, ic, FALSE, FALSE);
10224 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
10226 /* now move the left to the result if they are not the
10228 if (!sameRegs (AOP (left), AOP (result)) &&
10229 AOP_SIZE (result) > 1)
10231 size = AOP_SIZE (result);
10233 _startLazyDPSEvaluation ();
10236 l = aopGet (left, offset, FALSE, TRUE, NULL);
10237 if (*l == '@' && IS_AOP_PREG (result))
10240 emitcode ("mov", "a,%s", l);
10241 aopPut (result, "a", offset);
10244 aopPut (result, l, offset);
10247 _endLazyDPSEvaluation ();
10250 tlbl = newiTempLabel (NULL);
10251 tlbl1 = newiTempLabel (NULL);
10252 size = AOP_SIZE (result);
10255 /* if it is only one byte then */
10258 l = aopGet (left, 0, FALSE, FALSE, NULL);
10260 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
10263 emitcode ("rrc", "a");
10265 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
10267 aopPut (result, "a", 0);
10271 reAdjustPreg (AOP (result));
10272 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
10275 _startLazyDPSEvaluation ();
10278 l = aopGet (result, offset, FALSE, FALSE, NULL);
10280 emitcode ("rrc", "a");
10281 aopPut (result, "a", offset--);
10283 _endLazyDPSEvaluation ();
10284 reAdjustPreg (AOP (result));
10287 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
10291 freeAsmop (result, NULL, ic, TRUE);
10292 freeAsmop (left, NULL, ic, TRUE);
10295 /*-----------------------------------------------------------------*/
10296 /* emitPtrByteGet - emits code to get a byte into A through a */
10297 /* pointer register (R0, R1, or DPTR). The */
10298 /* original value of A can be preserved in B. */
10299 /*-----------------------------------------------------------------*/
10301 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
10308 emitcode ("mov", "b,a");
10309 emitcode ("mov", "a,@%s", rname);
10314 emitcode ("mov", "b,a");
10315 emitcode ("movx", "a,@%s", rname);
10320 emitcode ("mov", "b,a");
10321 emitcode ("movx", "a,@dptr");
10326 emitcode ("mov", "b,a");
10327 emitcode ("clr", "a");
10328 emitcode ("movc", "a,@a+dptr");
10334 emitcode ("push", "b");
10335 emitcode ("push", "acc");
10337 emitcode ("lcall", "__gptrget");
10339 emitcode ("pop", "b");
10344 /*-----------------------------------------------------------------*/
10345 /* emitPtrByteSet - emits code to set a byte from src through a */
10346 /* pointer register (R0, R1, or DPTR). */
10347 /*-----------------------------------------------------------------*/
10349 emitPtrByteSet (char *rname, int p_type, char *src)
10358 emitcode ("mov", "@%s,a", rname);
10361 emitcode ("mov", "@%s,%s", rname, src);
10366 emitcode ("movx", "@%s,a", rname);
10371 emitcode ("movx", "@dptr,a");
10376 emitcode ("lcall", "__gptrput");
10381 /*-----------------------------------------------------------------*/
10382 /* genUnpackBits - generates code for unpacking bits */
10383 /*-----------------------------------------------------------------*/
10385 genUnpackBits (operand * result, char *rname, int ptype)
10387 int offset = 0; /* result byte offset */
10388 int rsize; /* result size */
10389 int rlen = 0; /* remaining bitfield length */
10390 sym_link *etype; /* bitfield type information */
10391 int blen; /* bitfield length */
10392 int bstr; /* bitfield starting bit within byte */
10394 D(emitcode (";", "genUnpackBits"));
10396 etype = getSpec (operandType (result));
10397 rsize = getSize (operandType (result));
10398 blen = SPEC_BLEN (etype);
10399 bstr = SPEC_BSTR (etype);
10401 /* If the bitfield length is less than a byte */
10404 emitPtrByteGet (rname, ptype, FALSE);
10406 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
10407 if (!SPEC_USIGN (etype))
10409 /* signed bitfield */
10410 symbol *tlbl = newiTempLabel (NULL);
10412 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
10413 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
10416 aopPut (result, "a", offset++);
10420 /* Bit field did not fit in a byte. Copy all
10421 but the partial byte at the end. */
10422 for (rlen=blen;rlen>=8;rlen-=8)
10424 emitPtrByteGet (rname, ptype, FALSE);
10425 aopPut (result, "a", offset++);
10427 emitcode ("inc", "%s", rname);
10430 /* Handle the partial byte at the end */
10433 emitPtrByteGet (rname, ptype, FALSE);
10434 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
10435 if (!SPEC_USIGN (etype))
10437 /* signed bitfield */
10438 symbol *tlbl = newiTempLabel (NULL);
10440 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
10441 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
10444 aopPut (result, "a", offset++);
10448 if (offset < rsize)
10452 if (SPEC_USIGN (etype))
10456 /* signed bitfield: sign extension with 0x00 or 0xff */
10457 emitcode ("rlc", "a");
10458 emitcode ("subb", "a,acc");
10464 aopPut (result, source, offset++);
10469 /*-----------------------------------------------------------------*/
10470 /* genDataPointerGet - generates code when ptr offset is known */
10471 /*-----------------------------------------------------------------*/
10473 genDataPointerGet (operand * left,
10479 int size, offset = 0;
10480 aopOp (result, ic, TRUE, FALSE);
10482 /* get the string representation of the name */
10483 l = aopGet (left, 0, FALSE, TRUE, NULL);
10484 size = AOP_SIZE (result);
10485 _startLazyDPSEvaluation ();
10490 SNPRINTF (buffer, sizeof(buffer),
10491 "(%s + %d)", l + 1, offset);
10495 SNPRINTF (buffer, sizeof(buffer),
10498 aopPut (result, buffer, offset++);
10500 _endLazyDPSEvaluation ();
10502 freeAsmop (result, NULL, ic, TRUE);
10503 freeAsmop (left, NULL, ic, TRUE);
10506 /*-----------------------------------------------------------------*/
10507 /* genNearPointerGet - emitcode for near pointer fetch */
10508 /*-----------------------------------------------------------------*/
10510 genNearPointerGet (operand * left,
10518 sym_link *rtype, *retype, *letype;
10519 sym_link *ltype = operandType (left);
10522 rtype = operandType (result);
10523 retype = getSpec (rtype);
10524 letype = getSpec (ltype);
10526 aopOp (left, ic, FALSE, FALSE);
10528 /* if left is rematerialisable and
10529 result is not bitfield variable type and
10530 the left is pointer to data space i.e
10531 lower 128 bytes of space */
10532 if (AOP_TYPE (left) == AOP_IMMD &&
10533 !IS_BITFIELD (retype) &&
10534 !IS_BITFIELD (letype) &&
10535 DCL_TYPE (ltype) == POINTER)
10537 genDataPointerGet (left, result, ic);
10541 /* if the value is already in a pointer register
10542 then don't need anything more */
10543 if (!AOP_INPREG (AOP (left)))
10545 /* otherwise get a free pointer register */
10546 aop = newAsmop (0);
10547 preg = getFreePtr (ic, &aop, FALSE);
10548 emitcode ("mov", "%s,%s",
10550 aopGet (left, 0, FALSE, TRUE, DP2_RESULT_REG));
10551 rname = preg->name;
10554 rname = aopGet (left, 0, FALSE, FALSE, DP2_RESULT_REG);
10556 freeAsmop (left, NULL, ic, TRUE);
10557 aopOp (result, ic, FALSE, FALSE);
10559 /* if bitfield then unpack the bits */
10560 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10561 genUnpackBits (result, rname, POINTER);
10564 /* we have can just get the values */
10565 int size = AOP_SIZE (result);
10570 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
10573 emitcode ("mov", "a,@%s", rname);
10574 aopPut (result, "a", offset);
10578 SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
10579 aopPut (result, buffer, offset);
10583 emitcode ("inc", "%s", rname);
10587 /* now some housekeeping stuff */
10588 if (aop) /* we had to allocate for this iCode */
10590 if (pi) { /* post increment present */
10591 aopPut (left, rname, 0);
10593 freeAsmop (NULL, aop, ic, TRUE);
10597 /* we did not allocate which means left
10598 already in a pointer register, then
10599 if size > 0 && this could be used again
10600 we have to point it back to where it
10602 if (AOP_SIZE (result) > 1 &&
10603 !OP_SYMBOL (left)->remat &&
10604 (OP_SYMBOL (left)->liveTo > ic->seq ||
10608 int size = AOP_SIZE (result) - 1;
10610 emitcode ("dec", "%s", rname);
10615 freeAsmop (result, NULL, ic, TRUE);
10616 if (pi) pi->generated = 1;
10619 /*-----------------------------------------------------------------*/
10620 /* genPagedPointerGet - emitcode for paged pointer fetch */
10621 /*-----------------------------------------------------------------*/
10623 genPagedPointerGet (operand * left,
10631 sym_link *rtype, *retype, *letype;
10633 rtype = operandType (result);
10634 retype = getSpec (rtype);
10635 letype = getSpec (operandType (left));
10636 aopOp (left, ic, FALSE, FALSE);
10638 /* if the value is already in a pointer register
10639 then don't need anything more */
10640 if (!AOP_INPREG (AOP (left)))
10642 /* otherwise get a free pointer register */
10643 aop = newAsmop (0);
10644 preg = getFreePtr (ic, &aop, FALSE);
10645 emitcode ("mov", "%s,%s",
10647 aopGet (left, 0, FALSE, TRUE, NULL));
10648 rname = preg->name;
10651 rname = aopGet (left, 0, FALSE, FALSE, NULL);
10653 freeAsmop (left, NULL, ic, TRUE);
10654 aopOp (result, ic, FALSE, FALSE);
10656 /* if bitfield then unpack the bits */
10657 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10658 genUnpackBits (result, rname, PPOINTER);
10661 /* we have can just get the values */
10662 int size = AOP_SIZE (result);
10668 emitcode ("movx", "a,@%s", rname);
10669 aopPut (result, "a", offset);
10674 emitcode ("inc", "%s", rname);
10678 /* now some housekeeping stuff */
10679 if (aop) /* we had to allocate for this iCode */
10682 aopPut (left, rname, 0);
10683 freeAsmop (NULL, aop, ic, TRUE);
10687 /* we did not allocate which means left
10688 already in a pointer register, then
10689 if size > 0 && this could be used again
10690 we have to point it back to where it
10692 if (AOP_SIZE (result) > 1 &&
10693 !OP_SYMBOL (left)->remat &&
10694 (OP_SYMBOL (left)->liveTo > ic->seq ||
10698 int size = AOP_SIZE (result) - 1;
10700 emitcode ("dec", "%s", rname);
10705 freeAsmop (result, NULL, ic, TRUE);
10706 if (pi) pi->generated = 1;
10709 /*-----------------------------------------------------------------*/
10710 /* genFarPointerGet - get value from far space */
10711 /*-----------------------------------------------------------------*/
10713 genFarPointerGet (operand * left,
10714 operand * result, iCode * ic, iCode *pi)
10716 int size, offset, dopi=1;
10717 sym_link *retype = getSpec (operandType (result));
10718 sym_link *letype = getSpec (operandType (left));
10719 D (emitcode (";", "genFarPointerGet"););
10721 aopOp (left, ic, FALSE, FALSE);
10723 /* if the operand is already in dptr
10724 then we do nothing else we move the value to dptr */
10725 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
10727 /* if this is rematerializable */
10728 if (AOP_TYPE (left) == AOP_IMMD)
10730 emitcode ("mov", "dptr,%s", aopGet (left, 0, TRUE, FALSE, NULL));
10734 /* we need to get it byte by byte */
10735 _startLazyDPSEvaluation ();
10736 if (AOP_TYPE (left) != AOP_DPTR)
10738 emitcode ("mov", "dpl,%s", aopGet (left, 0, FALSE, FALSE, NULL));
10739 emitcode ("mov", "dph,%s", aopGet (left, 1, FALSE, FALSE, NULL));
10740 if (options.model == MODEL_FLAT24)
10741 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10745 /* We need to generate a load to DPTR indirect through DPTR. */
10746 D (emitcode (";", "genFarPointerGet -- indirection special case."););
10747 emitcode ("push", "%s", aopGet (left, 0, FALSE, TRUE, NULL));
10748 emitcode ("push", "%s", aopGet (left, 1, FALSE, TRUE, NULL));
10749 if (options.model == MODEL_FLAT24)
10750 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10751 emitcode ("pop", "dph");
10752 emitcode ("pop", "dpl");
10755 _endLazyDPSEvaluation ();
10758 /* so dptr now contains the address */
10759 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10761 /* if bit then unpack */
10762 if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
10763 if (AOP_INDPTRn(left)) {
10764 genSetDPTR(AOP(left)->aopu.dptr);
10766 genUnpackBits (result, "dptr", FPOINTER);
10767 if (AOP_INDPTRn(left)) {
10772 size = AOP_SIZE (result);
10775 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10777 genSetDPTR(AOP(left)->aopu.dptr);
10778 emitcode ("movx", "a,@dptr");
10779 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10780 emitcode ("inc", "dptr");
10782 aopPut (result, "a", offset++);
10785 _startLazyDPSEvaluation ();
10787 if (AOP_INDPTRn(left)) {
10788 genSetDPTR(AOP(left)->aopu.dptr);
10794 emitcode ("movx", "a,@dptr");
10795 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10796 emitcode ("inc", "dptr");
10798 aopPut (result, "a", offset++);
10800 _endLazyDPSEvaluation ();
10803 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10804 if (!AOP_INDPTRn(left)) {
10805 _startLazyDPSEvaluation ();
10806 aopPut (left, "dpl", 0);
10807 aopPut (left, "dph", 1);
10808 if (options.model == MODEL_FLAT24)
10809 aopPut (left, "dpx", 2);
10810 _endLazyDPSEvaluation ();
10813 } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) &&
10814 AOP_SIZE(result) > 1 &&
10816 (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
10818 size = AOP_SIZE (result) - 1;
10819 if (AOP_INDPTRn(left)) {
10820 genSetDPTR(AOP(left)->aopu.dptr);
10822 while (size--) emitcode ("lcall","__decdptr");
10823 if (AOP_INDPTRn(left)) {
10828 freeAsmop (result, NULL, ic, TRUE);
10829 freeAsmop (left, NULL, ic, TRUE);
10832 /*-----------------------------------------------------------------*/
10833 /* genCodePointerGet - get value from code space */
10834 /*-----------------------------------------------------------------*/
10836 genCodePointerGet (operand * left,
10837 operand * result, iCode * ic, iCode *pi)
10839 int size, offset, dopi=1;
10840 sym_link *retype = getSpec (operandType (result));
10842 aopOp (left, ic, FALSE, FALSE);
10844 /* if the operand is already in dptr
10845 then we do nothing else we move the value to dptr */
10846 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
10848 /* if this is rematerializable */
10849 if (AOP_TYPE (left) == AOP_IMMD)
10851 emitcode ("mov", "dptr,%s", aopGet (left, 0, TRUE, FALSE, NULL));
10854 { /* we need to get it byte by byte */
10855 _startLazyDPSEvaluation ();
10856 if (AOP_TYPE (left) != AOP_DPTR)
10858 emitcode ("mov", "dpl,%s", aopGet (left, 0, FALSE, FALSE, NULL));
10859 emitcode ("mov", "dph,%s", aopGet (left, 1, FALSE, FALSE, NULL));
10860 if (options.model == MODEL_FLAT24)
10861 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10865 /* We need to generate a load to DPTR indirect through DPTR. */
10866 D (emitcode (";", "gencodePointerGet -- indirection special case."););
10867 emitcode ("push", "%s", aopGet (left, 0, FALSE, TRUE, NULL));
10868 emitcode ("push", "%s", aopGet (left, 1, FALSE, TRUE, NULL));
10869 if (options.model == MODEL_FLAT24)
10870 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10871 emitcode ("pop", "dph");
10872 emitcode ("pop", "dpl");
10875 _endLazyDPSEvaluation ();
10878 /* so dptr now contains the address */
10879 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10881 /* if bit then unpack */
10882 if (IS_BITFIELD (retype)) {
10883 if (AOP_INDPTRn(left)) {
10884 genSetDPTR(AOP(left)->aopu.dptr);
10886 genUnpackBits (result, "dptr", CPOINTER);
10887 if (AOP_INDPTRn(left)) {
10892 size = AOP_SIZE (result);
10894 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10896 genSetDPTR(AOP(left)->aopu.dptr);
10897 emitcode ("clr", "a");
10898 emitcode ("movc", "a,@a+dptr");
10899 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10900 emitcode ("inc", "dptr");
10902 aopPut (result, "a", offset++);
10905 _startLazyDPSEvaluation ();
10908 if (AOP_INDPTRn(left)) {
10909 genSetDPTR(AOP(left)->aopu.dptr);
10915 emitcode ("clr", "a");
10916 emitcode ("movc", "a,@a+dptr");
10917 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10918 emitcode ("inc", "dptr");
10919 aopPut (result, "a", offset++);
10921 _endLazyDPSEvaluation ();
10924 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10925 if (!AOP_INDPTRn(left)) {
10926 _startLazyDPSEvaluation ();
10928 aopPut (left, "dpl", 0);
10929 aopPut (left, "dph", 1);
10930 if (options.model == MODEL_FLAT24)
10931 aopPut (left, "dpx", 2);
10933 _endLazyDPSEvaluation ();
10936 } else if (IS_SYMOP(left) &&
10937 (OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
10938 AOP_SIZE(result) > 1 &&
10939 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10941 size = AOP_SIZE (result) - 1;
10942 if (AOP_INDPTRn(left)) {
10943 genSetDPTR(AOP(left)->aopu.dptr);
10945 while (size--) emitcode ("lcall","__decdptr");
10946 if (AOP_INDPTRn(left)) {
10951 freeAsmop (result, NULL, ic, TRUE);
10952 freeAsmop (left, NULL, ic, TRUE);
10955 /*-----------------------------------------------------------------*/
10956 /* genGenPointerGet - get value from generic pointer space */
10957 /*-----------------------------------------------------------------*/
10959 genGenPointerGet (operand * left,
10960 operand * result, iCode * ic, iCode * pi)
10964 sym_link *retype = getSpec (operandType (result));
10965 sym_link *letype = getSpec (operandType (left));
10967 D (emitcode (";", "genGenPointerGet"));
10969 aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
10971 pushedB = pushB ();
10972 /* if the operand is already in dptr
10973 then we do nothing else we move the value to dptr */
10974 if (AOP_TYPE (left) != AOP_STR)
10976 /* if this is rematerializable */
10977 if (AOP_TYPE (left) == AOP_IMMD)
10979 emitcode ("mov", "dptr,%s", aopGet (left, 0, TRUE, FALSE, NULL));
10980 if (AOP(left)->aopu.aop_immd.from_cast_remat)
10982 MOVB (aopGet (left, AOP_SIZE(left)-1, FALSE, FALSE, NULL));
10986 emitcode ("mov", "b,#%d", pointerCode (retype));
10990 { /* we need to get it byte by byte */
10991 _startLazyDPSEvaluation ();
10992 emitcode ("mov", "dpl,%s", aopGet (left,0,FALSE,FALSE,NULL));
10993 emitcode ("mov", "dph,%s", aopGet (left,1,FALSE,FALSE,NULL));
10994 if (options.model == MODEL_FLAT24) {
10995 emitcode ("mov", "dpx,%s", aopGet (left,2,FALSE,FALSE,NULL));
10996 emitcode ("mov", "b,%s", aopGet (left,3,FALSE,FALSE,NULL));
10998 emitcode ("mov", "b,%s", aopGet (left,2,FALSE,FALSE,NULL));
11000 _endLazyDPSEvaluation ();
11004 /* so dptr-b now contains the address */
11005 aopOp (result, ic, FALSE, TRUE);
11007 /* if bit then unpack */
11008 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11010 genUnpackBits (result, "dptr", GPOINTER);
11014 size = AOP_SIZE (result);
11021 // Get two bytes at a time, results in _AP & A.
11022 // dptr will be incremented ONCE by __gptrgetWord.
11024 // Note: any change here must be coordinated
11025 // with the implementation of __gptrgetWord
11026 // in device/lib/_gptrget.c
11027 emitcode ("lcall", "__gptrgetWord");
11028 aopPut (result, "a", offset++);
11029 aopPut (result, DP2_RESULT_REG, offset++);
11034 // Only one byte to get.
11035 emitcode ("lcall", "__gptrget");
11036 aopPut (result, "a", offset++);
11039 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
11041 emitcode ("inc", "dptr");
11046 if (pi && AOP_TYPE (left) != AOP_IMMD) {
11047 _startLazyDPSEvaluation ();
11049 aopPut (left, "dpl", 0);
11050 aopPut (left, "dph", 1);
11051 if (options.model == MODEL_FLAT24) {
11052 aopPut (left, "dpx", 2);
11053 aopPut (left, "b", 3);
11054 } else aopPut (left, "b", 2);
11056 _endLazyDPSEvaluation ();
11059 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
11060 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
11062 size = AOP_SIZE (result) - 1;
11063 while (size--) emitcode ("lcall","__decdptr");
11067 freeAsmop (result, NULL, ic, TRUE);
11068 freeAsmop (left, NULL, ic, TRUE);
11071 /*-----------------------------------------------------------------*/
11072 /* genPointerGet - generate code for pointer get */
11073 /*-----------------------------------------------------------------*/
11075 genPointerGet (iCode * ic, iCode *pi)
11077 operand *left, *result;
11078 sym_link *type, *etype;
11081 D (emitcode (";", "genPointerGet"));
11083 left = IC_LEFT (ic);
11084 result = IC_RESULT (ic);
11086 /* depending on the type of pointer we need to
11087 move it to the correct pointer register */
11088 type = operandType (left);
11089 etype = getSpec (type);
11090 /* if left is of type of pointer then it is simple */
11091 if (IS_PTR (type) && !IS_FUNC (type->next))
11092 p_type = DCL_TYPE (type);
11095 /* we have to go by the storage class */
11096 p_type = PTR_TYPE (SPEC_OCLS (etype));
11099 /* special case when cast remat */
11100 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
11101 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
11103 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
11104 type = operandType (left);
11105 p_type = DCL_TYPE (type);
11107 /* now that we have the pointer type we assign
11108 the pointer values */
11114 genNearPointerGet (left, result, ic, pi);
11118 genPagedPointerGet (left, result, ic, pi);
11122 genFarPointerGet (left, result, ic, pi);
11126 genCodePointerGet (left, result, ic, pi);
11130 genGenPointerGet (left, result, ic, pi);
11136 /*-----------------------------------------------------------------*/
11137 /* genPackBits - generates code for packed bit storage */
11138 /*-----------------------------------------------------------------*/
11140 genPackBits (sym_link * etype,
11142 char *rname, int p_type)
11144 int offset = 0; /* source byte offset */
11145 int rlen = 0; /* remaining bitfield length */
11146 int blen; /* bitfield length */
11147 int bstr; /* bitfield starting bit within byte */
11148 int litval; /* source literal value (if AOP_LIT) */
11149 unsigned char mask; /* bitmask within current byte */
11151 D(emitcode (";", "genPackBits"));
11153 blen = SPEC_BLEN (etype);
11154 bstr = SPEC_BSTR (etype);
11156 /* If the bitfield length is less than a byte */
11159 mask = ((unsigned char) (0xFF << (blen + bstr)) |
11160 (unsigned char) (0xFF >> (8 - bstr)));
11162 if (AOP_TYPE (right) == AOP_LIT)
11164 /* Case with a bitfield length <8 and literal source
11166 litval = (int) ulFromVal (AOP (right)->aopu.aop_lit);
11168 litval &= (~mask) & 0xff;
11169 emitPtrByteGet (rname, p_type, FALSE);
11170 if ((mask|litval)!=0xff)
11171 emitcode ("anl","a,#!constbyte", mask);
11173 emitcode ("orl","a,#!constbyte", litval);
11177 if ((blen==1) && (p_type!=GPOINTER))
11179 /* Case with a bitfield length == 1 and no generic pointer
11181 if (AOP_TYPE (right) == AOP_CRY)
11182 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
11185 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
11186 emitcode ("rrc","a");
11188 emitPtrByteGet (rname, p_type, FALSE);
11189 emitcode ("mov","acc.%d,c",bstr);
11194 /* Case with a bitfield length < 8 and arbitrary source
11196 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
11197 /* shift and mask source value */
11199 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
11201 pushedB = pushB ();
11202 /* transfer A to B and get next byte */
11203 emitPtrByteGet (rname, p_type, TRUE);
11205 emitcode ("anl", "a,#!constbyte", mask);
11206 emitcode ("orl", "a,b");
11207 if (p_type == GPOINTER)
11208 emitcode ("pop", "b");
11214 emitPtrByteSet (rname, p_type, "a");
11218 /* Bit length is greater than 7 bits. In this case, copy */
11219 /* all except the partial byte at the end */
11220 for (rlen=blen;rlen>=8;rlen-=8)
11222 emitPtrByteSet (rname, p_type,
11223 aopGet (right, offset++, FALSE, TRUE, NULL) );
11225 emitcode ("inc", "%s", rname);
11228 /* If there was a partial byte at the end */
11231 mask = (((unsigned char) -1 << rlen) & 0xff);
11233 if (AOP_TYPE (right) == AOP_LIT)
11235 /* Case with partial byte and literal source
11237 litval = (int) ulFromVal (AOP (right)->aopu.aop_lit);
11238 litval >>= (blen-rlen);
11239 litval &= (~mask) & 0xff;
11240 emitPtrByteGet (rname, p_type, FALSE);
11241 if ((mask|litval)!=0xff)
11242 emitcode ("anl","a,#!constbyte", mask);
11244 emitcode ("orl","a,#!constbyte", litval);
11249 /* Case with partial byte and arbitrary source
11251 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11252 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
11254 pushedB = pushB ();
11255 /* transfer A to B and get next byte */
11256 emitPtrByteGet (rname, p_type, TRUE);
11258 emitcode ("anl", "a,#!constbyte", mask);
11259 emitcode ("orl", "a,b");
11260 if (p_type == GPOINTER)
11261 emitcode ("pop", "b");
11265 emitPtrByteSet (rname, p_type, "a");
11270 /*-----------------------------------------------------------------*/
11271 /* genDataPointerSet - remat pointer to data space */
11272 /*-----------------------------------------------------------------*/
11274 genDataPointerSet (operand * right,
11278 int size, offset = 0;
11279 char *l, buffer[256];
11281 D (emitcode (";", "genDataPointerSet"));
11283 aopOp (right, ic, FALSE, FALSE);
11285 l = aopGet (result, 0, FALSE, TRUE, NULL);
11286 size = AOP_SIZE (right);
11290 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l + 1, offset);
11292 SNPRINTF (buffer, sizeof(buffer), "%s", l + 1);
11293 emitcode ("mov", "%s,%s", buffer,
11294 aopGet (right, offset++, FALSE, FALSE, NULL));
11297 freeAsmop (result, NULL, ic, TRUE);
11298 freeAsmop (right, NULL, ic, TRUE);
11301 /*-----------------------------------------------------------------*/
11302 /* genNearPointerSet - emitcode for near pointer put */
11303 /*-----------------------------------------------------------------*/
11305 genNearPointerSet (operand * right,
11312 sym_link *retype, *letype;
11313 sym_link *ptype = operandType (result);
11315 D (emitcode (";", "genNearPointerSet"));
11317 retype = getSpec (operandType (right));
11318 letype = getSpec (ptype);
11320 aopOp (result, ic, FALSE, FALSE);
11322 /* if the result is rematerializable &
11323 in data space & not a bit variable */
11324 if (AOP_TYPE (result) == AOP_IMMD &&
11325 DCL_TYPE (ptype) == POINTER &&
11326 !IS_BITVAR (retype) &&
11327 !IS_BITVAR (letype))
11329 genDataPointerSet (right, result, ic);
11333 /* if the value is already in a pointer register
11334 then don't need anything more */
11335 if (!AOP_INPREG (AOP (result)))
11337 /* otherwise get a free pointer register */
11340 aop = newAsmop (0);
11341 preg = getFreePtr (ic, &aop, FALSE);
11342 emitcode ("mov", "%s,%s",
11344 aopGet (result, 0, FALSE, TRUE, NULL));
11345 rname = preg->name;
11349 rname = aopGet (result, 0, FALSE, FALSE, NULL);
11352 aopOp (right, ic, FALSE, FALSE);
11354 /* if bitfield then unpack the bits */
11355 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11356 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
11359 /* we can just get the values */
11360 int size = AOP_SIZE (right);
11365 l = aopGet (right, offset, FALSE, TRUE, NULL);
11366 if ((*l == '@') || (strcmp (l, "acc") == 0))
11369 emitcode ("mov", "@%s,a", rname);
11372 emitcode ("mov", "@%s,%s", rname, l);
11374 emitcode ("inc", "%s", rname);
11379 /* now some housekeeping stuff */
11380 if (aop) /* we had to allocate for this iCode */
11383 aopPut (result, rname, 0);
11384 freeAsmop (NULL, aop, ic, TRUE);
11388 /* we did not allocate which means left
11389 already in a pointer register, then
11390 if size > 0 && this could be used again
11391 we have to point it back to where it
11393 if (AOP_SIZE (right) > 1 &&
11394 !OP_SYMBOL (result)->remat &&
11395 (OP_SYMBOL (result)->liveTo > ic->seq ||
11399 int size = AOP_SIZE (right) - 1;
11401 emitcode ("dec", "%s", rname);
11406 if (pi) pi->generated = 1;
11407 freeAsmop (result, NULL, ic, TRUE);
11408 freeAsmop (right, NULL, ic, TRUE);
11411 /*-----------------------------------------------------------------*/
11412 /* genPagedPointerSet - emitcode for Paged pointer put */
11413 /*-----------------------------------------------------------------*/
11415 genPagedPointerSet (operand * right,
11422 sym_link *retype, *letype;
11424 D (emitcode (";", "genPagedPointerSet"));
11426 retype = getSpec (operandType (right));
11427 letype = getSpec (operandType (result));
11429 aopOp (result, ic, FALSE, FALSE);
11431 /* if the value is already in a pointer register
11432 then don't need anything more */
11433 if (!AOP_INPREG (AOP (result)))
11435 /* otherwise get a free pointer register */
11438 aop = newAsmop (0);
11439 preg = getFreePtr (ic, &aop, FALSE);
11440 emitcode ("mov", "%s,%s",
11442 aopGet (result, 0, FALSE, TRUE, NULL));
11443 rname = preg->name;
11446 rname = aopGet (result, 0, FALSE, FALSE, NULL);
11448 aopOp (right, ic, FALSE, FALSE);
11450 /* if bitfield then unpack the bits */
11451 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11452 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
11455 /* we have can just get the values */
11456 int size = AOP_SIZE (right);
11461 l = aopGet (right, offset, FALSE, TRUE, NULL);
11463 emitcode ("movx", "@%s,a", rname);
11466 emitcode ("inc", "%s", rname);
11472 /* now some housekeeping stuff */
11476 aopPut (result, rname, 0);
11477 /* we had to allocate for this iCode */
11478 freeAsmop (NULL, aop, ic, TRUE);
11482 /* we did not allocate which means left
11483 already in a pointer register, then
11484 if size > 0 && this could be used again
11485 we have to point it back to where it
11487 if (AOP_SIZE (right) > 1 &&
11488 !OP_SYMBOL (result)->remat &&
11489 (OP_SYMBOL (result)->liveTo > ic->seq ||
11493 int size = AOP_SIZE (right) - 1;
11495 emitcode ("dec", "%s", rname);
11500 if (pi) pi->generated = 1;
11501 freeAsmop (result, NULL, ic, TRUE);
11502 freeAsmop (right, NULL, ic, TRUE);
11505 /*-----------------------------------------------------------------*/
11506 /* genFarPointerSet - set value from far space */
11507 /*-----------------------------------------------------------------*/
11509 genFarPointerSet (operand * right,
11510 operand * result, iCode * ic, iCode *pi)
11512 int size, offset, dopi=1;
11513 sym_link *retype = getSpec (operandType (right));
11514 sym_link *letype = getSpec (operandType (result));
11516 aopOp (result, ic, FALSE, FALSE);
11518 /* if the operand is already in dptr
11519 then we do nothing else we move the value to dptr */
11520 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
11522 /* if this is remateriazable */
11523 if (AOP_TYPE (result) == AOP_IMMD)
11524 emitcode ("mov", "dptr,%s",
11525 aopGet (result, 0, TRUE, FALSE, NULL));
11528 /* we need to get it byte by byte */
11529 _startLazyDPSEvaluation ();
11530 if (AOP_TYPE (result) != AOP_DPTR)
11532 emitcode ("mov", "dpl,%s", aopGet (result, 0, FALSE, FALSE, NULL));
11533 emitcode ("mov", "dph,%s", aopGet (result, 1, FALSE, FALSE, NULL));
11534 if (options.model == MODEL_FLAT24)
11535 emitcode ("mov", "dpx,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11539 /* We need to generate a load to DPTR indirect through DPTR. */
11540 D (emitcode (";", "genFarPointerSet -- indirection special case."););
11542 emitcode ("push", "%s", aopGet (result, 0, FALSE, TRUE, NULL));
11543 emitcode ("push", "%s", aopGet (result, 1, FALSE, TRUE, NULL));
11544 if (options.model == MODEL_FLAT24)
11545 emitcode ("mov", "dpx,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11546 emitcode ("pop", "dph");
11547 emitcode ("pop", "dpl");
11550 _endLazyDPSEvaluation ();
11553 /* so dptr now contains the address */
11554 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
11556 /* if bit then unpack */
11557 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11559 if (AOP_INDPTRn(result)) {
11560 genSetDPTR(AOP(result)->aopu.dptr);
11562 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
11563 if (AOP_INDPTRn(result)) {
11567 size = AOP_SIZE (right);
11569 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
11571 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11573 genSetDPTR(AOP(result)->aopu.dptr);
11574 emitcode ("movx", "@dptr,a");
11575 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
11576 emitcode ("inc", "dptr");
11580 _startLazyDPSEvaluation ();
11582 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11584 if (AOP_INDPTRn(result)) {
11585 genSetDPTR(AOP(result)->aopu.dptr);
11591 emitcode ("movx", "@dptr,a");
11592 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
11593 emitcode ("inc", "dptr");
11595 _endLazyDPSEvaluation ();
11599 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
11600 if (!AOP_INDPTRn(result)) {
11601 _startLazyDPSEvaluation ();
11603 aopPut (result,"dpl",0);
11604 aopPut (result,"dph",1);
11605 if (options.model == MODEL_FLAT24)
11606 aopPut (result,"dpx",2);
11608 _endLazyDPSEvaluation ();
11611 } else if (IS_SYMOP (result) &&
11612 (OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
11613 AOP_SIZE(right) > 1 &&
11614 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
11616 size = AOP_SIZE (right) - 1;
11617 if (AOP_INDPTRn(result)) {
11618 genSetDPTR(AOP(result)->aopu.dptr);
11620 while (size--) emitcode ("lcall","__decdptr");
11621 if (AOP_INDPTRn(result)) {
11625 freeAsmop (result, NULL, ic, TRUE);
11626 freeAsmop (right, NULL, ic, TRUE);
11629 /*-----------------------------------------------------------------*/
11630 /* genGenPointerSet - set value from generic pointer space */
11631 /*-----------------------------------------------------------------*/
11633 genGenPointerSet (operand * right,
11634 operand * result, iCode * ic, iCode *pi)
11638 sym_link *retype = getSpec (operandType (right));
11639 sym_link *letype = getSpec (operandType (result));
11641 aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
11643 pushedB = pushB ();
11644 /* if the operand is already in dptr
11645 then we do nothing else we move the value to dptr */
11646 if (AOP_TYPE (result) != AOP_STR)
11648 _startLazyDPSEvaluation ();
11649 /* if this is remateriazable */
11650 if (AOP_TYPE (result) == AOP_IMMD)
11652 emitcode ("mov", "dptr,%s", aopGet (result, 0, TRUE, FALSE, NULL));
11653 if (AOP(result)->aopu.aop_immd.from_cast_remat)
11655 MOVB (aopGet (result, AOP_SIZE(result)-1, FALSE, FALSE, NULL));
11660 "b,%s + 1", aopGet (result, 0, TRUE, FALSE, NULL));
11664 { /* we need to get it byte by byte */
11665 emitcode ("mov", "dpl,%s", aopGet (result, 0, FALSE, FALSE, NULL));
11666 emitcode ("mov", "dph,%s", aopGet (result, 1, FALSE, FALSE, NULL));
11667 if (options.model == MODEL_FLAT24) {
11668 emitcode ("mov", "dpx,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11669 emitcode ("mov", "b,%s", aopGet (result, 3, FALSE, FALSE, NULL));
11671 emitcode ("mov", "b,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11674 _endLazyDPSEvaluation ();
11676 /* so dptr + b now contains the address */
11677 aopOp (right, ic, FALSE, TRUE);
11679 /* if bit then unpack */
11680 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11682 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
11686 size = AOP_SIZE (right);
11689 _startLazyDPSEvaluation ();
11694 // Set two bytes at a time, passed in _AP & A.
11695 // dptr will be incremented ONCE by __gptrputWord.
11697 // Note: any change here must be coordinated
11698 // with the implementation of __gptrputWord
11699 // in device/lib/_gptrput.c
11700 emitcode("mov", "_ap, %s",
11701 aopGet (right, offset++, FALSE, FALSE, NULL));
11702 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11706 emitcode ("lcall", "__gptrputWord");
11711 // Only one byte to put.
11712 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11716 emitcode ("lcall", "__gptrput");
11719 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
11721 emitcode ("inc", "dptr");
11724 _endLazyDPSEvaluation ();
11727 if (pi && AOP_TYPE (result) != AOP_IMMD) {
11728 _startLazyDPSEvaluation ();
11730 aopPut (result, "dpl",0);
11731 aopPut (result, "dph",1);
11732 if (options.model == MODEL_FLAT24) {
11733 aopPut (result, "dpx",2);
11734 aopPut (result, "b",3);
11736 aopPut (result, "b",2);
11738 _endLazyDPSEvaluation ();
11741 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
11742 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
11744 size = AOP_SIZE (right) - 1;
11745 while (size--) emitcode ("lcall","__decdptr");
11749 freeAsmop (result, NULL, ic, TRUE);
11750 freeAsmop (right, NULL, ic, TRUE);
11753 /*-----------------------------------------------------------------*/
11754 /* genPointerSet - stores the value into a pointer location */
11755 /*-----------------------------------------------------------------*/
11757 genPointerSet (iCode * ic, iCode *pi)
11759 operand *right, *result;
11760 sym_link *type, *etype;
11763 D (emitcode (";", "genPointerSet"));
11765 right = IC_RIGHT (ic);
11766 result = IC_RESULT (ic);
11768 /* depending on the type of pointer we need to
11769 move it to the correct pointer register */
11770 type = operandType (result);
11771 etype = getSpec (type);
11772 /* if left is of type of pointer then it is simple */
11773 if (IS_PTR (type) && !IS_FUNC (type->next))
11775 p_type = DCL_TYPE (type);
11779 /* we have to go by the storage class */
11780 p_type = PTR_TYPE (SPEC_OCLS (etype));
11783 /* special case when cast remat */
11784 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
11785 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
11786 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
11787 type = operandType (result);
11788 p_type = DCL_TYPE (type);
11791 /* now that we have the pointer type we assign
11792 the pointer values */
11798 genNearPointerSet (right, result, ic, pi);
11802 genPagedPointerSet (right, result, ic, pi);
11806 genFarPointerSet (right, result, ic, pi);
11810 genGenPointerSet (right, result, ic, pi);
11814 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11815 "genPointerSet: illegal pointer type");
11819 /*-----------------------------------------------------------------*/
11820 /* genIfx - generate code for Ifx statement */
11821 /*-----------------------------------------------------------------*/
11823 genIfx (iCode * ic, iCode * popIc)
11825 operand *cond = IC_COND (ic);
11829 D (emitcode (";", "genIfx"));
11831 aopOp (cond, ic, FALSE, FALSE);
11833 /* get the value into acc */
11834 if (AOP_TYPE (cond) != AOP_CRY)
11841 if (AOP(cond)->aopu.aop_dir)
11842 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
11845 /* the result is now in the accumulator or a directly addressable bit */
11846 freeAsmop (cond, NULL, ic, TRUE);
11848 /* if there was something to be popped then do it */
11852 /* if the condition is a bit variable */
11854 genIfxJump (ic, dup);
11855 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
11856 genIfxJump (ic, SPIL_LOC (cond)->rname);
11857 else if (isbit && !IS_ITEMP (cond))
11858 genIfxJump (ic, OP_SYMBOL (cond)->rname);
11860 genIfxJump (ic, "a");
11865 /*-----------------------------------------------------------------*/
11866 /* genAddrOf - generates code for address of */
11867 /*-----------------------------------------------------------------*/
11869 genAddrOf (iCode * ic)
11871 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
11874 D (emitcode (";", "genAddrOf"));
11876 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11878 /* if the operand is on the stack then we
11879 need to get the stack offset of this
11884 /* if 10 bit stack */
11885 if (options.stack10bit) {
11889 tsprintf(buff, sizeof(buff),
11890 "#!constbyte",(options.stack_loc >> 16) & 0xff);
11891 /* if it has an offset then we need to compute it */
11892 /* emitcode ("subb", "a,#!constbyte", */
11893 /* -((sym->stack < 0) ? */
11894 /* ((short) (sym->stack - _G.nRegsSaved)) : */
11895 /* ((short) sym->stack)) & 0xff); */
11896 /* emitcode ("mov","b,a"); */
11897 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
11898 /* ((short) (sym->stack - _G.nRegsSaved)) : */
11899 /* ((short) sym->stack)) >> 8) & 0xff); */
11901 emitcode ("mov", "a,_bpx");
11902 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
11903 ((char) (sym->stack - _G.nRegsSaved)) :
11904 ((char) sym->stack )) & 0xff);
11905 emitcode ("mov", "b,a");
11906 emitcode ("mov", "a,_bpx+1");
11908 offset = (((sym->stack < 0) ?
11909 ((short) (sym->stack - _G.nRegsSaved)) :
11910 ((short) sym->stack )) >> 8) & 0xff;
11912 emitcode ("addc","a,#!constbyte", offset);
11914 aopPut (IC_RESULT (ic), "b", 0);
11915 aopPut (IC_RESULT (ic), "a", 1);
11916 aopPut (IC_RESULT (ic), buff, 2);
11918 /* we can just move _bp */
11919 aopPut (IC_RESULT (ic), "_bpx", 0);
11920 aopPut (IC_RESULT (ic), "_bpx+1", 1);
11921 aopPut (IC_RESULT (ic), buff, 2);
11924 /* if it has an offset then we need to compute it */
11927 emitcode ("mov", "a,_bp");
11928 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
11929 aopPut (IC_RESULT (ic), "a", 0);
11933 /* we can just move _bp */
11934 aopPut (IC_RESULT (ic), "_bp", 0);
11936 /* fill the result with zero */
11937 size = AOP_SIZE (IC_RESULT (ic)) - 1;
11940 if (options.stack10bit && size < (FPTRSIZE - 1)) {
11942 "*** warning: pointer to stack var truncated.\n");
11948 aopPut (IC_RESULT (ic), zero, offset++);
11954 /* object not on stack then we need the name */
11955 size = AOP_SIZE (IC_RESULT (ic));
11960 char s[SDCC_NAME_MAX];
11964 tsprintf(s, sizeof(s), "#!his",sym->rname);
11967 tsprintf(s, sizeof(s), "#!hihis",sym->rname);
11970 tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
11972 default: /* should not need this (just in case) */
11973 SNPRINTF (s, sizeof(s), "#(%s >> %d)",
11980 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11983 aopPut (IC_RESULT (ic), s, offset++);
11987 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11991 #if 0 // obsolete, and buggy for != xdata
11992 /*-----------------------------------------------------------------*/
11993 /* genArrayInit - generates code for address of */
11994 /*-----------------------------------------------------------------*/
11996 genArrayInit (iCode * ic)
11998 literalList *iLoop;
12000 int elementSize = 0, eIndex;
12001 unsigned val, lastVal;
12003 operand *left=IC_LEFT(ic);
12005 D (emitcode (";", "genArrayInit"));
12007 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
12009 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
12011 // Load immediate value into DPTR.
12012 emitcode("mov", "dptr, %s",
12013 aopGet (IC_LEFT(ic), 0, TRUE, FALSE, NULL));
12015 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
12018 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12019 "Unexpected operand to genArrayInit.\n");
12022 // a regression because of SDCCcse.c:1.52
12023 emitcode ("mov", "dpl,%s", aopGet (left, 0, FALSE, FALSE, NULL));
12024 emitcode ("mov", "dph,%s", aopGet (left, 1, FALSE, FALSE, NULL));
12025 if (options.model == MODEL_FLAT24)
12026 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
12030 type = operandType(IC_LEFT(ic));
12032 if (type && type->next)
12034 elementSize = getSize(type->next);
12038 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12039 "can't determine element size in genArrayInit.\n");
12043 iLoop = IC_ARRAYILIST(ic);
12048 bool firstpass = TRUE;
12050 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
12051 iLoop->count, (int)iLoop->literalValue, elementSize);
12057 symbol *tlbl = NULL;
12059 count = ix > 256 ? 256 : ix;
12063 tlbl = newiTempLabel (NULL);
12064 if (firstpass || (count & 0xff))
12066 emitcode("mov", "b, #!constbyte", count & 0xff);
12074 for (eIndex = 0; eIndex < elementSize; eIndex++)
12076 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
12077 if (val != lastVal)
12079 emitcode("mov", "a, #!constbyte", val);
12083 emitcode("movx", "@dptr, a");
12084 emitcode("inc", "dptr");
12089 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
12095 iLoop = iLoop->next;
12098 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
12102 /*-----------------------------------------------------------------*/
12103 /* genFarFarAssign - assignment when both are in far space */
12104 /*-----------------------------------------------------------------*/
12106 genFarFarAssign (operand * result, operand * right, iCode * ic)
12108 int size = AOP_SIZE (right);
12110 symbol *rSym = NULL;
12114 /* quick & easy case. */
12115 D (emitcode(";","genFarFarAssign (1 byte case)"));
12116 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
12117 freeAsmop (right, NULL, ic, FALSE);
12118 /* now assign DPTR to result */
12120 aopOp(result, ic, FALSE, FALSE);
12122 aopPut (result, "a", 0);
12123 freeAsmop(result, NULL, ic, FALSE);
12127 /* See if we've got an underlying symbol to abuse. */
12128 if (IS_SYMOP(result) && OP_SYMBOL(result))
12130 if (IS_TRUE_SYMOP(result))
12132 rSym = OP_SYMBOL(result);
12134 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
12136 rSym = OP_SYMBOL(result)->usl.spillLoc;
12140 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
12142 /* We can use the '390 auto-toggle feature to good effect here. */
12144 D (emitcode(";", "genFarFarAssign (390 auto-toggle fun)"));
12145 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12146 emitcode ("mov", "dptr,#%s", rSym->rname);
12147 /* DP2 = result, DP1 = right, DP1 is current. */
12150 emitcode("movx", "a,@dptr");
12151 emitcode("movx", "@dptr,a");
12154 emitcode("inc", "dptr");
12155 emitcode("inc", "dptr");
12158 emitcode("mov", "dps,#0");
12159 freeAsmop (right, NULL, ic, FALSE);
12161 some alternative code for processors without auto-toggle
12162 no time to test now, so later well put in...kpb
12163 D (emitcode(";", "genFarFarAssign (dual-dptr fun)"));
12164 emitcode("mov", "dps,#1"); /* Select DPTR2. */
12165 emitcode ("mov", "dptr,#%s", rSym->rname);
12166 /* DP2 = result, DP1 = right, DP1 is current. */
12170 emitcode("movx", "a,@dptr");
12172 emitcode("inc", "dptr");
12173 emitcode("inc", "dps");
12174 emitcode("movx", "@dptr,a");
12176 emitcode("inc", "dptr");
12177 emitcode("inc", "dps");
12179 emitcode("mov", "dps,#0");
12180 freeAsmop (right, NULL, ic, FALSE);
12185 D (emitcode (";", "genFarFarAssign"));
12186 aopOp (result, ic, TRUE, TRUE);
12188 _startLazyDPSEvaluation ();
12193 aopGet (right, offset, FALSE, FALSE, NULL), offset);
12196 _endLazyDPSEvaluation ();
12197 freeAsmop (result, NULL, ic, FALSE);
12198 freeAsmop (right, NULL, ic, FALSE);
12202 /*-----------------------------------------------------------------*/
12203 /* genAssign - generate code for assignment */
12204 /*-----------------------------------------------------------------*/
12206 genAssign (iCode * ic)
12208 operand *result, *right;
12210 unsigned long lit = 0L;
12212 D (emitcode (";", "genAssign"));
12214 result = IC_RESULT (ic);
12215 right = IC_RIGHT (ic);
12217 /* if they are the same */
12218 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
12221 aopOp (right, ic, FALSE, FALSE);
12223 emitcode (";", "genAssign: resultIsFar = %s",
12224 isOperandInFarSpace (result) ?
12227 /* special case both in far space */
12228 if ((AOP_TYPE (right) == AOP_DPTR ||
12229 AOP_TYPE (right) == AOP_DPTR2) &&
12230 /* IS_TRUE_SYMOP(result) && */
12231 isOperandInFarSpace (result))
12233 genFarFarAssign (result, right, ic);
12237 aopOp (result, ic, TRUE, FALSE);
12239 /* if they are the same registers */
12240 if (sameRegs (AOP (right), AOP (result)))
12243 /* if the result is a bit */
12244 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
12246 /* if the right size is a literal then
12247 we know what the value is */
12248 if (AOP_TYPE (right) == AOP_LIT)
12250 if (((int) operandLitValue (right)))
12251 aopPut (result, one, 0);
12253 aopPut (result, zero, 0);
12257 /* the right is also a bit variable */
12258 if (AOP_TYPE (right) == AOP_CRY)
12260 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
12261 aopPut (result, "c", 0);
12265 /* we need to or */
12267 aopPut (result, "a", 0);
12271 /* bit variables done */
12273 size = AOP_SIZE (result);
12275 if (AOP_TYPE (right) == AOP_LIT)
12276 lit = ulFromVal (AOP (right)->aopu.aop_lit);
12279 (AOP_TYPE (result) != AOP_REG) &&
12280 (AOP_TYPE (right) == AOP_LIT) &&
12281 !IS_FLOAT (operandType (right)))
12283 _startLazyDPSEvaluation ();
12284 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
12287 aopGet (right, offset, FALSE, FALSE, NULL),
12292 /* And now fill the rest with zeros. */
12295 emitcode ("clr", "a");
12299 aopPut (result, "a", offset++);
12301 _endLazyDPSEvaluation ();
12305 _startLazyDPSEvaluation ();
12309 aopGet (right, offset, FALSE, FALSE, NULL),
12313 _endLazyDPSEvaluation ();
12317 freeAsmop (result, NULL, ic, TRUE);
12318 freeAsmop (right, NULL, ic, TRUE);
12321 /*-----------------------------------------------------------------*/
12322 /* genJumpTab - generates code for jump table */
12323 /*-----------------------------------------------------------------*/
12325 genJumpTab (iCode * ic)
12330 D (emitcode (";", "genJumpTab"));
12332 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
12333 /* get the condition into accumulator */
12334 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE, NULL);
12336 /* multiply by four! */
12337 emitcode ("add", "a,acc");
12338 emitcode ("add", "a,acc");
12339 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
12341 jtab = newiTempLabel (NULL);
12342 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
12343 emitcode ("jmp", "@a+dptr");
12345 /* now generate the jump labels */
12346 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
12347 jtab = setNextItem (IC_JTLABELS (ic)))
12348 emitcode ("ljmp", "!tlabel", jtab->key + 100);
12352 /*-----------------------------------------------------------------*/
12353 /* genCast - gen code for casting */
12354 /*-----------------------------------------------------------------*/
12356 genCast (iCode * ic)
12358 operand *result = IC_RESULT (ic);
12359 sym_link *ctype = operandType (IC_LEFT (ic));
12360 sym_link *rtype = operandType (IC_RIGHT (ic));
12361 operand *right = IC_RIGHT (ic);
12364 D (emitcode (";", "genCast"));
12366 /* if they are equivalent then do nothing */
12367 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
12370 aopOp (right, ic, FALSE, AOP_IS_STR (result));
12371 aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR));
12373 /* if the result is a bit (and not a bitfield) */
12374 if (IS_BIT (OP_SYMBOL (result)->type))
12376 /* if the right size is a literal then
12377 we know what the value is */
12378 if (AOP_TYPE (right) == AOP_LIT)
12380 if (((int) operandLitValue (right)))
12381 aopPut (result, one, 0);
12383 aopPut (result, zero, 0);
12388 /* the right is also a bit variable */
12389 if (AOP_TYPE (right) == AOP_CRY)
12391 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
12392 aopPut (result, "c", 0);
12396 /* we need to or */
12398 aopPut (result, "a", 0);
12402 /* if they are the same size : or less */
12403 if (AOP_SIZE (result) <= AOP_SIZE (right))
12406 /* if they are in the same place */
12407 if (sameRegs (AOP (right), AOP (result)))
12410 /* if they in different places then copy */
12411 size = AOP_SIZE (result);
12413 _startLazyDPSEvaluation ();
12417 aopGet (right, offset, FALSE, FALSE, NULL),
12421 _endLazyDPSEvaluation ();
12425 /* if the result is of type pointer */
12426 if (IS_PTR (ctype))
12430 sym_link *type = operandType (right);
12432 /* pointer to generic pointer */
12433 if (IS_GENPTR (ctype))
12437 p_type = DCL_TYPE (type);
12441 #if OLD_CAST_BEHAVIOR
12442 /* KV: we are converting a non-pointer type to
12443 * a generic pointer. This (ifdef'd out) code
12444 * says that the resulting generic pointer
12445 * should have the same class as the storage
12446 * location of the non-pointer variable.
12448 * For example, converting an int (which happens
12449 * to be stored in DATA space) to a pointer results
12450 * in a DATA generic pointer; if the original int
12451 * in XDATA space, so will be the resulting pointer.
12453 * I don't like that behavior, and thus this change:
12454 * all such conversions will be forced to XDATA and
12455 * throw a warning. If you want some non-XDATA
12456 * type, or you want to suppress the warning, you
12457 * must go through an intermediate cast, like so:
12459 * char _generic *gp = (char _xdata *)(intVar);
12461 sym_link *etype = getSpec (type);
12463 /* we have to go by the storage class */
12464 if (SPEC_OCLS (etype) != generic)
12466 p_type = PTR_TYPE (SPEC_OCLS (etype));
12471 /* Converting unknown class (i.e. register variable)
12472 * to generic pointer. This is not good, but
12473 * we'll make a guess (and throw a warning).
12476 werror (W_INT_TO_GEN_PTR_CAST);
12480 /* the first two bytes are known */
12481 size = GPTRSIZE - 1;
12483 _startLazyDPSEvaluation ();
12487 aopGet (right, offset, FALSE, FALSE, NULL),
12491 _endLazyDPSEvaluation ();
12493 /* the last byte depending on type */
12495 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
12500 // pointerTypeToGPByte will have bitched.
12504 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%x", gpVal);
12505 aopPut (result, gpValStr, GPTRSIZE - 1);
12510 /* just copy the pointers */
12511 size = AOP_SIZE (result);
12513 _startLazyDPSEvaluation ();
12517 aopGet (right, offset, FALSE, FALSE, NULL),
12521 _endLazyDPSEvaluation ();
12525 /* so we now know that the size of destination is greater
12526 than the size of the source */
12527 /* we move to result for the size of source */
12528 size = AOP_SIZE (right);
12530 _startLazyDPSEvaluation ();
12534 aopGet (right, offset, FALSE, FALSE, NULL),
12538 _endLazyDPSEvaluation ();
12540 /* now depending on the sign of the source && destination */
12541 size = AOP_SIZE (result) - AOP_SIZE (right);
12542 /* if unsigned or not an integral type */
12543 /* also, if the source is a bit, we don't need to sign extend, because
12544 * it can't possibly have set the sign bit.
12546 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
12550 aopPut (result, zero, offset++);
12555 /* we need to extend the sign :{ */
12556 MOVA (aopGet (right, AOP_SIZE (right) - 1,
12557 FALSE, FALSE, NULL));
12558 emitcode ("rlc", "a");
12559 emitcode ("subb", "a,acc");
12561 aopPut (result, "a", offset++);
12564 /* we are done hurray !!!! */
12567 freeAsmop (right, NULL, ic, TRUE);
12568 freeAsmop (result, NULL, ic, TRUE);
12572 /*-----------------------------------------------------------------*/
12573 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
12574 /*-----------------------------------------------------------------*/
12575 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
12577 operand *from , *to , *count;
12582 /* we know it has to be 3 parameters */
12583 assert (nparms == 3);
12585 rsave = newBitVect(16);
12586 /* save DPTR if it needs to be saved */
12587 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12588 if (bitVectBitValue(ic->rMask,i))
12589 rsave = bitVectSetBit(rsave,i);
12591 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12592 ds390_rUmaskForOp (IC_RESULT(ic))));
12599 aopOp (from, ic->next, FALSE, FALSE);
12601 /* get from into DPTR1 */
12602 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12603 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12604 if (options.model == MODEL_FLAT24) {
12605 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12608 freeAsmop (from, NULL, ic, FALSE);
12609 aopOp (to, ic, FALSE, FALSE);
12610 /* get "to" into DPTR */
12611 /* if the operand is already in dptr
12612 then we do nothing else we move the value to dptr */
12613 if (AOP_TYPE (to) != AOP_STR) {
12614 /* if already in DPTR then we need to push */
12615 if (AOP_TYPE(to) == AOP_DPTR) {
12616 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12617 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12618 if (options.model == MODEL_FLAT24)
12619 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12620 emitcode ("pop", "dph");
12621 emitcode ("pop", "dpl");
12623 _startLazyDPSEvaluation ();
12624 /* if this is remateriazable */
12625 if (AOP_TYPE (to) == AOP_IMMD) {
12626 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12627 } else { /* we need to get it byte by byte */
12628 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12629 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12630 if (options.model == MODEL_FLAT24) {
12631 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12634 _endLazyDPSEvaluation ();
12637 freeAsmop (to, NULL, ic, FALSE);
12638 _G.dptrInUse = _G.dptr1InUse = 1;
12639 aopOp (count, ic->next->next, FALSE,FALSE);
12640 lbl =newiTempLabel(NULL);
12642 /* now for the actual copy */
12643 if (AOP_TYPE(count) == AOP_LIT &&
12644 (int) ulFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12645 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12647 emitcode ("lcall","__bi_memcpyc2x_s");
12649 emitcode ("lcall","__bi_memcpyx2x_s");
12651 freeAsmop (count, NULL, ic, FALSE);
12653 symbol *lbl1 = newiTempLabel(NULL);
12655 emitcode (";"," Auto increment but no djnz");
12656 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
12657 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
12658 freeAsmop (count, NULL, ic, FALSE);
12659 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12662 emitcode ("clr","a");
12663 emitcode ("movc", "a,@a+dptr");
12665 emitcode ("movx", "a,@dptr");
12666 emitcode ("movx", "@dptr,a");
12667 emitcode ("inc", "dptr");
12668 emitcode ("inc", "dptr");
12669 emitcode ("mov","a,b");
12670 emitcode ("orl","a,_ap");
12671 emitcode ("jz","!tlabel",lbl1->key+100);
12672 emitcode ("mov","a,_ap");
12673 emitcode ("add","a,#!constbyte",0xFF);
12674 emitcode ("mov","_ap,a");
12675 emitcode ("mov","a,b");
12676 emitcode ("addc","a,#!constbyte",0xFF);
12677 emitcode ("mov","b,a");
12678 emitcode ("sjmp","!tlabel",lbl->key+100);
12681 emitcode ("mov", "dps,#0");
12682 _G.dptrInUse = _G.dptr1InUse = 0;
12683 unsavermask(rsave);
12687 /*-----------------------------------------------------------------*/
12688 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
12689 /*-----------------------------------------------------------------*/
12690 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
12692 operand *from , *to , *count;
12697 /* we know it has to be 3 parameters */
12698 assert (nparms == 3);
12700 rsave = newBitVect(16);
12701 /* save DPTR if it needs to be saved */
12702 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12703 if (bitVectBitValue(ic->rMask,i))
12704 rsave = bitVectSetBit(rsave,i);
12706 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12707 ds390_rUmaskForOp (IC_RESULT(ic))));
12714 aopOp (from, ic->next, FALSE, FALSE);
12716 /* get from into DPTR1 */
12717 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12718 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12719 if (options.model == MODEL_FLAT24) {
12720 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12723 freeAsmop (from, NULL, ic, FALSE);
12724 aopOp (to, ic, FALSE, FALSE);
12725 /* get "to" into DPTR */
12726 /* if the operand is already in dptr
12727 then we do nothing else we move the value to dptr */
12728 if (AOP_TYPE (to) != AOP_STR) {
12729 /* if already in DPTR then we need to push */
12730 if (AOP_TYPE(to) == AOP_DPTR) {
12731 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12732 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12733 if (options.model == MODEL_FLAT24)
12734 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12735 emitcode ("pop", "dph");
12736 emitcode ("pop", "dpl");
12738 _startLazyDPSEvaluation ();
12739 /* if this is remateriazable */
12740 if (AOP_TYPE (to) == AOP_IMMD) {
12741 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12742 } else { /* we need to get it byte by byte */
12743 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12744 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12745 if (options.model == MODEL_FLAT24) {
12746 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12749 _endLazyDPSEvaluation ();
12752 freeAsmop (to, NULL, ic, FALSE);
12753 _G.dptrInUse = _G.dptr1InUse = 1;
12754 aopOp (count, ic->next->next, FALSE,FALSE);
12755 lbl =newiTempLabel(NULL);
12756 lbl2 =newiTempLabel(NULL);
12758 /* now for the actual compare */
12759 if (AOP_TYPE(count) == AOP_LIT &&
12760 (int) ulFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12761 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12763 emitcode("lcall","__bi_memcmpc2x_s");
12765 emitcode("lcall","__bi_memcmpx2x_s");
12766 freeAsmop (count, NULL, ic, FALSE);
12767 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12768 aopPut(IC_RESULT(ic),"a",0);
12769 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12771 symbol *lbl1 = newiTempLabel(NULL);
12773 emitcode("push","ar0");
12774 emitcode (";"," Auto increment but no djnz");
12775 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
12776 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
12777 freeAsmop (count, NULL, ic, FALSE);
12778 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12781 emitcode ("clr","a");
12782 emitcode ("movc", "a,@a+dptr");
12784 emitcode ("movx", "a,@dptr");
12785 emitcode ("mov","r0,a");
12786 emitcode ("movx", "a,@dptr");
12787 emitcode ("clr","c");
12788 emitcode ("subb","a,r0");
12789 emitcode ("jnz","!tlabel",lbl2->key+100);
12790 emitcode ("inc", "dptr");
12791 emitcode ("inc", "dptr");
12792 emitcode ("mov","a,b");
12793 emitcode ("orl","a,_ap");
12794 emitcode ("jz","!tlabel",lbl1->key+100);
12795 emitcode ("mov","a,_ap");
12796 emitcode ("add","a,#!constbyte",0xFF);
12797 emitcode ("mov","_ap,a");
12798 emitcode ("mov","a,b");
12799 emitcode ("addc","a,#!constbyte",0xFF);
12800 emitcode ("mov","b,a");
12801 emitcode ("sjmp","!tlabel",lbl->key+100);
12803 emitcode ("clr","a");
12805 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12806 aopPut(IC_RESULT(ic),"a",0);
12807 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12808 emitcode("pop","ar0");
12809 emitcode ("mov", "dps,#0");
12811 _G.dptrInUse = _G.dptr1InUse = 0;
12812 unsavermask(rsave);
12816 /*-----------------------------------------------------------------*/
12817 /* genInp - gen code for __builtin_inp read data from a mem mapped */
12818 /* port, first parameter output area second parameter pointer to */
12819 /* port third parameter count */
12820 /*-----------------------------------------------------------------*/
12821 static void genInp( iCode *ic, int nparms, operand **parms)
12823 operand *from , *to , *count;
12828 /* we know it has to be 3 parameters */
12829 assert (nparms == 3);
12831 rsave = newBitVect(16);
12832 /* save DPTR if it needs to be saved */
12833 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12834 if (bitVectBitValue(ic->rMask,i))
12835 rsave = bitVectSetBit(rsave,i);
12837 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12838 ds390_rUmaskForOp (IC_RESULT(ic))));
12845 aopOp (from, ic->next, FALSE, FALSE);
12847 /* get from into DPTR1 */
12848 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12849 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12850 if (options.model == MODEL_FLAT24) {
12851 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12854 freeAsmop (from, NULL, ic, FALSE);
12855 aopOp (to, ic, FALSE, FALSE);
12856 /* get "to" into DPTR */
12857 /* if the operand is already in dptr
12858 then we do nothing else we move the value to dptr */
12859 if (AOP_TYPE (to) != AOP_STR) {
12860 /* if already in DPTR then we need to push */
12861 if (AOP_TYPE(to) == AOP_DPTR) {
12862 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12863 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12864 if (options.model == MODEL_FLAT24)
12865 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12866 emitcode ("pop", "dph");
12867 emitcode ("pop", "dpl");
12869 _startLazyDPSEvaluation ();
12870 /* if this is remateriazable */
12871 if (AOP_TYPE (to) == AOP_IMMD) {
12872 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12873 } else { /* we need to get it byte by byte */
12874 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12875 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12876 if (options.model == MODEL_FLAT24) {
12877 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12880 _endLazyDPSEvaluation ();
12883 freeAsmop (to, NULL, ic, FALSE);
12885 _G.dptrInUse = _G.dptr1InUse = 1;
12886 aopOp (count, ic->next->next, FALSE,FALSE);
12887 lbl =newiTempLabel(NULL);
12889 /* now for the actual copy */
12890 if (AOP_TYPE(count) == AOP_LIT &&
12891 (int) ulFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12892 emitcode (";","OH JOY auto increment with djnz (very fast)");
12893 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
12894 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12895 freeAsmop (count, NULL, ic, FALSE);
12897 emitcode ("movx", "a,@dptr"); /* read data from port */
12898 emitcode ("dec","dps"); /* switch to DPTR */
12899 emitcode ("movx", "@dptr,a"); /* save into location */
12900 emitcode ("inc", "dptr"); /* point to next area */
12901 emitcode ("inc","dps"); /* switch to DPTR2 */
12902 emitcode ("djnz","b,!tlabel",lbl->key+100);
12904 symbol *lbl1 = newiTempLabel(NULL);
12906 emitcode (";"," Auto increment but no djnz");
12907 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
12908 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
12909 freeAsmop (count, NULL, ic, FALSE);
12910 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
12912 emitcode ("movx", "a,@dptr");
12913 emitcode ("dec","dps"); /* switch to DPTR */
12914 emitcode ("movx", "@dptr,a");
12915 emitcode ("inc", "dptr");
12916 emitcode ("inc","dps"); /* switch to DPTR2 */
12917 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
12918 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
12919 emitcode ("mov","a,b");
12920 emitcode ("orl","a,_ap");
12921 emitcode ("jz","!tlabel",lbl1->key+100);
12922 emitcode ("mov","a,_ap");
12923 emitcode ("add","a,#!constbyte",0xFF);
12924 emitcode ("mov","_ap,a");
12925 emitcode ("mov","a,b");
12926 emitcode ("addc","a,#!constbyte",0xFF);
12927 emitcode ("mov","b,a");
12928 emitcode ("sjmp","!tlabel",lbl->key+100);
12931 emitcode ("mov", "dps,#0");
12932 _G.dptrInUse = _G.dptr1InUse = 0;
12933 unsavermask(rsave);
12937 /*-----------------------------------------------------------------*/
12938 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
12939 /* port, first parameter output area second parameter pointer to */
12940 /* port third parameter count */
12941 /*-----------------------------------------------------------------*/
12942 static void genOutp( iCode *ic, int nparms, operand **parms)
12944 operand *from , *to , *count;
12949 /* we know it has to be 3 parameters */
12950 assert (nparms == 3);
12952 rsave = newBitVect(16);
12953 /* save DPTR if it needs to be saved */
12954 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12955 if (bitVectBitValue(ic->rMask,i))
12956 rsave = bitVectSetBit(rsave,i);
12958 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12959 ds390_rUmaskForOp (IC_RESULT(ic))));
12966 aopOp (from, ic->next, FALSE, FALSE);
12968 /* get from into DPTR1 */
12969 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12970 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12971 if (options.model == MODEL_FLAT24) {
12972 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12975 freeAsmop (from, NULL, ic, FALSE);
12976 aopOp (to, ic, FALSE, FALSE);
12977 /* get "to" into DPTR */
12978 /* if the operand is already in dptr
12979 then we do nothing else we move the value to dptr */
12980 if (AOP_TYPE (to) != AOP_STR) {
12981 /* if already in DPTR then we need to push */
12982 if (AOP_TYPE(to) == AOP_DPTR) {
12983 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12984 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12985 if (options.model == MODEL_FLAT24)
12986 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12987 emitcode ("pop", "dph");
12988 emitcode ("pop", "dpl");
12990 _startLazyDPSEvaluation ();
12991 /* if this is remateriazable */
12992 if (AOP_TYPE (to) == AOP_IMMD) {
12993 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12994 } else { /* we need to get it byte by byte */
12995 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12996 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12997 if (options.model == MODEL_FLAT24) {
12998 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
13001 _endLazyDPSEvaluation ();
13004 freeAsmop (to, NULL, ic, FALSE);
13006 _G.dptrInUse = _G.dptr1InUse = 1;
13007 aopOp (count, ic->next->next, FALSE,FALSE);
13008 lbl =newiTempLabel(NULL);
13010 /* now for the actual copy */
13011 if (AOP_TYPE(count) == AOP_LIT &&
13012 (int) ulFromVal (AOP(count)->aopu.aop_lit) <= 256) {
13013 emitcode (";","OH JOY auto increment with djnz (very fast)");
13014 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
13015 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
13017 emitcode ("movx", "a,@dptr"); /* read data from port */
13018 emitcode ("inc","dps"); /* switch to DPTR2 */
13019 emitcode ("movx", "@dptr,a"); /* save into location */
13020 emitcode ("inc", "dptr"); /* point to next area */
13021 emitcode ("dec","dps"); /* switch to DPTR */
13022 emitcode ("djnz","b,!tlabel",lbl->key+100);
13023 freeAsmop (count, NULL, ic, FALSE);
13025 symbol *lbl1 = newiTempLabel(NULL);
13027 emitcode (";"," Auto increment but no djnz");
13028 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
13029 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
13030 freeAsmop (count, NULL, ic, FALSE);
13031 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
13033 emitcode ("movx", "a,@dptr");
13034 emitcode ("inc", "dptr");
13035 emitcode ("inc","dps"); /* switch to DPTR2 */
13036 emitcode ("movx", "@dptr,a");
13037 emitcode ("dec","dps"); /* switch to DPTR */
13038 emitcode ("mov","a,b");
13039 emitcode ("orl","a,_ap");
13040 emitcode ("jz","!tlabel",lbl1->key+100);
13041 emitcode ("mov","a,_ap");
13042 emitcode ("add","a,#!constbyte",0xFF);
13043 emitcode ("mov","_ap,a");
13044 emitcode ("mov","a,b");
13045 emitcode ("addc","a,#!constbyte",0xFF);
13046 emitcode ("mov","b,a");
13047 emitcode ("sjmp","!tlabel",lbl->key+100);
13050 emitcode ("mov", "dps,#0");
13051 _G.dptrInUse = _G.dptr1InUse = 0;
13052 unsavermask(rsave);
13056 /*-----------------------------------------------------------------*/
13057 /* genSwapW - swap lower & high order bytes */
13058 /*-----------------------------------------------------------------*/
13059 static void genSwapW(iCode *ic, int nparms, operand **parms)
13063 assert (nparms==1);
13066 dest=IC_RESULT(ic);
13068 assert(getSize(operandType(src))==2);
13070 aopOp (src, ic, FALSE, FALSE);
13071 emitcode ("mov","a,%s",aopGet(src,0,FALSE,FALSE,NULL));
13073 MOVB(aopGet(src,1,FALSE,FALSE,"b"));
13075 freeAsmop (src, NULL, ic, FALSE);
13077 aopOp (dest,ic, FALSE, FALSE);
13078 aopPut(dest,"b",0);
13079 aopPut(dest,"a",1);
13080 freeAsmop (dest, NULL, ic, FALSE);
13083 /*-----------------------------------------------------------------*/
13084 /* genMemsetX - gencode for memSetX data */
13085 /*-----------------------------------------------------------------*/
13086 static void genMemsetX(iCode *ic, int nparms, operand **parms)
13088 operand *to , *val , *count;
13094 /* we know it has to be 3 parameters */
13095 assert (nparms == 3);
13101 /* save DPTR if it needs to be saved */
13102 rsave = newBitVect(16);
13103 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
13104 if (bitVectBitValue(ic->rMask,i))
13105 rsave = bitVectSetBit(rsave,i);
13107 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
13108 ds390_rUmaskForOp (IC_RESULT(ic))));
13111 aopOp (to, ic, FALSE, FALSE);
13112 /* get "to" into DPTR */
13113 /* if the operand is already in dptr
13114 then we do nothing else we move the value to dptr */
13115 if (AOP_TYPE (to) != AOP_STR) {
13116 /* if already in DPTR then we need to push */
13117 if (AOP_TYPE(to) == AOP_DPTR) {
13118 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
13119 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
13120 if (options.model == MODEL_FLAT24)
13121 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
13122 emitcode ("pop", "dph");
13123 emitcode ("pop", "dpl");
13125 _startLazyDPSEvaluation ();
13126 /* if this is remateriazable */
13127 if (AOP_TYPE (to) == AOP_IMMD) {
13128 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
13129 } else { /* we need to get it byte by byte */
13130 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
13131 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
13132 if (options.model == MODEL_FLAT24) {
13133 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
13136 _endLazyDPSEvaluation ();
13139 freeAsmop (to, NULL, ic, FALSE);
13141 aopOp (val, ic->next->next, FALSE,FALSE);
13142 aopOp (count, ic->next->next, FALSE,FALSE);
13143 lbl =newiTempLabel(NULL);
13144 /* now for the actual copy */
13145 if (AOP_TYPE(count) == AOP_LIT &&
13146 (int) ulFromVal (AOP(count)->aopu.aop_lit) <= 256) {
13147 l = aopGet(val, 0, FALSE, FALSE, NULL);
13148 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
13151 emitcode ("movx", "@dptr,a");
13152 emitcode ("inc", "dptr");
13153 emitcode ("djnz","b,!tlabel",lbl->key+100);
13155 symbol *lbl1 = newiTempLabel(NULL);
13157 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
13158 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
13160 MOVA (aopGet(val, 0, FALSE, FALSE, NULL));
13161 emitcode ("movx", "@dptr,a");
13162 emitcode ("inc", "dptr");
13163 emitcode ("mov","a,b");
13164 emitcode ("orl","a,_ap");
13165 emitcode ("jz","!tlabel",lbl1->key+100);
13166 emitcode ("mov","a,_ap");
13167 emitcode ("add","a,#!constbyte",0xFF);
13168 emitcode ("mov","_ap,a");
13169 emitcode ("mov","a,b");
13170 emitcode ("addc","a,#!constbyte",0xFF);
13171 emitcode ("mov","b,a");
13172 emitcode ("sjmp","!tlabel",lbl->key+100);
13175 freeAsmop (count, NULL, ic, FALSE);
13176 unsavermask(rsave);
13179 /*-----------------------------------------------------------------*/
13180 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
13181 /*-----------------------------------------------------------------*/
13182 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
13185 operand *pnum, *result;
13188 assert (nparms==1);
13189 /* save registers that need to be saved */
13190 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13191 ds390_rUmaskForOp (IC_RESULT(ic))));
13194 aopOp (pnum, ic, FALSE, FALSE);
13195 emitcode ("mov","a,%s",aopGet(pnum,0,FALSE,FALSE,DP2_RESULT_REG));
13196 freeAsmop (pnum, NULL, ic, FALSE);
13197 emitcode ("lcall","NatLib_LoadPrimitive");
13198 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
13199 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
13200 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
13201 for (i = (size-1) ; i >= 0 ; i-- ) {
13202 emitcode ("push","a%s",javaRet[i]);
13204 for (i=0; i < size ; i++ ) {
13205 emitcode ("pop","a%s",
13206 aopGet(result,i,FALSE,FALSE,DP2_RESULT_REG));
13209 for (i = 0 ; i < size ; i++ ) {
13210 aopPut(result,javaRet[i],i);
13213 freeAsmop (result, NULL, ic, FALSE);
13214 unsavermask(rsave);
13217 /*-----------------------------------------------------------------*/
13218 /* genNatLibLoadPointer - calls TINI api function to load pointer */
13219 /*-----------------------------------------------------------------*/
13220 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
13223 operand *pnum, *result;
13227 assert (nparms==1);
13228 /* save registers that need to be saved */
13229 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13230 ds390_rUmaskForOp (IC_RESULT(ic))));
13233 aopOp (pnum, ic, FALSE, FALSE);
13234 emitcode ("mov","a,%s",aopGet(pnum,0,FALSE,FALSE,DP2_RESULT_REG));
13235 freeAsmop (pnum, NULL, ic, FALSE);
13236 emitcode ("lcall","NatLib_LoadPointer");
13237 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
13238 if (AOP_TYPE(result)!=AOP_STR) {
13239 for (i = 0 ; i < size ; i++ ) {
13240 aopPut(result,fReturn[i],i);
13243 freeAsmop (result, NULL, ic, FALSE);
13244 unsavermask(rsave);
13247 /*-----------------------------------------------------------------*/
13248 /* genNatLibInstallStateBlock - */
13249 /*-----------------------------------------------------------------*/
13250 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
13251 operand **parms, const char *name)
13254 operand *psb, *handle;
13255 assert (nparms==2);
13257 /* save registers that need to be saved */
13258 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13259 ds390_rUmaskForOp (IC_RESULT(ic))));
13263 /* put pointer to state block into DPTR1 */
13264 aopOp (psb, ic, FALSE, FALSE);
13265 if (AOP_TYPE (psb) == AOP_IMMD) {
13266 emitcode ("mov","dps,#1");
13267 emitcode ("mov", "dptr,%s",
13268 aopGet (psb, 0, TRUE, FALSE, DP2_RESULT_REG));
13269 emitcode ("mov","dps,#0");
13271 emitcode ("mov","dpl1,%s",aopGet(psb,0,FALSE,FALSE,DP2_RESULT_REG));
13272 emitcode ("mov","dph1,%s",aopGet(psb,1,FALSE,FALSE,DP2_RESULT_REG));
13273 emitcode ("mov","dpx1,%s",aopGet(psb,2,FALSE,FALSE,DP2_RESULT_REG));
13275 freeAsmop (psb, NULL, ic, FALSE);
13277 /* put libraryID into DPTR */
13278 emitcode ("mov","dptr,#LibraryID");
13280 /* put handle into r3:r2 */
13281 aopOp (handle, ic, FALSE, FALSE);
13282 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13283 emitcode ("push","%s",aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13284 emitcode ("push","%s",aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13285 emitcode ("pop","ar3");
13286 emitcode ("pop","ar2");
13288 emitcode ("mov","r2,%s",aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13289 emitcode ("mov","r3,%s",aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13291 freeAsmop (psb, NULL, ic, FALSE);
13293 /* make the call */
13294 emitcode ("lcall","NatLib_Install%sStateBlock",name);
13296 /* put return value into place*/
13298 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
13300 aopPut(IC_RESULT(ic),"a",0);
13301 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13302 unsavermask(rsave);
13305 /*-----------------------------------------------------------------*/
13306 /* genNatLibRemoveStateBlock - */
13307 /*-----------------------------------------------------------------*/
13308 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
13314 /* save registers that need to be saved */
13315 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13316 ds390_rUmaskForOp (IC_RESULT(ic))));
13318 /* put libraryID into DPTR */
13319 emitcode ("mov","dptr,#LibraryID");
13320 /* make the call */
13321 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
13322 unsavermask(rsave);
13325 /*-----------------------------------------------------------------*/
13326 /* genNatLibGetStateBlock - */
13327 /*-----------------------------------------------------------------*/
13328 static void genNatLibGetStateBlock(iCode *ic,int nparms,
13329 operand **parms,const char *name)
13332 symbol *lbl = newiTempLabel(NULL);
13335 /* save registers that need to be saved */
13336 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13337 ds390_rUmaskForOp (IC_RESULT(ic))));
13339 /* put libraryID into DPTR */
13340 emitcode ("mov","dptr,#LibraryID");
13341 /* make the call */
13342 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
13343 emitcode ("jnz","!tlabel",lbl->key+100);
13345 /* put return value into place */
13346 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
13347 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
13348 emitcode ("push","ar3");
13349 emitcode ("push","ar2");
13350 emitcode ("pop","%s",
13351 aopGet(IC_RESULT(ic),0,FALSE,TRUE,DP2_RESULT_REG));
13352 emitcode ("pop","%s",
13353 aopGet(IC_RESULT(ic),1,FALSE,TRUE,DP2_RESULT_REG));
13355 aopPut(IC_RESULT(ic),"r2",0);
13356 aopPut(IC_RESULT(ic),"r3",1);
13358 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13360 unsavermask(rsave);
13363 /*-----------------------------------------------------------------*/
13364 /* genMMMalloc - */
13365 /*-----------------------------------------------------------------*/
13366 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
13367 int size, const char *name)
13372 symbol *lbl = newiTempLabel(NULL);
13374 assert (nparms == 1);
13375 /* save registers that need to be saved */
13376 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13377 ds390_rUmaskForOp (IC_RESULT(ic))));
13380 aopOp (bsize,ic,FALSE,FALSE);
13382 /* put the size in R4-R2 */
13383 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
13384 emitcode("push","%s",aopGet(bsize,0,FALSE,TRUE,DP2_RESULT_REG));
13385 emitcode("push","%s",aopGet(bsize,1,FALSE,TRUE,DP2_RESULT_REG));
13387 emitcode("push","%s",aopGet(bsize,2,FALSE,TRUE,DP2_RESULT_REG));
13388 emitcode("pop","ar4");
13390 emitcode("pop","ar3");
13391 emitcode("pop","ar2");
13393 emitcode ("mov","r2,%s",aopGet(bsize,0,FALSE,TRUE,DP2_RESULT_REG));
13394 emitcode ("mov","r3,%s",aopGet(bsize,1,FALSE,TRUE,DP2_RESULT_REG));
13396 emitcode("mov","r4,%s",aopGet(bsize,2,FALSE,TRUE,DP2_RESULT_REG));
13399 freeAsmop (bsize, NULL, ic, FALSE);
13401 /* make the call */
13402 emitcode ("lcall","MM_%s",name);
13403 emitcode ("jz","!tlabel",lbl->key+100);
13404 emitcode ("mov","r2,#!constbyte",0xff);
13405 emitcode ("mov","r3,#!constbyte",0xff);
13407 /* we don't care about the pointer : we just save the handle */
13408 rsym = OP_SYMBOL(IC_RESULT(ic));
13409 if (rsym->liveFrom != rsym->liveTo) {
13410 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
13411 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
13412 emitcode ("push","ar3");
13413 emitcode ("push","ar2");
13414 emitcode ("pop","%s",
13415 aopGet(IC_RESULT(ic),0,FALSE,TRUE,DP2_RESULT_REG));
13416 emitcode ("pop","%s",
13417 aopGet(IC_RESULT(ic),1,FALSE,TRUE,DP2_RESULT_REG));
13419 aopPut(IC_RESULT(ic),"r2",0);
13420 aopPut(IC_RESULT(ic),"r3",1);
13422 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13424 unsavermask(rsave);
13427 /*-----------------------------------------------------------------*/
13429 /*-----------------------------------------------------------------*/
13430 static void genMMDeref (iCode *ic,int nparms, operand **parms)
13435 assert (nparms == 1);
13436 /* save registers that need to be saved */
13437 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13438 ds390_rUmaskForOp (IC_RESULT(ic))));
13441 aopOp (handle,ic,FALSE,FALSE);
13443 /* put the size in R4-R2 */
13444 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13445 emitcode("push","%s",
13446 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13447 emitcode("push","%s",
13448 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13449 emitcode("pop","ar3");
13450 emitcode("pop","ar2");
13452 emitcode ("mov","r2,%s",
13453 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13454 emitcode ("mov","r3,%s",
13455 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13457 freeAsmop (handle, NULL, ic, FALSE);
13459 /* make the call */
13460 emitcode ("lcall","MM_Deref");
13463 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13464 if (rsym->liveFrom != rsym->liveTo) {
13465 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13466 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
13467 _startLazyDPSEvaluation ();
13469 aopPut(IC_RESULT(ic),"dpl",0);
13470 aopPut(IC_RESULT(ic),"dph",1);
13471 aopPut(IC_RESULT(ic),"dpx",2);
13473 _endLazyDPSEvaluation ();
13478 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13479 unsavermask(rsave);
13482 /*-----------------------------------------------------------------*/
13483 /* genMMUnrestrictedPersist - */
13484 /*-----------------------------------------------------------------*/
13485 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
13490 assert (nparms == 1);
13491 /* save registers that need to be saved */
13492 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13493 ds390_rUmaskForOp (IC_RESULT(ic))));
13496 aopOp (handle,ic,FALSE,FALSE);
13498 /* put the size in R3-R2 */
13499 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13500 emitcode("push","%s",
13501 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13502 emitcode("push","%s",
13503 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13504 emitcode("pop","ar3");
13505 emitcode("pop","ar2");
13507 emitcode ("mov","r2,%s",
13508 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13509 emitcode ("mov","r3,%s",
13510 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13512 freeAsmop (handle, NULL, ic, FALSE);
13514 /* make the call */
13515 emitcode ("lcall","MM_UnrestrictedPersist");
13518 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13519 if (rsym->liveFrom != rsym->liveTo) {
13520 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13521 aopPut(IC_RESULT(ic),"a",0);
13522 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13525 unsavermask(rsave);
13528 /*-----------------------------------------------------------------*/
13529 /* genSystemExecJavaProcess - */
13530 /*-----------------------------------------------------------------*/
13531 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
13534 operand *handle, *pp;
13536 assert (nparms==2);
13537 /* save registers that need to be saved */
13538 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13539 ds390_rUmaskForOp (IC_RESULT(ic))));
13544 /* put the handle in R3-R2 */
13545 aopOp (handle,ic,FALSE,FALSE);
13546 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13547 emitcode("push","%s",
13548 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13549 emitcode("push","%s",
13550 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13551 emitcode("pop","ar3");
13552 emitcode("pop","ar2");
13554 emitcode ("mov","r2,%s",
13555 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13556 emitcode ("mov","r3,%s",
13557 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13559 freeAsmop (handle, NULL, ic, FALSE);
13561 /* put pointer in DPTR */
13562 aopOp (pp,ic,FALSE,FALSE);
13563 if (AOP_TYPE(pp) == AOP_IMMD) {
13564 emitcode ("mov", "dptr,%s",
13565 aopGet (pp, 0, TRUE, FALSE, NULL));
13566 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
13567 emitcode ("mov","dpl,%s",aopGet(pp,0,FALSE,FALSE,NULL));
13568 emitcode ("mov","dph,%s",aopGet(pp,1,FALSE,FALSE,NULL));
13569 emitcode ("mov","dpx,%s",aopGet(pp,2,FALSE,FALSE,NULL));
13571 freeAsmop (handle, NULL, ic, FALSE);
13573 /* make the call */
13574 emitcode ("lcall","System_ExecJavaProcess");
13576 /* put result in place */
13578 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13579 if (rsym->liveFrom != rsym->liveTo) {
13580 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13581 aopPut(IC_RESULT(ic),"a",0);
13582 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13586 unsavermask(rsave);
13589 /*-----------------------------------------------------------------*/
13590 /* genSystemRTCRegisters - */
13591 /*-----------------------------------------------------------------*/
13592 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
13598 assert (nparms==1);
13599 /* save registers that need to be saved */
13600 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13601 ds390_rUmaskForOp (IC_RESULT(ic))));
13604 /* put pointer in DPTR */
13605 aopOp (pp,ic,FALSE,FALSE);
13606 if (AOP_TYPE (pp) == AOP_IMMD) {
13607 emitcode ("mov","dps,#1");
13608 emitcode ("mov", "dptr,%s",
13609 aopGet (pp, 0, TRUE, FALSE, NULL));
13610 emitcode ("mov","dps,#0");
13612 emitcode ("mov","dpl1,%s",
13613 aopGet(pp,0,FALSE,FALSE,DP2_RESULT_REG));
13614 emitcode ("mov","dph1,%s",
13615 aopGet(pp,1,FALSE,FALSE,DP2_RESULT_REG));
13616 emitcode ("mov","dpx1,%s",
13617 aopGet(pp,2,FALSE,FALSE,DP2_RESULT_REG));
13619 freeAsmop (pp, NULL, ic, FALSE);
13621 /* make the call */
13622 emitcode ("lcall","System_%sRTCRegisters",name);
13624 unsavermask(rsave);
13627 /*-----------------------------------------------------------------*/
13628 /* genSystemThreadSleep - */
13629 /*-----------------------------------------------------------------*/
13630 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
13635 assert (nparms==1);
13636 /* save registers that need to be saved */
13637 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13638 ds390_rUmaskForOp (IC_RESULT(ic))));
13641 aopOp(to,ic,FALSE,FALSE);
13642 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
13643 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
13644 emitcode ("push","%s",
13645 aopGet(to,0,FALSE,TRUE,DP2_RESULT_REG));
13646 emitcode ("push","%s",
13647 aopGet(to,1,FALSE,TRUE,DP2_RESULT_REG));
13648 emitcode ("push","%s",
13649 aopGet(to,2,FALSE,TRUE,DP2_RESULT_REG));
13650 emitcode ("push","%s",
13651 aopGet(to,3,FALSE,TRUE,DP2_RESULT_REG));
13652 emitcode ("pop","ar3");
13653 emitcode ("pop","ar2");
13654 emitcode ("pop","ar1");
13655 emitcode ("pop","ar0");
13657 emitcode ("mov","r0,%s",
13658 aopGet(to,0,FALSE,TRUE,DP2_RESULT_REG));
13659 emitcode ("mov","r1,%s",
13660 aopGet(to,1,FALSE,TRUE,DP2_RESULT_REG));
13661 emitcode ("mov","r2,%s",
13662 aopGet(to,2,FALSE,TRUE,DP2_RESULT_REG));
13663 emitcode ("mov","r3,%s",
13664 aopGet(to,3,FALSE,TRUE,DP2_RESULT_REG));
13666 freeAsmop (to, NULL, ic, FALSE);
13668 /* suspend in acc */
13670 aopOp(s,ic,FALSE,FALSE);
13671 emitcode ("mov","a,%s",
13672 aopGet(s,0,FALSE,TRUE,NULL));
13673 freeAsmop (s, NULL, ic, FALSE);
13675 /* make the call */
13676 emitcode ("lcall","System_%s",name);
13678 unsavermask(rsave);
13681 /*-----------------------------------------------------------------*/
13682 /* genSystemThreadResume - */
13683 /*-----------------------------------------------------------------*/
13684 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
13689 assert (nparms==2);
13690 /* save registers that need to be saved */
13691 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13692 ds390_rUmaskForOp (IC_RESULT(ic))));
13698 aopOp(pid,ic,FALSE,FALSE);
13699 emitcode ("mov","r0,%s",
13700 aopGet(pid,0,FALSE,TRUE,DP2_RESULT_REG));
13701 freeAsmop (pid, NULL, ic, FALSE);
13704 aopOp(tid,ic,FALSE,FALSE);
13705 emitcode ("mov","a,%s",
13706 aopGet(tid,0,FALSE,TRUE,DP2_RESULT_REG));
13707 freeAsmop (tid, NULL, ic, FALSE);
13709 emitcode ("lcall","System_ThreadResume");
13711 /* put result into place */
13713 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13714 if (rsym->liveFrom != rsym->liveTo) {
13715 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13716 aopPut(IC_RESULT(ic),"a",0);
13717 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13720 unsavermask(rsave);
13723 /*-----------------------------------------------------------------*/
13724 /* genSystemProcessResume - */
13725 /*-----------------------------------------------------------------*/
13726 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
13731 assert (nparms==1);
13732 /* save registers that need to be saved */
13733 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13734 ds390_rUmaskForOp (IC_RESULT(ic))));
13739 aopOp(pid,ic,FALSE,FALSE);
13740 emitcode ("mov","a,%s",
13741 aopGet(pid,0,FALSE,TRUE,DP2_RESULT_REG));
13742 freeAsmop (pid, NULL, ic, FALSE);
13744 emitcode ("lcall","System_ProcessResume");
13746 unsavermask(rsave);
13749 /*-----------------------------------------------------------------*/
13751 /*-----------------------------------------------------------------*/
13752 static void genSystem (iCode *ic,int nparms,char *name)
13754 assert(nparms == 0);
13756 emitcode ("lcall","System_%s",name);
13759 /*-----------------------------------------------------------------*/
13760 /* genSystemPoll - */
13761 /*-----------------------------------------------------------------*/
13762 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
13767 assert (nparms==1);
13768 /* save registers that need to be saved */
13769 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13770 ds390_rUmaskForOp (IC_RESULT(ic))));
13773 aopOp (fp,ic,FALSE,FALSE);
13774 if (AOP_TYPE (fp) == AOP_IMMD) {
13775 emitcode ("mov", "dptr,%s",
13776 aopGet (fp, 0, TRUE, FALSE, DP2_RESULT_REG));
13777 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
13778 emitcode ("mov","dpl,%s",
13779 aopGet(fp,0,FALSE,FALSE,DP2_RESULT_REG));
13780 emitcode ("mov","dph,%s",
13781 aopGet(fp,1,FALSE,FALSE,DP2_RESULT_REG));
13782 emitcode ("mov","dpx,%s",
13783 aopGet(fp,2,FALSE,FALSE,DP2_RESULT_REG));
13785 freeAsmop (fp, NULL, ic, FALSE);
13787 emitcode ("lcall","System_%sPoll",name);
13789 /* put result into place */
13791 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13792 if (rsym->liveFrom != rsym->liveTo) {
13793 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13794 aopPut(IC_RESULT(ic),"a",0);
13795 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13798 unsavermask(rsave);
13801 /*-----------------------------------------------------------------*/
13802 /* genSystemGetCurrentID - */
13803 /*-----------------------------------------------------------------*/
13804 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
13806 assert (nparms==0);
13808 emitcode ("lcall","System_GetCurrent%sId",name);
13809 /* put result into place */
13811 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13812 if (rsym->liveFrom != rsym->liveTo) {
13813 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13814 aopPut(IC_RESULT(ic),"a",0);
13815 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13820 /*-----------------------------------------------------------------*/
13821 /* genDjnz - generate decrement & jump if not zero instrucion */
13822 /*-----------------------------------------------------------------*/
13824 genDjnz (iCode * ic, iCode * ifx)
13826 symbol *lbl, *lbl1;
13830 /* if the if condition has a false label
13831 then we cannot save */
13832 if (IC_FALSE (ifx))
13835 /* if the minus is not of the form a = a - 1 */
13836 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
13837 !IS_OP_LITERAL (IC_RIGHT (ic)))
13840 if (operandLitValue (IC_RIGHT (ic)) != 1)
13843 /* if the size of this greater than one then no
13845 if (getSize (operandType (IC_RESULT (ic))) > 1)
13848 /* otherwise we can save BIG */
13850 D (emitcode (";", "genDjnz"));
13852 lbl = newiTempLabel (NULL);
13853 lbl1 = newiTempLabel (NULL);
13855 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
13857 if (AOP_NEEDSACC(IC_RESULT(ic)))
13859 /* If the result is accessed indirectly via
13860 * the accumulator, we must explicitly write
13861 * it back after the decrement.
13863 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE, NULL);
13865 if (strcmp(rByte, "a"))
13867 /* Something is hopelessly wrong */
13868 fprintf(stderr, "*** warning: internal error at %s:%d\n",
13869 __FILE__, __LINE__);
13870 /* We can just give up; the generated code will be inefficient,
13871 * but what the hey.
13873 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13876 emitcode ("dec", "%s", rByte);
13877 aopPut (IC_RESULT (ic), rByte, 0);
13878 emitcode ("jnz", "!tlabel", lbl->key + 100);
13880 else if (IS_AOP_PREG (IC_RESULT (ic)))
13882 emitcode ("dec", "%s",
13883 aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL));
13884 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL));
13885 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13886 ifx->generated = 1;
13887 emitcode ("jnz", "!tlabel", lbl->key + 100);
13891 emitcode ("djnz", "%s,!tlabel", aopGet (IC_RESULT (ic), 0, FALSE, TRUE, NULL),
13894 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
13896 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
13899 if (!ifx->generated)
13900 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13901 ifx->generated = 1;
13905 /*-----------------------------------------------------------------*/
13906 /* genReceive - generate code for a receive iCode */
13907 /*-----------------------------------------------------------------*/
13909 genReceive (iCode * ic)
13911 int size = getSize (operandType (IC_RESULT (ic)));
13915 D (emitcode (";", "genReceive"));
13917 if (ic->argreg == 1)
13919 /* first parameter */
13920 if (AOP_IS_STR(IC_RESULT(ic)))
13922 /* Nothing to do: it's already in the proper place. */
13929 useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
13930 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
13931 IS_TRUE_SYMOP (IC_RESULT (ic)));
13934 aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
13937 /* Sanity checking... */
13938 if (AOP_USESDPTR(IC_RESULT(ic)))
13940 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
13941 "genReceive got unexpected DPTR.");
13943 assignResultValue (IC_RESULT (ic), NULL);
13946 else if (ic->argreg > 12)
13947 { /* bit parameters */
13948 if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
13950 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
13951 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
13952 outBitC(IC_RESULT (ic));
13957 /* second receive onwards */
13958 /* this gets a little tricky since unused receives will be
13959 eliminated, we have saved the reg in the type field . and
13960 we use that to figure out which register to use */
13961 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
13962 rb1off = ic->argreg;
13965 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
13968 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13971 /*-----------------------------------------------------------------*/
13972 /* genDummyRead - generate code for dummy read of volatiles */
13973 /*-----------------------------------------------------------------*/
13975 genDummyRead (iCode * ic)
13980 D (emitcode(";", "genDummyRead"));
13982 op = IC_RIGHT (ic);
13983 if (op && IS_SYMOP (op))
13985 aopOp (op, ic, FALSE, FALSE);
13987 /* if the result is a bit */
13988 if (AOP_TYPE (op) == AOP_CRY)
13989 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13992 /* bit variables done */
13994 size = AOP_SIZE (op);
13998 MOVA (aopGet (op, offset, FALSE, FALSE, FALSE));
14003 freeAsmop (op, NULL, ic, TRUE);
14007 if (op && IS_SYMOP (op))
14009 aopOp (op, ic, FALSE, FALSE);
14011 /* if the result is a bit */
14012 if (AOP_TYPE (op) == AOP_CRY)
14013 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
14016 /* bit variables done */
14018 size = AOP_SIZE (op);
14022 MOVA (aopGet (op, offset, FALSE, FALSE, FALSE));
14027 freeAsmop (op, NULL, ic, TRUE);
14031 /*-----------------------------------------------------------------*/
14032 /* genCritical - generate code for start of a critical sequence */
14033 /*-----------------------------------------------------------------*/
14035 genCritical (iCode *ic)
14037 symbol *tlbl = newiTempLabel (NULL);
14039 D (emitcode(";", "genCritical"));
14041 if (IC_RESULT (ic))
14043 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
14044 aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
14045 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
14046 aopPut (IC_RESULT (ic), zero, 0);
14048 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
14052 emitcode ("setb", "c");
14053 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
14054 emitcode ("clr", "c");
14056 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
14060 /*-----------------------------------------------------------------*/
14061 /* genEndCritical - generate code for end of a critical sequence */
14062 /*-----------------------------------------------------------------*/
14064 genEndCritical (iCode *ic)
14066 D(emitcode(";", "genEndCritical"));
14070 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
14071 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
14073 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
14074 emitcode ("mov", "ea,c");
14078 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE, FALSE));
14079 emitcode ("rrc", "a");
14080 emitcode ("mov", "ea,c");
14082 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
14086 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
14087 emitcode ("mov", "ea,c");
14093 /*-----------------------------------------------------------------*/
14094 /* genBuiltIn - calls the appropriate function to generating code */
14095 /* for a built in function */
14096 /*-----------------------------------------------------------------*/
14097 static void genBuiltIn (iCode *ic)
14099 operand *bi_parms[MAX_BUILTIN_ARGS];
14104 /* get all the arguments for a built in function */
14105 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
14107 /* which function is it */
14108 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
14109 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
14110 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
14111 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
14112 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
14113 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
14114 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
14115 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
14116 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
14117 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
14118 genMemsetX(bi_iCode,nbi_parms,bi_parms);
14119 } else if (strcmp(bif->name,"__builtin_inp")==0) {
14120 genInp(bi_iCode,nbi_parms,bi_parms);
14121 } else if (strcmp(bif->name,"__builtin_outp")==0) {
14122 genOutp(bi_iCode,nbi_parms,bi_parms);
14123 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
14124 genSwapW(bi_iCode,nbi_parms,bi_parms);
14125 /* JavaNative builtIns */
14126 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
14127 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
14128 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
14129 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
14130 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
14131 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
14132 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
14133 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
14134 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
14135 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
14136 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
14137 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
14138 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
14139 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
14140 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
14141 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
14142 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
14143 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
14144 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
14145 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
14146 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
14147 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
14148 } else if (strcmp(bif->name,"MM_Malloc")==0) {
14149 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
14150 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
14151 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
14152 } else if (strcmp(bif->name,"MM_Free")==0) {
14153 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
14154 } else if (strcmp(bif->name,"MM_Deref")==0) {
14155 genMMDeref(bi_iCode,nbi_parms,bi_parms);
14156 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
14157 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
14158 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
14159 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
14160 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
14161 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
14162 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
14163 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
14164 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
14165 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
14166 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
14167 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
14168 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
14169 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
14170 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
14171 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
14172 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
14173 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
14174 } else if (strcmp(bif->name,"System_SaveThread")==0) {
14175 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
14176 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
14177 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
14178 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
14179 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
14180 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
14181 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
14182 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
14183 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
14184 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
14185 genSystem(bi_iCode,nbi_parms,"ProcessYield");
14186 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
14187 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
14188 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
14189 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
14190 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
14191 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
14192 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
14193 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
14194 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
14195 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
14197 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
14203 /*-----------------------------------------------------------------*/
14204 /* gen390Code - generate code for Dallas 390 based controllers */
14205 /*-----------------------------------------------------------------*/
14207 gen390Code (iCode * lic)
14212 _G.currentFunc = NULL;
14213 lineHead = lineCurr = NULL;
14214 dptrn[1][0] = "dpl1";
14215 dptrn[1][1] = "dph1";
14216 dptrn[1][2] = "dpx1";
14218 if (options.model == MODEL_FLAT24) {
14219 fReturnSizeDS390 = 5;
14220 fReturn = fReturn24;
14222 fReturnSizeDS390 = 4;
14223 fReturn = fReturn16;
14224 options.stack10bit=0;
14227 /* print the allocation information */
14228 if (allocInfo && currFunc)
14229 printAllocInfo (currFunc, codeOutBuf);
14231 /* if debug information required */
14232 if (options.debug && currFunc)
14234 debugFile->writeFunction (currFunc, lic);
14236 /* stack pointer name */
14237 if (options.useXstack)
14243 for (ic = lic; ic; ic = ic->next)
14245 _G.current_iCode = ic;
14247 if (ic->lineno && cln != ic->lineno)
14251 debugFile->writeCLine (ic);
14253 if (!options.noCcodeInAsm) {
14254 emitcode (";", "%s:%d: %s", ic->filename, ic->lineno,
14255 printCLine(ic->filename, ic->lineno));
14259 if (options.iCodeInAsm) {
14260 const char *iLine = printILine(ic);
14261 emitcode(";", "ic:%d: %s", ic->key, iLine);
14264 /* if the result is marked as
14265 spilt and rematerializable or code for
14266 this has already been generated then
14268 if (resultRemat (ic) || ic->generated)
14271 /* depending on the operation */
14291 /* IPOP happens only when trying to restore a
14292 spilt live range, if there is an ifx statement
14293 following this pop then the if statement might
14294 be using some of the registers being popped which
14295 would destory the contents of the register so
14296 we need to check for this condition and handle it */
14298 ic->next->op == IFX &&
14299 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
14300 genIfx (ic->next, ic);
14318 genEndFunction (ic);
14338 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
14355 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
14359 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
14366 /* note these two are xlated by algebraic equivalence
14367 during parsing SDCC.y */
14368 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
14369 "got '>=' or '<=' shouldn't have come here");
14373 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
14385 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
14389 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
14393 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
14417 genRightShift (ic);
14420 case GET_VALUE_AT_ADDRESS:
14422 hasInc (IC_LEFT (ic), ic,
14423 getSize (operandType (IC_RESULT (ic)))));
14427 if (POINTER_SET (ic))
14429 hasInc (IC_RESULT (ic), ic,
14430 getSize (operandType (IC_RIGHT (ic)))));
14456 if (ic->builtinSEND)
14459 addSet (&_G.sendSet, ic);
14462 case DUMMY_READ_VOLATILE:
14471 genEndCritical (ic);
14478 #if 0 // obsolete, and buggy for != xdata
14485 /* This should never happen, right? */
14486 fprintf(stderr, "*** Probable error: unsupported op 0x%x (%c) in %s @ %d\n",
14487 ic->op, ic->op, __FILE__, __LINE__);
14493 /* now we are ready to call the
14494 peep hole optimizer */
14495 if (!options.nopeep)
14496 peepHole (&lineHead);
14498 /* now do the actual printing */
14499 printLine (lineHead, codeOutBuf);