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) ulFromVal (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) ulFromVal (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 (ulFromVal (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) ulFromVal (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) ulFromVal (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) ulFromVal (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) ulFromVal (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) ulFromVal (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) ulFromVal (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) ulFromVal (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) ulFromVal (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) ulFromVal (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) ulFromVal (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) ulFromVal (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) ulFromVal (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) ulFromVal (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) ulFromVal (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) ulFromVal (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 = ulFromVal (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 = ulFromVal (AOP (right)->aopu.aop_lit);
6456 // emitcode (";", "genCmp #3.1");
6457 emitcode ("subb", "a,#!constbyte",
6458 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
6462 // emitcode (";", "genCmp #3.2");
6464 MOVB (aopGet (right, offset++, FALSE, FALSE, "b"));
6465 saveAccWarn = DEFAULT_ACC_WARNING;
6466 emitcode ("xrl", "b,#!constbyte",0x80);
6467 emitcode ("subb", "a,b");
6474 // emitcode (";", "genCmp #4");
6476 s = aopGet (right, offset++, FALSE, FALSE, "b");
6477 saveAccWarn = DEFAULT_ACC_WARNING;
6479 emitcode ("subb", "a,%s", s);
6486 /* Don't need the left & right operands any more; do need the result. */
6487 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6488 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6490 aopOp (result, ic, FALSE, FALSE);
6494 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6500 /* if the result is used in the next
6501 ifx conditional branch then generate
6502 code a little differently */
6505 genIfxJump (ifx, "c");
6511 /* leave the result in acc */
6513 freeAsmop (result, NULL, ic, TRUE);
6516 /*-----------------------------------------------------------------*/
6517 /* genCmpGt :- greater than comparison */
6518 /*-----------------------------------------------------------------*/
6520 genCmpGt (iCode * ic, iCode * ifx)
6522 operand *left, *right;
6523 sym_link *letype, *retype;
6526 D (emitcode (";", "genCmpGt"));
6528 left = IC_LEFT (ic);
6529 right = IC_RIGHT (ic);
6531 letype = getSpec (operandType (left));
6532 retype = getSpec (operandType (right));
6533 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6535 /* assign the left & right amsops */
6538 genCmp (right, left, ic, ifx, sign);
6541 /*-----------------------------------------------------------------*/
6542 /* genCmpLt - less than comparisons */
6543 /*-----------------------------------------------------------------*/
6545 genCmpLt (iCode * ic, iCode * ifx)
6547 operand *left, *right;
6548 sym_link *letype, *retype;
6551 D (emitcode (";", "genCmpLt"));
6553 left = IC_LEFT (ic);
6554 right = IC_RIGHT (ic);
6556 letype = getSpec (operandType (left));
6557 retype = getSpec (operandType (right));
6558 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6560 /* assign the left & right amsops */
6563 genCmp (left, right, ic, ifx, sign);
6566 /*-----------------------------------------------------------------*/
6567 /* gencjneshort - compare and jump if not equal */
6568 /*-----------------------------------------------------------------*/
6570 gencjneshort (operand * left, operand * right, symbol * lbl)
6572 int size = max (AOP_SIZE (left), AOP_SIZE (right));
6574 unsigned long lit = 0L;
6576 D (emitcode (";", "gencjneshort"));
6578 /* if the left side is a literal or
6579 if the right is in a pointer register and left
6581 if ((AOP_TYPE (left) == AOP_LIT) ||
6582 (AOP_TYPE (left) == AOP_IMMD) ||
6583 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6590 if (AOP_TYPE (right) == AOP_LIT)
6591 lit = ulFromVal (AOP (right)->aopu.aop_lit);
6593 if (opIsGptr (left) || opIsGptr (right))
6595 /* We are comparing a generic pointer to something.
6596 * Exclude the generic type byte from the comparison.
6599 D (emitcode (";", "cjneshort: generic ptr special case."););
6603 /* if the right side is a literal then anything goes */
6604 if (AOP_TYPE (right) == AOP_LIT &&
6605 AOP_TYPE (left) != AOP_DIR)
6609 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
6610 emitcode ("cjne", "a,%s,!tlabel",
6611 aopGet (right, offset, FALSE, FALSE, NULL),
6617 /* if the right side is in a register or in direct space or
6618 if the left is a pointer register & right is not */
6619 else if (AOP_TYPE (right) == AOP_REG ||
6620 AOP_TYPE (right) == AOP_DIR ||
6621 AOP_TYPE (right) == AOP_LIT ||
6622 AOP_TYPE (right) == AOP_IMMD ||
6623 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6624 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6628 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
6629 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6630 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6631 emitcode ("jnz", "!tlabel", lbl->key + 100);
6633 emitcode ("cjne", "a,%s,!tlabel",
6634 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG),
6641 /* right is a pointer reg need both a & b */
6644 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
6645 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
6646 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
6652 /*-----------------------------------------------------------------*/
6653 /* gencjne - compare and jump if not equal */
6654 /*-----------------------------------------------------------------*/
6656 gencjne (operand * left, operand * right, symbol * lbl)
6658 symbol *tlbl = newiTempLabel (NULL);
6660 D (emitcode (";", "gencjne"));
6662 gencjneshort (left, right, lbl);
6664 emitcode ("mov", "a,%s", one);
6665 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
6667 emitcode ("clr", "a");
6671 /*-----------------------------------------------------------------*/
6672 /* genCmpEq - generates code for equal to */
6673 /*-----------------------------------------------------------------*/
6675 genCmpEq (iCode * ic, iCode * ifx)
6677 operand *left, *right, *result;
6679 D (emitcode (";", "genCmpEq"));
6682 AOP_SET_LOCALS (ic);
6684 /* if literal, literal on the right or
6685 if the right is in a pointer register and left
6687 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6688 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6690 operand *t = IC_RIGHT (ic);
6691 IC_RIGHT (ic) = IC_LEFT (ic);
6695 if (ifx && /* !AOP_SIZE(result) */
6696 OP_SYMBOL (result) &&
6697 OP_SYMBOL (result)->regType == REG_CND)
6700 /* if they are both bit variables */
6701 if (AOP_TYPE (left) == AOP_CRY &&
6702 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6704 if (AOP_TYPE (right) == AOP_LIT)
6706 unsigned long lit = ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6709 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6710 emitcode ("cpl", "c");
6714 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6718 emitcode ("clr", "c");
6720 /* AOP_TYPE(right) == AOP_CRY */
6724 symbol *lbl = newiTempLabel (NULL);
6725 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6726 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6727 emitcode ("cpl", "c");
6730 /* if true label then we jump if condition
6732 tlbl = newiTempLabel (NULL);
6735 emitcode ("jnc", "!tlabel", tlbl->key + 100);
6736 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6740 emitcode ("jc", "!tlabel", tlbl->key + 100);
6741 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6747 tlbl = newiTempLabel (NULL);
6748 gencjneshort (left, right, tlbl);
6751 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6756 symbol *lbl = newiTempLabel (NULL);
6757 emitcode ("sjmp", "!tlabel", lbl->key + 100);
6759 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6763 /* mark the icode as generated */
6766 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6767 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6771 /* if they are both bit variables */
6772 if (AOP_TYPE (left) == AOP_CRY &&
6773 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6775 if (AOP_TYPE (right) == AOP_LIT)
6777 unsigned long lit = ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6780 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6781 emitcode ("cpl", "c");
6785 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6789 emitcode ("clr", "c");
6791 /* AOP_TYPE(right) == AOP_CRY */
6795 symbol *lbl = newiTempLabel (NULL);
6796 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6797 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6798 emitcode ("cpl", "c");
6802 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6803 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6805 aopOp (result, ic, TRUE, FALSE);
6808 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6815 genIfxJump (ifx, "c");
6818 /* if the result is used in an arithmetic operation
6819 then put the result in place */
6824 gencjne (left, right, newiTempLabel (NULL));
6826 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6827 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6829 aopOp (result, ic, TRUE, FALSE);
6831 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6833 aopPut (result, "a", 0);
6838 genIfxJump (ifx, "a");
6841 /* if the result is used in an arithmetic operation
6842 then put the result in place */
6843 if (AOP_TYPE (result) != AOP_CRY)
6845 /* leave the result in acc */
6849 freeAsmop (result, NULL, ic, TRUE);
6852 /*-----------------------------------------------------------------*/
6853 /* ifxForOp - returns the icode containing the ifx for operand */
6854 /*-----------------------------------------------------------------*/
6856 ifxForOp (operand * op, iCode * ic)
6858 /* if true symbol then needs to be assigned */
6859 if (IS_TRUE_SYMOP (op))
6862 /* if this has register type condition and
6863 the next instruction is ifx with the same operand
6864 and live to of the operand is upto the ifx only then */
6866 ic->next->op == IFX &&
6867 IC_COND (ic->next)->key == op->key &&
6868 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6874 /*-----------------------------------------------------------------*/
6875 /* hasInc - operand is incremented before any other use */
6876 /*-----------------------------------------------------------------*/
6878 hasInc (operand *op, iCode *ic, int osize)
6880 sym_link *type = operandType(op);
6881 sym_link *retype = getSpec (type);
6882 iCode *lic = ic->next;
6885 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6886 if (!IS_SYMOP(op)) return NULL;
6888 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6889 if (IS_AGGREGATE(type->next)) return NULL;
6890 if (osize != (isize = getSize(type->next))) return NULL;
6893 /* if operand of the form op = op + <sizeof *op> */
6894 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6895 isOperandEqual(IC_RESULT(lic),op) &&
6896 isOperandLiteral(IC_RIGHT(lic)) &&
6897 operandLitValue(IC_RIGHT(lic)) == isize) {
6900 /* if the operand used or deffed */
6901 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6904 /* if GOTO or IFX */
6905 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6911 /*-----------------------------------------------------------------*/
6912 /* genAndOp - for && operation */
6913 /*-----------------------------------------------------------------*/
6915 genAndOp (iCode * ic)
6917 operand *left, *right, *result;
6920 D (emitcode (";", "genAndOp"));
6922 /* note here that && operations that are in an
6923 if statement are taken away by backPatchLabels
6924 only those used in arthmetic operations remain */
6926 AOP_SET_LOCALS (ic);
6928 /* if both are bit variables */
6929 if (AOP_TYPE (left) == AOP_CRY &&
6930 AOP_TYPE (right) == AOP_CRY)
6932 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6933 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6934 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6935 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6937 aopOp (result,ic,FALSE, FALSE);
6942 tlbl = newiTempLabel (NULL);
6944 emitcode ("jz", "!tlabel", tlbl->key + 100);
6947 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6948 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6950 aopOp (result,ic,FALSE, FALSE);
6954 freeAsmop (result, NULL, ic, TRUE);
6958 /*-----------------------------------------------------------------*/
6959 /* genOrOp - for || operation */
6960 /*-----------------------------------------------------------------*/
6962 genOrOp (iCode * ic)
6964 operand *left, *right, *result;
6967 D (emitcode (";", "genOrOp"));
6969 /* note here that || operations that are in an
6970 if statement are taken away by backPatchLabels
6971 only those used in arthmetic operations remain */
6973 AOP_SET_LOCALS (ic);
6975 /* if both are bit variables */
6976 if (AOP_TYPE (left) == AOP_CRY &&
6977 AOP_TYPE (right) == AOP_CRY)
6979 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6980 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6981 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6982 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6984 aopOp (result,ic,FALSE, FALSE);
6990 tlbl = newiTempLabel (NULL);
6992 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6995 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6996 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6998 aopOp (result,ic,FALSE, FALSE);
7003 freeAsmop (result, NULL, ic, TRUE);
7006 /*-----------------------------------------------------------------*/
7007 /* isLiteralBit - test if lit == 2^n */
7008 /*-----------------------------------------------------------------*/
7010 isLiteralBit (unsigned long lit)
7012 unsigned long pw[32] =
7013 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
7014 0x100L, 0x200L, 0x400L, 0x800L,
7015 0x1000L, 0x2000L, 0x4000L, 0x8000L,
7016 0x10000L, 0x20000L, 0x40000L, 0x80000L,
7017 0x100000L, 0x200000L, 0x400000L, 0x800000L,
7018 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
7019 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
7022 for (idx = 0; idx < 32; idx++)
7028 /*-----------------------------------------------------------------*/
7029 /* continueIfTrue - */
7030 /*-----------------------------------------------------------------*/
7032 continueIfTrue (iCode * ic)
7035 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
7039 /*-----------------------------------------------------------------*/
7041 /*-----------------------------------------------------------------*/
7043 jumpIfTrue (iCode * ic)
7046 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
7050 /*-----------------------------------------------------------------*/
7051 /* jmpTrueOrFalse - */
7052 /*-----------------------------------------------------------------*/
7054 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
7056 // ugly but optimized by peephole
7059 symbol *nlbl = newiTempLabel (NULL);
7060 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
7062 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
7067 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
7073 // Generate code to perform a bit-wise logic operation
7074 // on two operands in far space (assumed to already have been
7075 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
7076 // in far space. This requires pushing the result on the stack
7077 // then popping it into the result.
7079 genFarFarLogicOp(iCode *ic, char *logicOp)
7081 int size, resultSize, compSize;
7085 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
7086 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
7087 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
7089 _startLazyDPSEvaluation();
7090 for (size = compSize; (size--); offset++)
7092 MOVA (aopGet (IC_LEFT(ic), offset, FALSE, FALSE, NULL));
7093 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
7094 MOVA (aopGet (IC_RIGHT(ic), offset, FALSE, FALSE, NULL));
7096 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
7097 emitcode ("push", "acc");
7099 _endLazyDPSEvaluation();
7101 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7102 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7103 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
7105 resultSize = AOP_SIZE(IC_RESULT(ic));
7107 ADJUST_PUSHED_RESULT(compSize, resultSize);
7109 _startLazyDPSEvaluation();
7112 emitcode ("pop", "acc");
7113 aopPut (IC_RESULT (ic), "a", compSize);
7115 _endLazyDPSEvaluation();
7116 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
7120 /*-----------------------------------------------------------------*/
7121 /* genAnd - code for and */
7122 /*-----------------------------------------------------------------*/
7124 genAnd (iCode * ic, iCode * ifx)
7126 operand *left, *right, *result;
7127 int size, offset = 0;
7128 unsigned long lit = 0L;
7133 D (emitcode (";", "genAnd"));
7135 AOP_OP_3_NOFATAL (ic, pushResult);
7136 AOP_SET_LOCALS (ic);
7140 genFarFarLogicOp(ic, "anl");
7145 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
7147 AOP_TYPE (left), AOP_TYPE (right));
7148 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
7150 AOP_SIZE (left), AOP_SIZE (right));
7153 /* if left is a literal & right is not then exchange them */
7154 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7155 #ifdef LOGIC_OPS_BROKEN
7156 || AOP_NEEDSACC (left)
7160 operand *tmp = right;
7165 /* if result = right then exchange left and right */
7166 if (sameRegs (AOP (result), AOP (right)))
7168 operand *tmp = right;
7173 /* if right is bit then exchange them */
7174 if (AOP_TYPE (right) == AOP_CRY &&
7175 AOP_TYPE (left) != AOP_CRY)
7177 operand *tmp = right;
7181 if (AOP_TYPE (right) == AOP_LIT)
7182 lit = ulFromVal (AOP (right)->aopu.aop_lit);
7184 size = AOP_SIZE (result);
7187 // result = bit & yy;
7188 if (AOP_TYPE (left) == AOP_CRY)
7190 // c = bit & literal;
7191 if (AOP_TYPE (right) == AOP_LIT)
7195 if (size && sameRegs (AOP (result), AOP (left)))
7198 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7203 if (size && (AOP_TYPE (result) == AOP_CRY))
7205 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
7208 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7213 emitcode ("clr", "c");
7218 if (AOP_TYPE (right) == AOP_CRY)
7221 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7222 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
7227 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
7229 emitcode ("rrc", "a");
7230 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
7238 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7239 genIfxJump (ifx, "c");
7243 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7244 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7245 if ((AOP_TYPE (right) == AOP_LIT) &&
7246 (AOP_TYPE (result) == AOP_CRY) &&
7247 (AOP_TYPE (left) != AOP_CRY))
7249 int posbit = isLiteralBit (lit);
7254 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE, NULL));
7258 switch (posbit & 0x07)
7260 case 0: emitcode ("rrc", "a");
7262 case 7: emitcode ("rlc", "a");
7264 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
7273 SNPRINTF (buffer, sizeof(buffer),
7274 "acc.%d", posbit & 0x07);
7275 genIfxJump (ifx, buffer);
7279 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
7286 symbol *tlbl = newiTempLabel (NULL);
7287 int sizel = AOP_SIZE (left);
7289 emitcode ("setb", "c");
7292 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
7294 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7296 if ((posbit = isLiteralBit (bytelit)) != 0)
7297 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
7300 if (bytelit != 0x0FFL)
7301 emitcode ("anl", "a,%s",
7302 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG));
7303 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7308 // bit = left & literal
7311 emitcode ("clr", "c");
7314 // if(left & literal)
7318 jmpTrueOrFalse (ifx, tlbl);
7328 /* if left is same as result */
7329 if (sameRegs (AOP (result), AOP (left)))
7331 for (; size--; offset++)
7333 if (AOP_TYPE (right) == AOP_LIT)
7335 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7336 if (bytelit == 0x0FF)
7338 /* dummy read of volatile operand */
7339 if (isOperandVolatile (left, FALSE))
7340 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7344 else if (bytelit == 0)
7346 aopPut (result, zero, offset);
7348 else if (IS_AOP_PREG (result))
7350 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7351 emitcode ("anl", "a,%s",
7352 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG));
7353 aopPut (result, "a", offset);
7356 emitcode ("anl", "%s,%s",
7357 aopGet (left, offset, FALSE, TRUE, NULL),
7358 aopGet (right, offset, FALSE, FALSE, NULL));
7362 if (AOP_TYPE (left) == AOP_ACC)
7365 emitcode("mov", "a,b");
7366 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7368 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7370 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
7371 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7372 emitcode ("anl", "a,b");
7373 aopPut (result, "a", offset);
7375 else if (aopGetUsesAcc (left, offset))
7377 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7378 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7379 aopPut (result, "a", offset);
7383 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7384 if (IS_AOP_PREG (result))
7386 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7387 aopPut (result, "a", offset);
7390 emitcode ("anl", "%s,a", aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7397 // left & result in different registers
7398 if (AOP_TYPE (result) == AOP_CRY)
7401 // if(size), result in bit
7402 // if(!size && ifx), conditional oper: if(left & right)
7403 symbol *tlbl = newiTempLabel (NULL);
7404 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
7406 emitcode ("setb", "c");
7409 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7410 && AOP_TYPE(left)==AOP_ACC)
7413 emitcode("mov", "a,b");
7414 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, NULL));
7416 else if (AOP_TYPE(left)==AOP_ACC)
7420 bool pushedB = pushB ();
7421 emitcode("mov", "b,a");
7422 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7423 emitcode("anl", "a,b");
7428 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7429 emitcode("anl", "a,b");
7432 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7434 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE, NULL));
7435 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7436 emitcode ("anl", "a,b");
7438 else if (aopGetUsesAcc (left, offset))
7440 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7441 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7445 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7446 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE, DP2_RESULT_REG));
7449 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7459 jmpTrueOrFalse (ifx, tlbl);
7465 for (; (size--); offset++)
7468 // result = left & right
7469 if (AOP_TYPE (right) == AOP_LIT)
7471 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7472 if (bytelit == 0x0FF)
7475 aopGet (left, offset, FALSE, FALSE, NULL),
7479 else if (bytelit == 0)
7481 /* dummy read of volatile operand */
7482 if (isOperandVolatile (left, FALSE))
7483 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7484 aopPut (result, zero, offset);
7487 else if (AOP_TYPE (left) == AOP_ACC)
7491 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, NULL));
7492 aopPut (result, "a", offset);
7497 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE, NULL));
7498 aopPut (result, "b", offset);
7503 // faster than result <- left, anl result,right
7504 // and better if result is SFR
7505 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7506 && AOP_TYPE(left)==AOP_ACC)
7509 emitcode("mov", "a,b");
7510 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, NULL));
7512 else if (AOP_TYPE(left)==AOP_ACC)
7516 bool pushedB = pushB ();
7517 emitcode("mov", "b,a");
7518 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7519 emitcode("anl", "a,b");
7524 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7525 emitcode("anl", "a,b");
7528 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7530 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
7531 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7532 emitcode ("anl", "a,b");
7534 else if (aopGetUsesAcc (left, offset))
7536 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7537 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7541 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7542 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE, DP2_RESULT_REG));
7544 aopPut (result, "a", offset);
7550 freeAsmop (result, NULL, ic, TRUE);
7551 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7552 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7555 /*-----------------------------------------------------------------*/
7556 /* genOr - code for or */
7557 /*-----------------------------------------------------------------*/
7559 genOr (iCode * ic, iCode * ifx)
7561 operand *left, *right, *result;
7562 int size, offset = 0;
7563 unsigned long lit = 0L;
7567 D (emitcode (";", "genOr"));
7569 AOP_OP_3_NOFATAL (ic, pushResult);
7570 AOP_SET_LOCALS (ic);
7574 genFarFarLogicOp(ic, "orl");
7580 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
7582 AOP_TYPE (left), AOP_TYPE (right));
7583 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
7585 AOP_SIZE (left), AOP_SIZE (right));
7588 /* if left is a literal & right is not then exchange them */
7589 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7590 #ifdef LOGIC_OPS_BROKEN
7591 || AOP_NEEDSACC (left) // I think this is a net loss now.
7595 operand *tmp = right;
7600 /* if result = right then exchange them */
7601 if (sameRegs (AOP (result), AOP (right)))
7603 operand *tmp = right;
7608 /* if right is bit then exchange them */
7609 if (AOP_TYPE (right) == AOP_CRY &&
7610 AOP_TYPE (left) != AOP_CRY)
7612 operand *tmp = right;
7616 if (AOP_TYPE (right) == AOP_LIT)
7617 lit = ulFromVal (AOP (right)->aopu.aop_lit);
7619 size = AOP_SIZE (result);
7623 if (AOP_TYPE (left) == AOP_CRY)
7625 if (AOP_TYPE (right) == AOP_LIT)
7627 // c = bit | literal;
7630 // lit != 0 => result = 1
7631 if (AOP_TYPE (result) == AOP_CRY)
7634 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7636 continueIfTrue (ifx);
7639 emitcode ("setb", "c");
7643 // lit == 0 => result = left
7644 if (size && sameRegs (AOP (result), AOP (left)))
7646 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7651 if (AOP_TYPE (right) == AOP_CRY)
7654 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7655 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7660 symbol *tlbl = newiTempLabel (NULL);
7661 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
7662 emitcode ("setb", "c");
7663 emitcode ("jb", "%s,!tlabel",
7664 AOP (left)->aopu.aop_dir, tlbl->key + 100);
7666 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7667 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7669 jmpTrueOrFalse (ifx, tlbl);
7684 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7685 genIfxJump (ifx, "c");
7689 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7690 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7691 if ((AOP_TYPE (right) == AOP_LIT) &&
7692 (AOP_TYPE (result) == AOP_CRY) &&
7693 (AOP_TYPE (left) != AOP_CRY))
7699 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7701 continueIfTrue (ifx);
7706 // lit = 0, result = boolean(left)
7708 emitcode ("setb", "c");
7712 symbol *tlbl = newiTempLabel (NULL);
7713 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7719 genIfxJump (ifx, "a");
7727 /* if left is same as result */
7728 if (sameRegs (AOP (result), AOP (left)))
7730 for (; size--; offset++)
7732 if (AOP_TYPE (right) == AOP_LIT)
7734 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7737 /* dummy read of volatile operand */
7738 if (isOperandVolatile (left, FALSE))
7739 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7743 else if (bytelit == 0x0FF)
7745 aopPut (result, "#0xFF", offset);
7747 else if (IS_AOP_PREG (left))
7749 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7750 emitcode ("orl", "a,%s",
7751 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7752 aopPut (result, "a", offset);
7756 emitcode ("orl", "%s,%s",
7757 aopGet (left, offset, FALSE, TRUE, NULL),
7758 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7763 if (AOP_TYPE (left) == AOP_ACC)
7766 emitcode("mov", "a,b");
7767 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7769 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7771 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE, NULL));
7772 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7773 emitcode ("orl", "a,b");
7774 aopPut (result, "a", offset);
7776 else if (aopGetUsesAcc (left, offset))
7778 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7779 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7780 aopPut (result, "a", offset);
7784 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7785 if (IS_AOP_PREG (left))
7787 emitcode ("orl", "a,%s",
7788 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7789 aopPut (result, "a", offset);
7793 emitcode ("orl", "%s,a",
7794 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7802 // left & result in different registers
7803 if (AOP_TYPE (result) == AOP_CRY)
7806 // if(size), result in bit
7807 // if(!size && ifx), conditional oper: if(left | right)
7808 symbol *tlbl = newiTempLabel (NULL);
7809 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7811 emitcode ("setb", "c");
7814 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7815 && AOP_TYPE(left)==AOP_ACC)
7818 emitcode("mov", "a,b");
7819 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7821 else if (AOP_TYPE(left)==AOP_ACC)
7825 bool pushedB = pushB ();
7826 emitcode("mov", "b,a");
7827 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7828 emitcode("orl", "a,b");
7833 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7834 emitcode("orl", "a,b");
7837 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7839 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
7840 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7841 emitcode ("orl", "a,b");
7843 else if (aopGetUsesAcc (left, offset))
7845 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7846 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7850 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7851 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE, DP2_RESULT_REG));
7854 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7864 jmpTrueOrFalse (ifx, tlbl);
7870 _startLazyDPSEvaluation();
7871 for (; (size--); offset++)
7874 // result = left | right
7875 if (AOP_TYPE (right) == AOP_LIT)
7877 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7881 aopGet (left, offset, FALSE, FALSE, NULL),
7885 else if (bytelit == 0x0FF)
7887 /* dummy read of volatile operand */
7888 if (isOperandVolatile (left, FALSE))
7889 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7890 aopPut (result, "#0xFF", offset);
7894 // faster than result <- left, orl result,right
7895 // and better if result is SFR
7896 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7897 && AOP_TYPE(left)==AOP_ACC)
7900 emitcode("mov", "a,b");
7901 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7903 else if (AOP_TYPE(left)==AOP_ACC)
7907 bool pushedB = pushB ();
7908 emitcode("mov", "b,a");
7909 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7910 emitcode("orl", "a,b");
7915 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7916 emitcode("orl", "a,b");
7919 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7921 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
7922 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7923 emitcode ("orl", "a,b");
7925 else if (aopGetUsesAcc (left, offset))
7927 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7928 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7932 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7933 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE, DP2_RESULT_REG));
7935 aopPut (result, "a", offset);
7937 _endLazyDPSEvaluation();
7942 freeAsmop (result, NULL, ic, TRUE);
7943 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7944 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7947 /*-----------------------------------------------------------------*/
7948 /* genXor - code for xclusive or */
7949 /*-----------------------------------------------------------------*/
7951 genXor (iCode * ic, iCode * ifx)
7953 operand *left, *right, *result;
7954 int size, offset = 0;
7955 unsigned long lit = 0L;
7959 D (emitcode (";", "genXor"));
7961 AOP_OP_3_NOFATAL (ic, pushResult);
7962 AOP_SET_LOCALS (ic);
7966 genFarFarLogicOp(ic, "xrl");
7971 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
7973 AOP_TYPE (left), AOP_TYPE (right));
7974 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
7976 AOP_SIZE (left), AOP_SIZE (right));
7979 /* if left is a literal & right is not ||
7980 if left needs acc & right does not */
7981 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7982 #ifdef LOGIC_OPS_BROKEN
7983 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
7987 operand *tmp = right;
7992 /* if result = right then exchange them */
7993 if (sameRegs (AOP (result), AOP (right)))
7995 operand *tmp = right;
8000 /* if right is bit then exchange them */
8001 if (AOP_TYPE (right) == AOP_CRY &&
8002 AOP_TYPE (left) != AOP_CRY)
8004 operand *tmp = right;
8008 if (AOP_TYPE (right) == AOP_LIT)
8009 lit = ulFromVal (AOP (right)->aopu.aop_lit);
8011 size = AOP_SIZE (result);
8015 if (AOP_TYPE (left) == AOP_CRY)
8017 if (AOP_TYPE (right) == AOP_LIT)
8019 // c = bit & literal;
8022 // lit>>1 != 0 => result = 1
8023 if (AOP_TYPE (result) == AOP_CRY)
8026 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
8028 continueIfTrue (ifx);
8031 emitcode ("setb", "c");
8038 // lit == 0, result = left
8039 if (size && sameRegs (AOP (result), AOP (left)))
8041 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
8045 // lit == 1, result = not(left)
8046 if (size && sameRegs (AOP (result), AOP (left)))
8048 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
8053 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
8054 emitcode ("cpl", "c");
8062 symbol *tlbl = newiTempLabel (NULL);
8063 if (AOP_TYPE (right) == AOP_CRY)
8066 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8070 int sizer = AOP_SIZE (right);
8072 // if val>>1 != 0, result = 1
8073 emitcode ("setb", "c");
8076 MOVA (aopGet (right, sizer - 1, FALSE, FALSE, NULL));
8078 // test the msb of the lsb
8079 emitcode ("anl", "a,#!constbyte",0xfe);
8080 emitcode ("jnz", "!tlabel", tlbl->key + 100);
8084 emitcode ("rrc", "a");
8086 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
8087 emitcode ("cpl", "c");
8095 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
8096 genIfxJump (ifx, "c");
8100 /* if left is same as result */
8101 if (sameRegs (AOP (result), AOP (left)))
8103 for (; size--; offset++)
8105 if (AOP_TYPE (right) == AOP_LIT)
8107 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
8110 /* dummy read of volatile operand */
8111 if (isOperandVolatile (left, FALSE))
8112 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8116 else if (IS_AOP_PREG (left))
8118 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8119 emitcode ("xrl", "a,%s",
8120 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG));
8121 aopPut (result, "a", offset);
8125 emitcode ("xrl", "%s,%s",
8126 aopGet (left, offset, FALSE, TRUE, NULL),
8127 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8132 if (AOP_TYPE (left) == AOP_ACC)
8135 emitcode("mov", "a,b");
8136 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8138 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
8140 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
8141 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8142 emitcode ("xrl", "a,b");
8143 aopPut (result, "a", offset);
8145 else if (aopGetUsesAcc (left, offset))
8147 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8148 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8149 aopPut (result, "a", offset);
8153 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
8154 if (IS_AOP_PREG (left))
8156 emitcode ("xrl", "a,%s",
8157 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
8158 aopPut (result, "a", offset);
8161 emitcode ("xrl", "%s,a",
8162 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
8169 // left & result in different registers
8170 if (AOP_TYPE (result) == AOP_CRY)
8173 // if(size), result in bit
8174 // if(!size && ifx), conditional oper: if(left ^ right)
8175 symbol *tlbl = newiTempLabel (NULL);
8176 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
8179 emitcode ("setb", "c");
8182 if ((AOP_TYPE (right) == AOP_LIT) &&
8183 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
8185 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8187 else if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
8188 && AOP_TYPE(left)==AOP_ACC)
8191 emitcode("mov", "a,b");
8192 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8194 else if (AOP_TYPE(left)==AOP_ACC)
8198 bool pushedB = pushB ();
8199 emitcode("mov", "b,a");
8200 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8201 emitcode("xrl", "a,b");
8206 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8207 emitcode("xrl", "a,b");
8210 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
8212 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
8213 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8214 emitcode ("xrl", "a,b");
8216 else if (aopGetUsesAcc (left, offset))
8218 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8219 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8223 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
8224 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
8227 emitcode ("jnz", "!tlabel", tlbl->key + 100);
8237 jmpTrueOrFalse (ifx, tlbl);
8241 for (; (size--); offset++)
8244 // result = left ^ right
8245 if (AOP_TYPE (right) == AOP_LIT)
8247 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
8251 aopGet (left, offset, FALSE, FALSE, NULL),
8255 D (emitcode (";", "better literal XOR."));
8256 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8257 emitcode ("xrl", "a, %s",
8258 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8262 // faster than result <- left, anl result,right
8263 // and better if result is SFR
8264 if (AOP_TYPE (left) == AOP_ACC)
8266 emitcode ("xrl", "a,%s",
8267 aopGet (right, offset,
8268 FALSE, FALSE, DP2_RESULT_REG));
8272 char *rOp = aopGet (right, offset, FALSE, FALSE, NULL);
8273 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
8275 emitcode("mov", "b,a");
8279 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8280 emitcode ("xrl", "a,%s", rOp);
8283 aopPut (result, "a", offset);
8289 freeAsmop (result, NULL, ic, TRUE);
8290 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
8291 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
8294 /*-----------------------------------------------------------------*/
8295 /* genInline - write the inline code out */
8296 /*-----------------------------------------------------------------*/
8298 genInline (iCode * ic)
8300 char *buffer, *bp, *bp1;
8301 bool inComment = FALSE;
8303 D (emitcode (";", "genInline"));
8305 _G.inLine += (!options.asmpeep);
8307 buffer = bp = bp1 = Safe_strdup (IC_INLINE(ic));
8309 /* emit each line as a code */
8327 /* Add \n for labels, not dirs such as c:\mydir */
8328 if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
8346 _G.inLine -= (!options.asmpeep);
8349 /*-----------------------------------------------------------------*/
8350 /* genRRC - rotate right with carry */
8351 /*-----------------------------------------------------------------*/
8355 operand *left, *result;
8359 D (emitcode (";", "genRRC"));
8361 /* rotate right with carry */
8362 left = IC_LEFT (ic);
8363 result = IC_RESULT (ic);
8364 aopOp (left, ic, FALSE, FALSE);
8365 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8367 /* move it to the result */
8368 size = AOP_SIZE (result);
8372 _startLazyDPSEvaluation ();
8375 l = aopGet (left, offset, FALSE, FALSE, NULL);
8377 emitcode ("rrc", "a");
8378 if (AOP_SIZE (result) > 1)
8379 aopPut (result, "a", offset--);
8381 _endLazyDPSEvaluation ();
8383 /* now we need to put the carry into the
8384 highest order byte of the result */
8385 if (AOP_SIZE (result) > 1)
8387 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE, NULL);
8390 emitcode ("mov", "acc.7,c");
8391 aopPut (result, "a", AOP_SIZE (result) - 1);
8392 freeAsmop (result, NULL, ic, TRUE);
8393 freeAsmop (left, NULL, ic, TRUE);
8396 /*-----------------------------------------------------------------*/
8397 /* genRLC - generate code for rotate left with carry */
8398 /*-----------------------------------------------------------------*/
8402 operand *left, *result;
8406 D (emitcode (";", "genRLC"));
8408 /* rotate right with carry */
8409 left = IC_LEFT (ic);
8410 result = IC_RESULT (ic);
8411 aopOp (left, ic, FALSE, FALSE);
8412 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8414 /* move it to the result */
8415 size = AOP_SIZE (result);
8419 l = aopGet (left, offset, FALSE, FALSE, NULL);
8421 emitcode ("add", "a,acc");
8422 if (AOP_SIZE (result) > 1)
8424 aopPut (result, "a", offset++);
8427 _startLazyDPSEvaluation ();
8430 l = aopGet (left, offset, FALSE, FALSE, NULL);
8432 emitcode ("rlc", "a");
8433 if (AOP_SIZE (result) > 1)
8434 aopPut (result, "a", offset++);
8436 _endLazyDPSEvaluation ();
8438 /* now we need to put the carry into the
8439 highest order byte of the result */
8440 if (AOP_SIZE (result) > 1)
8442 l = aopGet (result, 0, FALSE, FALSE, NULL);
8445 emitcode ("mov", "acc.0,c");
8446 aopPut (result, "a", 0);
8447 freeAsmop (result, NULL, ic, TRUE);
8448 freeAsmop (left, NULL, ic, TRUE);
8451 /*-----------------------------------------------------------------*/
8452 /* genGetHbit - generates code get highest order bit */
8453 /*-----------------------------------------------------------------*/
8455 genGetHbit (iCode * ic)
8457 operand *left, *result;
8459 D (emitcode (";", "genGetHbit"));
8461 left = IC_LEFT (ic);
8462 result = IC_RESULT (ic);
8463 aopOp (left, ic, FALSE, FALSE);
8464 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8466 /* get the highest order byte into a */
8467 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
8468 if (AOP_TYPE (result) == AOP_CRY)
8470 emitcode ("rlc", "a");
8475 emitcode ("rl", "a");
8476 emitcode ("anl", "a,#1");
8481 freeAsmop (result, NULL, ic, TRUE);
8482 freeAsmop (left, NULL, ic, TRUE);
8485 /*-----------------------------------------------------------------*/
8486 /* genSwap - generates code to swap nibbles or bytes */
8487 /*-----------------------------------------------------------------*/
8489 genSwap (iCode * ic)
8491 operand *left, *result;
8493 D(emitcode (";", "genSwap"));
8495 left = IC_LEFT (ic);
8496 result = IC_RESULT (ic);
8497 aopOp (left, ic, FALSE, FALSE);
8498 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8500 _startLazyDPSEvaluation ();
8501 switch (AOP_SIZE (left))
8503 case 1: /* swap nibbles in byte */
8504 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
8505 emitcode ("swap", "a");
8506 aopPut (result, "a", 0);
8508 case 2: /* swap bytes in word */
8509 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
8511 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
8512 aopPut (result, aopGet (left, 1, FALSE, FALSE, NULL), 0);
8513 aopPut (result, "a", 1);
8515 else if (operandsEqu (left, result))
8518 bool pushedB = FALSE, leftInB = FALSE;
8520 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
8521 if (AOP_NEEDSACC (left) || AOP_NEEDSACC (result))
8524 emitcode ("mov", "b,a");
8528 aopPut (result, aopGet (left, 1, FALSE, FALSE, NULL), 0);
8529 aopPut (result, reg, 1);
8536 aopPut (result, aopGet (left, 1, FALSE, FALSE, NULL), 0);
8537 aopPut (result, aopGet (left, 0, FALSE, FALSE, NULL), 1);
8541 wassertl(FALSE, "unsupported SWAP operand size");
8543 _endLazyDPSEvaluation ();
8545 freeAsmop (result, NULL, ic, TRUE);
8546 freeAsmop (left, NULL, ic, TRUE);
8549 /*-----------------------------------------------------------------*/
8550 /* AccRol - rotate left accumulator by known count */
8551 /*-----------------------------------------------------------------*/
8553 AccRol (int shCount)
8555 shCount &= 0x0007; // shCount : 0..7
8562 emitcode ("rl", "a");
8565 emitcode ("rl", "a");
8566 emitcode ("rl", "a");
8569 emitcode ("swap", "a");
8570 emitcode ("rr", "a");
8573 emitcode ("swap", "a");
8576 emitcode ("swap", "a");
8577 emitcode ("rl", "a");
8580 emitcode ("rr", "a");
8581 emitcode ("rr", "a");
8584 emitcode ("rr", "a");
8589 /*-----------------------------------------------------------------*/
8590 /* AccLsh - left shift accumulator by known count */
8591 /*-----------------------------------------------------------------*/
8593 AccLsh (int shCount)
8598 emitcode ("add", "a,acc");
8599 else if (shCount == 2)
8601 emitcode ("add", "a,acc");
8602 emitcode ("add", "a,acc");
8606 /* rotate left accumulator */
8608 /* and kill the lower order bits */
8609 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
8614 /*-----------------------------------------------------------------*/
8615 /* AccRsh - right shift accumulator by known count */
8616 /*-----------------------------------------------------------------*/
8618 AccRsh (int shCount)
8625 emitcode ("rrc", "a");
8629 /* rotate right accumulator */
8630 AccRol (8 - shCount);
8631 /* and kill the higher order bits */
8632 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
8637 #ifdef BETTER_LITERAL_SHIFT
8638 /*-----------------------------------------------------------------*/
8639 /* AccSRsh - signed right shift accumulator by known count */
8640 /*-----------------------------------------------------------------*/
8642 AccSRsh (int shCount)
8649 emitcode ("mov", "c,acc.7");
8650 emitcode ("rrc", "a");
8652 else if (shCount == 2)
8654 emitcode ("mov", "c,acc.7");
8655 emitcode ("rrc", "a");
8656 emitcode ("mov", "c,acc.7");
8657 emitcode ("rrc", "a");
8661 tlbl = newiTempLabel (NULL);
8662 /* rotate right accumulator */
8663 AccRol (8 - shCount);
8664 /* and kill the higher order bits */
8665 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
8666 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8667 emitcode ("orl", "a,#!constbyte",
8668 (unsigned char) ~SRMask[shCount]);
8675 #ifdef BETTER_LITERAL_SHIFT
8676 /*-----------------------------------------------------------------*/
8677 /* shiftR1Left2Result - shift right one byte from left to result */
8678 /*-----------------------------------------------------------------*/
8680 shiftR1Left2Result (operand * left, int offl,
8681 operand * result, int offr,
8682 int shCount, int sign)
8684 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
8685 /* shift right accumulator */
8690 aopPut (result, "a", offr);
8694 #ifdef BETTER_LITERAL_SHIFT
8695 /*-----------------------------------------------------------------*/
8696 /* shiftL1Left2Result - shift left one byte from left to result */
8697 /*-----------------------------------------------------------------*/
8699 shiftL1Left2Result (operand * left, int offl,
8700 operand * result, int offr, int shCount)
8703 l = aopGet (left, offl, FALSE, FALSE, NULL);
8705 /* shift left accumulator */
8707 aopPut (result, "a", offr);
8711 #ifdef BETTER_LITERAL_SHIFT
8712 /*-----------------------------------------------------------------*/
8713 /* movLeft2Result - move byte from left to result */
8714 /*-----------------------------------------------------------------*/
8716 movLeft2Result (operand * left, int offl,
8717 operand * result, int offr, int sign)
8720 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8722 l = aopGet (left, offl, FALSE, FALSE, NULL);
8724 if (*l == '@' && (IS_AOP_PREG (result)))
8726 emitcode ("mov", "a,%s", l);
8727 aopPut (result, "a", offr);
8733 aopPut (result, l, offr);
8737 /* MSB sign in acc.7 ! */
8738 if (getDataSize (left) == offl + 1)
8741 aopPut (result, "a", offr);
8749 #ifdef BETTER_LITERAL_SHIFT
8750 /*-----------------------------------------------------------------*/
8751 /* AccAXRrl1 - right rotate a:x by 1 */
8752 /*-----------------------------------------------------------------*/
8756 emitcode ("mov", "c,acc.0");
8757 emitcode ("xch", "a,%s", x);
8758 emitcode ("rrc", "a");
8759 emitcode ("xch", "a,%s", x);
8760 emitcode ("rrc", "a");
8764 #ifdef BETTER_LITERAL_SHIFT
8766 /*-----------------------------------------------------------------*/
8767 /* AccAXLrl1 - left rotate a:x by 1 */
8768 /*-----------------------------------------------------------------*/
8772 emitcode ("mov", "c,acc.7");
8773 emitcode ("xch", "a,%s", x);
8774 emitcode ("rlc", "a");
8775 emitcode ("xch", "a,%s", x);
8776 emitcode ("rlc", "a");
8780 #ifdef BETTER_LITERAL_SHIFT
8781 /*-----------------------------------------------------------------*/
8782 /* AccAXRsh1 - right shift c->a:x->c by 1 */
8783 /*-----------------------------------------------------------------*/
8787 emitcode ("rrc", "a");
8788 emitcode ("xch", "a,%s", x);
8789 emitcode ("rrc", "a");
8790 emitcode ("xch", "a,%s", x);
8794 #ifdef BETTER_LITERAL_SHIFT
8795 /*-----------------------------------------------------------------*/
8796 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8797 /*-----------------------------------------------------------------*/
8801 emitcode ("xch", "a,%s", x);
8802 emitcode ("add", "a,acc");
8803 emitcode ("xch", "a,%s", x);
8804 emitcode ("rlc", "a");
8808 #ifdef BETTER_LITERAL_SHIFT
8809 /*-----------------------------------------------------------------*/
8810 /* AccAXLsh - left shift a:x by known count (0..7) */
8811 /*-----------------------------------------------------------------*/
8813 AccAXLsh (char *x, int shCount)
8828 case 5: // AAAAABBB:CCCCCDDD
8830 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8832 emitcode ("anl", "a,#!constbyte",
8833 SLMask[shCount]); // BBB00000:CCCCCDDD
8835 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8837 AccRol (shCount); // DDDCCCCC:BBB00000
8839 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8841 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8843 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8845 emitcode ("anl", "a,#!constbyte",
8846 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8848 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8850 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8853 case 6: // AAAAAABB:CCCCCCDD
8854 emitcode ("anl", "a,#!constbyte",
8855 SRMask[shCount]); // 000000BB:CCCCCCDD
8857 AccAXRrl1 (x); // D000000B:BCCCCCCD
8858 AccAXRrl1 (x); // DD000000:BBCCCCCC
8859 emitcode ("xch", "a,%s", x); // BBCCCCCC:DD000000
8861 emitcode ("mov", "c,acc.0"); // c = B
8862 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8863 emitcode("rrc","a");
8864 emitcode("xch","a,%s", x);
8865 emitcode("rrc","a");
8866 emitcode("mov","c,acc.0"); //<< get correct bit
8867 emitcode("xch","a,%s", x);
8869 emitcode("rrc","a");
8870 emitcode("xch","a,%s", x);
8871 emitcode("rrc","a");
8872 emitcode("xch","a,%s", x);
8875 case 7: // a:x <<= 7
8877 emitcode ("anl", "a,#!constbyte",
8878 SRMask[shCount]); // 0000000B:CCCCCCCD
8880 AccAXRrl1 (x); // D0000000:BCCCCCCC
8882 emitcode ("xch", "a,%s", x); // BCCCCCCC:D0000000
8891 #ifdef BETTER_LITERAL_SHIFT
8893 /*-----------------------------------------------------------------*/
8894 /* AccAXRsh - right shift a:x known count (0..7) */
8895 /*-----------------------------------------------------------------*/
8897 AccAXRsh (char *x, int shCount)
8905 AccAXRsh1 (x); // 0->a:x
8910 AccAXRsh1 (x); // 0->a:x
8913 AccAXRsh1 (x); // 0->a:x
8918 case 5: // AAAAABBB:CCCCCDDD = a:x
8920 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8922 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8924 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8926 emitcode ("anl", "a,#!constbyte",
8927 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8929 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8931 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8933 emitcode ("anl", "a,#!constbyte",
8934 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8936 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8938 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8940 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8943 case 6: // AABBBBBB:CCDDDDDD
8945 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDE
8946 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8948 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8950 emitcode ("anl", "a,#!constbyte",
8951 SRMask[shCount]); // 000000AA:BBBBBBCC
8954 case 7: // ABBBBBBB:CDDDDDDD
8956 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8958 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8960 emitcode ("anl", "a,#!constbyte",
8961 SRMask[shCount]); // 0000000A:BBBBBBBC
8970 #ifdef BETTER_LITERAL_SHIFT
8971 /*-----------------------------------------------------------------*/
8972 /* AccAXRshS - right shift signed a:x known count (0..7) */
8973 /*-----------------------------------------------------------------*/
8975 AccAXRshS (char *x, int shCount)
8983 emitcode ("mov", "c,acc.7");
8984 AccAXRsh1 (x); // s->a:x
8988 emitcode ("mov", "c,acc.7");
8989 AccAXRsh1 (x); // s->a:x
8991 emitcode ("mov", "c,acc.7");
8992 AccAXRsh1 (x); // s->a:x
8997 case 5: // AAAAABBB:CCCCCDDD = a:x
8999 tlbl = newiTempLabel (NULL);
9000 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
9002 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
9004 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
9006 emitcode ("anl", "a,#!constbyte",
9007 SRMask[shCount]); // 000CCCCC:BBBAAAAA
9009 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
9011 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
9013 emitcode ("anl", "a,#!constbyte",
9014 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
9016 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
9018 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
9020 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
9022 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
9023 emitcode ("orl", "a,#!constbyte",
9024 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
9027 break; // SSSSAAAA:BBBCCCCC
9029 case 6: // AABBBBBB:CCDDDDDD
9031 tlbl = newiTempLabel (NULL);
9033 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
9034 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
9036 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
9038 emitcode ("anl", "a,#!constbyte",
9039 SRMask[shCount]); // 000000AA:BBBBBBCC
9041 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
9042 emitcode ("orl", "a,#!constbyte",
9043 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
9047 case 7: // ABBBBBBB:CDDDDDDD
9049 tlbl = newiTempLabel (NULL);
9051 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
9053 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
9055 emitcode ("anl", "a,#!constbyte",
9056 SRMask[shCount]); // 0000000A:BBBBBBBC
9058 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
9059 emitcode ("orl", "a,#!constbyte",
9060 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
9070 #ifdef BETTER_LITERAL_SHIFT
9072 _loadLeftIntoAx(char **lsb,
9078 // Get the initial value from left into a pair of registers.
9079 // MSB must be in A, LSB can be any register.
9081 // If the result is held in registers, it is an optimization
9082 // if the LSB can be held in the register which will hold the,
9083 // result LSB since this saves us from having to copy it into
9084 // the result following AccAXLsh.
9086 // If the result is addressed indirectly, this is not a gain.
9087 if (AOP_NEEDSACC(result))
9091 _startLazyDPSEvaluation();
9092 if (AOP_TYPE(left) == AOP_DPTR2)
9095 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE, NULL));
9096 // get LSB in DP2_RESULT_REG.
9097 leftByte = aopGet (left, offl, FALSE, FALSE, DP2_RESULT_REG);
9098 assert(!strcmp(leftByte, DP2_RESULT_REG));
9102 // get LSB into DP2_RESULT_REG
9103 leftByte = aopGet (left, offl, FALSE, FALSE, NULL);
9104 if (strcmp(leftByte, DP2_RESULT_REG))
9107 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
9110 leftByte = aopGet (left, offl + MSB16, FALSE, FALSE, NULL);
9111 assert(strcmp(leftByte, DP2_RESULT_REG));
9114 _endLazyDPSEvaluation();
9115 *lsb = DP2_RESULT_REG;
9119 if (sameRegs (AOP (result), AOP (left)) &&
9120 ((offl + MSB16) == offr))
9122 /* don't crash result[offr] */
9123 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
9124 emitcode ("xch", "a,%s",
9125 aopGet (left, offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
9129 movLeft2Result (left, offl, result, offr, 0);
9130 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE, NULL));
9132 *lsb = aopGet (result, offr, FALSE, FALSE, DP2_RESULT_REG);
9133 assert(strcmp(*lsb,"a"));
9138 _storeAxResults(char *lsb,
9142 _startLazyDPSEvaluation();
9143 if (AOP_NEEDSACC(result))
9145 /* We have to explicitly update the result LSB.
9147 emitcode ("xch","a,%s", lsb);
9148 aopPut (result, "a", offr);
9149 emitcode ("mov","a,%s", lsb);
9151 if (getDataSize (result) > 1)
9153 aopPut (result, "a", offr + MSB16);
9155 _endLazyDPSEvaluation();
9158 /*-----------------------------------------------------------------*/
9159 /* shiftL2Left2Result - shift left two bytes from left to result */
9160 /*-----------------------------------------------------------------*/
9162 shiftL2Left2Result (operand * left, int offl,
9163 operand * result, int offr, int shCount)
9167 _loadLeftIntoAx(&lsb, left, result, offl, offr);
9169 AccAXLsh (lsb, shCount);
9171 _storeAxResults(lsb, result, offr);
9175 #ifdef BETTER_LITERAL_SHIFT
9176 /*-----------------------------------------------------------------*/
9177 /* shiftR2Left2Result - shift right two bytes from left to result */
9178 /*-----------------------------------------------------------------*/
9180 shiftR2Left2Result (operand * left, int offl,
9181 operand * result, int offr,
9182 int shCount, int sign)
9186 _loadLeftIntoAx(&lsb, left, result, offl, offr);
9188 /* a:x >> shCount (x = lsb(result)) */
9191 AccAXRshS(lsb, shCount);
9195 AccAXRsh(lsb, shCount);
9198 _storeAxResults(lsb, result, offr);
9202 /*-----------------------------------------------------------------*/
9203 /* shiftLLeftOrResult - shift left one byte from left, or to result */
9204 /*-----------------------------------------------------------------*/
9206 shiftLLeftOrResult (operand * left, int offl,
9207 operand * result, int offr, int shCount)
9209 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
9210 /* shift left accumulator */
9212 /* or with result */
9213 emitcode ("orl", "a,%s",
9214 aopGet (result, offr, FALSE, FALSE, DP2_RESULT_REG));
9215 /* back to result */
9216 aopPut (result, "a", offr);
9221 /*-----------------------------------------------------------------*/
9222 /* shiftRLeftOrResult - shift right one byte from left,or to result */
9223 /*-----------------------------------------------------------------*/
9225 shiftRLeftOrResult (operand * left, int offl,
9226 operand * result, int offr, int shCount)
9228 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
9229 /* shift right accumulator */
9231 /* or with result */
9232 emitcode ("orl", "a,%s",
9233 aopGet (result, offr, FALSE, FALSE, DP2_RESULT_REG));
9234 /* back to result */
9235 aopPut (result, "a", offr);
9239 #ifdef BETTER_LITERAL_SHIFT
9240 /*-----------------------------------------------------------------*/
9241 /* genlshOne - left shift a one byte quantity by known count */
9242 /*-----------------------------------------------------------------*/
9244 genlshOne (operand * result, operand * left, int shCount)
9246 D (emitcode (";", "genlshOne"));
9248 shiftL1Left2Result (left, LSB, result, LSB, shCount);
9252 #ifdef BETTER_LITERAL_SHIFT
9253 /*-----------------------------------------------------------------*/
9254 /* genlshTwo - left shift two bytes by known amount != 0 */
9255 /*-----------------------------------------------------------------*/
9257 genlshTwo (operand * result, operand * left, int shCount)
9261 D (emitcode (";", "genlshTwo"));
9263 size = getDataSize (result);
9265 /* if shCount >= 8 */
9270 _startLazyDPSEvaluation();
9276 _endLazyDPSEvaluation();
9277 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
9278 aopPut (result, zero, LSB);
9282 movLeft2Result (left, LSB, result, MSB16, 0);
9283 aopPut (result, zero, LSB);
9284 _endLazyDPSEvaluation();
9289 aopPut (result, zero, LSB);
9290 _endLazyDPSEvaluation();
9294 /* 1 <= shCount <= 7 */
9298 shiftL1Left2Result (left, LSB, result, LSB, shCount);
9300 shiftL2Left2Result (left, LSB, result, LSB, shCount);
9307 /*-----------------------------------------------------------------*/
9308 /* shiftLLong - shift left one long from left to result */
9309 /* offl = LSB or MSB16 */
9310 /*-----------------------------------------------------------------*/
9312 shiftLLong (operand * left, operand * result, int offr)
9315 int size = AOP_SIZE (result);
9317 if (size >= LSB + offr)
9319 l = aopGet (left, LSB, FALSE, FALSE, NULL);
9321 emitcode ("add", "a,acc");
9322 if (sameRegs (AOP (left), AOP (result)) &&
9323 size >= MSB16 + offr && offr != LSB)
9324 emitcode ("xch", "a,%s",
9325 aopGet (left, LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
9327 aopPut (result, "a", LSB + offr);
9330 if (size >= MSB16 + offr)
9332 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
9334 l = aopGet (left, MSB16, FALSE, FALSE, TRUE);
9337 emitcode ("rlc", "a");
9338 if (sameRegs (AOP (left), AOP (result)) &&
9339 size >= MSB24 + offr && offr != LSB)
9340 emitcode ("xch", "a,%s",
9341 aopGet (left, MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
9343 aopPut (result, "a", MSB16 + offr);
9346 if (size >= MSB24 + offr)
9348 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
9350 l = aopGet (left, MSB24, FALSE, FALSE, NULL);
9353 emitcode ("rlc", "a");
9354 if (sameRegs (AOP (left), AOP (result)) &&
9355 size >= MSB32 + offr && offr != LSB)
9356 emitcode ("xch", "a,%s",
9357 aopGet (left, MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
9359 aopPut (result, "a", MSB24 + offr);
9362 if (size > MSB32 + offr)
9364 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
9366 l = aopGet (left, MSB32, FALSE, FALSE, NULL);
9369 emitcode ("rlc", "a");
9370 aopPut (result, "a", MSB32 + offr);
9373 aopPut (result, zero, LSB);
9379 /*-----------------------------------------------------------------*/
9380 /* genlshFour - shift four byte by a known amount != 0 */
9381 /*-----------------------------------------------------------------*/
9383 genlshFour (operand * result, operand * left, int shCount)
9387 D (emitcode (";", "genlshFour"));
9389 size = AOP_SIZE (result);
9391 /* if shifting more that 3 bytes */
9396 /* lowest order of left goes to the highest
9397 order of the destination */
9398 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
9400 movLeft2Result (left, LSB, result, MSB32, 0);
9401 aopPut (result, zero, LSB);
9402 aopPut (result, zero, MSB16);
9403 aopPut (result, zero, MSB24);
9407 /* more than two bytes */
9408 else if (shCount >= 16)
9410 /* lower order two bytes goes to higher order two bytes */
9412 /* if some more remaining */
9414 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
9417 movLeft2Result (left, MSB16, result, MSB32, 0);
9418 movLeft2Result (left, LSB, result, MSB24, 0);
9420 aopPut (result, zero, MSB16);
9421 aopPut (result, zero, LSB);
9425 /* if more than 1 byte */
9426 else if (shCount >= 8)
9428 /* lower order three bytes goes to higher order three bytes */
9433 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
9435 movLeft2Result (left, LSB, result, MSB16, 0);
9441 movLeft2Result (left, MSB24, result, MSB32, 0);
9442 movLeft2Result (left, MSB16, result, MSB24, 0);
9443 movLeft2Result (left, LSB, result, MSB16, 0);
9444 aopPut (result, zero, LSB);
9446 else if (shCount == 1)
9447 shiftLLong (left, result, MSB16);
9450 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
9451 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
9452 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
9453 aopPut (result, zero, LSB);
9458 /* 1 <= shCount <= 7 */
9459 else if (shCount <= 2)
9461 shiftLLong (left, result, LSB);
9463 shiftLLong (result, result, LSB);
9465 /* 3 <= shCount <= 7, optimize */
9468 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
9469 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
9470 shiftL2Left2Result (left, LSB, result, LSB, shCount);
9475 #ifdef BETTER_LITERAL_SHIFT
9476 /*-----------------------------------------------------------------*/
9477 /* genLeftShiftLiteral - left shifting by known count */
9478 /*-----------------------------------------------------------------*/
9480 genLeftShiftLiteral (operand * left,
9485 int shCount = (int) ulFromVal (AOP (right)->aopu.aop_lit);
9488 size = getSize (operandType (result));
9490 D (emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
9492 /* We only handle certain easy cases so far. */
9494 && (shCount < (size * 8))
9498 D(emitcode (";", "genLeftShiftLiteral wimping out"););
9502 freeAsmop (right, NULL, ic, TRUE);
9504 aopOp(left, ic, FALSE, FALSE);
9505 aopOp(result, ic, FALSE, AOP_USESDPTR(left));
9508 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
9510 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
9511 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
9513 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
9516 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
9518 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
9519 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
9521 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
9527 emitcode ("; shift left ", "result %d, left %d", size,
9531 /* I suppose that the left size >= result size */
9534 _startLazyDPSEvaluation();
9537 movLeft2Result (left, size, result, size, 0);
9539 _endLazyDPSEvaluation();
9541 else if (shCount >= (size * 8))
9543 _startLazyDPSEvaluation();
9546 aopPut (result, zero, size);
9548 _endLazyDPSEvaluation();
9555 genlshOne (result, left, shCount);
9559 genlshTwo (result, left, shCount);
9563 genlshFour (result, left, shCount);
9567 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9568 "*** ack! mystery literal shift!\n");
9572 freeAsmop (result, NULL, ic, TRUE);
9573 freeAsmop (left, NULL, ic, TRUE);
9578 /*-----------------------------------------------------------------*/
9579 /* genLeftShift - generates code for left shifting */
9580 /*-----------------------------------------------------------------*/
9582 genLeftShift (iCode * ic)
9584 operand *left, *right, *result;
9587 symbol *tlbl, *tlbl1;
9590 D (emitcode (";", "genLeftShift"));
9592 right = IC_RIGHT (ic);
9593 left = IC_LEFT (ic);
9594 result = IC_RESULT (ic);
9596 aopOp (right, ic, FALSE, FALSE);
9599 #ifdef BETTER_LITERAL_SHIFT
9600 /* if the shift count is known then do it
9601 as efficiently as possible */
9602 if (AOP_TYPE (right) == AOP_LIT)
9604 if (genLeftShiftLiteral (left, right, result, ic))
9611 /* shift count is unknown then we have to form
9612 a loop get the loop count in B : Note: we take
9613 only the lower order byte since shifting
9614 more that 32 bits make no sense anyway, ( the
9615 largest size of an object can be only 32 bits ) */
9618 if (AOP_TYPE (right) == AOP_LIT)
9620 /* Really should be handled by genLeftShiftLiteral,
9621 * but since I'm too lazy to fix that today, at least we can make
9622 * some small improvement.
9624 emitcode("mov", "b,#!constbyte",
9625 ((int) ulFromVal (AOP (right)->aopu.aop_lit)) + 1);
9629 MOVB (aopGet (right, 0, FALSE, FALSE, "b"));
9630 emitcode ("inc", "b");
9632 freeAsmop (right, NULL, ic, TRUE);
9633 aopOp (left, ic, FALSE, FALSE);
9634 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9636 /* now move the left to the result if they are not the same */
9637 if (!sameRegs (AOP (left), AOP (result)) &&
9638 AOP_SIZE (result) > 1)
9641 size = AOP_SIZE (result);
9643 _startLazyDPSEvaluation ();
9646 l = aopGet (left, offset, FALSE, TRUE, NULL);
9647 if (*l == '@' && (IS_AOP_PREG (result)))
9650 emitcode ("mov", "a,%s", l);
9651 aopPut (result, "a", offset);
9654 aopPut (result, l, offset);
9657 _endLazyDPSEvaluation ();
9660 tlbl = newiTempLabel (NULL);
9661 size = AOP_SIZE (result);
9663 tlbl1 = newiTempLabel (NULL);
9665 /* if it is only one byte then */
9668 symbol *tlbl1 = newiTempLabel (NULL);
9670 l = aopGet (left, 0, FALSE, FALSE, NULL);
9672 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9674 emitcode ("add", "a,acc");
9676 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9678 aopPut (result, "a", 0);
9682 reAdjustPreg (AOP (result));
9684 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9686 l = aopGet (result, offset, FALSE, FALSE, NULL);
9688 emitcode ("add", "a,acc");
9689 aopPut (result, "a", offset++);
9690 _startLazyDPSEvaluation ();
9693 l = aopGet (result, offset, FALSE, FALSE, NULL);
9695 emitcode ("rlc", "a");
9696 aopPut (result, "a", offset++);
9698 _endLazyDPSEvaluation ();
9699 reAdjustPreg (AOP (result));
9702 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9705 freeAsmop (result, NULL, ic, TRUE);
9706 freeAsmop (left, NULL, ic, TRUE);
9709 #ifdef BETTER_LITERAL_SHIFT
9710 /*-----------------------------------------------------------------*/
9711 /* genrshOne - right shift a one byte quantity by known count */
9712 /*-----------------------------------------------------------------*/
9714 genrshOne (operand * result, operand * left,
9715 int shCount, int sign)
9717 D (emitcode (";", "genrshOne"));
9719 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9723 #ifdef BETTER_LITERAL_SHIFT
9724 /*-----------------------------------------------------------------*/
9725 /* genrshTwo - right shift two bytes by known amount != 0 */
9726 /*-----------------------------------------------------------------*/
9728 genrshTwo (operand * result, operand * left,
9729 int shCount, int sign)
9731 D (emitcode (";", "genrshTwo"));
9733 /* if shCount >= 8 */
9737 _startLazyDPSEvaluation();
9739 shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
9741 movLeft2Result (left, MSB16, result, LSB, sign);
9742 addSign (result, MSB16, sign);
9743 _endLazyDPSEvaluation();
9746 /* 1 <= shCount <= 7 */
9748 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9752 /*-----------------------------------------------------------------*/
9753 /* shiftRLong - shift right one long from left to result */
9754 /* offl = LSB or MSB16 */
9755 /*-----------------------------------------------------------------*/
9757 shiftRLong (operand * left, int offl,
9758 operand * result, int sign)
9760 bool overlapping = regsInCommon (left, result) || operandsEqu(left, result);
9762 if (overlapping && offl>1)
9764 // we are in big trouble, but this shouldn't happen
9765 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9768 MOVA (aopGet (left, MSB32, FALSE, FALSE, NULL));
9775 emitcode ("rlc", "a");
9776 emitcode ("subb", "a,acc");
9777 emitcode ("xch", "a,%s",
9778 aopGet(left, MSB32, FALSE, FALSE, DP2_RESULT_REG));
9782 aopPut (result, zero, MSB32);
9788 emitcode ("clr", "c");
9792 emitcode ("mov", "c,acc.7");
9795 emitcode ("rrc", "a");
9797 if (overlapping && offl==MSB16)
9799 emitcode ("xch", "a,%s", aopGet (left, MSB24, FALSE, FALSE, DP2_RESULT_REG));
9803 aopPut (result, "a", MSB32 - offl);
9804 MOVA (aopGet (left, MSB24, FALSE, FALSE, NULL));
9807 emitcode ("rrc", "a");
9809 if (overlapping && offl==MSB16)
9811 emitcode ("xch", "a,%s", aopGet (left, MSB16, FALSE, FALSE, DP2_RESULT_REG));
9815 aopPut (result, "a", MSB24 - offl);
9816 MOVA (aopGet (left, MSB16, FALSE, FALSE, NULL));
9819 emitcode ("rrc", "a");
9822 aopPut (result, "a", MSB16 - offl);
9826 if (overlapping && offl==MSB16)
9828 emitcode ("xch", "a,%s", aopGet (left, LSB, FALSE, FALSE, DP2_RESULT_REG));
9832 aopPut (result, "a", MSB16 - offl);
9833 MOVA (aopGet (left, LSB, FALSE, FALSE, NULL));
9835 emitcode ("rrc", "a");
9836 aopPut (result, "a", LSB);
9840 /*-----------------------------------------------------------------*/
9841 /* genrshFour - shift four byte by a known amount != 0 */
9842 /*-----------------------------------------------------------------*/
9844 genrshFour (operand * result, operand * left,
9845 int shCount, int sign)
9847 D (emitcode (";", "genrshFour"));
9849 /* if shifting more that 3 bytes */
9853 _startLazyDPSEvaluation();
9855 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9857 movLeft2Result (left, MSB32, result, LSB, sign);
9858 addSign (result, MSB16, sign);
9859 _endLazyDPSEvaluation();
9861 else if (shCount >= 16)
9864 _startLazyDPSEvaluation();
9866 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9869 movLeft2Result (left, MSB24, result, LSB, 0);
9870 movLeft2Result (left, MSB32, result, MSB16, sign);
9872 addSign (result, MSB24, sign);
9873 _endLazyDPSEvaluation();
9875 else if (shCount >= 8)
9878 _startLazyDPSEvaluation();
9881 shiftRLong (left, MSB16, result, sign);
9883 else if (shCount == 0)
9885 movLeft2Result (left, MSB16, result, LSB, 0);
9886 movLeft2Result (left, MSB24, result, MSB16, 0);
9887 movLeft2Result (left, MSB32, result, MSB24, sign);
9888 addSign (result, MSB32, sign);
9892 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9893 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9894 /* the last shift is signed */
9895 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9896 addSign (result, MSB32, sign);
9898 _endLazyDPSEvaluation();
9902 /* 1 <= shCount <= 7 */
9905 shiftRLong (left, LSB, result, sign);
9907 shiftRLong (result, LSB, result, sign);
9911 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9912 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9913 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9918 #ifdef BETTER_LITERAL_SHIFT
9919 /*-----------------------------------------------------------------*/
9920 /* genRightShiftLiteral - right shifting by known count */
9921 /*-----------------------------------------------------------------*/
9923 genRightShiftLiteral (operand * left,
9929 int shCount = (int) ulFromVal (AOP (right)->aopu.aop_lit);
9932 size = getSize (operandType (result));
9934 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
9936 /* We only handle certain easy cases so far. */
9938 && (shCount < (size * 8))
9943 D(emitcode (";", "genRightShiftLiteral wimping out"););
9947 freeAsmop (right, NULL, ic, TRUE);
9949 aopOp (left, ic, FALSE, FALSE);
9950 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9953 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9957 /* test the LEFT size !!! */
9959 /* I suppose that the left size >= result size */
9962 size = getDataSize (result);
9963 _startLazyDPSEvaluation();
9965 movLeft2Result (left, size, result, size, 0);
9966 _endLazyDPSEvaluation();
9968 else if (shCount >= (size * 8))
9972 /* get sign in acc.7 */
9973 MOVA (aopGet (left, size - 1, FALSE, FALSE, NULL));
9975 addSign (result, LSB, sign);
9982 genrshOne (result, left, shCount, sign);
9986 genrshTwo (result, left, shCount, sign);
9990 genrshFour (result, left, shCount, sign);
9997 freeAsmop (result, NULL, ic, TRUE);
9998 freeAsmop (left, NULL, ic, TRUE);
10004 /*-----------------------------------------------------------------*/
10005 /* genSignedRightShift - right shift of signed number */
10006 /*-----------------------------------------------------------------*/
10008 genSignedRightShift (iCode * ic)
10010 operand *right, *left, *result;
10013 symbol *tlbl, *tlbl1;
10016 D (emitcode (";", "genSignedRightShift"));
10018 /* we do it the hard way put the shift count in b
10019 and loop thru preserving the sign */
10021 right = IC_RIGHT (ic);
10022 left = IC_LEFT (ic);
10023 result = IC_RESULT (ic);
10025 aopOp (right, ic, FALSE, FALSE);
10027 #ifdef BETTER_LITERAL_SHIFT
10028 if (AOP_TYPE (right) == AOP_LIT)
10030 if (genRightShiftLiteral (left, right, result, ic, 1))
10036 /* shift count is unknown then we have to form
10037 a loop get the loop count in B : Note: we take
10038 only the lower order byte since shifting
10039 more that 32 bits make no sense anyway, ( the
10040 largest size of an object can be only 32 bits ) */
10042 pushedB = pushB ();
10043 if (AOP_TYPE (right) == AOP_LIT)
10045 /* Really should be handled by genRightShiftLiteral,
10046 * but since I'm too lazy to fix that today, at least we can make
10047 * some small improvement.
10049 emitcode("mov", "b,#!constbyte",
10050 ((int) ulFromVal (AOP (right)->aopu.aop_lit)) + 1);
10054 MOVB (aopGet (right, 0, FALSE, FALSE, "b"));
10055 emitcode ("inc", "b");
10057 freeAsmop (right, NULL, ic, TRUE);
10058 aopOp (left, ic, FALSE, FALSE);
10059 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
10061 /* now move the left to the result if they are not the
10063 if (!sameRegs (AOP (left), AOP (result)) &&
10064 AOP_SIZE (result) > 1)
10067 size = AOP_SIZE (result);
10069 _startLazyDPSEvaluation ();
10072 l = aopGet (left, offset, FALSE, TRUE, NULL);
10073 if (*l == '@' && IS_AOP_PREG (result))
10076 emitcode ("mov", "a,%s", l);
10077 aopPut (result, "a", offset);
10080 aopPut (result, l, offset);
10083 _endLazyDPSEvaluation ();
10086 /* mov the highest order bit to OVR */
10087 tlbl = newiTempLabel (NULL);
10088 tlbl1 = newiTempLabel (NULL);
10090 size = AOP_SIZE (result);
10092 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
10093 emitcode ("rlc", "a");
10094 emitcode ("mov", "ov,c");
10095 /* if it is only one byte then */
10098 l = aopGet (left, 0, FALSE, FALSE, NULL);
10100 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
10102 emitcode ("mov", "c,ov");
10103 emitcode ("rrc", "a");
10105 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
10107 aopPut (result, "a", 0);
10111 reAdjustPreg (AOP (result));
10112 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
10114 emitcode ("mov", "c,ov");
10115 _startLazyDPSEvaluation ();
10118 l = aopGet (result, offset, FALSE, FALSE, NULL);
10120 emitcode ("rrc", "a");
10121 aopPut (result, "a", offset--);
10123 _endLazyDPSEvaluation ();
10124 reAdjustPreg (AOP (result));
10126 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
10130 freeAsmop (result, NULL, ic, TRUE);
10131 freeAsmop (left, NULL, ic, TRUE);
10134 /*-----------------------------------------------------------------*/
10135 /* genRightShift - generate code for right shifting */
10136 /*-----------------------------------------------------------------*/
10138 genRightShift (iCode * ic)
10140 operand *right, *left, *result;
10144 symbol *tlbl, *tlbl1;
10147 D (emitcode (";", "genRightShift"));
10149 /* if signed then we do it the hard way preserve the
10150 sign bit moving it inwards */
10151 letype = getSpec (operandType (IC_LEFT (ic)));
10153 if (!SPEC_USIGN (letype))
10155 genSignedRightShift (ic);
10159 /* signed & unsigned types are treated the same : i.e. the
10160 signed is NOT propagated inwards : quoting from the
10161 ANSI - standard : "for E1 >> E2, is equivalent to division
10162 by 2**E2 if unsigned or if it has a non-negative value,
10163 otherwise the result is implementation defined ", MY definition
10164 is that the sign does not get propagated */
10166 right = IC_RIGHT (ic);
10167 left = IC_LEFT (ic);
10168 result = IC_RESULT (ic);
10170 aopOp (right, ic, FALSE, FALSE);
10172 #ifdef BETTER_LITERAL_SHIFT
10173 /* if the shift count is known then do it
10174 as efficiently as possible */
10175 if (AOP_TYPE (right) == AOP_LIT)
10177 if (genRightShiftLiteral (left, right, result, ic, 0))
10184 /* shift count is unknown then we have to form
10185 a loop get the loop count in B : Note: we take
10186 only the lower order byte since shifting
10187 more that 32 bits make no sense anyway, ( the
10188 largest size of an object can be only 32 bits ) */
10190 pushedB = pushB ();
10191 if (AOP_TYPE (right) == AOP_LIT)
10193 /* Really should be handled by genRightShiftLiteral,
10194 * but since I'm too lazy to fix that today, at least we can make
10195 * some small improvement.
10197 emitcode("mov", "b,#!constbyte",
10198 ((int) ulFromVal (AOP (right)->aopu.aop_lit)) + 1);
10202 MOVB (aopGet (right, 0, FALSE, FALSE, "b"));
10203 emitcode ("inc", "b");
10205 freeAsmop (right, NULL, ic, TRUE);
10206 aopOp (left, ic, FALSE, FALSE);
10207 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
10209 /* now move the left to the result if they are not the
10211 if (!sameRegs (AOP (left), AOP (result)) &&
10212 AOP_SIZE (result) > 1)
10214 size = AOP_SIZE (result);
10216 _startLazyDPSEvaluation ();
10219 l = aopGet (left, offset, FALSE, TRUE, NULL);
10220 if (*l == '@' && IS_AOP_PREG (result))
10223 emitcode ("mov", "a,%s", l);
10224 aopPut (result, "a", offset);
10227 aopPut (result, l, offset);
10230 _endLazyDPSEvaluation ();
10233 tlbl = newiTempLabel (NULL);
10234 tlbl1 = newiTempLabel (NULL);
10235 size = AOP_SIZE (result);
10238 /* if it is only one byte then */
10241 l = aopGet (left, 0, FALSE, FALSE, NULL);
10243 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
10246 emitcode ("rrc", "a");
10248 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
10250 aopPut (result, "a", 0);
10254 reAdjustPreg (AOP (result));
10255 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
10258 _startLazyDPSEvaluation ();
10261 l = aopGet (result, offset, FALSE, FALSE, NULL);
10263 emitcode ("rrc", "a");
10264 aopPut (result, "a", offset--);
10266 _endLazyDPSEvaluation ();
10267 reAdjustPreg (AOP (result));
10270 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
10274 freeAsmop (result, NULL, ic, TRUE);
10275 freeAsmop (left, NULL, ic, TRUE);
10278 /*-----------------------------------------------------------------*/
10279 /* emitPtrByteGet - emits code to get a byte into A through a */
10280 /* pointer register (R0, R1, or DPTR). The */
10281 /* original value of A can be preserved in B. */
10282 /*-----------------------------------------------------------------*/
10284 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
10291 emitcode ("mov", "b,a");
10292 emitcode ("mov", "a,@%s", rname);
10297 emitcode ("mov", "b,a");
10298 emitcode ("movx", "a,@%s", rname);
10303 emitcode ("mov", "b,a");
10304 emitcode ("movx", "a,@dptr");
10309 emitcode ("mov", "b,a");
10310 emitcode ("clr", "a");
10311 emitcode ("movc", "a,@a+dptr");
10317 emitcode ("push", "b");
10318 emitcode ("push", "acc");
10320 emitcode ("lcall", "__gptrget");
10322 emitcode ("pop", "b");
10327 /*-----------------------------------------------------------------*/
10328 /* emitPtrByteSet - emits code to set a byte from src through a */
10329 /* pointer register (R0, R1, or DPTR). */
10330 /*-----------------------------------------------------------------*/
10332 emitPtrByteSet (char *rname, int p_type, char *src)
10341 emitcode ("mov", "@%s,a", rname);
10344 emitcode ("mov", "@%s,%s", rname, src);
10349 emitcode ("movx", "@%s,a", rname);
10354 emitcode ("movx", "@dptr,a");
10359 emitcode ("lcall", "__gptrput");
10364 /*-----------------------------------------------------------------*/
10365 /* genUnpackBits - generates code for unpacking bits */
10366 /*-----------------------------------------------------------------*/
10368 genUnpackBits (operand * result, char *rname, int ptype)
10370 int offset = 0; /* result byte offset */
10371 int rsize; /* result size */
10372 int rlen = 0; /* remaining bitfield length */
10373 sym_link *etype; /* bitfield type information */
10374 int blen; /* bitfield length */
10375 int bstr; /* bitfield starting bit within byte */
10377 D(emitcode (";", "genUnpackBits"));
10379 etype = getSpec (operandType (result));
10380 rsize = getSize (operandType (result));
10381 blen = SPEC_BLEN (etype);
10382 bstr = SPEC_BSTR (etype);
10384 /* If the bitfield length is less than a byte */
10387 emitPtrByteGet (rname, ptype, FALSE);
10389 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
10390 if (!SPEC_USIGN (etype))
10392 /* signed bitfield */
10393 symbol *tlbl = newiTempLabel (NULL);
10395 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
10396 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
10399 aopPut (result, "a", offset++);
10403 /* Bit field did not fit in a byte. Copy all
10404 but the partial byte at the end. */
10405 for (rlen=blen;rlen>=8;rlen-=8)
10407 emitPtrByteGet (rname, ptype, FALSE);
10408 aopPut (result, "a", offset++);
10410 emitcode ("inc", "%s", rname);
10413 /* Handle the partial byte at the end */
10416 emitPtrByteGet (rname, ptype, FALSE);
10417 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
10418 if (!SPEC_USIGN (etype))
10420 /* signed bitfield */
10421 symbol *tlbl = newiTempLabel (NULL);
10423 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
10424 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
10427 aopPut (result, "a", offset++);
10431 if (offset < rsize)
10435 if (SPEC_USIGN (etype))
10439 /* signed bitfield: sign extension with 0x00 or 0xff */
10440 emitcode ("rlc", "a");
10441 emitcode ("subb", "a,acc");
10447 aopPut (result, source, offset++);
10452 /*-----------------------------------------------------------------*/
10453 /* genDataPointerGet - generates code when ptr offset is known */
10454 /*-----------------------------------------------------------------*/
10456 genDataPointerGet (operand * left,
10462 int size, offset = 0;
10463 aopOp (result, ic, TRUE, FALSE);
10465 /* get the string representation of the name */
10466 l = aopGet (left, 0, FALSE, TRUE, NULL);
10467 size = AOP_SIZE (result);
10468 _startLazyDPSEvaluation ();
10473 SNPRINTF (buffer, sizeof(buffer),
10474 "(%s + %d)", l + 1, offset);
10478 SNPRINTF (buffer, sizeof(buffer),
10481 aopPut (result, buffer, offset++);
10483 _endLazyDPSEvaluation ();
10485 freeAsmop (result, NULL, ic, TRUE);
10486 freeAsmop (left, NULL, ic, TRUE);
10489 /*-----------------------------------------------------------------*/
10490 /* genNearPointerGet - emitcode for near pointer fetch */
10491 /*-----------------------------------------------------------------*/
10493 genNearPointerGet (operand * left,
10501 sym_link *rtype, *retype, *letype;
10502 sym_link *ltype = operandType (left);
10505 rtype = operandType (result);
10506 retype = getSpec (rtype);
10507 letype = getSpec (ltype);
10509 aopOp (left, ic, FALSE, FALSE);
10511 /* if left is rematerialisable and
10512 result is not bitfield variable type and
10513 the left is pointer to data space i.e
10514 lower 128 bytes of space */
10515 if (AOP_TYPE (left) == AOP_IMMD &&
10516 !IS_BITFIELD (retype) &&
10517 !IS_BITFIELD (letype) &&
10518 DCL_TYPE (ltype) == POINTER)
10520 genDataPointerGet (left, result, ic);
10524 /* if the value is already in a pointer register
10525 then don't need anything more */
10526 if (!AOP_INPREG (AOP (left)))
10528 /* otherwise get a free pointer register */
10529 aop = newAsmop (0);
10530 preg = getFreePtr (ic, &aop, FALSE);
10531 emitcode ("mov", "%s,%s",
10533 aopGet (left, 0, FALSE, TRUE, DP2_RESULT_REG));
10534 rname = preg->name;
10537 rname = aopGet (left, 0, FALSE, FALSE, DP2_RESULT_REG);
10539 freeAsmop (left, NULL, ic, TRUE);
10540 aopOp (result, ic, FALSE, FALSE);
10542 /* if bitfield then unpack the bits */
10543 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10544 genUnpackBits (result, rname, POINTER);
10547 /* we have can just get the values */
10548 int size = AOP_SIZE (result);
10553 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
10556 emitcode ("mov", "a,@%s", rname);
10557 aopPut (result, "a", offset);
10561 SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
10562 aopPut (result, buffer, offset);
10566 emitcode ("inc", "%s", rname);
10570 /* now some housekeeping stuff */
10571 if (aop) /* we had to allocate for this iCode */
10573 if (pi) { /* post increment present */
10574 aopPut (left, rname, 0);
10576 freeAsmop (NULL, aop, ic, TRUE);
10580 /* we did not allocate which means left
10581 already in a pointer register, then
10582 if size > 0 && this could be used again
10583 we have to point it back to where it
10585 if (AOP_SIZE (result) > 1 &&
10586 !OP_SYMBOL (left)->remat &&
10587 (OP_SYMBOL (left)->liveTo > ic->seq ||
10591 int size = AOP_SIZE (result) - 1;
10593 emitcode ("dec", "%s", rname);
10598 freeAsmop (result, NULL, ic, TRUE);
10599 if (pi) pi->generated = 1;
10602 /*-----------------------------------------------------------------*/
10603 /* genPagedPointerGet - emitcode for paged pointer fetch */
10604 /*-----------------------------------------------------------------*/
10606 genPagedPointerGet (operand * left,
10614 sym_link *rtype, *retype, *letype;
10616 rtype = operandType (result);
10617 retype = getSpec (rtype);
10618 letype = getSpec (operandType (left));
10619 aopOp (left, ic, FALSE, FALSE);
10621 /* if the value is already in a pointer register
10622 then don't need anything more */
10623 if (!AOP_INPREG (AOP (left)))
10625 /* otherwise get a free pointer register */
10626 aop = newAsmop (0);
10627 preg = getFreePtr (ic, &aop, FALSE);
10628 emitcode ("mov", "%s,%s",
10630 aopGet (left, 0, FALSE, TRUE, NULL));
10631 rname = preg->name;
10634 rname = aopGet (left, 0, FALSE, FALSE, NULL);
10636 freeAsmop (left, NULL, ic, TRUE);
10637 aopOp (result, ic, FALSE, FALSE);
10639 /* if bitfield then unpack the bits */
10640 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10641 genUnpackBits (result, rname, PPOINTER);
10644 /* we have can just get the values */
10645 int size = AOP_SIZE (result);
10651 emitcode ("movx", "a,@%s", rname);
10652 aopPut (result, "a", offset);
10657 emitcode ("inc", "%s", rname);
10661 /* now some housekeeping stuff */
10662 if (aop) /* we had to allocate for this iCode */
10665 aopPut (left, rname, 0);
10666 freeAsmop (NULL, aop, ic, TRUE);
10670 /* we did not allocate which means left
10671 already in a pointer register, then
10672 if size > 0 && this could be used again
10673 we have to point it back to where it
10675 if (AOP_SIZE (result) > 1 &&
10676 !OP_SYMBOL (left)->remat &&
10677 (OP_SYMBOL (left)->liveTo > ic->seq ||
10681 int size = AOP_SIZE (result) - 1;
10683 emitcode ("dec", "%s", rname);
10688 freeAsmop (result, NULL, ic, TRUE);
10689 if (pi) pi->generated = 1;
10692 /*-----------------------------------------------------------------*/
10693 /* genFarPointerGet - get value from far space */
10694 /*-----------------------------------------------------------------*/
10696 genFarPointerGet (operand * left,
10697 operand * result, iCode * ic, iCode *pi)
10699 int size, offset, dopi=1;
10700 sym_link *retype = getSpec (operandType (result));
10701 sym_link *letype = getSpec (operandType (left));
10702 D (emitcode (";", "genFarPointerGet"););
10704 aopOp (left, ic, FALSE, FALSE);
10706 /* if the operand is already in dptr
10707 then we do nothing else we move the value to dptr */
10708 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
10710 /* if this is rematerializable */
10711 if (AOP_TYPE (left) == AOP_IMMD)
10713 emitcode ("mov", "dptr,%s", aopGet (left, 0, TRUE, FALSE, NULL));
10717 /* we need to get it byte by byte */
10718 _startLazyDPSEvaluation ();
10719 if (AOP_TYPE (left) != AOP_DPTR)
10721 emitcode ("mov", "dpl,%s", aopGet (left, 0, FALSE, FALSE, NULL));
10722 emitcode ("mov", "dph,%s", aopGet (left, 1, FALSE, FALSE, NULL));
10723 if (options.model == MODEL_FLAT24)
10724 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10728 /* We need to generate a load to DPTR indirect through DPTR. */
10729 D (emitcode (";", "genFarPointerGet -- indirection special case."););
10730 emitcode ("push", "%s", aopGet (left, 0, FALSE, TRUE, NULL));
10731 emitcode ("push", "%s", aopGet (left, 1, FALSE, TRUE, NULL));
10732 if (options.model == MODEL_FLAT24)
10733 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10734 emitcode ("pop", "dph");
10735 emitcode ("pop", "dpl");
10738 _endLazyDPSEvaluation ();
10741 /* so dptr now contains the address */
10742 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10744 /* if bit then unpack */
10745 if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
10746 if (AOP_INDPTRn(left)) {
10747 genSetDPTR(AOP(left)->aopu.dptr);
10749 genUnpackBits (result, "dptr", FPOINTER);
10750 if (AOP_INDPTRn(left)) {
10755 size = AOP_SIZE (result);
10758 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10760 genSetDPTR(AOP(left)->aopu.dptr);
10761 emitcode ("movx", "a,@dptr");
10762 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10763 emitcode ("inc", "dptr");
10765 aopPut (result, "a", offset++);
10768 _startLazyDPSEvaluation ();
10770 if (AOP_INDPTRn(left)) {
10771 genSetDPTR(AOP(left)->aopu.dptr);
10777 emitcode ("movx", "a,@dptr");
10778 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10779 emitcode ("inc", "dptr");
10781 aopPut (result, "a", offset++);
10783 _endLazyDPSEvaluation ();
10786 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10787 if (!AOP_INDPTRn(left)) {
10788 _startLazyDPSEvaluation ();
10789 aopPut (left, "dpl", 0);
10790 aopPut (left, "dph", 1);
10791 if (options.model == MODEL_FLAT24)
10792 aopPut (left, "dpx", 2);
10793 _endLazyDPSEvaluation ();
10796 } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) &&
10797 AOP_SIZE(result) > 1 &&
10799 (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
10801 size = AOP_SIZE (result) - 1;
10802 if (AOP_INDPTRn(left)) {
10803 genSetDPTR(AOP(left)->aopu.dptr);
10805 while (size--) emitcode ("lcall","__decdptr");
10806 if (AOP_INDPTRn(left)) {
10811 freeAsmop (result, NULL, ic, TRUE);
10812 freeAsmop (left, NULL, ic, TRUE);
10815 /*-----------------------------------------------------------------*/
10816 /* genCodePointerGet - get value from code space */
10817 /*-----------------------------------------------------------------*/
10819 genCodePointerGet (operand * left,
10820 operand * result, iCode * ic, iCode *pi)
10822 int size, offset, dopi=1;
10823 sym_link *retype = getSpec (operandType (result));
10825 aopOp (left, ic, FALSE, FALSE);
10827 /* if the operand is already in dptr
10828 then we do nothing else we move the value to dptr */
10829 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
10831 /* if this is rematerializable */
10832 if (AOP_TYPE (left) == AOP_IMMD)
10834 emitcode ("mov", "dptr,%s", aopGet (left, 0, TRUE, FALSE, NULL));
10837 { /* we need to get it byte by byte */
10838 _startLazyDPSEvaluation ();
10839 if (AOP_TYPE (left) != AOP_DPTR)
10841 emitcode ("mov", "dpl,%s", aopGet (left, 0, FALSE, FALSE, NULL));
10842 emitcode ("mov", "dph,%s", aopGet (left, 1, FALSE, FALSE, NULL));
10843 if (options.model == MODEL_FLAT24)
10844 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10848 /* We need to generate a load to DPTR indirect through DPTR. */
10849 D (emitcode (";", "gencodePointerGet -- indirection special case."););
10850 emitcode ("push", "%s", aopGet (left, 0, FALSE, TRUE, NULL));
10851 emitcode ("push", "%s", aopGet (left, 1, FALSE, TRUE, NULL));
10852 if (options.model == MODEL_FLAT24)
10853 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10854 emitcode ("pop", "dph");
10855 emitcode ("pop", "dpl");
10858 _endLazyDPSEvaluation ();
10861 /* so dptr now contains the address */
10862 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10864 /* if bit then unpack */
10865 if (IS_BITFIELD (retype)) {
10866 if (AOP_INDPTRn(left)) {
10867 genSetDPTR(AOP(left)->aopu.dptr);
10869 genUnpackBits (result, "dptr", CPOINTER);
10870 if (AOP_INDPTRn(left)) {
10875 size = AOP_SIZE (result);
10877 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10879 genSetDPTR(AOP(left)->aopu.dptr);
10880 emitcode ("clr", "a");
10881 emitcode ("movc", "a,@a+dptr");
10882 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10883 emitcode ("inc", "dptr");
10885 aopPut (result, "a", offset++);
10888 _startLazyDPSEvaluation ();
10891 if (AOP_INDPTRn(left)) {
10892 genSetDPTR(AOP(left)->aopu.dptr);
10898 emitcode ("clr", "a");
10899 emitcode ("movc", "a,@a+dptr");
10900 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10901 emitcode ("inc", "dptr");
10902 aopPut (result, "a", offset++);
10904 _endLazyDPSEvaluation ();
10907 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10908 if (!AOP_INDPTRn(left)) {
10909 _startLazyDPSEvaluation ();
10911 aopPut (left, "dpl", 0);
10912 aopPut (left, "dph", 1);
10913 if (options.model == MODEL_FLAT24)
10914 aopPut (left, "dpx", 2);
10916 _endLazyDPSEvaluation ();
10919 } else if (IS_SYMOP(left) &&
10920 (OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
10921 AOP_SIZE(result) > 1 &&
10922 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10924 size = AOP_SIZE (result) - 1;
10925 if (AOP_INDPTRn(left)) {
10926 genSetDPTR(AOP(left)->aopu.dptr);
10928 while (size--) emitcode ("lcall","__decdptr");
10929 if (AOP_INDPTRn(left)) {
10934 freeAsmop (result, NULL, ic, TRUE);
10935 freeAsmop (left, NULL, ic, TRUE);
10938 /*-----------------------------------------------------------------*/
10939 /* genGenPointerGet - get value from generic pointer space */
10940 /*-----------------------------------------------------------------*/
10942 genGenPointerGet (operand * left,
10943 operand * result, iCode * ic, iCode * pi)
10947 sym_link *retype = getSpec (operandType (result));
10948 sym_link *letype = getSpec (operandType (left));
10950 D (emitcode (";", "genGenPointerGet"));
10952 aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
10954 pushedB = pushB ();
10955 /* if the operand is already in dptr
10956 then we do nothing else we move the value to dptr */
10957 if (AOP_TYPE (left) != AOP_STR)
10959 /* if this is rematerializable */
10960 if (AOP_TYPE (left) == AOP_IMMD)
10962 emitcode ("mov", "dptr,%s", aopGet (left, 0, TRUE, FALSE, NULL));
10963 if (AOP(left)->aopu.aop_immd.from_cast_remat)
10965 MOVB (aopGet (left, AOP_SIZE(left)-1, FALSE, FALSE, NULL));
10969 emitcode ("mov", "b,#%d", pointerCode (retype));
10973 { /* we need to get it byte by byte */
10974 _startLazyDPSEvaluation ();
10975 emitcode ("mov", "dpl,%s", aopGet (left,0,FALSE,FALSE,NULL));
10976 emitcode ("mov", "dph,%s", aopGet (left,1,FALSE,FALSE,NULL));
10977 if (options.model == MODEL_FLAT24) {
10978 emitcode ("mov", "dpx,%s", aopGet (left,2,FALSE,FALSE,NULL));
10979 emitcode ("mov", "b,%s", aopGet (left,3,FALSE,FALSE,NULL));
10981 emitcode ("mov", "b,%s", aopGet (left,2,FALSE,FALSE,NULL));
10983 _endLazyDPSEvaluation ();
10987 /* so dptr-b now contains the address */
10988 aopOp (result, ic, FALSE, TRUE);
10990 /* if bit then unpack */
10991 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10993 genUnpackBits (result, "dptr", GPOINTER);
10997 size = AOP_SIZE (result);
11004 // Get two bytes at a time, results in _AP & A.
11005 // dptr will be incremented ONCE by __gptrgetWord.
11007 // Note: any change here must be coordinated
11008 // with the implementation of __gptrgetWord
11009 // in device/lib/_gptrget.c
11010 emitcode ("lcall", "__gptrgetWord");
11011 aopPut (result, "a", offset++);
11012 aopPut (result, DP2_RESULT_REG, offset++);
11017 // Only one byte to get.
11018 emitcode ("lcall", "__gptrget");
11019 aopPut (result, "a", offset++);
11022 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
11024 emitcode ("inc", "dptr");
11029 if (pi && AOP_TYPE (left) != AOP_IMMD) {
11030 _startLazyDPSEvaluation ();
11032 aopPut (left, "dpl", 0);
11033 aopPut (left, "dph", 1);
11034 if (options.model == MODEL_FLAT24) {
11035 aopPut (left, "dpx", 2);
11036 aopPut (left, "b", 3);
11037 } else aopPut (left, "b", 2);
11039 _endLazyDPSEvaluation ();
11042 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
11043 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
11045 size = AOP_SIZE (result) - 1;
11046 while (size--) emitcode ("lcall","__decdptr");
11050 freeAsmop (result, NULL, ic, TRUE);
11051 freeAsmop (left, NULL, ic, TRUE);
11054 /*-----------------------------------------------------------------*/
11055 /* genPointerGet - generate code for pointer get */
11056 /*-----------------------------------------------------------------*/
11058 genPointerGet (iCode * ic, iCode *pi)
11060 operand *left, *result;
11061 sym_link *type, *etype;
11064 D (emitcode (";", "genPointerGet"));
11066 left = IC_LEFT (ic);
11067 result = IC_RESULT (ic);
11069 /* depending on the type of pointer we need to
11070 move it to the correct pointer register */
11071 type = operandType (left);
11072 etype = getSpec (type);
11073 /* if left is of type of pointer then it is simple */
11074 if (IS_PTR (type) && !IS_FUNC (type->next))
11075 p_type = DCL_TYPE (type);
11078 /* we have to go by the storage class */
11079 p_type = PTR_TYPE (SPEC_OCLS (etype));
11082 /* special case when cast remat */
11083 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
11084 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
11086 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
11087 type = operandType (left);
11088 p_type = DCL_TYPE (type);
11090 /* now that we have the pointer type we assign
11091 the pointer values */
11097 genNearPointerGet (left, result, ic, pi);
11101 genPagedPointerGet (left, result, ic, pi);
11105 genFarPointerGet (left, result, ic, pi);
11109 genCodePointerGet (left, result, ic, pi);
11113 genGenPointerGet (left, result, ic, pi);
11119 /*-----------------------------------------------------------------*/
11120 /* genPackBits - generates code for packed bit storage */
11121 /*-----------------------------------------------------------------*/
11123 genPackBits (sym_link * etype,
11125 char *rname, int p_type)
11127 int offset = 0; /* source byte offset */
11128 int rlen = 0; /* remaining bitfield length */
11129 int blen; /* bitfield length */
11130 int bstr; /* bitfield starting bit within byte */
11131 int litval; /* source literal value (if AOP_LIT) */
11132 unsigned char mask; /* bitmask within current byte */
11134 D(emitcode (";", "genPackBits"));
11136 blen = SPEC_BLEN (etype);
11137 bstr = SPEC_BSTR (etype);
11139 /* If the bitfield length is less than a byte */
11142 mask = ((unsigned char) (0xFF << (blen + bstr)) |
11143 (unsigned char) (0xFF >> (8 - bstr)));
11145 if (AOP_TYPE (right) == AOP_LIT)
11147 /* Case with a bitfield length <8 and literal source
11149 litval = (int) ulFromVal (AOP (right)->aopu.aop_lit);
11151 litval &= (~mask) & 0xff;
11152 emitPtrByteGet (rname, p_type, FALSE);
11153 if ((mask|litval)!=0xff)
11154 emitcode ("anl","a,#!constbyte", mask);
11156 emitcode ("orl","a,#!constbyte", litval);
11160 if ((blen==1) && (p_type!=GPOINTER))
11162 /* Case with a bitfield length == 1 and no generic pointer
11164 if (AOP_TYPE (right) == AOP_CRY)
11165 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
11168 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
11169 emitcode ("rrc","a");
11171 emitPtrByteGet (rname, p_type, FALSE);
11172 emitcode ("mov","acc.%d,c",bstr);
11177 /* Case with a bitfield length < 8 and arbitrary source
11179 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
11180 /* shift and mask source value */
11182 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
11184 pushedB = pushB ();
11185 /* transfer A to B and get next byte */
11186 emitPtrByteGet (rname, p_type, TRUE);
11188 emitcode ("anl", "a,#!constbyte", mask);
11189 emitcode ("orl", "a,b");
11190 if (p_type == GPOINTER)
11191 emitcode ("pop", "b");
11197 emitPtrByteSet (rname, p_type, "a");
11201 /* Bit length is greater than 7 bits. In this case, copy */
11202 /* all except the partial byte at the end */
11203 for (rlen=blen;rlen>=8;rlen-=8)
11205 emitPtrByteSet (rname, p_type,
11206 aopGet (right, offset++, FALSE, TRUE, NULL) );
11208 emitcode ("inc", "%s", rname);
11211 /* If there was a partial byte at the end */
11214 mask = (((unsigned char) -1 << rlen) & 0xff);
11216 if (AOP_TYPE (right) == AOP_LIT)
11218 /* Case with partial byte and literal source
11220 litval = (int) ulFromVal (AOP (right)->aopu.aop_lit);
11221 litval >>= (blen-rlen);
11222 litval &= (~mask) & 0xff;
11223 emitPtrByteGet (rname, p_type, FALSE);
11224 if ((mask|litval)!=0xff)
11225 emitcode ("anl","a,#!constbyte", mask);
11227 emitcode ("orl","a,#!constbyte", litval);
11232 /* Case with partial byte and arbitrary source
11234 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11235 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
11237 pushedB = pushB ();
11238 /* transfer A to B and get next byte */
11239 emitPtrByteGet (rname, p_type, TRUE);
11241 emitcode ("anl", "a,#!constbyte", mask);
11242 emitcode ("orl", "a,b");
11243 if (p_type == GPOINTER)
11244 emitcode ("pop", "b");
11248 emitPtrByteSet (rname, p_type, "a");
11253 /*-----------------------------------------------------------------*/
11254 /* genDataPointerSet - remat pointer to data space */
11255 /*-----------------------------------------------------------------*/
11257 genDataPointerSet (operand * right,
11261 int size, offset = 0;
11262 char *l, buffer[256];
11264 D (emitcode (";", "genDataPointerSet"));
11266 aopOp (right, ic, FALSE, FALSE);
11268 l = aopGet (result, 0, FALSE, TRUE, NULL);
11269 size = AOP_SIZE (right);
11273 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l + 1, offset);
11275 SNPRINTF (buffer, sizeof(buffer), "%s", l + 1);
11276 emitcode ("mov", "%s,%s", buffer,
11277 aopGet (right, offset++, FALSE, FALSE, NULL));
11280 freeAsmop (result, NULL, ic, TRUE);
11281 freeAsmop (right, NULL, ic, TRUE);
11284 /*-----------------------------------------------------------------*/
11285 /* genNearPointerSet - emitcode for near pointer put */
11286 /*-----------------------------------------------------------------*/
11288 genNearPointerSet (operand * right,
11295 sym_link *retype, *letype;
11296 sym_link *ptype = operandType (result);
11298 D (emitcode (";", "genNearPointerSet"));
11300 retype = getSpec (operandType (right));
11301 letype = getSpec (ptype);
11303 aopOp (result, ic, FALSE, FALSE);
11305 /* if the result is rematerializable &
11306 in data space & not a bit variable */
11307 if (AOP_TYPE (result) == AOP_IMMD &&
11308 DCL_TYPE (ptype) == POINTER &&
11309 !IS_BITVAR (retype) &&
11310 !IS_BITVAR (letype))
11312 genDataPointerSet (right, result, ic);
11316 /* if the value is already in a pointer register
11317 then don't need anything more */
11318 if (!AOP_INPREG (AOP (result)))
11320 /* otherwise get a free pointer register */
11323 aop = newAsmop (0);
11324 preg = getFreePtr (ic, &aop, FALSE);
11325 emitcode ("mov", "%s,%s",
11327 aopGet (result, 0, FALSE, TRUE, NULL));
11328 rname = preg->name;
11332 rname = aopGet (result, 0, FALSE, FALSE, NULL);
11335 aopOp (right, ic, FALSE, FALSE);
11337 /* if bitfield then unpack the bits */
11338 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11339 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
11342 /* we can just get the values */
11343 int size = AOP_SIZE (right);
11348 l = aopGet (right, offset, FALSE, TRUE, NULL);
11349 if ((*l == '@') || (strcmp (l, "acc") == 0))
11352 emitcode ("mov", "@%s,a", rname);
11355 emitcode ("mov", "@%s,%s", rname, l);
11357 emitcode ("inc", "%s", rname);
11362 /* now some housekeeping stuff */
11363 if (aop) /* we had to allocate for this iCode */
11366 aopPut (result, rname, 0);
11367 freeAsmop (NULL, aop, ic, TRUE);
11371 /* we did not allocate which means left
11372 already in a pointer register, then
11373 if size > 0 && this could be used again
11374 we have to point it back to where it
11376 if (AOP_SIZE (right) > 1 &&
11377 !OP_SYMBOL (result)->remat &&
11378 (OP_SYMBOL (result)->liveTo > ic->seq ||
11382 int size = AOP_SIZE (right) - 1;
11384 emitcode ("dec", "%s", rname);
11389 if (pi) pi->generated = 1;
11390 freeAsmop (result, NULL, ic, TRUE);
11391 freeAsmop (right, NULL, ic, TRUE);
11394 /*-----------------------------------------------------------------*/
11395 /* genPagedPointerSet - emitcode for Paged pointer put */
11396 /*-----------------------------------------------------------------*/
11398 genPagedPointerSet (operand * right,
11405 sym_link *retype, *letype;
11407 D (emitcode (";", "genPagedPointerSet"));
11409 retype = getSpec (operandType (right));
11410 letype = getSpec (operandType (result));
11412 aopOp (result, ic, FALSE, FALSE);
11414 /* if the value is already in a pointer register
11415 then don't need anything more */
11416 if (!AOP_INPREG (AOP (result)))
11418 /* otherwise get a free pointer register */
11421 aop = newAsmop (0);
11422 preg = getFreePtr (ic, &aop, FALSE);
11423 emitcode ("mov", "%s,%s",
11425 aopGet (result, 0, FALSE, TRUE, NULL));
11426 rname = preg->name;
11429 rname = aopGet (result, 0, FALSE, FALSE, NULL);
11431 aopOp (right, ic, FALSE, FALSE);
11433 /* if bitfield then unpack the bits */
11434 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11435 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
11438 /* we have can just get the values */
11439 int size = AOP_SIZE (right);
11444 l = aopGet (right, offset, FALSE, TRUE, NULL);
11446 emitcode ("movx", "@%s,a", rname);
11449 emitcode ("inc", "%s", rname);
11455 /* now some housekeeping stuff */
11459 aopPut (result, rname, 0);
11460 /* we had to allocate for this iCode */
11461 freeAsmop (NULL, aop, ic, TRUE);
11465 /* we did not allocate which means left
11466 already in a pointer register, then
11467 if size > 0 && this could be used again
11468 we have to point it back to where it
11470 if (AOP_SIZE (right) > 1 &&
11471 !OP_SYMBOL (result)->remat &&
11472 (OP_SYMBOL (result)->liveTo > ic->seq ||
11476 int size = AOP_SIZE (right) - 1;
11478 emitcode ("dec", "%s", rname);
11483 if (pi) pi->generated = 1;
11484 freeAsmop (result, NULL, ic, TRUE);
11485 freeAsmop (right, NULL, ic, TRUE);
11488 /*-----------------------------------------------------------------*/
11489 /* genFarPointerSet - set value from far space */
11490 /*-----------------------------------------------------------------*/
11492 genFarPointerSet (operand * right,
11493 operand * result, iCode * ic, iCode *pi)
11495 int size, offset, dopi=1;
11496 sym_link *retype = getSpec (operandType (right));
11497 sym_link *letype = getSpec (operandType (result));
11499 aopOp (result, ic, FALSE, FALSE);
11501 /* if the operand is already in dptr
11502 then we do nothing else we move the value to dptr */
11503 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
11505 /* if this is remateriazable */
11506 if (AOP_TYPE (result) == AOP_IMMD)
11507 emitcode ("mov", "dptr,%s",
11508 aopGet (result, 0, TRUE, FALSE, NULL));
11511 /* we need to get it byte by byte */
11512 _startLazyDPSEvaluation ();
11513 if (AOP_TYPE (result) != AOP_DPTR)
11515 emitcode ("mov", "dpl,%s", aopGet (result, 0, FALSE, FALSE, NULL));
11516 emitcode ("mov", "dph,%s", aopGet (result, 1, FALSE, FALSE, NULL));
11517 if (options.model == MODEL_FLAT24)
11518 emitcode ("mov", "dpx,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11522 /* We need to generate a load to DPTR indirect through DPTR. */
11523 D (emitcode (";", "genFarPointerSet -- indirection special case."););
11525 emitcode ("push", "%s", aopGet (result, 0, FALSE, TRUE, NULL));
11526 emitcode ("push", "%s", aopGet (result, 1, FALSE, TRUE, NULL));
11527 if (options.model == MODEL_FLAT24)
11528 emitcode ("mov", "dpx,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11529 emitcode ("pop", "dph");
11530 emitcode ("pop", "dpl");
11533 _endLazyDPSEvaluation ();
11536 /* so dptr now contains the address */
11537 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
11539 /* if bit then unpack */
11540 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11542 if (AOP_INDPTRn(result)) {
11543 genSetDPTR(AOP(result)->aopu.dptr);
11545 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
11546 if (AOP_INDPTRn(result)) {
11550 size = AOP_SIZE (right);
11552 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
11554 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11556 genSetDPTR(AOP(result)->aopu.dptr);
11557 emitcode ("movx", "@dptr,a");
11558 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
11559 emitcode ("inc", "dptr");
11563 _startLazyDPSEvaluation ();
11565 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11567 if (AOP_INDPTRn(result)) {
11568 genSetDPTR(AOP(result)->aopu.dptr);
11574 emitcode ("movx", "@dptr,a");
11575 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
11576 emitcode ("inc", "dptr");
11578 _endLazyDPSEvaluation ();
11582 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
11583 if (!AOP_INDPTRn(result)) {
11584 _startLazyDPSEvaluation ();
11586 aopPut (result,"dpl",0);
11587 aopPut (result,"dph",1);
11588 if (options.model == MODEL_FLAT24)
11589 aopPut (result,"dpx",2);
11591 _endLazyDPSEvaluation ();
11594 } else if (IS_SYMOP (result) &&
11595 (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 = ulFromVal (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) ulFromVal (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) ulFromVal (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) ulFromVal (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) ulFromVal (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) ulFromVal (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);