1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for DS80C390
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7 DS390 adaptation by Kevin Vigor <kevin@vigor.nu>
9 This program is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 2, or (at your option) any
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 In other words, you are welcome to use, share and improve this program.
24 You are forbidden to forbid anyone else to use, share and improve
25 what you give them. Help stamp out software-hoarding!
26 -------------------------------------------------------------------------*/
29 #define D(x) do if (options.verboseAsm) {x;} while(0)
35 #include "SDCCglobl.h"
37 #include "dbuf_string.h"
44 #define BETTER_LITERAL_SHIFT
46 char *aopLiteral (value * val, int offset);
49 /* this is the down and dirty file with all kinds of
50 kludgy & hacky stuff. This is what it is all about
51 CODE GENERATION for a specific MCU . some of the
52 routines may be reusable, will have to see */
54 static char *zero = "#0";
55 static char *one = "#1";
58 #define TR_DPTR(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_DPTR1 %s ", s); }
59 #define TR_AP(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_AP %s ", s); }
61 unsigned fReturnSizeDS390 = 5;
62 static char *fReturn24[] =
63 {"dpl", "dph", "dpx", "b", "a"};
64 static char *fReturn16[] =
65 {"dpl", "dph", "b", "a"};
66 static char **fReturn = fReturn24;
67 static char *accUse[] =
69 static char *dptrn[2][3];
70 static char *javaRet[] = { "r0","r1","r2","r3"};
71 static short rbank = -1;
73 #define REG_WITH_INDEX ds390_regWithIdx
75 #define AOP(op) op->aop
76 #define AOP_TYPE(op) AOP(op)->type
77 #define AOP_SIZE(op) AOP(op)->size
78 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
79 AOP_TYPE(x) == AOP_R0))
81 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
82 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
85 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
86 (x->aopu.aop_reg[0] == REG_WITH_INDEX(R0_IDX) || \
87 x->aopu.aop_reg[0] == REG_WITH_INDEX(R1_IDX) )))
88 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
89 #define AOP_USESDPTR(x) ((AOP_TYPE(x) == AOP_DPTR) || (AOP_TYPE(x) == AOP_STR))
90 #define AOP_USESDPTR2(x) ((AOP_TYPE(x) == AOP_DPTR2) || (AOP_TYPE(x) == AOP_DPTRn))
92 // The following two macros can be used even if the aop has not yet been aopOp'd.
93 #define AOP_IS_STR(x) (IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
94 #define AOP_IS_DPTRn(x) (IS_SYMOP(x) && OP_SYMBOL(x)->dptr)
96 /* Workaround for DS80C390 bug: div ab may return bogus results
97 * if A is accessed in instruction immediately before the div.
99 * Will be fixed in B4 rev of processor, Dallas claims.
102 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
103 if (!AOP_NEEDSACC(RIGHT)) \
105 /* We can load A first, then B, since \
106 * B (the RIGHT operand) won't clobber A, \
107 * thus avoiding touching A right before the div. \
109 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
110 L = aopGet(LEFT,0,FALSE,FALSE,NULL); \
112 L = aopGet(RIGHT,0,FALSE,FALSE,"b"); \
117 /* Just stuff in a nop after loading A. */ \
118 emitcode("mov","b,%s",aopGet(RIGHT,0,FALSE,FALSE,NULL));\
119 L = aopGet(LEFT,0,FALSE,FALSE,NULL); \
121 emitcode("nop", "; workaround for DS80C390 div bug."); \
124 #define R0INB _G.bu.bs.r0InB
125 #define R1INB _G.bu.bs.r1InB
126 #define OPINB _G.bu.bs.OpInB
127 #define BINUSE _G.bu.BInUse
137 short r0InB : 2;//2 so we can see it overflow
138 short r1InB : 2;//2 so we can see it overflow
139 short OpInB : 2;//2 so we can see it overflow
150 iCode *current_iCode;
155 static char *rb1regs[] = {
156 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7",
157 "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7"
160 static void saveRBank (int, iCode *, bool);
162 #define RESULTONSTACK(x) \
163 (IC_RESULT(x) && IC_RESULT(x)->aop && \
164 IC_RESULT(x)->aop->type == AOP_STK )
166 #define MOVA(x) mova(x) /* use function to avoid multiple eval */
167 #define MOVB(x) movb(x)
169 #define CLRC emitcode("clr","c")
170 #define SETC emitcode("setb","c")
172 // A scratch register which will be used to hold
173 // result bytes from operands in far space via DPTR2.
174 #define DP2_RESULT_REG "_ap"
176 static lineNode *lineHead = NULL;
177 static lineNode *lineCurr = NULL;
179 static unsigned char SLMask[] =
180 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
181 0xE0, 0xC0, 0x80, 0x00};
182 static unsigned char SRMask[] =
183 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
184 0x07, 0x03, 0x01, 0x00};
190 #define PROTECT_SP {if (options.protect_sp_update) { \
191 symbol *lbl = newiTempLabel(NULL); \
192 emitcode ("setb","F1"); \
193 emitcode ("jbc","EA,!tlabel",lbl->key+100); \
194 emitcode ("clr","F1"); \
197 #define UNPROTECT_SP { if (options.protect_sp_update) { \
198 emitcode ("mov","EA,F1"); \
201 static int _currentDPS; /* Current processor DPS. */
202 static int _desiredDPS; /* DPS value compiler thinks we should be using. */
203 static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */
205 /*-----------------------------------------------------------------*/
206 /* emitcode - writes the code into a file : for now it is simple */
207 /*-----------------------------------------------------------------*/
209 emitcode (const char *inst, const char *fmt,...)
213 const char *lbp, *lb;
215 dbuf_init (&dbuf, INITIAL_INLINEASM);
221 dbuf_append_str (&dbuf, inst);
225 dbuf_append_char (&dbuf, '\t');
226 dbuf_tvprintf (&dbuf, fmt, ap);
231 dbuf_tvprintf (&dbuf, fmt, ap);
234 lbp = lb = dbuf_c_str(&dbuf);
236 while (isspace ((unsigned char)*lbp))
243 lineCurr = (lineCurr ?
244 connectLine (lineCurr, newLineNode (lb)) :
245 (lineHead = newLineNode (lb)));
247 lineCurr->isInline = _G.inLine;
248 lineCurr->isDebug = _G.debugLine;
249 lineCurr->ic = _G.current_iCode;
250 lineCurr->aln = ds390newAsmLineNode(_currentDPS);
251 lineCurr->isComment = (*lbp == ';');
260 emitLabel (symbol *tlbl)
262 emitcode ("", "!tlabeldef", tlbl->key + 100);
263 lineCurr->isLabel = 1;
266 /*-----------------------------------------------------------------*/
267 /* ds390_emitDebuggerSymbol - associate the current code location */
268 /* with a debugger symbol */
269 /*-----------------------------------------------------------------*/
271 ds390_emitDebuggerSymbol (char * debugSym)
274 emitcode ("", "%s ==.", debugSym);
278 /*-----------------------------------------------------------------*/
279 /* mova - moves specified value into accumulator */
280 /*-----------------------------------------------------------------*/
284 /* do some early peephole optimization */
285 if (!strncmp(x, "a", 2) || !strncmp(x, "acc", 4))
288 emitcode("mov", "a,%s", x);
291 /*-----------------------------------------------------------------*/
292 /* movb - moves specified value into register b */
293 /*-----------------------------------------------------------------*/
297 /* do some early peephole optimization */
298 if (!strncmp(x, "b", 2))
301 emitcode("mov","b,%s", x);
304 /*-----------------------------------------------------------------*/
305 /* movc - moves specified value into the carry */
306 /*-----------------------------------------------------------------*/
314 else if (strcmp (s, "c"))
315 {/* it's not in carry already */
317 /* set C, if a >= 1 */
318 emitcode ("add", "a,#0xff");
322 /*-----------------------------------------------------------------*/
323 /* pushB - saves register B if necessary */
324 /*-----------------------------------------------------------------*/
328 bool pushedB = FALSE;
332 emitcode ("push", "b");
333 // printf("B was in use !\n");
343 /*-----------------------------------------------------------------*/
344 /* popB - restores value of register B if necessary */
345 /*-----------------------------------------------------------------*/
351 emitcode ("pop", "b");
359 /*-----------------------------------------------------------------*/
360 /* pushReg - saves register */
361 /*-----------------------------------------------------------------*/
363 pushReg (int index, bool bits_pushed)
365 regs * reg = REG_WITH_INDEX (index);
366 if (reg->type == REG_BIT)
369 emitcode ("push", "%s", reg->base);
373 emitcode ("push", "%s", reg->dname);
377 /*-----------------------------------------------------------------*/
378 /* popReg - restores register */
379 /*-----------------------------------------------------------------*/
381 popReg (int index, bool bits_popped)
383 regs * reg = REG_WITH_INDEX (index);
384 if (reg->type == REG_BIT)
387 emitcode ("pop", "%s", reg->base);
391 emitcode ("pop", "%s", reg->dname);
395 /*-----------------------------------------------------------------*/
396 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
397 /*-----------------------------------------------------------------*/
399 getFreePtr (iCode * ic, asmop ** aopp, bool result)
404 /* the logic: if r0 & r1 used in the instruction
405 then we are in trouble otherwise */
407 /* first check if r0 & r1 are used by this
408 instruction, in which case we are in trouble */
409 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
410 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
415 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
416 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
418 /* if no usage of r0 then return it */
421 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
422 (*aopp)->type = AOP_R0;
424 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
427 /* if no usage of r1 then return it */
430 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
431 (*aopp)->type = AOP_R1;
433 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R1_IDX);
436 /* now we know they both have usage */
437 /* if r0 not used in this instruction */
440 /* push it if not already pushed */
443 emitcode ("push", "%s",
444 REG_WITH_INDEX (R0_IDX)->dname);
448 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
449 (*aopp)->type = AOP_R0;
451 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
454 /* if r1 not used then */
458 /* push it if not already pushed */
461 emitcode ("push", "%s",
462 REG_WITH_INDEX (R1_IDX)->dname);
466 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
467 (*aopp)->type = AOP_R1;
468 return REG_WITH_INDEX (R1_IDX);
472 /* I said end of world, but not quite end of world yet */
473 /* if this is a result then we can push it on the stack */
476 (*aopp)->type = AOP_STK;
480 /* now this is REALLY the end of the world */
481 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
482 "getFreePtr should never reach here");
485 return NULL; // notreached, but makes compiler happy.
489 /*-----------------------------------------------------------------*/
490 /* genSetDPTR: generate code to select which DPTR is in use (zero */
491 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */
492 /* alternate DPTR (DPL1/DPH1/DPX1). */
493 /*-----------------------------------------------------------------*/
498 /* If we are doing lazy evaluation, simply note the desired
499 * change, but don't emit any code yet.
509 emitcode ("mov", "dps,#0");
514 emitcode ("mov", "dps,#1");
518 /*------------------------------------------------------------------*/
519 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
521 /* Any code that operates on DPTR (NB: not on the individual */
522 /* components, like DPH) *must* call _flushLazyDPS() before using */
523 /* DPTR within a lazy DPS evaluation block. */
525 /* Note that aopPut and aopGet already contain the proper calls to */
526 /* _flushLazyDPS, so it is safe to use these calls within a lazy */
527 /* DPS evaluation block. */
529 /* Also, _flushLazyDPS must be called before any flow control */
530 /* operations that could potentially branch out of the block. */
532 /* Lazy DPS evaluation is simply an optimization (though an */
533 /* important one), so if in doubt, leave it out. */
534 /*------------------------------------------------------------------*/
536 _startLazyDPSEvaluation (void)
540 #ifdef BETTER_LITERAL_SHIFT
547 /*------------------------------------------------------------------*/
548 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
549 /* desired one. Call before using DPTR within a lazy DPS evaluation */
551 /*------------------------------------------------------------------*/
561 if (_desiredDPS != _currentDPS)
565 emitcode ("inc", "dps");
569 emitcode ("dec", "dps");
571 _currentDPS = _desiredDPS;
575 /*-----------------------------------------------------------------*/
576 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
578 /* Forces us back to the safe state (standard DPTR selected). */
579 /*-----------------------------------------------------------------*/
581 _endLazyDPSEvaluation (void)
583 #ifdef BETTER_LITERAL_SHIFT
601 /*-----------------------------------------------------------------*/
602 /* newAsmop - creates a new asmOp */
603 /*-----------------------------------------------------------------*/
605 newAsmop (short type)
609 aop = Safe_calloc (1, sizeof (asmop));
615 /*-----------------------------------------------------------------*/
616 /* pointerCode - returns the code for a pointer type */
617 /*-----------------------------------------------------------------*/
619 pointerCode (sym_link * etype)
622 return PTR_TYPE (SPEC_OCLS (etype));
626 /*-----------------------------------------------------------------*/
627 /* leftRightUseAcc - returns size of accumulator use by operands */
628 /*-----------------------------------------------------------------*/
630 leftRightUseAcc(iCode *ic)
639 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
640 "null iCode pointer");
647 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
650 size = getSize (OP_SYMBOL (op)->type);
655 else if (ic->op == JUMPTABLE)
658 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
661 size = getSize (OP_SYMBOL (op)->type);
669 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
672 size = getSize (OP_SYMBOL (op)->type);
677 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
680 size = getSize (OP_SYMBOL (op)->type);
692 /*-----------------------------------------------------------------*/
693 /* aopForSym - for a true symbol */
694 /*-----------------------------------------------------------------*/
696 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
700 bool accuse = leftRightUseAcc (ic) || _G.accInUse;
701 char *dpl = useDP2 ? "dpl1" : "dpl";
702 char *dph = useDP2 ? "dph1" : "dph";
703 char *dpx = useDP2 ? "dpx1" : "dpx";
705 wassertl (ic != NULL, "Got a null iCode");
706 wassertl (sym != NULL, "Got a null symbol");
708 space = SPEC_OCLS (sym->etype);
710 /* if already has one */
713 if ((sym->aop->type == AOP_DPTR && useDP2)
714 || (sym->aop->type == AOP_DPTR2 && !useDP2))
718 sym->aop->allocated++;
723 /* assign depending on the storage class */
724 /* if it is on the stack or indirectly addressable */
725 /* space we need to assign either r0 or r1 to it */
726 if ((sym->onStack && !options.stack10bit) || sym->iaccess)
728 sym->aop = aop = newAsmop (0);
729 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
730 aop->size = getSize (sym->type);
732 /* now assign the address of the variable to
733 the pointer register */
734 if (aop->type != AOP_STK)
738 signed char offset = ((sym->stack < 0) ?
739 ((signed char) (sym->stack - _G.nRegsSaved)) :
740 ((signed char) sym->stack)) & 0xff;
742 if ((abs(offset) <= 3) ||
743 (accuse && (abs(offset) <= 7)))
745 emitcode ("mov", "%s,_bp",
746 aop->aopu.aop_ptr->name);
749 emitcode ("dec", aop->aopu.aop_ptr->name);
754 emitcode ("inc", aop->aopu.aop_ptr->name);
761 emitcode ("push", "acc");
762 emitcode ("mov", "a,_bp");
763 emitcode ("add", "a,#!constbyte", offset);
764 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
766 emitcode ("pop", "acc");
771 emitcode ("mov", "%s,#%s",
772 aop->aopu.aop_ptr->name,
775 aop->paged = space->paged;
778 aop->aopu.aop_stk = sym->stack;
782 if (sym->onStack && options.stack10bit)
784 short stack_val = -((sym->stack < 0) ?
785 ((short) (sym->stack - _G.nRegsSaved)) :
786 ((short) sym->stack)) ;
788 emitcode ("push",dpl);
789 emitcode ("push",dph);
790 emitcode ("push",dpx);
792 /* It's on the 10 bit stack, which is located in
795 if (stack_val < 0 && stack_val > -5)
796 { /* between -5 & -1 */
797 if (options.model == MODEL_FLAT24)
799 emitcode ("mov", "%s,#!constbyte", dpx,
800 (options.stack_loc >> 16) & 0xff);
802 emitcode ("mov", "%s,_bpx+1", dph);
803 emitcode ("mov", "%s,_bpx", dpl);
805 emitcode ("mov","dps,#1");
807 stack_val = -stack_val;
808 while (stack_val--) {
809 emitcode ("inc","dptr");
812 emitcode("mov","dps,#0");
818 emitcode ("push", "acc");
820 emitcode ("mov", "a,_bpx");
821 emitcode ("clr","c");
822 emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
823 emitcode ("mov","%s,a", dpl);
824 emitcode ("mov","a,_bpx+1");
825 emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
826 emitcode ("mov", "%s,a", dph);
827 if (options.model == MODEL_FLAT24)
829 emitcode ("mov", "%s,#!constbyte", dpx,
830 (options.stack_loc >> 16) & 0xff);
834 emitcode ("pop", "acc");
836 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
837 aop->size = getSize (sym->type);
841 /* if in bit space */
842 if (IN_BITSPACE (space))
844 sym->aop = aop = newAsmop (AOP_CRY);
845 aop->aopu.aop_dir = sym->rname;
846 aop->size = getSize (sym->type);
849 /* if it is in direct space */
850 if (IN_DIRSPACE (space))
852 sym->aop = aop = newAsmop (AOP_DIR);
853 aop->aopu.aop_dir = sym->rname;
854 aop->size = getSize (sym->type);
858 /* special case for a function */
859 if (IS_FUNC (sym->type) && !(sym->isitmp))
861 sym->aop = aop = newAsmop (AOP_IMMD);
862 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
863 aop->size = FPTRSIZE;
867 /* only remaining is far space */
868 /* in which case DPTR gets the address */
869 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
874 emitcode ("mov", "dptr,#%s", sym->rname);
879 emitcode ("mov", "dptr,#%s", sym->rname);
881 aop->size = getSize (sym->type);
883 /* if it is in code space */
884 if (IN_CODESPACE (space))
890 /*-----------------------------------------------------------------*/
891 /* aopForRemat - rematerialzes an object */
892 /*-----------------------------------------------------------------*/
894 aopForRemat (symbol * sym)
896 iCode *ic = sym->rematiCode;
897 asmop *aop = newAsmop (AOP_IMMD);
904 val += (int) operandLitValue (IC_RIGHT (ic));
905 else if (ic->op == '-')
906 val -= (int) operandLitValue (IC_RIGHT (ic));
907 else if (IS_CAST_ICODE(ic)) {
908 sym_link *from_type = operandType(IC_RIGHT(ic));
909 aop->aopu.aop_immd.from_cast_remat = 1;
910 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
911 ptr_type = pointerTypeToGPByte (DCL_TYPE(from_type), NULL, NULL);
915 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
920 SNPRINTF (buffer, sizeof(buffer),
922 OP_SYMBOL (IC_LEFT (ic))->rname,
923 val >= 0 ? '+' : '-',
924 abs (val) & 0xffffff);
928 if (IS_ASSIGN_ICODE(ic) && isOperandLiteral(IC_RIGHT(ic)))
930 SNPRINTF(buffer, sizeof(buffer),
931 "0x%x",(int) operandLitValue (IC_RIGHT (ic)));
935 strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
939 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
940 /* set immd2 field if required */
941 if (aop->aopu.aop_immd.from_cast_remat)
943 tsprintf(buffer, sizeof(buffer), "#!constbyte",ptr_type);
944 aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
950 /*-----------------------------------------------------------------*/
951 /* aopHasRegs - returns true if aop has regs between from-to */
952 /*-----------------------------------------------------------------*/
953 static int aopHasRegs(asmop *aop, int from, int to)
957 if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
959 for (; size < aop->size ; size++) {
961 for (reg = from ; reg <= to ; reg++)
962 if (aop->aopu.aop_reg[size] == REG_WITH_INDEX(reg)) return 1;
967 /*-----------------------------------------------------------------*/
968 /* regsInCommon - two operands have some registers in common */
969 /*-----------------------------------------------------------------*/
971 regsInCommon (operand * op1, operand * op2)
976 /* if they have registers in common */
977 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
980 sym1 = OP_SYMBOL (op1);
981 sym2 = OP_SYMBOL (op2);
983 if (sym1->nRegs == 0 || sym2->nRegs == 0)
986 for (i = 0; i < sym1->nRegs; i++)
992 for (j = 0; j < sym2->nRegs; j++)
997 if (sym2->regs[j] == sym1->regs[i])
1005 /*-----------------------------------------------------------------*/
1006 /* operandsEqu - equivalent */
1007 /*-----------------------------------------------------------------*/
1009 operandsEqu (operand * op1, operand * op2)
1011 symbol *sym1, *sym2;
1013 /* if they're not symbols */
1014 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
1017 sym1 = OP_SYMBOL (op1);
1018 sym2 = OP_SYMBOL (op2);
1020 /* if both are itemps & one is spilt
1021 and the other is not then false */
1022 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
1023 sym1->isspilt != sym2->isspilt)
1026 /* if they are the same */
1030 /* if they have the same rname */
1031 if (sym1->rname[0] && sym2->rname[0] &&
1032 strcmp (sym1->rname, sym2->rname) == 0 &&
1033 !(IS_PARM (op2) && IS_ITEMP (op1)))
1036 /* if left is a tmp & right is not */
1037 if (IS_ITEMP (op1) &&
1040 (sym1->usl.spillLoc == sym2))
1043 if (IS_ITEMP (op2) &&
1047 (sym2->usl.spillLoc == sym1))
1050 /* are they spilt to the same location */
1051 if (IS_ITEMP (op2) &&
1055 (sym1->usl.spillLoc == sym2->usl.spillLoc))
1061 /*-----------------------------------------------------------------*/
1062 /* sameRegs - two asmops have the same registers */
1063 /*-----------------------------------------------------------------*/
1065 sameRegs (asmop * aop1, asmop * aop2)
1071 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
1078 if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
1081 if (aop1->type != aop2->type)
1084 if (aop1->size != aop2->size)
1087 for (i = 0; i < aop1->size; i++)
1088 if (aop1->aopu.aop_reg[i] != aop2->aopu.aop_reg[i])
1094 /*-----------------------------------------------------------------*/
1095 /* aopOp - allocates an asmop for an operand : */
1096 /*-----------------------------------------------------------------*/
1098 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
1107 /* if this a literal */
1108 if (IS_OP_LITERAL (op))
1110 op->aop = aop = newAsmop (AOP_LIT);
1111 aop->aopu.aop_lit = op->operand.valOperand;
1112 aop->size = getSize (operandType (op));
1116 /* if already has a asmop then continue */
1119 if ((op->aop->type == AOP_DPTR && useDP2)
1120 || (op->aop->type == AOP_DPTR2 && !useDP2))
1124 op->aop->allocated++;
1129 /* if the underlying symbol has a aop */
1130 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
1132 op->aop = OP_SYMBOL (op)->aop;
1133 if ((op->aop->type == AOP_DPTR && useDP2)
1134 || (op->aop->type == AOP_DPTR2 && !useDP2))
1138 op->aop->allocated++;
1143 /* if this is a true symbol */
1144 if (IS_TRUE_SYMOP (op))
1146 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
1150 /* this is a temporary : this has
1156 e) can be a return use only */
1158 sym = OP_SYMBOL (op);
1160 /* if the type is a conditional */
1161 if (sym->regType == REG_CND)
1163 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
1168 /* if it is spilt then two situations
1170 b) has a spill location */
1171 if (sym->isspilt || sym->nRegs == 0)
1174 /* rematerialize it NOW */
1177 sym->aop = op->aop = aop =
1179 aop->size = getSize (sym->type);
1186 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
1187 aop->size = getSize (sym->type);
1188 for (i = 0; i < 2; i++)
1189 aop->aopu.aop_str[i] = accUse[i];
1199 /* a AOP_STR uses DPTR, but DPTR is already in use;
1202 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
1205 aop = op->aop = sym->aop = newAsmop (AOP_STR);
1206 aop->size = getSize (sym->type);
1207 for (i = 0; i < fReturnSizeDS390; i++)
1208 aop->aopu.aop_str[i] = fReturn[i];
1212 if (sym->dptr) { /* has been allocated to a DPTRn */
1213 aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
1214 aop->size = getSize (sym->type);
1215 aop->aopu.dptr = sym->dptr;
1219 if (sym->usl.spillLoc)
1221 asmop *oldAsmOp = NULL;
1223 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1225 /* force a new aop if sizes differ */
1226 oldAsmOp = sym->usl.spillLoc->aop;
1227 sym->usl.spillLoc->aop = NULL;
1229 sym->aop = op->aop = aop =
1230 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
1231 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1233 /* Don't reuse the new aop, go with the last one */
1234 sym->usl.spillLoc->aop = oldAsmOp;
1236 aop->size = getSize (sym->type);
1240 /* else must be a dummy iTemp */
1241 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1242 aop->size = getSize (sym->type);
1246 /* if the type is a bit register */
1247 if (sym->regType == REG_BIT)
1249 sym->aop = op->aop = aop = newAsmop (AOP_CRY);
1250 aop->size = sym->nRegs;//1???
1251 aop->aopu.aop_reg[0] = sym->regs[0];
1252 aop->aopu.aop_dir = sym->regs[0]->name;
1256 /* must be in a register */
1257 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1258 aop->size = sym->nRegs;
1259 for (i = 0; i < sym->nRegs; i++)
1260 aop->aopu.aop_reg[i] = sym->regs[i];
1263 /*-----------------------------------------------------------------*/
1264 /* freeAsmop - free up the asmop given to an operand */
1265 /*----------------------------------------------------------------*/
1267 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1284 /* depending on the asmop type only three cases need work
1285 AOP_R0, AOP_R1 & AOP_STK */
1293 emitcode ("pop", "ar0");
1297 bitVectUnSetBit (ic->rUsed, R0_IDX);
1305 emitcode ("pop", "ar1");
1309 bitVectUnSetBit (ic->rUsed, R1_IDX);
1315 int stk = aop->aopu.aop_stk + aop->size;
1316 bitVectUnSetBit (ic->rUsed, R0_IDX);
1317 bitVectUnSetBit (ic->rUsed, R1_IDX);
1319 getFreePtr (ic, &aop, FALSE);
1321 if (options.stack10bit)
1323 /* I'm not sure what to do here yet... */
1326 "*** Warning: probably generating bad code for "
1327 "10 bit stack mode.\n");
1332 emitcode ("mov", "a,_bp");
1333 emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
1334 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1338 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1343 emitcode ("pop", "acc");
1344 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1347 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1350 freeAsmop (op, NULL, ic, TRUE);
1353 emitcode ("pop", "ar1");
1358 emitcode ("pop", "ar0");
1363 if (_G.dptr1InUse) {
1364 emitcode ("pop","dpx1");
1365 emitcode ("pop","dph1");
1366 emitcode ("pop","dpl1");
1371 emitcode ("pop","dpx");
1372 emitcode ("pop","dph");
1373 emitcode ("pop","dpl");
1379 /* all other cases just dealloc */
1385 OP_SYMBOL (op)->aop = NULL;
1386 /* if the symbol has a spill */
1388 SPIL_LOC (op)->aop = NULL;
1393 #define DEFAULT_ACC_WARNING 0
1394 static int saveAccWarn = DEFAULT_ACC_WARNING;
1397 /*-----------------------------------------------------------------*/
1398 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
1399 /* clobber the accumulator */
1400 /*-----------------------------------------------------------------*/
1402 aopGetUsesAcc (operand * oper, int offset)
1404 asmop * aop = AOP (oper);
1406 if (offset > (aop->size - 1))
1426 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1437 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1443 /* Error case --- will have been caught already */
1449 /*-------------------------------------------------------------------*/
1450 /* aopGet - for fetching value of the aop */
1452 /* Set saveAcc to NULL if you are sure it is OK to clobber the value */
1453 /* in the accumulator. Set it to the name of a free register */
1454 /* if acc must be preserved; the register will be used to preserve */
1455 /* acc temporarily and to return the result byte. */
1456 /*-------------------------------------------------------------------*/
1458 aopGet (operand * oper,
1464 asmop * aop = AOP (oper);
1466 /* offset is greater than
1468 if (offset > (aop->size - 1) &&
1469 aop->type != AOP_LIT)
1472 /* depending on type */
1480 /* if we need to increment it */
1481 while (offset > aop->coff)
1483 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1487 while (offset < aop->coff)
1489 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1496 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1497 return (dname ? "acc" : "a");
1499 SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1500 return Safe_strdup(buffer);
1503 assert(offset <= 3);
1504 return dptrn[aop->aopu.dptr][offset];
1509 if (aop->type == AOP_DPTR2)
1517 // if (aop->type != AOP_DPTR2)
1519 // if (saveAccWarn) { fprintf(stderr, "saveAcc for DPTR...\n"); }
1520 // emitcode(";", "spanky: saveAcc for DPTR");
1523 emitcode ("xch", "a, %s", saveAcc);
1528 while (offset > aop->coff)
1530 emitcode ("inc", "dptr");
1534 while (offset < aop->coff)
1536 emitcode ("lcall", "__decdptr");
1543 emitcode ("clr", "a");
1544 emitcode ("movc", "a,@a+dptr");
1548 emitcode ("movx", "a,@dptr");
1551 if (aop->type == AOP_DPTR2)
1559 emitcode ("xch", "a, %s", saveAcc);
1560 // if (strcmp(saveAcc, "_ap"))
1562 // emitcode(";", "spiffy: non _ap return from aopGet.");
1567 return (dname ? "acc" : "a");
1570 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1572 SNPRINTF(buffer, sizeof(buffer),
1573 "%s",aop->aopu.aop_immd.aop_immd2);
1577 SNPRINTF(buffer, sizeof(buffer),
1578 "#%s", aop->aopu.aop_immd.aop_immd1);
1584 tsprintf(buffer, sizeof(buffer),
1585 "#!his",aop->aopu.aop_immd.aop_immd1);
1588 tsprintf(buffer, sizeof(buffer),
1589 "#!hihis",aop->aopu.aop_immd.aop_immd1);
1592 tsprintf(buffer, sizeof(buffer),
1593 "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1595 default: /* should not need this (just in case) */
1596 SNPRINTF (buffer, sizeof(buffer),
1598 aop->aopu.aop_immd.aop_immd1,
1604 SNPRINTF (buffer, sizeof(buffer),
1606 aop->aopu.aop_immd.aop_immd1);
1608 return Safe_strdup(buffer);
1611 if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
1613 SNPRINTF (buffer, sizeof(buffer),
1615 aop->aopu.aop_dir, offset * 8);
1619 SNPRINTF (buffer, sizeof(buffer),
1626 SNPRINTF (buffer, sizeof(buffer),
1631 return Safe_strdup(buffer);
1635 return aop->aopu.aop_reg[offset]->dname;
1637 return aop->aopu.aop_reg[offset]->name;
1640 emitcode ("clr", "a");
1641 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1642 emitcode ("rlc", "a");
1643 return (dname ? "acc" : "a");
1646 if (!offset && dname)
1648 return aop->aopu.aop_str[offset];
1651 return aopLiteral (aop->aopu.aop_lit, offset);
1655 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1659 return aop->aopu.aop_str[offset];
1663 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1664 "aopget got unsupported aop->type");
1667 return NULL; // not reached, but makes compiler happy.
1670 /*-----------------------------------------------------------------*/
1671 /* aopPut - puts a string for a aop and indicates if acc is in use */
1672 /*-----------------------------------------------------------------*/
1674 aopPut (operand * result, const char *s, int offset)
1676 bool bvolatile = isOperandVolatile (result, FALSE);
1677 bool accuse = FALSE;
1678 asmop * aop = AOP (result);
1680 if (aop->size && offset > (aop->size - 1))
1682 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1683 "aopPut got offset > aop->size");
1687 /* will assign value to value */
1688 /* depending on where it is ofcourse */
1692 MOVA (s); /* read s in case it was volatile */
1697 if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1699 SNPRINTF (buffer, sizeof(buffer),
1701 aop->aopu.aop_dir, offset * 8);
1705 SNPRINTF (buffer, sizeof(buffer),
1707 aop->aopu.aop_dir, offset);
1711 SNPRINTF (buffer, sizeof(buffer),
1716 if (strcmp (buffer, s) || bvolatile)
1718 emitcode ("mov", "%s,%s", buffer, s);
1720 if (!strcmp (buffer, "acc"))
1727 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1728 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1731 strcmp (s, "r0") == 0 ||
1732 strcmp (s, "r1") == 0 ||
1733 strcmp (s, "r2") == 0 ||
1734 strcmp (s, "r3") == 0 ||
1735 strcmp (s, "r4") == 0 ||
1736 strcmp (s, "r5") == 0 ||
1737 strcmp (s, "r6") == 0 ||
1738 strcmp (s, "r7") == 0)
1740 emitcode ("mov", "%s,%s",
1741 aop->aopu.aop_reg[offset]->dname, s);
1745 emitcode ("mov", "%s,%s",
1746 aop->aopu.aop_reg[offset]->name, s);
1752 emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1758 if (aop->type == AOP_DPTR2)
1766 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1767 "aopPut writing to code space");
1771 while (offset > aop->coff)
1774 emitcode ("inc", "dptr");
1777 while (offset < aop->coff)
1780 emitcode ("lcall", "__decdptr");
1785 /* if not in accumulator */
1788 emitcode ("movx", "@dptr,a");
1790 if (aop->type == AOP_DPTR2)
1798 while (offset > aop->coff)
1801 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1803 while (offset < aop->coff)
1806 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1813 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1818 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1820 else if (strcmp (s, "r0") == 0 ||
1821 strcmp (s, "r1") == 0 ||
1822 strcmp (s, "r2") == 0 ||
1823 strcmp (s, "r3") == 0 ||
1824 strcmp (s, "r4") == 0 ||
1825 strcmp (s, "r5") == 0 ||
1826 strcmp (s, "r6") == 0 ||
1827 strcmp (s, "r7") == 0)
1830 SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1831 emitcode ("mov", "@%s,%s",
1832 aop->aopu.aop_ptr->name, buffer);
1836 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1841 if (strcmp (s, "a") == 0)
1842 emitcode ("push", "acc");
1846 emitcode ("push", "acc");
1848 emitcode ("push", s);
1854 /* if not bit variable */
1855 if (!aop->aopu.aop_dir)
1857 /* inefficient: move carry into A and use jz/jnz */
1858 emitcode ("clr", "a");
1859 emitcode ("rlc", "a");
1865 emitcode ("clr", "%s", aop->aopu.aop_dir);
1867 emitcode ("setb", "%s", aop->aopu.aop_dir);
1868 else if (!strcmp (s, "c"))
1869 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1870 else if (strcmp (s, aop->aopu.aop_dir))
1873 /* set C, if a >= 1 */
1874 emitcode ("add", "a,#!constbyte",0xff);
1875 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1882 if (strcmp (aop->aopu.aop_str[offset], s) || bvolatile)
1883 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1889 if (!offset && (strcmp (s, "acc") == 0) && !bvolatile)
1892 if (strcmp (aop->aopu.aop_str[offset], s) && !bvolatile)
1893 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1897 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1898 "aopPut got unsupported aop->type");
1906 /*--------------------------------------------------------------------*/
1907 /* reAdjustPreg - points a register back to where it should (coff==0) */
1908 /*--------------------------------------------------------------------*/
1910 reAdjustPreg (asmop * aop)
1912 if ((aop->coff==0) || (aop->size <= 1))
1920 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1924 if (aop->type == AOP_DPTR2)
1931 emitcode ("lcall", "__decdptr");
1934 if (aop->type == AOP_DPTR2)
1943 /*-----------------------------------------------------------------*/
1944 /* opIsGptr: returns non-zero if the passed operand is */
1945 /* a generic pointer type. */
1946 /*-----------------------------------------------------------------*/
1948 opIsGptr (operand * op)
1950 sym_link *type = operandType (op);
1952 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1959 /*-----------------------------------------------------------------*/
1960 /* getDataSize - get the operand data size */
1961 /*-----------------------------------------------------------------*/
1963 getDataSize (operand * op)
1966 size = AOP_SIZE (op);
1967 if (size == GPTRSIZE)
1969 sym_link *type = operandType (op);
1970 if (IS_GENPTR (type))
1972 /* generic pointer; arithmetic operations
1973 * should ignore the high byte (pointer type).
1981 /*-----------------------------------------------------------------*/
1982 /* outAcc - output Acc */
1983 /*-----------------------------------------------------------------*/
1985 outAcc (operand * result)
1988 size = getDataSize (result);
1991 aopPut (result, "a", 0);
1994 /* unsigned or positive */
1997 aopPut (result, zero, offset++);
2002 /*-----------------------------------------------------------------*/
2003 /* outBitC - output a bit C */
2004 /*-----------------------------------------------------------------*/
2006 outBitC (operand * result)
2008 /* if the result is bit */
2009 if (AOP_TYPE (result) == AOP_CRY)
2011 aopPut (result, "c", 0);
2015 emitcode ("clr", "a");
2016 emitcode ("rlc", "a");
2021 /*-----------------------------------------------------------------*/
2022 /* toBoolean - emit code for orl a,operator(sizeop) */
2023 /*-----------------------------------------------------------------*/
2025 toBoolean (operand * oper)
2027 int size = AOP_SIZE (oper) - 1;
2031 /* The generic part of a generic pointer should
2032 * not participate in it's truth value.
2034 * i.e. 0x10000000 is zero.
2036 if (opIsGptr (oper))
2038 D (emitcode (";", "toBoolean: generic ptr special case."));
2042 _startLazyDPSEvaluation ();
2043 MOVA (aopGet (oper, 0, FALSE, FALSE, NULL));
2044 if (AOP_NEEDSACC (oper) && size && (AOP (oper)->type != AOP_ACC))
2047 emitcode("mov", "b,a");
2050 MOVA (aopGet (oper, offset++, FALSE, FALSE, NULL));
2051 emitcode ("orl", "b,a");
2053 MOVA (aopGet (oper, offset++, FALSE, FALSE, NULL));
2054 emitcode ("orl", "a,b");
2061 emitcode ("orl", "a,%s",
2062 aopGet (oper, offset++, FALSE, FALSE, NULL));
2065 _endLazyDPSEvaluation ();
2069 /*-----------------------------------------------------------------*/
2070 /* genNot - generate code for ! operation */
2071 /*-----------------------------------------------------------------*/
2077 D (emitcode (";", "genNot"));
2079 /* assign asmOps to operand & result */
2080 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2081 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
2083 /* if in bit space then a special case */
2084 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2086 /* if left==result then cpl bit */
2087 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2089 emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2093 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2094 emitcode ("cpl", "c");
2095 outBitC (IC_RESULT (ic));
2100 toBoolean (IC_LEFT (ic));
2102 /* set C, if a == 0 */
2103 tlbl = newiTempLabel (NULL);
2104 emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
2106 outBitC (IC_RESULT (ic));
2109 /* release the aops */
2110 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2111 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2115 /*-----------------------------------------------------------------*/
2116 /* genCpl - generate code for complement */
2117 /*-----------------------------------------------------------------*/
2124 sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
2126 D(emitcode (";", "genCpl"));
2128 /* assign asmOps to operand & result */
2129 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2130 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
2132 /* special case if in bit space */
2133 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2137 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
2138 (SPEC_USIGN (letype) && IS_CHAR (letype)))
2140 /* promotion rules are responsible for this strange result:
2141 bit -> int -> ~int -> bit
2142 uchar -> int -> ~int -> bit
2144 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
2148 tlbl=newiTempLabel(NULL);
2149 l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE, NULL);
2150 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
2151 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
2152 IS_AOP_PREG (IC_LEFT (ic)))
2154 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
2159 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
2162 outBitC (IC_RESULT(ic));
2166 size = AOP_SIZE (IC_RESULT (ic));
2167 _startLazyDPSEvaluation ();
2170 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL);
2172 emitcode ("cpl", "a");
2173 aopPut (IC_RESULT (ic), "a", offset++);
2175 _endLazyDPSEvaluation ();
2179 /* release the aops */
2180 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2181 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2184 /*-----------------------------------------------------------------*/
2185 /* genUminusFloat - unary minus for floating points */
2186 /*-----------------------------------------------------------------*/
2188 genUminusFloat (operand * op, operand * result)
2190 int size, offset = 0;
2193 D (emitcode (";", "genUminusFloat"));
2195 /* for this we just copy and then flip the bit */
2197 _startLazyDPSEvaluation ();
2198 size = AOP_SIZE (op) - 1;
2203 aopGet (op, offset, FALSE, FALSE, NULL),
2208 l = aopGet (op, offset, FALSE, FALSE, NULL);
2211 emitcode ("cpl", "acc.7");
2212 aopPut (result, "a", offset);
2213 _endLazyDPSEvaluation ();
2216 /*-----------------------------------------------------------------*/
2217 /* genUminus - unary minus code generation */
2218 /*-----------------------------------------------------------------*/
2220 genUminus (iCode * ic)
2225 D (emitcode (";", "genUminus"));
2228 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2229 aopOp (IC_RESULT (ic), ic, TRUE, (AOP_TYPE(IC_LEFT (ic)) == AOP_DPTR));
2231 /* if both in bit space then special
2233 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2234 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2237 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2238 emitcode ("cpl", "c");
2239 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2243 optype = operandType (IC_LEFT (ic));
2245 /* if float then do float stuff */
2246 if (IS_FLOAT (optype))
2248 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2252 /* otherwise subtract from zero */
2253 size = AOP_SIZE (IC_LEFT (ic));
2255 _startLazyDPSEvaluation ();
2258 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL);
2259 if (!strcmp (l, "a"))
2263 emitcode ("cpl", "a");
2264 emitcode ("addc", "a,#0");
2270 emitcode ("clr", "a");
2271 emitcode ("subb", "a,%s", l);
2273 aopPut (IC_RESULT (ic), "a", offset++);
2275 _endLazyDPSEvaluation ();
2277 /* if any remaining bytes in the result */
2278 /* we just need to propagate the sign */
2279 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2281 emitcode ("rlc", "a");
2282 emitcode ("subb", "a,acc");
2284 aopPut (IC_RESULT (ic), "a", offset++);
2288 /* release the aops */
2289 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2290 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2293 /*-----------------------------------------------------------------*/
2294 /* savermask - saves registers in the mask */
2295 /*-----------------------------------------------------------------*/
2296 static void savermask(bitVect *rs_mask)
2300 if (options.useXstack)
2302 if (bitVectBitValue (rs_mask, R0_IDX))
2303 emitcode ("mov", "b,r0");
2304 emitcode ("mov", "r0,%s", spname);
2305 for (i = 0; i < ds390_nRegs; i++)
2307 if (bitVectBitValue (rs_mask, i))
2310 emitcode ("mov", "a,b");
2312 emitcode ("mov", "a,%s", REG_WITH_INDEX (i)->name);
2313 emitcode ("movx", "@r0,a");
2314 emitcode ("inc", "r0");
2317 emitcode ("mov", "%s,r0", spname);
2318 if (bitVectBitValue (rs_mask, R0_IDX))
2319 emitcode ("mov", "r0,b");
2323 bool bits_pushed = FALSE;
2324 for (i = 0; i < ds390_nRegs; i++)
2326 if (bitVectBitValue (rs_mask, i))
2328 bits_pushed = pushReg (i, bits_pushed);
2334 /*-----------------------------------------------------------------*/
2335 /* saveRegisters - will look for a call and save the registers */
2336 /*-----------------------------------------------------------------*/
2338 saveRegisters (iCode * lic)
2344 for (ic = lic; ic; ic = ic->next)
2345 if (ic->op == CALL || ic->op == PCALL)
2350 fprintf (stderr, "found parameter push with no function call\n");
2354 /* if the registers have been saved already or don't need to be then
2357 || (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))) && !TARGET_IS_DS400) )
2360 /* special case if DPTR alive across a function call then must save it
2361 even though callee saves */
2362 if (IS_SYMOP(IC_LEFT(ic)) &&
2363 IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type))
2366 rsave = newBitVect(ic->rMask->size);
2367 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2368 if (bitVectBitValue(ic->rMask,i))
2369 rsave = bitVectSetBit(rsave,i);
2371 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2375 /* save the registers in use at this time but skip the
2376 ones for the result */
2377 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2378 ds390_rUmaskForOp (IC_RESULT(ic)));
2384 /*-----------------------------------------------------------------*/
2385 /* usavermask - restore registers with mask */
2386 /*-----------------------------------------------------------------*/
2387 static void unsavermask(bitVect *rs_mask)
2391 if (options.useXstack)
2393 emitcode ("mov", "r0,%s", spname);
2394 for (i = ds390_nRegs; i >= 0; i--)
2396 if (bitVectBitValue (rs_mask, i))
2398 regs * reg = REG_WITH_INDEX (i);
2399 emitcode ("dec", "r0");
2400 emitcode ("movx", "a,@r0");
2403 emitcode ("push", "acc");
2407 emitcode ("mov", "%s,a", reg->name);
2411 emitcode ("mov", "%s,r0", spname);
2412 if (bitVectBitValue (rs_mask, R0_IDX))
2414 emitcode ("pop", "ar0");
2419 bool bits_popped = FALSE;
2420 for (i = ds390_nRegs; i >= 0; i--)
2422 if (bitVectBitValue (rs_mask, i))
2424 bits_popped = popReg (i, bits_popped);
2430 /*-----------------------------------------------------------------*/
2431 /* unsaveRegisters - pop the pushed registers */
2432 /*-----------------------------------------------------------------*/
2434 unsaveRegisters (iCode * ic)
2438 if (IS_SYMOP(IC_LEFT (ic)) &&
2439 IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2441 rsave = newBitVect(ic->rMask->size);
2442 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2443 if (bitVectBitValue(ic->rMask,i))
2444 rsave = bitVectSetBit(rsave,i);
2446 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2448 /* restore the registers in use at this time but skip the
2449 ones for the result */
2450 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2451 ds390_rUmaskForOp (IC_RESULT(ic)));
2457 /*-----------------------------------------------------------------*/
2459 /*-----------------------------------------------------------------*/
2461 pushSide (operand * oper, int size)
2464 _startLazyDPSEvaluation ();
2467 char *l = aopGet (oper, offset++, FALSE, TRUE, NULL);
2468 if (AOP_TYPE (oper) != AOP_REG &&
2469 AOP_TYPE (oper) != AOP_DIR &&
2473 emitcode ("push", "acc");
2477 emitcode ("push", "%s", l);
2480 _endLazyDPSEvaluation ();
2483 /*-----------------------------------------------------------------*/
2484 /* assignResultValue - also indicates if acc is in use afterwards */
2485 /*-----------------------------------------------------------------*/
2487 assignResultValue (operand * oper, operand * func)
2490 unsigned size = AOP_SIZE (oper);
2491 bool accuse = FALSE;
2492 bool pushedA = FALSE;
2494 if (func && IS_BIT (OP_SYM_ETYPE (func)))
2500 if (size == fReturnSizeDS390)
2502 /* I don't think this case can ever happen... */
2503 /* ACC is the last part of this. If writing the result
2504 * uses ACC, we must preserve it.
2506 if (AOP_NEEDSACC(oper))
2508 emitcode(";", "assignResultValue special case for ACC.");
2509 emitcode("push", "acc");
2515 _startLazyDPSEvaluation ();
2518 accuse |= aopPut (oper, fReturn[offset], offset);
2521 _endLazyDPSEvaluation ();
2525 emitcode ("pop", "acc");
2526 accuse |= aopPut (oper, "a", offset);
2532 /*-----------------------------------------------------------------*/
2533 /* genXpush - pushes onto the external stack */
2534 /*-----------------------------------------------------------------*/
2536 genXpush (iCode * ic)
2538 asmop *aop = newAsmop (0);
2540 int size, offset = 0;
2542 D (emitcode (";", "genXpush"));
2544 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2545 r = getFreePtr (ic, &aop, FALSE);
2547 size = AOP_SIZE (IC_LEFT (ic));
2551 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
2552 emitcode ("mov", "%s,_spx", r->name);
2553 emitcode ("inc", "_spx"); // allocate space first
2554 emitcode ("movx", "@%s,a", r->name);
2558 // allocate space first
2559 emitcode ("mov", "%s,_spx", r->name);
2561 emitcode ("add", "a,#%d", size);
2562 emitcode ("mov", "_spx,a");
2564 _startLazyDPSEvaluation ();
2567 MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE, NULL));
2568 emitcode ("movx", "@%s,a", r->name);
2569 emitcode ("inc", "%s", r->name);
2571 _endLazyDPSEvaluation ();
2574 freeAsmop (NULL, aop, ic, TRUE);
2575 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2578 /*-----------------------------------------------------------------*/
2579 /* genIpush - generate code for pushing this gets a little complex */
2580 /*-----------------------------------------------------------------*/
2582 genIpush (iCode * ic)
2584 int size, offset = 0;
2588 D (emitcode (";", "genIpush"));
2590 /* if this is not a parm push : ie. it is spill push
2591 and spill push is always done on the local stack */
2595 /* and the item is spilt then do nothing */
2596 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2599 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2600 size = AOP_SIZE (IC_LEFT (ic));
2601 /* push it on the stack */
2602 _startLazyDPSEvaluation ();
2605 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE, NULL);
2611 emitcode ("push", "%s", l);
2613 _endLazyDPSEvaluation ();
2617 /* this is a parameter push: in this case we call
2618 the routine to find the call and save those
2619 registers that need to be saved */
2622 /* if use external stack then call the external
2623 stack pushing routine */
2624 if (options.useXstack)
2630 /* then do the push */
2631 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2633 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2634 size = AOP_SIZE (IC_LEFT (ic));
2636 _startLazyDPSEvaluation ();
2639 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE, NULL);
2640 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2641 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2644 if (strcmp (l, prev) || *l == '@')
2646 emitcode ("push", "acc");
2650 emitcode ("push", "%s", l);
2654 _endLazyDPSEvaluation ();
2656 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2659 /*-----------------------------------------------------------------*/
2660 /* genIpop - recover the registers: can happen only for spilling */
2661 /*-----------------------------------------------------------------*/
2663 genIpop (iCode * ic)
2667 D (emitcode (";", "genIpop"));
2669 /* if the temp was not pushed then */
2670 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2673 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2674 size = AOP_SIZE (IC_LEFT (ic));
2675 offset = (size - 1);
2676 _startLazyDPSEvaluation ();
2679 emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2680 FALSE, TRUE, NULL));
2682 _endLazyDPSEvaluation ();
2684 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2687 /*-----------------------------------------------------------------*/
2688 /* saveRBank - saves an entire register bank on the stack */
2689 /*-----------------------------------------------------------------*/
2691 saveRBank (int bank, iCode * ic, bool pushPsw)
2694 int count = 8 + (ds390_nBitRegs/8) + (pushPsw ? 1 : 0);
2698 if (options.useXstack)
2702 /* Assume r0 is available for use. */
2703 r = REG_WITH_INDEX (R0_IDX);;
2708 r = getFreePtr (ic, &aop, FALSE);
2710 // allocate space first
2711 emitcode ("mov", "%s,_spx", r->name);
2713 emitcode ("add", "a,#%d", count);
2714 emitcode ("mov", "_spx,a");
2717 for (i = 0; i < 8; i++) /* only R0-R7 needs saving */
2719 if (options.useXstack)
2721 emitcode ("mov", "a,(%s+%d)",
2722 regs390[i].base, 8 * bank + regs390[i].offset);
2723 emitcode ("movx", "@%s,a", r->name);
2725 emitcode ("inc", "%s", r->name);
2728 emitcode ("push", "(%s+%d)",
2729 regs390[i].base, 8 * bank + regs390[i].offset);
2732 if (ds390_nBitRegs > 0)
2734 if (options.useXstack)
2736 emitcode ("mov", "a,bits");
2737 emitcode ("movx", "@%s,a", r->name);
2739 emitcode ("inc", "%s", r->name);
2743 emitcode ("push", "bits");
2750 if (options.useXstack)
2752 emitcode ("mov", "a,psw");
2753 emitcode ("movx", "@%s,a", r->name);
2757 emitcode ("push", "psw");
2760 emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2765 freeAsmop (NULL, aop, ic, TRUE);
2774 /*-----------------------------------------------------------------*/
2775 /* unsaveRBank - restores the register bank from stack */
2776 /*-----------------------------------------------------------------*/
2778 unsaveRBank (int bank, iCode * ic, bool popPsw)
2784 if (options.useXstack)
2788 /* Assume r0 is available for use. */
2789 r = REG_WITH_INDEX (R0_IDX);;
2794 r = getFreePtr (ic, &aop, FALSE);
2796 emitcode ("mov", "%s,_spx", r->name);
2801 if (options.useXstack)
2803 emitcode ("dec", "%s", r->name);
2804 emitcode ("movx", "a,@%s", r->name);
2805 emitcode ("mov", "psw,a");
2809 emitcode ("pop", "psw");
2813 if (ds390_nBitRegs > 0)
2815 if (options.useXstack)
2817 emitcode ("dec", "%s", r->name);
2818 emitcode ("movx", "a,@%s", r->name);
2819 emitcode ("mov", "bits,a");
2823 emitcode ("pop", "bits");
2827 for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2829 if (options.useXstack)
2831 emitcode ("dec", "%s", r->name);
2832 emitcode ("movx", "a,@%s", r->name);
2833 emitcode ("mov", "(%s+%d),a",
2834 regs390[i].base, 8 * bank + regs390[i].offset);
2838 emitcode ("pop", "(%s+%d)",
2839 regs390[i].base, 8 * bank + regs390[i].offset);
2843 if (options.useXstack)
2845 emitcode ("mov", "_spx,%s", r->name);
2850 freeAsmop (NULL, aop, ic, TRUE);
2854 /*-----------------------------------------------------------------*/
2855 /* genSend - gen code for SEND */
2856 /*-----------------------------------------------------------------*/
2857 static void genSend(set *sendSet)
2862 static int rb1_count = 0;
2864 /* first we do all bit parameters */
2865 for (sic = setFirstItem (sendSet); sic;
2866 sic = setNextItem (sendSet))
2868 if (sic->argreg > 12)
2870 int bit = sic->argreg-13;
2872 aopOp (IC_LEFT (sic), sic, FALSE,
2873 (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2875 /* if left is a literal then
2876 we know what the value is */
2877 if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2879 if (((int) operandLitValue (IC_LEFT (sic))))
2880 emitcode ("setb", "b[%d]", bit);
2882 emitcode ("clr", "b[%d]", bit);
2884 else if (AOP_TYPE (IC_LEFT (sic)) == AOP_CRY)
2886 char *l = AOP (IC_LEFT (sic))->aopu.aop_dir;
2887 if (strcmp (l, "c"))
2888 emitcode ("mov", "c,%s", l);
2889 emitcode ("mov", "b[%d],c", bit);
2894 toBoolean (IC_LEFT (sic));
2895 /* set C, if a >= 1 */
2896 emitcode ("add", "a,#0xff");
2897 emitcode ("mov", "b[%d],c", bit);
2902 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2908 saveRegisters (setFirstItem (sendSet));
2909 emitcode ("mov", "bits,b");
2912 /* then we do all other parameters */
2913 for (sic = setFirstItem (sendSet); sic;
2914 sic = setNextItem (sendSet))
2916 if (sic->argreg <= 12)
2918 int size, offset = 0;
2920 size = getSize (operandType (IC_LEFT (sic)));
2921 D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2922 if (sendCount == 0) { /* first parameter */
2923 // we know that dpl(hxb) is the result, so
2925 _startLazyDPSEvaluation ();
2927 aopOp (IC_LEFT (sic), sic, FALSE,
2928 (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2930 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2934 char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE, NULL);
2935 if (strcmp (l, fReturn[offset]))
2937 emitcode ("mov", "%s,%s", fReturn[offset], l);
2941 _endLazyDPSEvaluation ();
2942 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2944 } else { /* if more parameter in registers */
2945 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2947 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (IC_LEFT (sic), offset++,
2948 FALSE, FALSE, NULL));
2950 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2958 adjustEsp(const char *reg)
2960 emitcode ("anl","%s,#3", reg);
2961 if (TARGET_IS_DS400)
2963 emitcode ("orl","%s,#!constbyte",
2965 (options.stack_loc >> 8) & 0xff);
2969 /*-----------------------------------------------------------------*/
2970 /* selectRegBank - emit code to select the register bank */
2971 /*-----------------------------------------------------------------*/
2973 selectRegBank (short bank, bool keepFlags)
2975 /* if f.e. result is in carry */
2978 emitcode ("anl", "psw,#0xE7");
2980 emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2984 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2988 /*-----------------------------------------------------------------*/
2989 /* genCall - generates a call statement */
2990 /*-----------------------------------------------------------------*/
2992 genCall (iCode * ic)
2996 bool restoreBank = FALSE;
2997 bool swapBanks = FALSE;
2998 bool accuse = FALSE;
2999 bool accPushed = FALSE;
3000 bool resultInF0 = FALSE;
3001 bool assignResultGenerated = FALSE;
3003 D (emitcode (";", "genCall"));
3005 /* if we are calling a not _naked function that is not using
3006 the same register bank then we need to save the
3007 destination registers on the stack */
3008 dtype = operandType (IC_LEFT (ic));
3009 etype = getSpec(dtype);
3010 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
3011 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
3012 IFFUNC_ISISR (currFunc->type))
3016 /* This is unexpected; the bank should have been saved in
3019 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
3025 /* if caller saves & we have not saved then */
3029 /* if send set is not empty then assign */
3030 /* We've saved all the registers we care about;
3031 * therefore, we may clobber any register not used
3032 * in the calling convention (i.e. anything not in
3037 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
3038 genSend(reverseSet(_G.sendSet));
3040 genSend(_G.sendSet);
3047 emitcode ("mov", "psw,#!constbyte",
3048 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3052 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
3053 OP_SYMBOL (IC_LEFT (ic))->rname :
3054 OP_SYMBOL (IC_LEFT (ic))->name));
3058 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
3061 /* if we need assign a result value */
3062 if ((IS_ITEMP (IC_RESULT (ic)) &&
3063 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3064 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3065 OP_SYMBOL (IC_RESULT (ic))->accuse ||
3066 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3067 IS_TRUE_SYMOP (IC_RESULT (ic)))
3069 if (isOperandInFarSpace (IC_RESULT (ic))
3070 && getSize (operandType (IC_RESULT (ic))) <= 2)
3072 int size = getSize (operandType (IC_RESULT (ic)));
3073 bool pushedB = FALSE;
3075 /* Special case for 1 or 2 byte return in far space. */
3080 emitcode ("mov", "b,%s", fReturn[1]);
3084 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
3089 aopPut (IC_RESULT (ic), "a", 0);
3093 aopPut (IC_RESULT (ic), "b", 1);
3095 assignResultGenerated = TRUE;
3096 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3100 bool pushedB = pushB ();
3101 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
3104 accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3105 assignResultGenerated = TRUE;
3106 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3110 /* adjust the stack for parameters if required */
3114 if (options.stack10bit) {
3115 if (ic->parmBytes <= 10) {
3116 emitcode(";","stack adjustment for parms");
3117 for (i=0; i < ic->parmBytes ; i++) {
3118 emitcode("pop","acc");
3122 emitcode ("clr","c");
3123 emitcode ("mov","a,sp");
3124 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
3125 emitcode ("mov","sp,a");
3126 emitcode ("mov","a,esp");
3128 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
3129 emitcode ("mov","esp,a");
3133 if (ic->parmBytes > 3)
3137 emitcode ("push", "acc");
3140 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3141 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3142 !assignResultGenerated)
3144 emitcode ("mov", "F0,c");
3148 emitcode ("mov", "a,%s", spname);
3149 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
3150 emitcode ("mov", "%s,a", spname);
3152 /* unsaveRegisters from xstack needs acc, but */
3153 /* unsaveRegisters from stack needs this popped */
3154 if (accPushed && !options.useXstack)
3156 emitcode ("pop", "acc");
3161 for (i = 0; i < ic->parmBytes; i++)
3162 emitcode ("dec", "%s", spname);
3166 /* if we had saved some registers then unsave them */
3167 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3169 if (accuse && !accPushed && options.useXstack)
3171 /* xstack needs acc, but doesn't touch normal stack */
3172 emitcode ("push", "acc");
3175 unsaveRegisters (ic);
3178 /* if register bank was saved then pop them */
3180 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
3182 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
3185 emitcode ("mov", "c,F0");
3187 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
3188 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3189 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3193 emitcode ("pop", "acc");
3196 /*-----------------------------------------------------------------*/
3197 /* genPcall - generates a call by pointer statement */
3198 /*-----------------------------------------------------------------*/
3200 genPcall (iCode * ic)
3204 symbol *rlbl = newiTempLabel (NULL);
3205 bool restoreBank=FALSE;
3206 bool resultInF0 = FALSE;
3208 D (emitcode (";", "genPcall"));
3210 dtype = operandType (IC_LEFT (ic))->next;
3211 etype = getSpec(dtype);
3212 /* if caller saves & we have not saved then */
3216 /* if we are calling a not _naked function that is not using
3217 the same register bank then we need to save the
3218 destination registers on the stack */
3219 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
3220 IFFUNC_ISISR (currFunc->type) &&
3221 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
3222 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3226 /* push the return address on to the stack */
3227 emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
3228 emitcode ("push", "acc");
3229 emitcode ("mov", "a,#!hil", (rlbl->key + 100));
3230 emitcode ("push", "acc");
3232 if (options.model == MODEL_FLAT24)
3234 emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
3235 emitcode ("push", "acc");
3238 /* now push the calling address */
3239 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3241 pushSide (IC_LEFT (ic), FPTRSIZE);
3243 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3245 /* if send set is not empty the assign */
3248 genSend(reverseSet(_G.sendSet));
3253 emitcode ("ret", "");
3257 /* if we need assign a result value */
3258 if ((IS_ITEMP (IC_RESULT (ic)) &&
3259 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3260 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3261 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3262 IS_TRUE_SYMOP (IC_RESULT (ic)))
3266 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
3269 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3271 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3274 /* adjust the stack for parameters if required */
3278 if (options.stack10bit) {
3279 if (ic->parmBytes <= 10) {
3280 emitcode(";","stack adjustment for parms");
3281 for (i=0; i < ic->parmBytes ; i++) {
3282 emitcode("pop","acc");
3285 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3286 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3288 emitcode ("mov", "F0,c");
3293 emitcode ("clr","c");
3294 emitcode ("mov","a,sp");
3295 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
3296 emitcode ("mov","sp,a");
3297 emitcode ("mov","a,esp");
3299 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
3300 emitcode ("mov","esp,a");
3304 if (ic->parmBytes > 3) {
3305 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3306 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3308 emitcode ("mov", "F0,c");
3312 emitcode ("mov", "a,%s", spname);
3313 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
3314 emitcode ("mov", "%s,a", spname);
3317 for (i = 0; i < ic->parmBytes; i++)
3318 emitcode ("dec", "%s", spname);
3321 /* if register bank was saved then unsave them */
3323 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3325 /* if we had saved some registers then unsave them */
3327 unsaveRegisters (ic);
3329 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3332 emitcode ("mov", "c,F0");
3334 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
3335 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3336 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3340 /*-----------------------------------------------------------------*/
3341 /* resultRemat - result is rematerializable */
3342 /*-----------------------------------------------------------------*/
3344 resultRemat (iCode * ic)
3346 if (SKIP_IC (ic) || ic->op == IFX)
3349 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3351 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3352 if (sym->remat && !POINTER_SET (ic))
3359 /*-----------------------------------------------------------------*/
3360 /* inExcludeList - return 1 if the string is in exclude Reg list */
3361 /*-----------------------------------------------------------------*/
3363 regsCmp(void *p1, void *p2)
3365 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3369 inExcludeList (char *s)
3371 const char *p = setFirstItem(options.excludeRegsSet);
3373 if (p == NULL || STRCASECMP(p, "none") == 0)
3377 return isinSetWith(options.excludeRegsSet, s, regsCmp);
3380 /*-----------------------------------------------------------------*/
3381 /* genFunction - generated code for function entry */
3382 /*-----------------------------------------------------------------*/
3384 genFunction (iCode * ic)
3386 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3388 bool switchedPSW = FALSE;
3389 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3391 D (emitcode (";", "genFunction"));
3394 /* create the function header */
3395 emitcode (";", "-----------------------------------------");
3396 emitcode (";", " function %s", sym->name);
3397 emitcode (";", "-----------------------------------------");
3399 emitcode ("", "%s:", sym->rname);
3400 lineCurr->isLabel = 1;
3401 ftype = operandType (IC_LEFT (ic));
3402 _G.currentFunc = sym;
3404 if (IFFUNC_ISNAKED(ftype))
3406 emitcode(";", "naked function: no prologue.");
3410 if (options.stack_probe)
3411 emitcode ("lcall","__stack_probe");
3413 /* here we need to generate the equates for the
3414 register bank if required */
3415 if (FUNC_REGBANK (ftype) != rbank)
3419 rbank = FUNC_REGBANK (ftype);
3420 for (i = 0; i < ds390_nRegs; i++)
3422 if (regs390[i].print) {
3423 if (strcmp (regs390[i].base, "0") == 0)
3424 emitcode ("", "%s !equ !constbyte",
3426 8 * rbank + regs390[i].offset);
3428 emitcode ("", "%s !equ %s + !constbyte",
3431 8 * rbank + regs390[i].offset);
3436 /* if this is an interrupt service routine then
3437 save acc, b, dpl, dph */
3438 if (IFFUNC_ISISR (sym->type))
3440 if (!inExcludeList ("acc"))
3441 emitcode ("push", "acc");
3442 if (!inExcludeList ("b"))
3443 emitcode ("push", "b");
3444 if (!inExcludeList ("dpl"))
3445 emitcode ("push", "dpl");
3446 if (!inExcludeList ("dph"))
3447 emitcode ("push", "dph");
3448 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3450 emitcode ("push", "dpx");
3451 /* Make sure we're using standard DPTR */
3452 emitcode ("push", "dps");
3453 emitcode ("mov", "dps,#0");
3454 if (options.stack10bit)
3456 /* This ISR could conceivably use DPTR2. Better save it. */
3457 emitcode ("push", "dpl1");
3458 emitcode ("push", "dph1");
3459 emitcode ("push", "dpx1");
3460 emitcode ("push", DP2_RESULT_REG);
3463 /* if this isr has no bank i.e. is going to
3464 run with bank 0 , then we need to save more
3466 if (!FUNC_REGBANK (sym->type))
3470 /* if this function does not call any other
3471 function then we can be economical and
3472 save only those registers that are used */
3473 if (!IFFUNC_HASFCALL(sym->type))
3475 /* if any registers used */
3478 bool bits_pushed = FALSE;
3479 /* save the registers used */
3480 for (i = 0; i < sym->regsUsed->size; i++)
3482 if (bitVectBitValue (sym->regsUsed, i))
3483 bits_pushed = pushReg (i, bits_pushed);
3489 /* this function has a function call. We cannot
3490 determine register usage so we will have to push the
3492 saveRBank (0, ic, FALSE);
3493 if (options.parms_in_bank1) {
3494 for (i=0; i < 8 ; i++ ) {
3495 emitcode ("push","%s",rb1regs[i]);
3502 /* This ISR uses a non-zero bank.
3504 * We assume that the bank is available for our
3507 * However, if this ISR calls a function which uses some
3508 * other bank, we must save that bank entirely.
3510 unsigned long banksToSave = 0;
3512 if (IFFUNC_HASFCALL(sym->type))
3515 #define MAX_REGISTER_BANKS 4
3520 for (i = ic; i; i = i->next)
3522 if (i->op == ENDFUNCTION)
3524 /* we got to the end OK. */
3532 dtype = operandType (IC_LEFT(i));
3534 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3536 /* Mark this bank for saving. */
3537 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3539 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3543 banksToSave |= (1 << FUNC_REGBANK(dtype));
3546 /* And note that we don't need to do it in
3554 /* This is a mess; we have no idea what
3555 * register bank the called function might
3558 * The only thing I can think of to do is
3559 * throw a warning and hope.
3561 werror(W_FUNCPTR_IN_USING_ISR);
3565 if (banksToSave && options.useXstack)
3567 /* Since we aren't passing it an ic,
3568 * saveRBank will assume r0 is available to abuse.
3570 * So switch to our (trashable) bank now, so
3571 * the caller's R0 isn't trashed.
3573 emitcode ("push", "psw");
3574 emitcode ("mov", "psw,#!constbyte",
3575 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3579 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3581 if (banksToSave & (1 << ix))
3583 saveRBank(ix, NULL, FALSE);
3587 // TODO: this needs a closer look
3588 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3593 /* if callee-save to be used for this function
3594 then save the registers being used in this function */
3595 if (IFFUNC_CALLEESAVES(sym->type))
3599 /* if any registers used */
3602 bool bits_pushed = FALSE;
3603 /* save the registers used */
3604 for (i = 0; i < sym->regsUsed->size; i++)
3606 if (bitVectBitValue (sym->regsUsed, i))
3608 bits_pushed = pushReg (i, bits_pushed);
3616 /* set the register bank to the desired value */
3617 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3620 emitcode ("push", "psw");
3621 emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3625 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3626 if (options.stack10bit) {
3627 emitcode ("push","_bpx");
3628 emitcode ("push","_bpx+1");
3629 emitcode ("mov","_bpx,%s",spname);
3630 emitcode ("mov","_bpx+1,esp");
3631 adjustEsp("_bpx+1");
3633 if (options.useXstack)
3635 emitcode ("mov", "r0,%s", spname);
3636 emitcode ("mov", "a,_bp");
3637 emitcode ("movx", "@r0,a");
3638 emitcode ("inc", "%s", spname);
3640 /* set up the stack */
3641 emitcode ("push", "_bp"); /* save the callers stack */
3643 emitcode ("mov", "_bp,%s", spname);
3647 /* adjust the stack for the function */
3650 if (options.stack10bit) {
3651 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
3652 assert (sym->recvSize <= 4);
3653 if (sym->stack <= 8) {
3654 while (i--) emitcode ("push","acc");
3657 emitcode ("mov","a,sp");
3658 emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3659 emitcode ("mov","sp,a");
3660 emitcode ("mov","a,esp");
3662 emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3663 emitcode ("mov","esp,a");
3668 werror (W_STACK_OVERFLOW, sym->name);
3670 if (i > 3 && sym->recvSize < 4) {
3672 emitcode ("mov", "a,sp");
3673 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3674 emitcode ("mov", "sp,a");
3678 emitcode ("inc", "sp");
3685 emitcode ("mov", "a,_spx");
3686 emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3687 emitcode ("mov", "_spx,a");
3690 /* if critical function then turn interrupts off */
3691 if (IFFUNC_ISCRITICAL (ftype))
3693 symbol *tlbl = newiTempLabel (NULL);
3694 emitcode ("setb", "c");
3695 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3696 emitcode ("clr", "c");
3698 emitcode ("push", "psw"); /* save old ea via c in psw */
3702 /*-----------------------------------------------------------------*/
3703 /* genEndFunction - generates epilogue for functions */
3704 /*-----------------------------------------------------------------*/
3706 genEndFunction (iCode * ic)
3708 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3709 lineNode *lnp = lineCurr;
3711 bitVect *regsUsedPrologue;
3712 bitVect *regsUnneeded;
3715 D (emitcode (";", "genEndFunction"));
3717 _G.currentFunc = NULL;
3718 if (IFFUNC_ISNAKED(sym->type))
3720 emitcode(";", "naked function: no epilogue.");
3721 if (options.debug && currFunc)
3722 debugFile->writeEndFunction (currFunc, ic, 0);
3726 if (IFFUNC_ISCRITICAL (sym->type))
3728 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3730 emitcode ("rlc", "a"); /* save c in a */
3731 emitcode ("pop", "psw"); /* restore ea via c in psw */
3732 emitcode ("mov", "ea,c");
3733 emitcode ("rrc", "a"); /* restore c from a */
3737 emitcode ("pop", "psw"); /* restore ea via c in psw */
3738 emitcode ("mov", "ea,c");
3742 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3743 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3745 if (options.stack10bit) {
3747 emitcode ("mov", "sp,_bpx", spname);
3748 emitcode ("mov", "esp,_bpx+1", spname);
3751 emitcode ("mov", "%s,_bp", spname);
3755 /* if use external stack but some variables were
3756 added to the local stack then decrement the
3758 if (options.useXstack && sym->stack) {
3759 emitcode ("mov", "a,sp");
3760 emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3761 emitcode ("mov", "sp,a");
3765 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3766 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3768 if (options.useXstack) {
3769 emitcode ("mov", "r0,%s", spname);
3770 emitcode ("movx", "a,@r0");
3771 emitcode ("mov", "_bp,a");
3772 emitcode ("dec", "%s", spname);
3774 if (options.stack10bit) {
3775 emitcode ("pop", "_bpx+1");
3776 emitcode ("pop", "_bpx");
3778 emitcode ("pop", "_bp");
3783 /* restore the register bank */
3784 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3786 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3787 || !options.useXstack)
3789 /* Special case of ISR using non-zero bank with useXstack
3792 emitcode ("pop", "psw");
3796 if (IFFUNC_ISISR (sym->type))
3799 /* now we need to restore the registers */
3800 /* if this isr has no bank i.e. is going to
3801 run with bank 0 , then we need to save more
3803 if (!FUNC_REGBANK (sym->type))
3806 /* if this function does not call any other
3807 function then we can be economical and
3808 save only those registers that are used */
3809 if (!IFFUNC_HASFCALL(sym->type))
3811 /* if any registers used */
3814 bool bits_popped = FALSE;
3815 /* save the registers used */
3816 for (i = sym->regsUsed->size; i >= 0; i--)
3818 if (bitVectBitValue (sym->regsUsed, i))
3819 bits_popped = popReg (i, bits_popped);
3825 /* this function has a function call. We cannot
3826 determine register usage so we will have to pop the
3828 if (options.parms_in_bank1) {
3829 for (i = 7 ; i >= 0 ; i-- ) {
3830 emitcode ("pop","%s",rb1regs[i]);
3833 unsaveRBank (0, ic, FALSE);
3838 /* This ISR uses a non-zero bank.
3840 * Restore any register banks saved by genFunction
3843 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3846 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3848 if (savedBanks & (1 << ix))
3850 unsaveRBank(ix, NULL, FALSE);
3854 if (options.useXstack)
3856 /* Restore bank AFTER calling unsaveRBank,
3857 * since it can trash r0.
3859 emitcode ("pop", "psw");
3863 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3865 if (options.stack10bit)
3867 emitcode ("pop", DP2_RESULT_REG);
3868 emitcode ("pop", "dpx1");
3869 emitcode ("pop", "dph1");
3870 emitcode ("pop", "dpl1");
3872 emitcode ("pop", "dps");
3873 emitcode ("pop", "dpx");
3875 if (!inExcludeList ("dph"))
3876 emitcode ("pop", "dph");
3877 if (!inExcludeList ("dpl"))
3878 emitcode ("pop", "dpl");
3879 if (!inExcludeList ("b"))
3880 emitcode ("pop", "b");
3881 if (!inExcludeList ("acc"))
3882 emitcode ("pop", "acc");
3884 /* if debug then send end of function */
3885 if (options.debug && currFunc)
3887 debugFile->writeEndFunction (currFunc, ic, 1);
3890 emitcode ("reti", "");
3894 if (IFFUNC_CALLEESAVES(sym->type))
3898 /* if any registers used */
3901 /* save the registers used */
3902 for (i = sym->regsUsed->size; i >= 0; i--)
3904 if (bitVectBitValue (sym->regsUsed, i))
3905 emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
3910 /* if debug then send end of function */
3911 if (options.debug && currFunc)
3913 debugFile->writeEndFunction (currFunc, ic, 1);
3916 emitcode ("ret", "");
3919 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3922 /* If this was an interrupt handler using bank 0 that called another */
3923 /* function, then all registers must be saved; nothing to optimized. */
3924 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3925 && !FUNC_REGBANK(sym->type))
3928 /* There are no push/pops to optimize if not callee-saves or ISR */
3929 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3932 /* If there were stack parameters, we cannot optimize without also */
3933 /* fixing all of the stack offsets; this is too dificult to consider. */
3934 if (FUNC_HASSTACKPARM(sym->type))
3937 /* Compute the registers actually used */
3938 regsUsed = newBitVect (ds390_nRegs);
3939 regsUsedPrologue = newBitVect (ds390_nRegs);
3942 if (lnp->ic && lnp->ic->op == FUNCTION)
3943 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3945 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3947 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3948 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3955 if (bitVectBitValue (regsUsedPrologue, DPS_IDX)
3956 && !bitVectBitValue (regsUsed, DPS_IDX))
3958 bitVectUnSetBit (regsUsedPrologue, DPS_IDX);
3961 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3962 && !bitVectBitValue (regsUsed, CND_IDX))
3964 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3965 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3966 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3967 bitVectUnSetBit (regsUsed, CND_IDX);
3970 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3972 /* If this was an interrupt handler that called another function */
3973 /* function, then assume working registers may be modified by it. */
3974 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3976 regsUsed = bitVectSetBit (regsUsed, AP_IDX);
3977 regsUsed = bitVectSetBit (regsUsed, DPX1_IDX);
3978 regsUsed = bitVectSetBit (regsUsed, DPL1_IDX);
3979 regsUsed = bitVectSetBit (regsUsed, DPH1_IDX);
3980 regsUsed = bitVectSetBit (regsUsed, DPX_IDX);
3981 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3982 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3983 regsUsed = bitVectSetBit (regsUsed, DPS_IDX);
3984 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3985 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3986 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3989 /* Remove the unneeded push/pops */
3990 regsUnneeded = newBitVect (ds390_nRegs);
3993 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3995 if (!strncmp(lnp->line, "push", 4))
3997 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3998 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4000 connectLine (lnp->prev, lnp->next);
4001 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4004 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
4006 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
4007 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4009 connectLine (lnp->prev, lnp->next);
4010 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4017 for (idx = 0; idx < regsUnneeded->size; idx++)
4018 if (bitVectBitValue (regsUnneeded, idx))
4019 emitcode (";", "eliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
4021 freeBitVect (regsUnneeded);
4022 freeBitVect (regsUsed);
4023 freeBitVect (regsUsedPrologue);
4026 /*-----------------------------------------------------------------*/
4027 /* genJavaNativeRet - generate code for return JavaNative */
4028 /*-----------------------------------------------------------------*/
4029 static void genJavaNativeRet(iCode *ic)
4033 aopOp (IC_LEFT (ic), ic, FALSE,
4034 AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
4035 size = AOP_SIZE (IC_LEFT (ic));
4039 /* it is assigned to GPR0-R3 then push them */
4040 if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
4041 aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
4042 for (i = 0 ; i < size ; i++ ) {
4043 emitcode ("push","%s",
4044 aopGet(IC_LEFT(ic),i,FALSE,TRUE,DP2_RESULT_REG));
4046 for (i = (size-1) ; i >= 0 ; i--) {
4047 emitcode ("pop","a%s",javaRet[i]);
4050 for (i = 0 ; i < size ; i++)
4051 emitcode ("mov","%s,%s",javaRet[i],
4052 aopGet(IC_LEFT(ic),i,FALSE,TRUE,DP2_RESULT_REG));
4054 for (i = size ; i < 4 ; i++ )
4055 emitcode ("mov","%s,#0",javaRet[i]);
4059 /*-----------------------------------------------------------------*/
4060 /* genRet - generate code for return statement */
4061 /*-----------------------------------------------------------------*/
4065 int size, offset = 0, pushed = 0;
4067 D (emitcode (";", "genRet"));
4069 /* if we have no return value then
4070 just generate the "ret" */
4074 /* if this is a JavaNative function then return
4075 value in different register */
4076 if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
4077 genJavaNativeRet(ic);
4080 /* we have something to return then
4081 move the return value into place */
4082 aopOp (IC_LEFT (ic), ic, FALSE,
4083 (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
4084 size = AOP_SIZE (IC_LEFT (ic));
4086 _startLazyDPSEvaluation ();
4088 if (IS_BIT(_G.currentFunc->etype))
4090 movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4097 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
4099 l = aopGet (IC_LEFT (ic), offset++,
4101 emitcode ("push", "%s", l);
4106 /* Since A is the last element of fReturn,
4107 * it is OK to clobber it in the aopGet.
4109 l = aopGet (IC_LEFT (ic), offset,
4110 FALSE, FALSE, NULL);
4111 if (strcmp (fReturn[offset], l))
4112 emitcode ("mov", "%s,%s", fReturn[offset++], l);
4115 _endLazyDPSEvaluation ();
4120 if (strcmp (fReturn[pushed], "a"))
4121 emitcode ("pop", fReturn[pushed]);
4123 emitcode ("pop", "acc");
4125 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
4128 /* generate a jump to the return label
4129 if the next is not the return statement */
4130 if (!(ic->next && ic->next->op == LABEL &&
4131 IC_LABEL (ic->next) == returnLabel))
4133 emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
4137 /*-----------------------------------------------------------------*/
4138 /* genLabel - generates a label */
4139 /*-----------------------------------------------------------------*/
4141 genLabel (iCode * ic)
4143 /* special case never generate */
4144 if (IC_LABEL (ic) == entryLabel)
4147 D (emitcode (";", "genLabel"));
4149 emitLabel (IC_LABEL (ic));
4152 /*-----------------------------------------------------------------*/
4153 /* genGoto - generates a ljmp */
4154 /*-----------------------------------------------------------------*/
4156 genGoto (iCode * ic)
4158 D (emitcode (";", "genGoto"));
4160 emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
4163 /*-----------------------------------------------------------------*/
4164 /* findLabelBackwards: walks back through the iCode chain looking */
4165 /* for the given label. Returns number of iCode instructions */
4166 /* between that label and given ic. */
4167 /* Returns zero if label not found. */
4168 /*-----------------------------------------------------------------*/
4170 findLabelBackwards (iCode * ic, int key)
4179 /* If we have any pushes or pops, we cannot predict the distance.
4180 I don't like this at all, this should be dealt with in the
4182 if (ic->op == IPUSH || ic->op == IPOP) {
4186 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4188 /* printf("findLabelBackwards = %d\n", count); */
4196 /*-----------------------------------------------------------------*/
4197 /* genPlusIncr :- does addition with increment if possible */
4198 /*-----------------------------------------------------------------*/
4200 genPlusIncr (iCode * ic)
4202 unsigned int icount;
4203 unsigned int size = getDataSize (IC_RESULT (ic));
4205 /* will try to generate an increment */
4206 /* if the right side is not a literal
4208 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4211 /* if the literal value of the right hand side
4212 is greater than 4 then it is not worth it */
4213 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4216 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4217 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4219 emitcode("inc","%s",aopGet(IC_RESULT(ic),0,FALSE,FALSE,NULL));
4223 /* if increment 16 bits in register */
4225 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4226 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4227 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4236 /* If the next instruction is a goto and the goto target
4237 * is <= 5 instructions previous to this, we can generate
4238 * jumps straight to that target.
4240 if (ic->next && ic->next->op == GOTO
4241 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4244 D (emitcode (";", "tail increment optimized (range %d)", labelRange));
4245 tlbl = IC_LABEL (ic->next);
4250 tlbl = newiTempLabel (NULL);
4253 l = aopGet (IC_RESULT (ic), LSB, FALSE, FALSE, NULL);
4254 emitcode ("inc", "%s", l);
4256 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4257 IS_AOP_PREG (IC_RESULT (ic)))
4259 emitcode ("cjne", "%s,%s,!tlabel", l, zero, tlbl->key + 100);
4263 emitcode ("clr", "a");
4264 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4267 l = aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE, NULL);
4268 emitcode ("inc", "%s", l);
4271 if (!strcmp(l, "acc"))
4273 emitcode("jnz", "!tlabel", tlbl->key + 100);
4275 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4276 IS_AOP_PREG (IC_RESULT (ic)))
4278 emitcode ("cjne", "%s,%s,!tlabel", l, zero, tlbl->key + 100);
4282 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4285 l = aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE, NULL);
4286 emitcode ("inc", "%s", l);
4290 if (!strcmp(l, "acc"))
4292 emitcode("jnz", "!tlabel", tlbl->key + 100);
4294 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4295 IS_AOP_PREG (IC_RESULT (ic)))
4297 emitcode ("cjne", "%s,%s,!tlabel", l, zero, tlbl->key + 100);
4301 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4304 l = aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE, NULL);
4305 emitcode ("inc", "%s", l);
4315 if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
4316 !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 &&
4317 options.model == MODEL_FLAT24 )
4319 if (IC_RESULT(ic)->isGptr)
4321 emitcode ("mov", "b,%s", aopGet(IC_LEFT (ic), 3, FALSE, FALSE, NULL));
4325 emitcode ("mov", "dpx,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE, NULL));
4327 emitcode ("mov", "dph,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE, NULL));
4329 emitcode ("mov", "dpl,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4333 emitcode ("inc", "dptr");
4337 if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
4338 AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
4340 emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
4342 emitcode ("inc", "dptr");
4343 emitcode ("mov", "dps,#0");
4347 /* if the sizes are greater than 1 then we cannot */
4348 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4349 AOP_SIZE (IC_LEFT (ic)) > 1)
4352 /* we can if the aops of the left & result match or
4353 if they are in registers and the registers are the
4356 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4357 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4358 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4362 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4363 emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
4364 aopPut (IC_RESULT (ic), "a", 0);
4368 _startLazyDPSEvaluation ();
4371 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4373 _endLazyDPSEvaluation ();
4382 /*-----------------------------------------------------------------*/
4383 /* outBitAcc - output a bit in acc */
4384 /*-----------------------------------------------------------------*/
4386 outBitAcc (operand * result)
4388 symbol *tlbl = newiTempLabel (NULL);
4389 /* if the result is a bit */
4390 if (AOP_TYPE (result) == AOP_CRY)
4392 aopPut (result, "a", 0);
4396 emitcode ("jz", "!tlabel", tlbl->key + 100);
4397 emitcode ("mov", "a,%s", one);
4403 /*-----------------------------------------------------------------*/
4404 /* genPlusBits - generates code for addition of two bits */
4405 /*-----------------------------------------------------------------*/
4407 genPlusBits (iCode * ic)
4409 D (emitcode (";", "genPlusBits"));
4411 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4413 symbol *lbl = newiTempLabel (NULL);
4414 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4415 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4416 emitcode ("cpl", "c");
4418 outBitC (IC_RESULT (ic));
4422 emitcode ("clr", "a");
4423 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4424 emitcode ("rlc", "a");
4425 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4426 emitcode ("addc", "a,%s", zero);
4427 outAcc (IC_RESULT (ic));
4432 adjustArithmeticResult (iCode * ic)
4434 if (opIsGptr (IC_RESULT (ic)) &&
4435 opIsGptr (IC_LEFT (ic)) &&
4436 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4438 aopPut (IC_RESULT (ic),
4439 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE, NULL),
4443 if (opIsGptr (IC_RESULT (ic)) &&
4444 opIsGptr (IC_RIGHT (ic)) &&
4445 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4447 aopPut (IC_RESULT (ic),
4448 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE, NULL),
4452 if (opIsGptr (IC_RESULT (ic)) &&
4453 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4454 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4455 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4456 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4459 SNPRINTF (buffer, sizeof(buffer),
4460 "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4461 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4465 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
4466 // generates the result if possible. If result is generated, returns TRUE; otherwise
4467 // returns false and caller must deal with fact that result isn't aopOp'd.
4468 bool aopOp3(iCode * ic)
4470 bool dp1InUse, dp2InUse;
4473 // First, generate the right opcode. DPTR may be used if neither left nor result are
4476 // D (emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
4477 // AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
4478 // AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
4479 // AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
4481 // D (emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
4482 // AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
4483 // AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
4484 // AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
4487 // Right uses DPTR unless left or result is an AOP_STR; however,
4488 // if right is an AOP_STR, it must use DPTR regardless.
4489 if ((AOP_IS_STR (IC_LEFT (ic)) || AOP_IS_STR (IC_RESULT (ic)))
4490 && !AOP_IS_STR (IC_RIGHT (ic)))
4499 aopOp (IC_RIGHT(ic), ic, FALSE, useDp2);
4501 // if the right used DPTR, left MUST use DPTR2.
4502 // if the right used DPTR2, left MUST use DPTR.
4503 // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
4504 // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
4505 // enabling us to assign DPTR to result.
4507 if (AOP_USESDPTR (IC_RIGHT (ic)))
4511 else if (AOP_USESDPTR2 (IC_RIGHT (ic)))
4517 if (AOP_IS_STR (IC_RESULT (ic)) && !AOP_IS_STR (IC_LEFT (ic)))
4527 aopOp (IC_LEFT (ic), ic, FALSE, useDp2);
4530 // We've op'd the left & right. So, if left or right are the same operand as result,
4531 // we know aopOp will succeed, and we can just do it & bail.
4532 if (isOperandEqual (IC_LEFT (ic), IC_RESULT (ic)))
4534 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4537 if (isOperandEqual (IC_RIGHT (ic), IC_RESULT (ic)))
4539 // D (emitcode(";", "aopOp3: (left | right) & result equal"));
4540 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4544 // Operands may be equivalent (but not equal) if they share a spill location. If
4545 // so, use the same DPTR or DPTR2.
4546 if (operandsEqu (IC_LEFT (ic), IC_RESULT (ic)))
4548 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4551 if (operandsEqu (IC_RIGHT (ic), IC_RESULT (ic)))
4553 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4557 // Note which dptrs are currently in use.
4558 dp1InUse = AOP_USESDPTR (IC_LEFT (ic)) || AOP_USESDPTR (IC_RIGHT (ic));
4559 dp2InUse = AOP_USESDPTR2 (IC_LEFT (ic)) || AOP_USESDPTR2 (IC_RIGHT (ic));
4561 // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot
4563 if (dp1InUse && AOP_IS_STR (IC_RESULT (ic)))
4568 // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
4569 if (dp2InUse && AOP_IS_DPTRn (IC_RESULT (ic)))
4574 // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck
4575 if (dp1InUse && dp2InUse && isOperandInFarSpace (IC_RESULT (ic)))
4580 aopOp (IC_RESULT (ic), ic, TRUE, dp1InUse);
4582 // Some sanity checking...
4583 if (dp1InUse && AOP_USESDPTR (IC_RESULT (ic)))
4586 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
4587 __FILE__, __LINE__, ic->filename, ic->lineno);
4588 emitcode(";", ">>> unexpected DPTR here.");
4591 if (dp2InUse && AOP_USESDPTR2 (IC_RESULT (ic)))
4594 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
4595 __FILE__, __LINE__, ic->filename, ic->lineno);
4596 emitcode(";", ">>> unexpected DPTR2 here.");
4602 // Macro to aopOp all three operands of an ic. If this cannot be done,
4603 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
4604 // will be set TRUE. The caller must then handle the case specially, noting
4605 // that the IC_RESULT operand is not aopOp'd.
4607 #define AOP_OP_3_NOFATAL(ic, rc) \
4608 do { rc = !aopOp3(ic); } while (0)
4610 // aopOp the left & right operands of an ic.
4611 #define AOP_OP_2(ic) \
4612 aopOp (IC_RIGHT (ic), ic, FALSE, AOP_IS_STR (IC_LEFT (ic))); \
4613 aopOp (IC_LEFT (ic), ic, FALSE, AOP_USESDPTR (IC_RIGHT (ic)));
4615 // convienience macro.
4616 #define AOP_SET_LOCALS(ic) \
4617 left = IC_LEFT(ic); \
4618 right = IC_RIGHT(ic); \
4619 result = IC_RESULT(ic);
4622 // Given an integer value of pushedSize bytes on the stack,
4623 // adjust it to be resultSize bytes, either by discarding
4624 // the most significant bytes or by zero-padding.
4626 // On exit from this macro, pushedSize will have been adjusted to
4627 // equal resultSize, and ACC may be trashed.
4628 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
4629 /* If the pushed data is bigger than the result, \
4630 * simply discard unused bytes. Icky, but works. \
4632 while (pushedSize > resultSize) \
4634 D (emitcode (";", "discarding unused result byte.")); \
4635 emitcode ("pop", "acc"); \
4638 if (pushedSize < resultSize) \
4640 emitcode ("clr", "a"); \
4641 /* Conversly, we haven't pushed enough here. \
4642 * just zero-pad, and all is well. \
4644 while (pushedSize < resultSize) \
4646 emitcode("push", "acc"); \
4650 assert(pushedSize == resultSize);
4652 /*-----------------------------------------------------------------*/
4653 /* genPlus - generates code for addition */
4654 /*-----------------------------------------------------------------*/
4656 genPlus (iCode * ic)
4658 int size, offset = 0;
4661 bool swappedLR = FALSE;
4663 D (emitcode (";", "genPlus"));
4665 /* special cases :- */
4666 if ( AOP_IS_STR (IC_LEFT (ic)) &&
4667 isOperandLiteral (IC_RIGHT (ic)) && OP_SYMBOL (IC_RESULT (ic))->ruonly) {
4668 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
4669 size = (int)floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4671 while (size--) emitcode ("inc","dptr");
4673 emitcode ("mov", "a,dpl");
4674 emitcode ("add", "a,#!constbyte", size & 0xff);
4675 emitcode ("mov", "dpl,a");
4676 emitcode ("mov", "a,dph");
4677 emitcode ("addc", "a,#!constbyte", (size >> 8) & 0xff);
4678 emitcode ("mov", "dph,a");
4679 emitcode ("mov", "a,dpx");
4680 emitcode ("addc", "a,#!constbyte", (size >> 16) & 0xff);
4681 emitcode ("mov", "dpx,a");
4683 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4686 if ( IS_SYMOP (IC_LEFT (ic)) &&
4687 OP_SYMBOL (IC_LEFT (ic))->remat &&
4688 isOperandInFarSpace (IC_RIGHT (ic))) {
4689 operand *op = IC_RIGHT(ic);
4690 IC_RIGHT(ic) = IC_LEFT(ic);
4694 AOP_OP_3_NOFATAL (ic, pushResult);
4698 D (emitcode (";", "genPlus: must push result: 3 ops in far space"));
4703 /* if literal, literal on the right or
4704 if left requires ACC or right is already
4706 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4707 ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic)))) ||
4708 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4710 operand *t = IC_RIGHT (ic);
4711 IC_RIGHT (ic) = IC_LEFT (ic);
4714 D (emitcode (";", "Swapped plus args."));
4717 /* if both left & right are in bit
4719 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4720 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4726 /* if left in bit space & right literal */
4727 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4728 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4730 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4731 /* if result in bit space */
4732 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4734 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4735 emitcode ("cpl", "c");
4736 outBitC (IC_RESULT (ic));
4740 size = getDataSize (IC_RESULT (ic));
4741 _startLazyDPSEvaluation ();
4744 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4745 emitcode ("addc", "a,%s", zero);
4746 aopPut (IC_RESULT (ic), "a", offset++);
4748 _endLazyDPSEvaluation ();
4753 /* if I can do an increment instead
4754 of add then GOOD for ME */
4755 if (genPlusIncr (ic) == TRUE)
4757 D (emitcode (";", "did genPlusIncr"));
4762 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4764 _startLazyDPSEvaluation ();
4767 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4769 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
4771 emitcode ("add", "a,%s",
4772 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4774 emitcode ("addc", "a,%s",
4775 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4779 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4781 /* right is going to use ACC or we would have taken the
4784 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4786 D(emitcode(";", "+ AOP_ACC special case."););
4787 emitcode("xch", "a, %s", DP2_RESULT_REG);
4789 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4792 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4795 emitcode("add", "a, %s", DP2_RESULT_REG);
4799 emitcode ("add", "a,%s",
4800 aopGet (IC_LEFT(ic), offset, FALSE, FALSE,
4806 emitcode ("addc", "a,%s",
4807 aopGet (IC_LEFT (ic), offset, FALSE, FALSE,
4813 aopPut (IC_RESULT (ic), "a", offset);
4817 emitcode ("push", "acc");
4821 _endLazyDPSEvaluation ();
4825 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4827 size = getDataSize (IC_LEFT (ic));
4828 rSize = getDataSize (IC_RESULT (ic));
4830 ADJUST_PUSHED_RESULT(size, rSize);
4832 _startLazyDPSEvaluation ();
4835 emitcode ("pop", "acc");
4836 aopPut (IC_RESULT (ic), "a", size);
4838 _endLazyDPSEvaluation ();
4841 adjustArithmeticResult (ic);
4844 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4847 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4848 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4852 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4853 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4857 /*-----------------------------------------------------------------*/
4858 /* genMinusDec :- does subtraction with decrement if possible */
4859 /*-----------------------------------------------------------------*/
4861 genMinusDec (iCode * ic)
4863 unsigned int icount;
4864 unsigned int size = getDataSize (IC_RESULT (ic));
4866 /* will try to generate an increment */
4867 /* if the right side is not a literal
4869 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4872 /* if the literal value of the right hand side
4873 is greater than 4 then it is not worth it */
4874 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4877 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4878 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4880 emitcode("dec","%s",aopGet(IC_RESULT(ic),0,FALSE,FALSE,NULL));
4884 /* if decrement 16 bits in register */
4885 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4886 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4887 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4896 /* If the next instruction is a goto and the goto target
4897 * is <= 5 instructions previous to this, we can generate
4898 * jumps straight to that target.
4900 if (ic->next && ic->next->op == GOTO
4901 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4904 D (emitcode (";", "tail decrement optimized (range %d)", labelRange));
4905 tlbl = IC_LABEL (ic->next);
4910 tlbl = newiTempLabel (NULL);
4914 l = aopGet (IC_RESULT (ic), LSB, FALSE, FALSE, NULL);
4915 emitcode ("dec", "%s", l);
4917 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4918 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4919 IS_AOP_PREG (IC_RESULT (ic)))
4921 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4925 emitcode ("mov", "a,#!constbyte",0xff);
4926 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4928 l = aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE, NULL);
4929 emitcode ("dec", "%s", l);
4932 if (!strcmp(l, "acc"))
4934 emitcode("jnz", "!tlabel", tlbl->key + 100);
4936 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4937 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4938 IS_AOP_PREG (IC_RESULT (ic)))
4940 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4944 emitcode ("mov", "a,#!constbyte",0xff);
4945 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4947 l = aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE, NULL);
4948 emitcode ("dec", "%s", l);
4952 if (!strcmp(l, "acc"))
4954 emitcode("jnz", "!tlabel", tlbl->key + 100);
4956 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4957 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4958 IS_AOP_PREG (IC_RESULT (ic)))
4960 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4964 emitcode ("mov", "a,#!constbyte",0xff);
4965 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4967 l = aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE, NULL);
4968 emitcode ("dec", "%s", l);
4977 /* if the sizes are greater than 1 then we cannot */
4978 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4979 AOP_SIZE (IC_LEFT (ic)) > 1)
4982 /* we can if the aops of the left & result match or
4983 if they are in registers and the registers are the
4986 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4987 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4988 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4992 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4994 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL));
4999 l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL);
5002 _startLazyDPSEvaluation ();
5005 emitcode ("dec", "%s", l);
5007 _endLazyDPSEvaluation ();
5009 if (AOP_NEEDSACC (IC_RESULT (ic)))
5010 aopPut (IC_RESULT (ic), "a", 0);
5018 /*-----------------------------------------------------------------*/
5019 /* addSign - complete with sign */
5020 /*-----------------------------------------------------------------*/
5022 addSign (operand * result, int offset, int sign)
5024 int size = (getDataSize (result) - offset);
5027 _startLazyDPSEvaluation();
5030 emitcode ("rlc", "a");
5031 emitcode ("subb", "a,acc");
5034 aopPut (result, "a", offset++);
5041 aopPut (result, zero, offset++);
5044 _endLazyDPSEvaluation();
5048 /*-----------------------------------------------------------------*/
5049 /* genMinusBits - generates code for subtraction of two bits */
5050 /*-----------------------------------------------------------------*/
5052 genMinusBits (iCode * ic)
5054 symbol *lbl = newiTempLabel (NULL);
5056 D (emitcode (";", "genMinusBits"));
5058 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
5060 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
5061 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
5062 emitcode ("cpl", "c");
5064 outBitC (IC_RESULT (ic));
5068 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
5069 emitcode ("subb", "a,acc");
5070 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
5071 emitcode ("inc", "a");
5073 aopPut (IC_RESULT (ic), "a", 0);
5074 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
5078 /*-----------------------------------------------------------------*/
5079 /* genMinus - generates code for subtraction */
5080 /*-----------------------------------------------------------------*/
5082 genMinus (iCode * ic)
5084 int size, offset = 0;
5089 D (emitcode (";", "genMinus"));
5091 AOP_OP_3_NOFATAL(ic, pushResult);
5095 /* special cases :- */
5096 /* if both left & right are in bit space */
5097 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
5098 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
5104 /* if I can do an decrement instead
5105 of subtract then GOOD for ME */
5106 if (genMinusDec (ic) == TRUE)
5111 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
5113 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
5119 lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5124 /* if literal, add a,#-lit, else normal subb */
5125 _startLazyDPSEvaluation ();
5127 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
5128 if (AOP_USESDPTR(IC_RIGHT(ic))) {
5129 emitcode ("mov","b,%s",
5130 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
5131 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
5132 emitcode ("subb","a,b");
5134 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
5135 emitcode ("subb", "a,%s",
5136 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE,
5140 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
5141 /* first add without previous c */
5143 if (!size && lit==-1) {
5144 emitcode ("dec", "a");
5146 emitcode ("add", "a,#!constbyte",
5147 (unsigned int) (lit & 0x0FFL));
5150 emitcode ("addc", "a,#!constbyte",
5151 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5156 emitcode ("push", "acc");
5158 aopPut (IC_RESULT (ic), "a", offset);
5162 _endLazyDPSEvaluation ();
5166 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
5168 size = getDataSize (IC_LEFT (ic));
5169 rSize = getDataSize (IC_RESULT (ic));
5171 ADJUST_PUSHED_RESULT(size, rSize);
5173 _startLazyDPSEvaluation ();
5176 emitcode ("pop", "acc");
5177 aopPut (IC_RESULT (ic), "a", size);
5179 _endLazyDPSEvaluation ();
5182 adjustArithmeticResult (ic);
5185 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5186 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5187 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5191 /*-----------------------------------------------------------------*/
5192 /* genMultbits :- multiplication of bits */
5193 /*-----------------------------------------------------------------*/
5195 genMultbits (operand * left,
5200 D (emitcode (";", "genMultbits"));
5202 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5203 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5204 aopOp(result, ic, TRUE, FALSE);
5208 /*-----------------------------------------------------------------*/
5209 /* genMultOneByte : 8*8=8/16 bit multiplication */
5210 /*-----------------------------------------------------------------*/
5212 genMultOneByte (operand * left,
5219 bool runtimeSign, compiletimeSign;
5220 bool lUnsigned, rUnsigned, pushedB;
5222 /* (if two literals: the value is computed before) */
5223 /* if one literal, literal on the right */
5224 if (AOP_TYPE (left) == AOP_LIT)
5229 /* emitcode (";", "swapped left and right"); */
5231 /* if no literal, unsigned on the right: shorter code */
5232 if ( AOP_TYPE (right) != AOP_LIT
5233 && SPEC_USIGN (getSpec (operandType (left))))
5240 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5241 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5245 if ((lUnsigned && rUnsigned)
5246 /* sorry, I don't know how to get size
5247 without calling aopOp (result,...);
5248 see Feature Request */
5249 /* || size == 1 */ ) /* no, this is not a bug; with a 1 byte result there's
5250 no need to take care about the signedness! */
5252 /* just an unsigned 8 * 8 = 8 multiply
5254 /* emitcode (";","unsigned"); */
5255 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
5256 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
5257 emitcode ("mul", "ab");
5260 aopOp (result, ic, TRUE, FALSE);
5261 size = AOP_SIZE (result);
5263 if (size < 1 || size > 2)
5265 /* this should never happen */
5266 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
5267 size, __FILE__, lineno);
5271 aopPut (result, "a", 0);
5274 aopPut (result, "b", 1);
5280 /* we have to do a signed multiply */
5281 /* emitcode (";", "signed"); */
5283 /* now sign adjust for both left & right */
5285 /* let's see what's needed: */
5286 /* apply negative sign during runtime */
5287 runtimeSign = FALSE;
5288 /* negative sign from literals */
5289 compiletimeSign = FALSE;
5293 if (AOP_TYPE(left) == AOP_LIT)
5295 /* signed literal */
5296 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5298 compiletimeSign = TRUE;
5301 /* signed but not literal */
5307 if (AOP_TYPE(right) == AOP_LIT)
5309 /* signed literal */
5310 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5312 compiletimeSign ^= TRUE;
5315 /* signed but not literal */
5319 /* initialize F0, which stores the runtime sign */
5322 if (compiletimeSign)
5323 emitcode ("setb", "F0"); /* set sign flag */
5325 emitcode ("clr", "F0"); /* reset sign flag */
5328 /* save the signs of the operands */
5329 if (AOP_TYPE(right) == AOP_LIT)
5331 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5333 if (!rUnsigned && val < 0)
5334 emitcode ("mov", "b,#!constbyte", -val);
5336 emitcode ("mov", "b,#!constbyte", (unsigned char) val);
5338 else /* ! literal */
5340 if (rUnsigned) /* emitcode (";", "signed"); */
5341 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
5344 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
5345 lbl = newiTempLabel (NULL);
5346 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5347 emitcode ("cpl", "F0"); /* complement sign flag */
5348 emitcode ("cpl", "a"); /* 2's complement */
5349 emitcode ("inc", "a");
5351 emitcode ("mov", "b,a");
5355 if (AOP_TYPE(left) == AOP_LIT)
5357 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5359 if (!lUnsigned && val < 0)
5360 emitcode ("mov", "a,#!constbyte", -val);
5362 emitcode ("mov", "a,#!constbyte", (unsigned char) val);
5364 else /* ! literal */
5366 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
5368 if (!lUnsigned) /* emitcode (";", "signed"); */
5370 lbl = newiTempLabel (NULL);
5371 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5372 emitcode ("cpl", "F0"); /* complement sign flag */
5373 emitcode ("cpl", "a"); /* 2's complement */
5374 emitcode ("inc", "a");
5379 /* now the multiplication */
5380 emitcode ("mul", "ab");
5382 aopOp(result, ic, TRUE, FALSE);
5383 size = AOP_SIZE (result);
5385 if (size < 1 || size > 2)
5387 /* this should never happen */
5388 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
5389 size, __FILE__, lineno);
5393 if (runtimeSign || compiletimeSign)
5395 lbl = newiTempLabel (NULL);
5397 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5398 emitcode ("cpl", "a"); /* lsb 2's complement */
5400 emitcode ("inc", "a"); /* inc doesn't set carry flag */
5403 emitcode ("add", "a,#1"); /* this sets carry flag */
5404 emitcode ("xch", "a,b");
5405 emitcode ("cpl", "a"); /* msb 2's complement */
5406 emitcode ("addc", "a,#0");
5407 emitcode ("xch", "a,b");
5411 aopPut (result, "a", 0);
5414 aopPut (result, "b", 1);
5419 /*-----------------------------------------------------------------*/
5420 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
5421 /*-----------------------------------------------------------------*/
5422 static void genMultTwoByte (operand *left, operand *right,
5423 operand *result, iCode *ic)
5425 sym_link *retype = getSpec(operandType(right));
5426 sym_link *letype = getSpec(operandType(left));
5427 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5430 if (AOP_TYPE (left) == AOP_LIT) {
5435 /* save EA bit in F1 */
5436 lbl = newiTempLabel(NULL);
5437 emitcode ("setb","F1");
5438 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5439 emitcode ("clr","F1");
5442 /* load up MB with right */
5444 emitcode("clr","F0");
5445 if (AOP_TYPE(right) == AOP_LIT) {
5446 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5448 emitcode("setb","F0");
5451 emitcode ("mov","mb,#!constbyte",val & 0xff);
5452 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5454 lbl = newiTempLabel(NULL);
5455 emitcode ("mov","b,%s",aopGet(right,0,FALSE,FALSE,NULL));
5456 emitcode ("mov","a,%s",aopGet(right,1,FALSE,FALSE,NULL));
5457 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5458 emitcode ("xch", "a,b");
5459 emitcode ("cpl","a");
5460 emitcode ("add", "a,#1");
5461 emitcode ("xch", "a,b");
5462 emitcode ("cpl", "a"); // msb
5463 emitcode ("addc", "a,#0");
5464 emitcode ("setb","F0");
5466 emitcode ("mov","mb,b");
5467 emitcode ("mov","mb,a");
5470 emitcode ("mov","mb,%s",aopGet(right,0,FALSE,FALSE,NULL));
5471 emitcode ("mov","mb,%s",aopGet(right,1,FALSE,FALSE,NULL));
5473 /* load up MA with left */
5475 lbl = newiTempLabel(NULL);
5476 emitcode ("mov","b,%s",aopGet(left,0,FALSE,FALSE,NULL));
5477 emitcode ("mov","a,%s",aopGet(left,1,FALSE,FALSE,NULL));
5478 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5479 emitcode ("xch", "a,b");
5480 emitcode ("cpl","a");
5481 emitcode ("add", "a,#1");
5482 emitcode ("xch", "a,b");
5483 emitcode ("cpl", "a"); // msb
5484 emitcode ("addc","a,#0");
5485 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5486 emitcode ("setb","F0");
5488 emitcode ("mov","ma,b");
5489 emitcode ("mov","ma,a");
5491 emitcode ("mov","ma,%s",aopGet(left,0,FALSE,FALSE,NULL));
5492 emitcode ("mov","ma,%s",aopGet(left,1,FALSE,FALSE,NULL));
5494 /* wait for multiplication to finish */
5495 lbl = newiTempLabel(NULL);
5497 emitcode("mov","a,mcnt1");
5498 emitcode("anl","a,#!constbyte",0x80);
5499 emitcode("jnz","!tlabel",lbl->key+100);
5501 freeAsmop (left, NULL, ic, TRUE);
5502 freeAsmop (right, NULL, ic,TRUE);
5503 aopOp(result, ic, TRUE, FALSE);
5505 /* if unsigned then simple */
5507 emitcode ("mov","a,ma");
5508 if (AOP_SIZE(result) >= 4) aopPut(result,"a",3);
5509 emitcode ("mov","a,ma");
5510 if (AOP_SIZE(result) >= 3) aopPut(result,"a",2);
5511 aopPut(result,"ma",1);
5512 aopPut(result,"ma",0);
5514 emitcode("push","ma");
5515 emitcode("push","ma");
5516 emitcode("push","ma");
5518 /* negate result if needed */
5519 lbl = newiTempLabel(NULL);
5520 emitcode("jnb","F0,!tlabel",lbl->key+100);
5521 emitcode("cpl","a");
5522 emitcode("add","a,#1");
5524 if (AOP_TYPE(result) == AOP_ACC)
5526 D (emitcode(";", "ACC special case."));
5527 /* We know result is the only live aop, and
5528 * it's obviously not a DPTR2, so AP is available.
5530 emitcode("mov", "%s,acc", DP2_RESULT_REG);
5534 aopPut(result,"a",0);
5537 emitcode("pop","acc");
5538 lbl = newiTempLabel(NULL);
5539 emitcode("jnb","F0,!tlabel",lbl->key+100);
5540 emitcode("cpl","a");
5541 emitcode("addc","a,#0");
5543 aopPut(result,"a",1);
5544 emitcode("pop","acc");
5545 if (AOP_SIZE(result) >= 3) {
5546 lbl = newiTempLabel(NULL);
5547 emitcode("jnb","F0,!tlabel",lbl->key+100);
5548 emitcode("cpl","a");
5549 emitcode("addc","a,#0");
5551 aopPut(result,"a",2);
5553 emitcode("pop","acc");
5554 if (AOP_SIZE(result) >= 4) {
5555 lbl = newiTempLabel(NULL);
5556 emitcode("jnb","F0,!tlabel",lbl->key+100);
5557 emitcode("cpl","a");
5558 emitcode("addc","a,#0");
5560 aopPut(result,"a",3);
5562 if (AOP_TYPE(result) == AOP_ACC)
5564 /* We stashed the result away above. */
5565 emitcode("mov", "acc,%s", DP2_RESULT_REG);
5569 freeAsmop (result, NULL, ic, TRUE);
5571 /* restore EA bit in F1 */
5572 lbl = newiTempLabel(NULL);
5573 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5574 emitcode ("setb","EA");
5579 /*-----------------------------------------------------------------*/
5580 /* genMult - generates code for multiplication */
5581 /*-----------------------------------------------------------------*/
5583 genMult (iCode * ic)
5585 operand *left = IC_LEFT (ic);
5586 operand *right = IC_RIGHT (ic);
5587 operand *result = IC_RESULT (ic);
5589 D (emitcode (";", "genMult"));
5591 /* assign the asmops */
5594 /* special cases first */
5596 if (AOP_TYPE (left) == AOP_CRY &&
5597 AOP_TYPE (right) == AOP_CRY)
5599 genMultbits (left, right, result, ic);
5603 /* if both are of size == 1 */
5604 if (AOP_SIZE (left) == 1 &&
5605 AOP_SIZE (right) == 1)
5607 genMultOneByte (left, right, result, ic);
5611 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5612 /* use the ds390 ARITHMETIC accel UNIT */
5613 genMultTwoByte (left, right, result, ic);
5616 /* should have been converted to function call */
5620 freeAsmop (result, NULL, ic, TRUE);
5621 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5622 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5625 /*-----------------------------------------------------------------*/
5626 /* genDivbits :- division of bits */
5627 /*-----------------------------------------------------------------*/
5629 genDivbits (operand * left,
5637 D(emitcode (";", "genDivbits"));
5641 /* the result must be bit */
5642 LOAD_AB_FOR_DIV (left, right, l);
5643 emitcode ("div", "ab");
5644 emitcode ("rrc", "a");
5645 aopOp(result, ic, TRUE, FALSE);
5649 aopPut (result, "c", 0);
5652 /*-----------------------------------------------------------------*/
5653 /* genDivOneByte : 8 bit division */
5654 /*-----------------------------------------------------------------*/
5656 genDivOneByte (operand * left,
5661 bool lUnsigned, rUnsigned, pushedB;
5662 bool runtimeSign, compiletimeSign;
5667 D(emitcode (";", "genDivOneByte"));
5670 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5671 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5675 /* signed or unsigned */
5676 if (lUnsigned && rUnsigned)
5678 /* unsigned is easy */
5679 LOAD_AB_FOR_DIV (left, right, l);
5680 emitcode ("div", "ab");
5683 aopOp (result, ic, TRUE, FALSE);
5684 aopPut (result, "a", 0);
5687 size = AOP_SIZE (result) - 1;
5690 aopPut (result, zero, offset++);
5696 /* signed is a little bit more difficult */
5698 /* now sign adjust for both left & right */
5700 /* let's see what's needed: */
5701 /* apply negative sign during runtime */
5702 runtimeSign = FALSE;
5703 /* negative sign from literals */
5704 compiletimeSign = FALSE;
5708 if (AOP_TYPE(left) == AOP_LIT)
5710 /* signed literal */
5711 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5713 compiletimeSign = TRUE;
5716 /* signed but not literal */
5722 if (AOP_TYPE(right) == AOP_LIT)
5724 /* signed literal */
5725 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5727 compiletimeSign ^= TRUE;
5730 /* signed but not literal */
5734 /* initialize F0, which stores the runtime sign */
5737 if (compiletimeSign)
5738 emitcode ("setb", "F0"); /* set sign flag */
5740 emitcode ("clr", "F0"); /* reset sign flag */
5743 /* save the signs of the operands */
5744 if (AOP_TYPE(right) == AOP_LIT)
5746 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5748 if (!rUnsigned && val < 0)
5749 emitcode ("mov", "b,#0x%02x", -val);
5751 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5753 else /* ! literal */
5756 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
5759 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
5760 lbl = newiTempLabel (NULL);
5761 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5762 emitcode ("cpl", "F0"); /* complement sign flag */
5763 emitcode ("cpl", "a"); /* 2's complement */
5764 emitcode ("inc", "a");
5766 emitcode ("mov", "b,a");
5770 if (AOP_TYPE(left) == AOP_LIT)
5772 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5774 if (!lUnsigned && val < 0)
5775 emitcode ("mov", "a,#0x%02x", -val);
5777 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5779 else /* ! literal */
5781 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
5785 lbl = newiTempLabel (NULL);
5786 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5787 emitcode ("cpl", "F0"); /* complement sign flag */
5788 emitcode ("cpl", "a"); /* 2's complement */
5789 emitcode ("inc", "a");
5794 /* now the division */
5795 emitcode ("nop", "; workaround for DS80C390 div bug.");
5796 emitcode ("div", "ab");
5798 if (runtimeSign || compiletimeSign)
5800 lbl = newiTempLabel (NULL);
5802 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5803 emitcode ("cpl", "a"); /* lsb 2's complement */
5804 emitcode ("inc", "a");
5808 aopOp (result, ic, TRUE, FALSE);
5809 size = AOP_SIZE (result) - 1;
5813 /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
5814 then the result will be in b, a */
5815 emitcode ("mov", "b,a"); /* 1 */
5816 /* msb is 0x00 or 0xff depending on the sign */
5819 emitcode ("mov", "c,F0");
5820 emitcode ("subb", "a,acc");
5821 emitcode ("xch", "a,b"); /* 2 */
5823 aopPut (result, "b", offset++); /* write msb's */
5825 else /* compiletimeSign */
5827 aopPut (result, "#0xff", offset++); /* write msb's */
5829 aopPut (result, "a", 0); /* 3: write lsb */
5834 aopOp(result, ic, TRUE, FALSE);
5835 size = AOP_SIZE (result) - 1;
5837 aopPut (result, "a", 0);
5839 aopPut (result, zero, offset++);
5845 /*-----------------------------------------------------------------*/
5846 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
5847 /*-----------------------------------------------------------------*/
5848 static void genDivTwoByte (operand *left, operand *right,
5849 operand *result, iCode *ic)
5851 sym_link *retype = getSpec(operandType(right));
5852 sym_link *letype = getSpec(operandType(left));
5853 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5856 /* save EA bit in F1 */
5857 lbl = newiTempLabel(NULL);
5858 emitcode ("setb","F1");
5859 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5860 emitcode ("clr","F1");
5863 /* load up MA with left */
5865 emitcode("clr","F0");
5866 lbl = newiTempLabel(NULL);
5867 emitcode ("mov","b,%s",aopGet(left,0,FALSE,FALSE,NULL));
5868 emitcode ("mov","a,%s",aopGet(left,1,FALSE,FALSE,NULL));
5869 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5870 emitcode ("xch", "a,b");
5871 emitcode ("cpl","a");
5872 emitcode ("add", "a,#1");
5873 emitcode ("xch", "a,b");
5874 emitcode ("cpl", "a"); // msb
5875 emitcode ("addc","a,#0");
5876 emitcode ("setb","F0");
5878 emitcode ("mov","ma,b");
5879 emitcode ("mov","ma,a");
5881 emitcode ("mov","ma,%s",aopGet(left,0,FALSE,FALSE,NULL));
5882 emitcode ("mov","ma,%s",aopGet(left,1,FALSE,FALSE,NULL));
5885 /* load up MB with right */
5887 if (AOP_TYPE(right) == AOP_LIT) {
5888 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5890 lbl = newiTempLabel(NULL);
5891 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5892 emitcode("setb","F0");
5896 emitcode ("mov","mb,#!constbyte",val & 0xff);
5897 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5899 lbl = newiTempLabel(NULL);
5900 emitcode ("mov","b,%s",aopGet(right,0,FALSE,FALSE,NULL));
5901 emitcode ("mov","a,%s",aopGet(right,1,FALSE,FALSE,NULL));
5902 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5903 emitcode ("xch", "a,b");
5904 emitcode ("cpl","a");
5905 emitcode ("add", "a,#1");
5906 emitcode ("xch", "a,b");
5907 emitcode ("cpl", "a"); // msb
5908 emitcode ("addc", "a,#0");
5909 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5910 emitcode ("setb","F0");
5912 emitcode ("mov","mb,b");
5913 emitcode ("mov","mb,a");
5916 emitcode ("mov","mb,%s",aopGet(right,0,FALSE,FALSE,NULL));
5917 emitcode ("mov","mb,%s",aopGet(right,1,FALSE,FALSE,NULL));
5920 /* wait for multiplication to finish */
5921 lbl = newiTempLabel(NULL);
5923 emitcode("mov","a,mcnt1");
5924 emitcode("anl","a,#!constbyte",0x80);
5925 emitcode("jnz","!tlabel",lbl->key+100);
5927 freeAsmop (left, NULL, ic, TRUE);
5928 freeAsmop (right, NULL, ic,TRUE);
5929 aopOp(result, ic, TRUE, FALSE);
5931 /* if unsigned then simple */
5933 aopPut(result,"ma",1);
5934 aopPut(result,"ma",0);
5936 emitcode("push","ma");
5938 /* negate result if needed */
5939 lbl = newiTempLabel(NULL);
5940 emitcode("jnb","F0,!tlabel",lbl->key+100);
5941 emitcode("cpl","a");
5942 emitcode("add","a,#1");
5944 aopPut(result,"a",0);
5945 emitcode("pop","acc");
5946 lbl = newiTempLabel(NULL);
5947 emitcode("jnb","F0,!tlabel",lbl->key+100);
5948 emitcode("cpl","a");
5949 emitcode("addc","a,#0");
5951 aopPut(result,"a",1);
5953 freeAsmop (result, NULL, ic, TRUE);
5954 /* restore EA bit in F1 */
5955 lbl = newiTempLabel(NULL);
5956 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5957 emitcode ("setb","EA");
5962 /*-----------------------------------------------------------------*/
5963 /* genDiv - generates code for division */
5964 /*-----------------------------------------------------------------*/
5968 operand *left = IC_LEFT (ic);
5969 operand *right = IC_RIGHT (ic);
5970 operand *result = IC_RESULT (ic);
5972 D (emitcode (";", "genDiv"));
5974 /* assign the amsops */
5977 /* special cases first */
5979 if (AOP_TYPE (left) == AOP_CRY &&
5980 AOP_TYPE (right) == AOP_CRY)
5982 genDivbits (left, right, result, ic);
5986 /* if both are of size == 1 */
5987 if (AOP_SIZE (left) == 1 &&
5988 AOP_SIZE (right) == 1)
5990 genDivOneByte (left, right, result, ic);
5994 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5995 /* use the ds390 ARITHMETIC accel UNIT */
5996 genDivTwoByte (left, right, result, ic);
5999 /* should have been converted to function call */
6002 freeAsmop (result, NULL, ic, TRUE);
6003 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6004 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6007 /*-----------------------------------------------------------------*/
6008 /* genModbits :- modulus of bits */
6009 /*-----------------------------------------------------------------*/
6011 genModbits (operand * left,
6019 D (emitcode (";", "genModbits"));
6023 /* the result must be bit */
6024 LOAD_AB_FOR_DIV (left, right, l);
6025 emitcode ("div", "ab");
6026 emitcode ("mov", "a,b");
6027 emitcode ("rrc", "a");
6028 aopOp(result, ic, TRUE, FALSE);
6032 aopPut (result, "c", 0);
6035 /*-----------------------------------------------------------------*/
6036 /* genModOneByte : 8 bit modulus */
6037 /*-----------------------------------------------------------------*/
6039 genModOneByte (operand * left,
6044 bool lUnsigned, rUnsigned, pushedB;
6045 bool runtimeSign, compiletimeSign;
6050 D (emitcode (";", "genModOneByte"));
6053 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
6054 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
6058 /* signed or unsigned */
6059 if (lUnsigned && rUnsigned)
6061 /* unsigned is easy */
6062 LOAD_AB_FOR_DIV (left, right, l);
6063 emitcode ("div", "ab");
6064 aopOp (result, ic, TRUE, FALSE);
6065 aopPut (result, "b", 0);
6067 for (size = AOP_SIZE (result) - 1; size--;)
6068 aopPut (result, zero, offset++);
6074 /* signed is a little bit more difficult */
6076 /* now sign adjust for both left & right */
6078 /* modulus: sign of the right operand has no influence on the result! */
6079 if (AOP_TYPE(right) == AOP_LIT)
6081 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
6083 if (!rUnsigned && val < 0)
6084 emitcode ("mov", "b,#0x%02x", -val);
6086 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
6088 else /* not literal */
6091 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
6094 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
6095 lbl = newiTempLabel (NULL);
6096 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
6097 emitcode ("cpl", "a"); /* 2's complement */
6098 emitcode ("inc", "a");
6100 emitcode ("mov", "b,a");
6104 /* let's see what's needed: */
6105 /* apply negative sign during runtime */
6106 runtimeSign = FALSE;
6107 /* negative sign from literals */
6108 compiletimeSign = FALSE;
6110 /* sign adjust left side */
6111 if (AOP_TYPE(left) == AOP_LIT)
6113 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
6115 if (!lUnsigned && val < 0)
6117 compiletimeSign = TRUE; /* set sign flag */
6118 emitcode ("mov", "a,#0x%02x", -val);
6121 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
6123 else /* ! literal */
6125 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
6130 emitcode ("clr", "F0"); /* clear sign flag */
6132 lbl = newiTempLabel (NULL);
6133 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
6134 emitcode ("setb", "F0"); /* set sign flag */
6135 emitcode ("cpl", "a"); /* 2's complement */
6136 emitcode ("inc", "a");
6141 /* now the modulus */
6142 emitcode ("nop", "; workaround for DS80C390 div bug.");
6143 emitcode ("div", "ab");
6145 if (runtimeSign || compiletimeSign)
6147 emitcode ("mov", "a,b");
6148 lbl = newiTempLabel (NULL);
6150 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
6151 emitcode ("cpl", "a"); /* lsb 2's complement */
6152 emitcode ("inc", "a");
6156 aopOp (result, ic, TRUE, FALSE);
6157 size = AOP_SIZE (result) - 1;
6161 /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
6162 then the result will be in b, a */
6163 emitcode ("mov", "b,a"); /* 1 */
6164 /* msb is 0x00 or 0xff depending on the sign */
6167 emitcode ("mov", "c,F0");
6168 emitcode ("subb", "a,acc");
6169 emitcode ("xch", "a,b"); /* 2 */
6171 aopPut (result, "b", offset++); /* write msb's */
6173 else /* compiletimeSign */
6175 aopPut (result, "#0xff", offset++); /* write msb's */
6177 aopPut (result, "a", 0); /* 3: write lsb */
6182 aopOp(result, ic, TRUE, FALSE);
6183 size = AOP_SIZE (result) - 1;
6185 aopPut (result, "b", 0);
6187 aopPut (result, zero, offset++);
6193 /*-----------------------------------------------------------------*/
6194 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
6195 /*-----------------------------------------------------------------*/
6196 static void genModTwoByte (operand *left, operand *right,
6197 operand *result, iCode *ic)
6199 sym_link *retype = getSpec(operandType(right));
6200 sym_link *letype = getSpec(operandType(left));
6201 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
6204 /* load up MA with left */
6205 /* save EA bit in F1 */
6206 lbl = newiTempLabel(NULL);
6207 emitcode ("setb","F1");
6208 emitcode ("jbc","EA,!tlabel",lbl->key+100);
6209 emitcode ("clr","F1");
6213 lbl = newiTempLabel(NULL);
6214 emitcode ("mov","b,%s",aopGet(left,0,FALSE,FALSE,NULL));
6215 emitcode ("mov","a,%s",aopGet(left,1,FALSE,FALSE,NULL));
6216 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
6217 emitcode ("xch", "a,b");
6218 emitcode ("cpl","a");
6219 emitcode ("add", "a,#1");
6220 emitcode ("xch", "a,b");
6221 emitcode ("cpl", "a"); // msb
6222 emitcode ("addc","a,#0");
6224 emitcode ("mov","ma,b");
6225 emitcode ("mov","ma,a");
6227 emitcode ("mov","ma,%s",aopGet(left,0,FALSE,FALSE,NULL));
6228 emitcode ("mov","ma,%s",aopGet(left,1,FALSE,FALSE,NULL));
6231 /* load up MB with right */
6233 if (AOP_TYPE(right) == AOP_LIT) {
6234 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
6238 emitcode ("mov","mb,#!constbyte",val & 0xff);
6239 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
6241 lbl = newiTempLabel(NULL);
6242 emitcode ("mov","b,%s",aopGet(right,0,FALSE,FALSE,NULL));
6243 emitcode ("mov","a,%s",aopGet(right,1,FALSE,FALSE,NULL));
6244 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
6245 emitcode ("xch", "a,b");
6246 emitcode ("cpl","a");
6247 emitcode ("add", "a,#1");
6248 emitcode ("xch", "a,b");
6249 emitcode ("cpl", "a"); // msb
6250 emitcode ("addc", "a,#0");
6252 emitcode ("mov","mb,b");
6253 emitcode ("mov","mb,a");
6256 emitcode ("mov","mb,%s",aopGet(right,0,FALSE,FALSE,NULL));
6257 emitcode ("mov","mb,%s",aopGet(right,1,FALSE,FALSE,NULL));
6260 /* wait for multiplication to finish */
6261 lbl = newiTempLabel(NULL);
6263 emitcode("mov","a,mcnt1");
6264 emitcode("anl","a,#!constbyte",0x80);
6265 emitcode("jnz","!tlabel",lbl->key+100);
6267 freeAsmop (left, NULL, ic, TRUE);
6268 freeAsmop (right, NULL, ic,TRUE);
6269 aopOp(result, ic, TRUE, FALSE);
6271 aopPut(result,"mb",1);
6272 aopPut(result,"mb",0);
6273 freeAsmop (result, NULL, ic, TRUE);
6275 /* restore EA bit in F1 */
6276 lbl = newiTempLabel(NULL);
6277 emitcode ("jnb","F1,!tlabel",lbl->key+100);
6278 emitcode ("setb","EA");
6282 /*-----------------------------------------------------------------*/
6283 /* genMod - generates code for division */
6284 /*-----------------------------------------------------------------*/
6288 operand *left = IC_LEFT (ic);
6289 operand *right = IC_RIGHT (ic);
6290 operand *result = IC_RESULT (ic);
6292 D (emitcode (";", "genMod"));
6294 /* assign the asmops */
6297 /* special cases first */
6299 if (AOP_TYPE (left) == AOP_CRY &&
6300 AOP_TYPE (right) == AOP_CRY)
6302 genModbits (left, right, result, ic);
6306 /* if both are of size == 1 */
6307 if (AOP_SIZE (left) == 1 &&
6308 AOP_SIZE (right) == 1)
6310 genModOneByte (left, right, result, ic);
6314 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
6315 /* use the ds390 ARITHMETIC accel UNIT */
6316 genModTwoByte (left, right, result, ic);
6320 /* should have been converted to function call */
6324 freeAsmop (result, NULL, ic, TRUE);
6325 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6326 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6329 /*-----------------------------------------------------------------*/
6330 /* genIfxJump :- will create a jump depending on the ifx */
6331 /*-----------------------------------------------------------------*/
6333 genIfxJump (iCode * ic, char *jval)
6336 symbol *tlbl = newiTempLabel (NULL);
6339 D (emitcode (";", "genIfxJump"));
6341 /* if true label then we jump if condition
6345 jlbl = IC_TRUE (ic);
6346 inst = ((strcmp (jval, "a") == 0 ? "jz" :
6347 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
6351 /* false label is present */
6352 jlbl = IC_FALSE (ic);
6353 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
6354 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
6356 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
6357 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
6359 emitcode (inst, "!tlabel", tlbl->key + 100);
6360 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
6363 /* mark the icode as generated */
6367 /*-----------------------------------------------------------------*/
6368 /* genCmp :- greater or less than comparison */
6369 /*-----------------------------------------------------------------*/
6371 genCmp (operand * left, operand * right,
6372 iCode * ic, iCode * ifx, int sign)
6374 int size, offset = 0;
6375 unsigned long lit = 0L;
6378 D (emitcode (";", "genCmp"));
6380 result = IC_RESULT (ic);
6382 /* if left & right are bit variables */
6383 if (AOP_TYPE (left) == AOP_CRY &&
6384 AOP_TYPE (right) == AOP_CRY)
6386 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6387 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6391 /* subtract right from left if at the
6392 end the carry flag is set then we know that
6393 left is greater than right */
6394 size = max (AOP_SIZE (left), AOP_SIZE (right));
6396 /* if unsigned char cmp with lit, do cjne left,#right,zz */
6397 if ((size == 1) && !sign &&
6398 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
6400 symbol *lbl = newiTempLabel (NULL);
6401 emitcode ("cjne", "%s,%s,!tlabel",
6402 aopGet (left, offset, FALSE, FALSE, NULL),
6403 aopGet (right, offset, FALSE, FALSE, NULL),
6409 if (AOP_TYPE (right) == AOP_LIT)
6411 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6412 /* optimize if(x < 0) or if(x >= 0) */
6421 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
6423 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6424 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6426 aopOp (result, ic, FALSE, FALSE);
6428 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
6430 freeAsmop (result, NULL, ic, TRUE);
6431 genIfxJump (ifx, "acc.7");
6436 emitcode ("rlc", "a");
6438 goto release_freedLR;
6446 // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
6447 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
6448 // emitcode (";", "genCmp #2");
6449 if (sign && (size == 0))
6451 // emitcode (";", "genCmp #3");
6452 emitcode ("xrl", "a,#!constbyte",0x80);
6453 if (AOP_TYPE (right) == AOP_LIT)
6455 unsigned long lit = (unsigned long)
6456 floatFromVal (AOP (right)->aopu.aop_lit);
6457 // emitcode (";", "genCmp #3.1");
6458 emitcode ("subb", "a,#!constbyte",
6459 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
6463 // emitcode (";", "genCmp #3.2");
6465 MOVB (aopGet (right, offset++, FALSE, FALSE, "b"));
6466 saveAccWarn = DEFAULT_ACC_WARNING;
6467 emitcode ("xrl", "b,#!constbyte",0x80);
6468 emitcode ("subb", "a,b");
6475 // emitcode (";", "genCmp #4");
6477 s = aopGet (right, offset++, FALSE, FALSE, "b");
6478 saveAccWarn = DEFAULT_ACC_WARNING;
6480 emitcode ("subb", "a,%s", s);
6487 /* Don't need the left & right operands any more; do need the result. */
6488 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6489 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6491 aopOp (result, ic, FALSE, FALSE);
6495 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6501 /* if the result is used in the next
6502 ifx conditional branch then generate
6503 code a little differently */
6506 genIfxJump (ifx, "c");
6512 /* leave the result in acc */
6514 freeAsmop (result, NULL, ic, TRUE);
6517 /*-----------------------------------------------------------------*/
6518 /* genCmpGt :- greater than comparison */
6519 /*-----------------------------------------------------------------*/
6521 genCmpGt (iCode * ic, iCode * ifx)
6523 operand *left, *right;
6524 sym_link *letype, *retype;
6527 D (emitcode (";", "genCmpGt"));
6529 left = IC_LEFT (ic);
6530 right = IC_RIGHT (ic);
6532 letype = getSpec (operandType (left));
6533 retype = getSpec (operandType (right));
6534 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6536 /* assign the left & right amsops */
6539 genCmp (right, left, ic, ifx, sign);
6542 /*-----------------------------------------------------------------*/
6543 /* genCmpLt - less than comparisons */
6544 /*-----------------------------------------------------------------*/
6546 genCmpLt (iCode * ic, iCode * ifx)
6548 operand *left, *right;
6549 sym_link *letype, *retype;
6552 D (emitcode (";", "genCmpLt"));
6554 left = IC_LEFT (ic);
6555 right = IC_RIGHT (ic);
6557 letype = getSpec (operandType (left));
6558 retype = getSpec (operandType (right));
6559 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6561 /* assign the left & right amsops */
6564 genCmp (left, right, ic, ifx, sign);
6567 /*-----------------------------------------------------------------*/
6568 /* gencjneshort - compare and jump if not equal */
6569 /*-----------------------------------------------------------------*/
6571 gencjneshort (operand * left, operand * right, symbol * lbl)
6573 int size = max (AOP_SIZE (left), AOP_SIZE (right));
6575 unsigned long lit = 0L;
6577 D (emitcode (";", "gencjneshort"));
6579 /* if the left side is a literal or
6580 if the right is in a pointer register and left
6582 if ((AOP_TYPE (left) == AOP_LIT) ||
6583 (AOP_TYPE (left) == AOP_IMMD) ||
6584 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6591 if (AOP_TYPE (right) == AOP_LIT)
6592 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6594 if (opIsGptr (left) || opIsGptr (right))
6596 /* We are comparing a generic pointer to something.
6597 * Exclude the generic type byte from the comparison.
6600 D (emitcode (";", "cjneshort: generic ptr special case."););
6604 /* if the right side is a literal then anything goes */
6605 if (AOP_TYPE (right) == AOP_LIT &&
6606 AOP_TYPE (left) != AOP_DIR)
6610 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
6611 emitcode ("cjne", "a,%s,!tlabel",
6612 aopGet (right, offset, FALSE, FALSE, NULL),
6618 /* if the right side is in a register or in direct space or
6619 if the left is a pointer register & right is not */
6620 else if (AOP_TYPE (right) == AOP_REG ||
6621 AOP_TYPE (right) == AOP_DIR ||
6622 AOP_TYPE (right) == AOP_LIT ||
6623 AOP_TYPE (right) == AOP_IMMD ||
6624 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6625 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6629 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
6630 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6631 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6632 emitcode ("jnz", "!tlabel", lbl->key + 100);
6634 emitcode ("cjne", "a,%s,!tlabel",
6635 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG),
6642 /* right is a pointer reg need both a & b */
6645 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
6646 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
6647 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
6653 /*-----------------------------------------------------------------*/
6654 /* gencjne - compare and jump if not equal */
6655 /*-----------------------------------------------------------------*/
6657 gencjne (operand * left, operand * right, symbol * lbl)
6659 symbol *tlbl = newiTempLabel (NULL);
6661 D (emitcode (";", "gencjne"));
6663 gencjneshort (left, right, lbl);
6665 emitcode ("mov", "a,%s", one);
6666 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
6668 emitcode ("clr", "a");
6672 /*-----------------------------------------------------------------*/
6673 /* genCmpEq - generates code for equal to */
6674 /*-----------------------------------------------------------------*/
6676 genCmpEq (iCode * ic, iCode * ifx)
6678 operand *left, *right, *result;
6680 D (emitcode (";", "genCmpEq"));
6683 AOP_SET_LOCALS (ic);
6685 /* if literal, literal on the right or
6686 if the right is in a pointer register and left
6688 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6689 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6691 operand *t = IC_RIGHT (ic);
6692 IC_RIGHT (ic) = IC_LEFT (ic);
6696 if (ifx && /* !AOP_SIZE(result) */
6697 OP_SYMBOL (result) &&
6698 OP_SYMBOL (result)->regType == REG_CND)
6701 /* if they are both bit variables */
6702 if (AOP_TYPE (left) == AOP_CRY &&
6703 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6705 if (AOP_TYPE (right) == AOP_LIT)
6707 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6710 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6711 emitcode ("cpl", "c");
6715 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6719 emitcode ("clr", "c");
6721 /* AOP_TYPE(right) == AOP_CRY */
6725 symbol *lbl = newiTempLabel (NULL);
6726 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6727 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6728 emitcode ("cpl", "c");
6731 /* if true label then we jump if condition
6733 tlbl = newiTempLabel (NULL);
6736 emitcode ("jnc", "!tlabel", tlbl->key + 100);
6737 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6741 emitcode ("jc", "!tlabel", tlbl->key + 100);
6742 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6748 tlbl = newiTempLabel (NULL);
6749 gencjneshort (left, right, tlbl);
6752 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6757 symbol *lbl = newiTempLabel (NULL);
6758 emitcode ("sjmp", "!tlabel", lbl->key + 100);
6760 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6764 /* mark the icode as generated */
6767 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6768 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6772 /* if they are both bit variables */
6773 if (AOP_TYPE (left) == AOP_CRY &&
6774 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6776 if (AOP_TYPE (right) == AOP_LIT)
6778 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6781 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6782 emitcode ("cpl", "c");
6786 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6790 emitcode ("clr", "c");
6792 /* AOP_TYPE(right) == AOP_CRY */
6796 symbol *lbl = newiTempLabel (NULL);
6797 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6798 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6799 emitcode ("cpl", "c");
6803 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6804 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6806 aopOp (result, ic, TRUE, FALSE);
6809 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6816 genIfxJump (ifx, "c");
6819 /* if the result is used in an arithmetic operation
6820 then put the result in place */
6825 gencjne (left, right, newiTempLabel (NULL));
6827 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6828 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6830 aopOp (result, ic, TRUE, FALSE);
6832 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6834 aopPut (result, "a", 0);
6839 genIfxJump (ifx, "a");
6842 /* if the result is used in an arithmetic operation
6843 then put the result in place */
6844 if (AOP_TYPE (result) != AOP_CRY)
6846 /* leave the result in acc */
6850 freeAsmop (result, NULL, ic, TRUE);
6853 /*-----------------------------------------------------------------*/
6854 /* ifxForOp - returns the icode containing the ifx for operand */
6855 /*-----------------------------------------------------------------*/
6857 ifxForOp (operand * op, iCode * ic)
6859 /* if true symbol then needs to be assigned */
6860 if (IS_TRUE_SYMOP (op))
6863 /* if this has register type condition and
6864 the next instruction is ifx with the same operand
6865 and live to of the operand is upto the ifx only then */
6867 ic->next->op == IFX &&
6868 IC_COND (ic->next)->key == op->key &&
6869 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6875 /*-----------------------------------------------------------------*/
6876 /* hasInc - operand is incremented before any other use */
6877 /*-----------------------------------------------------------------*/
6879 hasInc (operand *op, iCode *ic, int osize)
6881 sym_link *type = operandType(op);
6882 sym_link *retype = getSpec (type);
6883 iCode *lic = ic->next;
6886 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6887 if (!IS_SYMOP(op)) return NULL;
6889 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6890 if (IS_AGGREGATE(type->next)) return NULL;
6891 if (osize != (isize = getSize(type->next))) return NULL;
6894 /* if operand of the form op = op + <sizeof *op> */
6895 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6896 isOperandEqual(IC_RESULT(lic),op) &&
6897 isOperandLiteral(IC_RIGHT(lic)) &&
6898 operandLitValue(IC_RIGHT(lic)) == isize) {
6901 /* if the operand used or deffed */
6902 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6905 /* if GOTO or IFX */
6906 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6912 /*-----------------------------------------------------------------*/
6913 /* genAndOp - for && operation */
6914 /*-----------------------------------------------------------------*/
6916 genAndOp (iCode * ic)
6918 operand *left, *right, *result;
6921 D (emitcode (";", "genAndOp"));
6923 /* note here that && operations that are in an
6924 if statement are taken away by backPatchLabels
6925 only those used in arthmetic operations remain */
6927 AOP_SET_LOCALS (ic);
6929 /* if both are bit variables */
6930 if (AOP_TYPE (left) == AOP_CRY &&
6931 AOP_TYPE (right) == AOP_CRY)
6933 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6934 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6935 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6936 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6938 aopOp (result,ic,FALSE, FALSE);
6943 tlbl = newiTempLabel (NULL);
6945 emitcode ("jz", "!tlabel", tlbl->key + 100);
6948 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6949 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6951 aopOp (result,ic,FALSE, FALSE);
6955 freeAsmop (result, NULL, ic, TRUE);
6959 /*-----------------------------------------------------------------*/
6960 /* genOrOp - for || operation */
6961 /*-----------------------------------------------------------------*/
6963 genOrOp (iCode * ic)
6965 operand *left, *right, *result;
6968 D (emitcode (";", "genOrOp"));
6970 /* note here that || operations that are in an
6971 if statement are taken away by backPatchLabels
6972 only those used in arthmetic operations remain */
6974 AOP_SET_LOCALS (ic);
6976 /* if both are bit variables */
6977 if (AOP_TYPE (left) == AOP_CRY &&
6978 AOP_TYPE (right) == AOP_CRY)
6980 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6981 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6982 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6983 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6985 aopOp (result,ic,FALSE, FALSE);
6991 tlbl = newiTempLabel (NULL);
6993 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6996 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6997 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6999 aopOp (result,ic,FALSE, FALSE);
7004 freeAsmop (result, NULL, ic, TRUE);
7007 /*-----------------------------------------------------------------*/
7008 /* isLiteralBit - test if lit == 2^n */
7009 /*-----------------------------------------------------------------*/
7011 isLiteralBit (unsigned long lit)
7013 unsigned long pw[32] =
7014 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
7015 0x100L, 0x200L, 0x400L, 0x800L,
7016 0x1000L, 0x2000L, 0x4000L, 0x8000L,
7017 0x10000L, 0x20000L, 0x40000L, 0x80000L,
7018 0x100000L, 0x200000L, 0x400000L, 0x800000L,
7019 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
7020 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
7023 for (idx = 0; idx < 32; idx++)
7029 /*-----------------------------------------------------------------*/
7030 /* continueIfTrue - */
7031 /*-----------------------------------------------------------------*/
7033 continueIfTrue (iCode * ic)
7036 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
7040 /*-----------------------------------------------------------------*/
7042 /*-----------------------------------------------------------------*/
7044 jumpIfTrue (iCode * ic)
7047 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
7051 /*-----------------------------------------------------------------*/
7052 /* jmpTrueOrFalse - */
7053 /*-----------------------------------------------------------------*/
7055 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
7057 // ugly but optimized by peephole
7060 symbol *nlbl = newiTempLabel (NULL);
7061 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
7063 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
7068 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
7074 // Generate code to perform a bit-wise logic operation
7075 // on two operands in far space (assumed to already have been
7076 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
7077 // in far space. This requires pushing the result on the stack
7078 // then popping it into the result.
7080 genFarFarLogicOp(iCode *ic, char *logicOp)
7082 int size, resultSize, compSize;
7086 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
7087 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
7088 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
7090 _startLazyDPSEvaluation();
7091 for (size = compSize; (size--); offset++)
7093 MOVA (aopGet (IC_LEFT(ic), offset, FALSE, FALSE, NULL));
7094 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
7095 MOVA (aopGet (IC_RIGHT(ic), offset, FALSE, FALSE, NULL));
7097 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
7098 emitcode ("push", "acc");
7100 _endLazyDPSEvaluation();
7102 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7103 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7104 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
7106 resultSize = AOP_SIZE(IC_RESULT(ic));
7108 ADJUST_PUSHED_RESULT(compSize, resultSize);
7110 _startLazyDPSEvaluation();
7113 emitcode ("pop", "acc");
7114 aopPut (IC_RESULT (ic), "a", compSize);
7116 _endLazyDPSEvaluation();
7117 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
7121 /*-----------------------------------------------------------------*/
7122 /* genAnd - code for and */
7123 /*-----------------------------------------------------------------*/
7125 genAnd (iCode * ic, iCode * ifx)
7127 operand *left, *right, *result;
7128 int size, offset = 0;
7129 unsigned long lit = 0L;
7134 D (emitcode (";", "genAnd"));
7136 AOP_OP_3_NOFATAL (ic, pushResult);
7137 AOP_SET_LOCALS (ic);
7141 genFarFarLogicOp(ic, "anl");
7146 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
7148 AOP_TYPE (left), AOP_TYPE (right));
7149 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
7151 AOP_SIZE (left), AOP_SIZE (right));
7154 /* if left is a literal & right is not then exchange them */
7155 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7156 #ifdef LOGIC_OPS_BROKEN
7157 || AOP_NEEDSACC (left)
7161 operand *tmp = right;
7166 /* if result = right then exchange left and right */
7167 if (sameRegs (AOP (result), AOP (right)))
7169 operand *tmp = right;
7174 /* if right is bit then exchange them */
7175 if (AOP_TYPE (right) == AOP_CRY &&
7176 AOP_TYPE (left) != AOP_CRY)
7178 operand *tmp = right;
7182 if (AOP_TYPE (right) == AOP_LIT)
7183 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7185 size = AOP_SIZE (result);
7188 // result = bit & yy;
7189 if (AOP_TYPE (left) == AOP_CRY)
7191 // c = bit & literal;
7192 if (AOP_TYPE (right) == AOP_LIT)
7196 if (size && sameRegs (AOP (result), AOP (left)))
7199 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7204 if (size && (AOP_TYPE (result) == AOP_CRY))
7206 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
7209 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7214 emitcode ("clr", "c");
7219 if (AOP_TYPE (right) == AOP_CRY)
7222 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7223 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
7228 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
7230 emitcode ("rrc", "a");
7231 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
7239 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7240 genIfxJump (ifx, "c");
7244 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7245 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7246 if ((AOP_TYPE (right) == AOP_LIT) &&
7247 (AOP_TYPE (result) == AOP_CRY) &&
7248 (AOP_TYPE (left) != AOP_CRY))
7250 int posbit = isLiteralBit (lit);
7255 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE, NULL));
7259 switch (posbit & 0x07)
7261 case 0: emitcode ("rrc", "a");
7263 case 7: emitcode ("rlc", "a");
7265 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
7274 SNPRINTF (buffer, sizeof(buffer),
7275 "acc.%d", posbit & 0x07);
7276 genIfxJump (ifx, buffer);
7280 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
7287 symbol *tlbl = newiTempLabel (NULL);
7288 int sizel = AOP_SIZE (left);
7290 emitcode ("setb", "c");
7293 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
7295 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7297 if ((posbit = isLiteralBit (bytelit)) != 0)
7298 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
7301 if (bytelit != 0x0FFL)
7302 emitcode ("anl", "a,%s",
7303 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG));
7304 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7309 // bit = left & literal
7312 emitcode ("clr", "c");
7315 // if(left & literal)
7319 jmpTrueOrFalse (ifx, tlbl);
7329 /* if left is same as result */
7330 if (sameRegs (AOP (result), AOP (left)))
7332 for (; size--; offset++)
7334 if (AOP_TYPE (right) == AOP_LIT)
7336 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7337 if (bytelit == 0x0FF)
7339 /* dummy read of volatile operand */
7340 if (isOperandVolatile (left, FALSE))
7341 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7345 else if (bytelit == 0)
7347 aopPut (result, zero, offset);
7349 else if (IS_AOP_PREG (result))
7351 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7352 emitcode ("anl", "a,%s",
7353 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG));
7354 aopPut (result, "a", offset);
7357 emitcode ("anl", "%s,%s",
7358 aopGet (left, offset, FALSE, TRUE, NULL),
7359 aopGet (right, offset, FALSE, FALSE, NULL));
7363 if (AOP_TYPE (left) == AOP_ACC)
7366 emitcode("mov", "a,b");
7367 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7369 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7371 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
7372 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7373 emitcode ("anl", "a,b");
7374 aopPut (result, "a", offset);
7376 else if (aopGetUsesAcc (left, offset))
7378 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7379 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7380 aopPut (result, "a", offset);
7384 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7385 if (IS_AOP_PREG (result))
7387 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7388 aopPut (result, "a", offset);
7391 emitcode ("anl", "%s,a", aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7398 // left & result in different registers
7399 if (AOP_TYPE (result) == AOP_CRY)
7402 // if(size), result in bit
7403 // if(!size && ifx), conditional oper: if(left & right)
7404 symbol *tlbl = newiTempLabel (NULL);
7405 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
7407 emitcode ("setb", "c");
7410 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7411 && AOP_TYPE(left)==AOP_ACC)
7414 emitcode("mov", "a,b");
7415 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, NULL));
7417 else if (AOP_TYPE(left)==AOP_ACC)
7421 bool pushedB = pushB ();
7422 emitcode("mov", "b,a");
7423 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7424 emitcode("anl", "a,b");
7429 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7430 emitcode("anl", "a,b");
7433 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7435 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE, NULL));
7436 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7437 emitcode ("anl", "a,b");
7439 else if (aopGetUsesAcc (left, offset))
7441 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7442 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7446 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7447 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE, DP2_RESULT_REG));
7450 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7460 jmpTrueOrFalse (ifx, tlbl);
7466 for (; (size--); offset++)
7469 // result = left & right
7470 if (AOP_TYPE (right) == AOP_LIT)
7472 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7473 if (bytelit == 0x0FF)
7476 aopGet (left, offset, FALSE, FALSE, NULL),
7480 else if (bytelit == 0)
7482 /* dummy read of volatile operand */
7483 if (isOperandVolatile (left, FALSE))
7484 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7485 aopPut (result, zero, offset);
7488 else if (AOP_TYPE (left) == AOP_ACC)
7492 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, NULL));
7493 aopPut (result, "a", offset);
7498 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE, NULL));
7499 aopPut (result, "b", offset);
7504 // faster than result <- left, anl result,right
7505 // and better if result is SFR
7506 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7507 && AOP_TYPE(left)==AOP_ACC)
7510 emitcode("mov", "a,b");
7511 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, NULL));
7513 else if (AOP_TYPE(left)==AOP_ACC)
7517 bool pushedB = pushB ();
7518 emitcode("mov", "b,a");
7519 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7520 emitcode("anl", "a,b");
7525 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7526 emitcode("anl", "a,b");
7529 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7531 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
7532 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7533 emitcode ("anl", "a,b");
7535 else if (aopGetUsesAcc (left, offset))
7537 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7538 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7542 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7543 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE, DP2_RESULT_REG));
7545 aopPut (result, "a", offset);
7551 freeAsmop (result, NULL, ic, TRUE);
7552 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7553 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7556 /*-----------------------------------------------------------------*/
7557 /* genOr - code for or */
7558 /*-----------------------------------------------------------------*/
7560 genOr (iCode * ic, iCode * ifx)
7562 operand *left, *right, *result;
7563 int size, offset = 0;
7564 unsigned long lit = 0L;
7568 D (emitcode (";", "genOr"));
7570 AOP_OP_3_NOFATAL (ic, pushResult);
7571 AOP_SET_LOCALS (ic);
7575 genFarFarLogicOp(ic, "orl");
7581 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
7583 AOP_TYPE (left), AOP_TYPE (right));
7584 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
7586 AOP_SIZE (left), AOP_SIZE (right));
7589 /* if left is a literal & right is not then exchange them */
7590 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7591 #ifdef LOGIC_OPS_BROKEN
7592 || AOP_NEEDSACC (left) // I think this is a net loss now.
7596 operand *tmp = right;
7601 /* if result = right then exchange them */
7602 if (sameRegs (AOP (result), AOP (right)))
7604 operand *tmp = right;
7609 /* if right is bit then exchange them */
7610 if (AOP_TYPE (right) == AOP_CRY &&
7611 AOP_TYPE (left) != AOP_CRY)
7613 operand *tmp = right;
7617 if (AOP_TYPE (right) == AOP_LIT)
7618 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7620 size = AOP_SIZE (result);
7624 if (AOP_TYPE (left) == AOP_CRY)
7626 if (AOP_TYPE (right) == AOP_LIT)
7628 // c = bit | literal;
7631 // lit != 0 => result = 1
7632 if (AOP_TYPE (result) == AOP_CRY)
7635 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7637 continueIfTrue (ifx);
7640 emitcode ("setb", "c");
7644 // lit == 0 => result = left
7645 if (size && sameRegs (AOP (result), AOP (left)))
7647 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7652 if (AOP_TYPE (right) == AOP_CRY)
7655 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7656 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7661 symbol *tlbl = newiTempLabel (NULL);
7662 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
7663 emitcode ("setb", "c");
7664 emitcode ("jb", "%s,!tlabel",
7665 AOP (left)->aopu.aop_dir, tlbl->key + 100);
7667 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7668 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7670 jmpTrueOrFalse (ifx, tlbl);
7685 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7686 genIfxJump (ifx, "c");
7690 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7691 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7692 if ((AOP_TYPE (right) == AOP_LIT) &&
7693 (AOP_TYPE (result) == AOP_CRY) &&
7694 (AOP_TYPE (left) != AOP_CRY))
7700 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7702 continueIfTrue (ifx);
7707 // lit = 0, result = boolean(left)
7709 emitcode ("setb", "c");
7713 symbol *tlbl = newiTempLabel (NULL);
7714 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7720 genIfxJump (ifx, "a");
7728 /* if left is same as result */
7729 if (sameRegs (AOP (result), AOP (left)))
7731 for (; size--; offset++)
7733 if (AOP_TYPE (right) == AOP_LIT)
7735 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7738 /* dummy read of volatile operand */
7739 if (isOperandVolatile (left, FALSE))
7740 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7744 else if (bytelit == 0x0FF)
7746 aopPut (result, "#0xFF", offset);
7748 else if (IS_AOP_PREG (left))
7750 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7751 emitcode ("orl", "a,%s",
7752 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7753 aopPut (result, "a", offset);
7757 emitcode ("orl", "%s,%s",
7758 aopGet (left, offset, FALSE, TRUE, NULL),
7759 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7764 if (AOP_TYPE (left) == AOP_ACC)
7767 emitcode("mov", "a,b");
7768 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7770 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7772 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE, NULL));
7773 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7774 emitcode ("orl", "a,b");
7775 aopPut (result, "a", offset);
7777 else if (aopGetUsesAcc (left, offset))
7779 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7780 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7781 aopPut (result, "a", offset);
7785 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7786 if (IS_AOP_PREG (left))
7788 emitcode ("orl", "a,%s",
7789 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7790 aopPut (result, "a", offset);
7794 emitcode ("orl", "%s,a",
7795 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7803 // left & result in different registers
7804 if (AOP_TYPE (result) == AOP_CRY)
7807 // if(size), result in bit
7808 // if(!size && ifx), conditional oper: if(left | right)
7809 symbol *tlbl = newiTempLabel (NULL);
7810 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7812 emitcode ("setb", "c");
7815 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7816 && AOP_TYPE(left)==AOP_ACC)
7819 emitcode("mov", "a,b");
7820 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7822 else if (AOP_TYPE(left)==AOP_ACC)
7826 bool pushedB = pushB ();
7827 emitcode("mov", "b,a");
7828 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7829 emitcode("orl", "a,b");
7834 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7835 emitcode("orl", "a,b");
7838 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7840 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
7841 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7842 emitcode ("orl", "a,b");
7844 else if (aopGetUsesAcc (left, offset))
7846 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7847 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7851 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7852 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE, DP2_RESULT_REG));
7855 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7865 jmpTrueOrFalse (ifx, tlbl);
7871 _startLazyDPSEvaluation();
7872 for (; (size--); offset++)
7875 // result = left | right
7876 if (AOP_TYPE (right) == AOP_LIT)
7878 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7882 aopGet (left, offset, FALSE, FALSE, NULL),
7886 else if (bytelit == 0x0FF)
7888 /* dummy read of volatile operand */
7889 if (isOperandVolatile (left, FALSE))
7890 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7891 aopPut (result, "#0xFF", offset);
7895 // faster than result <- left, orl result,right
7896 // and better if result is SFR
7897 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7898 && AOP_TYPE(left)==AOP_ACC)
7901 emitcode("mov", "a,b");
7902 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7904 else if (AOP_TYPE(left)==AOP_ACC)
7908 bool pushedB = pushB ();
7909 emitcode("mov", "b,a");
7910 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7911 emitcode("orl", "a,b");
7916 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7917 emitcode("orl", "a,b");
7920 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7922 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
7923 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7924 emitcode ("orl", "a,b");
7926 else if (aopGetUsesAcc (left, offset))
7928 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7929 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7933 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7934 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE, DP2_RESULT_REG));
7936 aopPut (result, "a", offset);
7938 _endLazyDPSEvaluation();
7943 freeAsmop (result, NULL, ic, TRUE);
7944 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7945 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7948 /*-----------------------------------------------------------------*/
7949 /* genXor - code for xclusive or */
7950 /*-----------------------------------------------------------------*/
7952 genXor (iCode * ic, iCode * ifx)
7954 operand *left, *right, *result;
7955 int size, offset = 0;
7956 unsigned long lit = 0L;
7960 D (emitcode (";", "genXor"));
7962 AOP_OP_3_NOFATAL (ic, pushResult);
7963 AOP_SET_LOCALS (ic);
7967 genFarFarLogicOp(ic, "xrl");
7972 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
7974 AOP_TYPE (left), AOP_TYPE (right));
7975 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
7977 AOP_SIZE (left), AOP_SIZE (right));
7980 /* if left is a literal & right is not ||
7981 if left needs acc & right does not */
7982 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7983 #ifdef LOGIC_OPS_BROKEN
7984 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
7988 operand *tmp = right;
7993 /* if result = right then exchange them */
7994 if (sameRegs (AOP (result), AOP (right)))
7996 operand *tmp = right;
8001 /* if right is bit then exchange them */
8002 if (AOP_TYPE (right) == AOP_CRY &&
8003 AOP_TYPE (left) != AOP_CRY)
8005 operand *tmp = right;
8009 if (AOP_TYPE (right) == AOP_LIT)
8010 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8012 size = AOP_SIZE (result);
8016 if (AOP_TYPE (left) == AOP_CRY)
8018 if (AOP_TYPE (right) == AOP_LIT)
8020 // c = bit & literal;
8023 // lit>>1 != 0 => result = 1
8024 if (AOP_TYPE (result) == AOP_CRY)
8027 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
8029 continueIfTrue (ifx);
8032 emitcode ("setb", "c");
8039 // lit == 0, result = left
8040 if (size && sameRegs (AOP (result), AOP (left)))
8042 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
8046 // lit == 1, result = not(left)
8047 if (size && sameRegs (AOP (result), AOP (left)))
8049 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
8054 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
8055 emitcode ("cpl", "c");
8063 symbol *tlbl = newiTempLabel (NULL);
8064 if (AOP_TYPE (right) == AOP_CRY)
8067 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8071 int sizer = AOP_SIZE (right);
8073 // if val>>1 != 0, result = 1
8074 emitcode ("setb", "c");
8077 MOVA (aopGet (right, sizer - 1, FALSE, FALSE, NULL));
8079 // test the msb of the lsb
8080 emitcode ("anl", "a,#!constbyte",0xfe);
8081 emitcode ("jnz", "!tlabel", tlbl->key + 100);
8085 emitcode ("rrc", "a");
8087 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
8088 emitcode ("cpl", "c");
8096 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
8097 genIfxJump (ifx, "c");
8101 /* if left is same as result */
8102 if (sameRegs (AOP (result), AOP (left)))
8104 for (; size--; offset++)
8106 if (AOP_TYPE (right) == AOP_LIT)
8108 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
8111 /* dummy read of volatile operand */
8112 if (isOperandVolatile (left, FALSE))
8113 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8117 else if (IS_AOP_PREG (left))
8119 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8120 emitcode ("xrl", "a,%s",
8121 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG));
8122 aopPut (result, "a", offset);
8126 emitcode ("xrl", "%s,%s",
8127 aopGet (left, offset, FALSE, TRUE, NULL),
8128 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8133 if (AOP_TYPE (left) == AOP_ACC)
8136 emitcode("mov", "a,b");
8137 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8139 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
8141 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
8142 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8143 emitcode ("xrl", "a,b");
8144 aopPut (result, "a", offset);
8146 else if (aopGetUsesAcc (left, offset))
8148 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8149 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8150 aopPut (result, "a", offset);
8154 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
8155 if (IS_AOP_PREG (left))
8157 emitcode ("xrl", "a,%s",
8158 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
8159 aopPut (result, "a", offset);
8162 emitcode ("xrl", "%s,a",
8163 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
8170 // left & result in different registers
8171 if (AOP_TYPE (result) == AOP_CRY)
8174 // if(size), result in bit
8175 // if(!size && ifx), conditional oper: if(left ^ right)
8176 symbol *tlbl = newiTempLabel (NULL);
8177 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
8180 emitcode ("setb", "c");
8183 if ((AOP_TYPE (right) == AOP_LIT) &&
8184 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
8186 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8188 else if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
8189 && AOP_TYPE(left)==AOP_ACC)
8192 emitcode("mov", "a,b");
8193 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8195 else if (AOP_TYPE(left)==AOP_ACC)
8199 bool pushedB = pushB ();
8200 emitcode("mov", "b,a");
8201 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8202 emitcode("xrl", "a,b");
8207 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8208 emitcode("xrl", "a,b");
8211 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
8213 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
8214 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8215 emitcode ("xrl", "a,b");
8217 else if (aopGetUsesAcc (left, offset))
8219 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8220 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8224 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
8225 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
8228 emitcode ("jnz", "!tlabel", tlbl->key + 100);
8238 jmpTrueOrFalse (ifx, tlbl);
8242 for (; (size--); offset++)
8245 // result = left ^ right
8246 if (AOP_TYPE (right) == AOP_LIT)
8248 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
8252 aopGet (left, offset, FALSE, FALSE, NULL),
8256 D (emitcode (";", "better literal XOR."));
8257 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8258 emitcode ("xrl", "a, %s",
8259 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8263 // faster than result <- left, anl result,right
8264 // and better if result is SFR
8265 if (AOP_TYPE (left) == AOP_ACC)
8267 emitcode ("xrl", "a,%s",
8268 aopGet (right, offset,
8269 FALSE, FALSE, DP2_RESULT_REG));
8273 char *rOp = aopGet (right, offset, FALSE, FALSE, NULL);
8274 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
8276 emitcode("mov", "b,a");
8280 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8281 emitcode ("xrl", "a,%s", rOp);
8284 aopPut (result, "a", offset);
8290 freeAsmop (result, NULL, ic, TRUE);
8291 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
8292 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
8295 /*-----------------------------------------------------------------*/
8296 /* genInline - write the inline code out */
8297 /*-----------------------------------------------------------------*/
8299 genInline (iCode * ic)
8301 char *buffer, *bp, *bp1;
8302 bool inComment = FALSE;
8304 D (emitcode (";", "genInline"));
8306 _G.inLine += (!options.asmpeep);
8308 buffer = bp = bp1 = Safe_strdup (IC_INLINE(ic));
8310 /* emit each line as a code */
8328 /* Add \n for labels, not dirs such as c:\mydir */
8329 if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
8347 _G.inLine -= (!options.asmpeep);
8350 /*-----------------------------------------------------------------*/
8351 /* genRRC - rotate right with carry */
8352 /*-----------------------------------------------------------------*/
8356 operand *left, *result;
8360 D (emitcode (";", "genRRC"));
8362 /* rotate right with carry */
8363 left = IC_LEFT (ic);
8364 result = IC_RESULT (ic);
8365 aopOp (left, ic, FALSE, FALSE);
8366 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8368 /* move it to the result */
8369 size = AOP_SIZE (result);
8373 _startLazyDPSEvaluation ();
8376 l = aopGet (left, offset, FALSE, FALSE, NULL);
8378 emitcode ("rrc", "a");
8379 if (AOP_SIZE (result) > 1)
8380 aopPut (result, "a", offset--);
8382 _endLazyDPSEvaluation ();
8384 /* now we need to put the carry into the
8385 highest order byte of the result */
8386 if (AOP_SIZE (result) > 1)
8388 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE, NULL);
8391 emitcode ("mov", "acc.7,c");
8392 aopPut (result, "a", AOP_SIZE (result) - 1);
8393 freeAsmop (result, NULL, ic, TRUE);
8394 freeAsmop (left, NULL, ic, TRUE);
8397 /*-----------------------------------------------------------------*/
8398 /* genRLC - generate code for rotate left with carry */
8399 /*-----------------------------------------------------------------*/
8403 operand *left, *result;
8407 D (emitcode (";", "genRLC"));
8409 /* rotate right with carry */
8410 left = IC_LEFT (ic);
8411 result = IC_RESULT (ic);
8412 aopOp (left, ic, FALSE, FALSE);
8413 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8415 /* move it to the result */
8416 size = AOP_SIZE (result);
8420 l = aopGet (left, offset, FALSE, FALSE, NULL);
8422 emitcode ("add", "a,acc");
8423 if (AOP_SIZE (result) > 1)
8425 aopPut (result, "a", offset++);
8428 _startLazyDPSEvaluation ();
8431 l = aopGet (left, offset, FALSE, FALSE, NULL);
8433 emitcode ("rlc", "a");
8434 if (AOP_SIZE (result) > 1)
8435 aopPut (result, "a", offset++);
8437 _endLazyDPSEvaluation ();
8439 /* now we need to put the carry into the
8440 highest order byte of the result */
8441 if (AOP_SIZE (result) > 1)
8443 l = aopGet (result, 0, FALSE, FALSE, NULL);
8446 emitcode ("mov", "acc.0,c");
8447 aopPut (result, "a", 0);
8448 freeAsmop (result, NULL, ic, TRUE);
8449 freeAsmop (left, NULL, ic, TRUE);
8452 /*-----------------------------------------------------------------*/
8453 /* genGetHbit - generates code get highest order bit */
8454 /*-----------------------------------------------------------------*/
8456 genGetHbit (iCode * ic)
8458 operand *left, *result;
8460 D (emitcode (";", "genGetHbit"));
8462 left = IC_LEFT (ic);
8463 result = IC_RESULT (ic);
8464 aopOp (left, ic, FALSE, FALSE);
8465 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8467 /* get the highest order byte into a */
8468 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
8469 if (AOP_TYPE (result) == AOP_CRY)
8471 emitcode ("rlc", "a");
8476 emitcode ("rl", "a");
8477 emitcode ("anl", "a,#1");
8482 freeAsmop (result, NULL, ic, TRUE);
8483 freeAsmop (left, NULL, ic, TRUE);
8486 /*-----------------------------------------------------------------*/
8487 /* genSwap - generates code to swap nibbles or bytes */
8488 /*-----------------------------------------------------------------*/
8490 genSwap (iCode * ic)
8492 operand *left, *result;
8494 D(emitcode (";", "genSwap"));
8496 left = IC_LEFT (ic);
8497 result = IC_RESULT (ic);
8498 aopOp (left, ic, FALSE, FALSE);
8499 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8501 _startLazyDPSEvaluation ();
8502 switch (AOP_SIZE (left))
8504 case 1: /* swap nibbles in byte */
8505 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
8506 emitcode ("swap", "a");
8507 aopPut (result, "a", 0);
8509 case 2: /* swap bytes in word */
8510 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
8512 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
8513 aopPut (result, aopGet (left, 1, FALSE, FALSE, NULL), 0);
8514 aopPut (result, "a", 1);
8516 else if (operandsEqu (left, result))
8519 bool pushedB = FALSE, leftInB = FALSE;
8521 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
8522 if (AOP_NEEDSACC (left) || AOP_NEEDSACC (result))
8525 emitcode ("mov", "b,a");
8529 aopPut (result, aopGet (left, 1, FALSE, FALSE, NULL), 0);
8530 aopPut (result, reg, 1);
8537 aopPut (result, aopGet (left, 1, FALSE, FALSE, NULL), 0);
8538 aopPut (result, aopGet (left, 0, FALSE, FALSE, NULL), 1);
8542 wassertl(FALSE, "unsupported SWAP operand size");
8544 _endLazyDPSEvaluation ();
8546 freeAsmop (result, NULL, ic, TRUE);
8547 freeAsmop (left, NULL, ic, TRUE);
8550 /*-----------------------------------------------------------------*/
8551 /* AccRol - rotate left accumulator by known count */
8552 /*-----------------------------------------------------------------*/
8554 AccRol (int shCount)
8556 shCount &= 0x0007; // shCount : 0..7
8563 emitcode ("rl", "a");
8566 emitcode ("rl", "a");
8567 emitcode ("rl", "a");
8570 emitcode ("swap", "a");
8571 emitcode ("rr", "a");
8574 emitcode ("swap", "a");
8577 emitcode ("swap", "a");
8578 emitcode ("rl", "a");
8581 emitcode ("rr", "a");
8582 emitcode ("rr", "a");
8585 emitcode ("rr", "a");
8590 /*-----------------------------------------------------------------*/
8591 /* AccLsh - left shift accumulator by known count */
8592 /*-----------------------------------------------------------------*/
8594 AccLsh (int shCount)
8599 emitcode ("add", "a,acc");
8600 else if (shCount == 2)
8602 emitcode ("add", "a,acc");
8603 emitcode ("add", "a,acc");
8607 /* rotate left accumulator */
8609 /* and kill the lower order bits */
8610 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
8615 /*-----------------------------------------------------------------*/
8616 /* AccRsh - right shift accumulator by known count */
8617 /*-----------------------------------------------------------------*/
8619 AccRsh (int shCount)
8626 emitcode ("rrc", "a");
8630 /* rotate right accumulator */
8631 AccRol (8 - shCount);
8632 /* and kill the higher order bits */
8633 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
8638 #ifdef BETTER_LITERAL_SHIFT
8639 /*-----------------------------------------------------------------*/
8640 /* AccSRsh - signed right shift accumulator by known count */
8641 /*-----------------------------------------------------------------*/
8643 AccSRsh (int shCount)
8650 emitcode ("mov", "c,acc.7");
8651 emitcode ("rrc", "a");
8653 else if (shCount == 2)
8655 emitcode ("mov", "c,acc.7");
8656 emitcode ("rrc", "a");
8657 emitcode ("mov", "c,acc.7");
8658 emitcode ("rrc", "a");
8662 tlbl = newiTempLabel (NULL);
8663 /* rotate right accumulator */
8664 AccRol (8 - shCount);
8665 /* and kill the higher order bits */
8666 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
8667 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8668 emitcode ("orl", "a,#!constbyte",
8669 (unsigned char) ~SRMask[shCount]);
8676 #ifdef BETTER_LITERAL_SHIFT
8677 /*-----------------------------------------------------------------*/
8678 /* shiftR1Left2Result - shift right one byte from left to result */
8679 /*-----------------------------------------------------------------*/
8681 shiftR1Left2Result (operand * left, int offl,
8682 operand * result, int offr,
8683 int shCount, int sign)
8685 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
8686 /* shift right accumulator */
8691 aopPut (result, "a", offr);
8695 #ifdef BETTER_LITERAL_SHIFT
8696 /*-----------------------------------------------------------------*/
8697 /* shiftL1Left2Result - shift left one byte from left to result */
8698 /*-----------------------------------------------------------------*/
8700 shiftL1Left2Result (operand * left, int offl,
8701 operand * result, int offr, int shCount)
8704 l = aopGet (left, offl, FALSE, FALSE, NULL);
8706 /* shift left accumulator */
8708 aopPut (result, "a", offr);
8712 #ifdef BETTER_LITERAL_SHIFT
8713 /*-----------------------------------------------------------------*/
8714 /* movLeft2Result - move byte from left to result */
8715 /*-----------------------------------------------------------------*/
8717 movLeft2Result (operand * left, int offl,
8718 operand * result, int offr, int sign)
8721 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8723 l = aopGet (left, offl, FALSE, FALSE, NULL);
8725 if (*l == '@' && (IS_AOP_PREG (result)))
8727 emitcode ("mov", "a,%s", l);
8728 aopPut (result, "a", offr);
8734 aopPut (result, l, offr);
8738 /* MSB sign in acc.7 ! */
8739 if (getDataSize (left) == offl + 1)
8742 aopPut (result, "a", offr);
8750 #ifdef BETTER_LITERAL_SHIFT
8751 /*-----------------------------------------------------------------*/
8752 /* AccAXRrl1 - right rotate a:x by 1 */
8753 /*-----------------------------------------------------------------*/
8757 emitcode ("mov", "c,acc.0");
8758 emitcode ("xch", "a,%s", x);
8759 emitcode ("rrc", "a");
8760 emitcode ("xch", "a,%s", x);
8761 emitcode ("rrc", "a");
8765 #ifdef BETTER_LITERAL_SHIFT
8767 /*-----------------------------------------------------------------*/
8768 /* AccAXLrl1 - left rotate a:x by 1 */
8769 /*-----------------------------------------------------------------*/
8773 emitcode ("mov", "c,acc.7");
8774 emitcode ("xch", "a,%s", x);
8775 emitcode ("rlc", "a");
8776 emitcode ("xch", "a,%s", x);
8777 emitcode ("rlc", "a");
8781 #ifdef BETTER_LITERAL_SHIFT
8782 /*-----------------------------------------------------------------*/
8783 /* AccAXRsh1 - right shift c->a:x->c by 1 */
8784 /*-----------------------------------------------------------------*/
8788 emitcode ("rrc", "a");
8789 emitcode ("xch", "a,%s", x);
8790 emitcode ("rrc", "a");
8791 emitcode ("xch", "a,%s", x);
8795 #ifdef BETTER_LITERAL_SHIFT
8796 /*-----------------------------------------------------------------*/
8797 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8798 /*-----------------------------------------------------------------*/
8802 emitcode ("xch", "a,%s", x);
8803 emitcode ("add", "a,acc");
8804 emitcode ("xch", "a,%s", x);
8805 emitcode ("rlc", "a");
8809 #ifdef BETTER_LITERAL_SHIFT
8810 /*-----------------------------------------------------------------*/
8811 /* AccAXLsh - left shift a:x by known count (0..7) */
8812 /*-----------------------------------------------------------------*/
8814 AccAXLsh (char *x, int shCount)
8829 case 5: // AAAAABBB:CCCCCDDD
8831 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8833 emitcode ("anl", "a,#!constbyte",
8834 SLMask[shCount]); // BBB00000:CCCCCDDD
8836 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8838 AccRol (shCount); // DDDCCCCC:BBB00000
8840 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8842 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8844 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8846 emitcode ("anl", "a,#!constbyte",
8847 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8849 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8851 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8854 case 6: // AAAAAABB:CCCCCCDD
8855 emitcode ("anl", "a,#!constbyte",
8856 SRMask[shCount]); // 000000BB:CCCCCCDD
8858 AccAXRrl1 (x); // D000000B:BCCCCCCD
8859 AccAXRrl1 (x); // DD000000:BBCCCCCC
8860 emitcode ("xch", "a,%s", x); // BBCCCCCC:DD000000
8862 emitcode ("mov", "c,acc.0"); // c = B
8863 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8864 emitcode("rrc","a");
8865 emitcode("xch","a,%s", x);
8866 emitcode("rrc","a");
8867 emitcode("mov","c,acc.0"); //<< get correct bit
8868 emitcode("xch","a,%s", x);
8870 emitcode("rrc","a");
8871 emitcode("xch","a,%s", x);
8872 emitcode("rrc","a");
8873 emitcode("xch","a,%s", x);
8876 case 7: // a:x <<= 7
8878 emitcode ("anl", "a,#!constbyte",
8879 SRMask[shCount]); // 0000000B:CCCCCCCD
8881 AccAXRrl1 (x); // D0000000:BCCCCCCC
8883 emitcode ("xch", "a,%s", x); // BCCCCCCC:D0000000
8892 #ifdef BETTER_LITERAL_SHIFT
8894 /*-----------------------------------------------------------------*/
8895 /* AccAXRsh - right shift a:x known count (0..7) */
8896 /*-----------------------------------------------------------------*/
8898 AccAXRsh (char *x, int shCount)
8906 AccAXRsh1 (x); // 0->a:x
8911 AccAXRsh1 (x); // 0->a:x
8914 AccAXRsh1 (x); // 0->a:x
8919 case 5: // AAAAABBB:CCCCCDDD = a:x
8921 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8923 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8925 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8927 emitcode ("anl", "a,#!constbyte",
8928 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8930 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8932 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8934 emitcode ("anl", "a,#!constbyte",
8935 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8937 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8939 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8941 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8944 case 6: // AABBBBBB:CCDDDDDD
8946 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDE
8947 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8949 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8951 emitcode ("anl", "a,#!constbyte",
8952 SRMask[shCount]); // 000000AA:BBBBBBCC
8955 case 7: // ABBBBBBB:CDDDDDDD
8957 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8959 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8961 emitcode ("anl", "a,#!constbyte",
8962 SRMask[shCount]); // 0000000A:BBBBBBBC
8971 #ifdef BETTER_LITERAL_SHIFT
8972 /*-----------------------------------------------------------------*/
8973 /* AccAXRshS - right shift signed a:x known count (0..7) */
8974 /*-----------------------------------------------------------------*/
8976 AccAXRshS (char *x, int shCount)
8984 emitcode ("mov", "c,acc.7");
8985 AccAXRsh1 (x); // s->a:x
8989 emitcode ("mov", "c,acc.7");
8990 AccAXRsh1 (x); // s->a:x
8992 emitcode ("mov", "c,acc.7");
8993 AccAXRsh1 (x); // s->a:x
8998 case 5: // AAAAABBB:CCCCCDDD = a:x
9000 tlbl = newiTempLabel (NULL);
9001 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
9003 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
9005 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
9007 emitcode ("anl", "a,#!constbyte",
9008 SRMask[shCount]); // 000CCCCC:BBBAAAAA
9010 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
9012 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
9014 emitcode ("anl", "a,#!constbyte",
9015 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
9017 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
9019 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
9021 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
9023 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
9024 emitcode ("orl", "a,#!constbyte",
9025 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
9028 break; // SSSSAAAA:BBBCCCCC
9030 case 6: // AABBBBBB:CCDDDDDD
9032 tlbl = newiTempLabel (NULL);
9034 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
9035 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
9037 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
9039 emitcode ("anl", "a,#!constbyte",
9040 SRMask[shCount]); // 000000AA:BBBBBBCC
9042 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
9043 emitcode ("orl", "a,#!constbyte",
9044 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
9048 case 7: // ABBBBBBB:CDDDDDDD
9050 tlbl = newiTempLabel (NULL);
9052 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
9054 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
9056 emitcode ("anl", "a,#!constbyte",
9057 SRMask[shCount]); // 0000000A:BBBBBBBC
9059 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
9060 emitcode ("orl", "a,#!constbyte",
9061 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
9071 #ifdef BETTER_LITERAL_SHIFT
9073 _loadLeftIntoAx(char **lsb,
9079 // Get the initial value from left into a pair of registers.
9080 // MSB must be in A, LSB can be any register.
9082 // If the result is held in registers, it is an optimization
9083 // if the LSB can be held in the register which will hold the,
9084 // result LSB since this saves us from having to copy it into
9085 // the result following AccAXLsh.
9087 // If the result is addressed indirectly, this is not a gain.
9088 if (AOP_NEEDSACC(result))
9092 _startLazyDPSEvaluation();
9093 if (AOP_TYPE(left) == AOP_DPTR2)
9096 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE, NULL));
9097 // get LSB in DP2_RESULT_REG.
9098 leftByte = aopGet (left, offl, FALSE, FALSE, DP2_RESULT_REG);
9099 assert(!strcmp(leftByte, DP2_RESULT_REG));
9103 // get LSB into DP2_RESULT_REG
9104 leftByte = aopGet (left, offl, FALSE, FALSE, NULL);
9105 if (strcmp(leftByte, DP2_RESULT_REG))
9108 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
9111 leftByte = aopGet (left, offl + MSB16, FALSE, FALSE, NULL);
9112 assert(strcmp(leftByte, DP2_RESULT_REG));
9115 _endLazyDPSEvaluation();
9116 *lsb = DP2_RESULT_REG;
9120 if (sameRegs (AOP (result), AOP (left)) &&
9121 ((offl + MSB16) == offr))
9123 /* don't crash result[offr] */
9124 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
9125 emitcode ("xch", "a,%s",
9126 aopGet (left, offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
9130 movLeft2Result (left, offl, result, offr, 0);
9131 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE, NULL));
9133 *lsb = aopGet (result, offr, FALSE, FALSE, DP2_RESULT_REG);
9134 assert(strcmp(*lsb,"a"));
9139 _storeAxResults(char *lsb,
9143 _startLazyDPSEvaluation();
9144 if (AOP_NEEDSACC(result))
9146 /* We have to explicitly update the result LSB.
9148 emitcode ("xch","a,%s", lsb);
9149 aopPut (result, "a", offr);
9150 emitcode ("mov","a,%s", lsb);
9152 if (getDataSize (result) > 1)
9154 aopPut (result, "a", offr + MSB16);
9156 _endLazyDPSEvaluation();
9159 /*-----------------------------------------------------------------*/
9160 /* shiftL2Left2Result - shift left two bytes from left to result */
9161 /*-----------------------------------------------------------------*/
9163 shiftL2Left2Result (operand * left, int offl,
9164 operand * result, int offr, int shCount)
9168 _loadLeftIntoAx(&lsb, left, result, offl, offr);
9170 AccAXLsh (lsb, shCount);
9172 _storeAxResults(lsb, result, offr);
9176 #ifdef BETTER_LITERAL_SHIFT
9177 /*-----------------------------------------------------------------*/
9178 /* shiftR2Left2Result - shift right two bytes from left to result */
9179 /*-----------------------------------------------------------------*/
9181 shiftR2Left2Result (operand * left, int offl,
9182 operand * result, int offr,
9183 int shCount, int sign)
9187 _loadLeftIntoAx(&lsb, left, result, offl, offr);
9189 /* a:x >> shCount (x = lsb(result)) */
9192 AccAXRshS(lsb, shCount);
9196 AccAXRsh(lsb, shCount);
9199 _storeAxResults(lsb, result, offr);
9203 /*-----------------------------------------------------------------*/
9204 /* shiftLLeftOrResult - shift left one byte from left, or to result */
9205 /*-----------------------------------------------------------------*/
9207 shiftLLeftOrResult (operand * left, int offl,
9208 operand * result, int offr, int shCount)
9210 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
9211 /* shift left accumulator */
9213 /* or with result */
9214 emitcode ("orl", "a,%s",
9215 aopGet (result, offr, FALSE, FALSE, DP2_RESULT_REG));
9216 /* back to result */
9217 aopPut (result, "a", offr);
9222 /*-----------------------------------------------------------------*/
9223 /* shiftRLeftOrResult - shift right one byte from left,or to result */
9224 /*-----------------------------------------------------------------*/
9226 shiftRLeftOrResult (operand * left, int offl,
9227 operand * result, int offr, int shCount)
9229 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
9230 /* shift right accumulator */
9232 /* or with result */
9233 emitcode ("orl", "a,%s",
9234 aopGet (result, offr, FALSE, FALSE, DP2_RESULT_REG));
9235 /* back to result */
9236 aopPut (result, "a", offr);
9240 #ifdef BETTER_LITERAL_SHIFT
9241 /*-----------------------------------------------------------------*/
9242 /* genlshOne - left shift a one byte quantity by known count */
9243 /*-----------------------------------------------------------------*/
9245 genlshOne (operand * result, operand * left, int shCount)
9247 D (emitcode (";", "genlshOne"));
9249 shiftL1Left2Result (left, LSB, result, LSB, shCount);
9253 #ifdef BETTER_LITERAL_SHIFT
9254 /*-----------------------------------------------------------------*/
9255 /* genlshTwo - left shift two bytes by known amount != 0 */
9256 /*-----------------------------------------------------------------*/
9258 genlshTwo (operand * result, operand * left, int shCount)
9262 D (emitcode (";", "genlshTwo"));
9264 size = getDataSize (result);
9266 /* if shCount >= 8 */
9271 _startLazyDPSEvaluation();
9277 _endLazyDPSEvaluation();
9278 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
9279 aopPut (result, zero, LSB);
9283 movLeft2Result (left, LSB, result, MSB16, 0);
9284 aopPut (result, zero, LSB);
9285 _endLazyDPSEvaluation();
9290 aopPut (result, zero, LSB);
9291 _endLazyDPSEvaluation();
9295 /* 1 <= shCount <= 7 */
9299 shiftL1Left2Result (left, LSB, result, LSB, shCount);
9301 shiftL2Left2Result (left, LSB, result, LSB, shCount);
9308 /*-----------------------------------------------------------------*/
9309 /* shiftLLong - shift left one long from left to result */
9310 /* offl = LSB or MSB16 */
9311 /*-----------------------------------------------------------------*/
9313 shiftLLong (operand * left, operand * result, int offr)
9316 int size = AOP_SIZE (result);
9318 if (size >= LSB + offr)
9320 l = aopGet (left, LSB, FALSE, FALSE, NULL);
9322 emitcode ("add", "a,acc");
9323 if (sameRegs (AOP (left), AOP (result)) &&
9324 size >= MSB16 + offr && offr != LSB)
9325 emitcode ("xch", "a,%s",
9326 aopGet (left, LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
9328 aopPut (result, "a", LSB + offr);
9331 if (size >= MSB16 + offr)
9333 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
9335 l = aopGet (left, MSB16, FALSE, FALSE, TRUE);
9338 emitcode ("rlc", "a");
9339 if (sameRegs (AOP (left), AOP (result)) &&
9340 size >= MSB24 + offr && offr != LSB)
9341 emitcode ("xch", "a,%s",
9342 aopGet (left, MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
9344 aopPut (result, "a", MSB16 + offr);
9347 if (size >= MSB24 + offr)
9349 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
9351 l = aopGet (left, MSB24, FALSE, FALSE, NULL);
9354 emitcode ("rlc", "a");
9355 if (sameRegs (AOP (left), AOP (result)) &&
9356 size >= MSB32 + offr && offr != LSB)
9357 emitcode ("xch", "a,%s",
9358 aopGet (left, MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
9360 aopPut (result, "a", MSB24 + offr);
9363 if (size > MSB32 + offr)
9365 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
9367 l = aopGet (left, MSB32, FALSE, FALSE, NULL);
9370 emitcode ("rlc", "a");
9371 aopPut (result, "a", MSB32 + offr);
9374 aopPut (result, zero, LSB);
9380 /*-----------------------------------------------------------------*/
9381 /* genlshFour - shift four byte by a known amount != 0 */
9382 /*-----------------------------------------------------------------*/
9384 genlshFour (operand * result, operand * left, int shCount)
9388 D (emitcode (";", "genlshFour"));
9390 size = AOP_SIZE (result);
9392 /* if shifting more that 3 bytes */
9397 /* lowest order of left goes to the highest
9398 order of the destination */
9399 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
9401 movLeft2Result (left, LSB, result, MSB32, 0);
9402 aopPut (result, zero, LSB);
9403 aopPut (result, zero, MSB16);
9404 aopPut (result, zero, MSB24);
9408 /* more than two bytes */
9409 else if (shCount >= 16)
9411 /* lower order two bytes goes to higher order two bytes */
9413 /* if some more remaining */
9415 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
9418 movLeft2Result (left, MSB16, result, MSB32, 0);
9419 movLeft2Result (left, LSB, result, MSB24, 0);
9421 aopPut (result, zero, MSB16);
9422 aopPut (result, zero, LSB);
9426 /* if more than 1 byte */
9427 else if (shCount >= 8)
9429 /* lower order three bytes goes to higher order three bytes */
9434 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
9436 movLeft2Result (left, LSB, result, MSB16, 0);
9442 movLeft2Result (left, MSB24, result, MSB32, 0);
9443 movLeft2Result (left, MSB16, result, MSB24, 0);
9444 movLeft2Result (left, LSB, result, MSB16, 0);
9445 aopPut (result, zero, LSB);
9447 else if (shCount == 1)
9448 shiftLLong (left, result, MSB16);
9451 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
9452 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
9453 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
9454 aopPut (result, zero, LSB);
9459 /* 1 <= shCount <= 7 */
9460 else if (shCount <= 2)
9462 shiftLLong (left, result, LSB);
9464 shiftLLong (result, result, LSB);
9466 /* 3 <= shCount <= 7, optimize */
9469 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
9470 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
9471 shiftL2Left2Result (left, LSB, result, LSB, shCount);
9476 #ifdef BETTER_LITERAL_SHIFT
9477 /*-----------------------------------------------------------------*/
9478 /* genLeftShiftLiteral - left shifting by known count */
9479 /*-----------------------------------------------------------------*/
9481 genLeftShiftLiteral (operand * left,
9486 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9489 size = getSize (operandType (result));
9491 D (emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
9493 /* We only handle certain easy cases so far. */
9495 && (shCount < (size * 8))
9499 D(emitcode (";", "genLeftShiftLiteral wimping out"););
9503 freeAsmop (right, NULL, ic, TRUE);
9505 aopOp(left, ic, FALSE, FALSE);
9506 aopOp(result, ic, FALSE, AOP_USESDPTR(left));
9509 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
9511 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
9512 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
9514 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
9517 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
9519 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
9520 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
9522 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
9528 emitcode ("; shift left ", "result %d, left %d", size,
9532 /* I suppose that the left size >= result size */
9535 _startLazyDPSEvaluation();
9538 movLeft2Result (left, size, result, size, 0);
9540 _endLazyDPSEvaluation();
9542 else if (shCount >= (size * 8))
9544 _startLazyDPSEvaluation();
9547 aopPut (result, zero, size);
9549 _endLazyDPSEvaluation();
9556 genlshOne (result, left, shCount);
9560 genlshTwo (result, left, shCount);
9564 genlshFour (result, left, shCount);
9568 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9569 "*** ack! mystery literal shift!\n");
9573 freeAsmop (result, NULL, ic, TRUE);
9574 freeAsmop (left, NULL, ic, TRUE);
9579 /*-----------------------------------------------------------------*/
9580 /* genLeftShift - generates code for left shifting */
9581 /*-----------------------------------------------------------------*/
9583 genLeftShift (iCode * ic)
9585 operand *left, *right, *result;
9588 symbol *tlbl, *tlbl1;
9591 D (emitcode (";", "genLeftShift"));
9593 right = IC_RIGHT (ic);
9594 left = IC_LEFT (ic);
9595 result = IC_RESULT (ic);
9597 aopOp (right, ic, FALSE, FALSE);
9600 #ifdef BETTER_LITERAL_SHIFT
9601 /* if the shift count is known then do it
9602 as efficiently as possible */
9603 if (AOP_TYPE (right) == AOP_LIT)
9605 if (genLeftShiftLiteral (left, right, result, ic))
9612 /* shift count is unknown then we have to form
9613 a loop get the loop count in B : Note: we take
9614 only the lower order byte since shifting
9615 more that 32 bits make no sense anyway, ( the
9616 largest size of an object can be only 32 bits ) */
9619 if (AOP_TYPE (right) == AOP_LIT)
9621 /* Really should be handled by genLeftShiftLiteral,
9622 * but since I'm too lazy to fix that today, at least we can make
9623 * some small improvement.
9625 emitcode("mov", "b,#!constbyte",
9626 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9630 MOVB (aopGet (right, 0, FALSE, FALSE, "b"));
9631 emitcode ("inc", "b");
9633 freeAsmop (right, NULL, ic, TRUE);
9634 aopOp (left, ic, FALSE, FALSE);
9635 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9637 /* now move the left to the result if they are not the same */
9638 if (!sameRegs (AOP (left), AOP (result)) &&
9639 AOP_SIZE (result) > 1)
9642 size = AOP_SIZE (result);
9644 _startLazyDPSEvaluation ();
9647 l = aopGet (left, offset, FALSE, TRUE, NULL);
9648 if (*l == '@' && (IS_AOP_PREG (result)))
9651 emitcode ("mov", "a,%s", l);
9652 aopPut (result, "a", offset);
9655 aopPut (result, l, offset);
9658 _endLazyDPSEvaluation ();
9661 tlbl = newiTempLabel (NULL);
9662 size = AOP_SIZE (result);
9664 tlbl1 = newiTempLabel (NULL);
9666 /* if it is only one byte then */
9669 symbol *tlbl1 = newiTempLabel (NULL);
9671 l = aopGet (left, 0, FALSE, FALSE, NULL);
9673 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9675 emitcode ("add", "a,acc");
9677 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9679 aopPut (result, "a", 0);
9683 reAdjustPreg (AOP (result));
9685 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9687 l = aopGet (result, offset, FALSE, FALSE, NULL);
9689 emitcode ("add", "a,acc");
9690 aopPut (result, "a", offset++);
9691 _startLazyDPSEvaluation ();
9694 l = aopGet (result, offset, FALSE, FALSE, NULL);
9696 emitcode ("rlc", "a");
9697 aopPut (result, "a", offset++);
9699 _endLazyDPSEvaluation ();
9700 reAdjustPreg (AOP (result));
9703 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9706 freeAsmop (result, NULL, ic, TRUE);
9707 freeAsmop (left, NULL, ic, TRUE);
9710 #ifdef BETTER_LITERAL_SHIFT
9711 /*-----------------------------------------------------------------*/
9712 /* genrshOne - right shift a one byte quantity by known count */
9713 /*-----------------------------------------------------------------*/
9715 genrshOne (operand * result, operand * left,
9716 int shCount, int sign)
9718 D (emitcode (";", "genrshOne"));
9720 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9724 #ifdef BETTER_LITERAL_SHIFT
9725 /*-----------------------------------------------------------------*/
9726 /* genrshTwo - right shift two bytes by known amount != 0 */
9727 /*-----------------------------------------------------------------*/
9729 genrshTwo (operand * result, operand * left,
9730 int shCount, int sign)
9732 D (emitcode (";", "genrshTwo"));
9734 /* if shCount >= 8 */
9738 _startLazyDPSEvaluation();
9740 shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
9742 movLeft2Result (left, MSB16, result, LSB, sign);
9743 addSign (result, MSB16, sign);
9744 _endLazyDPSEvaluation();
9747 /* 1 <= shCount <= 7 */
9749 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9753 /*-----------------------------------------------------------------*/
9754 /* shiftRLong - shift right one long from left to result */
9755 /* offl = LSB or MSB16 */
9756 /*-----------------------------------------------------------------*/
9758 shiftRLong (operand * left, int offl,
9759 operand * result, int sign)
9761 bool overlapping = regsInCommon (left, result) || operandsEqu(left, result);
9763 if (overlapping && offl>1)
9765 // we are in big trouble, but this shouldn't happen
9766 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9769 MOVA (aopGet (left, MSB32, FALSE, FALSE, NULL));
9776 emitcode ("rlc", "a");
9777 emitcode ("subb", "a,acc");
9778 emitcode ("xch", "a,%s",
9779 aopGet(left, MSB32, FALSE, FALSE, DP2_RESULT_REG));
9783 aopPut (result, zero, MSB32);
9789 emitcode ("clr", "c");
9793 emitcode ("mov", "c,acc.7");
9796 emitcode ("rrc", "a");
9798 if (overlapping && offl==MSB16)
9800 emitcode ("xch", "a,%s", aopGet (left, MSB24, FALSE, FALSE, DP2_RESULT_REG));
9804 aopPut (result, "a", MSB32 - offl);
9805 MOVA (aopGet (left, MSB24, FALSE, FALSE, NULL));
9808 emitcode ("rrc", "a");
9810 if (overlapping && offl==MSB16)
9812 emitcode ("xch", "a,%s", aopGet (left, MSB16, FALSE, FALSE, DP2_RESULT_REG));
9816 aopPut (result, "a", MSB24 - offl);
9817 MOVA (aopGet (left, MSB16, FALSE, FALSE, NULL));
9820 emitcode ("rrc", "a");
9823 aopPut (result, "a", MSB16 - offl);
9827 if (overlapping && offl==MSB16)
9829 emitcode ("xch", "a,%s", aopGet (left, LSB, FALSE, FALSE, DP2_RESULT_REG));
9833 aopPut (result, "a", MSB16 - offl);
9834 MOVA (aopGet (left, LSB, FALSE, FALSE, NULL));
9836 emitcode ("rrc", "a");
9837 aopPut (result, "a", LSB);
9841 /*-----------------------------------------------------------------*/
9842 /* genrshFour - shift four byte by a known amount != 0 */
9843 /*-----------------------------------------------------------------*/
9845 genrshFour (operand * result, operand * left,
9846 int shCount, int sign)
9848 D (emitcode (";", "genrshFour"));
9850 /* if shifting more that 3 bytes */
9854 _startLazyDPSEvaluation();
9856 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9858 movLeft2Result (left, MSB32, result, LSB, sign);
9859 addSign (result, MSB16, sign);
9860 _endLazyDPSEvaluation();
9862 else if (shCount >= 16)
9865 _startLazyDPSEvaluation();
9867 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9870 movLeft2Result (left, MSB24, result, LSB, 0);
9871 movLeft2Result (left, MSB32, result, MSB16, sign);
9873 addSign (result, MSB24, sign);
9874 _endLazyDPSEvaluation();
9876 else if (shCount >= 8)
9879 _startLazyDPSEvaluation();
9882 shiftRLong (left, MSB16, result, sign);
9884 else if (shCount == 0)
9886 movLeft2Result (left, MSB16, result, LSB, 0);
9887 movLeft2Result (left, MSB24, result, MSB16, 0);
9888 movLeft2Result (left, MSB32, result, MSB24, sign);
9889 addSign (result, MSB32, sign);
9893 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9894 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9895 /* the last shift is signed */
9896 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9897 addSign (result, MSB32, sign);
9899 _endLazyDPSEvaluation();
9903 /* 1 <= shCount <= 7 */
9906 shiftRLong (left, LSB, result, sign);
9908 shiftRLong (result, LSB, result, sign);
9912 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9913 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9914 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9919 #ifdef BETTER_LITERAL_SHIFT
9920 /*-----------------------------------------------------------------*/
9921 /* genRightShiftLiteral - right shifting by known count */
9922 /*-----------------------------------------------------------------*/
9924 genRightShiftLiteral (operand * left,
9930 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9933 size = getSize (operandType (result));
9935 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
9937 /* We only handle certain easy cases so far. */
9939 && (shCount < (size * 8))
9944 D(emitcode (";", "genRightShiftLiteral wimping out"););
9948 freeAsmop (right, NULL, ic, TRUE);
9950 aopOp (left, ic, FALSE, FALSE);
9951 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9954 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9958 /* test the LEFT size !!! */
9960 /* I suppose that the left size >= result size */
9963 size = getDataSize (result);
9964 _startLazyDPSEvaluation();
9966 movLeft2Result (left, size, result, size, 0);
9967 _endLazyDPSEvaluation();
9969 else if (shCount >= (size * 8))
9973 /* get sign in acc.7 */
9974 MOVA (aopGet (left, size - 1, FALSE, FALSE, NULL));
9976 addSign (result, LSB, sign);
9983 genrshOne (result, left, shCount, sign);
9987 genrshTwo (result, left, shCount, sign);
9991 genrshFour (result, left, shCount, sign);
9998 freeAsmop (result, NULL, ic, TRUE);
9999 freeAsmop (left, NULL, ic, TRUE);
10005 /*-----------------------------------------------------------------*/
10006 /* genSignedRightShift - right shift of signed number */
10007 /*-----------------------------------------------------------------*/
10009 genSignedRightShift (iCode * ic)
10011 operand *right, *left, *result;
10014 symbol *tlbl, *tlbl1;
10017 D (emitcode (";", "genSignedRightShift"));
10019 /* we do it the hard way put the shift count in b
10020 and loop thru preserving the sign */
10022 right = IC_RIGHT (ic);
10023 left = IC_LEFT (ic);
10024 result = IC_RESULT (ic);
10026 aopOp (right, ic, FALSE, FALSE);
10028 #ifdef BETTER_LITERAL_SHIFT
10029 if (AOP_TYPE (right) == AOP_LIT)
10031 if (genRightShiftLiteral (left, right, result, ic, 1))
10037 /* shift count is unknown then we have to form
10038 a loop get the loop count in B : Note: we take
10039 only the lower order byte since shifting
10040 more that 32 bits make no sense anyway, ( the
10041 largest size of an object can be only 32 bits ) */
10043 pushedB = pushB ();
10044 if (AOP_TYPE (right) == AOP_LIT)
10046 /* Really should be handled by genRightShiftLiteral,
10047 * but since I'm too lazy to fix that today, at least we can make
10048 * some small improvement.
10050 emitcode("mov", "b,#!constbyte",
10051 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
10055 MOVB (aopGet (right, 0, FALSE, FALSE, "b"));
10056 emitcode ("inc", "b");
10058 freeAsmop (right, NULL, ic, TRUE);
10059 aopOp (left, ic, FALSE, FALSE);
10060 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
10062 /* now move the left to the result if they are not the
10064 if (!sameRegs (AOP (left), AOP (result)) &&
10065 AOP_SIZE (result) > 1)
10068 size = AOP_SIZE (result);
10070 _startLazyDPSEvaluation ();
10073 l = aopGet (left, offset, FALSE, TRUE, NULL);
10074 if (*l == '@' && IS_AOP_PREG (result))
10077 emitcode ("mov", "a,%s", l);
10078 aopPut (result, "a", offset);
10081 aopPut (result, l, offset);
10084 _endLazyDPSEvaluation ();
10087 /* mov the highest order bit to OVR */
10088 tlbl = newiTempLabel (NULL);
10089 tlbl1 = newiTempLabel (NULL);
10091 size = AOP_SIZE (result);
10093 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
10094 emitcode ("rlc", "a");
10095 emitcode ("mov", "ov,c");
10096 /* if it is only one byte then */
10099 l = aopGet (left, 0, FALSE, FALSE, NULL);
10101 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
10103 emitcode ("mov", "c,ov");
10104 emitcode ("rrc", "a");
10106 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
10108 aopPut (result, "a", 0);
10112 reAdjustPreg (AOP (result));
10113 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
10115 emitcode ("mov", "c,ov");
10116 _startLazyDPSEvaluation ();
10119 l = aopGet (result, offset, FALSE, FALSE, NULL);
10121 emitcode ("rrc", "a");
10122 aopPut (result, "a", offset--);
10124 _endLazyDPSEvaluation ();
10125 reAdjustPreg (AOP (result));
10127 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
10131 freeAsmop (result, NULL, ic, TRUE);
10132 freeAsmop (left, NULL, ic, TRUE);
10135 /*-----------------------------------------------------------------*/
10136 /* genRightShift - generate code for right shifting */
10137 /*-----------------------------------------------------------------*/
10139 genRightShift (iCode * ic)
10141 operand *right, *left, *result;
10145 symbol *tlbl, *tlbl1;
10148 D (emitcode (";", "genRightShift"));
10150 /* if signed then we do it the hard way preserve the
10151 sign bit moving it inwards */
10152 letype = getSpec (operandType (IC_LEFT (ic)));
10154 if (!SPEC_USIGN (letype))
10156 genSignedRightShift (ic);
10160 /* signed & unsigned types are treated the same : i.e. the
10161 signed is NOT propagated inwards : quoting from the
10162 ANSI - standard : "for E1 >> E2, is equivalent to division
10163 by 2**E2 if unsigned or if it has a non-negative value,
10164 otherwise the result is implementation defined ", MY definition
10165 is that the sign does not get propagated */
10167 right = IC_RIGHT (ic);
10168 left = IC_LEFT (ic);
10169 result = IC_RESULT (ic);
10171 aopOp (right, ic, FALSE, FALSE);
10173 #ifdef BETTER_LITERAL_SHIFT
10174 /* if the shift count is known then do it
10175 as efficiently as possible */
10176 if (AOP_TYPE (right) == AOP_LIT)
10178 if (genRightShiftLiteral (left, right, result, ic, 0))
10185 /* shift count is unknown then we have to form
10186 a loop get the loop count in B : Note: we take
10187 only the lower order byte since shifting
10188 more that 32 bits make no sense anyway, ( the
10189 largest size of an object can be only 32 bits ) */
10191 pushedB = pushB ();
10192 if (AOP_TYPE (right) == AOP_LIT)
10194 /* Really should be handled by genRightShiftLiteral,
10195 * but since I'm too lazy to fix that today, at least we can make
10196 * some small improvement.
10198 emitcode("mov", "b,#!constbyte",
10199 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
10203 MOVB (aopGet (right, 0, FALSE, FALSE, "b"));
10204 emitcode ("inc", "b");
10206 freeAsmop (right, NULL, ic, TRUE);
10207 aopOp (left, ic, FALSE, FALSE);
10208 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
10210 /* now move the left to the result if they are not the
10212 if (!sameRegs (AOP (left), AOP (result)) &&
10213 AOP_SIZE (result) > 1)
10215 size = AOP_SIZE (result);
10217 _startLazyDPSEvaluation ();
10220 l = aopGet (left, offset, FALSE, TRUE, NULL);
10221 if (*l == '@' && IS_AOP_PREG (result))
10224 emitcode ("mov", "a,%s", l);
10225 aopPut (result, "a", offset);
10228 aopPut (result, l, offset);
10231 _endLazyDPSEvaluation ();
10234 tlbl = newiTempLabel (NULL);
10235 tlbl1 = newiTempLabel (NULL);
10236 size = AOP_SIZE (result);
10239 /* if it is only one byte then */
10242 l = aopGet (left, 0, FALSE, FALSE, NULL);
10244 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
10247 emitcode ("rrc", "a");
10249 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
10251 aopPut (result, "a", 0);
10255 reAdjustPreg (AOP (result));
10256 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
10259 _startLazyDPSEvaluation ();
10262 l = aopGet (result, offset, FALSE, FALSE, NULL);
10264 emitcode ("rrc", "a");
10265 aopPut (result, "a", offset--);
10267 _endLazyDPSEvaluation ();
10268 reAdjustPreg (AOP (result));
10271 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
10275 freeAsmop (result, NULL, ic, TRUE);
10276 freeAsmop (left, NULL, ic, TRUE);
10279 /*-----------------------------------------------------------------*/
10280 /* emitPtrByteGet - emits code to get a byte into A through a */
10281 /* pointer register (R0, R1, or DPTR). The */
10282 /* original value of A can be preserved in B. */
10283 /*-----------------------------------------------------------------*/
10285 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
10292 emitcode ("mov", "b,a");
10293 emitcode ("mov", "a,@%s", rname);
10298 emitcode ("mov", "b,a");
10299 emitcode ("movx", "a,@%s", rname);
10304 emitcode ("mov", "b,a");
10305 emitcode ("movx", "a,@dptr");
10310 emitcode ("mov", "b,a");
10311 emitcode ("clr", "a");
10312 emitcode ("movc", "a,@a+dptr");
10318 emitcode ("push", "b");
10319 emitcode ("push", "acc");
10321 emitcode ("lcall", "__gptrget");
10323 emitcode ("pop", "b");
10328 /*-----------------------------------------------------------------*/
10329 /* emitPtrByteSet - emits code to set a byte from src through a */
10330 /* pointer register (R0, R1, or DPTR). */
10331 /*-----------------------------------------------------------------*/
10333 emitPtrByteSet (char *rname, int p_type, char *src)
10342 emitcode ("mov", "@%s,a", rname);
10345 emitcode ("mov", "@%s,%s", rname, src);
10350 emitcode ("movx", "@%s,a", rname);
10355 emitcode ("movx", "@dptr,a");
10360 emitcode ("lcall", "__gptrput");
10365 /*-----------------------------------------------------------------*/
10366 /* genUnpackBits - generates code for unpacking bits */
10367 /*-----------------------------------------------------------------*/
10369 genUnpackBits (operand * result, char *rname, int ptype)
10371 int offset = 0; /* result byte offset */
10372 int rsize; /* result size */
10373 int rlen = 0; /* remaining bitfield length */
10374 sym_link *etype; /* bitfield type information */
10375 int blen; /* bitfield length */
10376 int bstr; /* bitfield starting bit within byte */
10378 D(emitcode (";", "genUnpackBits"));
10380 etype = getSpec (operandType (result));
10381 rsize = getSize (operandType (result));
10382 blen = SPEC_BLEN (etype);
10383 bstr = SPEC_BSTR (etype);
10385 /* If the bitfield length is less than a byte */
10388 emitPtrByteGet (rname, ptype, FALSE);
10390 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
10391 if (!SPEC_USIGN (etype))
10393 /* signed bitfield */
10394 symbol *tlbl = newiTempLabel (NULL);
10396 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
10397 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
10400 aopPut (result, "a", offset++);
10404 /* Bit field did not fit in a byte. Copy all
10405 but the partial byte at the end. */
10406 for (rlen=blen;rlen>=8;rlen-=8)
10408 emitPtrByteGet (rname, ptype, FALSE);
10409 aopPut (result, "a", offset++);
10411 emitcode ("inc", "%s", rname);
10414 /* Handle the partial byte at the end */
10417 emitPtrByteGet (rname, ptype, FALSE);
10418 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
10419 if (!SPEC_USIGN (etype))
10421 /* signed bitfield */
10422 symbol *tlbl = newiTempLabel (NULL);
10424 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
10425 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
10428 aopPut (result, "a", offset++);
10432 if (offset < rsize)
10436 if (SPEC_USIGN (etype))
10440 /* signed bitfield: sign extension with 0x00 or 0xff */
10441 emitcode ("rlc", "a");
10442 emitcode ("subb", "a,acc");
10448 aopPut (result, source, offset++);
10453 /*-----------------------------------------------------------------*/
10454 /* genDataPointerGet - generates code when ptr offset is known */
10455 /*-----------------------------------------------------------------*/
10457 genDataPointerGet (operand * left,
10463 int size, offset = 0;
10464 aopOp (result, ic, TRUE, FALSE);
10466 /* get the string representation of the name */
10467 l = aopGet (left, 0, FALSE, TRUE, NULL);
10468 size = AOP_SIZE (result);
10469 _startLazyDPSEvaluation ();
10474 SNPRINTF (buffer, sizeof(buffer),
10475 "(%s + %d)", l + 1, offset);
10479 SNPRINTF (buffer, sizeof(buffer),
10482 aopPut (result, buffer, offset++);
10484 _endLazyDPSEvaluation ();
10486 freeAsmop (result, NULL, ic, TRUE);
10487 freeAsmop (left, NULL, ic, TRUE);
10490 /*-----------------------------------------------------------------*/
10491 /* genNearPointerGet - emitcode for near pointer fetch */
10492 /*-----------------------------------------------------------------*/
10494 genNearPointerGet (operand * left,
10502 sym_link *rtype, *retype, *letype;
10503 sym_link *ltype = operandType (left);
10506 rtype = operandType (result);
10507 retype = getSpec (rtype);
10508 letype = getSpec (ltype);
10510 aopOp (left, ic, FALSE, FALSE);
10512 /* if left is rematerialisable and
10513 result is not bitfield variable type and
10514 the left is pointer to data space i.e
10515 lower 128 bytes of space */
10516 if (AOP_TYPE (left) == AOP_IMMD &&
10517 !IS_BITFIELD (retype) &&
10518 !IS_BITFIELD (letype) &&
10519 DCL_TYPE (ltype) == POINTER)
10521 genDataPointerGet (left, result, ic);
10525 /* if the value is already in a pointer register
10526 then don't need anything more */
10527 if (!AOP_INPREG (AOP (left)))
10529 /* otherwise get a free pointer register */
10530 aop = newAsmop (0);
10531 preg = getFreePtr (ic, &aop, FALSE);
10532 emitcode ("mov", "%s,%s",
10534 aopGet (left, 0, FALSE, TRUE, DP2_RESULT_REG));
10535 rname = preg->name;
10538 rname = aopGet (left, 0, FALSE, FALSE, DP2_RESULT_REG);
10540 freeAsmop (left, NULL, ic, TRUE);
10541 aopOp (result, ic, FALSE, FALSE);
10543 /* if bitfield then unpack the bits */
10544 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10545 genUnpackBits (result, rname, POINTER);
10548 /* we have can just get the values */
10549 int size = AOP_SIZE (result);
10554 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
10557 emitcode ("mov", "a,@%s", rname);
10558 aopPut (result, "a", offset);
10562 SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
10563 aopPut (result, buffer, offset);
10567 emitcode ("inc", "%s", rname);
10571 /* now some housekeeping stuff */
10572 if (aop) /* we had to allocate for this iCode */
10574 if (pi) { /* post increment present */
10575 aopPut (left, rname, 0);
10577 freeAsmop (NULL, aop, ic, TRUE);
10581 /* we did not allocate which means left
10582 already in a pointer register, then
10583 if size > 0 && this could be used again
10584 we have to point it back to where it
10586 if (AOP_SIZE (result) > 1 &&
10587 !OP_SYMBOL (left)->remat &&
10588 (OP_SYMBOL (left)->liveTo > ic->seq ||
10592 int size = AOP_SIZE (result) - 1;
10594 emitcode ("dec", "%s", rname);
10599 freeAsmop (result, NULL, ic, TRUE);
10600 if (pi) pi->generated = 1;
10603 /*-----------------------------------------------------------------*/
10604 /* genPagedPointerGet - emitcode for paged pointer fetch */
10605 /*-----------------------------------------------------------------*/
10607 genPagedPointerGet (operand * left,
10615 sym_link *rtype, *retype, *letype;
10617 rtype = operandType (result);
10618 retype = getSpec (rtype);
10619 letype = getSpec (operandType (left));
10620 aopOp (left, ic, FALSE, FALSE);
10622 /* if the value is already in a pointer register
10623 then don't need anything more */
10624 if (!AOP_INPREG (AOP (left)))
10626 /* otherwise get a free pointer register */
10627 aop = newAsmop (0);
10628 preg = getFreePtr (ic, &aop, FALSE);
10629 emitcode ("mov", "%s,%s",
10631 aopGet (left, 0, FALSE, TRUE, NULL));
10632 rname = preg->name;
10635 rname = aopGet (left, 0, FALSE, FALSE, NULL);
10637 freeAsmop (left, NULL, ic, TRUE);
10638 aopOp (result, ic, FALSE, FALSE);
10640 /* if bitfield then unpack the bits */
10641 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10642 genUnpackBits (result, rname, PPOINTER);
10645 /* we have can just get the values */
10646 int size = AOP_SIZE (result);
10652 emitcode ("movx", "a,@%s", rname);
10653 aopPut (result, "a", offset);
10658 emitcode ("inc", "%s", rname);
10662 /* now some housekeeping stuff */
10663 if (aop) /* we had to allocate for this iCode */
10666 aopPut (left, rname, 0);
10667 freeAsmop (NULL, aop, ic, TRUE);
10671 /* we did not allocate which means left
10672 already in a pointer register, then
10673 if size > 0 && this could be used again
10674 we have to point it back to where it
10676 if (AOP_SIZE (result) > 1 &&
10677 !OP_SYMBOL (left)->remat &&
10678 (OP_SYMBOL (left)->liveTo > ic->seq ||
10682 int size = AOP_SIZE (result) - 1;
10684 emitcode ("dec", "%s", rname);
10689 freeAsmop (result, NULL, ic, TRUE);
10690 if (pi) pi->generated = 1;
10693 /*-----------------------------------------------------------------*/
10694 /* genFarPointerGet - get value from far space */
10695 /*-----------------------------------------------------------------*/
10697 genFarPointerGet (operand * left,
10698 operand * result, iCode * ic, iCode *pi)
10700 int size, offset, dopi=1;
10701 sym_link *retype = getSpec (operandType (result));
10702 sym_link *letype = getSpec (operandType (left));
10703 D (emitcode (";", "genFarPointerGet"););
10705 aopOp (left, ic, FALSE, FALSE);
10707 /* if the operand is already in dptr
10708 then we do nothing else we move the value to dptr */
10709 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
10711 /* if this is rematerializable */
10712 if (AOP_TYPE (left) == AOP_IMMD)
10714 emitcode ("mov", "dptr,%s", aopGet (left, 0, TRUE, FALSE, NULL));
10718 /* we need to get it byte by byte */
10719 _startLazyDPSEvaluation ();
10720 if (AOP_TYPE (left) != AOP_DPTR)
10722 emitcode ("mov", "dpl,%s", aopGet (left, 0, FALSE, FALSE, NULL));
10723 emitcode ("mov", "dph,%s", aopGet (left, 1, FALSE, FALSE, NULL));
10724 if (options.model == MODEL_FLAT24)
10725 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10729 /* We need to generate a load to DPTR indirect through DPTR. */
10730 D (emitcode (";", "genFarPointerGet -- indirection special case."););
10731 emitcode ("push", "%s", aopGet (left, 0, FALSE, TRUE, NULL));
10732 emitcode ("push", "%s", aopGet (left, 1, FALSE, TRUE, NULL));
10733 if (options.model == MODEL_FLAT24)
10734 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10735 emitcode ("pop", "dph");
10736 emitcode ("pop", "dpl");
10739 _endLazyDPSEvaluation ();
10742 /* so dptr now contains the address */
10743 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10745 /* if bit then unpack */
10746 if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
10747 if (AOP_INDPTRn(left)) {
10748 genSetDPTR(AOP(left)->aopu.dptr);
10750 genUnpackBits (result, "dptr", FPOINTER);
10751 if (AOP_INDPTRn(left)) {
10756 size = AOP_SIZE (result);
10759 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10761 genSetDPTR(AOP(left)->aopu.dptr);
10762 emitcode ("movx", "a,@dptr");
10763 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10764 emitcode ("inc", "dptr");
10766 aopPut (result, "a", offset++);
10769 _startLazyDPSEvaluation ();
10771 if (AOP_INDPTRn(left)) {
10772 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++);
10784 _endLazyDPSEvaluation ();
10787 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10788 if (!AOP_INDPTRn(left)) {
10789 _startLazyDPSEvaluation ();
10790 aopPut (left, "dpl", 0);
10791 aopPut (left, "dph", 1);
10792 if (options.model == MODEL_FLAT24)
10793 aopPut (left, "dpx", 2);
10794 _endLazyDPSEvaluation ();
10797 } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) &&
10798 AOP_SIZE(result) > 1 &&
10800 (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
10802 size = AOP_SIZE (result) - 1;
10803 if (AOP_INDPTRn(left)) {
10804 genSetDPTR(AOP(left)->aopu.dptr);
10806 while (size--) emitcode ("lcall","__decdptr");
10807 if (AOP_INDPTRn(left)) {
10812 freeAsmop (result, NULL, ic, TRUE);
10813 freeAsmop (left, NULL, ic, TRUE);
10816 /*-----------------------------------------------------------------*/
10817 /* genCodePointerGet - get value from code space */
10818 /*-----------------------------------------------------------------*/
10820 genCodePointerGet (operand * left,
10821 operand * result, iCode * ic, iCode *pi)
10823 int size, offset, dopi=1;
10824 sym_link *retype = getSpec (operandType (result));
10826 aopOp (left, ic, FALSE, FALSE);
10828 /* if the operand is already in dptr
10829 then we do nothing else we move the value to dptr */
10830 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
10832 /* if this is rematerializable */
10833 if (AOP_TYPE (left) == AOP_IMMD)
10835 emitcode ("mov", "dptr,%s", aopGet (left, 0, TRUE, FALSE, NULL));
10838 { /* we need to get it byte by byte */
10839 _startLazyDPSEvaluation ();
10840 if (AOP_TYPE (left) != AOP_DPTR)
10842 emitcode ("mov", "dpl,%s", aopGet (left, 0, FALSE, FALSE, NULL));
10843 emitcode ("mov", "dph,%s", aopGet (left, 1, FALSE, FALSE, NULL));
10844 if (options.model == MODEL_FLAT24)
10845 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10849 /* We need to generate a load to DPTR indirect through DPTR. */
10850 D (emitcode (";", "gencodePointerGet -- indirection special case."););
10851 emitcode ("push", "%s", aopGet (left, 0, FALSE, TRUE, NULL));
10852 emitcode ("push", "%s", aopGet (left, 1, FALSE, TRUE, NULL));
10853 if (options.model == MODEL_FLAT24)
10854 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10855 emitcode ("pop", "dph");
10856 emitcode ("pop", "dpl");
10859 _endLazyDPSEvaluation ();
10862 /* so dptr now contains the address */
10863 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10865 /* if bit then unpack */
10866 if (IS_BITFIELD (retype)) {
10867 if (AOP_INDPTRn(left)) {
10868 genSetDPTR(AOP(left)->aopu.dptr);
10870 genUnpackBits (result, "dptr", CPOINTER);
10871 if (AOP_INDPTRn(left)) {
10876 size = AOP_SIZE (result);
10878 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10880 genSetDPTR(AOP(left)->aopu.dptr);
10881 emitcode ("clr", "a");
10882 emitcode ("movc", "a,@a+dptr");
10883 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10884 emitcode ("inc", "dptr");
10886 aopPut (result, "a", offset++);
10889 _startLazyDPSEvaluation ();
10892 if (AOP_INDPTRn(left)) {
10893 genSetDPTR(AOP(left)->aopu.dptr);
10899 emitcode ("clr", "a");
10900 emitcode ("movc", "a,@a+dptr");
10901 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10902 emitcode ("inc", "dptr");
10903 aopPut (result, "a", offset++);
10905 _endLazyDPSEvaluation ();
10908 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10909 if (!AOP_INDPTRn(left)) {
10910 _startLazyDPSEvaluation ();
10912 aopPut (left, "dpl", 0);
10913 aopPut (left, "dph", 1);
10914 if (options.model == MODEL_FLAT24)
10915 aopPut (left, "dpx", 2);
10917 _endLazyDPSEvaluation ();
10920 } else if (IS_SYMOP(left) &&
10921 (OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
10922 AOP_SIZE(result) > 1 &&
10923 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10925 size = AOP_SIZE (result) - 1;
10926 if (AOP_INDPTRn(left)) {
10927 genSetDPTR(AOP(left)->aopu.dptr);
10929 while (size--) emitcode ("lcall","__decdptr");
10930 if (AOP_INDPTRn(left)) {
10935 freeAsmop (result, NULL, ic, TRUE);
10936 freeAsmop (left, NULL, ic, TRUE);
10939 /*-----------------------------------------------------------------*/
10940 /* genGenPointerGet - get value from generic pointer space */
10941 /*-----------------------------------------------------------------*/
10943 genGenPointerGet (operand * left,
10944 operand * result, iCode * ic, iCode * pi)
10948 sym_link *retype = getSpec (operandType (result));
10949 sym_link *letype = getSpec (operandType (left));
10951 D (emitcode (";", "genGenPointerGet"));
10953 aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
10955 pushedB = pushB ();
10956 /* if the operand is already in dptr
10957 then we do nothing else we move the value to dptr */
10958 if (AOP_TYPE (left) != AOP_STR)
10960 /* if this is rematerializable */
10961 if (AOP_TYPE (left) == AOP_IMMD)
10963 emitcode ("mov", "dptr,%s", aopGet (left, 0, TRUE, FALSE, NULL));
10964 if (AOP(left)->aopu.aop_immd.from_cast_remat)
10966 MOVB (aopGet (left, AOP_SIZE(left)-1, FALSE, FALSE, NULL));
10970 emitcode ("mov", "b,#%d", pointerCode (retype));
10974 { /* we need to get it byte by byte */
10975 _startLazyDPSEvaluation ();
10976 emitcode ("mov", "dpl,%s", aopGet (left,0,FALSE,FALSE,NULL));
10977 emitcode ("mov", "dph,%s", aopGet (left,1,FALSE,FALSE,NULL));
10978 if (options.model == MODEL_FLAT24) {
10979 emitcode ("mov", "dpx,%s", aopGet (left,2,FALSE,FALSE,NULL));
10980 emitcode ("mov", "b,%s", aopGet (left,3,FALSE,FALSE,NULL));
10982 emitcode ("mov", "b,%s", aopGet (left,2,FALSE,FALSE,NULL));
10984 _endLazyDPSEvaluation ();
10988 /* so dptr-b now contains the address */
10989 aopOp (result, ic, FALSE, TRUE);
10991 /* if bit then unpack */
10992 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10994 genUnpackBits (result, "dptr", GPOINTER);
10998 size = AOP_SIZE (result);
11005 // Get two bytes at a time, results in _AP & A.
11006 // dptr will be incremented ONCE by __gptrgetWord.
11008 // Note: any change here must be coordinated
11009 // with the implementation of __gptrgetWord
11010 // in device/lib/_gptrget.c
11011 emitcode ("lcall", "__gptrgetWord");
11012 aopPut (result, "a", offset++);
11013 aopPut (result, DP2_RESULT_REG, offset++);
11018 // Only one byte to get.
11019 emitcode ("lcall", "__gptrget");
11020 aopPut (result, "a", offset++);
11023 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
11025 emitcode ("inc", "dptr");
11030 if (pi && AOP_TYPE (left) != AOP_IMMD) {
11031 _startLazyDPSEvaluation ();
11033 aopPut (left, "dpl", 0);
11034 aopPut (left, "dph", 1);
11035 if (options.model == MODEL_FLAT24) {
11036 aopPut (left, "dpx", 2);
11037 aopPut (left, "b", 3);
11038 } else aopPut (left, "b", 2);
11040 _endLazyDPSEvaluation ();
11043 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
11044 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
11046 size = AOP_SIZE (result) - 1;
11047 while (size--) emitcode ("lcall","__decdptr");
11051 freeAsmop (result, NULL, ic, TRUE);
11052 freeAsmop (left, NULL, ic, TRUE);
11055 /*-----------------------------------------------------------------*/
11056 /* genPointerGet - generate code for pointer get */
11057 /*-----------------------------------------------------------------*/
11059 genPointerGet (iCode * ic, iCode *pi)
11061 operand *left, *result;
11062 sym_link *type, *etype;
11065 D (emitcode (";", "genPointerGet"));
11067 left = IC_LEFT (ic);
11068 result = IC_RESULT (ic);
11070 /* depending on the type of pointer we need to
11071 move it to the correct pointer register */
11072 type = operandType (left);
11073 etype = getSpec (type);
11074 /* if left is of type of pointer then it is simple */
11075 if (IS_PTR (type) && !IS_FUNC (type->next))
11076 p_type = DCL_TYPE (type);
11079 /* we have to go by the storage class */
11080 p_type = PTR_TYPE (SPEC_OCLS (etype));
11083 /* special case when cast remat */
11084 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
11085 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
11087 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
11088 type = operandType (left);
11089 p_type = DCL_TYPE (type);
11091 /* now that we have the pointer type we assign
11092 the pointer values */
11098 genNearPointerGet (left, result, ic, pi);
11102 genPagedPointerGet (left, result, ic, pi);
11106 genFarPointerGet (left, result, ic, pi);
11110 genCodePointerGet (left, result, ic, pi);
11114 genGenPointerGet (left, result, ic, pi);
11120 /*-----------------------------------------------------------------*/
11121 /* genPackBits - generates code for packed bit storage */
11122 /*-----------------------------------------------------------------*/
11124 genPackBits (sym_link * etype,
11126 char *rname, int p_type)
11128 int offset = 0; /* source byte offset */
11129 int rlen = 0; /* remaining bitfield length */
11130 int blen; /* bitfield length */
11131 int bstr; /* bitfield starting bit within byte */
11132 int litval; /* source literal value (if AOP_LIT) */
11133 unsigned char mask; /* bitmask within current byte */
11135 D(emitcode (";", "genPackBits"));
11137 blen = SPEC_BLEN (etype);
11138 bstr = SPEC_BSTR (etype);
11140 /* If the bitfield length is less than a byte */
11143 mask = ((unsigned char) (0xFF << (blen + bstr)) |
11144 (unsigned char) (0xFF >> (8 - bstr)));
11146 if (AOP_TYPE (right) == AOP_LIT)
11148 /* Case with a bitfield length <8 and literal source
11150 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
11152 litval &= (~mask) & 0xff;
11153 emitPtrByteGet (rname, p_type, FALSE);
11154 if ((mask|litval)!=0xff)
11155 emitcode ("anl","a,#!constbyte", mask);
11157 emitcode ("orl","a,#!constbyte", litval);
11161 if ((blen==1) && (p_type!=GPOINTER))
11163 /* Case with a bitfield length == 1 and no generic pointer
11165 if (AOP_TYPE (right) == AOP_CRY)
11166 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
11169 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
11170 emitcode ("rrc","a");
11172 emitPtrByteGet (rname, p_type, FALSE);
11173 emitcode ("mov","acc.%d,c",bstr);
11178 /* Case with a bitfield length < 8 and arbitrary source
11180 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
11181 /* shift and mask source value */
11183 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
11185 pushedB = pushB ();
11186 /* transfer A to B and get next byte */
11187 emitPtrByteGet (rname, p_type, TRUE);
11189 emitcode ("anl", "a,#!constbyte", mask);
11190 emitcode ("orl", "a,b");
11191 if (p_type == GPOINTER)
11192 emitcode ("pop", "b");
11198 emitPtrByteSet (rname, p_type, "a");
11202 /* Bit length is greater than 7 bits. In this case, copy */
11203 /* all except the partial byte at the end */
11204 for (rlen=blen;rlen>=8;rlen-=8)
11206 emitPtrByteSet (rname, p_type,
11207 aopGet (right, offset++, FALSE, TRUE, NULL) );
11209 emitcode ("inc", "%s", rname);
11212 /* If there was a partial byte at the end */
11215 mask = (((unsigned char) -1 << rlen) & 0xff);
11217 if (AOP_TYPE (right) == AOP_LIT)
11219 /* Case with partial byte and literal source
11221 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
11222 litval >>= (blen-rlen);
11223 litval &= (~mask) & 0xff;
11224 emitPtrByteGet (rname, p_type, FALSE);
11225 if ((mask|litval)!=0xff)
11226 emitcode ("anl","a,#!constbyte", mask);
11228 emitcode ("orl","a,#!constbyte", litval);
11233 /* Case with partial byte and arbitrary source
11235 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11236 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
11238 pushedB = pushB ();
11239 /* transfer A to B and get next byte */
11240 emitPtrByteGet (rname, p_type, TRUE);
11242 emitcode ("anl", "a,#!constbyte", mask);
11243 emitcode ("orl", "a,b");
11244 if (p_type == GPOINTER)
11245 emitcode ("pop", "b");
11249 emitPtrByteSet (rname, p_type, "a");
11254 /*-----------------------------------------------------------------*/
11255 /* genDataPointerSet - remat pointer to data space */
11256 /*-----------------------------------------------------------------*/
11258 genDataPointerSet (operand * right,
11262 int size, offset = 0;
11263 char *l, buffer[256];
11265 D (emitcode (";", "genDataPointerSet"));
11267 aopOp (right, ic, FALSE, FALSE);
11269 l = aopGet (result, 0, FALSE, TRUE, NULL);
11270 size = AOP_SIZE (right);
11274 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l + 1, offset);
11276 SNPRINTF (buffer, sizeof(buffer), "%s", l + 1);
11277 emitcode ("mov", "%s,%s", buffer,
11278 aopGet (right, offset++, FALSE, FALSE, NULL));
11281 freeAsmop (result, NULL, ic, TRUE);
11282 freeAsmop (right, NULL, ic, TRUE);
11285 /*-----------------------------------------------------------------*/
11286 /* genNearPointerSet - emitcode for near pointer put */
11287 /*-----------------------------------------------------------------*/
11289 genNearPointerSet (operand * right,
11296 sym_link *retype, *letype;
11297 sym_link *ptype = operandType (result);
11299 D (emitcode (";", "genNearPointerSet"));
11301 retype = getSpec (operandType (right));
11302 letype = getSpec (ptype);
11304 aopOp (result, ic, FALSE, FALSE);
11306 /* if the result is rematerializable &
11307 in data space & not a bit variable */
11308 if (AOP_TYPE (result) == AOP_IMMD &&
11309 DCL_TYPE (ptype) == POINTER &&
11310 !IS_BITVAR (retype) &&
11311 !IS_BITVAR (letype))
11313 genDataPointerSet (right, result, ic);
11317 /* if the value is already in a pointer register
11318 then don't need anything more */
11319 if (!AOP_INPREG (AOP (result)))
11321 /* otherwise get a free pointer register */
11324 aop = newAsmop (0);
11325 preg = getFreePtr (ic, &aop, FALSE);
11326 emitcode ("mov", "%s,%s",
11328 aopGet (result, 0, FALSE, TRUE, NULL));
11329 rname = preg->name;
11333 rname = aopGet (result, 0, FALSE, FALSE, NULL);
11336 aopOp (right, ic, FALSE, FALSE);
11338 /* if bitfield then unpack the bits */
11339 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11340 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
11343 /* we can just get the values */
11344 int size = AOP_SIZE (right);
11349 l = aopGet (right, offset, FALSE, TRUE, NULL);
11350 if ((*l == '@') || (strcmp (l, "acc") == 0))
11353 emitcode ("mov", "@%s,a", rname);
11356 emitcode ("mov", "@%s,%s", rname, l);
11358 emitcode ("inc", "%s", rname);
11363 /* now some housekeeping stuff */
11364 if (aop) /* we had to allocate for this iCode */
11367 aopPut (result, rname, 0);
11368 freeAsmop (NULL, aop, ic, TRUE);
11372 /* we did not allocate which means left
11373 already in a pointer register, then
11374 if size > 0 && this could be used again
11375 we have to point it back to where it
11377 if (AOP_SIZE (right) > 1 &&
11378 !OP_SYMBOL (result)->remat &&
11379 (OP_SYMBOL (result)->liveTo > ic->seq ||
11383 int size = AOP_SIZE (right) - 1;
11385 emitcode ("dec", "%s", rname);
11390 if (pi) pi->generated = 1;
11391 freeAsmop (result, NULL, ic, TRUE);
11392 freeAsmop (right, NULL, ic, TRUE);
11395 /*-----------------------------------------------------------------*/
11396 /* genPagedPointerSet - emitcode for Paged pointer put */
11397 /*-----------------------------------------------------------------*/
11399 genPagedPointerSet (operand * right,
11406 sym_link *retype, *letype;
11408 D (emitcode (";", "genPagedPointerSet"));
11410 retype = getSpec (operandType (right));
11411 letype = getSpec (operandType (result));
11413 aopOp (result, ic, FALSE, FALSE);
11415 /* if the value is already in a pointer register
11416 then don't need anything more */
11417 if (!AOP_INPREG (AOP (result)))
11419 /* otherwise get a free pointer register */
11422 aop = newAsmop (0);
11423 preg = getFreePtr (ic, &aop, FALSE);
11424 emitcode ("mov", "%s,%s",
11426 aopGet (result, 0, FALSE, TRUE, NULL));
11427 rname = preg->name;
11430 rname = aopGet (result, 0, FALSE, FALSE, NULL);
11432 aopOp (right, ic, FALSE, FALSE);
11434 /* if bitfield then unpack the bits */
11435 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11436 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
11439 /* we have can just get the values */
11440 int size = AOP_SIZE (right);
11445 l = aopGet (right, offset, FALSE, TRUE, NULL);
11447 emitcode ("movx", "@%s,a", rname);
11450 emitcode ("inc", "%s", rname);
11456 /* now some housekeeping stuff */
11460 aopPut (result, rname, 0);
11461 /* we had to allocate for this iCode */
11462 freeAsmop (NULL, aop, ic, TRUE);
11466 /* we did not allocate which means left
11467 already in a pointer register, then
11468 if size > 0 && this could be used again
11469 we have to point it back to where it
11471 if (AOP_SIZE (right) > 1 &&
11472 !OP_SYMBOL (result)->remat &&
11473 (OP_SYMBOL (result)->liveTo > ic->seq ||
11477 int size = AOP_SIZE (right) - 1;
11479 emitcode ("dec", "%s", rname);
11484 if (pi) pi->generated = 1;
11485 freeAsmop (result, NULL, ic, TRUE);
11486 freeAsmop (right, NULL, ic, TRUE);
11489 /*-----------------------------------------------------------------*/
11490 /* genFarPointerSet - set value from far space */
11491 /*-----------------------------------------------------------------*/
11493 genFarPointerSet (operand * right,
11494 operand * result, iCode * ic, iCode *pi)
11496 int size, offset, dopi=1;
11497 sym_link *retype = getSpec (operandType (right));
11498 sym_link *letype = getSpec (operandType (result));
11500 aopOp (result, ic, FALSE, FALSE);
11502 /* if the operand is already in dptr
11503 then we do nothing else we move the value to dptr */
11504 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
11506 /* if this is remateriazable */
11507 if (AOP_TYPE (result) == AOP_IMMD)
11508 emitcode ("mov", "dptr,%s",
11509 aopGet (result, 0, TRUE, FALSE, NULL));
11512 /* we need to get it byte by byte */
11513 _startLazyDPSEvaluation ();
11514 if (AOP_TYPE (result) != AOP_DPTR)
11516 emitcode ("mov", "dpl,%s", aopGet (result, 0, FALSE, FALSE, NULL));
11517 emitcode ("mov", "dph,%s", aopGet (result, 1, FALSE, FALSE, NULL));
11518 if (options.model == MODEL_FLAT24)
11519 emitcode ("mov", "dpx,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11523 /* We need to generate a load to DPTR indirect through DPTR. */
11524 D (emitcode (";", "genFarPointerSet -- indirection special case."););
11526 emitcode ("push", "%s", aopGet (result, 0, FALSE, TRUE, NULL));
11527 emitcode ("push", "%s", aopGet (result, 1, FALSE, TRUE, NULL));
11528 if (options.model == MODEL_FLAT24)
11529 emitcode ("mov", "dpx,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11530 emitcode ("pop", "dph");
11531 emitcode ("pop", "dpl");
11534 _endLazyDPSEvaluation ();
11537 /* so dptr now contains the address */
11538 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
11540 /* if bit then unpack */
11541 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11543 if (AOP_INDPTRn(result)) {
11544 genSetDPTR(AOP(result)->aopu.dptr);
11546 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
11547 if (AOP_INDPTRn(result)) {
11551 size = AOP_SIZE (right);
11553 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
11555 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11557 genSetDPTR(AOP(result)->aopu.dptr);
11558 emitcode ("movx", "@dptr,a");
11559 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
11560 emitcode ("inc", "dptr");
11564 _startLazyDPSEvaluation ();
11566 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11568 if (AOP_INDPTRn(result)) {
11569 genSetDPTR(AOP(result)->aopu.dptr);
11575 emitcode ("movx", "@dptr,a");
11576 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
11577 emitcode ("inc", "dptr");
11579 _endLazyDPSEvaluation ();
11583 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
11584 if (!AOP_INDPTRn(result)) {
11585 _startLazyDPSEvaluation ();
11587 aopPut (result,"dpl",0);
11588 aopPut (result,"dph",1);
11589 if (options.model == MODEL_FLAT24)
11590 aopPut (result,"dpx",2);
11592 _endLazyDPSEvaluation ();
11595 } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
11596 AOP_SIZE(right) > 1 &&
11597 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
11599 size = AOP_SIZE (right) - 1;
11600 if (AOP_INDPTRn(result)) {
11601 genSetDPTR(AOP(result)->aopu.dptr);
11603 while (size--) emitcode ("lcall","__decdptr");
11604 if (AOP_INDPTRn(result)) {
11608 freeAsmop (result, NULL, ic, TRUE);
11609 freeAsmop (right, NULL, ic, TRUE);
11612 /*-----------------------------------------------------------------*/
11613 /* genGenPointerSet - set value from generic pointer space */
11614 /*-----------------------------------------------------------------*/
11616 genGenPointerSet (operand * right,
11617 operand * result, iCode * ic, iCode *pi)
11621 sym_link *retype = getSpec (operandType (right));
11622 sym_link *letype = getSpec (operandType (result));
11624 aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
11626 pushedB = pushB ();
11627 /* if the operand is already in dptr
11628 then we do nothing else we move the value to dptr */
11629 if (AOP_TYPE (result) != AOP_STR)
11631 _startLazyDPSEvaluation ();
11632 /* if this is remateriazable */
11633 if (AOP_TYPE (result) == AOP_IMMD)
11635 emitcode ("mov", "dptr,%s", aopGet (result, 0, TRUE, FALSE, NULL));
11636 if (AOP(result)->aopu.aop_immd.from_cast_remat)
11638 MOVB (aopGet (result, AOP_SIZE(result)-1, FALSE, FALSE, NULL));
11643 "b,%s + 1", aopGet (result, 0, TRUE, FALSE, NULL));
11647 { /* we need to get it byte by byte */
11648 emitcode ("mov", "dpl,%s", aopGet (result, 0, FALSE, FALSE, NULL));
11649 emitcode ("mov", "dph,%s", aopGet (result, 1, FALSE, FALSE, NULL));
11650 if (options.model == MODEL_FLAT24) {
11651 emitcode ("mov", "dpx,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11652 emitcode ("mov", "b,%s", aopGet (result, 3, FALSE, FALSE, NULL));
11654 emitcode ("mov", "b,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11657 _endLazyDPSEvaluation ();
11659 /* so dptr + b now contains the address */
11660 aopOp (right, ic, FALSE, TRUE);
11662 /* if bit then unpack */
11663 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11665 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
11669 size = AOP_SIZE (right);
11672 _startLazyDPSEvaluation ();
11677 // Set two bytes at a time, passed in _AP & A.
11678 // dptr will be incremented ONCE by __gptrputWord.
11680 // Note: any change here must be coordinated
11681 // with the implementation of __gptrputWord
11682 // in device/lib/_gptrput.c
11683 emitcode("mov", "_ap, %s",
11684 aopGet (right, offset++, FALSE, FALSE, NULL));
11685 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11689 emitcode ("lcall", "__gptrputWord");
11694 // Only one byte to put.
11695 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11699 emitcode ("lcall", "__gptrput");
11702 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
11704 emitcode ("inc", "dptr");
11707 _endLazyDPSEvaluation ();
11710 if (pi && AOP_TYPE (result) != AOP_IMMD) {
11711 _startLazyDPSEvaluation ();
11713 aopPut (result, "dpl",0);
11714 aopPut (result, "dph",1);
11715 if (options.model == MODEL_FLAT24) {
11716 aopPut (result, "dpx",2);
11717 aopPut (result, "b",3);
11719 aopPut (result, "b",2);
11721 _endLazyDPSEvaluation ();
11724 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
11725 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
11727 size = AOP_SIZE (right) - 1;
11728 while (size--) emitcode ("lcall","__decdptr");
11732 freeAsmop (result, NULL, ic, TRUE);
11733 freeAsmop (right, NULL, ic, TRUE);
11736 /*-----------------------------------------------------------------*/
11737 /* genPointerSet - stores the value into a pointer location */
11738 /*-----------------------------------------------------------------*/
11740 genPointerSet (iCode * ic, iCode *pi)
11742 operand *right, *result;
11743 sym_link *type, *etype;
11746 D (emitcode (";", "genPointerSet"));
11748 right = IC_RIGHT (ic);
11749 result = IC_RESULT (ic);
11751 /* depending on the type of pointer we need to
11752 move it to the correct pointer register */
11753 type = operandType (result);
11754 etype = getSpec (type);
11755 /* if left is of type of pointer then it is simple */
11756 if (IS_PTR (type) && !IS_FUNC (type->next))
11758 p_type = DCL_TYPE (type);
11762 /* we have to go by the storage class */
11763 p_type = PTR_TYPE (SPEC_OCLS (etype));
11766 /* special case when cast remat */
11767 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
11768 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
11769 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
11770 type = operandType (result);
11771 p_type = DCL_TYPE (type);
11774 /* now that we have the pointer type we assign
11775 the pointer values */
11781 genNearPointerSet (right, result, ic, pi);
11785 genPagedPointerSet (right, result, ic, pi);
11789 genFarPointerSet (right, result, ic, pi);
11793 genGenPointerSet (right, result, ic, pi);
11797 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11798 "genPointerSet: illegal pointer type");
11802 /*-----------------------------------------------------------------*/
11803 /* genIfx - generate code for Ifx statement */
11804 /*-----------------------------------------------------------------*/
11806 genIfx (iCode * ic, iCode * popIc)
11808 operand *cond = IC_COND (ic);
11812 D (emitcode (";", "genIfx"));
11814 aopOp (cond, ic, FALSE, FALSE);
11816 /* get the value into acc */
11817 if (AOP_TYPE (cond) != AOP_CRY)
11824 if (AOP(cond)->aopu.aop_dir)
11825 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
11828 /* the result is now in the accumulator or a directly addressable bit */
11829 freeAsmop (cond, NULL, ic, TRUE);
11831 /* if there was something to be popped then do it */
11835 /* if the condition is a bit variable */
11837 genIfxJump (ic, dup);
11838 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
11839 genIfxJump (ic, SPIL_LOC (cond)->rname);
11840 else if (isbit && !IS_ITEMP (cond))
11841 genIfxJump (ic, OP_SYMBOL (cond)->rname);
11843 genIfxJump (ic, "a");
11848 /*-----------------------------------------------------------------*/
11849 /* genAddrOf - generates code for address of */
11850 /*-----------------------------------------------------------------*/
11852 genAddrOf (iCode * ic)
11854 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
11857 D (emitcode (";", "genAddrOf"));
11859 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11861 /* if the operand is on the stack then we
11862 need to get the stack offset of this
11867 /* if 10 bit stack */
11868 if (options.stack10bit) {
11872 tsprintf(buff, sizeof(buff),
11873 "#!constbyte",(options.stack_loc >> 16) & 0xff);
11874 /* if it has an offset then we need to compute it */
11875 /* emitcode ("subb", "a,#!constbyte", */
11876 /* -((sym->stack < 0) ? */
11877 /* ((short) (sym->stack - _G.nRegsSaved)) : */
11878 /* ((short) sym->stack)) & 0xff); */
11879 /* emitcode ("mov","b,a"); */
11880 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
11881 /* ((short) (sym->stack - _G.nRegsSaved)) : */
11882 /* ((short) sym->stack)) >> 8) & 0xff); */
11884 emitcode ("mov", "a,_bpx");
11885 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
11886 ((char) (sym->stack - _G.nRegsSaved)) :
11887 ((char) sym->stack )) & 0xff);
11888 emitcode ("mov", "b,a");
11889 emitcode ("mov", "a,_bpx+1");
11891 offset = (((sym->stack < 0) ?
11892 ((short) (sym->stack - _G.nRegsSaved)) :
11893 ((short) sym->stack )) >> 8) & 0xff;
11895 emitcode ("addc","a,#!constbyte", offset);
11897 aopPut (IC_RESULT (ic), "b", 0);
11898 aopPut (IC_RESULT (ic), "a", 1);
11899 aopPut (IC_RESULT (ic), buff, 2);
11901 /* we can just move _bp */
11902 aopPut (IC_RESULT (ic), "_bpx", 0);
11903 aopPut (IC_RESULT (ic), "_bpx+1", 1);
11904 aopPut (IC_RESULT (ic), buff, 2);
11907 /* if it has an offset then we need to compute it */
11910 emitcode ("mov", "a,_bp");
11911 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
11912 aopPut (IC_RESULT (ic), "a", 0);
11916 /* we can just move _bp */
11917 aopPut (IC_RESULT (ic), "_bp", 0);
11919 /* fill the result with zero */
11920 size = AOP_SIZE (IC_RESULT (ic)) - 1;
11923 if (options.stack10bit && size < (FPTRSIZE - 1)) {
11925 "*** warning: pointer to stack var truncated.\n");
11931 aopPut (IC_RESULT (ic), zero, offset++);
11937 /* object not on stack then we need the name */
11938 size = AOP_SIZE (IC_RESULT (ic));
11943 char s[SDCC_NAME_MAX];
11947 tsprintf(s, sizeof(s), "#!his",sym->rname);
11950 tsprintf(s, sizeof(s), "#!hihis",sym->rname);
11953 tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
11955 default: /* should not need this (just in case) */
11956 SNPRINTF (s, sizeof(s), "#(%s >> %d)",
11963 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11966 aopPut (IC_RESULT (ic), s, offset++);
11970 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11974 #if 0 // obsolete, and buggy for != xdata
11975 /*-----------------------------------------------------------------*/
11976 /* genArrayInit - generates code for address of */
11977 /*-----------------------------------------------------------------*/
11979 genArrayInit (iCode * ic)
11981 literalList *iLoop;
11983 int elementSize = 0, eIndex;
11984 unsigned val, lastVal;
11986 operand *left=IC_LEFT(ic);
11988 D (emitcode (";", "genArrayInit"));
11990 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
11992 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
11994 // Load immediate value into DPTR.
11995 emitcode("mov", "dptr, %s",
11996 aopGet (IC_LEFT(ic), 0, TRUE, FALSE, NULL));
11998 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
12001 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12002 "Unexpected operand to genArrayInit.\n");
12005 // a regression because of SDCCcse.c:1.52
12006 emitcode ("mov", "dpl,%s", aopGet (left, 0, FALSE, FALSE, NULL));
12007 emitcode ("mov", "dph,%s", aopGet (left, 1, FALSE, FALSE, NULL));
12008 if (options.model == MODEL_FLAT24)
12009 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
12013 type = operandType(IC_LEFT(ic));
12015 if (type && type->next)
12017 elementSize = getSize(type->next);
12021 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12022 "can't determine element size in genArrayInit.\n");
12026 iLoop = IC_ARRAYILIST(ic);
12031 bool firstpass = TRUE;
12033 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
12034 iLoop->count, (int)iLoop->literalValue, elementSize);
12040 symbol *tlbl = NULL;
12042 count = ix > 256 ? 256 : ix;
12046 tlbl = newiTempLabel (NULL);
12047 if (firstpass || (count & 0xff))
12049 emitcode("mov", "b, #!constbyte", count & 0xff);
12057 for (eIndex = 0; eIndex < elementSize; eIndex++)
12059 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
12060 if (val != lastVal)
12062 emitcode("mov", "a, #!constbyte", val);
12066 emitcode("movx", "@dptr, a");
12067 emitcode("inc", "dptr");
12072 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
12078 iLoop = iLoop->next;
12081 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
12085 /*-----------------------------------------------------------------*/
12086 /* genFarFarAssign - assignment when both are in far space */
12087 /*-----------------------------------------------------------------*/
12089 genFarFarAssign (operand * result, operand * right, iCode * ic)
12091 int size = AOP_SIZE (right);
12093 symbol *rSym = NULL;
12097 /* quick & easy case. */
12098 D (emitcode(";","genFarFarAssign (1 byte case)"));
12099 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
12100 freeAsmop (right, NULL, ic, FALSE);
12101 /* now assign DPTR to result */
12103 aopOp(result, ic, FALSE, FALSE);
12105 aopPut (result, "a", 0);
12106 freeAsmop(result, NULL, ic, FALSE);
12110 /* See if we've got an underlying symbol to abuse. */
12111 if (IS_SYMOP(result) && OP_SYMBOL(result))
12113 if (IS_TRUE_SYMOP(result))
12115 rSym = OP_SYMBOL(result);
12117 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
12119 rSym = OP_SYMBOL(result)->usl.spillLoc;
12123 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
12125 /* We can use the '390 auto-toggle feature to good effect here. */
12127 D (emitcode(";", "genFarFarAssign (390 auto-toggle fun)"));
12128 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12129 emitcode ("mov", "dptr,#%s", rSym->rname);
12130 /* DP2 = result, DP1 = right, DP1 is current. */
12133 emitcode("movx", "a,@dptr");
12134 emitcode("movx", "@dptr,a");
12137 emitcode("inc", "dptr");
12138 emitcode("inc", "dptr");
12141 emitcode("mov", "dps,#0");
12142 freeAsmop (right, NULL, ic, FALSE);
12144 some alternative code for processors without auto-toggle
12145 no time to test now, so later well put in...kpb
12146 D (emitcode(";", "genFarFarAssign (dual-dptr fun)"));
12147 emitcode("mov", "dps,#1"); /* Select DPTR2. */
12148 emitcode ("mov", "dptr,#%s", rSym->rname);
12149 /* DP2 = result, DP1 = right, DP1 is current. */
12153 emitcode("movx", "a,@dptr");
12155 emitcode("inc", "dptr");
12156 emitcode("inc", "dps");
12157 emitcode("movx", "@dptr,a");
12159 emitcode("inc", "dptr");
12160 emitcode("inc", "dps");
12162 emitcode("mov", "dps,#0");
12163 freeAsmop (right, NULL, ic, FALSE);
12168 D (emitcode (";", "genFarFarAssign"));
12169 aopOp (result, ic, TRUE, TRUE);
12171 _startLazyDPSEvaluation ();
12176 aopGet (right, offset, FALSE, FALSE, NULL), offset);
12179 _endLazyDPSEvaluation ();
12180 freeAsmop (result, NULL, ic, FALSE);
12181 freeAsmop (right, NULL, ic, FALSE);
12185 /*-----------------------------------------------------------------*/
12186 /* genAssign - generate code for assignment */
12187 /*-----------------------------------------------------------------*/
12189 genAssign (iCode * ic)
12191 operand *result, *right;
12193 unsigned long lit = 0L;
12195 D (emitcode (";", "genAssign"));
12197 result = IC_RESULT (ic);
12198 right = IC_RIGHT (ic);
12200 /* if they are the same */
12201 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
12204 aopOp (right, ic, FALSE, FALSE);
12206 emitcode (";", "genAssign: resultIsFar = %s",
12207 isOperandInFarSpace (result) ?
12210 /* special case both in far space */
12211 if ((AOP_TYPE (right) == AOP_DPTR ||
12212 AOP_TYPE (right) == AOP_DPTR2) &&
12213 /* IS_TRUE_SYMOP(result) && */
12214 isOperandInFarSpace (result))
12216 genFarFarAssign (result, right, ic);
12220 aopOp (result, ic, TRUE, FALSE);
12222 /* if they are the same registers */
12223 if (sameRegs (AOP (right), AOP (result)))
12226 /* if the result is a bit */
12227 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
12229 /* if the right size is a literal then
12230 we know what the value is */
12231 if (AOP_TYPE (right) == AOP_LIT)
12233 if (((int) operandLitValue (right)))
12234 aopPut (result, one, 0);
12236 aopPut (result, zero, 0);
12240 /* the right is also a bit variable */
12241 if (AOP_TYPE (right) == AOP_CRY)
12243 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
12244 aopPut (result, "c", 0);
12248 /* we need to or */
12250 aopPut (result, "a", 0);
12254 /* bit variables done */
12256 size = AOP_SIZE (result);
12258 if (AOP_TYPE (right) == AOP_LIT)
12259 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
12262 (AOP_TYPE (result) != AOP_REG) &&
12263 (AOP_TYPE (right) == AOP_LIT) &&
12264 !IS_FLOAT (operandType (right)))
12266 _startLazyDPSEvaluation ();
12267 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
12270 aopGet (right, offset, FALSE, FALSE, NULL),
12275 /* And now fill the rest with zeros. */
12278 emitcode ("clr", "a");
12282 aopPut (result, "a", offset++);
12284 _endLazyDPSEvaluation ();
12288 _startLazyDPSEvaluation ();
12292 aopGet (right, offset, FALSE, FALSE, NULL),
12296 _endLazyDPSEvaluation ();
12300 freeAsmop (result, NULL, ic, TRUE);
12301 freeAsmop (right, NULL, ic, TRUE);
12304 /*-----------------------------------------------------------------*/
12305 /* genJumpTab - generates code for jump table */
12306 /*-----------------------------------------------------------------*/
12308 genJumpTab (iCode * ic)
12313 D (emitcode (";", "genJumpTab"));
12315 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
12316 /* get the condition into accumulator */
12317 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE, NULL);
12319 /* multiply by four! */
12320 emitcode ("add", "a,acc");
12321 emitcode ("add", "a,acc");
12322 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
12324 jtab = newiTempLabel (NULL);
12325 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
12326 emitcode ("jmp", "@a+dptr");
12328 /* now generate the jump labels */
12329 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
12330 jtab = setNextItem (IC_JTLABELS (ic)))
12331 emitcode ("ljmp", "!tlabel", jtab->key + 100);
12335 /*-----------------------------------------------------------------*/
12336 /* genCast - gen code for casting */
12337 /*-----------------------------------------------------------------*/
12339 genCast (iCode * ic)
12341 operand *result = IC_RESULT (ic);
12342 sym_link *ctype = operandType (IC_LEFT (ic));
12343 sym_link *rtype = operandType (IC_RIGHT (ic));
12344 operand *right = IC_RIGHT (ic);
12347 D (emitcode (";", "genCast"));
12349 /* if they are equivalent then do nothing */
12350 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
12353 aopOp (right, ic, FALSE, AOP_IS_STR (result));
12354 aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR));
12356 /* if the result is a bit (and not a bitfield) */
12357 if (IS_BIT (OP_SYMBOL (result)->type))
12359 /* if the right size is a literal then
12360 we know what the value is */
12361 if (AOP_TYPE (right) == AOP_LIT)
12363 if (((int) operandLitValue (right)))
12364 aopPut (result, one, 0);
12366 aopPut (result, zero, 0);
12371 /* the right is also a bit variable */
12372 if (AOP_TYPE (right) == AOP_CRY)
12374 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
12375 aopPut (result, "c", 0);
12379 /* we need to or */
12381 aopPut (result, "a", 0);
12385 /* if they are the same size : or less */
12386 if (AOP_SIZE (result) <= AOP_SIZE (right))
12389 /* if they are in the same place */
12390 if (sameRegs (AOP (right), AOP (result)))
12393 /* if they in different places then copy */
12394 size = AOP_SIZE (result);
12396 _startLazyDPSEvaluation ();
12400 aopGet (right, offset, FALSE, FALSE, NULL),
12404 _endLazyDPSEvaluation ();
12408 /* if the result is of type pointer */
12409 if (IS_PTR (ctype))
12413 sym_link *type = operandType (right);
12415 /* pointer to generic pointer */
12416 if (IS_GENPTR (ctype))
12420 p_type = DCL_TYPE (type);
12424 #if OLD_CAST_BEHAVIOR
12425 /* KV: we are converting a non-pointer type to
12426 * a generic pointer. This (ifdef'd out) code
12427 * says that the resulting generic pointer
12428 * should have the same class as the storage
12429 * location of the non-pointer variable.
12431 * For example, converting an int (which happens
12432 * to be stored in DATA space) to a pointer results
12433 * in a DATA generic pointer; if the original int
12434 * in XDATA space, so will be the resulting pointer.
12436 * I don't like that behavior, and thus this change:
12437 * all such conversions will be forced to XDATA and
12438 * throw a warning. If you want some non-XDATA
12439 * type, or you want to suppress the warning, you
12440 * must go through an intermediate cast, like so:
12442 * char _generic *gp = (char _xdata *)(intVar);
12444 sym_link *etype = getSpec (type);
12446 /* we have to go by the storage class */
12447 if (SPEC_OCLS (etype) != generic)
12449 p_type = PTR_TYPE (SPEC_OCLS (etype));
12454 /* Converting unknown class (i.e. register variable)
12455 * to generic pointer. This is not good, but
12456 * we'll make a guess (and throw a warning).
12459 werror (W_INT_TO_GEN_PTR_CAST);
12463 /* the first two bytes are known */
12464 size = GPTRSIZE - 1;
12466 _startLazyDPSEvaluation ();
12470 aopGet (right, offset, FALSE, FALSE, NULL),
12474 _endLazyDPSEvaluation ();
12476 /* the last byte depending on type */
12478 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
12483 // pointerTypeToGPByte will have bitched.
12487 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%x", gpVal);
12488 aopPut (result, gpValStr, GPTRSIZE - 1);
12493 /* just copy the pointers */
12494 size = AOP_SIZE (result);
12496 _startLazyDPSEvaluation ();
12500 aopGet (right, offset, FALSE, FALSE, NULL),
12504 _endLazyDPSEvaluation ();
12508 /* so we now know that the size of destination is greater
12509 than the size of the source */
12510 /* we move to result for the size of source */
12511 size = AOP_SIZE (right);
12513 _startLazyDPSEvaluation ();
12517 aopGet (right, offset, FALSE, FALSE, NULL),
12521 _endLazyDPSEvaluation ();
12523 /* now depending on the sign of the source && destination */
12524 size = AOP_SIZE (result) - AOP_SIZE (right);
12525 /* if unsigned or not an integral type */
12526 /* also, if the source is a bit, we don't need to sign extend, because
12527 * it can't possibly have set the sign bit.
12529 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
12533 aopPut (result, zero, offset++);
12538 /* we need to extend the sign :{ */
12539 MOVA (aopGet (right, AOP_SIZE (right) - 1,
12540 FALSE, FALSE, NULL));
12541 emitcode ("rlc", "a");
12542 emitcode ("subb", "a,acc");
12544 aopPut (result, "a", offset++);
12547 /* we are done hurray !!!! */
12550 freeAsmop (right, NULL, ic, TRUE);
12551 freeAsmop (result, NULL, ic, TRUE);
12555 /*-----------------------------------------------------------------*/
12556 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
12557 /*-----------------------------------------------------------------*/
12558 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
12560 operand *from , *to , *count;
12565 /* we know it has to be 3 parameters */
12566 assert (nparms == 3);
12568 rsave = newBitVect(16);
12569 /* save DPTR if it needs to be saved */
12570 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12571 if (bitVectBitValue(ic->rMask,i))
12572 rsave = bitVectSetBit(rsave,i);
12574 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12575 ds390_rUmaskForOp (IC_RESULT(ic))));
12582 aopOp (from, ic->next, FALSE, FALSE);
12584 /* get from into DPTR1 */
12585 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12586 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12587 if (options.model == MODEL_FLAT24) {
12588 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12591 freeAsmop (from, NULL, ic, FALSE);
12592 aopOp (to, ic, FALSE, FALSE);
12593 /* get "to" into DPTR */
12594 /* if the operand is already in dptr
12595 then we do nothing else we move the value to dptr */
12596 if (AOP_TYPE (to) != AOP_STR) {
12597 /* if already in DPTR then we need to push */
12598 if (AOP_TYPE(to) == AOP_DPTR) {
12599 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12600 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12601 if (options.model == MODEL_FLAT24)
12602 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12603 emitcode ("pop", "dph");
12604 emitcode ("pop", "dpl");
12606 _startLazyDPSEvaluation ();
12607 /* if this is remateriazable */
12608 if (AOP_TYPE (to) == AOP_IMMD) {
12609 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12610 } else { /* we need to get it byte by byte */
12611 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12612 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12613 if (options.model == MODEL_FLAT24) {
12614 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12617 _endLazyDPSEvaluation ();
12620 freeAsmop (to, NULL, ic, FALSE);
12621 _G.dptrInUse = _G.dptr1InUse = 1;
12622 aopOp (count, ic->next->next, FALSE,FALSE);
12623 lbl =newiTempLabel(NULL);
12625 /* now for the actual copy */
12626 if (AOP_TYPE(count) == AOP_LIT &&
12627 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12628 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12630 emitcode ("lcall","__bi_memcpyc2x_s");
12632 emitcode ("lcall","__bi_memcpyx2x_s");
12634 freeAsmop (count, NULL, ic, FALSE);
12636 symbol *lbl1 = newiTempLabel(NULL);
12638 emitcode (";"," Auto increment but no djnz");
12639 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
12640 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
12641 freeAsmop (count, NULL, ic, FALSE);
12642 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12645 emitcode ("clr","a");
12646 emitcode ("movc", "a,@a+dptr");
12648 emitcode ("movx", "a,@dptr");
12649 emitcode ("movx", "@dptr,a");
12650 emitcode ("inc", "dptr");
12651 emitcode ("inc", "dptr");
12652 emitcode ("mov","a,b");
12653 emitcode ("orl","a,_ap");
12654 emitcode ("jz","!tlabel",lbl1->key+100);
12655 emitcode ("mov","a,_ap");
12656 emitcode ("add","a,#!constbyte",0xFF);
12657 emitcode ("mov","_ap,a");
12658 emitcode ("mov","a,b");
12659 emitcode ("addc","a,#!constbyte",0xFF);
12660 emitcode ("mov","b,a");
12661 emitcode ("sjmp","!tlabel",lbl->key+100);
12664 emitcode ("mov", "dps,#0");
12665 _G.dptrInUse = _G.dptr1InUse = 0;
12666 unsavermask(rsave);
12670 /*-----------------------------------------------------------------*/
12671 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
12672 /*-----------------------------------------------------------------*/
12673 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
12675 operand *from , *to , *count;
12680 /* we know it has to be 3 parameters */
12681 assert (nparms == 3);
12683 rsave = newBitVect(16);
12684 /* save DPTR if it needs to be saved */
12685 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12686 if (bitVectBitValue(ic->rMask,i))
12687 rsave = bitVectSetBit(rsave,i);
12689 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12690 ds390_rUmaskForOp (IC_RESULT(ic))));
12697 aopOp (from, ic->next, FALSE, FALSE);
12699 /* get from into DPTR1 */
12700 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12701 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12702 if (options.model == MODEL_FLAT24) {
12703 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12706 freeAsmop (from, NULL, ic, FALSE);
12707 aopOp (to, ic, FALSE, FALSE);
12708 /* get "to" into DPTR */
12709 /* if the operand is already in dptr
12710 then we do nothing else we move the value to dptr */
12711 if (AOP_TYPE (to) != AOP_STR) {
12712 /* if already in DPTR then we need to push */
12713 if (AOP_TYPE(to) == AOP_DPTR) {
12714 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12715 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12716 if (options.model == MODEL_FLAT24)
12717 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12718 emitcode ("pop", "dph");
12719 emitcode ("pop", "dpl");
12721 _startLazyDPSEvaluation ();
12722 /* if this is remateriazable */
12723 if (AOP_TYPE (to) == AOP_IMMD) {
12724 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12725 } else { /* we need to get it byte by byte */
12726 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12727 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12728 if (options.model == MODEL_FLAT24) {
12729 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12732 _endLazyDPSEvaluation ();
12735 freeAsmop (to, NULL, ic, FALSE);
12736 _G.dptrInUse = _G.dptr1InUse = 1;
12737 aopOp (count, ic->next->next, FALSE,FALSE);
12738 lbl =newiTempLabel(NULL);
12739 lbl2 =newiTempLabel(NULL);
12741 /* now for the actual compare */
12742 if (AOP_TYPE(count) == AOP_LIT &&
12743 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12744 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12746 emitcode("lcall","__bi_memcmpc2x_s");
12748 emitcode("lcall","__bi_memcmpx2x_s");
12749 freeAsmop (count, NULL, ic, FALSE);
12750 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12751 aopPut(IC_RESULT(ic),"a",0);
12752 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12754 symbol *lbl1 = newiTempLabel(NULL);
12756 emitcode("push","ar0");
12757 emitcode (";"," Auto increment but no djnz");
12758 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
12759 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
12760 freeAsmop (count, NULL, ic, FALSE);
12761 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12764 emitcode ("clr","a");
12765 emitcode ("movc", "a,@a+dptr");
12767 emitcode ("movx", "a,@dptr");
12768 emitcode ("mov","r0,a");
12769 emitcode ("movx", "a,@dptr");
12770 emitcode ("clr","c");
12771 emitcode ("subb","a,r0");
12772 emitcode ("jnz","!tlabel",lbl2->key+100);
12773 emitcode ("inc", "dptr");
12774 emitcode ("inc", "dptr");
12775 emitcode ("mov","a,b");
12776 emitcode ("orl","a,_ap");
12777 emitcode ("jz","!tlabel",lbl1->key+100);
12778 emitcode ("mov","a,_ap");
12779 emitcode ("add","a,#!constbyte",0xFF);
12780 emitcode ("mov","_ap,a");
12781 emitcode ("mov","a,b");
12782 emitcode ("addc","a,#!constbyte",0xFF);
12783 emitcode ("mov","b,a");
12784 emitcode ("sjmp","!tlabel",lbl->key+100);
12786 emitcode ("clr","a");
12788 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12789 aopPut(IC_RESULT(ic),"a",0);
12790 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12791 emitcode("pop","ar0");
12792 emitcode ("mov", "dps,#0");
12794 _G.dptrInUse = _G.dptr1InUse = 0;
12795 unsavermask(rsave);
12799 /*-----------------------------------------------------------------*/
12800 /* genInp - gen code for __builtin_inp read data from a mem mapped */
12801 /* port, first parameter output area second parameter pointer to */
12802 /* port third parameter count */
12803 /*-----------------------------------------------------------------*/
12804 static void genInp( iCode *ic, int nparms, operand **parms)
12806 operand *from , *to , *count;
12811 /* we know it has to be 3 parameters */
12812 assert (nparms == 3);
12814 rsave = newBitVect(16);
12815 /* save DPTR if it needs to be saved */
12816 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12817 if (bitVectBitValue(ic->rMask,i))
12818 rsave = bitVectSetBit(rsave,i);
12820 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12821 ds390_rUmaskForOp (IC_RESULT(ic))));
12828 aopOp (from, ic->next, FALSE, FALSE);
12830 /* get from into DPTR1 */
12831 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12832 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12833 if (options.model == MODEL_FLAT24) {
12834 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12837 freeAsmop (from, NULL, ic, FALSE);
12838 aopOp (to, ic, FALSE, FALSE);
12839 /* get "to" into DPTR */
12840 /* if the operand is already in dptr
12841 then we do nothing else we move the value to dptr */
12842 if (AOP_TYPE (to) != AOP_STR) {
12843 /* if already in DPTR then we need to push */
12844 if (AOP_TYPE(to) == AOP_DPTR) {
12845 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12846 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12847 if (options.model == MODEL_FLAT24)
12848 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12849 emitcode ("pop", "dph");
12850 emitcode ("pop", "dpl");
12852 _startLazyDPSEvaluation ();
12853 /* if this is remateriazable */
12854 if (AOP_TYPE (to) == AOP_IMMD) {
12855 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12856 } else { /* we need to get it byte by byte */
12857 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12858 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12859 if (options.model == MODEL_FLAT24) {
12860 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12863 _endLazyDPSEvaluation ();
12866 freeAsmop (to, NULL, ic, FALSE);
12868 _G.dptrInUse = _G.dptr1InUse = 1;
12869 aopOp (count, ic->next->next, FALSE,FALSE);
12870 lbl =newiTempLabel(NULL);
12872 /* now for the actual copy */
12873 if (AOP_TYPE(count) == AOP_LIT &&
12874 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12875 emitcode (";","OH JOY auto increment with djnz (very fast)");
12876 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
12877 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12878 freeAsmop (count, NULL, ic, FALSE);
12880 emitcode ("movx", "a,@dptr"); /* read data from port */
12881 emitcode ("dec","dps"); /* switch to DPTR */
12882 emitcode ("movx", "@dptr,a"); /* save into location */
12883 emitcode ("inc", "dptr"); /* point to next area */
12884 emitcode ("inc","dps"); /* switch to DPTR2 */
12885 emitcode ("djnz","b,!tlabel",lbl->key+100);
12887 symbol *lbl1 = newiTempLabel(NULL);
12889 emitcode (";"," Auto increment but no djnz");
12890 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
12891 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
12892 freeAsmop (count, NULL, ic, FALSE);
12893 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
12895 emitcode ("movx", "a,@dptr");
12896 emitcode ("dec","dps"); /* switch to DPTR */
12897 emitcode ("movx", "@dptr,a");
12898 emitcode ("inc", "dptr");
12899 emitcode ("inc","dps"); /* switch to DPTR2 */
12900 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
12901 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
12902 emitcode ("mov","a,b");
12903 emitcode ("orl","a,_ap");
12904 emitcode ("jz","!tlabel",lbl1->key+100);
12905 emitcode ("mov","a,_ap");
12906 emitcode ("add","a,#!constbyte",0xFF);
12907 emitcode ("mov","_ap,a");
12908 emitcode ("mov","a,b");
12909 emitcode ("addc","a,#!constbyte",0xFF);
12910 emitcode ("mov","b,a");
12911 emitcode ("sjmp","!tlabel",lbl->key+100);
12914 emitcode ("mov", "dps,#0");
12915 _G.dptrInUse = _G.dptr1InUse = 0;
12916 unsavermask(rsave);
12920 /*-----------------------------------------------------------------*/
12921 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
12922 /* port, first parameter output area second parameter pointer to */
12923 /* port third parameter count */
12924 /*-----------------------------------------------------------------*/
12925 static void genOutp( iCode *ic, int nparms, operand **parms)
12927 operand *from , *to , *count;
12932 /* we know it has to be 3 parameters */
12933 assert (nparms == 3);
12935 rsave = newBitVect(16);
12936 /* save DPTR if it needs to be saved */
12937 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12938 if (bitVectBitValue(ic->rMask,i))
12939 rsave = bitVectSetBit(rsave,i);
12941 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12942 ds390_rUmaskForOp (IC_RESULT(ic))));
12949 aopOp (from, ic->next, FALSE, FALSE);
12951 /* get from into DPTR1 */
12952 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12953 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12954 if (options.model == MODEL_FLAT24) {
12955 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12958 freeAsmop (from, NULL, ic, FALSE);
12959 aopOp (to, ic, FALSE, FALSE);
12960 /* get "to" into DPTR */
12961 /* if the operand is already in dptr
12962 then we do nothing else we move the value to dptr */
12963 if (AOP_TYPE (to) != AOP_STR) {
12964 /* if already in DPTR then we need to push */
12965 if (AOP_TYPE(to) == AOP_DPTR) {
12966 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12967 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12968 if (options.model == MODEL_FLAT24)
12969 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12970 emitcode ("pop", "dph");
12971 emitcode ("pop", "dpl");
12973 _startLazyDPSEvaluation ();
12974 /* if this is remateriazable */
12975 if (AOP_TYPE (to) == AOP_IMMD) {
12976 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12977 } else { /* we need to get it byte by byte */
12978 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12979 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12980 if (options.model == MODEL_FLAT24) {
12981 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12984 _endLazyDPSEvaluation ();
12987 freeAsmop (to, NULL, ic, FALSE);
12989 _G.dptrInUse = _G.dptr1InUse = 1;
12990 aopOp (count, ic->next->next, FALSE,FALSE);
12991 lbl =newiTempLabel(NULL);
12993 /* now for the actual copy */
12994 if (AOP_TYPE(count) == AOP_LIT &&
12995 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12996 emitcode (";","OH JOY auto increment with djnz (very fast)");
12997 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
12998 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
13000 emitcode ("movx", "a,@dptr"); /* read data from port */
13001 emitcode ("inc","dps"); /* switch to DPTR2 */
13002 emitcode ("movx", "@dptr,a"); /* save into location */
13003 emitcode ("inc", "dptr"); /* point to next area */
13004 emitcode ("dec","dps"); /* switch to DPTR */
13005 emitcode ("djnz","b,!tlabel",lbl->key+100);
13006 freeAsmop (count, NULL, ic, FALSE);
13008 symbol *lbl1 = newiTempLabel(NULL);
13010 emitcode (";"," Auto increment but no djnz");
13011 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
13012 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
13013 freeAsmop (count, NULL, ic, FALSE);
13014 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
13016 emitcode ("movx", "a,@dptr");
13017 emitcode ("inc", "dptr");
13018 emitcode ("inc","dps"); /* switch to DPTR2 */
13019 emitcode ("movx", "@dptr,a");
13020 emitcode ("dec","dps"); /* switch to DPTR */
13021 emitcode ("mov","a,b");
13022 emitcode ("orl","a,_ap");
13023 emitcode ("jz","!tlabel",lbl1->key+100);
13024 emitcode ("mov","a,_ap");
13025 emitcode ("add","a,#!constbyte",0xFF);
13026 emitcode ("mov","_ap,a");
13027 emitcode ("mov","a,b");
13028 emitcode ("addc","a,#!constbyte",0xFF);
13029 emitcode ("mov","b,a");
13030 emitcode ("sjmp","!tlabel",lbl->key+100);
13033 emitcode ("mov", "dps,#0");
13034 _G.dptrInUse = _G.dptr1InUse = 0;
13035 unsavermask(rsave);
13039 /*-----------------------------------------------------------------*/
13040 /* genSwapW - swap lower & high order bytes */
13041 /*-----------------------------------------------------------------*/
13042 static void genSwapW(iCode *ic, int nparms, operand **parms)
13046 assert (nparms==1);
13049 dest=IC_RESULT(ic);
13051 assert(getSize(operandType(src))==2);
13053 aopOp (src, ic, FALSE, FALSE);
13054 emitcode ("mov","a,%s",aopGet(src,0,FALSE,FALSE,NULL));
13056 MOVB(aopGet(src,1,FALSE,FALSE,"b"));
13058 freeAsmop (src, NULL, ic, FALSE);
13060 aopOp (dest,ic, FALSE, FALSE);
13061 aopPut(dest,"b",0);
13062 aopPut(dest,"a",1);
13063 freeAsmop (dest, NULL, ic, FALSE);
13066 /*-----------------------------------------------------------------*/
13067 /* genMemsetX - gencode for memSetX data */
13068 /*-----------------------------------------------------------------*/
13069 static void genMemsetX(iCode *ic, int nparms, operand **parms)
13071 operand *to , *val , *count;
13077 /* we know it has to be 3 parameters */
13078 assert (nparms == 3);
13084 /* save DPTR if it needs to be saved */
13085 rsave = newBitVect(16);
13086 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
13087 if (bitVectBitValue(ic->rMask,i))
13088 rsave = bitVectSetBit(rsave,i);
13090 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
13091 ds390_rUmaskForOp (IC_RESULT(ic))));
13094 aopOp (to, ic, FALSE, FALSE);
13095 /* get "to" into DPTR */
13096 /* if the operand is already in dptr
13097 then we do nothing else we move the value to dptr */
13098 if (AOP_TYPE (to) != AOP_STR) {
13099 /* if already in DPTR then we need to push */
13100 if (AOP_TYPE(to) == AOP_DPTR) {
13101 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
13102 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
13103 if (options.model == MODEL_FLAT24)
13104 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
13105 emitcode ("pop", "dph");
13106 emitcode ("pop", "dpl");
13108 _startLazyDPSEvaluation ();
13109 /* if this is remateriazable */
13110 if (AOP_TYPE (to) == AOP_IMMD) {
13111 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
13112 } else { /* we need to get it byte by byte */
13113 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
13114 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
13115 if (options.model == MODEL_FLAT24) {
13116 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
13119 _endLazyDPSEvaluation ();
13122 freeAsmop (to, NULL, ic, FALSE);
13124 aopOp (val, ic->next->next, FALSE,FALSE);
13125 aopOp (count, ic->next->next, FALSE,FALSE);
13126 lbl =newiTempLabel(NULL);
13127 /* now for the actual copy */
13128 if (AOP_TYPE(count) == AOP_LIT &&
13129 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
13130 l = aopGet(val, 0, FALSE, FALSE, NULL);
13131 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
13134 emitcode ("movx", "@dptr,a");
13135 emitcode ("inc", "dptr");
13136 emitcode ("djnz","b,!tlabel",lbl->key+100);
13138 symbol *lbl1 = newiTempLabel(NULL);
13140 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
13141 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
13143 MOVA (aopGet(val, 0, FALSE, FALSE, NULL));
13144 emitcode ("movx", "@dptr,a");
13145 emitcode ("inc", "dptr");
13146 emitcode ("mov","a,b");
13147 emitcode ("orl","a,_ap");
13148 emitcode ("jz","!tlabel",lbl1->key+100);
13149 emitcode ("mov","a,_ap");
13150 emitcode ("add","a,#!constbyte",0xFF);
13151 emitcode ("mov","_ap,a");
13152 emitcode ("mov","a,b");
13153 emitcode ("addc","a,#!constbyte",0xFF);
13154 emitcode ("mov","b,a");
13155 emitcode ("sjmp","!tlabel",lbl->key+100);
13158 freeAsmop (count, NULL, ic, FALSE);
13159 unsavermask(rsave);
13162 /*-----------------------------------------------------------------*/
13163 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
13164 /*-----------------------------------------------------------------*/
13165 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
13168 operand *pnum, *result;
13171 assert (nparms==1);
13172 /* save registers that need to be saved */
13173 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13174 ds390_rUmaskForOp (IC_RESULT(ic))));
13177 aopOp (pnum, ic, FALSE, FALSE);
13178 emitcode ("mov","a,%s",aopGet(pnum,0,FALSE,FALSE,DP2_RESULT_REG));
13179 freeAsmop (pnum, NULL, ic, FALSE);
13180 emitcode ("lcall","NatLib_LoadPrimitive");
13181 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
13182 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
13183 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
13184 for (i = (size-1) ; i >= 0 ; i-- ) {
13185 emitcode ("push","a%s",javaRet[i]);
13187 for (i=0; i < size ; i++ ) {
13188 emitcode ("pop","a%s",
13189 aopGet(result,i,FALSE,FALSE,DP2_RESULT_REG));
13192 for (i = 0 ; i < size ; i++ ) {
13193 aopPut(result,javaRet[i],i);
13196 freeAsmop (result, NULL, ic, FALSE);
13197 unsavermask(rsave);
13200 /*-----------------------------------------------------------------*/
13201 /* genNatLibLoadPointer - calls TINI api function to load pointer */
13202 /*-----------------------------------------------------------------*/
13203 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
13206 operand *pnum, *result;
13210 assert (nparms==1);
13211 /* save registers that need to be saved */
13212 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13213 ds390_rUmaskForOp (IC_RESULT(ic))));
13216 aopOp (pnum, ic, FALSE, FALSE);
13217 emitcode ("mov","a,%s",aopGet(pnum,0,FALSE,FALSE,DP2_RESULT_REG));
13218 freeAsmop (pnum, NULL, ic, FALSE);
13219 emitcode ("lcall","NatLib_LoadPointer");
13220 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
13221 if (AOP_TYPE(result)!=AOP_STR) {
13222 for (i = 0 ; i < size ; i++ ) {
13223 aopPut(result,fReturn[i],i);
13226 freeAsmop (result, NULL, ic, FALSE);
13227 unsavermask(rsave);
13230 /*-----------------------------------------------------------------*/
13231 /* genNatLibInstallStateBlock - */
13232 /*-----------------------------------------------------------------*/
13233 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
13234 operand **parms, const char *name)
13237 operand *psb, *handle;
13238 assert (nparms==2);
13240 /* save registers that need to be saved */
13241 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13242 ds390_rUmaskForOp (IC_RESULT(ic))));
13246 /* put pointer to state block into DPTR1 */
13247 aopOp (psb, ic, FALSE, FALSE);
13248 if (AOP_TYPE (psb) == AOP_IMMD) {
13249 emitcode ("mov","dps,#1");
13250 emitcode ("mov", "dptr,%s",
13251 aopGet (psb, 0, TRUE, FALSE, DP2_RESULT_REG));
13252 emitcode ("mov","dps,#0");
13254 emitcode ("mov","dpl1,%s",aopGet(psb,0,FALSE,FALSE,DP2_RESULT_REG));
13255 emitcode ("mov","dph1,%s",aopGet(psb,1,FALSE,FALSE,DP2_RESULT_REG));
13256 emitcode ("mov","dpx1,%s",aopGet(psb,2,FALSE,FALSE,DP2_RESULT_REG));
13258 freeAsmop (psb, NULL, ic, FALSE);
13260 /* put libraryID into DPTR */
13261 emitcode ("mov","dptr,#LibraryID");
13263 /* put handle into r3:r2 */
13264 aopOp (handle, ic, FALSE, FALSE);
13265 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13266 emitcode ("push","%s",aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13267 emitcode ("push","%s",aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13268 emitcode ("pop","ar3");
13269 emitcode ("pop","ar2");
13271 emitcode ("mov","r2,%s",aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13272 emitcode ("mov","r3,%s",aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13274 freeAsmop (psb, NULL, ic, FALSE);
13276 /* make the call */
13277 emitcode ("lcall","NatLib_Install%sStateBlock",name);
13279 /* put return value into place*/
13281 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
13283 aopPut(IC_RESULT(ic),"a",0);
13284 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13285 unsavermask(rsave);
13288 /*-----------------------------------------------------------------*/
13289 /* genNatLibRemoveStateBlock - */
13290 /*-----------------------------------------------------------------*/
13291 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
13297 /* save registers that need to be saved */
13298 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13299 ds390_rUmaskForOp (IC_RESULT(ic))));
13301 /* put libraryID into DPTR */
13302 emitcode ("mov","dptr,#LibraryID");
13303 /* make the call */
13304 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
13305 unsavermask(rsave);
13308 /*-----------------------------------------------------------------*/
13309 /* genNatLibGetStateBlock - */
13310 /*-----------------------------------------------------------------*/
13311 static void genNatLibGetStateBlock(iCode *ic,int nparms,
13312 operand **parms,const char *name)
13315 symbol *lbl = newiTempLabel(NULL);
13318 /* save registers that need to be saved */
13319 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13320 ds390_rUmaskForOp (IC_RESULT(ic))));
13322 /* put libraryID into DPTR */
13323 emitcode ("mov","dptr,#LibraryID");
13324 /* make the call */
13325 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
13326 emitcode ("jnz","!tlabel",lbl->key+100);
13328 /* put return value into place */
13329 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
13330 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
13331 emitcode ("push","ar3");
13332 emitcode ("push","ar2");
13333 emitcode ("pop","%s",
13334 aopGet(IC_RESULT(ic),0,FALSE,TRUE,DP2_RESULT_REG));
13335 emitcode ("pop","%s",
13336 aopGet(IC_RESULT(ic),1,FALSE,TRUE,DP2_RESULT_REG));
13338 aopPut(IC_RESULT(ic),"r2",0);
13339 aopPut(IC_RESULT(ic),"r3",1);
13341 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13343 unsavermask(rsave);
13346 /*-----------------------------------------------------------------*/
13347 /* genMMMalloc - */
13348 /*-----------------------------------------------------------------*/
13349 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
13350 int size, const char *name)
13355 symbol *lbl = newiTempLabel(NULL);
13357 assert (nparms == 1);
13358 /* save registers that need to be saved */
13359 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13360 ds390_rUmaskForOp (IC_RESULT(ic))));
13363 aopOp (bsize,ic,FALSE,FALSE);
13365 /* put the size in R4-R2 */
13366 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
13367 emitcode("push","%s",aopGet(bsize,0,FALSE,TRUE,DP2_RESULT_REG));
13368 emitcode("push","%s",aopGet(bsize,1,FALSE,TRUE,DP2_RESULT_REG));
13370 emitcode("push","%s",aopGet(bsize,2,FALSE,TRUE,DP2_RESULT_REG));
13371 emitcode("pop","ar4");
13373 emitcode("pop","ar3");
13374 emitcode("pop","ar2");
13376 emitcode ("mov","r2,%s",aopGet(bsize,0,FALSE,TRUE,DP2_RESULT_REG));
13377 emitcode ("mov","r3,%s",aopGet(bsize,1,FALSE,TRUE,DP2_RESULT_REG));
13379 emitcode("mov","r4,%s",aopGet(bsize,2,FALSE,TRUE,DP2_RESULT_REG));
13382 freeAsmop (bsize, NULL, ic, FALSE);
13384 /* make the call */
13385 emitcode ("lcall","MM_%s",name);
13386 emitcode ("jz","!tlabel",lbl->key+100);
13387 emitcode ("mov","r2,#!constbyte",0xff);
13388 emitcode ("mov","r3,#!constbyte",0xff);
13390 /* we don't care about the pointer : we just save the handle */
13391 rsym = OP_SYMBOL(IC_RESULT(ic));
13392 if (rsym->liveFrom != rsym->liveTo) {
13393 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
13394 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
13395 emitcode ("push","ar3");
13396 emitcode ("push","ar2");
13397 emitcode ("pop","%s",
13398 aopGet(IC_RESULT(ic),0,FALSE,TRUE,DP2_RESULT_REG));
13399 emitcode ("pop","%s",
13400 aopGet(IC_RESULT(ic),1,FALSE,TRUE,DP2_RESULT_REG));
13402 aopPut(IC_RESULT(ic),"r2",0);
13403 aopPut(IC_RESULT(ic),"r3",1);
13405 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13407 unsavermask(rsave);
13410 /*-----------------------------------------------------------------*/
13412 /*-----------------------------------------------------------------*/
13413 static void genMMDeref (iCode *ic,int nparms, operand **parms)
13418 assert (nparms == 1);
13419 /* save registers that need to be saved */
13420 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13421 ds390_rUmaskForOp (IC_RESULT(ic))));
13424 aopOp (handle,ic,FALSE,FALSE);
13426 /* put the size in R4-R2 */
13427 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13428 emitcode("push","%s",
13429 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13430 emitcode("push","%s",
13431 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13432 emitcode("pop","ar3");
13433 emitcode("pop","ar2");
13435 emitcode ("mov","r2,%s",
13436 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13437 emitcode ("mov","r3,%s",
13438 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13440 freeAsmop (handle, NULL, ic, FALSE);
13442 /* make the call */
13443 emitcode ("lcall","MM_Deref");
13446 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13447 if (rsym->liveFrom != rsym->liveTo) {
13448 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13449 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
13450 _startLazyDPSEvaluation ();
13452 aopPut(IC_RESULT(ic),"dpl",0);
13453 aopPut(IC_RESULT(ic),"dph",1);
13454 aopPut(IC_RESULT(ic),"dpx",2);
13456 _endLazyDPSEvaluation ();
13461 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13462 unsavermask(rsave);
13465 /*-----------------------------------------------------------------*/
13466 /* genMMUnrestrictedPersist - */
13467 /*-----------------------------------------------------------------*/
13468 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
13473 assert (nparms == 1);
13474 /* save registers that need to be saved */
13475 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13476 ds390_rUmaskForOp (IC_RESULT(ic))));
13479 aopOp (handle,ic,FALSE,FALSE);
13481 /* put the size in R3-R2 */
13482 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13483 emitcode("push","%s",
13484 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13485 emitcode("push","%s",
13486 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13487 emitcode("pop","ar3");
13488 emitcode("pop","ar2");
13490 emitcode ("mov","r2,%s",
13491 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13492 emitcode ("mov","r3,%s",
13493 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13495 freeAsmop (handle, NULL, ic, FALSE);
13497 /* make the call */
13498 emitcode ("lcall","MM_UnrestrictedPersist");
13501 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13502 if (rsym->liveFrom != rsym->liveTo) {
13503 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13504 aopPut(IC_RESULT(ic),"a",0);
13505 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13508 unsavermask(rsave);
13511 /*-----------------------------------------------------------------*/
13512 /* genSystemExecJavaProcess - */
13513 /*-----------------------------------------------------------------*/
13514 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
13517 operand *handle, *pp;
13519 assert (nparms==2);
13520 /* save registers that need to be saved */
13521 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13522 ds390_rUmaskForOp (IC_RESULT(ic))));
13527 /* put the handle in R3-R2 */
13528 aopOp (handle,ic,FALSE,FALSE);
13529 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13530 emitcode("push","%s",
13531 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13532 emitcode("push","%s",
13533 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13534 emitcode("pop","ar3");
13535 emitcode("pop","ar2");
13537 emitcode ("mov","r2,%s",
13538 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13539 emitcode ("mov","r3,%s",
13540 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13542 freeAsmop (handle, NULL, ic, FALSE);
13544 /* put pointer in DPTR */
13545 aopOp (pp,ic,FALSE,FALSE);
13546 if (AOP_TYPE(pp) == AOP_IMMD) {
13547 emitcode ("mov", "dptr,%s",
13548 aopGet (pp, 0, TRUE, FALSE, NULL));
13549 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
13550 emitcode ("mov","dpl,%s",aopGet(pp,0,FALSE,FALSE,NULL));
13551 emitcode ("mov","dph,%s",aopGet(pp,1,FALSE,FALSE,NULL));
13552 emitcode ("mov","dpx,%s",aopGet(pp,2,FALSE,FALSE,NULL));
13554 freeAsmop (handle, NULL, ic, FALSE);
13556 /* make the call */
13557 emitcode ("lcall","System_ExecJavaProcess");
13559 /* put result in place */
13561 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13562 if (rsym->liveFrom != rsym->liveTo) {
13563 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13564 aopPut(IC_RESULT(ic),"a",0);
13565 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13569 unsavermask(rsave);
13572 /*-----------------------------------------------------------------*/
13573 /* genSystemRTCRegisters - */
13574 /*-----------------------------------------------------------------*/
13575 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
13581 assert (nparms==1);
13582 /* save registers that need to be saved */
13583 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13584 ds390_rUmaskForOp (IC_RESULT(ic))));
13587 /* put pointer in DPTR */
13588 aopOp (pp,ic,FALSE,FALSE);
13589 if (AOP_TYPE (pp) == AOP_IMMD) {
13590 emitcode ("mov","dps,#1");
13591 emitcode ("mov", "dptr,%s",
13592 aopGet (pp, 0, TRUE, FALSE, NULL));
13593 emitcode ("mov","dps,#0");
13595 emitcode ("mov","dpl1,%s",
13596 aopGet(pp,0,FALSE,FALSE,DP2_RESULT_REG));
13597 emitcode ("mov","dph1,%s",
13598 aopGet(pp,1,FALSE,FALSE,DP2_RESULT_REG));
13599 emitcode ("mov","dpx1,%s",
13600 aopGet(pp,2,FALSE,FALSE,DP2_RESULT_REG));
13602 freeAsmop (pp, NULL, ic, FALSE);
13604 /* make the call */
13605 emitcode ("lcall","System_%sRTCRegisters",name);
13607 unsavermask(rsave);
13610 /*-----------------------------------------------------------------*/
13611 /* genSystemThreadSleep - */
13612 /*-----------------------------------------------------------------*/
13613 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
13618 assert (nparms==1);
13619 /* save registers that need to be saved */
13620 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13621 ds390_rUmaskForOp (IC_RESULT(ic))));
13624 aopOp(to,ic,FALSE,FALSE);
13625 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
13626 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
13627 emitcode ("push","%s",
13628 aopGet(to,0,FALSE,TRUE,DP2_RESULT_REG));
13629 emitcode ("push","%s",
13630 aopGet(to,1,FALSE,TRUE,DP2_RESULT_REG));
13631 emitcode ("push","%s",
13632 aopGet(to,2,FALSE,TRUE,DP2_RESULT_REG));
13633 emitcode ("push","%s",
13634 aopGet(to,3,FALSE,TRUE,DP2_RESULT_REG));
13635 emitcode ("pop","ar3");
13636 emitcode ("pop","ar2");
13637 emitcode ("pop","ar1");
13638 emitcode ("pop","ar0");
13640 emitcode ("mov","r0,%s",
13641 aopGet(to,0,FALSE,TRUE,DP2_RESULT_REG));
13642 emitcode ("mov","r1,%s",
13643 aopGet(to,1,FALSE,TRUE,DP2_RESULT_REG));
13644 emitcode ("mov","r2,%s",
13645 aopGet(to,2,FALSE,TRUE,DP2_RESULT_REG));
13646 emitcode ("mov","r3,%s",
13647 aopGet(to,3,FALSE,TRUE,DP2_RESULT_REG));
13649 freeAsmop (to, NULL, ic, FALSE);
13651 /* suspend in acc */
13653 aopOp(s,ic,FALSE,FALSE);
13654 emitcode ("mov","a,%s",
13655 aopGet(s,0,FALSE,TRUE,NULL));
13656 freeAsmop (s, NULL, ic, FALSE);
13658 /* make the call */
13659 emitcode ("lcall","System_%s",name);
13661 unsavermask(rsave);
13664 /*-----------------------------------------------------------------*/
13665 /* genSystemThreadResume - */
13666 /*-----------------------------------------------------------------*/
13667 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
13672 assert (nparms==2);
13673 /* save registers that need to be saved */
13674 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13675 ds390_rUmaskForOp (IC_RESULT(ic))));
13681 aopOp(pid,ic,FALSE,FALSE);
13682 emitcode ("mov","r0,%s",
13683 aopGet(pid,0,FALSE,TRUE,DP2_RESULT_REG));
13684 freeAsmop (pid, NULL, ic, FALSE);
13687 aopOp(tid,ic,FALSE,FALSE);
13688 emitcode ("mov","a,%s",
13689 aopGet(tid,0,FALSE,TRUE,DP2_RESULT_REG));
13690 freeAsmop (tid, NULL, ic, FALSE);
13692 emitcode ("lcall","System_ThreadResume");
13694 /* put result into place */
13696 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13697 if (rsym->liveFrom != rsym->liveTo) {
13698 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13699 aopPut(IC_RESULT(ic),"a",0);
13700 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13703 unsavermask(rsave);
13706 /*-----------------------------------------------------------------*/
13707 /* genSystemProcessResume - */
13708 /*-----------------------------------------------------------------*/
13709 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
13714 assert (nparms==1);
13715 /* save registers that need to be saved */
13716 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13717 ds390_rUmaskForOp (IC_RESULT(ic))));
13722 aopOp(pid,ic,FALSE,FALSE);
13723 emitcode ("mov","a,%s",
13724 aopGet(pid,0,FALSE,TRUE,DP2_RESULT_REG));
13725 freeAsmop (pid, NULL, ic, FALSE);
13727 emitcode ("lcall","System_ProcessResume");
13729 unsavermask(rsave);
13732 /*-----------------------------------------------------------------*/
13734 /*-----------------------------------------------------------------*/
13735 static void genSystem (iCode *ic,int nparms,char *name)
13737 assert(nparms == 0);
13739 emitcode ("lcall","System_%s",name);
13742 /*-----------------------------------------------------------------*/
13743 /* genSystemPoll - */
13744 /*-----------------------------------------------------------------*/
13745 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
13750 assert (nparms==1);
13751 /* save registers that need to be saved */
13752 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13753 ds390_rUmaskForOp (IC_RESULT(ic))));
13756 aopOp (fp,ic,FALSE,FALSE);
13757 if (AOP_TYPE (fp) == AOP_IMMD) {
13758 emitcode ("mov", "dptr,%s",
13759 aopGet (fp, 0, TRUE, FALSE, DP2_RESULT_REG));
13760 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
13761 emitcode ("mov","dpl,%s",
13762 aopGet(fp,0,FALSE,FALSE,DP2_RESULT_REG));
13763 emitcode ("mov","dph,%s",
13764 aopGet(fp,1,FALSE,FALSE,DP2_RESULT_REG));
13765 emitcode ("mov","dpx,%s",
13766 aopGet(fp,2,FALSE,FALSE,DP2_RESULT_REG));
13768 freeAsmop (fp, NULL, ic, FALSE);
13770 emitcode ("lcall","System_%sPoll",name);
13772 /* put result into place */
13774 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13775 if (rsym->liveFrom != rsym->liveTo) {
13776 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13777 aopPut(IC_RESULT(ic),"a",0);
13778 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13781 unsavermask(rsave);
13784 /*-----------------------------------------------------------------*/
13785 /* genSystemGetCurrentID - */
13786 /*-----------------------------------------------------------------*/
13787 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
13789 assert (nparms==0);
13791 emitcode ("lcall","System_GetCurrent%sId",name);
13792 /* put result into place */
13794 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13795 if (rsym->liveFrom != rsym->liveTo) {
13796 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13797 aopPut(IC_RESULT(ic),"a",0);
13798 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13803 /*-----------------------------------------------------------------*/
13804 /* genDjnz - generate decrement & jump if not zero instrucion */
13805 /*-----------------------------------------------------------------*/
13807 genDjnz (iCode * ic, iCode * ifx)
13809 symbol *lbl, *lbl1;
13813 /* if the if condition has a false label
13814 then we cannot save */
13815 if (IC_FALSE (ifx))
13818 /* if the minus is not of the form a = a - 1 */
13819 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
13820 !IS_OP_LITERAL (IC_RIGHT (ic)))
13823 if (operandLitValue (IC_RIGHT (ic)) != 1)
13826 /* if the size of this greater than one then no
13828 if (getSize (operandType (IC_RESULT (ic))) > 1)
13831 /* otherwise we can save BIG */
13833 D (emitcode (";", "genDjnz"));
13835 lbl = newiTempLabel (NULL);
13836 lbl1 = newiTempLabel (NULL);
13838 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
13840 if (AOP_NEEDSACC(IC_RESULT(ic)))
13842 /* If the result is accessed indirectly via
13843 * the accumulator, we must explicitly write
13844 * it back after the decrement.
13846 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE, NULL);
13848 if (strcmp(rByte, "a"))
13850 /* Something is hopelessly wrong */
13851 fprintf(stderr, "*** warning: internal error at %s:%d\n",
13852 __FILE__, __LINE__);
13853 /* We can just give up; the generated code will be inefficient,
13854 * but what the hey.
13856 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13859 emitcode ("dec", "%s", rByte);
13860 aopPut (IC_RESULT (ic), rByte, 0);
13861 emitcode ("jnz", "!tlabel", lbl->key + 100);
13863 else if (IS_AOP_PREG (IC_RESULT (ic)))
13865 emitcode ("dec", "%s",
13866 aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL));
13867 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL));
13868 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13869 ifx->generated = 1;
13870 emitcode ("jnz", "!tlabel", lbl->key + 100);
13874 emitcode ("djnz", "%s,!tlabel", aopGet (IC_RESULT (ic), 0, FALSE, TRUE, NULL),
13877 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
13879 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
13882 if (!ifx->generated)
13883 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13884 ifx->generated = 1;
13888 /*-----------------------------------------------------------------*/
13889 /* genReceive - generate code for a receive iCode */
13890 /*-----------------------------------------------------------------*/
13892 genReceive (iCode * ic)
13894 int size = getSize (operandType (IC_RESULT (ic)));
13898 D (emitcode (";", "genReceive"));
13900 if (ic->argreg == 1)
13902 /* first parameter */
13903 if (AOP_IS_STR(IC_RESULT(ic)))
13905 /* Nothing to do: it's already in the proper place. */
13912 useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
13913 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
13914 IS_TRUE_SYMOP (IC_RESULT (ic)));
13917 aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
13920 /* Sanity checking... */
13921 if (AOP_USESDPTR(IC_RESULT(ic)))
13923 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
13924 "genReceive got unexpected DPTR.");
13926 assignResultValue (IC_RESULT (ic), NULL);
13929 else if (ic->argreg > 12)
13930 { /* bit parameters */
13931 if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
13933 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
13934 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
13935 outBitC(IC_RESULT (ic));
13940 /* second receive onwards */
13941 /* this gets a little tricky since unused receives will be
13942 eliminated, we have saved the reg in the type field . and
13943 we use that to figure out which register to use */
13944 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
13945 rb1off = ic->argreg;
13948 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
13951 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13954 /*-----------------------------------------------------------------*/
13955 /* genDummyRead - generate code for dummy read of volatiles */
13956 /*-----------------------------------------------------------------*/
13958 genDummyRead (iCode * ic)
13963 D (emitcode(";", "genDummyRead"));
13965 op = IC_RIGHT (ic);
13966 if (op && IS_SYMOP (op))
13968 aopOp (op, ic, FALSE, FALSE);
13970 /* if the result is a bit */
13971 if (AOP_TYPE (op) == AOP_CRY)
13972 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13975 /* bit variables done */
13977 size = AOP_SIZE (op);
13981 MOVA (aopGet (op, offset, FALSE, FALSE, FALSE));
13986 freeAsmop (op, NULL, ic, TRUE);
13990 if (op && IS_SYMOP (op))
13992 aopOp (op, ic, FALSE, FALSE);
13994 /* if the result is a bit */
13995 if (AOP_TYPE (op) == AOP_CRY)
13996 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13999 /* bit variables done */
14001 size = AOP_SIZE (op);
14005 MOVA (aopGet (op, offset, FALSE, FALSE, FALSE));
14010 freeAsmop (op, NULL, ic, TRUE);
14014 /*-----------------------------------------------------------------*/
14015 /* genCritical - generate code for start of a critical sequence */
14016 /*-----------------------------------------------------------------*/
14018 genCritical (iCode *ic)
14020 symbol *tlbl = newiTempLabel (NULL);
14022 D (emitcode(";", "genCritical"));
14024 if (IC_RESULT (ic))
14026 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
14027 aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
14028 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
14029 aopPut (IC_RESULT (ic), zero, 0);
14031 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
14035 emitcode ("setb", "c");
14036 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
14037 emitcode ("clr", "c");
14039 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
14043 /*-----------------------------------------------------------------*/
14044 /* genEndCritical - generate code for end of a critical sequence */
14045 /*-----------------------------------------------------------------*/
14047 genEndCritical (iCode *ic)
14049 D(emitcode(";", "genEndCritical"));
14053 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
14054 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
14056 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
14057 emitcode ("mov", "ea,c");
14061 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE, FALSE));
14062 emitcode ("rrc", "a");
14063 emitcode ("mov", "ea,c");
14065 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
14069 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
14070 emitcode ("mov", "ea,c");
14076 /*-----------------------------------------------------------------*/
14077 /* genBuiltIn - calls the appropriate function to generating code */
14078 /* for a built in function */
14079 /*-----------------------------------------------------------------*/
14080 static void genBuiltIn (iCode *ic)
14082 operand *bi_parms[MAX_BUILTIN_ARGS];
14087 /* get all the arguments for a built in function */
14088 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
14090 /* which function is it */
14091 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
14092 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
14093 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
14094 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
14095 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
14096 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
14097 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
14098 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
14099 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
14100 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
14101 genMemsetX(bi_iCode,nbi_parms,bi_parms);
14102 } else if (strcmp(bif->name,"__builtin_inp")==0) {
14103 genInp(bi_iCode,nbi_parms,bi_parms);
14104 } else if (strcmp(bif->name,"__builtin_outp")==0) {
14105 genOutp(bi_iCode,nbi_parms,bi_parms);
14106 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
14107 genSwapW(bi_iCode,nbi_parms,bi_parms);
14108 /* JavaNative builtIns */
14109 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
14110 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
14111 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
14112 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
14113 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
14114 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
14115 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
14116 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
14117 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
14118 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
14119 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
14120 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
14121 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
14122 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
14123 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
14124 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
14125 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
14126 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
14127 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
14128 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
14129 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
14130 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
14131 } else if (strcmp(bif->name,"MM_Malloc")==0) {
14132 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
14133 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
14134 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
14135 } else if (strcmp(bif->name,"MM_Free")==0) {
14136 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
14137 } else if (strcmp(bif->name,"MM_Deref")==0) {
14138 genMMDeref(bi_iCode,nbi_parms,bi_parms);
14139 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
14140 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
14141 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
14142 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
14143 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
14144 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
14145 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
14146 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
14147 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
14148 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
14149 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
14150 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
14151 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
14152 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
14153 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
14154 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
14155 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
14156 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
14157 } else if (strcmp(bif->name,"System_SaveThread")==0) {
14158 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
14159 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
14160 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
14161 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
14162 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
14163 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
14164 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
14165 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
14166 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
14167 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
14168 genSystem(bi_iCode,nbi_parms,"ProcessYield");
14169 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
14170 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
14171 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
14172 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
14173 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
14174 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
14175 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
14176 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
14177 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
14178 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
14180 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
14186 /*-----------------------------------------------------------------*/
14187 /* gen390Code - generate code for Dallas 390 based controllers */
14188 /*-----------------------------------------------------------------*/
14190 gen390Code (iCode * lic)
14195 _G.currentFunc = NULL;
14196 lineHead = lineCurr = NULL;
14197 dptrn[1][0] = "dpl1";
14198 dptrn[1][1] = "dph1";
14199 dptrn[1][2] = "dpx1";
14201 if (options.model == MODEL_FLAT24) {
14202 fReturnSizeDS390 = 5;
14203 fReturn = fReturn24;
14205 fReturnSizeDS390 = 4;
14206 fReturn = fReturn16;
14207 options.stack10bit=0;
14210 /* print the allocation information */
14211 if (allocInfo && currFunc)
14212 printAllocInfo (currFunc, codeOutBuf);
14214 /* if debug information required */
14215 if (options.debug && currFunc)
14217 debugFile->writeFunction (currFunc, lic);
14219 /* stack pointer name */
14220 if (options.useXstack)
14226 for (ic = lic; ic; ic = ic->next)
14228 _G.current_iCode = ic;
14230 if (ic->lineno && cln != ic->lineno)
14234 debugFile->writeCLine (ic);
14236 if (!options.noCcodeInAsm) {
14237 emitcode (";", "%s:%d: %s", ic->filename, ic->lineno,
14238 printCLine(ic->filename, ic->lineno));
14242 if (options.iCodeInAsm) {
14243 char *iLine = printILine(ic);
14244 emitcode(";", "ic:%d: %s", ic->key, iLine);
14247 /* if the result is marked as
14248 spilt and rematerializable or code for
14249 this has already been generated then
14251 if (resultRemat (ic) || ic->generated)
14254 /* depending on the operation */
14274 /* IPOP happens only when trying to restore a
14275 spilt live range, if there is an ifx statement
14276 following this pop then the if statement might
14277 be using some of the registers being popped which
14278 would destory the contents of the register so
14279 we need to check for this condition and handle it */
14281 ic->next->op == IFX &&
14282 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
14283 genIfx (ic->next, ic);
14301 genEndFunction (ic);
14321 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
14338 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
14342 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
14349 /* note these two are xlated by algebraic equivalence
14350 during parsing SDCC.y */
14351 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
14352 "got '>=' or '<=' shouldn't have come here");
14356 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
14368 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
14372 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
14376 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
14400 genRightShift (ic);
14403 case GET_VALUE_AT_ADDRESS:
14405 hasInc (IC_LEFT (ic), ic,
14406 getSize (operandType (IC_RESULT (ic)))));
14410 if (POINTER_SET (ic))
14412 hasInc (IC_RESULT (ic), ic,
14413 getSize (operandType (IC_RIGHT (ic)))));
14439 if (ic->builtinSEND)
14442 addSet (&_G.sendSet, ic);
14445 case DUMMY_READ_VOLATILE:
14454 genEndCritical (ic);
14461 #if 0 // obsolete, and buggy for != xdata
14468 /* This should never happen, right? */
14469 fprintf(stderr, "*** Probable error: unsupported op 0x%x (%c) in %s @ %d\n",
14470 ic->op, ic->op, __FILE__, __LINE__);
14476 /* now we are ready to call the
14477 peep hole optimizer */
14478 if (!options.nopeep)
14479 peepHole (&lineHead);
14481 /* now do the actual printing */
14482 printLine (lineHead, codeOutBuf);