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 if (op && IS_GENPTR (operandType (op)) && (AOP_SIZE (op) == GPTRSIZE))
1957 /*-----------------------------------------------------------------*/
1958 /* getDataSize - get the operand data size */
1959 /*-----------------------------------------------------------------*/
1961 getDataSize (operand * op)
1963 int size = AOP_SIZE (op);
1965 if (size == GPTRSIZE)
1967 sym_link *type = operandType (op);
1968 if (IS_GENPTR (type))
1970 /* generic pointer; arithmetic operations
1971 * should ignore the high byte (pointer type).
1979 /*-----------------------------------------------------------------*/
1980 /* outAcc - output Acc */
1981 /*-----------------------------------------------------------------*/
1983 outAcc (operand * result)
1986 size = getDataSize (result);
1989 aopPut (result, "a", 0);
1992 /* unsigned or positive */
1995 aopPut (result, zero, offset++);
2000 /*-----------------------------------------------------------------*/
2001 /* outBitC - output a bit C */
2002 /*-----------------------------------------------------------------*/
2004 outBitC (operand * result)
2006 /* if the result is bit */
2007 if (AOP_TYPE (result) == AOP_CRY)
2009 aopPut (result, "c", 0);
2013 emitcode ("clr", "a");
2014 emitcode ("rlc", "a");
2019 /*-----------------------------------------------------------------*/
2020 /* toBoolean - emit code for orl a,operator(sizeop) */
2021 /*-----------------------------------------------------------------*/
2023 toBoolean (operand * oper)
2025 int size = AOP_SIZE (oper) - 1;
2029 /* The generic part of a generic pointer should
2030 * not participate in it's truth value.
2032 * i.e. 0x10000000 is zero.
2034 if (opIsGptr (oper))
2036 D (emitcode (";", "toBoolean: generic ptr special case."));
2040 _startLazyDPSEvaluation ();
2041 MOVA (aopGet (oper, 0, FALSE, FALSE, NULL));
2042 if (AOP_NEEDSACC (oper) && size && (AOP (oper)->type != AOP_ACC))
2045 emitcode("mov", "b,a");
2048 MOVA (aopGet (oper, offset++, FALSE, FALSE, NULL));
2049 emitcode ("orl", "b,a");
2051 MOVA (aopGet (oper, offset++, FALSE, FALSE, NULL));
2052 emitcode ("orl", "a,b");
2059 emitcode ("orl", "a,%s",
2060 aopGet (oper, offset++, FALSE, FALSE, NULL));
2063 _endLazyDPSEvaluation ();
2067 /*-----------------------------------------------------------------*/
2068 /* genNot - generate code for ! operation */
2069 /*-----------------------------------------------------------------*/
2075 D (emitcode (";", "genNot"));
2077 /* assign asmOps to operand & result */
2078 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2079 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
2081 /* if in bit space then a special case */
2082 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2084 /* if left==result then cpl bit */
2085 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2087 emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2091 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2092 emitcode ("cpl", "c");
2093 outBitC (IC_RESULT (ic));
2098 toBoolean (IC_LEFT (ic));
2100 /* set C, if a == 0 */
2101 tlbl = newiTempLabel (NULL);
2102 emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
2104 outBitC (IC_RESULT (ic));
2107 /* release the aops */
2108 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2109 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2113 /*-----------------------------------------------------------------*/
2114 /* genCpl - generate code for complement */
2115 /*-----------------------------------------------------------------*/
2122 sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
2124 D(emitcode (";", "genCpl"));
2126 /* assign asmOps to operand & result */
2127 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2128 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
2130 /* special case if in bit space */
2131 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2135 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
2136 (SPEC_USIGN (letype) && IS_CHAR (letype)))
2138 /* promotion rules are responsible for this strange result:
2139 bit -> int -> ~int -> bit
2140 uchar -> int -> ~int -> bit
2142 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
2146 tlbl=newiTempLabel(NULL);
2147 l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE, NULL);
2148 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
2149 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
2150 IS_AOP_PREG (IC_LEFT (ic)))
2152 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
2157 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
2160 outBitC (IC_RESULT(ic));
2164 size = AOP_SIZE (IC_RESULT (ic));
2165 _startLazyDPSEvaluation ();
2168 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL);
2170 emitcode ("cpl", "a");
2171 aopPut (IC_RESULT (ic), "a", offset++);
2173 _endLazyDPSEvaluation ();
2177 /* release the aops */
2178 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2179 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2182 /*-----------------------------------------------------------------*/
2183 /* genUminusFloat - unary minus for floating points */
2184 /*-----------------------------------------------------------------*/
2186 genUminusFloat (operand * op, operand * result)
2188 int size, offset = 0;
2191 D (emitcode (";", "genUminusFloat"));
2193 /* for this we just copy and then flip the bit */
2195 _startLazyDPSEvaluation ();
2196 size = AOP_SIZE (op) - 1;
2201 aopGet (op, offset, FALSE, FALSE, NULL),
2206 l = aopGet (op, offset, FALSE, FALSE, NULL);
2209 emitcode ("cpl", "acc.7");
2210 aopPut (result, "a", offset);
2211 _endLazyDPSEvaluation ();
2214 /*-----------------------------------------------------------------*/
2215 /* genUminus - unary minus code generation */
2216 /*-----------------------------------------------------------------*/
2218 genUminus (iCode * ic)
2223 D (emitcode (";", "genUminus"));
2226 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2227 aopOp (IC_RESULT (ic), ic, TRUE, (AOP_TYPE(IC_LEFT (ic)) == AOP_DPTR));
2229 /* if both in bit space then special
2231 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2232 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2235 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2236 emitcode ("cpl", "c");
2237 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2241 optype = operandType (IC_LEFT (ic));
2243 /* if float then do float stuff */
2244 if (IS_FLOAT (optype))
2246 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2250 /* otherwise subtract from zero */
2251 size = AOP_SIZE (IC_LEFT (ic));
2253 _startLazyDPSEvaluation ();
2256 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL);
2257 if (!strcmp (l, "a"))
2261 emitcode ("cpl", "a");
2262 emitcode ("addc", "a,#0");
2268 emitcode ("clr", "a");
2269 emitcode ("subb", "a,%s", l);
2271 aopPut (IC_RESULT (ic), "a", offset++);
2273 _endLazyDPSEvaluation ();
2275 /* if any remaining bytes in the result */
2276 /* we just need to propagate the sign */
2277 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2279 emitcode ("rlc", "a");
2280 emitcode ("subb", "a,acc");
2282 aopPut (IC_RESULT (ic), "a", offset++);
2286 /* release the aops */
2287 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2288 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2291 /*-----------------------------------------------------------------*/
2292 /* savermask - saves registers in the mask */
2293 /*-----------------------------------------------------------------*/
2294 static void savermask(bitVect *rs_mask)
2298 if (options.useXstack)
2300 if (bitVectBitValue (rs_mask, R0_IDX))
2301 emitcode ("mov", "b,r0");
2302 emitcode ("mov", "r0,%s", spname);
2303 for (i = 0; i < ds390_nRegs; i++)
2305 if (bitVectBitValue (rs_mask, i))
2308 emitcode ("mov", "a,b");
2310 emitcode ("mov", "a,%s", REG_WITH_INDEX (i)->name);
2311 emitcode ("movx", "@r0,a");
2312 emitcode ("inc", "r0");
2315 emitcode ("mov", "%s,r0", spname);
2316 if (bitVectBitValue (rs_mask, R0_IDX))
2317 emitcode ("mov", "r0,b");
2321 bool bits_pushed = FALSE;
2322 for (i = 0; i < ds390_nRegs; i++)
2324 if (bitVectBitValue (rs_mask, i))
2326 bits_pushed = pushReg (i, bits_pushed);
2332 /*-----------------------------------------------------------------*/
2333 /* saveRegisters - will look for a call and save the registers */
2334 /*-----------------------------------------------------------------*/
2336 saveRegisters (iCode * lic)
2342 for (ic = lic; ic; ic = ic->next)
2343 if (ic->op == CALL || ic->op == PCALL)
2348 fprintf (stderr, "found parameter push with no function call\n");
2352 /* if the registers have been saved already or don't need to be then
2355 || (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))) && !TARGET_IS_DS400) )
2358 /* special case if DPTR alive across a function call then must save it
2359 even though callee saves */
2360 if (IS_SYMOP(IC_LEFT(ic)) &&
2361 IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type))
2364 rsave = newBitVect(ic->rMask->size);
2365 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2366 if (bitVectBitValue(ic->rMask,i))
2367 rsave = bitVectSetBit(rsave,i);
2369 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2373 /* save the registers in use at this time but skip the
2374 ones for the result */
2375 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2376 ds390_rUmaskForOp (IC_RESULT(ic)));
2382 /*-----------------------------------------------------------------*/
2383 /* usavermask - restore registers with mask */
2384 /*-----------------------------------------------------------------*/
2385 static void unsavermask(bitVect *rs_mask)
2389 if (options.useXstack)
2391 emitcode ("mov", "r0,%s", spname);
2392 for (i = ds390_nRegs; i >= 0; i--)
2394 if (bitVectBitValue (rs_mask, i))
2396 regs * reg = REG_WITH_INDEX (i);
2397 emitcode ("dec", "r0");
2398 emitcode ("movx", "a,@r0");
2401 emitcode ("push", "acc");
2405 emitcode ("mov", "%s,a", reg->name);
2409 emitcode ("mov", "%s,r0", spname);
2410 if (bitVectBitValue (rs_mask, R0_IDX))
2412 emitcode ("pop", "ar0");
2417 bool bits_popped = FALSE;
2418 for (i = ds390_nRegs; i >= 0; i--)
2420 if (bitVectBitValue (rs_mask, i))
2422 bits_popped = popReg (i, bits_popped);
2428 /*-----------------------------------------------------------------*/
2429 /* unsaveRegisters - pop the pushed registers */
2430 /*-----------------------------------------------------------------*/
2432 unsaveRegisters (iCode * ic)
2436 if (IS_SYMOP(IC_LEFT (ic)) &&
2437 IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2439 rsave = newBitVect(ic->rMask->size);
2440 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2441 if (bitVectBitValue(ic->rMask,i))
2442 rsave = bitVectSetBit(rsave,i);
2444 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2446 /* restore the registers in use at this time but skip the
2447 ones for the result */
2448 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2449 ds390_rUmaskForOp (IC_RESULT(ic)));
2455 /*-----------------------------------------------------------------*/
2457 /*-----------------------------------------------------------------*/
2459 pushSide (operand * oper, int size, iCode * ic)
2462 int nPushed = _G.r0Pushed + _G.r1Pushed;
2464 aopOp (oper, ic, FALSE, FALSE);
2466 if (nPushed != _G.r0Pushed + _G.r1Pushed)
2468 while (offset < size)
2470 char *l = aopGet (oper, offset, FALSE, TRUE, NULL);
2471 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2473 freeAsmop (oper, NULL, ic, TRUE);
2475 while (offset < size)
2477 emitcode ("push", "%s", fReturn[offset++]);
2482 _startLazyDPSEvaluation ();
2485 char *l = aopGet (oper, offset++, FALSE, TRUE, NULL);
2486 if (AOP_TYPE (oper) != AOP_REG &&
2487 AOP_TYPE (oper) != AOP_DIR &&
2491 emitcode ("push", "acc");
2495 emitcode ("push", "%s", l);
2498 _endLazyDPSEvaluation ();
2499 freeAsmop (oper, NULL, ic, TRUE);
2502 /*-----------------------------------------------------------------*/
2503 /* assignResultValue - also indicates if acc is in use afterwards */
2504 /*-----------------------------------------------------------------*/
2506 assignResultValue (operand * oper, operand * func)
2509 unsigned size = AOP_SIZE (oper);
2510 bool accuse = FALSE;
2511 bool pushedA = FALSE;
2513 if (func && IS_BIT (OP_SYM_ETYPE (func)))
2519 if (size == fReturnSizeDS390)
2521 /* I don't think this case can ever happen... */
2522 /* ACC is the last part of this. If writing the result
2523 * uses ACC, we must preserve it.
2525 if (AOP_NEEDSACC(oper))
2527 emitcode(";", "assignResultValue special case for ACC.");
2528 emitcode("push", "acc");
2534 _startLazyDPSEvaluation ();
2537 accuse |= aopPut (oper, fReturn[offset], offset);
2540 _endLazyDPSEvaluation ();
2544 emitcode ("pop", "acc");
2545 accuse |= aopPut (oper, "a", offset);
2551 /*-----------------------------------------------------------------*/
2552 /* genXpush - pushes onto the external stack */
2553 /*-----------------------------------------------------------------*/
2555 genXpush (iCode * ic)
2557 asmop *aop = newAsmop (0);
2559 int size, offset = 0;
2561 D (emitcode (";", "genXpush"));
2563 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2564 r = getFreePtr (ic, &aop, FALSE);
2566 size = AOP_SIZE (IC_LEFT (ic));
2570 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
2571 emitcode ("mov", "%s,_spx", r->name);
2572 emitcode ("inc", "_spx"); // allocate space first
2573 emitcode ("movx", "@%s,a", r->name);
2577 // allocate space first
2578 emitcode ("mov", "%s,_spx", r->name);
2580 emitcode ("add", "a,#%d", size);
2581 emitcode ("mov", "_spx,a");
2583 _startLazyDPSEvaluation ();
2586 MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE, NULL));
2587 emitcode ("movx", "@%s,a", r->name);
2588 emitcode ("inc", "%s", r->name);
2590 _endLazyDPSEvaluation ();
2593 freeAsmop (NULL, aop, ic, TRUE);
2594 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2597 /*-----------------------------------------------------------------*/
2598 /* genIpush - generate code for pushing this gets a little complex */
2599 /*-----------------------------------------------------------------*/
2601 genIpush (iCode * ic)
2603 int size, offset = 0;
2607 D (emitcode (";", "genIpush"));
2609 /* if this is not a parm push : ie. it is spill push
2610 and spill push is always done on the local stack */
2614 /* and the item is spilt then do nothing */
2615 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2618 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2619 size = AOP_SIZE (IC_LEFT (ic));
2620 /* push it on the stack */
2621 _startLazyDPSEvaluation ();
2624 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE, NULL);
2630 emitcode ("push", "%s", l);
2632 _endLazyDPSEvaluation ();
2636 /* this is a parameter push: in this case we call
2637 the routine to find the call and save those
2638 registers that need to be saved */
2641 /* if use external stack then call the external
2642 stack pushing routine */
2643 if (options.useXstack)
2649 /* then do the push */
2650 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2652 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2653 size = AOP_SIZE (IC_LEFT (ic));
2655 _startLazyDPSEvaluation ();
2658 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE, NULL);
2659 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2660 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2663 if (strcmp (l, prev) || *l == '@')
2665 emitcode ("push", "acc");
2669 emitcode ("push", "%s", l);
2673 _endLazyDPSEvaluation ();
2675 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2678 /*-----------------------------------------------------------------*/
2679 /* genIpop - recover the registers: can happen only for spilling */
2680 /*-----------------------------------------------------------------*/
2682 genIpop (iCode * ic)
2686 D (emitcode (";", "genIpop"));
2688 /* if the temp was not pushed then */
2689 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2692 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2693 size = AOP_SIZE (IC_LEFT (ic));
2694 offset = (size - 1);
2695 _startLazyDPSEvaluation ();
2698 emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2699 FALSE, TRUE, NULL));
2701 _endLazyDPSEvaluation ();
2703 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2706 /*-----------------------------------------------------------------*/
2707 /* saveRBank - saves an entire register bank on the stack */
2708 /*-----------------------------------------------------------------*/
2710 saveRBank (int bank, iCode * ic, bool pushPsw)
2713 int count = 8 + (ds390_nBitRegs/8) + (pushPsw ? 1 : 0);
2717 if (options.useXstack)
2721 /* Assume r0 is available for use. */
2722 r = REG_WITH_INDEX (R0_IDX);;
2727 r = getFreePtr (ic, &aop, FALSE);
2729 // allocate space first
2730 emitcode ("mov", "%s,_spx", r->name);
2732 emitcode ("add", "a,#%d", count);
2733 emitcode ("mov", "_spx,a");
2736 for (i = 0; i < 8; i++) /* only R0-R7 needs saving */
2738 if (options.useXstack)
2740 emitcode ("mov", "a,(%s+%d)",
2741 regs390[i].base, 8 * bank + regs390[i].offset);
2742 emitcode ("movx", "@%s,a", r->name);
2744 emitcode ("inc", "%s", r->name);
2747 emitcode ("push", "(%s+%d)",
2748 regs390[i].base, 8 * bank + regs390[i].offset);
2751 if (ds390_nBitRegs > 0)
2753 if (options.useXstack)
2755 emitcode ("mov", "a,bits");
2756 emitcode ("movx", "@%s,a", r->name);
2758 emitcode ("inc", "%s", r->name);
2762 emitcode ("push", "bits");
2769 if (options.useXstack)
2771 emitcode ("mov", "a,psw");
2772 emitcode ("movx", "@%s,a", r->name);
2776 emitcode ("push", "psw");
2779 emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2784 freeAsmop (NULL, aop, ic, TRUE);
2793 /*-----------------------------------------------------------------*/
2794 /* unsaveRBank - restores the register bank from stack */
2795 /*-----------------------------------------------------------------*/
2797 unsaveRBank (int bank, iCode * ic, bool popPsw)
2803 if (options.useXstack)
2807 /* Assume r0 is available for use. */
2808 r = REG_WITH_INDEX (R0_IDX);;
2813 r = getFreePtr (ic, &aop, FALSE);
2815 emitcode ("mov", "%s,_spx", r->name);
2820 if (options.useXstack)
2822 emitcode ("dec", "%s", r->name);
2823 emitcode ("movx", "a,@%s", r->name);
2824 emitcode ("mov", "psw,a");
2828 emitcode ("pop", "psw");
2832 if (ds390_nBitRegs > 0)
2834 if (options.useXstack)
2836 emitcode ("dec", "%s", r->name);
2837 emitcode ("movx", "a,@%s", r->name);
2838 emitcode ("mov", "bits,a");
2842 emitcode ("pop", "bits");
2846 for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2848 if (options.useXstack)
2850 emitcode ("dec", "%s", r->name);
2851 emitcode ("movx", "a,@%s", r->name);
2852 emitcode ("mov", "(%s+%d),a",
2853 regs390[i].base, 8 * bank + regs390[i].offset);
2857 emitcode ("pop", "(%s+%d)",
2858 regs390[i].base, 8 * bank + regs390[i].offset);
2862 if (options.useXstack)
2864 emitcode ("mov", "_spx,%s", r->name);
2869 freeAsmop (NULL, aop, ic, TRUE);
2873 /*-----------------------------------------------------------------*/
2874 /* genSend - gen code for SEND */
2875 /*-----------------------------------------------------------------*/
2876 static void genSend(set *sendSet)
2881 static int rb1_count = 0;
2883 /* first we do all bit parameters */
2884 for (sic = setFirstItem (sendSet); sic;
2885 sic = setNextItem (sendSet))
2887 if (sic->argreg > 12)
2889 int bit = sic->argreg-13;
2891 aopOp (IC_LEFT (sic), sic, FALSE,
2892 (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2894 /* if left is a literal then
2895 we know what the value is */
2896 if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2898 if (((int) operandLitValue (IC_LEFT (sic))))
2899 emitcode ("setb", "b[%d]", bit);
2901 emitcode ("clr", "b[%d]", bit);
2903 else if (AOP_TYPE (IC_LEFT (sic)) == AOP_CRY)
2905 char *l = AOP (IC_LEFT (sic))->aopu.aop_dir;
2906 if (strcmp (l, "c"))
2907 emitcode ("mov", "c,%s", l);
2908 emitcode ("mov", "b[%d],c", bit);
2913 toBoolean (IC_LEFT (sic));
2914 /* set C, if a >= 1 */
2915 emitcode ("add", "a,#0xff");
2916 emitcode ("mov", "b[%d],c", bit);
2921 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2927 saveRegisters (setFirstItem (sendSet));
2928 emitcode ("mov", "bits,b");
2931 /* then we do all other parameters */
2932 for (sic = setFirstItem (sendSet); sic;
2933 sic = setNextItem (sendSet))
2935 if (sic->argreg <= 12)
2937 int size, offset = 0;
2939 size = getSize (operandType (IC_LEFT (sic)));
2940 D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2941 if (sendCount == 0) { /* first parameter */
2942 // we know that dpl(hxb) is the result, so
2944 _startLazyDPSEvaluation ();
2946 aopOp (IC_LEFT (sic), sic, FALSE,
2947 (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2949 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2953 char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE, NULL);
2954 if (strcmp (l, fReturn[offset]))
2956 emitcode ("mov", "%s,%s", fReturn[offset], l);
2960 _endLazyDPSEvaluation ();
2961 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2963 } else { /* if more parameter in registers */
2964 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2966 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (IC_LEFT (sic), offset++,
2967 FALSE, FALSE, NULL));
2969 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2977 adjustEsp(const char *reg)
2979 emitcode ("anl","%s,#3", reg);
2980 if (TARGET_IS_DS400)
2982 emitcode ("orl","%s,#!constbyte",
2984 (options.stack_loc >> 8) & 0xff);
2988 /*-----------------------------------------------------------------*/
2989 /* selectRegBank - emit code to select the register bank */
2990 /*-----------------------------------------------------------------*/
2992 selectRegBank (short bank, bool keepFlags)
2994 /* if f.e. result is in carry */
2997 emitcode ("anl", "psw,#0xE7");
2999 emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
3003 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
3007 /*-----------------------------------------------------------------*/
3008 /* genCall - generates a call statement */
3009 /*-----------------------------------------------------------------*/
3011 genCall (iCode * ic)
3015 bool restoreBank = FALSE;
3016 bool swapBanks = FALSE;
3017 bool accuse = FALSE;
3018 bool accPushed = FALSE;
3019 bool resultInF0 = FALSE;
3020 bool assignResultGenerated = FALSE;
3022 D (emitcode (";", "genCall"));
3024 /* if we are calling a not _naked function that is not using
3025 the same register bank then we need to save the
3026 destination registers on the stack */
3027 dtype = operandType (IC_LEFT (ic));
3028 etype = getSpec(dtype);
3029 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
3030 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
3031 IFFUNC_ISISR (currFunc->type))
3035 /* This is unexpected; the bank should have been saved in
3038 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
3044 /* if caller saves & we have not saved then */
3048 /* if send set is not empty then assign */
3049 /* We've saved all the registers we care about;
3050 * therefore, we may clobber any register not used
3051 * in the calling convention (i.e. anything not in
3056 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
3057 genSend(reverseSet(_G.sendSet));
3059 genSend(_G.sendSet);
3066 emitcode ("mov", "psw,#!constbyte",
3067 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3071 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
3072 OP_SYMBOL (IC_LEFT (ic))->rname :
3073 OP_SYMBOL (IC_LEFT (ic))->name));
3077 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
3080 /* if we need assign a result value */
3081 if ((IS_ITEMP (IC_RESULT (ic)) &&
3082 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3083 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3084 OP_SYMBOL (IC_RESULT (ic))->accuse ||
3085 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3086 IS_TRUE_SYMOP (IC_RESULT (ic)))
3088 if (isOperandInFarSpace (IC_RESULT (ic))
3089 && getSize (operandType (IC_RESULT (ic))) <= 2)
3091 int size = getSize (operandType (IC_RESULT (ic)));
3092 bool pushedB = FALSE;
3094 /* Special case for 1 or 2 byte return in far space. */
3099 emitcode ("mov", "b,%s", fReturn[1]);
3103 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
3108 aopPut (IC_RESULT (ic), "a", 0);
3112 aopPut (IC_RESULT (ic), "b", 1);
3114 assignResultGenerated = TRUE;
3115 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3119 bool pushedB = pushB ();
3120 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
3123 accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3124 assignResultGenerated = TRUE;
3125 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3129 /* adjust the stack for parameters if required */
3133 if (options.stack10bit) {
3134 if (ic->parmBytes <= 10) {
3135 emitcode(";","stack adjustment for parms");
3136 for (i=0; i < ic->parmBytes ; i++) {
3137 emitcode("pop","acc");
3141 emitcode ("clr","c");
3142 emitcode ("mov","a,sp");
3143 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
3144 emitcode ("mov","sp,a");
3145 emitcode ("mov","a,esp");
3147 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
3148 emitcode ("mov","esp,a");
3152 if (ic->parmBytes > 3)
3156 emitcode ("push", "acc");
3159 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3160 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3161 !assignResultGenerated)
3163 emitcode ("mov", "F0,c");
3167 emitcode ("mov", "a,%s", spname);
3168 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
3169 emitcode ("mov", "%s,a", spname);
3171 /* unsaveRegisters from xstack needs acc, but */
3172 /* unsaveRegisters from stack needs this popped */
3173 if (accPushed && !options.useXstack)
3175 emitcode ("pop", "acc");
3180 for (i = 0; i < ic->parmBytes; i++)
3181 emitcode ("dec", "%s", spname);
3185 /* if we had saved some registers then unsave them */
3186 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3188 if (accuse && !accPushed && options.useXstack)
3190 /* xstack needs acc, but doesn't touch normal stack */
3191 emitcode ("push", "acc");
3194 unsaveRegisters (ic);
3197 /* if register bank was saved then pop them */
3199 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
3201 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
3204 emitcode ("mov", "c,F0");
3206 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
3207 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3208 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3212 emitcode ("pop", "acc");
3215 /*-----------------------------------------------------------------*/
3216 /* genPcall - generates a call by pointer statement */
3217 /*-----------------------------------------------------------------*/
3219 genPcall (iCode * ic)
3223 symbol *rlbl = newiTempLabel (NULL);
3224 bool restoreBank=FALSE;
3225 bool resultInF0 = FALSE;
3227 D (emitcode (";", "genPcall"));
3229 dtype = operandType (IC_LEFT (ic))->next;
3230 etype = getSpec(dtype);
3231 /* if caller saves & we have not saved then */
3235 /* if we are calling a not _naked function that is not using
3236 the same register bank then we need to save the
3237 destination registers on the stack */
3238 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
3239 IFFUNC_ISISR (currFunc->type) &&
3240 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
3241 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3245 /* push the return address on to the stack */
3246 emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
3247 emitcode ("push", "acc");
3248 emitcode ("mov", "a,#!hil", (rlbl->key + 100));
3249 emitcode ("push", "acc");
3251 if (options.model == MODEL_FLAT24)
3253 emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
3254 emitcode ("push", "acc");
3257 /* now push the function address */
3258 pushSide (IC_LEFT (ic), FPTRSIZE, ic);
3260 /* if send set is not empty then assign */
3263 genSend(reverseSet(_G.sendSet));
3268 emitcode ("ret", "");
3272 /* if we need assign a result value */
3273 if ((IS_ITEMP (IC_RESULT (ic)) &&
3274 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3275 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3276 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3277 IS_TRUE_SYMOP (IC_RESULT (ic)))
3281 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
3284 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3286 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3289 /* adjust the stack for parameters if required */
3293 if (options.stack10bit) {
3294 if (ic->parmBytes <= 10) {
3295 emitcode(";","stack adjustment for parms");
3296 for (i=0; i < ic->parmBytes ; i++) {
3297 emitcode("pop","acc");
3300 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3301 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3303 emitcode ("mov", "F0,c");
3308 emitcode ("clr","c");
3309 emitcode ("mov","a,sp");
3310 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
3311 emitcode ("mov","sp,a");
3312 emitcode ("mov","a,esp");
3314 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
3315 emitcode ("mov","esp,a");
3319 if (ic->parmBytes > 3) {
3320 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3321 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3323 emitcode ("mov", "F0,c");
3327 emitcode ("mov", "a,%s", spname);
3328 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
3329 emitcode ("mov", "%s,a", spname);
3332 for (i = 0; i < ic->parmBytes; i++)
3333 emitcode ("dec", "%s", spname);
3336 /* if register bank was saved then unsave them */
3338 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3340 /* if we had saved some registers then unsave them */
3342 unsaveRegisters (ic);
3344 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3347 emitcode ("mov", "c,F0");
3349 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
3350 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3351 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3355 /*-----------------------------------------------------------------*/
3356 /* resultRemat - result is rematerializable */
3357 /*-----------------------------------------------------------------*/
3359 resultRemat (iCode * ic)
3361 if (SKIP_IC (ic) || ic->op == IFX)
3364 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3366 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3367 if (sym->remat && !POINTER_SET (ic))
3374 /*-----------------------------------------------------------------*/
3375 /* inExcludeList - return 1 if the string is in exclude Reg list */
3376 /*-----------------------------------------------------------------*/
3378 regsCmp(void *p1, void *p2)
3380 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3384 inExcludeList (char *s)
3386 const char *p = setFirstItem(options.excludeRegsSet);
3388 if (p == NULL || STRCASECMP(p, "none") == 0)
3392 return isinSetWith(options.excludeRegsSet, s, regsCmp);
3395 /*-----------------------------------------------------------------*/
3396 /* genFunction - generated code for function entry */
3397 /*-----------------------------------------------------------------*/
3399 genFunction (iCode * ic)
3401 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3403 bool switchedPSW = FALSE;
3404 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3406 D (emitcode (";", "genFunction"));
3409 /* create the function header */
3410 emitcode (";", "-----------------------------------------");
3411 emitcode (";", " function %s", sym->name);
3412 emitcode (";", "-----------------------------------------");
3414 emitcode ("", "%s:", sym->rname);
3415 lineCurr->isLabel = 1;
3416 ftype = operandType (IC_LEFT (ic));
3417 _G.currentFunc = sym;
3419 if (IFFUNC_ISNAKED(ftype))
3421 emitcode(";", "naked function: no prologue.");
3425 if (options.stack_probe)
3426 emitcode ("lcall","__stack_probe");
3428 /* here we need to generate the equates for the
3429 register bank if required */
3430 if (FUNC_REGBANK (ftype) != rbank)
3434 rbank = FUNC_REGBANK (ftype);
3435 for (i = 0; i < ds390_nRegs; i++)
3437 if (regs390[i].print) {
3438 if (strcmp (regs390[i].base, "0") == 0)
3439 emitcode ("", "%s !equ !constbyte",
3441 8 * rbank + regs390[i].offset);
3443 emitcode ("", "%s !equ %s + !constbyte",
3446 8 * rbank + regs390[i].offset);
3451 /* if this is an interrupt service routine then
3452 save acc, b, dpl, dph */
3453 if (IFFUNC_ISISR (sym->type))
3455 if (!inExcludeList ("acc"))
3456 emitcode ("push", "acc");
3457 if (!inExcludeList ("b"))
3458 emitcode ("push", "b");
3459 if (!inExcludeList ("dpl"))
3460 emitcode ("push", "dpl");
3461 if (!inExcludeList ("dph"))
3462 emitcode ("push", "dph");
3463 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3465 emitcode ("push", "dpx");
3466 /* Make sure we're using standard DPTR */
3467 emitcode ("push", "dps");
3468 emitcode ("mov", "dps,#0");
3469 if (options.stack10bit)
3471 /* This ISR could conceivably use DPTR2. Better save it. */
3472 emitcode ("push", "dpl1");
3473 emitcode ("push", "dph1");
3474 emitcode ("push", "dpx1");
3475 emitcode ("push", DP2_RESULT_REG);
3478 /* if this isr has no bank i.e. is going to
3479 run with bank 0 , then we need to save more
3481 if (!FUNC_REGBANK (sym->type))
3485 /* if this function does not call any other
3486 function then we can be economical and
3487 save only those registers that are used */
3488 if (!IFFUNC_HASFCALL(sym->type))
3490 /* if any registers used */
3493 bool bits_pushed = FALSE;
3494 /* save the registers used */
3495 for (i = 0; i < sym->regsUsed->size; i++)
3497 if (bitVectBitValue (sym->regsUsed, i))
3498 bits_pushed = pushReg (i, bits_pushed);
3504 /* this function has a function call. We cannot
3505 determine register usage so we will have to push the
3507 saveRBank (0, ic, FALSE);
3508 if (options.parms_in_bank1) {
3509 for (i=0; i < 8 ; i++ ) {
3510 emitcode ("push","%s",rb1regs[i]);
3517 /* This ISR uses a non-zero bank.
3519 * We assume that the bank is available for our
3522 * However, if this ISR calls a function which uses some
3523 * other bank, we must save that bank entirely.
3525 unsigned long banksToSave = 0;
3527 if (IFFUNC_HASFCALL(sym->type))
3530 #define MAX_REGISTER_BANKS 4
3535 for (i = ic; i; i = i->next)
3537 if (i->op == ENDFUNCTION)
3539 /* we got to the end OK. */
3547 dtype = operandType (IC_LEFT(i));
3549 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3551 /* Mark this bank for saving. */
3552 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3554 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3558 banksToSave |= (1 << FUNC_REGBANK(dtype));
3561 /* And note that we don't need to do it in
3569 /* This is a mess; we have no idea what
3570 * register bank the called function might
3573 * The only thing I can think of to do is
3574 * throw a warning and hope.
3576 werror(W_FUNCPTR_IN_USING_ISR);
3580 if (banksToSave && options.useXstack)
3582 /* Since we aren't passing it an ic,
3583 * saveRBank will assume r0 is available to abuse.
3585 * So switch to our (trashable) bank now, so
3586 * the caller's R0 isn't trashed.
3588 emitcode ("push", "psw");
3589 emitcode ("mov", "psw,#!constbyte",
3590 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3594 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3596 if (banksToSave & (1 << ix))
3598 saveRBank(ix, NULL, FALSE);
3602 // TODO: this needs a closer look
3603 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3608 /* if callee-save to be used for this function
3609 then save the registers being used in this function */
3610 if (IFFUNC_CALLEESAVES(sym->type))
3614 /* if any registers used */
3617 bool bits_pushed = FALSE;
3618 /* save the registers used */
3619 for (i = 0; i < sym->regsUsed->size; i++)
3621 if (bitVectBitValue (sym->regsUsed, i))
3623 bits_pushed = pushReg (i, bits_pushed);
3631 /* set the register bank to the desired value */
3632 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3635 emitcode ("push", "psw");
3636 emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3640 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3641 if (options.stack10bit) {
3642 emitcode ("push","_bpx");
3643 emitcode ("push","_bpx+1");
3644 emitcode ("mov","_bpx,%s",spname);
3645 emitcode ("mov","_bpx+1,esp");
3646 adjustEsp("_bpx+1");
3648 if (options.useXstack)
3650 emitcode ("mov", "r0,%s", spname);
3651 emitcode ("mov", "a,_bp");
3652 emitcode ("movx", "@r0,a");
3653 emitcode ("inc", "%s", spname);
3655 /* set up the stack */
3656 emitcode ("push", "_bp"); /* save the callers stack */
3658 emitcode ("mov", "_bp,%s", spname);
3662 /* adjust the stack for the function */
3665 if (options.stack10bit) {
3666 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
3667 assert (sym->recvSize <= 4);
3668 if (sym->stack <= 8) {
3669 while (i--) emitcode ("push","acc");
3672 emitcode ("mov","a,sp");
3673 emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3674 emitcode ("mov","sp,a");
3675 emitcode ("mov","a,esp");
3677 emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3678 emitcode ("mov","esp,a");
3683 werror (W_STACK_OVERFLOW, sym->name);
3685 if (i > 3 && sym->recvSize < 4) {
3687 emitcode ("mov", "a,sp");
3688 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3689 emitcode ("mov", "sp,a");
3693 emitcode ("inc", "sp");
3700 emitcode ("mov", "a,_spx");
3701 emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3702 emitcode ("mov", "_spx,a");
3705 /* if critical function then turn interrupts off */
3706 if (IFFUNC_ISCRITICAL (ftype))
3708 symbol *tlbl = newiTempLabel (NULL);
3709 emitcode ("setb", "c");
3710 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3711 emitcode ("clr", "c");
3713 emitcode ("push", "psw"); /* save old ea via c in psw */
3717 /*-----------------------------------------------------------------*/
3718 /* genEndFunction - generates epilogue for functions */
3719 /*-----------------------------------------------------------------*/
3721 genEndFunction (iCode * ic)
3723 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3724 lineNode *lnp = lineCurr;
3726 bitVect *regsUsedPrologue;
3727 bitVect *regsUnneeded;
3730 D (emitcode (";", "genEndFunction"));
3732 _G.currentFunc = NULL;
3733 if (IFFUNC_ISNAKED(sym->type))
3735 emitcode(";", "naked function: no epilogue.");
3736 if (options.debug && currFunc)
3737 debugFile->writeEndFunction (currFunc, ic, 0);
3741 if (IFFUNC_ISCRITICAL (sym->type))
3743 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3745 emitcode ("rlc", "a"); /* save c in a */
3746 emitcode ("pop", "psw"); /* restore ea via c in psw */
3747 emitcode ("mov", "ea,c");
3748 emitcode ("rrc", "a"); /* restore c from a */
3752 emitcode ("pop", "psw"); /* restore ea via c in psw */
3753 emitcode ("mov", "ea,c");
3757 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3758 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3760 if (options.stack10bit) {
3762 emitcode ("mov", "sp,_bpx", spname);
3763 emitcode ("mov", "esp,_bpx+1", spname);
3766 emitcode ("mov", "%s,_bp", spname);
3770 /* if use external stack but some variables were
3771 added to the local stack then decrement the
3773 if (options.useXstack && sym->stack) {
3774 emitcode ("mov", "a,sp");
3775 emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3776 emitcode ("mov", "sp,a");
3780 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3781 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3783 if (options.useXstack) {
3784 emitcode ("mov", "r0,%s", spname);
3785 emitcode ("movx", "a,@r0");
3786 emitcode ("mov", "_bp,a");
3787 emitcode ("dec", "%s", spname);
3789 if (options.stack10bit) {
3790 emitcode ("pop", "_bpx+1");
3791 emitcode ("pop", "_bpx");
3793 emitcode ("pop", "_bp");
3798 /* restore the register bank */
3799 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3801 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3802 || !options.useXstack)
3804 /* Special case of ISR using non-zero bank with useXstack
3807 emitcode ("pop", "psw");
3811 if (IFFUNC_ISISR (sym->type))
3814 /* now we need to restore the registers */
3815 /* if this isr has no bank i.e. is going to
3816 run with bank 0 , then we need to save more
3818 if (!FUNC_REGBANK (sym->type))
3821 /* if this function does not call any other
3822 function then we can be economical and
3823 save only those registers that are used */
3824 if (!IFFUNC_HASFCALL(sym->type))
3826 /* if any registers used */
3829 bool bits_popped = FALSE;
3830 /* save the registers used */
3831 for (i = sym->regsUsed->size; i >= 0; i--)
3833 if (bitVectBitValue (sym->regsUsed, i))
3834 bits_popped = popReg (i, bits_popped);
3840 /* this function has a function call. We cannot
3841 determine register usage so we will have to pop the
3843 if (options.parms_in_bank1) {
3844 for (i = 7 ; i >= 0 ; i-- ) {
3845 emitcode ("pop","%s",rb1regs[i]);
3848 unsaveRBank (0, ic, FALSE);
3853 /* This ISR uses a non-zero bank.
3855 * Restore any register banks saved by genFunction
3858 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3861 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3863 if (savedBanks & (1 << ix))
3865 unsaveRBank(ix, NULL, FALSE);
3869 if (options.useXstack)
3871 /* Restore bank AFTER calling unsaveRBank,
3872 * since it can trash r0.
3874 emitcode ("pop", "psw");
3878 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3880 if (options.stack10bit)
3882 emitcode ("pop", DP2_RESULT_REG);
3883 emitcode ("pop", "dpx1");
3884 emitcode ("pop", "dph1");
3885 emitcode ("pop", "dpl1");
3887 emitcode ("pop", "dps");
3888 emitcode ("pop", "dpx");
3890 if (!inExcludeList ("dph"))
3891 emitcode ("pop", "dph");
3892 if (!inExcludeList ("dpl"))
3893 emitcode ("pop", "dpl");
3894 if (!inExcludeList ("b"))
3895 emitcode ("pop", "b");
3896 if (!inExcludeList ("acc"))
3897 emitcode ("pop", "acc");
3899 /* if debug then send end of function */
3900 if (options.debug && currFunc)
3902 debugFile->writeEndFunction (currFunc, ic, 1);
3905 emitcode ("reti", "");
3909 if (IFFUNC_CALLEESAVES(sym->type))
3913 /* if any registers used */
3916 /* save the registers used */
3917 for (i = sym->regsUsed->size; i >= 0; i--)
3919 if (bitVectBitValue (sym->regsUsed, i))
3920 emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
3925 /* if debug then send end of function */
3926 if (options.debug && currFunc)
3928 debugFile->writeEndFunction (currFunc, ic, 1);
3931 emitcode ("ret", "");
3934 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3937 /* If this was an interrupt handler using bank 0 that called another */
3938 /* function, then all registers must be saved; nothing to optimized. */
3939 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3940 && !FUNC_REGBANK(sym->type))
3943 /* There are no push/pops to optimize if not callee-saves or ISR */
3944 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3947 /* If there were stack parameters, we cannot optimize without also */
3948 /* fixing all of the stack offsets; this is too dificult to consider. */
3949 if (FUNC_HASSTACKPARM(sym->type))
3952 /* Compute the registers actually used */
3953 regsUsed = newBitVect (ds390_nRegs);
3954 regsUsedPrologue = newBitVect (ds390_nRegs);
3957 if (lnp->ic && lnp->ic->op == FUNCTION)
3958 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3960 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3962 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3963 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3970 if (bitVectBitValue (regsUsedPrologue, DPS_IDX)
3971 && !bitVectBitValue (regsUsed, DPS_IDX))
3973 bitVectUnSetBit (regsUsedPrologue, DPS_IDX);
3976 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3977 && !bitVectBitValue (regsUsed, CND_IDX))
3979 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3980 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3981 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3982 bitVectUnSetBit (regsUsed, CND_IDX);
3985 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3987 /* If this was an interrupt handler that called another function */
3988 /* function, then assume working registers may be modified by it. */
3989 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3991 regsUsed = bitVectSetBit (regsUsed, AP_IDX);
3992 regsUsed = bitVectSetBit (regsUsed, DPX1_IDX);
3993 regsUsed = bitVectSetBit (regsUsed, DPL1_IDX);
3994 regsUsed = bitVectSetBit (regsUsed, DPH1_IDX);
3995 regsUsed = bitVectSetBit (regsUsed, DPX_IDX);
3996 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3997 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3998 regsUsed = bitVectSetBit (regsUsed, DPS_IDX);
3999 regsUsed = bitVectSetBit (regsUsed, B_IDX);
4000 regsUsed = bitVectSetBit (regsUsed, A_IDX);
4001 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
4004 /* Remove the unneeded push/pops */
4005 regsUnneeded = newBitVect (ds390_nRegs);
4008 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
4010 if (!strncmp(lnp->line, "push", 4))
4012 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
4013 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4015 connectLine (lnp->prev, lnp->next);
4016 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4019 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
4021 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
4022 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4024 connectLine (lnp->prev, lnp->next);
4025 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4032 for (idx = 0; idx < regsUnneeded->size; idx++)
4033 if (bitVectBitValue (regsUnneeded, idx))
4034 emitcode (";", "eliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
4036 freeBitVect (regsUnneeded);
4037 freeBitVect (regsUsed);
4038 freeBitVect (regsUsedPrologue);
4041 /*-----------------------------------------------------------------*/
4042 /* genJavaNativeRet - generate code for return JavaNative */
4043 /*-----------------------------------------------------------------*/
4044 static void genJavaNativeRet(iCode *ic)
4048 aopOp (IC_LEFT (ic), ic, FALSE,
4049 AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
4050 size = AOP_SIZE (IC_LEFT (ic));
4054 /* it is assigned to GPR0-R3 then push them */
4055 if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
4056 aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
4057 for (i = 0 ; i < size ; i++ ) {
4058 emitcode ("push","%s",
4059 aopGet(IC_LEFT(ic),i,FALSE,TRUE,DP2_RESULT_REG));
4061 for (i = (size-1) ; i >= 0 ; i--) {
4062 emitcode ("pop","a%s",javaRet[i]);
4065 for (i = 0 ; i < size ; i++)
4066 emitcode ("mov","%s,%s",javaRet[i],
4067 aopGet(IC_LEFT(ic),i,FALSE,TRUE,DP2_RESULT_REG));
4069 for (i = size ; i < 4 ; i++ )
4070 emitcode ("mov","%s,#0",javaRet[i]);
4074 /*-----------------------------------------------------------------*/
4075 /* genRet - generate code for return statement */
4076 /*-----------------------------------------------------------------*/
4080 int size, offset = 0, pushed = 0;
4082 D (emitcode (";", "genRet"));
4084 /* if we have no return value then
4085 just generate the "ret" */
4089 /* if this is a JavaNative function then return
4090 value in different register */
4091 if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
4092 genJavaNativeRet(ic);
4095 /* we have something to return then
4096 move the return value into place */
4097 aopOp (IC_LEFT (ic), ic, FALSE,
4098 (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
4099 size = AOP_SIZE (IC_LEFT (ic));
4101 _startLazyDPSEvaluation ();
4103 if (IS_BIT(_G.currentFunc->etype))
4105 movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4112 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
4114 l = aopGet (IC_LEFT (ic), offset++,
4116 emitcode ("push", "%s", l);
4121 /* Since A is the last element of fReturn,
4122 * it is OK to clobber it in the aopGet.
4124 l = aopGet (IC_LEFT (ic), offset,
4125 FALSE, FALSE, NULL);
4126 if (strcmp (fReturn[offset], l))
4127 emitcode ("mov", "%s,%s", fReturn[offset++], l);
4130 _endLazyDPSEvaluation ();
4135 if (strcmp (fReturn[pushed], "a"))
4136 emitcode ("pop", fReturn[pushed]);
4138 emitcode ("pop", "acc");
4140 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
4143 /* generate a jump to the return label
4144 if the next is not the return statement */
4145 if (!(ic->next && ic->next->op == LABEL &&
4146 IC_LABEL (ic->next) == returnLabel))
4148 emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
4152 /*-----------------------------------------------------------------*/
4153 /* genLabel - generates a label */
4154 /*-----------------------------------------------------------------*/
4156 genLabel (iCode * ic)
4158 /* special case never generate */
4159 if (IC_LABEL (ic) == entryLabel)
4162 D (emitcode (";", "genLabel"));
4164 emitLabel (IC_LABEL (ic));
4167 /*-----------------------------------------------------------------*/
4168 /* genGoto - generates a ljmp */
4169 /*-----------------------------------------------------------------*/
4171 genGoto (iCode * ic)
4173 D (emitcode (";", "genGoto"));
4175 emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
4178 /*-----------------------------------------------------------------*/
4179 /* findLabelBackwards: walks back through the iCode chain looking */
4180 /* for the given label. Returns number of iCode instructions */
4181 /* between that label and given ic. */
4182 /* Returns zero if label not found. */
4183 /*-----------------------------------------------------------------*/
4185 findLabelBackwards (iCode * ic, int key)
4194 /* If we have any pushes or pops, we cannot predict the distance.
4195 I don't like this at all, this should be dealt with in the
4197 if (ic->op == IPUSH || ic->op == IPOP) {
4201 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4203 /* printf("findLabelBackwards = %d\n", count); */
4211 /*-----------------------------------------------------------------*/
4212 /* genPlusIncr :- does addition with increment if possible */
4213 /*-----------------------------------------------------------------*/
4215 genPlusIncr (iCode * ic)
4217 unsigned int icount;
4218 unsigned int size = getDataSize (IC_RESULT (ic));
4220 /* will try to generate an increment */
4221 /* if the right side is not a literal
4223 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4226 /* if the literal value of the right hand side
4227 is greater than 4 then it is not worth it */
4228 if ((icount = (unsigned int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4231 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4232 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4234 emitcode("inc","%s",aopGet(IC_RESULT(ic),0,FALSE,FALSE,NULL));
4238 /* if increment 16 bits in register */
4240 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4241 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4242 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4251 /* If the next instruction is a goto and the goto target
4252 * is <= 5 instructions previous to this, we can generate
4253 * jumps straight to that target.
4255 if (ic->next && ic->next->op == GOTO
4256 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4259 D (emitcode (";", "tail increment optimized (range %d)", labelRange));
4260 tlbl = IC_LABEL (ic->next);
4265 tlbl = newiTempLabel (NULL);
4268 l = aopGet (IC_RESULT (ic), LSB, FALSE, FALSE, NULL);
4269 emitcode ("inc", "%s", l);
4271 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4272 IS_AOP_PREG (IC_RESULT (ic)))
4274 emitcode ("cjne", "%s,%s,!tlabel", l, zero, tlbl->key + 100);
4278 emitcode ("clr", "a");
4279 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4282 l = aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE, NULL);
4283 emitcode ("inc", "%s", l);
4286 if (!strcmp(l, "acc"))
4288 emitcode("jnz", "!tlabel", tlbl->key + 100);
4290 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4291 IS_AOP_PREG (IC_RESULT (ic)))
4293 emitcode ("cjne", "%s,%s,!tlabel", l, zero, tlbl->key + 100);
4297 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4300 l = aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE, NULL);
4301 emitcode ("inc", "%s", l);
4305 if (!strcmp(l, "acc"))
4307 emitcode("jnz", "!tlabel", tlbl->key + 100);
4309 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4310 IS_AOP_PREG (IC_RESULT (ic)))
4312 emitcode ("cjne", "%s,%s,!tlabel", l, zero, tlbl->key + 100);
4316 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4319 l = aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE, NULL);
4320 emitcode ("inc", "%s", l);
4330 if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
4331 !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 &&
4332 options.model == MODEL_FLAT24 )
4334 if (IC_RESULT(ic)->isGptr)
4336 emitcode ("mov", "b,%s", aopGet(IC_LEFT (ic), 3, FALSE, FALSE, NULL));
4340 emitcode ("mov", "dpx,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE, NULL));
4342 emitcode ("mov", "dph,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE, NULL));
4344 emitcode ("mov", "dpl,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4348 emitcode ("inc", "dptr");
4352 if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
4353 AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
4355 emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
4357 emitcode ("inc", "dptr");
4358 emitcode ("mov", "dps,#0");
4362 /* if the sizes are greater than 1 then we cannot */
4363 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4364 AOP_SIZE (IC_LEFT (ic)) > 1)
4367 /* we can if the aops of the left & result match or
4368 if they are in registers and the registers are the
4371 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4372 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4373 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4377 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4378 emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
4379 aopPut (IC_RESULT (ic), "a", 0);
4383 _startLazyDPSEvaluation ();
4386 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4388 _endLazyDPSEvaluation ();
4397 /*-----------------------------------------------------------------*/
4398 /* outBitAcc - output a bit in acc */
4399 /*-----------------------------------------------------------------*/
4401 outBitAcc (operand * result)
4403 symbol *tlbl = newiTempLabel (NULL);
4404 /* if the result is a bit */
4405 if (AOP_TYPE (result) == AOP_CRY)
4407 aopPut (result, "a", 0);
4411 emitcode ("jz", "!tlabel", tlbl->key + 100);
4412 emitcode ("mov", "a,%s", one);
4418 /*-----------------------------------------------------------------*/
4419 /* genPlusBits - generates code for addition of two bits */
4420 /*-----------------------------------------------------------------*/
4422 genPlusBits (iCode * ic)
4424 D (emitcode (";", "genPlusBits"));
4426 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4428 symbol *lbl = newiTempLabel (NULL);
4429 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4430 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4431 emitcode ("cpl", "c");
4433 outBitC (IC_RESULT (ic));
4437 emitcode ("clr", "a");
4438 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4439 emitcode ("rlc", "a");
4440 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4441 emitcode ("addc", "a,%s", zero);
4442 outAcc (IC_RESULT (ic));
4447 adjustArithmeticResult (iCode * ic)
4449 if (opIsGptr (IC_RESULT (ic)) &&
4450 opIsGptr (IC_LEFT (ic)) &&
4451 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4453 aopPut (IC_RESULT (ic),
4454 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE, NULL),
4458 if (opIsGptr (IC_RESULT (ic)) &&
4459 opIsGptr (IC_RIGHT (ic)) &&
4460 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4462 aopPut (IC_RESULT (ic),
4463 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE, NULL),
4467 if (opIsGptr (IC_RESULT (ic)) &&
4468 IC_LEFT (ic) && AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4469 IC_RIGHT (ic) && AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4470 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4471 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4474 SNPRINTF (buffer, sizeof(buffer),
4475 "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4476 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4480 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
4481 // generates the result if possible. If result is generated, returns TRUE; otherwise
4482 // returns false and caller must deal with fact that result isn't aopOp'd.
4483 bool aopOp3(iCode * ic)
4485 bool dp1InUse, dp2InUse;
4488 // First, generate the right opcode. DPTR may be used if neither left nor result are
4491 // D (emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
4492 // AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
4493 // AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
4494 // AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
4496 // D (emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
4497 // AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
4498 // AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
4499 // AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
4502 // Right uses DPTR unless left or result is an AOP_STR; however,
4503 // if right is an AOP_STR, it must use DPTR regardless.
4504 if ((AOP_IS_STR (IC_LEFT (ic)) || AOP_IS_STR (IC_RESULT (ic)))
4505 && !AOP_IS_STR (IC_RIGHT (ic)))
4514 aopOp (IC_RIGHT(ic), ic, FALSE, useDp2);
4516 // if the right used DPTR, left MUST use DPTR2.
4517 // if the right used DPTR2, left MUST use DPTR.
4518 // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
4519 // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
4520 // enabling us to assign DPTR to result.
4522 if (AOP_USESDPTR (IC_RIGHT (ic)))
4526 else if (AOP_USESDPTR2 (IC_RIGHT (ic)))
4532 if (AOP_IS_STR (IC_RESULT (ic)) && !AOP_IS_STR (IC_LEFT (ic)))
4542 aopOp (IC_LEFT (ic), ic, FALSE, useDp2);
4545 // We've op'd the left & right. So, if left or right are the same operand as result,
4546 // we know aopOp will succeed, and we can just do it & bail.
4547 if (isOperandEqual (IC_LEFT (ic), IC_RESULT (ic)))
4549 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4552 if (isOperandEqual (IC_RIGHT (ic), IC_RESULT (ic)))
4554 // D (emitcode(";", "aopOp3: (left | right) & result equal"));
4555 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4559 // Operands may be equivalent (but not equal) if they share a spill location. If
4560 // so, use the same DPTR or DPTR2.
4561 if (operandsEqu (IC_LEFT (ic), IC_RESULT (ic)))
4563 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4566 if (operandsEqu (IC_RIGHT (ic), IC_RESULT (ic)))
4568 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4572 // Note which dptrs are currently in use.
4573 dp1InUse = AOP_USESDPTR (IC_LEFT (ic)) || AOP_USESDPTR (IC_RIGHT (ic));
4574 dp2InUse = AOP_USESDPTR2 (IC_LEFT (ic)) || AOP_USESDPTR2 (IC_RIGHT (ic));
4576 // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot
4578 if (dp1InUse && AOP_IS_STR (IC_RESULT (ic)))
4583 // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
4584 if (dp2InUse && AOP_IS_DPTRn (IC_RESULT (ic)))
4589 // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck
4590 if (dp1InUse && dp2InUse && isOperandInFarSpace (IC_RESULT (ic)))
4595 aopOp (IC_RESULT (ic), ic, TRUE, dp1InUse);
4597 // Some sanity checking...
4598 if (dp1InUse && AOP_USESDPTR (IC_RESULT (ic)))
4601 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
4602 __FILE__, __LINE__, ic->filename, ic->lineno);
4603 emitcode(";", ">>> unexpected DPTR here.");
4606 if (dp2InUse && AOP_USESDPTR2 (IC_RESULT (ic)))
4609 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
4610 __FILE__, __LINE__, ic->filename, ic->lineno);
4611 emitcode(";", ">>> unexpected DPTR2 here.");
4617 // Macro to aopOp all three operands of an ic. If this cannot be done,
4618 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
4619 // will be set TRUE. The caller must then handle the case specially, noting
4620 // that the IC_RESULT operand is not aopOp'd.
4622 #define AOP_OP_3_NOFATAL(ic, rc) \
4623 do { rc = !aopOp3(ic); } while (0)
4625 // aopOp the left & right operands of an ic.
4626 #define AOP_OP_2(ic) \
4627 aopOp (IC_RIGHT (ic), ic, FALSE, AOP_IS_STR (IC_LEFT (ic))); \
4628 aopOp (IC_LEFT (ic), ic, FALSE, AOP_USESDPTR (IC_RIGHT (ic)));
4630 // convienience macro.
4631 #define AOP_SET_LOCALS(ic) \
4632 left = IC_LEFT(ic); \
4633 right = IC_RIGHT(ic); \
4634 result = IC_RESULT(ic);
4637 // Given an integer value of pushedSize bytes on the stack,
4638 // adjust it to be resultSize bytes, either by discarding
4639 // the most significant bytes or by zero-padding.
4641 // On exit from this macro, pushedSize will have been adjusted to
4642 // equal resultSize, and ACC may be trashed.
4643 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
4644 /* If the pushed data is bigger than the result, \
4645 * simply discard unused bytes. Icky, but works. \
4647 while (pushedSize > resultSize) \
4649 D (emitcode (";", "discarding unused result byte.")); \
4650 emitcode ("pop", "acc"); \
4653 if (pushedSize < resultSize) \
4655 emitcode ("clr", "a"); \
4656 /* Conversly, we haven't pushed enough here. \
4657 * just zero-pad, and all is well. \
4659 while (pushedSize < resultSize) \
4661 emitcode("push", "acc"); \
4665 assert(pushedSize == resultSize);
4667 /*-----------------------------------------------------------------*/
4668 /* genPlus - generates code for addition */
4669 /*-----------------------------------------------------------------*/
4671 genPlus (iCode * ic)
4673 int size, offset = 0;
4676 bool swappedLR = FALSE;
4678 D (emitcode (";", "genPlus"));
4680 /* special cases :- */
4681 if ( AOP_IS_STR (IC_LEFT (ic)) &&
4682 isOperandLiteral (IC_RIGHT (ic)) && OP_SYMBOL (IC_RESULT (ic))->ruonly) {
4683 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
4684 size = (int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4686 while (size--) emitcode ("inc","dptr");
4688 emitcode ("mov", "a,dpl");
4689 emitcode ("add", "a,#!constbyte", size & 0xff);
4690 emitcode ("mov", "dpl,a");
4691 emitcode ("mov", "a,dph");
4692 emitcode ("addc", "a,#!constbyte", (size >> 8) & 0xff);
4693 emitcode ("mov", "dph,a");
4694 emitcode ("mov", "a,dpx");
4695 emitcode ("addc", "a,#!constbyte", (size >> 16) & 0xff);
4696 emitcode ("mov", "dpx,a");
4698 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4701 if ( IS_SYMOP (IC_LEFT (ic)) &&
4702 OP_SYMBOL (IC_LEFT (ic))->remat &&
4703 isOperandInFarSpace (IC_RIGHT (ic))) {
4704 operand *op = IC_RIGHT(ic);
4705 IC_RIGHT(ic) = IC_LEFT(ic);
4709 AOP_OP_3_NOFATAL (ic, pushResult);
4713 D (emitcode (";", "genPlus: must push result: 3 ops in far space"));
4718 /* if literal, literal on the right or
4719 if left requires ACC or right is already
4721 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4722 ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic)))) ||
4723 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4725 operand *t = IC_RIGHT (ic);
4726 IC_RIGHT (ic) = IC_LEFT (ic);
4729 D (emitcode (";", "Swapped plus args."));
4732 /* if both left & right are in bit
4734 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4735 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4741 /* if left in bit space & right literal */
4742 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4743 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4745 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4746 /* if result in bit space */
4747 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4749 if (ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4750 emitcode ("cpl", "c");
4751 outBitC (IC_RESULT (ic));
4755 size = getDataSize (IC_RESULT (ic));
4756 _startLazyDPSEvaluation ();
4759 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4760 emitcode ("addc", "a,%s", zero);
4761 aopPut (IC_RESULT (ic), "a", offset++);
4763 _endLazyDPSEvaluation ();
4768 /* if I can do an increment instead
4769 of add then GOOD for ME */
4770 if (genPlusIncr (ic) == TRUE)
4772 D (emitcode (";", "did genPlusIncr"));
4777 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4779 _startLazyDPSEvaluation ();
4782 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4784 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
4786 emitcode ("add", "a,%s",
4787 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4789 emitcode ("addc", "a,%s",
4790 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4794 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4796 /* right is going to use ACC or we would have taken the
4799 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4801 D(emitcode(";", "+ AOP_ACC special case."););
4802 emitcode("xch", "a, %s", DP2_RESULT_REG);
4804 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4807 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4810 emitcode("add", "a, %s", DP2_RESULT_REG);
4814 emitcode ("add", "a,%s",
4815 aopGet (IC_LEFT(ic), offset, FALSE, FALSE,
4821 emitcode ("addc", "a,%s",
4822 aopGet (IC_LEFT (ic), offset, FALSE, FALSE,
4828 aopPut (IC_RESULT (ic), "a", offset);
4832 emitcode ("push", "acc");
4836 _endLazyDPSEvaluation ();
4840 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4842 size = getDataSize (IC_LEFT (ic));
4843 rSize = getDataSize (IC_RESULT (ic));
4845 ADJUST_PUSHED_RESULT(size, rSize);
4847 _startLazyDPSEvaluation ();
4850 emitcode ("pop", "acc");
4851 aopPut (IC_RESULT (ic), "a", size);
4853 _endLazyDPSEvaluation ();
4856 adjustArithmeticResult (ic);
4859 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4862 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4863 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4867 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4868 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4872 /*-----------------------------------------------------------------*/
4873 /* genMinusDec :- does subtraction with decrement if possible */
4874 /*-----------------------------------------------------------------*/
4876 genMinusDec (iCode * ic)
4878 unsigned int icount;
4879 unsigned int size = getDataSize (IC_RESULT (ic));
4881 /* will try to generate an increment */
4882 /* if the right side is not a literal
4884 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4887 /* if the literal value of the right hand side
4888 is greater than 4 then it is not worth it */
4889 if ((icount = (unsigned int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4892 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4893 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4895 emitcode("dec","%s",aopGet(IC_RESULT(ic),0,FALSE,FALSE,NULL));
4899 /* if decrement 16 bits in register */
4900 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4901 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4902 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4911 /* If the next instruction is a goto and the goto target
4912 * is <= 5 instructions previous to this, we can generate
4913 * jumps straight to that target.
4915 if (ic->next && ic->next->op == GOTO
4916 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4919 D (emitcode (";", "tail decrement optimized (range %d)", labelRange));
4920 tlbl = IC_LABEL (ic->next);
4925 tlbl = newiTempLabel (NULL);
4929 l = aopGet (IC_RESULT (ic), LSB, FALSE, FALSE, NULL);
4930 emitcode ("dec", "%s", l);
4932 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4933 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4934 IS_AOP_PREG (IC_RESULT (ic)))
4936 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4940 emitcode ("mov", "a,#!constbyte",0xff);
4941 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4943 l = aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE, NULL);
4944 emitcode ("dec", "%s", l);
4947 if (!strcmp(l, "acc"))
4949 emitcode("jnz", "!tlabel", tlbl->key + 100);
4951 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4952 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4953 IS_AOP_PREG (IC_RESULT (ic)))
4955 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4959 emitcode ("mov", "a,#!constbyte",0xff);
4960 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4962 l = aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE, NULL);
4963 emitcode ("dec", "%s", l);
4967 if (!strcmp(l, "acc"))
4969 emitcode("jnz", "!tlabel", tlbl->key + 100);
4971 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4972 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4973 IS_AOP_PREG (IC_RESULT (ic)))
4975 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4979 emitcode ("mov", "a,#!constbyte",0xff);
4980 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4982 l = aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE, NULL);
4983 emitcode ("dec", "%s", l);
4992 /* if the sizes are greater than 1 then we cannot */
4993 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4994 AOP_SIZE (IC_LEFT (ic)) > 1)
4997 /* we can if the aops of the left & result match or
4998 if they are in registers and the registers are the
5001 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
5002 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
5003 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
5007 if (aopGetUsesAcc (IC_LEFT (ic), 0))
5009 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL));
5014 l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL);
5017 _startLazyDPSEvaluation ();
5020 emitcode ("dec", "%s", l);
5022 _endLazyDPSEvaluation ();
5024 if (AOP_NEEDSACC (IC_RESULT (ic)))
5025 aopPut (IC_RESULT (ic), "a", 0);
5033 /*-----------------------------------------------------------------*/
5034 /* addSign - complete with sign */
5035 /*-----------------------------------------------------------------*/
5037 addSign (operand * result, int offset, int sign)
5039 int size = (getDataSize (result) - offset);
5042 _startLazyDPSEvaluation();
5045 emitcode ("rlc", "a");
5046 emitcode ("subb", "a,acc");
5049 aopPut (result, "a", offset++);
5056 aopPut (result, zero, offset++);
5059 _endLazyDPSEvaluation();
5063 /*-----------------------------------------------------------------*/
5064 /* genMinusBits - generates code for subtraction of two bits */
5065 /*-----------------------------------------------------------------*/
5067 genMinusBits (iCode * ic)
5069 symbol *lbl = newiTempLabel (NULL);
5071 D (emitcode (";", "genMinusBits"));
5073 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
5075 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
5076 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
5077 emitcode ("cpl", "c");
5079 outBitC (IC_RESULT (ic));
5083 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
5084 emitcode ("subb", "a,acc");
5085 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
5086 emitcode ("inc", "a");
5088 aopPut (IC_RESULT (ic), "a", 0);
5089 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
5093 /*-----------------------------------------------------------------*/
5094 /* genMinus - generates code for subtraction */
5095 /*-----------------------------------------------------------------*/
5097 genMinus (iCode * ic)
5099 int size, offset = 0;
5104 D (emitcode (";", "genMinus"));
5106 AOP_OP_3_NOFATAL(ic, pushResult);
5110 /* special cases :- */
5111 /* if both left & right are in bit space */
5112 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
5113 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
5119 /* if I can do an decrement instead
5120 of subtract then GOOD for ME */
5121 if (genMinusDec (ic) == TRUE)
5126 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
5128 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
5134 lit = (long) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5139 /* if literal, add a,#-lit, else normal subb */
5140 _startLazyDPSEvaluation ();
5142 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
5143 if (AOP_USESDPTR(IC_RIGHT(ic))) {
5144 emitcode ("mov","b,%s",
5145 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
5146 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
5147 emitcode ("subb","a,b");
5149 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
5150 emitcode ("subb", "a,%s",
5151 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE,
5155 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
5156 /* first add without previous c */
5158 if (!size && lit==-1) {
5159 emitcode ("dec", "a");
5161 emitcode ("add", "a,#!constbyte",
5162 (unsigned int) (lit & 0x0FFL));
5165 emitcode ("addc", "a,#!constbyte",
5166 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5171 emitcode ("push", "acc");
5173 aopPut (IC_RESULT (ic), "a", offset);
5177 _endLazyDPSEvaluation ();
5181 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
5183 size = getDataSize (IC_LEFT (ic));
5184 rSize = getDataSize (IC_RESULT (ic));
5186 ADJUST_PUSHED_RESULT(size, rSize);
5188 _startLazyDPSEvaluation ();
5191 emitcode ("pop", "acc");
5192 aopPut (IC_RESULT (ic), "a", size);
5194 _endLazyDPSEvaluation ();
5197 adjustArithmeticResult (ic);
5200 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5201 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5202 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5206 /*-----------------------------------------------------------------*/
5207 /* genMultbits :- multiplication of bits */
5208 /*-----------------------------------------------------------------*/
5210 genMultbits (operand * left,
5215 D (emitcode (";", "genMultbits"));
5217 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5218 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5219 aopOp(result, ic, TRUE, FALSE);
5223 /*-----------------------------------------------------------------*/
5224 /* genMultOneByte : 8*8=8/16 bit multiplication */
5225 /*-----------------------------------------------------------------*/
5227 genMultOneByte (operand * left,
5234 bool runtimeSign, compiletimeSign;
5235 bool lUnsigned, rUnsigned, pushedB;
5237 /* (if two literals: the value is computed before) */
5238 /* if one literal, literal on the right */
5239 if (AOP_TYPE (left) == AOP_LIT)
5244 /* emitcode (";", "swapped left and right"); */
5246 /* if no literal, unsigned on the right: shorter code */
5247 if ( AOP_TYPE (right) != AOP_LIT
5248 && SPEC_USIGN (getSpec (operandType (left))))
5255 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5256 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5260 if ((lUnsigned && rUnsigned)
5261 /* sorry, I don't know how to get size
5262 without calling aopOp (result,...);
5263 see Feature Request */
5264 /* || size == 1 */ ) /* no, this is not a bug; with a 1 byte result there's
5265 no need to take care about the signedness! */
5267 /* just an unsigned 8 * 8 = 8 multiply
5269 /* emitcode (";","unsigned"); */
5270 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
5271 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
5272 emitcode ("mul", "ab");
5275 aopOp (result, ic, TRUE, FALSE);
5276 size = AOP_SIZE (result);
5278 if (size < 1 || size > 2)
5280 /* this should never happen */
5281 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
5282 size, __FILE__, lineno);
5286 aopPut (result, "a", 0);
5289 aopPut (result, "b", 1);
5295 /* we have to do a signed multiply */
5296 /* emitcode (";", "signed"); */
5298 /* now sign adjust for both left & right */
5300 /* let's see what's needed: */
5301 /* apply negative sign during runtime */
5302 runtimeSign = FALSE;
5303 /* negative sign from literals */
5304 compiletimeSign = FALSE;
5308 if (AOP_TYPE(left) == AOP_LIT)
5310 /* signed literal */
5311 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5313 compiletimeSign = TRUE;
5316 /* signed but not literal */
5322 if (AOP_TYPE(right) == AOP_LIT)
5324 /* signed literal */
5325 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
5327 compiletimeSign ^= TRUE;
5330 /* signed but not literal */
5334 /* initialize F0, which stores the runtime sign */
5337 if (compiletimeSign)
5338 emitcode ("setb", "F0"); /* set sign flag */
5340 emitcode ("clr", "F0"); /* reset sign flag */
5343 /* save the signs of the operands */
5344 if (AOP_TYPE(right) == AOP_LIT)
5346 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
5348 if (!rUnsigned && val < 0)
5349 emitcode ("mov", "b,#!constbyte", -val);
5351 emitcode ("mov", "b,#!constbyte", (unsigned char) val);
5353 else /* ! literal */
5355 if (rUnsigned) /* emitcode (";", "signed"); */
5356 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
5359 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
5360 lbl = newiTempLabel (NULL);
5361 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5362 emitcode ("cpl", "F0"); /* complement sign flag */
5363 emitcode ("cpl", "a"); /* 2's complement */
5364 emitcode ("inc", "a");
5366 emitcode ("mov", "b,a");
5370 if (AOP_TYPE(left) == AOP_LIT)
5372 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5374 if (!lUnsigned && val < 0)
5375 emitcode ("mov", "a,#!constbyte", -val);
5377 emitcode ("mov", "a,#!constbyte", (unsigned char) val);
5379 else /* ! literal */
5381 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
5383 if (!lUnsigned) /* emitcode (";", "signed"); */
5385 lbl = newiTempLabel (NULL);
5386 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5387 emitcode ("cpl", "F0"); /* complement sign flag */
5388 emitcode ("cpl", "a"); /* 2's complement */
5389 emitcode ("inc", "a");
5394 /* now the multiplication */
5395 emitcode ("mul", "ab");
5397 aopOp(result, ic, TRUE, FALSE);
5398 size = AOP_SIZE (result);
5400 if (size < 1 || size > 2)
5402 /* this should never happen */
5403 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
5404 size, __FILE__, lineno);
5408 if (runtimeSign || compiletimeSign)
5410 lbl = newiTempLabel (NULL);
5412 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5413 emitcode ("cpl", "a"); /* lsb 2's complement */
5415 emitcode ("inc", "a"); /* inc doesn't set carry flag */
5418 emitcode ("add", "a,#1"); /* this sets carry flag */
5419 emitcode ("xch", "a,b");
5420 emitcode ("cpl", "a"); /* msb 2's complement */
5421 emitcode ("addc", "a,#0");
5422 emitcode ("xch", "a,b");
5426 aopPut (result, "a", 0);
5429 aopPut (result, "b", 1);
5434 /*-----------------------------------------------------------------*/
5435 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
5436 /*-----------------------------------------------------------------*/
5437 static void genMultTwoByte (operand *left, operand *right,
5438 operand *result, iCode *ic)
5440 sym_link *retype = getSpec(operandType(right));
5441 sym_link *letype = getSpec(operandType(left));
5442 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5445 if (AOP_TYPE (left) == AOP_LIT) {
5450 /* save EA bit in F1 */
5451 lbl = newiTempLabel(NULL);
5452 emitcode ("setb","F1");
5453 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5454 emitcode ("clr","F1");
5457 /* load up MB with right */
5459 emitcode("clr","F0");
5460 if (AOP_TYPE(right) == AOP_LIT) {
5461 int val=(int) ulFromVal (AOP (right)->aopu.aop_lit);
5463 emitcode("setb","F0");
5466 emitcode ("mov","mb,#!constbyte",val & 0xff);
5467 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5469 lbl = newiTempLabel(NULL);
5470 emitcode ("mov","b,%s",aopGet(right,0,FALSE,FALSE,NULL));
5471 emitcode ("mov","a,%s",aopGet(right,1,FALSE,FALSE,NULL));
5472 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5473 emitcode ("xch", "a,b");
5474 emitcode ("cpl","a");
5475 emitcode ("add", "a,#1");
5476 emitcode ("xch", "a,b");
5477 emitcode ("cpl", "a"); // msb
5478 emitcode ("addc", "a,#0");
5479 emitcode ("setb","F0");
5481 emitcode ("mov","mb,b");
5482 emitcode ("mov","mb,a");
5485 emitcode ("mov","mb,%s",aopGet(right,0,FALSE,FALSE,NULL));
5486 emitcode ("mov","mb,%s",aopGet(right,1,FALSE,FALSE,NULL));
5488 /* load up MA with left */
5490 lbl = newiTempLabel(NULL);
5491 emitcode ("mov","b,%s",aopGet(left,0,FALSE,FALSE,NULL));
5492 emitcode ("mov","a,%s",aopGet(left,1,FALSE,FALSE,NULL));
5493 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5494 emitcode ("xch", "a,b");
5495 emitcode ("cpl","a");
5496 emitcode ("add", "a,#1");
5497 emitcode ("xch", "a,b");
5498 emitcode ("cpl", "a"); // msb
5499 emitcode ("addc","a,#0");
5500 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5501 emitcode ("setb","F0");
5503 emitcode ("mov","ma,b");
5504 emitcode ("mov","ma,a");
5506 emitcode ("mov","ma,%s",aopGet(left,0,FALSE,FALSE,NULL));
5507 emitcode ("mov","ma,%s",aopGet(left,1,FALSE,FALSE,NULL));
5509 /* wait for multiplication to finish */
5510 lbl = newiTempLabel(NULL);
5512 emitcode("mov","a,mcnt1");
5513 emitcode("anl","a,#!constbyte",0x80);
5514 emitcode("jnz","!tlabel",lbl->key+100);
5516 freeAsmop (left, NULL, ic, TRUE);
5517 freeAsmop (right, NULL, ic,TRUE);
5518 aopOp(result, ic, TRUE, FALSE);
5520 /* if unsigned then simple */
5522 emitcode ("mov","a,ma");
5523 if (AOP_SIZE(result) >= 4) aopPut(result,"a",3);
5524 emitcode ("mov","a,ma");
5525 if (AOP_SIZE(result) >= 3) aopPut(result,"a",2);
5526 aopPut(result,"ma",1);
5527 aopPut(result,"ma",0);
5529 emitcode("push","ma");
5530 emitcode("push","ma");
5531 emitcode("push","ma");
5533 /* negate result if needed */
5534 lbl = newiTempLabel(NULL);
5535 emitcode("jnb","F0,!tlabel",lbl->key+100);
5536 emitcode("cpl","a");
5537 emitcode("add","a,#1");
5539 if (AOP_TYPE(result) == AOP_ACC)
5541 D (emitcode(";", "ACC special case."));
5542 /* We know result is the only live aop, and
5543 * it's obviously not a DPTR2, so AP is available.
5545 emitcode("mov", "%s,acc", DP2_RESULT_REG);
5549 aopPut(result,"a",0);
5552 emitcode("pop","acc");
5553 lbl = newiTempLabel(NULL);
5554 emitcode("jnb","F0,!tlabel",lbl->key+100);
5555 emitcode("cpl","a");
5556 emitcode("addc","a,#0");
5558 aopPut(result,"a",1);
5559 emitcode("pop","acc");
5560 if (AOP_SIZE(result) >= 3) {
5561 lbl = newiTempLabel(NULL);
5562 emitcode("jnb","F0,!tlabel",lbl->key+100);
5563 emitcode("cpl","a");
5564 emitcode("addc","a,#0");
5566 aopPut(result,"a",2);
5568 emitcode("pop","acc");
5569 if (AOP_SIZE(result) >= 4) {
5570 lbl = newiTempLabel(NULL);
5571 emitcode("jnb","F0,!tlabel",lbl->key+100);
5572 emitcode("cpl","a");
5573 emitcode("addc","a,#0");
5575 aopPut(result,"a",3);
5577 if (AOP_TYPE(result) == AOP_ACC)
5579 /* We stashed the result away above. */
5580 emitcode("mov", "acc,%s", DP2_RESULT_REG);
5584 freeAsmop (result, NULL, ic, TRUE);
5586 /* restore EA bit in F1 */
5587 lbl = newiTempLabel(NULL);
5588 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5589 emitcode ("setb","EA");
5594 /*-----------------------------------------------------------------*/
5595 /* genMult - generates code for multiplication */
5596 /*-----------------------------------------------------------------*/
5598 genMult (iCode * ic)
5600 operand *left = IC_LEFT (ic);
5601 operand *right = IC_RIGHT (ic);
5602 operand *result = IC_RESULT (ic);
5604 D (emitcode (";", "genMult"));
5606 /* assign the asmops */
5609 /* special cases first */
5611 if (AOP_TYPE (left) == AOP_CRY &&
5612 AOP_TYPE (right) == AOP_CRY)
5614 genMultbits (left, right, result, ic);
5618 /* if both are of size == 1 */
5619 if (AOP_SIZE (left) == 1 &&
5620 AOP_SIZE (right) == 1)
5622 genMultOneByte (left, right, result, ic);
5626 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5627 /* use the ds390 ARITHMETIC accel UNIT */
5628 genMultTwoByte (left, right, result, ic);
5631 /* should have been converted to function call */
5635 freeAsmop (result, NULL, ic, TRUE);
5636 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5637 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5640 /*-----------------------------------------------------------------*/
5641 /* genDivbits :- division of bits */
5642 /*-----------------------------------------------------------------*/
5644 genDivbits (operand * left,
5652 D(emitcode (";", "genDivbits"));
5656 /* the result must be bit */
5657 LOAD_AB_FOR_DIV (left, right, l);
5658 emitcode ("div", "ab");
5659 emitcode ("rrc", "a");
5660 aopOp(result, ic, TRUE, FALSE);
5664 aopPut (result, "c", 0);
5667 /*-----------------------------------------------------------------*/
5668 /* genDivOneByte : 8 bit division */
5669 /*-----------------------------------------------------------------*/
5671 genDivOneByte (operand * left,
5676 bool lUnsigned, rUnsigned, pushedB;
5677 bool runtimeSign, compiletimeSign;
5682 D(emitcode (";", "genDivOneByte"));
5685 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5686 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5690 /* signed or unsigned */
5691 if (lUnsigned && rUnsigned)
5693 /* unsigned is easy */
5694 LOAD_AB_FOR_DIV (left, right, l);
5695 emitcode ("div", "ab");
5698 aopOp (result, ic, TRUE, FALSE);
5699 aopPut (result, "a", 0);
5702 size = AOP_SIZE (result) - 1;
5705 aopPut (result, zero, offset++);
5711 /* signed is a little bit more difficult */
5713 /* now sign adjust for both left & right */
5715 /* let's see what's needed: */
5716 /* apply negative sign during runtime */
5717 runtimeSign = FALSE;
5718 /* negative sign from literals */
5719 compiletimeSign = FALSE;
5723 if (AOP_TYPE(left) == AOP_LIT)
5725 /* signed literal */
5726 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5728 compiletimeSign = TRUE;
5731 /* signed but not literal */
5737 if (AOP_TYPE(right) == AOP_LIT)
5739 /* signed literal */
5740 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
5742 compiletimeSign ^= TRUE;
5745 /* signed but not literal */
5749 /* initialize F0, which stores the runtime sign */
5752 if (compiletimeSign)
5753 emitcode ("setb", "F0"); /* set sign flag */
5755 emitcode ("clr", "F0"); /* reset sign flag */
5758 /* save the signs of the operands */
5759 if (AOP_TYPE(right) == AOP_LIT)
5761 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
5763 if (!rUnsigned && val < 0)
5764 emitcode ("mov", "b,#0x%02x", -val);
5766 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5768 else /* ! literal */
5771 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
5774 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
5775 lbl = newiTempLabel (NULL);
5776 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5777 emitcode ("cpl", "F0"); /* complement sign flag */
5778 emitcode ("cpl", "a"); /* 2's complement */
5779 emitcode ("inc", "a");
5781 emitcode ("mov", "b,a");
5785 if (AOP_TYPE(left) == AOP_LIT)
5787 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5789 if (!lUnsigned && val < 0)
5790 emitcode ("mov", "a,#0x%02x", -val);
5792 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5794 else /* ! literal */
5796 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
5800 lbl = newiTempLabel (NULL);
5801 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5802 emitcode ("cpl", "F0"); /* complement sign flag */
5803 emitcode ("cpl", "a"); /* 2's complement */
5804 emitcode ("inc", "a");
5809 /* now the division */
5810 emitcode ("nop", "; workaround for DS80C390 div bug.");
5811 emitcode ("div", "ab");
5813 if (runtimeSign || compiletimeSign)
5815 lbl = newiTempLabel (NULL);
5817 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5818 emitcode ("cpl", "a"); /* lsb 2's complement */
5819 emitcode ("inc", "a");
5823 aopOp (result, ic, TRUE, FALSE);
5824 size = AOP_SIZE (result) - 1;
5828 /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
5829 then the result will be in b, a */
5830 emitcode ("mov", "b,a"); /* 1 */
5831 /* msb is 0x00 or 0xff depending on the sign */
5834 emitcode ("mov", "c,F0");
5835 emitcode ("subb", "a,acc");
5836 emitcode ("xch", "a,b"); /* 2 */
5838 aopPut (result, "b", offset++); /* write msb's */
5840 else /* compiletimeSign */
5842 aopPut (result, "#0xff", offset++); /* write msb's */
5844 aopPut (result, "a", 0); /* 3: write lsb */
5849 aopOp(result, ic, TRUE, FALSE);
5850 size = AOP_SIZE (result) - 1;
5852 aopPut (result, "a", 0);
5854 aopPut (result, zero, offset++);
5860 /*-----------------------------------------------------------------*/
5861 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
5862 /*-----------------------------------------------------------------*/
5863 static void genDivTwoByte (operand *left, operand *right,
5864 operand *result, iCode *ic)
5866 sym_link *retype = getSpec(operandType(right));
5867 sym_link *letype = getSpec(operandType(left));
5868 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5871 /* save EA bit in F1 */
5872 lbl = newiTempLabel(NULL);
5873 emitcode ("setb","F1");
5874 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5875 emitcode ("clr","F1");
5878 /* load up MA with left */
5880 emitcode("clr","F0");
5881 lbl = newiTempLabel(NULL);
5882 emitcode ("mov","b,%s",aopGet(left,0,FALSE,FALSE,NULL));
5883 emitcode ("mov","a,%s",aopGet(left,1,FALSE,FALSE,NULL));
5884 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5885 emitcode ("xch", "a,b");
5886 emitcode ("cpl","a");
5887 emitcode ("add", "a,#1");
5888 emitcode ("xch", "a,b");
5889 emitcode ("cpl", "a"); // msb
5890 emitcode ("addc","a,#0");
5891 emitcode ("setb","F0");
5893 emitcode ("mov","ma,b");
5894 emitcode ("mov","ma,a");
5896 emitcode ("mov","ma,%s",aopGet(left,0,FALSE,FALSE,NULL));
5897 emitcode ("mov","ma,%s",aopGet(left,1,FALSE,FALSE,NULL));
5900 /* load up MB with right */
5902 if (AOP_TYPE(right) == AOP_LIT) {
5903 int val=(int) ulFromVal (AOP (right)->aopu.aop_lit);
5905 lbl = newiTempLabel(NULL);
5906 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5907 emitcode("setb","F0");
5911 emitcode ("mov","mb,#!constbyte",val & 0xff);
5912 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5914 lbl = newiTempLabel(NULL);
5915 emitcode ("mov","b,%s",aopGet(right,0,FALSE,FALSE,NULL));
5916 emitcode ("mov","a,%s",aopGet(right,1,FALSE,FALSE,NULL));
5917 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5918 emitcode ("xch", "a,b");
5919 emitcode ("cpl","a");
5920 emitcode ("add", "a,#1");
5921 emitcode ("xch", "a,b");
5922 emitcode ("cpl", "a"); // msb
5923 emitcode ("addc", "a,#0");
5924 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5925 emitcode ("setb","F0");
5927 emitcode ("mov","mb,b");
5928 emitcode ("mov","mb,a");
5931 emitcode ("mov","mb,%s",aopGet(right,0,FALSE,FALSE,NULL));
5932 emitcode ("mov","mb,%s",aopGet(right,1,FALSE,FALSE,NULL));
5935 /* wait for multiplication to finish */
5936 lbl = newiTempLabel(NULL);
5938 emitcode("mov","a,mcnt1");
5939 emitcode("anl","a,#!constbyte",0x80);
5940 emitcode("jnz","!tlabel",lbl->key+100);
5942 freeAsmop (left, NULL, ic, TRUE);
5943 freeAsmop (right, NULL, ic,TRUE);
5944 aopOp(result, ic, TRUE, FALSE);
5946 /* if unsigned then simple */
5948 aopPut(result,"ma",1);
5949 aopPut(result,"ma",0);
5951 emitcode("push","ma");
5953 /* negate result if needed */
5954 lbl = newiTempLabel(NULL);
5955 emitcode("jnb","F0,!tlabel",lbl->key+100);
5956 emitcode("cpl","a");
5957 emitcode("add","a,#1");
5959 aopPut(result,"a",0);
5960 emitcode("pop","acc");
5961 lbl = newiTempLabel(NULL);
5962 emitcode("jnb","F0,!tlabel",lbl->key+100);
5963 emitcode("cpl","a");
5964 emitcode("addc","a,#0");
5966 aopPut(result,"a",1);
5968 freeAsmop (result, NULL, ic, TRUE);
5969 /* restore EA bit in F1 */
5970 lbl = newiTempLabel(NULL);
5971 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5972 emitcode ("setb","EA");
5977 /*-----------------------------------------------------------------*/
5978 /* genDiv - generates code for division */
5979 /*-----------------------------------------------------------------*/
5983 operand *left = IC_LEFT (ic);
5984 operand *right = IC_RIGHT (ic);
5985 operand *result = IC_RESULT (ic);
5987 D (emitcode (";", "genDiv"));
5989 /* assign the amsops */
5992 /* special cases first */
5994 if (AOP_TYPE (left) == AOP_CRY &&
5995 AOP_TYPE (right) == AOP_CRY)
5997 genDivbits (left, right, result, ic);
6001 /* if both are of size == 1 */
6002 if (AOP_SIZE (left) == 1 &&
6003 AOP_SIZE (right) == 1)
6005 genDivOneByte (left, right, result, ic);
6009 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
6010 /* use the ds390 ARITHMETIC accel UNIT */
6011 genDivTwoByte (left, right, result, ic);
6014 /* should have been converted to function call */
6017 freeAsmop (result, NULL, ic, TRUE);
6018 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6019 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6022 /*-----------------------------------------------------------------*/
6023 /* genModbits :- modulus of bits */
6024 /*-----------------------------------------------------------------*/
6026 genModbits (operand * left,
6034 D (emitcode (";", "genModbits"));
6038 /* the result must be bit */
6039 LOAD_AB_FOR_DIV (left, right, l);
6040 emitcode ("div", "ab");
6041 emitcode ("mov", "a,b");
6042 emitcode ("rrc", "a");
6043 aopOp(result, ic, TRUE, FALSE);
6047 aopPut (result, "c", 0);
6050 /*-----------------------------------------------------------------*/
6051 /* genModOneByte : 8 bit modulus */
6052 /*-----------------------------------------------------------------*/
6054 genModOneByte (operand * left,
6059 bool lUnsigned, rUnsigned, pushedB;
6060 bool runtimeSign, compiletimeSign;
6065 D (emitcode (";", "genModOneByte"));
6068 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
6069 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
6073 /* signed or unsigned */
6074 if (lUnsigned && rUnsigned)
6076 /* unsigned is easy */
6077 LOAD_AB_FOR_DIV (left, right, l);
6078 emitcode ("div", "ab");
6079 aopOp (result, ic, TRUE, FALSE);
6080 aopPut (result, "b", 0);
6082 for (size = AOP_SIZE (result) - 1; size--;)
6083 aopPut (result, zero, offset++);
6089 /* signed is a little bit more difficult */
6091 /* now sign adjust for both left & right */
6093 /* modulus: sign of the right operand has no influence on the result! */
6094 if (AOP_TYPE(right) == AOP_LIT)
6096 signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
6098 if (!rUnsigned && val < 0)
6099 emitcode ("mov", "b,#0x%02x", -val);
6101 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
6103 else /* not literal */
6106 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
6109 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
6110 lbl = newiTempLabel (NULL);
6111 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
6112 emitcode ("cpl", "a"); /* 2's complement */
6113 emitcode ("inc", "a");
6115 emitcode ("mov", "b,a");
6119 /* let's see what's needed: */
6120 /* apply negative sign during runtime */
6121 runtimeSign = FALSE;
6122 /* negative sign from literals */
6123 compiletimeSign = FALSE;
6125 /* sign adjust left side */
6126 if (AOP_TYPE(left) == AOP_LIT)
6128 signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
6130 if (!lUnsigned && val < 0)
6132 compiletimeSign = TRUE; /* set sign flag */
6133 emitcode ("mov", "a,#0x%02x", -val);
6136 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
6138 else /* ! literal */
6140 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
6145 emitcode ("clr", "F0"); /* clear sign flag */
6147 lbl = newiTempLabel (NULL);
6148 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
6149 emitcode ("setb", "F0"); /* set sign flag */
6150 emitcode ("cpl", "a"); /* 2's complement */
6151 emitcode ("inc", "a");
6156 /* now the modulus */
6157 emitcode ("nop", "; workaround for DS80C390 div bug.");
6158 emitcode ("div", "ab");
6160 if (runtimeSign || compiletimeSign)
6162 emitcode ("mov", "a,b");
6163 lbl = newiTempLabel (NULL);
6165 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
6166 emitcode ("cpl", "a"); /* lsb 2's complement */
6167 emitcode ("inc", "a");
6171 aopOp (result, ic, TRUE, FALSE);
6172 size = AOP_SIZE (result) - 1;
6176 /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
6177 then the result will be in b, a */
6178 emitcode ("mov", "b,a"); /* 1 */
6179 /* msb is 0x00 or 0xff depending on the sign */
6182 emitcode ("mov", "c,F0");
6183 emitcode ("subb", "a,acc");
6184 emitcode ("xch", "a,b"); /* 2 */
6186 aopPut (result, "b", offset++); /* write msb's */
6188 else /* compiletimeSign */
6190 aopPut (result, "#0xff", offset++); /* write msb's */
6192 aopPut (result, "a", 0); /* 3: write lsb */
6197 aopOp(result, ic, TRUE, FALSE);
6198 size = AOP_SIZE (result) - 1;
6200 aopPut (result, "b", 0);
6202 aopPut (result, zero, offset++);
6208 /*-----------------------------------------------------------------*/
6209 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
6210 /*-----------------------------------------------------------------*/
6211 static void genModTwoByte (operand *left, operand *right,
6212 operand *result, iCode *ic)
6214 sym_link *retype = getSpec(operandType(right));
6215 sym_link *letype = getSpec(operandType(left));
6216 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
6219 /* load up MA with left */
6220 /* save EA bit in F1 */
6221 lbl = newiTempLabel(NULL);
6222 emitcode ("setb","F1");
6223 emitcode ("jbc","EA,!tlabel",lbl->key+100);
6224 emitcode ("clr","F1");
6228 lbl = newiTempLabel(NULL);
6229 emitcode ("mov","b,%s",aopGet(left,0,FALSE,FALSE,NULL));
6230 emitcode ("mov","a,%s",aopGet(left,1,FALSE,FALSE,NULL));
6231 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
6232 emitcode ("xch", "a,b");
6233 emitcode ("cpl","a");
6234 emitcode ("add", "a,#1");
6235 emitcode ("xch", "a,b");
6236 emitcode ("cpl", "a"); // msb
6237 emitcode ("addc","a,#0");
6239 emitcode ("mov","ma,b");
6240 emitcode ("mov","ma,a");
6242 emitcode ("mov","ma,%s",aopGet(left,0,FALSE,FALSE,NULL));
6243 emitcode ("mov","ma,%s",aopGet(left,1,FALSE,FALSE,NULL));
6246 /* load up MB with right */
6248 if (AOP_TYPE(right) == AOP_LIT) {
6249 int val=(int) ulFromVal (AOP (right)->aopu.aop_lit);
6253 emitcode ("mov","mb,#!constbyte",val & 0xff);
6254 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
6256 lbl = newiTempLabel(NULL);
6257 emitcode ("mov","b,%s",aopGet(right,0,FALSE,FALSE,NULL));
6258 emitcode ("mov","a,%s",aopGet(right,1,FALSE,FALSE,NULL));
6259 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
6260 emitcode ("xch", "a,b");
6261 emitcode ("cpl","a");
6262 emitcode ("add", "a,#1");
6263 emitcode ("xch", "a,b");
6264 emitcode ("cpl", "a"); // msb
6265 emitcode ("addc", "a,#0");
6267 emitcode ("mov","mb,b");
6268 emitcode ("mov","mb,a");
6271 emitcode ("mov","mb,%s",aopGet(right,0,FALSE,FALSE,NULL));
6272 emitcode ("mov","mb,%s",aopGet(right,1,FALSE,FALSE,NULL));
6275 /* wait for multiplication to finish */
6276 lbl = newiTempLabel(NULL);
6278 emitcode("mov","a,mcnt1");
6279 emitcode("anl","a,#!constbyte",0x80);
6280 emitcode("jnz","!tlabel",lbl->key+100);
6282 freeAsmop (left, NULL, ic, TRUE);
6283 freeAsmop (right, NULL, ic,TRUE);
6284 aopOp(result, ic, TRUE, FALSE);
6286 aopPut(result,"mb",1);
6287 aopPut(result,"mb",0);
6288 freeAsmop (result, NULL, ic, TRUE);
6290 /* restore EA bit in F1 */
6291 lbl = newiTempLabel(NULL);
6292 emitcode ("jnb","F1,!tlabel",lbl->key+100);
6293 emitcode ("setb","EA");
6297 /*-----------------------------------------------------------------*/
6298 /* genMod - generates code for division */
6299 /*-----------------------------------------------------------------*/
6303 operand *left = IC_LEFT (ic);
6304 operand *right = IC_RIGHT (ic);
6305 operand *result = IC_RESULT (ic);
6307 D (emitcode (";", "genMod"));
6309 /* assign the asmops */
6312 /* special cases first */
6314 if (AOP_TYPE (left) == AOP_CRY &&
6315 AOP_TYPE (right) == AOP_CRY)
6317 genModbits (left, right, result, ic);
6321 /* if both are of size == 1 */
6322 if (AOP_SIZE (left) == 1 &&
6323 AOP_SIZE (right) == 1)
6325 genModOneByte (left, right, result, ic);
6329 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
6330 /* use the ds390 ARITHMETIC accel UNIT */
6331 genModTwoByte (left, right, result, ic);
6335 /* should have been converted to function call */
6339 freeAsmop (result, NULL, ic, TRUE);
6340 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6341 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6344 /*-----------------------------------------------------------------*/
6345 /* genIfxJump :- will create a jump depending on the ifx */
6346 /*-----------------------------------------------------------------*/
6348 genIfxJump (iCode * ic, char *jval)
6351 symbol *tlbl = newiTempLabel (NULL);
6354 D (emitcode (";", "genIfxJump"));
6356 /* if true label then we jump if condition
6360 jlbl = IC_TRUE (ic);
6361 inst = ((strcmp (jval, "a") == 0 ? "jz" :
6362 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
6366 /* false label is present */
6367 jlbl = IC_FALSE (ic);
6368 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
6369 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
6371 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
6372 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
6374 emitcode (inst, "!tlabel", tlbl->key + 100);
6375 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
6378 /* mark the icode as generated */
6382 /*-----------------------------------------------------------------*/
6383 /* genCmp :- greater or less than comparison */
6384 /*-----------------------------------------------------------------*/
6386 genCmp (operand * left, operand * right,
6387 iCode * ic, iCode * ifx, int sign)
6389 int size, offset = 0;
6390 unsigned long lit = 0L;
6393 D (emitcode (";", "genCmp"));
6395 result = IC_RESULT (ic);
6397 /* if left & right are bit variables */
6398 if (AOP_TYPE (left) == AOP_CRY &&
6399 AOP_TYPE (right) == AOP_CRY)
6401 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6402 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6406 /* subtract right from left if at the
6407 end the carry flag is set then we know that
6408 left is greater than right */
6409 size = max (AOP_SIZE (left), AOP_SIZE (right));
6411 /* if unsigned char cmp with lit, do cjne left,#right,zz */
6412 if ((size == 1) && !sign &&
6413 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
6415 symbol *lbl = newiTempLabel (NULL);
6416 emitcode ("cjne", "%s,%s,!tlabel",
6417 aopGet (left, offset, FALSE, FALSE, NULL),
6418 aopGet (right, offset, FALSE, FALSE, NULL),
6424 if (AOP_TYPE (right) == AOP_LIT)
6426 lit = ulFromVal (AOP (right)->aopu.aop_lit);
6427 /* optimize if(x < 0) or if(x >= 0) */
6436 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
6438 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6439 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6441 aopOp (result, ic, FALSE, FALSE);
6443 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
6445 freeAsmop (result, NULL, ic, TRUE);
6446 genIfxJump (ifx, "acc.7");
6451 emitcode ("rlc", "a");
6453 goto release_freedLR;
6461 // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
6462 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
6463 // emitcode (";", "genCmp #2");
6464 if (sign && (size == 0))
6466 // emitcode (";", "genCmp #3");
6467 emitcode ("xrl", "a,#!constbyte",0x80);
6468 if (AOP_TYPE (right) == AOP_LIT)
6470 unsigned long lit = ulFromVal (AOP (right)->aopu.aop_lit);
6471 // emitcode (";", "genCmp #3.1");
6472 emitcode ("subb", "a,#!constbyte",
6473 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
6477 // emitcode (";", "genCmp #3.2");
6479 MOVB (aopGet (right, offset++, FALSE, FALSE, "b"));
6480 saveAccWarn = DEFAULT_ACC_WARNING;
6481 emitcode ("xrl", "b,#!constbyte",0x80);
6482 emitcode ("subb", "a,b");
6489 // emitcode (";", "genCmp #4");
6491 s = aopGet (right, offset++, FALSE, FALSE, "b");
6492 saveAccWarn = DEFAULT_ACC_WARNING;
6494 emitcode ("subb", "a,%s", s);
6501 /* Don't need the left & right operands any more; do need the result. */
6502 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6503 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6505 aopOp (result, ic, FALSE, FALSE);
6509 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6515 /* if the result is used in the next
6516 ifx conditional branch then generate
6517 code a little differently */
6520 genIfxJump (ifx, "c");
6526 /* leave the result in acc */
6528 freeAsmop (result, NULL, ic, TRUE);
6531 /*-----------------------------------------------------------------*/
6532 /* genCmpGt :- greater than comparison */
6533 /*-----------------------------------------------------------------*/
6535 genCmpGt (iCode * ic, iCode * ifx)
6537 operand *left, *right;
6538 sym_link *letype, *retype;
6541 D (emitcode (";", "genCmpGt"));
6543 left = IC_LEFT (ic);
6544 right = IC_RIGHT (ic);
6546 letype = getSpec (operandType (left));
6547 retype = getSpec (operandType (right));
6548 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6550 /* assign the left & right amsops */
6553 genCmp (right, left, ic, ifx, sign);
6556 /*-----------------------------------------------------------------*/
6557 /* genCmpLt - less than comparisons */
6558 /*-----------------------------------------------------------------*/
6560 genCmpLt (iCode * ic, iCode * ifx)
6562 operand *left, *right;
6563 sym_link *letype, *retype;
6566 D (emitcode (";", "genCmpLt"));
6568 left = IC_LEFT (ic);
6569 right = IC_RIGHT (ic);
6571 letype = getSpec (operandType (left));
6572 retype = getSpec (operandType (right));
6573 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6575 /* assign the left & right amsops */
6578 genCmp (left, right, ic, ifx, sign);
6581 /*-----------------------------------------------------------------*/
6582 /* gencjneshort - compare and jump if not equal */
6583 /*-----------------------------------------------------------------*/
6585 gencjneshort (operand * left, operand * right, symbol * lbl)
6587 int size = max (AOP_SIZE (left), AOP_SIZE (right));
6589 unsigned long lit = 0L;
6591 D (emitcode (";", "gencjneshort"));
6593 /* if the left side is a literal or
6594 if the right is in a pointer register and left
6596 if ((AOP_TYPE (left) == AOP_LIT) ||
6597 (AOP_TYPE (left) == AOP_IMMD) ||
6598 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6605 if (AOP_TYPE (right) == AOP_LIT)
6606 lit = ulFromVal (AOP (right)->aopu.aop_lit);
6608 if (opIsGptr (left) || opIsGptr (right))
6610 /* We are comparing a generic pointer to something.
6611 * Exclude the generic type byte from the comparison.
6614 D (emitcode (";", "cjneshort: generic ptr special case."););
6618 /* if the right side is a literal then anything goes */
6619 if (AOP_TYPE (right) == AOP_LIT &&
6620 AOP_TYPE (left) != AOP_DIR)
6624 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
6625 emitcode ("cjne", "a,%s,!tlabel",
6626 aopGet (right, offset, FALSE, FALSE, NULL),
6632 /* if the right side is in a register or in direct space or
6633 if the left is a pointer register & right is not */
6634 else if (AOP_TYPE (right) == AOP_REG ||
6635 AOP_TYPE (right) == AOP_DIR ||
6636 AOP_TYPE (right) == AOP_LIT ||
6637 AOP_TYPE (right) == AOP_IMMD ||
6638 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6639 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6643 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
6644 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6645 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6646 emitcode ("jnz", "!tlabel", lbl->key + 100);
6648 emitcode ("cjne", "a,%s,!tlabel",
6649 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG),
6656 /* right is a pointer reg need both a & b */
6659 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
6660 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
6661 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
6667 /*-----------------------------------------------------------------*/
6668 /* gencjne - compare and jump if not equal */
6669 /*-----------------------------------------------------------------*/
6671 gencjne (operand * left, operand * right, symbol * lbl)
6673 symbol *tlbl = newiTempLabel (NULL);
6675 D (emitcode (";", "gencjne"));
6677 gencjneshort (left, right, lbl);
6679 emitcode ("mov", "a,%s", one);
6680 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
6682 emitcode ("clr", "a");
6686 /*-----------------------------------------------------------------*/
6687 /* genCmpEq - generates code for equal to */
6688 /*-----------------------------------------------------------------*/
6690 genCmpEq (iCode * ic, iCode * ifx)
6692 operand *left, *right, *result;
6694 D (emitcode (";", "genCmpEq"));
6697 AOP_SET_LOCALS (ic);
6699 /* if literal, literal on the right or
6700 if the right is in a pointer register and left
6702 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6703 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6705 operand *t = IC_RIGHT (ic);
6706 IC_RIGHT (ic) = IC_LEFT (ic);
6710 if (ifx && /* !AOP_SIZE(result) */
6711 OP_SYMBOL (result) &&
6712 OP_SYMBOL (result)->regType == REG_CND)
6715 /* if they are both bit variables */
6716 if (AOP_TYPE (left) == AOP_CRY &&
6717 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6719 if (AOP_TYPE (right) == AOP_LIT)
6721 unsigned long lit = ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6724 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6725 emitcode ("cpl", "c");
6729 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6733 emitcode ("clr", "c");
6735 /* AOP_TYPE(right) == AOP_CRY */
6739 symbol *lbl = newiTempLabel (NULL);
6740 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6741 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6742 emitcode ("cpl", "c");
6745 /* if true label then we jump if condition
6747 tlbl = newiTempLabel (NULL);
6750 emitcode ("jnc", "!tlabel", tlbl->key + 100);
6751 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6755 emitcode ("jc", "!tlabel", tlbl->key + 100);
6756 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6762 tlbl = newiTempLabel (NULL);
6763 gencjneshort (left, right, tlbl);
6766 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6771 symbol *lbl = newiTempLabel (NULL);
6772 emitcode ("sjmp", "!tlabel", lbl->key + 100);
6774 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6778 /* mark the icode as generated */
6781 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6782 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6786 /* if they are both bit variables */
6787 if (AOP_TYPE (left) == AOP_CRY &&
6788 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6790 if (AOP_TYPE (right) == AOP_LIT)
6792 unsigned long lit = ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6795 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6796 emitcode ("cpl", "c");
6800 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6804 emitcode ("clr", "c");
6806 /* AOP_TYPE(right) == AOP_CRY */
6810 symbol *lbl = newiTempLabel (NULL);
6811 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6812 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6813 emitcode ("cpl", "c");
6817 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6818 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6820 aopOp (result, ic, TRUE, FALSE);
6823 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6830 genIfxJump (ifx, "c");
6833 /* if the result is used in an arithmetic operation
6834 then put the result in place */
6839 gencjne (left, right, newiTempLabel (NULL));
6841 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6842 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6844 aopOp (result, ic, TRUE, FALSE);
6846 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6848 aopPut (result, "a", 0);
6853 genIfxJump (ifx, "a");
6856 /* if the result is used in an arithmetic operation
6857 then put the result in place */
6858 if (AOP_TYPE (result) != AOP_CRY)
6860 /* leave the result in acc */
6864 freeAsmop (result, NULL, ic, TRUE);
6867 /*-----------------------------------------------------------------*/
6868 /* ifxForOp - returns the icode containing the ifx for operand */
6869 /*-----------------------------------------------------------------*/
6871 ifxForOp (operand * op, iCode * ic)
6873 /* if true symbol then needs to be assigned */
6874 if (IS_TRUE_SYMOP (op))
6877 /* if this has register type condition and
6878 the next instruction is ifx with the same operand
6879 and live to of the operand is upto the ifx only then */
6881 ic->next->op == IFX &&
6882 IC_COND (ic->next)->key == op->key &&
6883 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6889 /*-----------------------------------------------------------------*/
6890 /* hasInc - operand is incremented before any other use */
6891 /*-----------------------------------------------------------------*/
6893 hasInc (operand *op, iCode *ic, int osize)
6895 sym_link *type = operandType(op);
6896 sym_link *retype = getSpec (type);
6897 iCode *lic = ic->next;
6900 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6901 if (!IS_SYMOP(op)) return NULL;
6903 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6904 if (IS_AGGREGATE(type->next)) return NULL;
6905 if (osize != (isize = getSize(type->next))) return NULL;
6908 /* if operand of the form op = op + <sizeof *op> */
6909 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6910 isOperandEqual(IC_RESULT(lic),op) &&
6911 isOperandLiteral(IC_RIGHT(lic)) &&
6912 operandLitValue(IC_RIGHT(lic)) == isize) {
6915 /* if the operand used or deffed */
6916 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6919 /* if GOTO or IFX */
6920 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6926 /*-----------------------------------------------------------------*/
6927 /* genAndOp - for && operation */
6928 /*-----------------------------------------------------------------*/
6930 genAndOp (iCode * ic)
6932 operand *left, *right, *result;
6935 D (emitcode (";", "genAndOp"));
6937 /* note here that && operations that are in an
6938 if statement are taken away by backPatchLabels
6939 only those used in arthmetic operations remain */
6941 AOP_SET_LOCALS (ic);
6943 /* if both are bit variables */
6944 if (AOP_TYPE (left) == AOP_CRY &&
6945 AOP_TYPE (right) == AOP_CRY)
6947 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6948 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6949 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6950 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6952 aopOp (result,ic,FALSE, FALSE);
6957 tlbl = newiTempLabel (NULL);
6959 emitcode ("jz", "!tlabel", tlbl->key + 100);
6962 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6963 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6965 aopOp (result,ic,FALSE, FALSE);
6969 freeAsmop (result, NULL, ic, TRUE);
6973 /*-----------------------------------------------------------------*/
6974 /* genOrOp - for || operation */
6975 /*-----------------------------------------------------------------*/
6977 genOrOp (iCode * ic)
6979 operand *left, *right, *result;
6982 D (emitcode (";", "genOrOp"));
6984 /* note here that || operations that are in an
6985 if statement are taken away by backPatchLabels
6986 only those used in arthmetic operations remain */
6988 AOP_SET_LOCALS (ic);
6990 /* if both are bit variables */
6991 if (AOP_TYPE (left) == AOP_CRY &&
6992 AOP_TYPE (right) == AOP_CRY)
6994 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6995 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6996 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6997 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6999 aopOp (result,ic,FALSE, FALSE);
7005 tlbl = newiTempLabel (NULL);
7007 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7010 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7011 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7013 aopOp (result,ic,FALSE, FALSE);
7018 freeAsmop (result, NULL, ic, TRUE);
7021 /*-----------------------------------------------------------------*/
7022 /* isLiteralBit - test if lit == 2^n */
7023 /*-----------------------------------------------------------------*/
7025 isLiteralBit (unsigned long lit)
7027 unsigned long pw[32] =
7028 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
7029 0x100L, 0x200L, 0x400L, 0x800L,
7030 0x1000L, 0x2000L, 0x4000L, 0x8000L,
7031 0x10000L, 0x20000L, 0x40000L, 0x80000L,
7032 0x100000L, 0x200000L, 0x400000L, 0x800000L,
7033 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
7034 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
7037 for (idx = 0; idx < 32; idx++)
7043 /*-----------------------------------------------------------------*/
7044 /* continueIfTrue - */
7045 /*-----------------------------------------------------------------*/
7047 continueIfTrue (iCode * ic)
7050 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
7054 /*-----------------------------------------------------------------*/
7056 /*-----------------------------------------------------------------*/
7058 jumpIfTrue (iCode * ic)
7061 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
7065 /*-----------------------------------------------------------------*/
7066 /* jmpTrueOrFalse - */
7067 /*-----------------------------------------------------------------*/
7069 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
7071 // ugly but optimized by peephole
7074 symbol *nlbl = newiTempLabel (NULL);
7075 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
7077 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
7082 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
7088 // Generate code to perform a bit-wise logic operation
7089 // on two operands in far space (assumed to already have been
7090 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
7091 // in far space. This requires pushing the result on the stack
7092 // then popping it into the result.
7094 genFarFarLogicOp(iCode *ic, char *logicOp)
7096 int size, resultSize, compSize;
7100 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
7101 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
7102 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
7104 _startLazyDPSEvaluation();
7105 for (size = compSize; (size--); offset++)
7107 MOVA (aopGet (IC_LEFT(ic), offset, FALSE, FALSE, NULL));
7108 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
7109 MOVA (aopGet (IC_RIGHT(ic), offset, FALSE, FALSE, NULL));
7111 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
7112 emitcode ("push", "acc");
7114 _endLazyDPSEvaluation();
7116 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7117 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7118 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
7120 resultSize = AOP_SIZE(IC_RESULT(ic));
7122 ADJUST_PUSHED_RESULT(compSize, resultSize);
7124 _startLazyDPSEvaluation();
7127 emitcode ("pop", "acc");
7128 aopPut (IC_RESULT (ic), "a", compSize);
7130 _endLazyDPSEvaluation();
7131 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
7135 /*-----------------------------------------------------------------*/
7136 /* genAnd - code for and */
7137 /*-----------------------------------------------------------------*/
7139 genAnd (iCode * ic, iCode * ifx)
7141 operand *left, *right, *result;
7142 int size, offset = 0;
7143 unsigned long lit = 0L;
7148 D (emitcode (";", "genAnd"));
7150 AOP_OP_3_NOFATAL (ic, pushResult);
7151 AOP_SET_LOCALS (ic);
7155 genFarFarLogicOp(ic, "anl");
7160 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
7162 AOP_TYPE (left), AOP_TYPE (right));
7163 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
7165 AOP_SIZE (left), AOP_SIZE (right));
7168 /* if left is a literal & right is not then exchange them */
7169 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7170 #ifdef LOGIC_OPS_BROKEN
7171 || AOP_NEEDSACC (left)
7175 operand *tmp = right;
7180 /* if result = right then exchange left and right */
7181 if (sameRegs (AOP (result), AOP (right)))
7183 operand *tmp = right;
7188 /* if right is bit then exchange them */
7189 if (AOP_TYPE (right) == AOP_CRY &&
7190 AOP_TYPE (left) != AOP_CRY)
7192 operand *tmp = right;
7196 if (AOP_TYPE (right) == AOP_LIT)
7197 lit = ulFromVal (AOP (right)->aopu.aop_lit);
7199 size = AOP_SIZE (result);
7202 // result = bit & yy;
7203 if (AOP_TYPE (left) == AOP_CRY)
7205 // c = bit & literal;
7206 if (AOP_TYPE (right) == AOP_LIT)
7210 if (size && sameRegs (AOP (result), AOP (left)))
7213 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7218 if (size && (AOP_TYPE (result) == AOP_CRY))
7220 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
7223 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7228 emitcode ("clr", "c");
7233 if (AOP_TYPE (right) == AOP_CRY)
7236 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7237 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
7242 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
7244 emitcode ("rrc", "a");
7245 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
7253 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7254 genIfxJump (ifx, "c");
7258 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7259 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7260 if ((AOP_TYPE (right) == AOP_LIT) &&
7261 (AOP_TYPE (result) == AOP_CRY) &&
7262 (AOP_TYPE (left) != AOP_CRY))
7264 int posbit = isLiteralBit (lit);
7269 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE, NULL));
7273 switch (posbit & 0x07)
7275 case 0: emitcode ("rrc", "a");
7277 case 7: emitcode ("rlc", "a");
7279 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
7288 SNPRINTF (buffer, sizeof(buffer),
7289 "acc.%d", posbit & 0x07);
7290 genIfxJump (ifx, buffer);
7294 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
7301 symbol *tlbl = newiTempLabel (NULL);
7302 int sizel = AOP_SIZE (left);
7304 emitcode ("setb", "c");
7307 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
7309 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7311 if ((posbit = isLiteralBit (bytelit)) != 0)
7312 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
7315 if (bytelit != 0x0FFL)
7316 emitcode ("anl", "a,%s",
7317 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG));
7318 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7323 // bit = left & literal
7326 emitcode ("clr", "c");
7329 // if(left & literal)
7333 jmpTrueOrFalse (ifx, tlbl);
7343 /* if left is same as result */
7344 if (sameRegs (AOP (result), AOP (left)))
7346 for (; size--; offset++)
7348 if (AOP_TYPE (right) == AOP_LIT)
7350 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7351 if (bytelit == 0x0FF)
7353 /* dummy read of volatile operand */
7354 if (isOperandVolatile (left, FALSE))
7355 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7359 else if (bytelit == 0)
7361 aopPut (result, zero, offset);
7363 else if (IS_AOP_PREG (result))
7365 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7366 emitcode ("anl", "a,%s",
7367 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG));
7368 aopPut (result, "a", offset);
7371 emitcode ("anl", "%s,%s",
7372 aopGet (left, offset, FALSE, TRUE, NULL),
7373 aopGet (right, offset, FALSE, FALSE, NULL));
7377 if (AOP_TYPE (left) == AOP_ACC)
7380 emitcode("mov", "a,b");
7381 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7383 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7385 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
7386 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7387 emitcode ("anl", "a,b");
7388 aopPut (result, "a", offset);
7390 else if (aopGetUsesAcc (left, offset))
7392 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7393 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7394 aopPut (result, "a", offset);
7398 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7399 if (IS_AOP_PREG (result))
7401 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7402 aopPut (result, "a", offset);
7405 emitcode ("anl", "%s,a", aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7412 // left & result in different registers
7413 if (AOP_TYPE (result) == AOP_CRY)
7416 // if(size), result in bit
7417 // if(!size && ifx), conditional oper: if(left & right)
7418 symbol *tlbl = newiTempLabel (NULL);
7419 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
7421 emitcode ("setb", "c");
7424 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7425 && AOP_TYPE(left)==AOP_ACC)
7428 emitcode("mov", "a,b");
7429 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, NULL));
7431 else if (AOP_TYPE(left)==AOP_ACC)
7435 bool pushedB = pushB ();
7436 emitcode("mov", "b,a");
7437 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7438 emitcode("anl", "a,b");
7443 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7444 emitcode("anl", "a,b");
7447 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7449 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE, NULL));
7450 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7451 emitcode ("anl", "a,b");
7453 else if (aopGetUsesAcc (left, offset))
7455 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7456 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7460 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7461 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE, DP2_RESULT_REG));
7464 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7474 jmpTrueOrFalse (ifx, tlbl);
7480 for (; (size--); offset++)
7483 // result = left & right
7484 if (AOP_TYPE (right) == AOP_LIT)
7486 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7487 if (bytelit == 0x0FF)
7490 aopGet (left, offset, FALSE, FALSE, NULL),
7494 else if (bytelit == 0)
7496 /* dummy read of volatile operand */
7497 if (isOperandVolatile (left, FALSE))
7498 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7499 aopPut (result, zero, offset);
7502 else if (AOP_TYPE (left) == AOP_ACC)
7506 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, NULL));
7507 aopPut (result, "a", offset);
7512 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE, NULL));
7513 aopPut (result, "b", offset);
7518 // faster than result <- left, anl result,right
7519 // and better if result is SFR
7520 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7521 && AOP_TYPE(left)==AOP_ACC)
7524 emitcode("mov", "a,b");
7525 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, NULL));
7527 else if (AOP_TYPE(left)==AOP_ACC)
7531 bool pushedB = pushB ();
7532 emitcode("mov", "b,a");
7533 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7534 emitcode("anl", "a,b");
7539 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7540 emitcode("anl", "a,b");
7543 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7545 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
7546 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7547 emitcode ("anl", "a,b");
7549 else if (aopGetUsesAcc (left, offset))
7551 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7552 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7556 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7557 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE, DP2_RESULT_REG));
7559 aopPut (result, "a", offset);
7565 freeAsmop (result, NULL, ic, TRUE);
7566 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7567 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7570 /*-----------------------------------------------------------------*/
7571 /* genOr - code for or */
7572 /*-----------------------------------------------------------------*/
7574 genOr (iCode * ic, iCode * ifx)
7576 operand *left, *right, *result;
7577 int size, offset = 0;
7578 unsigned long lit = 0L;
7582 D (emitcode (";", "genOr"));
7584 AOP_OP_3_NOFATAL (ic, pushResult);
7585 AOP_SET_LOCALS (ic);
7589 genFarFarLogicOp(ic, "orl");
7595 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
7597 AOP_TYPE (left), AOP_TYPE (right));
7598 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
7600 AOP_SIZE (left), AOP_SIZE (right));
7603 /* if left is a literal & right is not then exchange them */
7604 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7605 #ifdef LOGIC_OPS_BROKEN
7606 || AOP_NEEDSACC (left) // I think this is a net loss now.
7610 operand *tmp = right;
7615 /* if result = right then exchange them */
7616 if (sameRegs (AOP (result), AOP (right)))
7618 operand *tmp = right;
7623 /* if right is bit then exchange them */
7624 if (AOP_TYPE (right) == AOP_CRY &&
7625 AOP_TYPE (left) != AOP_CRY)
7627 operand *tmp = right;
7631 if (AOP_TYPE (right) == AOP_LIT)
7632 lit = ulFromVal (AOP (right)->aopu.aop_lit);
7634 size = AOP_SIZE (result);
7638 if (AOP_TYPE (left) == AOP_CRY)
7640 if (AOP_TYPE (right) == AOP_LIT)
7642 // c = bit | literal;
7645 // lit != 0 => result = 1
7646 if (AOP_TYPE (result) == AOP_CRY)
7649 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7651 continueIfTrue (ifx);
7654 emitcode ("setb", "c");
7658 // lit == 0 => result = left
7659 if (size && sameRegs (AOP (result), AOP (left)))
7661 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7666 if (AOP_TYPE (right) == AOP_CRY)
7669 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7670 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7675 symbol *tlbl = newiTempLabel (NULL);
7676 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
7677 emitcode ("setb", "c");
7678 emitcode ("jb", "%s,!tlabel",
7679 AOP (left)->aopu.aop_dir, tlbl->key + 100);
7681 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7682 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7684 jmpTrueOrFalse (ifx, tlbl);
7699 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7700 genIfxJump (ifx, "c");
7704 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7705 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7706 if ((AOP_TYPE (right) == AOP_LIT) &&
7707 (AOP_TYPE (result) == AOP_CRY) &&
7708 (AOP_TYPE (left) != AOP_CRY))
7714 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7716 continueIfTrue (ifx);
7721 // lit = 0, result = boolean(left)
7723 emitcode ("setb", "c");
7727 symbol *tlbl = newiTempLabel (NULL);
7728 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7734 genIfxJump (ifx, "a");
7742 /* if left is same as result */
7743 if (sameRegs (AOP (result), AOP (left)))
7745 for (; size--; offset++)
7747 if (AOP_TYPE (right) == AOP_LIT)
7749 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7752 /* dummy read of volatile operand */
7753 if (isOperandVolatile (left, FALSE))
7754 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7758 else if (bytelit == 0x0FF)
7760 aopPut (result, "#0xFF", offset);
7762 else if (IS_AOP_PREG (left))
7764 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7765 emitcode ("orl", "a,%s",
7766 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7767 aopPut (result, "a", offset);
7771 emitcode ("orl", "%s,%s",
7772 aopGet (left, offset, FALSE, TRUE, NULL),
7773 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7778 if (AOP_TYPE (left) == AOP_ACC)
7781 emitcode("mov", "a,b");
7782 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7784 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7786 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE, NULL));
7787 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7788 emitcode ("orl", "a,b");
7789 aopPut (result, "a", offset);
7791 else if (aopGetUsesAcc (left, offset))
7793 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7794 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7795 aopPut (result, "a", offset);
7799 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7800 if (IS_AOP_PREG (left))
7802 emitcode ("orl", "a,%s",
7803 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7804 aopPut (result, "a", offset);
7808 emitcode ("orl", "%s,a",
7809 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7817 // left & result in different registers
7818 if (AOP_TYPE (result) == AOP_CRY)
7821 // if(size), result in bit
7822 // if(!size && ifx), conditional oper: if(left | right)
7823 symbol *tlbl = newiTempLabel (NULL);
7824 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7826 emitcode ("setb", "c");
7829 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7830 && AOP_TYPE(left)==AOP_ACC)
7833 emitcode("mov", "a,b");
7834 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7836 else if (AOP_TYPE(left)==AOP_ACC)
7840 bool pushedB = pushB ();
7841 emitcode("mov", "b,a");
7842 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7843 emitcode("orl", "a,b");
7848 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7849 emitcode("orl", "a,b");
7852 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7854 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
7855 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7856 emitcode ("orl", "a,b");
7858 else if (aopGetUsesAcc (left, offset))
7860 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7861 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7865 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7866 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE, DP2_RESULT_REG));
7869 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7879 jmpTrueOrFalse (ifx, tlbl);
7885 _startLazyDPSEvaluation();
7886 for (; (size--); offset++)
7889 // result = left | right
7890 if (AOP_TYPE (right) == AOP_LIT)
7892 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7896 aopGet (left, offset, FALSE, FALSE, NULL),
7900 else if (bytelit == 0x0FF)
7902 /* dummy read of volatile operand */
7903 if (isOperandVolatile (left, FALSE))
7904 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7905 aopPut (result, "#0xFF", offset);
7909 // faster than result <- left, orl result,right
7910 // and better if result is SFR
7911 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7912 && AOP_TYPE(left)==AOP_ACC)
7915 emitcode("mov", "a,b");
7916 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7918 else if (AOP_TYPE(left)==AOP_ACC)
7922 bool pushedB = pushB ();
7923 emitcode("mov", "b,a");
7924 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7925 emitcode("orl", "a,b");
7930 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7931 emitcode("orl", "a,b");
7934 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7936 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
7937 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7938 emitcode ("orl", "a,b");
7940 else if (aopGetUsesAcc (left, offset))
7942 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7943 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7947 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7948 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE, DP2_RESULT_REG));
7950 aopPut (result, "a", offset);
7952 _endLazyDPSEvaluation();
7957 freeAsmop (result, NULL, ic, TRUE);
7958 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7959 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7962 /*-----------------------------------------------------------------*/
7963 /* genXor - code for xclusive or */
7964 /*-----------------------------------------------------------------*/
7966 genXor (iCode * ic, iCode * ifx)
7968 operand *left, *right, *result;
7969 int size, offset = 0;
7970 unsigned long lit = 0L;
7974 D (emitcode (";", "genXor"));
7976 AOP_OP_3_NOFATAL (ic, pushResult);
7977 AOP_SET_LOCALS (ic);
7981 genFarFarLogicOp(ic, "xrl");
7986 emitcode (";", "Type res[%d] = l[%d]&r[%d]",
7988 AOP_TYPE (left), AOP_TYPE (right));
7989 emitcode (";", "Size res[%d] = l[%d]&r[%d]",
7991 AOP_SIZE (left), AOP_SIZE (right));
7994 /* if left is a literal & right is not ||
7995 if left needs acc & right does not */
7996 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7997 #ifdef LOGIC_OPS_BROKEN
7998 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
8002 operand *tmp = right;
8007 /* if result = right then exchange them */
8008 if (sameRegs (AOP (result), AOP (right)))
8010 operand *tmp = right;
8015 /* if right is bit then exchange them */
8016 if (AOP_TYPE (right) == AOP_CRY &&
8017 AOP_TYPE (left) != AOP_CRY)
8019 operand *tmp = right;
8023 if (AOP_TYPE (right) == AOP_LIT)
8024 lit = ulFromVal (AOP (right)->aopu.aop_lit);
8026 size = AOP_SIZE (result);
8030 if (AOP_TYPE (left) == AOP_CRY)
8032 if (AOP_TYPE (right) == AOP_LIT)
8034 // c = bit & literal;
8037 // lit>>1 != 0 => result = 1
8038 if (AOP_TYPE (result) == AOP_CRY)
8041 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
8043 continueIfTrue (ifx);
8046 emitcode ("setb", "c");
8053 // lit == 0, result = left
8054 if (size && sameRegs (AOP (result), AOP (left)))
8056 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
8060 // lit == 1, result = not(left)
8061 if (size && sameRegs (AOP (result), AOP (left)))
8063 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
8068 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
8069 emitcode ("cpl", "c");
8077 symbol *tlbl = newiTempLabel (NULL);
8078 if (AOP_TYPE (right) == AOP_CRY)
8081 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8085 int sizer = AOP_SIZE (right);
8087 // if val>>1 != 0, result = 1
8088 emitcode ("setb", "c");
8091 MOVA (aopGet (right, sizer - 1, FALSE, FALSE, NULL));
8093 // test the msb of the lsb
8094 emitcode ("anl", "a,#!constbyte",0xfe);
8095 emitcode ("jnz", "!tlabel", tlbl->key + 100);
8099 emitcode ("rrc", "a");
8101 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
8102 emitcode ("cpl", "c");
8110 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
8111 genIfxJump (ifx, "c");
8115 /* if left is same as result */
8116 if (sameRegs (AOP (result), AOP (left)))
8118 for (; size--; offset++)
8120 if (AOP_TYPE (right) == AOP_LIT)
8122 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
8125 /* dummy read of volatile operand */
8126 if (isOperandVolatile (left, FALSE))
8127 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8131 else if (IS_AOP_PREG (left))
8133 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8134 emitcode ("xrl", "a,%s",
8135 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG));
8136 aopPut (result, "a", offset);
8140 emitcode ("xrl", "%s,%s",
8141 aopGet (left, offset, FALSE, TRUE, NULL),
8142 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8147 if (AOP_TYPE (left) == AOP_ACC)
8150 emitcode("mov", "a,b");
8151 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8153 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
8155 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
8156 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8157 emitcode ("xrl", "a,b");
8158 aopPut (result, "a", offset);
8160 else if (aopGetUsesAcc (left, offset))
8162 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8163 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8164 aopPut (result, "a", offset);
8168 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
8169 if (IS_AOP_PREG (left))
8171 emitcode ("xrl", "a,%s",
8172 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
8173 aopPut (result, "a", offset);
8176 emitcode ("xrl", "%s,a",
8177 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
8184 // left & result in different registers
8185 if (AOP_TYPE (result) == AOP_CRY)
8188 // if(size), result in bit
8189 // if(!size && ifx), conditional oper: if(left ^ right)
8190 symbol *tlbl = newiTempLabel (NULL);
8191 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
8194 emitcode ("setb", "c");
8197 if ((AOP_TYPE (right) == AOP_LIT) &&
8198 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
8200 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8202 else if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
8203 && AOP_TYPE(left)==AOP_ACC)
8206 emitcode("mov", "a,b");
8207 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8209 else if (AOP_TYPE(left)==AOP_ACC)
8213 bool pushedB = pushB ();
8214 emitcode("mov", "b,a");
8215 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8216 emitcode("xrl", "a,b");
8221 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8222 emitcode("xrl", "a,b");
8225 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
8227 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
8228 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8229 emitcode ("xrl", "a,b");
8231 else if (aopGetUsesAcc (left, offset))
8233 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8234 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8238 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
8239 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
8242 emitcode ("jnz", "!tlabel", tlbl->key + 100);
8252 jmpTrueOrFalse (ifx, tlbl);
8256 for (; (size--); offset++)
8259 // result = left ^ right
8260 if (AOP_TYPE (right) == AOP_LIT)
8262 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
8266 aopGet (left, offset, FALSE, FALSE, NULL),
8270 D (emitcode (";", "better literal XOR."));
8271 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8272 emitcode ("xrl", "a, %s",
8273 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8277 // faster than result <- left, anl result,right
8278 // and better if result is SFR
8279 if (AOP_TYPE (left) == AOP_ACC)
8281 emitcode ("xrl", "a,%s",
8282 aopGet (right, offset,
8283 FALSE, FALSE, DP2_RESULT_REG));
8287 char *rOp = aopGet (right, offset, FALSE, FALSE, NULL);
8288 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
8290 emitcode("mov", "b,a");
8294 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8295 emitcode ("xrl", "a,%s", rOp);
8298 aopPut (result, "a", offset);
8304 freeAsmop (result, NULL, ic, TRUE);
8305 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
8306 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
8309 /*-----------------------------------------------------------------*/
8310 /* genInline - write the inline code out */
8311 /*-----------------------------------------------------------------*/
8313 genInline (iCode * ic)
8315 char *buffer, *bp, *bp1;
8316 bool inComment = FALSE;
8318 D (emitcode (";", "genInline"));
8320 _G.inLine += (!options.asmpeep);
8322 buffer = bp = bp1 = Safe_strdup (IC_INLINE(ic));
8324 /* emit each line as a code */
8342 /* Add \n for labels, not dirs such as c:\mydir */
8343 if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
8361 _G.inLine -= (!options.asmpeep);
8364 /*-----------------------------------------------------------------*/
8365 /* genRRC - rotate right with carry */
8366 /*-----------------------------------------------------------------*/
8370 operand *left, *result;
8374 D (emitcode (";", "genRRC"));
8376 /* rotate right with carry */
8377 left = IC_LEFT (ic);
8378 result = IC_RESULT (ic);
8379 aopOp (left, ic, FALSE, FALSE);
8380 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8382 /* move it to the result */
8383 size = AOP_SIZE (result);
8387 _startLazyDPSEvaluation ();
8390 l = aopGet (left, offset, FALSE, FALSE, NULL);
8392 emitcode ("rrc", "a");
8393 if (AOP_SIZE (result) > 1)
8394 aopPut (result, "a", offset--);
8396 _endLazyDPSEvaluation ();
8398 /* now we need to put the carry into the
8399 highest order byte of the result */
8400 if (AOP_SIZE (result) > 1)
8402 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE, NULL);
8405 emitcode ("mov", "acc.7,c");
8406 aopPut (result, "a", AOP_SIZE (result) - 1);
8407 freeAsmop (result, NULL, ic, TRUE);
8408 freeAsmop (left, NULL, ic, TRUE);
8411 /*-----------------------------------------------------------------*/
8412 /* genRLC - generate code for rotate left with carry */
8413 /*-----------------------------------------------------------------*/
8417 operand *left, *result;
8421 D (emitcode (";", "genRLC"));
8423 /* rotate right with carry */
8424 left = IC_LEFT (ic);
8425 result = IC_RESULT (ic);
8426 aopOp (left, ic, FALSE, FALSE);
8427 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8429 /* move it to the result */
8430 size = AOP_SIZE (result);
8434 l = aopGet (left, offset, FALSE, FALSE, NULL);
8436 emitcode ("add", "a,acc");
8437 if (AOP_SIZE (result) > 1)
8439 aopPut (result, "a", offset++);
8442 _startLazyDPSEvaluation ();
8445 l = aopGet (left, offset, FALSE, FALSE, NULL);
8447 emitcode ("rlc", "a");
8448 if (AOP_SIZE (result) > 1)
8449 aopPut (result, "a", offset++);
8451 _endLazyDPSEvaluation ();
8453 /* now we need to put the carry into the
8454 highest order byte of the result */
8455 if (AOP_SIZE (result) > 1)
8457 l = aopGet (result, 0, FALSE, FALSE, NULL);
8460 emitcode ("mov", "acc.0,c");
8461 aopPut (result, "a", 0);
8462 freeAsmop (result, NULL, ic, TRUE);
8463 freeAsmop (left, NULL, ic, TRUE);
8466 /*-----------------------------------------------------------------*/
8467 /* genGetHbit - generates code get highest order bit */
8468 /*-----------------------------------------------------------------*/
8470 genGetHbit (iCode * ic)
8472 operand *left, *result;
8474 D (emitcode (";", "genGetHbit"));
8476 left = IC_LEFT (ic);
8477 result = IC_RESULT (ic);
8478 aopOp (left, ic, FALSE, FALSE);
8479 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8481 /* get the highest order byte into a */
8482 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
8483 if (AOP_TYPE (result) == AOP_CRY)
8485 emitcode ("rlc", "a");
8490 emitcode ("rl", "a");
8491 emitcode ("anl", "a,#1");
8496 freeAsmop (result, NULL, ic, TRUE);
8497 freeAsmop (left, NULL, ic, TRUE);
8500 /*-----------------------------------------------------------------*/
8501 /* genSwap - generates code to swap nibbles or bytes */
8502 /*-----------------------------------------------------------------*/
8504 genSwap (iCode * ic)
8506 operand *left, *result;
8508 D(emitcode (";", "genSwap"));
8510 left = IC_LEFT (ic);
8511 result = IC_RESULT (ic);
8512 aopOp (left, ic, FALSE, FALSE);
8513 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8515 _startLazyDPSEvaluation ();
8516 switch (AOP_SIZE (left))
8518 case 1: /* swap nibbles in byte */
8519 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
8520 emitcode ("swap", "a");
8521 aopPut (result, "a", 0);
8523 case 2: /* swap bytes in word */
8524 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
8526 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
8527 aopPut (result, aopGet (left, 1, FALSE, FALSE, NULL), 0);
8528 aopPut (result, "a", 1);
8530 else if (operandsEqu (left, result))
8533 bool pushedB = FALSE, leftInB = FALSE;
8535 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
8536 if (AOP_NEEDSACC (left) || AOP_NEEDSACC (result))
8539 emitcode ("mov", "b,a");
8543 aopPut (result, aopGet (left, 1, FALSE, FALSE, NULL), 0);
8544 aopPut (result, reg, 1);
8551 aopPut (result, aopGet (left, 1, FALSE, FALSE, NULL), 0);
8552 aopPut (result, aopGet (left, 0, FALSE, FALSE, NULL), 1);
8556 wassertl(FALSE, "unsupported SWAP operand size");
8558 _endLazyDPSEvaluation ();
8560 freeAsmop (result, NULL, ic, TRUE);
8561 freeAsmop (left, NULL, ic, TRUE);
8564 /*-----------------------------------------------------------------*/
8565 /* AccRol - rotate left accumulator by known count */
8566 /*-----------------------------------------------------------------*/
8568 AccRol (int shCount)
8570 shCount &= 0x0007; // shCount : 0..7
8577 emitcode ("rl", "a");
8580 emitcode ("rl", "a");
8581 emitcode ("rl", "a");
8584 emitcode ("swap", "a");
8585 emitcode ("rr", "a");
8588 emitcode ("swap", "a");
8591 emitcode ("swap", "a");
8592 emitcode ("rl", "a");
8595 emitcode ("rr", "a");
8596 emitcode ("rr", "a");
8599 emitcode ("rr", "a");
8604 /*-----------------------------------------------------------------*/
8605 /* AccLsh - left shift accumulator by known count */
8606 /*-----------------------------------------------------------------*/
8608 AccLsh (int shCount)
8613 emitcode ("add", "a,acc");
8614 else if (shCount == 2)
8616 emitcode ("add", "a,acc");
8617 emitcode ("add", "a,acc");
8621 /* rotate left accumulator */
8623 /* and kill the lower order bits */
8624 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
8629 /*-----------------------------------------------------------------*/
8630 /* AccRsh - right shift accumulator by known count */
8631 /*-----------------------------------------------------------------*/
8633 AccRsh (int shCount)
8640 emitcode ("rrc", "a");
8644 /* rotate right accumulator */
8645 AccRol (8 - shCount);
8646 /* and kill the higher order bits */
8647 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
8652 #ifdef BETTER_LITERAL_SHIFT
8653 /*-----------------------------------------------------------------*/
8654 /* AccSRsh - signed right shift accumulator by known count */
8655 /*-----------------------------------------------------------------*/
8657 AccSRsh (int shCount)
8664 emitcode ("mov", "c,acc.7");
8665 emitcode ("rrc", "a");
8667 else if (shCount == 2)
8669 emitcode ("mov", "c,acc.7");
8670 emitcode ("rrc", "a");
8671 emitcode ("mov", "c,acc.7");
8672 emitcode ("rrc", "a");
8676 tlbl = newiTempLabel (NULL);
8677 /* rotate right accumulator */
8678 AccRol (8 - shCount);
8679 /* and kill the higher order bits */
8680 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
8681 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8682 emitcode ("orl", "a,#!constbyte",
8683 (unsigned char) ~SRMask[shCount]);
8690 #ifdef BETTER_LITERAL_SHIFT
8691 /*-----------------------------------------------------------------*/
8692 /* shiftR1Left2Result - shift right one byte from left to result */
8693 /*-----------------------------------------------------------------*/
8695 shiftR1Left2Result (operand * left, int offl,
8696 operand * result, int offr,
8697 int shCount, int sign)
8699 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
8700 /* shift right accumulator */
8705 aopPut (result, "a", offr);
8709 #ifdef BETTER_LITERAL_SHIFT
8710 /*-----------------------------------------------------------------*/
8711 /* shiftL1Left2Result - shift left one byte from left to result */
8712 /*-----------------------------------------------------------------*/
8714 shiftL1Left2Result (operand * left, int offl,
8715 operand * result, int offr, int shCount)
8718 l = aopGet (left, offl, FALSE, FALSE, NULL);
8720 /* shift left accumulator */
8722 aopPut (result, "a", offr);
8726 #ifdef BETTER_LITERAL_SHIFT
8727 /*-----------------------------------------------------------------*/
8728 /* movLeft2Result - move byte from left to result */
8729 /*-----------------------------------------------------------------*/
8731 movLeft2Result (operand * left, int offl,
8732 operand * result, int offr, int sign)
8735 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8737 l = aopGet (left, offl, FALSE, FALSE, NULL);
8739 if (*l == '@' && (IS_AOP_PREG (result)))
8741 emitcode ("mov", "a,%s", l);
8742 aopPut (result, "a", offr);
8748 aopPut (result, l, offr);
8752 /* MSB sign in acc.7 ! */
8753 if (getDataSize (left) == offl + 1)
8756 aopPut (result, "a", offr);
8764 #ifdef BETTER_LITERAL_SHIFT
8765 /*-----------------------------------------------------------------*/
8766 /* AccAXRrl1 - right rotate a:x by 1 */
8767 /*-----------------------------------------------------------------*/
8771 emitcode ("mov", "c,acc.0");
8772 emitcode ("xch", "a,%s", x);
8773 emitcode ("rrc", "a");
8774 emitcode ("xch", "a,%s", x);
8775 emitcode ("rrc", "a");
8779 #ifdef BETTER_LITERAL_SHIFT
8781 /*-----------------------------------------------------------------*/
8782 /* AccAXLrl1 - left rotate a:x by 1 */
8783 /*-----------------------------------------------------------------*/
8787 emitcode ("mov", "c,acc.7");
8788 emitcode ("xch", "a,%s", x);
8789 emitcode ("rlc", "a");
8790 emitcode ("xch", "a,%s", x);
8791 emitcode ("rlc", "a");
8795 #ifdef BETTER_LITERAL_SHIFT
8796 /*-----------------------------------------------------------------*/
8797 /* AccAXRsh1 - right shift c->a:x->c by 1 */
8798 /*-----------------------------------------------------------------*/
8802 emitcode ("rrc", "a");
8803 emitcode ("xch", "a,%s", x);
8804 emitcode ("rrc", "a");
8805 emitcode ("xch", "a,%s", x);
8809 #ifdef BETTER_LITERAL_SHIFT
8810 /*-----------------------------------------------------------------*/
8811 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8812 /*-----------------------------------------------------------------*/
8816 emitcode ("xch", "a,%s", x);
8817 emitcode ("add", "a,acc");
8818 emitcode ("xch", "a,%s", x);
8819 emitcode ("rlc", "a");
8823 #ifdef BETTER_LITERAL_SHIFT
8824 /*-----------------------------------------------------------------*/
8825 /* AccAXLsh - left shift a:x by known count (0..7) */
8826 /*-----------------------------------------------------------------*/
8828 AccAXLsh (char *x, int shCount)
8843 case 5: // AAAAABBB:CCCCCDDD
8845 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8847 emitcode ("anl", "a,#!constbyte",
8848 SLMask[shCount]); // BBB00000:CCCCCDDD
8850 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8852 AccRol (shCount); // DDDCCCCC:BBB00000
8854 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8856 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8858 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8860 emitcode ("anl", "a,#!constbyte",
8861 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8863 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8865 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8868 case 6: // AAAAAABB:CCCCCCDD
8869 emitcode ("anl", "a,#!constbyte",
8870 SRMask[shCount]); // 000000BB:CCCCCCDD
8872 AccAXRrl1 (x); // D000000B:BCCCCCCD
8873 AccAXRrl1 (x); // DD000000:BBCCCCCC
8874 emitcode ("xch", "a,%s", x); // BBCCCCCC:DD000000
8876 emitcode ("mov", "c,acc.0"); // c = B
8877 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8878 emitcode("rrc","a");
8879 emitcode("xch","a,%s", x);
8880 emitcode("rrc","a");
8881 emitcode("mov","c,acc.0"); //<< get correct bit
8882 emitcode("xch","a,%s", x);
8884 emitcode("rrc","a");
8885 emitcode("xch","a,%s", x);
8886 emitcode("rrc","a");
8887 emitcode("xch","a,%s", x);
8890 case 7: // a:x <<= 7
8892 emitcode ("anl", "a,#!constbyte",
8893 SRMask[shCount]); // 0000000B:CCCCCCCD
8895 AccAXRrl1 (x); // D0000000:BCCCCCCC
8897 emitcode ("xch", "a,%s", x); // BCCCCCCC:D0000000
8906 #ifdef BETTER_LITERAL_SHIFT
8908 /*-----------------------------------------------------------------*/
8909 /* AccAXRsh - right shift a:x known count (0..7) */
8910 /*-----------------------------------------------------------------*/
8912 AccAXRsh (char *x, int shCount)
8920 AccAXRsh1 (x); // 0->a:x
8925 AccAXRsh1 (x); // 0->a:x
8928 AccAXRsh1 (x); // 0->a:x
8933 case 5: // AAAAABBB:CCCCCDDD = a:x
8935 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8937 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8939 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8941 emitcode ("anl", "a,#!constbyte",
8942 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8944 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8946 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8948 emitcode ("anl", "a,#!constbyte",
8949 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8951 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8953 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8955 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8958 case 6: // AABBBBBB:CCDDDDDD
8960 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDE
8961 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8963 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8965 emitcode ("anl", "a,#!constbyte",
8966 SRMask[shCount]); // 000000AA:BBBBBBCC
8969 case 7: // ABBBBBBB:CDDDDDDD
8971 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8973 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8975 emitcode ("anl", "a,#!constbyte",
8976 SRMask[shCount]); // 0000000A:BBBBBBBC
8985 #ifdef BETTER_LITERAL_SHIFT
8986 /*-----------------------------------------------------------------*/
8987 /* AccAXRshS - right shift signed a:x known count (0..7) */
8988 /*-----------------------------------------------------------------*/
8990 AccAXRshS (char *x, int shCount)
8998 emitcode ("mov", "c,acc.7");
8999 AccAXRsh1 (x); // s->a:x
9003 emitcode ("mov", "c,acc.7");
9004 AccAXRsh1 (x); // s->a:x
9006 emitcode ("mov", "c,acc.7");
9007 AccAXRsh1 (x); // s->a:x
9012 case 5: // AAAAABBB:CCCCCDDD = a:x
9014 tlbl = newiTempLabel (NULL);
9015 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
9017 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
9019 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
9021 emitcode ("anl", "a,#!constbyte",
9022 SRMask[shCount]); // 000CCCCC:BBBAAAAA
9024 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
9026 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
9028 emitcode ("anl", "a,#!constbyte",
9029 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
9031 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
9033 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
9035 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
9037 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
9038 emitcode ("orl", "a,#!constbyte",
9039 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
9042 break; // SSSSAAAA:BBBCCCCC
9044 case 6: // AABBBBBB:CCDDDDDD
9046 tlbl = newiTempLabel (NULL);
9048 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
9049 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
9051 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
9053 emitcode ("anl", "a,#!constbyte",
9054 SRMask[shCount]); // 000000AA:BBBBBBCC
9056 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
9057 emitcode ("orl", "a,#!constbyte",
9058 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
9062 case 7: // ABBBBBBB:CDDDDDDD
9064 tlbl = newiTempLabel (NULL);
9066 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
9068 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
9070 emitcode ("anl", "a,#!constbyte",
9071 SRMask[shCount]); // 0000000A:BBBBBBBC
9073 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
9074 emitcode ("orl", "a,#!constbyte",
9075 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
9085 #ifdef BETTER_LITERAL_SHIFT
9087 _loadLeftIntoAx(char **lsb,
9093 // Get the initial value from left into a pair of registers.
9094 // MSB must be in A, LSB can be any register.
9096 // If the result is held in registers, it is an optimization
9097 // if the LSB can be held in the register which will hold the,
9098 // result LSB since this saves us from having to copy it into
9099 // the result following AccAXLsh.
9101 // If the result is addressed indirectly, this is not a gain.
9102 if (AOP_NEEDSACC(result))
9106 _startLazyDPSEvaluation();
9107 if (AOP_TYPE(left) == AOP_DPTR2)
9110 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE, NULL));
9111 // get LSB in DP2_RESULT_REG.
9112 leftByte = aopGet (left, offl, FALSE, FALSE, DP2_RESULT_REG);
9113 assert(!strcmp(leftByte, DP2_RESULT_REG));
9117 // get LSB into DP2_RESULT_REG
9118 leftByte = aopGet (left, offl, FALSE, FALSE, NULL);
9119 if (strcmp(leftByte, DP2_RESULT_REG))
9122 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
9125 leftByte = aopGet (left, offl + MSB16, FALSE, FALSE, NULL);
9126 assert(strcmp(leftByte, DP2_RESULT_REG));
9129 _endLazyDPSEvaluation();
9130 *lsb = DP2_RESULT_REG;
9134 if (sameRegs (AOP (result), AOP (left)) &&
9135 ((offl + MSB16) == offr))
9137 /* don't crash result[offr] */
9138 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
9139 emitcode ("xch", "a,%s",
9140 aopGet (left, offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
9144 movLeft2Result (left, offl, result, offr, 0);
9145 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE, NULL));
9147 *lsb = aopGet (result, offr, FALSE, FALSE, DP2_RESULT_REG);
9148 assert(strcmp(*lsb,"a"));
9153 _storeAxResults(char *lsb,
9157 _startLazyDPSEvaluation();
9158 if (AOP_NEEDSACC(result))
9160 /* We have to explicitly update the result LSB.
9162 emitcode ("xch","a,%s", lsb);
9163 aopPut (result, "a", offr);
9164 emitcode ("mov","a,%s", lsb);
9166 if (getDataSize (result) > 1)
9168 aopPut (result, "a", offr + MSB16);
9170 _endLazyDPSEvaluation();
9173 /*-----------------------------------------------------------------*/
9174 /* shiftL2Left2Result - shift left two bytes from left to result */
9175 /*-----------------------------------------------------------------*/
9177 shiftL2Left2Result (operand * left, int offl,
9178 operand * result, int offr, int shCount)
9182 _loadLeftIntoAx(&lsb, left, result, offl, offr);
9184 AccAXLsh (lsb, shCount);
9186 _storeAxResults(lsb, result, offr);
9190 #ifdef BETTER_LITERAL_SHIFT
9191 /*-----------------------------------------------------------------*/
9192 /* shiftR2Left2Result - shift right two bytes from left to result */
9193 /*-----------------------------------------------------------------*/
9195 shiftR2Left2Result (operand * left, int offl,
9196 operand * result, int offr,
9197 int shCount, int sign)
9201 _loadLeftIntoAx(&lsb, left, result, offl, offr);
9203 /* a:x >> shCount (x = lsb(result)) */
9206 AccAXRshS(lsb, shCount);
9210 AccAXRsh(lsb, shCount);
9213 _storeAxResults(lsb, result, offr);
9217 /*-----------------------------------------------------------------*/
9218 /* shiftLLeftOrResult - shift left one byte from left, or to result */
9219 /*-----------------------------------------------------------------*/
9221 shiftLLeftOrResult (operand * left, int offl,
9222 operand * result, int offr, int shCount)
9224 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
9225 /* shift left accumulator */
9227 /* or with result */
9228 emitcode ("orl", "a,%s",
9229 aopGet (result, offr, FALSE, FALSE, DP2_RESULT_REG));
9230 /* back to result */
9231 aopPut (result, "a", offr);
9236 /*-----------------------------------------------------------------*/
9237 /* shiftRLeftOrResult - shift right one byte from left,or to result */
9238 /*-----------------------------------------------------------------*/
9240 shiftRLeftOrResult (operand * left, int offl,
9241 operand * result, int offr, int shCount)
9243 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
9244 /* shift right accumulator */
9246 /* or with result */
9247 emitcode ("orl", "a,%s",
9248 aopGet (result, offr, FALSE, FALSE, DP2_RESULT_REG));
9249 /* back to result */
9250 aopPut (result, "a", offr);
9254 #ifdef BETTER_LITERAL_SHIFT
9255 /*-----------------------------------------------------------------*/
9256 /* genlshOne - left shift a one byte quantity by known count */
9257 /*-----------------------------------------------------------------*/
9259 genlshOne (operand * result, operand * left, int shCount)
9261 D (emitcode (";", "genlshOne"));
9263 shiftL1Left2Result (left, LSB, result, LSB, shCount);
9267 #ifdef BETTER_LITERAL_SHIFT
9268 /*-----------------------------------------------------------------*/
9269 /* genlshTwo - left shift two bytes by known amount != 0 */
9270 /*-----------------------------------------------------------------*/
9272 genlshTwo (operand * result, operand * left, int shCount)
9276 D (emitcode (";", "genlshTwo"));
9278 size = getDataSize (result);
9280 /* if shCount >= 8 */
9285 _startLazyDPSEvaluation();
9291 _endLazyDPSEvaluation();
9292 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
9293 aopPut (result, zero, LSB);
9297 movLeft2Result (left, LSB, result, MSB16, 0);
9298 aopPut (result, zero, LSB);
9299 _endLazyDPSEvaluation();
9304 aopPut (result, zero, LSB);
9305 _endLazyDPSEvaluation();
9309 /* 1 <= shCount <= 7 */
9313 shiftL1Left2Result (left, LSB, result, LSB, shCount);
9315 shiftL2Left2Result (left, LSB, result, LSB, shCount);
9322 /*-----------------------------------------------------------------*/
9323 /* shiftLLong - shift left one long from left to result */
9324 /* offl = LSB or MSB16 */
9325 /*-----------------------------------------------------------------*/
9327 shiftLLong (operand * left, operand * result, int offr)
9330 int size = AOP_SIZE (result);
9332 if (size >= LSB + offr)
9334 l = aopGet (left, LSB, FALSE, FALSE, NULL);
9336 emitcode ("add", "a,acc");
9337 if (sameRegs (AOP (left), AOP (result)) &&
9338 size >= MSB16 + offr && offr != LSB)
9339 emitcode ("xch", "a,%s",
9340 aopGet (left, LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
9342 aopPut (result, "a", LSB + offr);
9345 if (size >= MSB16 + offr)
9347 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
9349 l = aopGet (left, MSB16, FALSE, FALSE, TRUE);
9352 emitcode ("rlc", "a");
9353 if (sameRegs (AOP (left), AOP (result)) &&
9354 size >= MSB24 + offr && offr != LSB)
9355 emitcode ("xch", "a,%s",
9356 aopGet (left, MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
9358 aopPut (result, "a", MSB16 + offr);
9361 if (size >= MSB24 + offr)
9363 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
9365 l = aopGet (left, MSB24, FALSE, FALSE, NULL);
9368 emitcode ("rlc", "a");
9369 if (sameRegs (AOP (left), AOP (result)) &&
9370 size >= MSB32 + offr && offr != LSB)
9371 emitcode ("xch", "a,%s",
9372 aopGet (left, MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
9374 aopPut (result, "a", MSB24 + offr);
9377 if (size > MSB32 + offr)
9379 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
9381 l = aopGet (left, MSB32, FALSE, FALSE, NULL);
9384 emitcode ("rlc", "a");
9385 aopPut (result, "a", MSB32 + offr);
9388 aopPut (result, zero, LSB);
9394 /*-----------------------------------------------------------------*/
9395 /* genlshFour - shift four byte by a known amount != 0 */
9396 /*-----------------------------------------------------------------*/
9398 genlshFour (operand * result, operand * left, int shCount)
9402 D (emitcode (";", "genlshFour"));
9404 size = AOP_SIZE (result);
9406 /* if shifting more that 3 bytes */
9411 /* lowest order of left goes to the highest
9412 order of the destination */
9413 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
9415 movLeft2Result (left, LSB, result, MSB32, 0);
9416 aopPut (result, zero, LSB);
9417 aopPut (result, zero, MSB16);
9418 aopPut (result, zero, MSB24);
9422 /* more than two bytes */
9423 else if (shCount >= 16)
9425 /* lower order two bytes goes to higher order two bytes */
9427 /* if some more remaining */
9429 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
9432 movLeft2Result (left, MSB16, result, MSB32, 0);
9433 movLeft2Result (left, LSB, result, MSB24, 0);
9435 aopPut (result, zero, MSB16);
9436 aopPut (result, zero, LSB);
9440 /* if more than 1 byte */
9441 else if (shCount >= 8)
9443 /* lower order three bytes goes to higher order three bytes */
9448 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
9450 movLeft2Result (left, LSB, result, MSB16, 0);
9456 movLeft2Result (left, MSB24, result, MSB32, 0);
9457 movLeft2Result (left, MSB16, result, MSB24, 0);
9458 movLeft2Result (left, LSB, result, MSB16, 0);
9459 aopPut (result, zero, LSB);
9461 else if (shCount == 1)
9462 shiftLLong (left, result, MSB16);
9465 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
9466 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
9467 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
9468 aopPut (result, zero, LSB);
9473 /* 1 <= shCount <= 7 */
9474 else if (shCount <= 2)
9476 shiftLLong (left, result, LSB);
9478 shiftLLong (result, result, LSB);
9480 /* 3 <= shCount <= 7, optimize */
9483 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
9484 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
9485 shiftL2Left2Result (left, LSB, result, LSB, shCount);
9490 #ifdef BETTER_LITERAL_SHIFT
9491 /*-----------------------------------------------------------------*/
9492 /* genLeftShiftLiteral - left shifting by known count */
9493 /*-----------------------------------------------------------------*/
9495 genLeftShiftLiteral (operand * left,
9500 int shCount = (int) ulFromVal (AOP (right)->aopu.aop_lit);
9503 size = getSize (operandType (result));
9505 D (emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
9507 /* We only handle certain easy cases so far. */
9509 && (shCount < (size * 8))
9513 D(emitcode (";", "genLeftShiftLiteral wimping out"););
9517 freeAsmop (right, NULL, ic, TRUE);
9519 aopOp(left, ic, FALSE, FALSE);
9520 aopOp(result, ic, FALSE, AOP_USESDPTR(left));
9523 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
9525 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
9526 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
9528 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
9531 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
9533 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
9534 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
9536 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
9542 emitcode ("; shift left ", "result %d, left %d", size,
9546 /* I suppose that the left size >= result size */
9549 _startLazyDPSEvaluation();
9552 movLeft2Result (left, size, result, size, 0);
9554 _endLazyDPSEvaluation();
9556 else if (shCount >= (size * 8))
9558 _startLazyDPSEvaluation();
9561 aopPut (result, zero, size);
9563 _endLazyDPSEvaluation();
9570 genlshOne (result, left, shCount);
9574 genlshTwo (result, left, shCount);
9578 genlshFour (result, left, shCount);
9582 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9583 "*** ack! mystery literal shift!\n");
9587 freeAsmop (result, NULL, ic, TRUE);
9588 freeAsmop (left, NULL, ic, TRUE);
9593 /*-----------------------------------------------------------------*/
9594 /* genLeftShift - generates code for left shifting */
9595 /*-----------------------------------------------------------------*/
9597 genLeftShift (iCode * ic)
9599 operand *left, *right, *result;
9602 symbol *tlbl, *tlbl1;
9605 D (emitcode (";", "genLeftShift"));
9607 right = IC_RIGHT (ic);
9608 left = IC_LEFT (ic);
9609 result = IC_RESULT (ic);
9611 aopOp (right, ic, FALSE, FALSE);
9614 #ifdef BETTER_LITERAL_SHIFT
9615 /* if the shift count is known then do it
9616 as efficiently as possible */
9617 if (AOP_TYPE (right) == AOP_LIT)
9619 if (genLeftShiftLiteral (left, right, result, ic))
9626 /* shift count is unknown then we have to form
9627 a loop get the loop count in B : Note: we take
9628 only the lower order byte since shifting
9629 more that 32 bits make no sense anyway, ( the
9630 largest size of an object can be only 32 bits ) */
9633 if (AOP_TYPE (right) == AOP_LIT)
9635 /* Really should be handled by genLeftShiftLiteral,
9636 * but since I'm too lazy to fix that today, at least we can make
9637 * some small improvement.
9639 emitcode("mov", "b,#!constbyte",
9640 ((int) ulFromVal (AOP (right)->aopu.aop_lit)) + 1);
9644 MOVB (aopGet (right, 0, FALSE, FALSE, "b"));
9645 emitcode ("inc", "b");
9647 freeAsmop (right, NULL, ic, TRUE);
9648 aopOp (left, ic, FALSE, FALSE);
9649 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9651 /* now move the left to the result if they are not the same */
9652 if (!sameRegs (AOP (left), AOP (result)) &&
9653 AOP_SIZE (result) > 1)
9656 size = AOP_SIZE (result);
9658 _startLazyDPSEvaluation ();
9661 l = aopGet (left, offset, FALSE, TRUE, NULL);
9662 if (*l == '@' && (IS_AOP_PREG (result)))
9665 emitcode ("mov", "a,%s", l);
9666 aopPut (result, "a", offset);
9669 aopPut (result, l, offset);
9672 _endLazyDPSEvaluation ();
9675 tlbl = newiTempLabel (NULL);
9676 size = AOP_SIZE (result);
9678 tlbl1 = newiTempLabel (NULL);
9680 /* if it is only one byte then */
9683 symbol *tlbl1 = newiTempLabel (NULL);
9685 l = aopGet (left, 0, FALSE, FALSE, NULL);
9687 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9689 emitcode ("add", "a,acc");
9691 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9693 aopPut (result, "a", 0);
9697 reAdjustPreg (AOP (result));
9699 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9701 l = aopGet (result, offset, FALSE, FALSE, NULL);
9703 emitcode ("add", "a,acc");
9704 aopPut (result, "a", offset++);
9705 _startLazyDPSEvaluation ();
9708 l = aopGet (result, offset, FALSE, FALSE, NULL);
9710 emitcode ("rlc", "a");
9711 aopPut (result, "a", offset++);
9713 _endLazyDPSEvaluation ();
9714 reAdjustPreg (AOP (result));
9717 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9720 freeAsmop (result, NULL, ic, TRUE);
9721 freeAsmop (left, NULL, ic, TRUE);
9724 #ifdef BETTER_LITERAL_SHIFT
9725 /*-----------------------------------------------------------------*/
9726 /* genrshOne - right shift a one byte quantity by known count */
9727 /*-----------------------------------------------------------------*/
9729 genrshOne (operand * result, operand * left,
9730 int shCount, int sign)
9732 D (emitcode (";", "genrshOne"));
9734 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9738 #ifdef BETTER_LITERAL_SHIFT
9739 /*-----------------------------------------------------------------*/
9740 /* genrshTwo - right shift two bytes by known amount != 0 */
9741 /*-----------------------------------------------------------------*/
9743 genrshTwo (operand * result, operand * left,
9744 int shCount, int sign)
9746 D (emitcode (";", "genrshTwo"));
9748 /* if shCount >= 8 */
9752 _startLazyDPSEvaluation();
9754 shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
9756 movLeft2Result (left, MSB16, result, LSB, sign);
9757 addSign (result, MSB16, sign);
9758 _endLazyDPSEvaluation();
9761 /* 1 <= shCount <= 7 */
9763 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9767 /*-----------------------------------------------------------------*/
9768 /* shiftRLong - shift right one long from left to result */
9769 /* offl = LSB or MSB16 */
9770 /*-----------------------------------------------------------------*/
9772 shiftRLong (operand * left, int offl,
9773 operand * result, int sign)
9775 bool overlapping = regsInCommon (left, result) || operandsEqu(left, result);
9777 if (overlapping && offl>1)
9779 // we are in big trouble, but this shouldn't happen
9780 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9783 MOVA (aopGet (left, MSB32, FALSE, FALSE, NULL));
9790 emitcode ("rlc", "a");
9791 emitcode ("subb", "a,acc");
9792 emitcode ("xch", "a,%s",
9793 aopGet(left, MSB32, FALSE, FALSE, DP2_RESULT_REG));
9797 aopPut (result, zero, MSB32);
9803 emitcode ("clr", "c");
9807 emitcode ("mov", "c,acc.7");
9810 emitcode ("rrc", "a");
9812 if (overlapping && offl==MSB16)
9814 emitcode ("xch", "a,%s", aopGet (left, MSB24, FALSE, FALSE, DP2_RESULT_REG));
9818 aopPut (result, "a", MSB32 - offl);
9819 MOVA (aopGet (left, MSB24, FALSE, FALSE, NULL));
9822 emitcode ("rrc", "a");
9824 if (overlapping && offl==MSB16)
9826 emitcode ("xch", "a,%s", aopGet (left, MSB16, FALSE, FALSE, DP2_RESULT_REG));
9830 aopPut (result, "a", MSB24 - offl);
9831 MOVA (aopGet (left, MSB16, FALSE, FALSE, NULL));
9834 emitcode ("rrc", "a");
9837 aopPut (result, "a", MSB16 - offl);
9841 if (overlapping && offl==MSB16)
9843 emitcode ("xch", "a,%s", aopGet (left, LSB, FALSE, FALSE, DP2_RESULT_REG));
9847 aopPut (result, "a", MSB16 - offl);
9848 MOVA (aopGet (left, LSB, FALSE, FALSE, NULL));
9850 emitcode ("rrc", "a");
9851 aopPut (result, "a", LSB);
9855 /*-----------------------------------------------------------------*/
9856 /* genrshFour - shift four byte by a known amount != 0 */
9857 /*-----------------------------------------------------------------*/
9859 genrshFour (operand * result, operand * left,
9860 int shCount, int sign)
9862 D (emitcode (";", "genrshFour"));
9864 /* if shifting more that 3 bytes */
9868 _startLazyDPSEvaluation();
9870 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9872 movLeft2Result (left, MSB32, result, LSB, sign);
9873 addSign (result, MSB16, sign);
9874 _endLazyDPSEvaluation();
9876 else if (shCount >= 16)
9879 _startLazyDPSEvaluation();
9881 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9884 movLeft2Result (left, MSB24, result, LSB, 0);
9885 movLeft2Result (left, MSB32, result, MSB16, sign);
9887 addSign (result, MSB24, sign);
9888 _endLazyDPSEvaluation();
9890 else if (shCount >= 8)
9893 _startLazyDPSEvaluation();
9896 shiftRLong (left, MSB16, result, sign);
9898 else if (shCount == 0)
9900 movLeft2Result (left, MSB16, result, LSB, 0);
9901 movLeft2Result (left, MSB24, result, MSB16, 0);
9902 movLeft2Result (left, MSB32, result, MSB24, sign);
9903 addSign (result, MSB32, sign);
9907 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9908 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9909 /* the last shift is signed */
9910 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9911 addSign (result, MSB32, sign);
9913 _endLazyDPSEvaluation();
9917 /* 1 <= shCount <= 7 */
9920 shiftRLong (left, LSB, result, sign);
9922 shiftRLong (result, LSB, result, sign);
9926 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9927 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9928 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9933 #ifdef BETTER_LITERAL_SHIFT
9934 /*-----------------------------------------------------------------*/
9935 /* genRightShiftLiteral - right shifting by known count */
9936 /*-----------------------------------------------------------------*/
9938 genRightShiftLiteral (operand * left,
9944 int shCount = (int) ulFromVal (AOP (right)->aopu.aop_lit);
9947 size = getSize (operandType (result));
9949 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
9951 /* We only handle certain easy cases so far. */
9953 && (shCount < (size * 8))
9958 D(emitcode (";", "genRightShiftLiteral wimping out"););
9962 freeAsmop (right, NULL, ic, TRUE);
9964 aopOp (left, ic, FALSE, FALSE);
9965 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9968 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9972 /* test the LEFT size !!! */
9974 /* I suppose that the left size >= result size */
9977 size = getDataSize (result);
9978 _startLazyDPSEvaluation();
9980 movLeft2Result (left, size, result, size, 0);
9981 _endLazyDPSEvaluation();
9983 else if (shCount >= (size * 8))
9987 /* get sign in acc.7 */
9988 MOVA (aopGet (left, size - 1, FALSE, FALSE, NULL));
9990 addSign (result, LSB, sign);
9997 genrshOne (result, left, shCount, sign);
10001 genrshTwo (result, left, shCount, sign);
10005 genrshFour (result, left, shCount, sign);
10012 freeAsmop (result, NULL, ic, TRUE);
10013 freeAsmop (left, NULL, ic, TRUE);
10019 /*-----------------------------------------------------------------*/
10020 /* genSignedRightShift - right shift of signed number */
10021 /*-----------------------------------------------------------------*/
10023 genSignedRightShift (iCode * ic)
10025 operand *right, *left, *result;
10028 symbol *tlbl, *tlbl1;
10031 D (emitcode (";", "genSignedRightShift"));
10033 /* we do it the hard way put the shift count in b
10034 and loop thru preserving the sign */
10036 right = IC_RIGHT (ic);
10037 left = IC_LEFT (ic);
10038 result = IC_RESULT (ic);
10040 aopOp (right, ic, FALSE, FALSE);
10042 #ifdef BETTER_LITERAL_SHIFT
10043 if (AOP_TYPE (right) == AOP_LIT)
10045 if (genRightShiftLiteral (left, right, result, ic, 1))
10051 /* shift count is unknown then we have to form
10052 a loop get the loop count in B : Note: we take
10053 only the lower order byte since shifting
10054 more that 32 bits make no sense anyway, ( the
10055 largest size of an object can be only 32 bits ) */
10057 pushedB = pushB ();
10058 if (AOP_TYPE (right) == AOP_LIT)
10060 /* Really should be handled by genRightShiftLiteral,
10061 * but since I'm too lazy to fix that today, at least we can make
10062 * some small improvement.
10064 emitcode("mov", "b,#!constbyte",
10065 ((int) ulFromVal (AOP (right)->aopu.aop_lit)) + 1);
10069 MOVB (aopGet (right, 0, FALSE, FALSE, "b"));
10070 emitcode ("inc", "b");
10072 freeAsmop (right, NULL, ic, TRUE);
10073 aopOp (left, ic, FALSE, FALSE);
10074 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
10076 /* now move the left to the result if they are not the
10078 if (!sameRegs (AOP (left), AOP (result)) &&
10079 AOP_SIZE (result) > 1)
10082 size = AOP_SIZE (result);
10084 _startLazyDPSEvaluation ();
10087 l = aopGet (left, offset, FALSE, TRUE, NULL);
10088 if (*l == '@' && IS_AOP_PREG (result))
10091 emitcode ("mov", "a,%s", l);
10092 aopPut (result, "a", offset);
10095 aopPut (result, l, offset);
10098 _endLazyDPSEvaluation ();
10101 /* mov the highest order bit to OVR */
10102 tlbl = newiTempLabel (NULL);
10103 tlbl1 = newiTempLabel (NULL);
10105 size = AOP_SIZE (result);
10107 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
10108 emitcode ("rlc", "a");
10109 emitcode ("mov", "ov,c");
10110 /* if it is only one byte then */
10113 l = aopGet (left, 0, FALSE, FALSE, NULL);
10115 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
10117 emitcode ("mov", "c,ov");
10118 emitcode ("rrc", "a");
10120 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
10122 aopPut (result, "a", 0);
10126 reAdjustPreg (AOP (result));
10127 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
10129 emitcode ("mov", "c,ov");
10130 _startLazyDPSEvaluation ();
10133 l = aopGet (result, offset, FALSE, FALSE, NULL);
10135 emitcode ("rrc", "a");
10136 aopPut (result, "a", offset--);
10138 _endLazyDPSEvaluation ();
10139 reAdjustPreg (AOP (result));
10141 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
10145 freeAsmop (result, NULL, ic, TRUE);
10146 freeAsmop (left, NULL, ic, TRUE);
10149 /*-----------------------------------------------------------------*/
10150 /* genRightShift - generate code for right shifting */
10151 /*-----------------------------------------------------------------*/
10153 genRightShift (iCode * ic)
10155 operand *right, *left, *result;
10159 symbol *tlbl, *tlbl1;
10162 D (emitcode (";", "genRightShift"));
10164 /* if signed then we do it the hard way preserve the
10165 sign bit moving it inwards */
10166 letype = getSpec (operandType (IC_LEFT (ic)));
10168 if (!SPEC_USIGN (letype))
10170 genSignedRightShift (ic);
10174 /* signed & unsigned types are treated the same : i.e. the
10175 signed is NOT propagated inwards : quoting from the
10176 ANSI - standard : "for E1 >> E2, is equivalent to division
10177 by 2**E2 if unsigned or if it has a non-negative value,
10178 otherwise the result is implementation defined ", MY definition
10179 is that the sign does not get propagated */
10181 right = IC_RIGHT (ic);
10182 left = IC_LEFT (ic);
10183 result = IC_RESULT (ic);
10185 aopOp (right, ic, FALSE, FALSE);
10187 #ifdef BETTER_LITERAL_SHIFT
10188 /* if the shift count is known then do it
10189 as efficiently as possible */
10190 if (AOP_TYPE (right) == AOP_LIT)
10192 if (genRightShiftLiteral (left, right, result, ic, 0))
10199 /* shift count is unknown then we have to form
10200 a loop get the loop count in B : Note: we take
10201 only the lower order byte since shifting
10202 more that 32 bits make no sense anyway, ( the
10203 largest size of an object can be only 32 bits ) */
10205 pushedB = pushB ();
10206 if (AOP_TYPE (right) == AOP_LIT)
10208 /* Really should be handled by genRightShiftLiteral,
10209 * but since I'm too lazy to fix that today, at least we can make
10210 * some small improvement.
10212 emitcode("mov", "b,#!constbyte",
10213 ((int) ulFromVal (AOP (right)->aopu.aop_lit)) + 1);
10217 MOVB (aopGet (right, 0, FALSE, FALSE, "b"));
10218 emitcode ("inc", "b");
10220 freeAsmop (right, NULL, ic, TRUE);
10221 aopOp (left, ic, FALSE, FALSE);
10222 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
10224 /* now move the left to the result if they are not the
10226 if (!sameRegs (AOP (left), AOP (result)) &&
10227 AOP_SIZE (result) > 1)
10229 size = AOP_SIZE (result);
10231 _startLazyDPSEvaluation ();
10234 l = aopGet (left, offset, FALSE, TRUE, NULL);
10235 if (*l == '@' && IS_AOP_PREG (result))
10238 emitcode ("mov", "a,%s", l);
10239 aopPut (result, "a", offset);
10242 aopPut (result, l, offset);
10245 _endLazyDPSEvaluation ();
10248 tlbl = newiTempLabel (NULL);
10249 tlbl1 = newiTempLabel (NULL);
10250 size = AOP_SIZE (result);
10253 /* if it is only one byte then */
10256 l = aopGet (left, 0, FALSE, FALSE, NULL);
10258 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
10261 emitcode ("rrc", "a");
10263 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
10265 aopPut (result, "a", 0);
10269 reAdjustPreg (AOP (result));
10270 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
10273 _startLazyDPSEvaluation ();
10276 l = aopGet (result, offset, FALSE, FALSE, NULL);
10278 emitcode ("rrc", "a");
10279 aopPut (result, "a", offset--);
10281 _endLazyDPSEvaluation ();
10282 reAdjustPreg (AOP (result));
10285 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
10289 freeAsmop (result, NULL, ic, TRUE);
10290 freeAsmop (left, NULL, ic, TRUE);
10293 /*-----------------------------------------------------------------*/
10294 /* emitPtrByteGet - emits code to get a byte into A through a */
10295 /* pointer register (R0, R1, or DPTR). The */
10296 /* original value of A can be preserved in B. */
10297 /*-----------------------------------------------------------------*/
10299 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
10306 emitcode ("mov", "b,a");
10307 emitcode ("mov", "a,@%s", rname);
10312 emitcode ("mov", "b,a");
10313 emitcode ("movx", "a,@%s", rname);
10318 emitcode ("mov", "b,a");
10319 emitcode ("movx", "a,@dptr");
10324 emitcode ("mov", "b,a");
10325 emitcode ("clr", "a");
10326 emitcode ("movc", "a,@a+dptr");
10332 emitcode ("push", "b");
10333 emitcode ("push", "acc");
10335 emitcode ("lcall", "__gptrget");
10337 emitcode ("pop", "b");
10342 /*-----------------------------------------------------------------*/
10343 /* emitPtrByteSet - emits code to set a byte from src through a */
10344 /* pointer register (R0, R1, or DPTR). */
10345 /*-----------------------------------------------------------------*/
10347 emitPtrByteSet (char *rname, int p_type, char *src)
10356 emitcode ("mov", "@%s,a", rname);
10359 emitcode ("mov", "@%s,%s", rname, src);
10364 emitcode ("movx", "@%s,a", rname);
10369 emitcode ("movx", "@dptr,a");
10374 emitcode ("lcall", "__gptrput");
10379 /*-----------------------------------------------------------------*/
10380 /* genUnpackBits - generates code for unpacking bits */
10381 /*-----------------------------------------------------------------*/
10383 genUnpackBits (operand * result, char *rname, int ptype)
10385 int offset = 0; /* result byte offset */
10386 int rsize; /* result size */
10387 int rlen = 0; /* remaining bitfield length */
10388 sym_link *etype; /* bitfield type information */
10389 int blen; /* bitfield length */
10390 int bstr; /* bitfield starting bit within byte */
10392 D(emitcode (";", "genUnpackBits"));
10394 etype = getSpec (operandType (result));
10395 rsize = getSize (operandType (result));
10396 blen = SPEC_BLEN (etype);
10397 bstr = SPEC_BSTR (etype);
10399 /* If the bitfield length is less than a byte */
10402 emitPtrByteGet (rname, ptype, FALSE);
10404 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
10405 if (!SPEC_USIGN (etype))
10407 /* signed bitfield */
10408 symbol *tlbl = newiTempLabel (NULL);
10410 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
10411 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
10414 aopPut (result, "a", offset++);
10418 /* Bit field did not fit in a byte. Copy all
10419 but the partial byte at the end. */
10420 for (rlen=blen;rlen>=8;rlen-=8)
10422 emitPtrByteGet (rname, ptype, FALSE);
10423 aopPut (result, "a", offset++);
10425 emitcode ("inc", "%s", rname);
10428 /* Handle the partial byte at the end */
10431 emitPtrByteGet (rname, ptype, FALSE);
10432 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
10433 if (!SPEC_USIGN (etype))
10435 /* signed bitfield */
10436 symbol *tlbl = newiTempLabel (NULL);
10438 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
10439 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
10442 aopPut (result, "a", offset++);
10446 if (offset < rsize)
10450 if (SPEC_USIGN (etype))
10454 /* signed bitfield: sign extension with 0x00 or 0xff */
10455 emitcode ("rlc", "a");
10456 emitcode ("subb", "a,acc");
10462 aopPut (result, source, offset++);
10467 /*-----------------------------------------------------------------*/
10468 /* genDataPointerGet - generates code when ptr offset is known */
10469 /*-----------------------------------------------------------------*/
10471 genDataPointerGet (operand * left,
10477 int size, offset = 0;
10478 aopOp (result, ic, TRUE, FALSE);
10480 /* get the string representation of the name */
10481 l = aopGet (left, 0, FALSE, TRUE, NULL);
10482 size = AOP_SIZE (result);
10483 _startLazyDPSEvaluation ();
10488 SNPRINTF (buffer, sizeof(buffer),
10489 "(%s + %d)", l + 1, offset);
10493 SNPRINTF (buffer, sizeof(buffer),
10496 aopPut (result, buffer, offset++);
10498 _endLazyDPSEvaluation ();
10500 freeAsmop (result, NULL, ic, TRUE);
10501 freeAsmop (left, NULL, ic, TRUE);
10504 /*-----------------------------------------------------------------*/
10505 /* genNearPointerGet - emitcode for near pointer fetch */
10506 /*-----------------------------------------------------------------*/
10508 genNearPointerGet (operand * left,
10516 sym_link *rtype, *retype, *letype;
10517 sym_link *ltype = operandType (left);
10520 rtype = operandType (result);
10521 retype = getSpec (rtype);
10522 letype = getSpec (ltype);
10524 aopOp (left, ic, FALSE, FALSE);
10526 /* if left is rematerialisable and
10527 result is not bitfield variable type and
10528 the left is pointer to data space i.e
10529 lower 128 bytes of space */
10530 if (AOP_TYPE (left) == AOP_IMMD &&
10531 !IS_BITFIELD (retype) &&
10532 !IS_BITFIELD (letype) &&
10533 DCL_TYPE (ltype) == POINTER)
10535 genDataPointerGet (left, result, ic);
10539 /* if the value is already in a pointer register
10540 then don't need anything more */
10541 if (!AOP_INPREG (AOP (left)))
10543 /* otherwise get a free pointer register */
10544 aop = newAsmop (0);
10545 preg = getFreePtr (ic, &aop, FALSE);
10546 emitcode ("mov", "%s,%s",
10548 aopGet (left, 0, FALSE, TRUE, DP2_RESULT_REG));
10549 rname = preg->name;
10552 rname = aopGet (left, 0, FALSE, FALSE, DP2_RESULT_REG);
10554 freeAsmop (left, NULL, ic, TRUE);
10555 aopOp (result, ic, FALSE, FALSE);
10557 /* if bitfield then unpack the bits */
10558 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10559 genUnpackBits (result, rname, POINTER);
10562 /* we have can just get the values */
10563 int size = AOP_SIZE (result);
10568 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
10571 emitcode ("mov", "a,@%s", rname);
10572 aopPut (result, "a", offset);
10576 SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
10577 aopPut (result, buffer, offset);
10581 emitcode ("inc", "%s", rname);
10585 /* now some housekeeping stuff */
10586 if (aop) /* we had to allocate for this iCode */
10588 if (pi) { /* post increment present */
10589 aopPut (left, rname, 0);
10591 freeAsmop (NULL, aop, ic, TRUE);
10595 /* we did not allocate which means left
10596 already in a pointer register, then
10597 if size > 0 && this could be used again
10598 we have to point it back to where it
10600 if (AOP_SIZE (result) > 1 &&
10601 !OP_SYMBOL (left)->remat &&
10602 (OP_SYMBOL (left)->liveTo > ic->seq ||
10606 int size = AOP_SIZE (result) - 1;
10608 emitcode ("dec", "%s", rname);
10613 freeAsmop (result, NULL, ic, TRUE);
10614 if (pi) pi->generated = 1;
10617 /*-----------------------------------------------------------------*/
10618 /* genPagedPointerGet - emitcode for paged pointer fetch */
10619 /*-----------------------------------------------------------------*/
10621 genPagedPointerGet (operand * left,
10629 sym_link *rtype, *retype, *letype;
10631 rtype = operandType (result);
10632 retype = getSpec (rtype);
10633 letype = getSpec (operandType (left));
10634 aopOp (left, ic, FALSE, FALSE);
10636 /* if the value is already in a pointer register
10637 then don't need anything more */
10638 if (!AOP_INPREG (AOP (left)))
10640 /* otherwise get a free pointer register */
10641 aop = newAsmop (0);
10642 preg = getFreePtr (ic, &aop, FALSE);
10643 emitcode ("mov", "%s,%s",
10645 aopGet (left, 0, FALSE, TRUE, NULL));
10646 rname = preg->name;
10649 rname = aopGet (left, 0, FALSE, FALSE, NULL);
10651 freeAsmop (left, NULL, ic, TRUE);
10652 aopOp (result, ic, FALSE, FALSE);
10654 /* if bitfield then unpack the bits */
10655 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10656 genUnpackBits (result, rname, PPOINTER);
10659 /* we have can just get the values */
10660 int size = AOP_SIZE (result);
10666 emitcode ("movx", "a,@%s", rname);
10667 aopPut (result, "a", offset);
10672 emitcode ("inc", "%s", rname);
10676 /* now some housekeeping stuff */
10677 if (aop) /* we had to allocate for this iCode */
10680 aopPut (left, rname, 0);
10681 freeAsmop (NULL, aop, ic, TRUE);
10685 /* we did not allocate which means left
10686 already in a pointer register, then
10687 if size > 0 && this could be used again
10688 we have to point it back to where it
10690 if (AOP_SIZE (result) > 1 &&
10691 !OP_SYMBOL (left)->remat &&
10692 (OP_SYMBOL (left)->liveTo > ic->seq ||
10696 int size = AOP_SIZE (result) - 1;
10698 emitcode ("dec", "%s", rname);
10703 freeAsmop (result, NULL, ic, TRUE);
10704 if (pi) pi->generated = 1;
10707 /*-----------------------------------------------------------------*/
10708 /* genFarPointerGet - get value from far space */
10709 /*-----------------------------------------------------------------*/
10711 genFarPointerGet (operand * left,
10712 operand * result, iCode * ic, iCode *pi)
10714 int size, offset, dopi=1;
10715 sym_link *retype = getSpec (operandType (result));
10716 sym_link *letype = getSpec (operandType (left));
10717 D (emitcode (";", "genFarPointerGet"););
10719 aopOp (left, ic, FALSE, FALSE);
10721 /* if the operand is already in dptr
10722 then we do nothing else we move the value to dptr */
10723 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
10725 /* if this is rematerializable */
10726 if (AOP_TYPE (left) == AOP_IMMD)
10728 emitcode ("mov", "dptr,%s", aopGet (left, 0, TRUE, FALSE, NULL));
10732 /* we need to get it byte by byte */
10733 _startLazyDPSEvaluation ();
10734 if (AOP_TYPE (left) != AOP_DPTR)
10736 emitcode ("mov", "dpl,%s", aopGet (left, 0, FALSE, FALSE, NULL));
10737 emitcode ("mov", "dph,%s", aopGet (left, 1, FALSE, FALSE, NULL));
10738 if (options.model == MODEL_FLAT24)
10739 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10743 /* We need to generate a load to DPTR indirect through DPTR. */
10744 D (emitcode (";", "genFarPointerGet -- indirection special case."););
10745 emitcode ("push", "%s", aopGet (left, 0, FALSE, TRUE, NULL));
10746 emitcode ("push", "%s", aopGet (left, 1, FALSE, TRUE, NULL));
10747 if (options.model == MODEL_FLAT24)
10748 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10749 emitcode ("pop", "dph");
10750 emitcode ("pop", "dpl");
10753 _endLazyDPSEvaluation ();
10756 /* so dptr now contains the address */
10757 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10759 /* if bit then unpack */
10760 if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
10761 if (AOP_INDPTRn(left)) {
10762 genSetDPTR(AOP(left)->aopu.dptr);
10764 genUnpackBits (result, "dptr", FPOINTER);
10765 if (AOP_INDPTRn(left)) {
10770 size = AOP_SIZE (result);
10773 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10775 genSetDPTR(AOP(left)->aopu.dptr);
10776 emitcode ("movx", "a,@dptr");
10777 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10778 emitcode ("inc", "dptr");
10780 aopPut (result, "a", offset++);
10783 _startLazyDPSEvaluation ();
10785 if (AOP_INDPTRn(left)) {
10786 genSetDPTR(AOP(left)->aopu.dptr);
10792 emitcode ("movx", "a,@dptr");
10793 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10794 emitcode ("inc", "dptr");
10796 aopPut (result, "a", offset++);
10798 _endLazyDPSEvaluation ();
10801 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10802 if (!AOP_INDPTRn(left)) {
10803 _startLazyDPSEvaluation ();
10804 aopPut (left, "dpl", 0);
10805 aopPut (left, "dph", 1);
10806 if (options.model == MODEL_FLAT24)
10807 aopPut (left, "dpx", 2);
10808 _endLazyDPSEvaluation ();
10811 } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) &&
10812 AOP_SIZE(result) > 1 &&
10814 (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
10816 size = AOP_SIZE (result) - 1;
10817 if (AOP_INDPTRn(left)) {
10818 genSetDPTR(AOP(left)->aopu.dptr);
10820 while (size--) emitcode ("lcall","__decdptr");
10821 if (AOP_INDPTRn(left)) {
10826 freeAsmop (result, NULL, ic, TRUE);
10827 freeAsmop (left, NULL, ic, TRUE);
10830 /*-----------------------------------------------------------------*/
10831 /* genCodePointerGet - get value from code space */
10832 /*-----------------------------------------------------------------*/
10834 genCodePointerGet (operand * left,
10835 operand * result, iCode * ic, iCode *pi)
10837 int size, offset, dopi=1;
10838 sym_link *retype = getSpec (operandType (result));
10840 aopOp (left, ic, FALSE, FALSE);
10842 /* if the operand is already in dptr
10843 then we do nothing else we move the value to dptr */
10844 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
10846 /* if this is rematerializable */
10847 if (AOP_TYPE (left) == AOP_IMMD)
10849 emitcode ("mov", "dptr,%s", aopGet (left, 0, TRUE, FALSE, NULL));
10852 { /* we need to get it byte by byte */
10853 _startLazyDPSEvaluation ();
10854 if (AOP_TYPE (left) != AOP_DPTR)
10856 emitcode ("mov", "dpl,%s", aopGet (left, 0, FALSE, FALSE, NULL));
10857 emitcode ("mov", "dph,%s", aopGet (left, 1, FALSE, FALSE, NULL));
10858 if (options.model == MODEL_FLAT24)
10859 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10863 /* We need to generate a load to DPTR indirect through DPTR. */
10864 D (emitcode (";", "gencodePointerGet -- indirection special case."););
10865 emitcode ("push", "%s", aopGet (left, 0, FALSE, TRUE, NULL));
10866 emitcode ("push", "%s", aopGet (left, 1, FALSE, TRUE, NULL));
10867 if (options.model == MODEL_FLAT24)
10868 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10869 emitcode ("pop", "dph");
10870 emitcode ("pop", "dpl");
10873 _endLazyDPSEvaluation ();
10876 /* so dptr now contains the address */
10877 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10879 /* if bit then unpack */
10880 if (IS_BITFIELD (retype)) {
10881 if (AOP_INDPTRn(left)) {
10882 genSetDPTR(AOP(left)->aopu.dptr);
10884 genUnpackBits (result, "dptr", CPOINTER);
10885 if (AOP_INDPTRn(left)) {
10890 size = AOP_SIZE (result);
10892 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10894 genSetDPTR(AOP(left)->aopu.dptr);
10895 emitcode ("clr", "a");
10896 emitcode ("movc", "a,@a+dptr");
10897 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10898 emitcode ("inc", "dptr");
10900 aopPut (result, "a", offset++);
10903 _startLazyDPSEvaluation ();
10906 if (AOP_INDPTRn(left)) {
10907 genSetDPTR(AOP(left)->aopu.dptr);
10913 emitcode ("clr", "a");
10914 emitcode ("movc", "a,@a+dptr");
10915 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10916 emitcode ("inc", "dptr");
10917 aopPut (result, "a", offset++);
10919 _endLazyDPSEvaluation ();
10922 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10923 if (!AOP_INDPTRn(left)) {
10924 _startLazyDPSEvaluation ();
10926 aopPut (left, "dpl", 0);
10927 aopPut (left, "dph", 1);
10928 if (options.model == MODEL_FLAT24)
10929 aopPut (left, "dpx", 2);
10931 _endLazyDPSEvaluation ();
10934 } else if (IS_SYMOP(left) &&
10935 (OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
10936 AOP_SIZE(result) > 1 &&
10937 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10939 size = AOP_SIZE (result) - 1;
10940 if (AOP_INDPTRn(left)) {
10941 genSetDPTR(AOP(left)->aopu.dptr);
10943 while (size--) emitcode ("lcall","__decdptr");
10944 if (AOP_INDPTRn(left)) {
10949 freeAsmop (result, NULL, ic, TRUE);
10950 freeAsmop (left, NULL, ic, TRUE);
10953 /*-----------------------------------------------------------------*/
10954 /* genGenPointerGet - get value from generic pointer space */
10955 /*-----------------------------------------------------------------*/
10957 genGenPointerGet (operand * left,
10958 operand * result, iCode * ic, iCode * pi)
10962 sym_link *retype = getSpec (operandType (result));
10963 sym_link *letype = getSpec (operandType (left));
10965 D (emitcode (";", "genGenPointerGet"));
10967 aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
10969 pushedB = pushB ();
10970 /* if the operand is already in dptr
10971 then we do nothing else we move the value to dptr */
10972 if (AOP_TYPE (left) != AOP_STR)
10974 /* if this is rematerializable */
10975 if (AOP_TYPE (left) == AOP_IMMD)
10977 emitcode ("mov", "dptr,%s", aopGet (left, 0, TRUE, FALSE, NULL));
10978 if (AOP(left)->aopu.aop_immd.from_cast_remat)
10980 MOVB (aopGet (left, AOP_SIZE(left)-1, FALSE, FALSE, NULL));
10984 emitcode ("mov", "b,#%d", pointerCode (retype));
10988 { /* we need to get it byte by byte */
10989 _startLazyDPSEvaluation ();
10990 emitcode ("mov", "dpl,%s", aopGet (left,0,FALSE,FALSE,NULL));
10991 emitcode ("mov", "dph,%s", aopGet (left,1,FALSE,FALSE,NULL));
10992 if (options.model == MODEL_FLAT24) {
10993 emitcode ("mov", "dpx,%s", aopGet (left,2,FALSE,FALSE,NULL));
10994 emitcode ("mov", "b,%s", aopGet (left,3,FALSE,FALSE,NULL));
10996 emitcode ("mov", "b,%s", aopGet (left,2,FALSE,FALSE,NULL));
10998 _endLazyDPSEvaluation ();
11002 /* so dptr-b now contains the address */
11003 aopOp (result, ic, FALSE, TRUE);
11005 /* if bit then unpack */
11006 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11008 genUnpackBits (result, "dptr", GPOINTER);
11012 size = AOP_SIZE (result);
11019 // Get two bytes at a time, results in _AP & A.
11020 // dptr will be incremented ONCE by __gptrgetWord.
11022 // Note: any change here must be coordinated
11023 // with the implementation of __gptrgetWord
11024 // in device/lib/_gptrget.c
11025 emitcode ("lcall", "__gptrgetWord");
11026 aopPut (result, "a", offset++);
11027 aopPut (result, DP2_RESULT_REG, offset++);
11032 // Only one byte to get.
11033 emitcode ("lcall", "__gptrget");
11034 aopPut (result, "a", offset++);
11037 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
11039 emitcode ("inc", "dptr");
11044 if (pi && AOP_TYPE (left) != AOP_IMMD) {
11045 _startLazyDPSEvaluation ();
11047 aopPut (left, "dpl", 0);
11048 aopPut (left, "dph", 1);
11049 if (options.model == MODEL_FLAT24) {
11050 aopPut (left, "dpx", 2);
11051 aopPut (left, "b", 3);
11052 } else aopPut (left, "b", 2);
11054 _endLazyDPSEvaluation ();
11057 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
11058 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
11060 size = AOP_SIZE (result) - 1;
11061 while (size--) emitcode ("lcall","__decdptr");
11065 freeAsmop (result, NULL, ic, TRUE);
11066 freeAsmop (left, NULL, ic, TRUE);
11069 /*-----------------------------------------------------------------*/
11070 /* genPointerGet - generate code for pointer get */
11071 /*-----------------------------------------------------------------*/
11073 genPointerGet (iCode * ic, iCode *pi)
11075 operand *left, *result;
11076 sym_link *type, *etype;
11079 D (emitcode (";", "genPointerGet"));
11081 left = IC_LEFT (ic);
11082 result = IC_RESULT (ic);
11084 /* depending on the type of pointer we need to
11085 move it to the correct pointer register */
11086 type = operandType (left);
11087 etype = getSpec (type);
11088 /* if left is of type of pointer then it is simple */
11089 if (IS_PTR (type) && !IS_FUNC (type->next))
11090 p_type = DCL_TYPE (type);
11093 /* we have to go by the storage class */
11094 p_type = PTR_TYPE (SPEC_OCLS (etype));
11097 /* special case when cast remat */
11098 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
11099 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
11101 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
11102 type = operandType (left);
11103 p_type = DCL_TYPE (type);
11105 /* now that we have the pointer type we assign
11106 the pointer values */
11112 genNearPointerGet (left, result, ic, pi);
11116 genPagedPointerGet (left, result, ic, pi);
11120 genFarPointerGet (left, result, ic, pi);
11124 genCodePointerGet (left, result, ic, pi);
11128 genGenPointerGet (left, result, ic, pi);
11134 /*-----------------------------------------------------------------*/
11135 /* genPackBits - generates code for packed bit storage */
11136 /*-----------------------------------------------------------------*/
11138 genPackBits (sym_link * etype,
11140 char *rname, int p_type)
11142 int offset = 0; /* source byte offset */
11143 int rlen = 0; /* remaining bitfield length */
11144 int blen; /* bitfield length */
11145 int bstr; /* bitfield starting bit within byte */
11146 int litval; /* source literal value (if AOP_LIT) */
11147 unsigned char mask; /* bitmask within current byte */
11149 D(emitcode (";", "genPackBits"));
11151 blen = SPEC_BLEN (etype);
11152 bstr = SPEC_BSTR (etype);
11154 /* If the bitfield length is less than a byte */
11157 mask = ((unsigned char) (0xFF << (blen + bstr)) |
11158 (unsigned char) (0xFF >> (8 - bstr)));
11160 if (AOP_TYPE (right) == AOP_LIT)
11162 /* Case with a bitfield length <8 and literal source
11164 litval = (int) ulFromVal (AOP (right)->aopu.aop_lit);
11166 litval &= (~mask) & 0xff;
11167 emitPtrByteGet (rname, p_type, FALSE);
11168 if ((mask|litval)!=0xff)
11169 emitcode ("anl","a,#!constbyte", mask);
11171 emitcode ("orl","a,#!constbyte", litval);
11175 if ((blen==1) && (p_type!=GPOINTER))
11177 /* Case with a bitfield length == 1 and no generic pointer
11179 if (AOP_TYPE (right) == AOP_CRY)
11180 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
11183 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
11184 emitcode ("rrc","a");
11186 emitPtrByteGet (rname, p_type, FALSE);
11187 emitcode ("mov","acc.%d,c",bstr);
11192 /* Case with a bitfield length < 8 and arbitrary source
11194 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
11195 /* shift and mask source value */
11197 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
11199 pushedB = pushB ();
11200 /* transfer A to B and get next byte */
11201 emitPtrByteGet (rname, p_type, TRUE);
11203 emitcode ("anl", "a,#!constbyte", mask);
11204 emitcode ("orl", "a,b");
11205 if (p_type == GPOINTER)
11206 emitcode ("pop", "b");
11212 emitPtrByteSet (rname, p_type, "a");
11216 /* Bit length is greater than 7 bits. In this case, copy */
11217 /* all except the partial byte at the end */
11218 for (rlen=blen;rlen>=8;rlen-=8)
11220 emitPtrByteSet (rname, p_type,
11221 aopGet (right, offset++, FALSE, TRUE, NULL) );
11223 emitcode ("inc", "%s", rname);
11226 /* If there was a partial byte at the end */
11229 mask = (((unsigned char) -1 << rlen) & 0xff);
11231 if (AOP_TYPE (right) == AOP_LIT)
11233 /* Case with partial byte and literal source
11235 litval = (int) ulFromVal (AOP (right)->aopu.aop_lit);
11236 litval >>= (blen-rlen);
11237 litval &= (~mask) & 0xff;
11238 emitPtrByteGet (rname, p_type, FALSE);
11239 if ((mask|litval)!=0xff)
11240 emitcode ("anl","a,#!constbyte", mask);
11242 emitcode ("orl","a,#!constbyte", litval);
11247 /* Case with partial byte and arbitrary source
11249 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11250 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
11252 pushedB = pushB ();
11253 /* transfer A to B and get next byte */
11254 emitPtrByteGet (rname, p_type, TRUE);
11256 emitcode ("anl", "a,#!constbyte", mask);
11257 emitcode ("orl", "a,b");
11258 if (p_type == GPOINTER)
11259 emitcode ("pop", "b");
11263 emitPtrByteSet (rname, p_type, "a");
11268 /*-----------------------------------------------------------------*/
11269 /* genDataPointerSet - remat pointer to data space */
11270 /*-----------------------------------------------------------------*/
11272 genDataPointerSet (operand * right,
11276 int size, offset = 0;
11277 char *l, buffer[256];
11279 D (emitcode (";", "genDataPointerSet"));
11281 aopOp (right, ic, FALSE, FALSE);
11283 l = aopGet (result, 0, FALSE, TRUE, NULL);
11284 size = AOP_SIZE (right);
11288 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l + 1, offset);
11290 SNPRINTF (buffer, sizeof(buffer), "%s", l + 1);
11291 emitcode ("mov", "%s,%s", buffer,
11292 aopGet (right, offset++, FALSE, FALSE, NULL));
11295 freeAsmop (result, NULL, ic, TRUE);
11296 freeAsmop (right, NULL, ic, TRUE);
11299 /*-----------------------------------------------------------------*/
11300 /* genNearPointerSet - emitcode for near pointer put */
11301 /*-----------------------------------------------------------------*/
11303 genNearPointerSet (operand * right,
11310 sym_link *retype, *letype;
11311 sym_link *ptype = operandType (result);
11313 D (emitcode (";", "genNearPointerSet"));
11315 retype = getSpec (operandType (right));
11316 letype = getSpec (ptype);
11318 aopOp (result, ic, FALSE, FALSE);
11320 /* if the result is rematerializable &
11321 in data space & not a bit variable */
11322 if (AOP_TYPE (result) == AOP_IMMD &&
11323 DCL_TYPE (ptype) == POINTER &&
11324 !IS_BITVAR (retype) &&
11325 !IS_BITVAR (letype))
11327 genDataPointerSet (right, result, ic);
11331 /* if the value is already in a pointer register
11332 then don't need anything more */
11333 if (!AOP_INPREG (AOP (result)))
11335 /* otherwise get a free pointer register */
11338 aop = newAsmop (0);
11339 preg = getFreePtr (ic, &aop, FALSE);
11340 emitcode ("mov", "%s,%s",
11342 aopGet (result, 0, FALSE, TRUE, NULL));
11343 rname = preg->name;
11347 rname = aopGet (result, 0, FALSE, FALSE, NULL);
11350 aopOp (right, ic, FALSE, FALSE);
11352 /* if bitfield then unpack the bits */
11353 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11354 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
11357 /* we can just get the values */
11358 int size = AOP_SIZE (right);
11363 l = aopGet (right, offset, FALSE, TRUE, NULL);
11364 if ((*l == '@') || (strcmp (l, "acc") == 0))
11367 emitcode ("mov", "@%s,a", rname);
11370 emitcode ("mov", "@%s,%s", rname, l);
11372 emitcode ("inc", "%s", rname);
11377 /* now some housekeeping stuff */
11378 if (aop) /* we had to allocate for this iCode */
11381 aopPut (result, rname, 0);
11382 freeAsmop (NULL, aop, ic, TRUE);
11386 /* we did not allocate which means left
11387 already in a pointer register, then
11388 if size > 0 && this could be used again
11389 we have to point it back to where it
11391 if (AOP_SIZE (right) > 1 &&
11392 !OP_SYMBOL (result)->remat &&
11393 (OP_SYMBOL (result)->liveTo > ic->seq ||
11397 int size = AOP_SIZE (right) - 1;
11399 emitcode ("dec", "%s", rname);
11404 if (pi) pi->generated = 1;
11405 freeAsmop (result, NULL, ic, TRUE);
11406 freeAsmop (right, NULL, ic, TRUE);
11409 /*-----------------------------------------------------------------*/
11410 /* genPagedPointerSet - emitcode for Paged pointer put */
11411 /*-----------------------------------------------------------------*/
11413 genPagedPointerSet (operand * right,
11420 sym_link *retype, *letype;
11422 D (emitcode (";", "genPagedPointerSet"));
11424 retype = getSpec (operandType (right));
11425 letype = getSpec (operandType (result));
11427 aopOp (result, ic, FALSE, FALSE);
11429 /* if the value is already in a pointer register
11430 then don't need anything more */
11431 if (!AOP_INPREG (AOP (result)))
11433 /* otherwise get a free pointer register */
11436 aop = newAsmop (0);
11437 preg = getFreePtr (ic, &aop, FALSE);
11438 emitcode ("mov", "%s,%s",
11440 aopGet (result, 0, FALSE, TRUE, NULL));
11441 rname = preg->name;
11444 rname = aopGet (result, 0, FALSE, FALSE, NULL);
11446 aopOp (right, ic, FALSE, FALSE);
11448 /* if bitfield then unpack the bits */
11449 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11450 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
11453 /* we have can just get the values */
11454 int size = AOP_SIZE (right);
11459 l = aopGet (right, offset, FALSE, TRUE, NULL);
11461 emitcode ("movx", "@%s,a", rname);
11464 emitcode ("inc", "%s", rname);
11470 /* now some housekeeping stuff */
11474 aopPut (result, rname, 0);
11475 /* we had to allocate for this iCode */
11476 freeAsmop (NULL, aop, ic, TRUE);
11480 /* we did not allocate which means left
11481 already in a pointer register, then
11482 if size > 0 && this could be used again
11483 we have to point it back to where it
11485 if (AOP_SIZE (right) > 1 &&
11486 !OP_SYMBOL (result)->remat &&
11487 (OP_SYMBOL (result)->liveTo > ic->seq ||
11491 int size = AOP_SIZE (right) - 1;
11493 emitcode ("dec", "%s", rname);
11498 if (pi) pi->generated = 1;
11499 freeAsmop (result, NULL, ic, TRUE);
11500 freeAsmop (right, NULL, ic, TRUE);
11503 /*-----------------------------------------------------------------*/
11504 /* genFarPointerSet - set value from far space */
11505 /*-----------------------------------------------------------------*/
11507 genFarPointerSet (operand * right,
11508 operand * result, iCode * ic, iCode *pi)
11510 int size, offset, dopi=1;
11511 sym_link *retype = getSpec (operandType (right));
11512 sym_link *letype = getSpec (operandType (result));
11514 aopOp (result, ic, FALSE, FALSE);
11516 /* if the operand is already in dptr
11517 then we do nothing else we move the value to dptr */
11518 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
11520 /* if this is remateriazable */
11521 if (AOP_TYPE (result) == AOP_IMMD)
11522 emitcode ("mov", "dptr,%s",
11523 aopGet (result, 0, TRUE, FALSE, NULL));
11526 /* we need to get it byte by byte */
11527 _startLazyDPSEvaluation ();
11528 if (AOP_TYPE (result) != AOP_DPTR)
11530 emitcode ("mov", "dpl,%s", aopGet (result, 0, FALSE, FALSE, NULL));
11531 emitcode ("mov", "dph,%s", aopGet (result, 1, FALSE, FALSE, NULL));
11532 if (options.model == MODEL_FLAT24)
11533 emitcode ("mov", "dpx,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11537 /* We need to generate a load to DPTR indirect through DPTR. */
11538 D (emitcode (";", "genFarPointerSet -- indirection special case."););
11540 emitcode ("push", "%s", aopGet (result, 0, FALSE, TRUE, NULL));
11541 emitcode ("push", "%s", aopGet (result, 1, FALSE, TRUE, NULL));
11542 if (options.model == MODEL_FLAT24)
11543 emitcode ("mov", "dpx,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11544 emitcode ("pop", "dph");
11545 emitcode ("pop", "dpl");
11548 _endLazyDPSEvaluation ();
11551 /* so dptr now contains the address */
11552 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
11554 /* if bit then unpack */
11555 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11557 if (AOP_INDPTRn(result)) {
11558 genSetDPTR(AOP(result)->aopu.dptr);
11560 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
11561 if (AOP_INDPTRn(result)) {
11565 size = AOP_SIZE (right);
11567 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
11569 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11571 genSetDPTR(AOP(result)->aopu.dptr);
11572 emitcode ("movx", "@dptr,a");
11573 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
11574 emitcode ("inc", "dptr");
11578 _startLazyDPSEvaluation ();
11580 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11582 if (AOP_INDPTRn(result)) {
11583 genSetDPTR(AOP(result)->aopu.dptr);
11589 emitcode ("movx", "@dptr,a");
11590 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
11591 emitcode ("inc", "dptr");
11593 _endLazyDPSEvaluation ();
11597 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
11598 if (!AOP_INDPTRn(result)) {
11599 _startLazyDPSEvaluation ();
11601 aopPut (result,"dpl",0);
11602 aopPut (result,"dph",1);
11603 if (options.model == MODEL_FLAT24)
11604 aopPut (result,"dpx",2);
11606 _endLazyDPSEvaluation ();
11609 } else if (IS_SYMOP (result) &&
11610 (OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
11611 AOP_SIZE(right) > 1 &&
11612 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
11614 size = AOP_SIZE (right) - 1;
11615 if (AOP_INDPTRn(result)) {
11616 genSetDPTR(AOP(result)->aopu.dptr);
11618 while (size--) emitcode ("lcall","__decdptr");
11619 if (AOP_INDPTRn(result)) {
11623 freeAsmop (result, NULL, ic, TRUE);
11624 freeAsmop (right, NULL, ic, TRUE);
11627 /*-----------------------------------------------------------------*/
11628 /* genGenPointerSet - set value from generic pointer space */
11629 /*-----------------------------------------------------------------*/
11631 genGenPointerSet (operand * right,
11632 operand * result, iCode * ic, iCode *pi)
11636 sym_link *retype = getSpec (operandType (right));
11637 sym_link *letype = getSpec (operandType (result));
11639 aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
11641 pushedB = pushB ();
11642 /* if the operand is already in dptr
11643 then we do nothing else we move the value to dptr */
11644 if (AOP_TYPE (result) != AOP_STR)
11646 _startLazyDPSEvaluation ();
11647 /* if this is remateriazable */
11648 if (AOP_TYPE (result) == AOP_IMMD)
11650 emitcode ("mov", "dptr,%s", aopGet (result, 0, TRUE, FALSE, NULL));
11651 if (AOP(result)->aopu.aop_immd.from_cast_remat)
11653 MOVB (aopGet (result, AOP_SIZE(result)-1, FALSE, FALSE, NULL));
11658 "b,%s + 1", aopGet (result, 0, TRUE, FALSE, NULL));
11662 { /* we need to get it byte by byte */
11663 emitcode ("mov", "dpl,%s", aopGet (result, 0, FALSE, FALSE, NULL));
11664 emitcode ("mov", "dph,%s", aopGet (result, 1, FALSE, FALSE, NULL));
11665 if (options.model == MODEL_FLAT24) {
11666 emitcode ("mov", "dpx,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11667 emitcode ("mov", "b,%s", aopGet (result, 3, FALSE, FALSE, NULL));
11669 emitcode ("mov", "b,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11672 _endLazyDPSEvaluation ();
11674 /* so dptr + b now contains the address */
11675 aopOp (right, ic, FALSE, TRUE);
11677 /* if bit then unpack */
11678 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11680 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
11684 size = AOP_SIZE (right);
11687 _startLazyDPSEvaluation ();
11692 // Set two bytes at a time, passed in _AP & A.
11693 // dptr will be incremented ONCE by __gptrputWord.
11695 // Note: any change here must be coordinated
11696 // with the implementation of __gptrputWord
11697 // in device/lib/_gptrput.c
11698 emitcode("mov", "_ap, %s",
11699 aopGet (right, offset++, FALSE, FALSE, NULL));
11700 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11704 emitcode ("lcall", "__gptrputWord");
11709 // Only one byte to put.
11710 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11714 emitcode ("lcall", "__gptrput");
11717 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
11719 emitcode ("inc", "dptr");
11722 _endLazyDPSEvaluation ();
11725 if (pi && AOP_TYPE (result) != AOP_IMMD) {
11726 _startLazyDPSEvaluation ();
11728 aopPut (result, "dpl",0);
11729 aopPut (result, "dph",1);
11730 if (options.model == MODEL_FLAT24) {
11731 aopPut (result, "dpx",2);
11732 aopPut (result, "b",3);
11734 aopPut (result, "b",2);
11736 _endLazyDPSEvaluation ();
11739 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
11740 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
11742 size = AOP_SIZE (right) - 1;
11743 while (size--) emitcode ("lcall","__decdptr");
11747 freeAsmop (result, NULL, ic, TRUE);
11748 freeAsmop (right, NULL, ic, TRUE);
11751 /*-----------------------------------------------------------------*/
11752 /* genPointerSet - stores the value into a pointer location */
11753 /*-----------------------------------------------------------------*/
11755 genPointerSet (iCode * ic, iCode *pi)
11757 operand *right, *result;
11758 sym_link *type, *etype;
11761 D (emitcode (";", "genPointerSet"));
11763 right = IC_RIGHT (ic);
11764 result = IC_RESULT (ic);
11766 /* depending on the type of pointer we need to
11767 move it to the correct pointer register */
11768 type = operandType (result);
11769 etype = getSpec (type);
11770 /* if left is of type of pointer then it is simple */
11771 if (IS_PTR (type) && !IS_FUNC (type->next))
11773 p_type = DCL_TYPE (type);
11777 /* we have to go by the storage class */
11778 p_type = PTR_TYPE (SPEC_OCLS (etype));
11781 /* special case when cast remat */
11782 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
11783 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
11784 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
11785 type = operandType (result);
11786 p_type = DCL_TYPE (type);
11789 /* now that we have the pointer type we assign
11790 the pointer values */
11796 genNearPointerSet (right, result, ic, pi);
11800 genPagedPointerSet (right, result, ic, pi);
11804 genFarPointerSet (right, result, ic, pi);
11808 genGenPointerSet (right, result, ic, pi);
11812 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11813 "genPointerSet: illegal pointer type");
11817 /*-----------------------------------------------------------------*/
11818 /* genIfx - generate code for Ifx statement */
11819 /*-----------------------------------------------------------------*/
11821 genIfx (iCode * ic, iCode * popIc)
11823 operand *cond = IC_COND (ic);
11827 D (emitcode (";", "genIfx"));
11829 aopOp (cond, ic, FALSE, FALSE);
11831 /* get the value into acc */
11832 if (AOP_TYPE (cond) != AOP_CRY)
11839 if (AOP(cond)->aopu.aop_dir)
11840 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
11843 /* the result is now in the accumulator or a directly addressable bit */
11844 freeAsmop (cond, NULL, ic, TRUE);
11846 /* if there was something to be popped then do it */
11850 /* if the condition is a bit variable */
11852 genIfxJump (ic, dup);
11853 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
11854 genIfxJump (ic, SPIL_LOC (cond)->rname);
11855 else if (isbit && !IS_ITEMP (cond))
11856 genIfxJump (ic, OP_SYMBOL (cond)->rname);
11858 genIfxJump (ic, "a");
11863 /*-----------------------------------------------------------------*/
11864 /* genAddrOf - generates code for address of */
11865 /*-----------------------------------------------------------------*/
11867 genAddrOf (iCode * ic)
11869 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
11872 D (emitcode (";", "genAddrOf"));
11874 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11876 /* if the operand is on the stack then we
11877 need to get the stack offset of this
11882 /* if 10 bit stack */
11883 if (options.stack10bit) {
11887 tsprintf(buff, sizeof(buff),
11888 "#!constbyte",(options.stack_loc >> 16) & 0xff);
11889 /* if it has an offset then we need to compute it */
11890 /* emitcode ("subb", "a,#!constbyte", */
11891 /* -((sym->stack < 0) ? */
11892 /* ((short) (sym->stack - _G.nRegsSaved)) : */
11893 /* ((short) sym->stack)) & 0xff); */
11894 /* emitcode ("mov","b,a"); */
11895 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
11896 /* ((short) (sym->stack - _G.nRegsSaved)) : */
11897 /* ((short) sym->stack)) >> 8) & 0xff); */
11899 emitcode ("mov", "a,_bpx");
11900 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
11901 ((char) (sym->stack - _G.nRegsSaved)) :
11902 ((char) sym->stack )) & 0xff);
11903 emitcode ("mov", "b,a");
11904 emitcode ("mov", "a,_bpx+1");
11906 offset = (((sym->stack < 0) ?
11907 ((short) (sym->stack - _G.nRegsSaved)) :
11908 ((short) sym->stack )) >> 8) & 0xff;
11910 emitcode ("addc","a,#!constbyte", offset);
11912 aopPut (IC_RESULT (ic), "b", 0);
11913 aopPut (IC_RESULT (ic), "a", 1);
11914 aopPut (IC_RESULT (ic), buff, 2);
11916 /* we can just move _bp */
11917 aopPut (IC_RESULT (ic), "_bpx", 0);
11918 aopPut (IC_RESULT (ic), "_bpx+1", 1);
11919 aopPut (IC_RESULT (ic), buff, 2);
11922 /* if it has an offset then we need to compute it */
11925 emitcode ("mov", "a,_bp");
11926 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
11927 aopPut (IC_RESULT (ic), "a", 0);
11931 /* we can just move _bp */
11932 aopPut (IC_RESULT (ic), "_bp", 0);
11934 /* fill the result with zero */
11935 size = AOP_SIZE (IC_RESULT (ic)) - 1;
11938 if (options.stack10bit && size < (FPTRSIZE - 1)) {
11940 "*** warning: pointer to stack var truncated.\n");
11946 aopPut (IC_RESULT (ic), zero, offset++);
11952 /* object not on stack then we need the name */
11953 size = getDataSize (IC_RESULT (ic));
11958 char s[SDCC_NAME_MAX];
11963 tsprintf(s, sizeof(s), "#!his",sym->rname);
11966 tsprintf(s, sizeof(s), "#!hihis",sym->rname);
11969 tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
11971 default: /* should not need this (just in case) */
11972 SNPRINTF (s, sizeof(s), "#(%s >> %d)", sym->rname, offset * 8);
11977 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11980 aopPut (IC_RESULT (ic), s, offset++);
11982 if (opIsGptr (IC_RESULT (ic)))
11985 SNPRINTF (buffer, sizeof(buffer), "#0x%02x",
11986 pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
11987 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
11991 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11995 #if 0 // obsolete, and buggy for != xdata
11996 /*-----------------------------------------------------------------*/
11997 /* genArrayInit - generates code for address of */
11998 /*-----------------------------------------------------------------*/
12000 genArrayInit (iCode * ic)
12002 literalList *iLoop;
12004 int elementSize = 0, eIndex;
12005 unsigned val, lastVal;
12007 operand *left=IC_LEFT(ic);
12009 D (emitcode (";", "genArrayInit"));
12011 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
12013 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
12015 // Load immediate value into DPTR.
12016 emitcode("mov", "dptr, %s",
12017 aopGet (IC_LEFT(ic), 0, TRUE, FALSE, NULL));
12019 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
12022 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12023 "Unexpected operand to genArrayInit.\n");
12026 // a regression because of SDCCcse.c:1.52
12027 emitcode ("mov", "dpl,%s", aopGet (left, 0, FALSE, FALSE, NULL));
12028 emitcode ("mov", "dph,%s", aopGet (left, 1, FALSE, FALSE, NULL));
12029 if (options.model == MODEL_FLAT24)
12030 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
12034 type = operandType(IC_LEFT(ic));
12036 if (type && type->next)
12038 elementSize = getSize(type->next);
12042 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12043 "can't determine element size in genArrayInit.\n");
12047 iLoop = IC_ARRAYILIST(ic);
12052 bool firstpass = TRUE;
12054 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
12055 iLoop->count, (int)iLoop->literalValue, elementSize);
12061 symbol *tlbl = NULL;
12063 count = ix > 256 ? 256 : ix;
12067 tlbl = newiTempLabel (NULL);
12068 if (firstpass || (count & 0xff))
12070 emitcode("mov", "b, #!constbyte", count & 0xff);
12078 for (eIndex = 0; eIndex < elementSize; eIndex++)
12080 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
12081 if (val != lastVal)
12083 emitcode("mov", "a, #!constbyte", val);
12087 emitcode("movx", "@dptr, a");
12088 emitcode("inc", "dptr");
12093 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
12099 iLoop = iLoop->next;
12102 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
12106 /*-----------------------------------------------------------------*/
12107 /* genFarFarAssign - assignment when both are in far space */
12108 /*-----------------------------------------------------------------*/
12110 genFarFarAssign (operand * result, operand * right, iCode * ic)
12112 int size = AOP_SIZE (right);
12114 symbol *rSym = NULL;
12118 /* quick & easy case. */
12119 D (emitcode(";","genFarFarAssign (1 byte case)"));
12120 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
12121 freeAsmop (right, NULL, ic, FALSE);
12122 /* now assign DPTR to result */
12124 aopOp(result, ic, FALSE, FALSE);
12126 aopPut (result, "a", 0);
12127 freeAsmop(result, NULL, ic, FALSE);
12131 /* See if we've got an underlying symbol to abuse. */
12132 if (IS_SYMOP(result) && OP_SYMBOL(result))
12134 if (IS_TRUE_SYMOP(result))
12136 rSym = OP_SYMBOL(result);
12138 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
12140 rSym = OP_SYMBOL(result)->usl.spillLoc;
12144 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
12146 /* We can use the '390 auto-toggle feature to good effect here. */
12148 D (emitcode(";", "genFarFarAssign (390 auto-toggle fun)"));
12149 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12150 emitcode ("mov", "dptr,#%s", rSym->rname);
12151 /* DP2 = result, DP1 = right, DP1 is current. */
12154 emitcode("movx", "a,@dptr");
12155 emitcode("movx", "@dptr,a");
12158 emitcode("inc", "dptr");
12159 emitcode("inc", "dptr");
12162 emitcode("mov", "dps,#0");
12163 freeAsmop (right, NULL, ic, FALSE);
12165 some alternative code for processors without auto-toggle
12166 no time to test now, so later well put in...kpb
12167 D (emitcode(";", "genFarFarAssign (dual-dptr fun)"));
12168 emitcode("mov", "dps,#1"); /* Select DPTR2. */
12169 emitcode ("mov", "dptr,#%s", rSym->rname);
12170 /* DP2 = result, DP1 = right, DP1 is current. */
12174 emitcode("movx", "a,@dptr");
12176 emitcode("inc", "dptr");
12177 emitcode("inc", "dps");
12178 emitcode("movx", "@dptr,a");
12180 emitcode("inc", "dptr");
12181 emitcode("inc", "dps");
12183 emitcode("mov", "dps,#0");
12184 freeAsmop (right, NULL, ic, FALSE);
12189 D (emitcode (";", "genFarFarAssign"));
12190 aopOp (result, ic, TRUE, TRUE);
12192 _startLazyDPSEvaluation ();
12197 aopGet (right, offset, FALSE, FALSE, NULL), offset);
12200 _endLazyDPSEvaluation ();
12201 freeAsmop (result, NULL, ic, FALSE);
12202 freeAsmop (right, NULL, ic, FALSE);
12206 /*-----------------------------------------------------------------*/
12207 /* genAssign - generate code for assignment */
12208 /*-----------------------------------------------------------------*/
12210 genAssign (iCode * ic)
12212 operand *result, *right;
12214 unsigned long lit = 0L;
12216 D (emitcode (";", "genAssign"));
12218 result = IC_RESULT (ic);
12219 right = IC_RIGHT (ic);
12221 /* if they are the same */
12222 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
12225 aopOp (right, ic, FALSE, FALSE);
12227 emitcode (";", "genAssign: resultIsFar = %s",
12228 isOperandInFarSpace (result) ?
12231 /* special case both in far space */
12232 if ((AOP_TYPE (right) == AOP_DPTR ||
12233 AOP_TYPE (right) == AOP_DPTR2) &&
12234 /* IS_TRUE_SYMOP(result) && */
12235 isOperandInFarSpace (result))
12237 genFarFarAssign (result, right, ic);
12241 aopOp (result, ic, TRUE, FALSE);
12243 /* if they are the same registers */
12244 if (sameRegs (AOP (right), AOP (result)))
12247 /* if the result is a bit */
12248 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
12250 /* if the right size is a literal then
12251 we know what the value is */
12252 if (AOP_TYPE (right) == AOP_LIT)
12254 if (((int) operandLitValue (right)))
12255 aopPut (result, one, 0);
12257 aopPut (result, zero, 0);
12261 /* the right is also a bit variable */
12262 if (AOP_TYPE (right) == AOP_CRY)
12264 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
12265 aopPut (result, "c", 0);
12269 /* we need to or */
12271 aopPut (result, "a", 0);
12275 /* bit variables done */
12277 size = getDataSize (result);
12279 if (AOP_TYPE (right) == AOP_LIT)
12280 lit = ulFromVal (AOP (right)->aopu.aop_lit);
12283 (AOP_TYPE (result) != AOP_REG) &&
12284 (AOP_TYPE (right) == AOP_LIT) &&
12285 !IS_FLOAT (operandType (right)))
12287 _startLazyDPSEvaluation ();
12288 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
12291 aopGet (right, offset, FALSE, FALSE, NULL),
12296 /* And now fill the rest with zeros. */
12299 emitcode ("clr", "a");
12303 aopPut (result, "a", offset++);
12305 _endLazyDPSEvaluation ();
12309 _startLazyDPSEvaluation ();
12313 aopGet (right, offset, FALSE, FALSE, NULL),
12317 _endLazyDPSEvaluation ();
12319 adjustArithmeticResult (ic);
12322 freeAsmop (result, NULL, ic, TRUE);
12323 freeAsmop (right, NULL, ic, TRUE);
12326 /*-----------------------------------------------------------------*/
12327 /* genJumpTab - generates code for jump table */
12328 /*-----------------------------------------------------------------*/
12330 genJumpTab (iCode * ic)
12335 D (emitcode (";", "genJumpTab"));
12337 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
12338 /* get the condition into accumulator */
12339 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE, NULL);
12341 /* multiply by four! */
12342 emitcode ("add", "a,acc");
12343 emitcode ("add", "a,acc");
12344 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
12346 jtab = newiTempLabel (NULL);
12347 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
12348 emitcode ("jmp", "@a+dptr");
12350 /* now generate the jump labels */
12351 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
12352 jtab = setNextItem (IC_JTLABELS (ic)))
12353 emitcode ("ljmp", "!tlabel", jtab->key + 100);
12357 /*-----------------------------------------------------------------*/
12358 /* genCast - gen code for casting */
12359 /*-----------------------------------------------------------------*/
12361 genCast (iCode * ic)
12363 operand *result = IC_RESULT (ic);
12364 sym_link *ctype = operandType (IC_LEFT (ic));
12365 sym_link *rtype = operandType (IC_RIGHT (ic));
12366 operand *right = IC_RIGHT (ic);
12369 D (emitcode (";", "genCast"));
12371 /* if they are equivalent then do nothing */
12372 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
12375 aopOp (right, ic, FALSE, AOP_IS_STR (result));
12376 aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR));
12378 /* if the result is a bit (and not a bitfield) */
12379 if (IS_BIT (OP_SYMBOL (result)->type))
12381 /* if the right size is a literal then
12382 we know what the value is */
12383 if (AOP_TYPE (right) == AOP_LIT)
12385 if (((int) operandLitValue (right)))
12386 aopPut (result, one, 0);
12388 aopPut (result, zero, 0);
12393 /* the right is also a bit variable */
12394 if (AOP_TYPE (right) == AOP_CRY)
12396 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
12397 aopPut (result, "c", 0);
12401 /* we need to or */
12403 aopPut (result, "a", 0);
12407 /* if they are the same size : or less */
12408 if (AOP_SIZE (result) <= AOP_SIZE (right))
12411 /* if they are in the same place */
12412 if (sameRegs (AOP (right), AOP (result)))
12415 /* if they in different places then copy */
12416 size = AOP_SIZE (result);
12418 _startLazyDPSEvaluation ();
12422 aopGet (right, offset, FALSE, FALSE, NULL),
12426 _endLazyDPSEvaluation ();
12430 /* if the result is of type pointer */
12431 if (IS_PTR (ctype))
12435 sym_link *type = operandType (right);
12437 /* pointer to generic pointer */
12438 if (IS_GENPTR (ctype))
12442 p_type = DCL_TYPE (type);
12446 #if OLD_CAST_BEHAVIOR
12447 /* KV: we are converting a non-pointer type to
12448 * a generic pointer. This (ifdef'd out) code
12449 * says that the resulting generic pointer
12450 * should have the same class as the storage
12451 * location of the non-pointer variable.
12453 * For example, converting an int (which happens
12454 * to be stored in DATA space) to a pointer results
12455 * in a DATA generic pointer; if the original int
12456 * in XDATA space, so will be the resulting pointer.
12458 * I don't like that behavior, and thus this change:
12459 * all such conversions will be forced to XDATA and
12460 * throw a warning. If you want some non-XDATA
12461 * type, or you want to suppress the warning, you
12462 * must go through an intermediate cast, like so:
12464 * char _generic *gp = (char _xdata *)(intVar);
12466 sym_link *etype = getSpec (type);
12468 /* we have to go by the storage class */
12469 if (SPEC_OCLS (etype) != generic)
12471 p_type = PTR_TYPE (SPEC_OCLS (etype));
12476 /* Converting unknown class (i.e. register variable)
12477 * to generic pointer. This is not good, but
12478 * we'll make a guess (and throw a warning).
12481 werror (W_INT_TO_GEN_PTR_CAST);
12485 /* the first two bytes are known */
12486 size = GPTRSIZE - 1;
12488 _startLazyDPSEvaluation ();
12492 aopGet (right, offset, FALSE, FALSE, NULL),
12496 _endLazyDPSEvaluation ();
12498 /* the last byte depending on type */
12500 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
12505 // pointerTypeToGPByte will have bitched.
12509 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%x", gpVal);
12510 aopPut (result, gpValStr, GPTRSIZE - 1);
12515 /* just copy the pointers */
12516 size = AOP_SIZE (result);
12518 _startLazyDPSEvaluation ();
12522 aopGet (right, offset, FALSE, FALSE, NULL),
12526 _endLazyDPSEvaluation ();
12530 /* so we now know that the size of destination is greater
12531 than the size of the source */
12532 /* we move to result for the size of source */
12533 size = AOP_SIZE (right);
12535 _startLazyDPSEvaluation ();
12539 aopGet (right, offset, FALSE, FALSE, NULL),
12543 _endLazyDPSEvaluation ();
12545 /* now depending on the sign of the source && destination */
12546 size = AOP_SIZE (result) - AOP_SIZE (right);
12547 /* if unsigned or not an integral type */
12548 /* also, if the source is a bit, we don't need to sign extend, because
12549 * it can't possibly have set the sign bit.
12551 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
12555 aopPut (result, zero, offset++);
12560 /* we need to extend the sign :{ */
12561 MOVA (aopGet (right, AOP_SIZE (right) - 1,
12562 FALSE, FALSE, NULL));
12563 emitcode ("rlc", "a");
12564 emitcode ("subb", "a,acc");
12566 aopPut (result, "a", offset++);
12569 /* we are done hurray !!!! */
12572 freeAsmop (right, NULL, ic, TRUE);
12573 freeAsmop (result, NULL, ic, TRUE);
12577 /*-----------------------------------------------------------------*/
12578 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
12579 /*-----------------------------------------------------------------*/
12580 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
12582 operand *from , *to , *count;
12587 /* we know it has to be 3 parameters */
12588 assert (nparms == 3);
12590 rsave = newBitVect(16);
12591 /* save DPTR if it needs to be saved */
12592 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12593 if (bitVectBitValue(ic->rMask,i))
12594 rsave = bitVectSetBit(rsave,i);
12596 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12597 ds390_rUmaskForOp (IC_RESULT(ic))));
12604 aopOp (from, ic->next, FALSE, FALSE);
12606 /* get from into DPTR1 */
12607 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12608 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12609 if (options.model == MODEL_FLAT24) {
12610 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12613 freeAsmop (from, NULL, ic, FALSE);
12614 aopOp (to, ic, FALSE, FALSE);
12615 /* get "to" into DPTR */
12616 /* if the operand is already in dptr
12617 then we do nothing else we move the value to dptr */
12618 if (AOP_TYPE (to) != AOP_STR) {
12619 /* if already in DPTR then we need to push */
12620 if (AOP_TYPE(to) == AOP_DPTR) {
12621 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12622 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12623 if (options.model == MODEL_FLAT24)
12624 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12625 emitcode ("pop", "dph");
12626 emitcode ("pop", "dpl");
12628 _startLazyDPSEvaluation ();
12629 /* if this is remateriazable */
12630 if (AOP_TYPE (to) == AOP_IMMD) {
12631 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12632 } else { /* we need to get it byte by byte */
12633 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12634 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12635 if (options.model == MODEL_FLAT24) {
12636 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12639 _endLazyDPSEvaluation ();
12642 freeAsmop (to, NULL, ic, FALSE);
12643 _G.dptrInUse = _G.dptr1InUse = 1;
12644 aopOp (count, ic->next->next, FALSE,FALSE);
12645 lbl =newiTempLabel(NULL);
12647 /* now for the actual copy */
12648 if (AOP_TYPE(count) == AOP_LIT &&
12649 (int) ulFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12650 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12652 emitcode ("lcall","__bi_memcpyc2x_s");
12654 emitcode ("lcall","__bi_memcpyx2x_s");
12656 freeAsmop (count, NULL, ic, FALSE);
12658 symbol *lbl1 = newiTempLabel(NULL);
12660 emitcode (";"," Auto increment but no djnz");
12661 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
12662 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
12663 freeAsmop (count, NULL, ic, FALSE);
12664 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12667 emitcode ("clr","a");
12668 emitcode ("movc", "a,@a+dptr");
12670 emitcode ("movx", "a,@dptr");
12671 emitcode ("movx", "@dptr,a");
12672 emitcode ("inc", "dptr");
12673 emitcode ("inc", "dptr");
12674 emitcode ("mov","a,b");
12675 emitcode ("orl","a,_ap");
12676 emitcode ("jz","!tlabel",lbl1->key+100);
12677 emitcode ("mov","a,_ap");
12678 emitcode ("add","a,#!constbyte",0xFF);
12679 emitcode ("mov","_ap,a");
12680 emitcode ("mov","a,b");
12681 emitcode ("addc","a,#!constbyte",0xFF);
12682 emitcode ("mov","b,a");
12683 emitcode ("sjmp","!tlabel",lbl->key+100);
12686 emitcode ("mov", "dps,#0");
12687 _G.dptrInUse = _G.dptr1InUse = 0;
12688 unsavermask(rsave);
12692 /*-----------------------------------------------------------------*/
12693 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
12694 /*-----------------------------------------------------------------*/
12695 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
12697 operand *from , *to , *count;
12702 /* we know it has to be 3 parameters */
12703 assert (nparms == 3);
12705 rsave = newBitVect(16);
12706 /* save DPTR if it needs to be saved */
12707 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12708 if (bitVectBitValue(ic->rMask,i))
12709 rsave = bitVectSetBit(rsave,i);
12711 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12712 ds390_rUmaskForOp (IC_RESULT(ic))));
12719 aopOp (from, ic->next, FALSE, FALSE);
12721 /* get from into DPTR1 */
12722 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12723 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12724 if (options.model == MODEL_FLAT24) {
12725 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12728 freeAsmop (from, NULL, ic, FALSE);
12729 aopOp (to, ic, FALSE, FALSE);
12730 /* get "to" into DPTR */
12731 /* if the operand is already in dptr
12732 then we do nothing else we move the value to dptr */
12733 if (AOP_TYPE (to) != AOP_STR) {
12734 /* if already in DPTR then we need to push */
12735 if (AOP_TYPE(to) == AOP_DPTR) {
12736 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12737 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12738 if (options.model == MODEL_FLAT24)
12739 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12740 emitcode ("pop", "dph");
12741 emitcode ("pop", "dpl");
12743 _startLazyDPSEvaluation ();
12744 /* if this is remateriazable */
12745 if (AOP_TYPE (to) == AOP_IMMD) {
12746 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12747 } else { /* we need to get it byte by byte */
12748 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12749 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12750 if (options.model == MODEL_FLAT24) {
12751 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12754 _endLazyDPSEvaluation ();
12757 freeAsmop (to, NULL, ic, FALSE);
12758 _G.dptrInUse = _G.dptr1InUse = 1;
12759 aopOp (count, ic->next->next, FALSE,FALSE);
12760 lbl =newiTempLabel(NULL);
12761 lbl2 =newiTempLabel(NULL);
12763 /* now for the actual compare */
12764 if (AOP_TYPE(count) == AOP_LIT &&
12765 (int) ulFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12766 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12768 emitcode("lcall","__bi_memcmpc2x_s");
12770 emitcode("lcall","__bi_memcmpx2x_s");
12771 freeAsmop (count, NULL, ic, FALSE);
12772 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12773 aopPut(IC_RESULT(ic),"a",0);
12774 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12776 symbol *lbl1 = newiTempLabel(NULL);
12778 emitcode("push","ar0");
12779 emitcode (";"," Auto increment but no djnz");
12780 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
12781 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
12782 freeAsmop (count, NULL, ic, FALSE);
12783 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12786 emitcode ("clr","a");
12787 emitcode ("movc", "a,@a+dptr");
12789 emitcode ("movx", "a,@dptr");
12790 emitcode ("mov","r0,a");
12791 emitcode ("movx", "a,@dptr");
12792 emitcode ("clr","c");
12793 emitcode ("subb","a,r0");
12794 emitcode ("jnz","!tlabel",lbl2->key+100);
12795 emitcode ("inc", "dptr");
12796 emitcode ("inc", "dptr");
12797 emitcode ("mov","a,b");
12798 emitcode ("orl","a,_ap");
12799 emitcode ("jz","!tlabel",lbl1->key+100);
12800 emitcode ("mov","a,_ap");
12801 emitcode ("add","a,#!constbyte",0xFF);
12802 emitcode ("mov","_ap,a");
12803 emitcode ("mov","a,b");
12804 emitcode ("addc","a,#!constbyte",0xFF);
12805 emitcode ("mov","b,a");
12806 emitcode ("sjmp","!tlabel",lbl->key+100);
12808 emitcode ("clr","a");
12810 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12811 aopPut(IC_RESULT(ic),"a",0);
12812 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12813 emitcode("pop","ar0");
12814 emitcode ("mov", "dps,#0");
12816 _G.dptrInUse = _G.dptr1InUse = 0;
12817 unsavermask(rsave);
12821 /*-----------------------------------------------------------------*/
12822 /* genInp - gen code for __builtin_inp read data from a mem mapped */
12823 /* port, first parameter output area second parameter pointer to */
12824 /* port third parameter count */
12825 /*-----------------------------------------------------------------*/
12826 static void genInp( iCode *ic, int nparms, operand **parms)
12828 operand *from , *to , *count;
12833 /* we know it has to be 3 parameters */
12834 assert (nparms == 3);
12836 rsave = newBitVect(16);
12837 /* save DPTR if it needs to be saved */
12838 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12839 if (bitVectBitValue(ic->rMask,i))
12840 rsave = bitVectSetBit(rsave,i);
12842 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12843 ds390_rUmaskForOp (IC_RESULT(ic))));
12850 aopOp (from, ic->next, FALSE, FALSE);
12852 /* get from into DPTR1 */
12853 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12854 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12855 if (options.model == MODEL_FLAT24) {
12856 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12859 freeAsmop (from, NULL, ic, FALSE);
12860 aopOp (to, ic, FALSE, FALSE);
12861 /* get "to" into DPTR */
12862 /* if the operand is already in dptr
12863 then we do nothing else we move the value to dptr */
12864 if (AOP_TYPE (to) != AOP_STR) {
12865 /* if already in DPTR then we need to push */
12866 if (AOP_TYPE(to) == AOP_DPTR) {
12867 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12868 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12869 if (options.model == MODEL_FLAT24)
12870 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12871 emitcode ("pop", "dph");
12872 emitcode ("pop", "dpl");
12874 _startLazyDPSEvaluation ();
12875 /* if this is remateriazable */
12876 if (AOP_TYPE (to) == AOP_IMMD) {
12877 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12878 } else { /* we need to get it byte by byte */
12879 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12880 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12881 if (options.model == MODEL_FLAT24) {
12882 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12885 _endLazyDPSEvaluation ();
12888 freeAsmop (to, NULL, ic, FALSE);
12890 _G.dptrInUse = _G.dptr1InUse = 1;
12891 aopOp (count, ic->next->next, FALSE,FALSE);
12892 lbl =newiTempLabel(NULL);
12894 /* now for the actual copy */
12895 if (AOP_TYPE(count) == AOP_LIT &&
12896 (int) ulFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12897 emitcode (";","OH JOY auto increment with djnz (very fast)");
12898 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
12899 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12900 freeAsmop (count, NULL, ic, FALSE);
12902 emitcode ("movx", "a,@dptr"); /* read data from port */
12903 emitcode ("dec","dps"); /* switch to DPTR */
12904 emitcode ("movx", "@dptr,a"); /* save into location */
12905 emitcode ("inc", "dptr"); /* point to next area */
12906 emitcode ("inc","dps"); /* switch to DPTR2 */
12907 emitcode ("djnz","b,!tlabel",lbl->key+100);
12909 symbol *lbl1 = newiTempLabel(NULL);
12911 emitcode (";"," Auto increment but no djnz");
12912 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
12913 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
12914 freeAsmop (count, NULL, ic, FALSE);
12915 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
12917 emitcode ("movx", "a,@dptr");
12918 emitcode ("dec","dps"); /* switch to DPTR */
12919 emitcode ("movx", "@dptr,a");
12920 emitcode ("inc", "dptr");
12921 emitcode ("inc","dps"); /* switch to DPTR2 */
12922 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
12923 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
12924 emitcode ("mov","a,b");
12925 emitcode ("orl","a,_ap");
12926 emitcode ("jz","!tlabel",lbl1->key+100);
12927 emitcode ("mov","a,_ap");
12928 emitcode ("add","a,#!constbyte",0xFF);
12929 emitcode ("mov","_ap,a");
12930 emitcode ("mov","a,b");
12931 emitcode ("addc","a,#!constbyte",0xFF);
12932 emitcode ("mov","b,a");
12933 emitcode ("sjmp","!tlabel",lbl->key+100);
12936 emitcode ("mov", "dps,#0");
12937 _G.dptrInUse = _G.dptr1InUse = 0;
12938 unsavermask(rsave);
12942 /*-----------------------------------------------------------------*/
12943 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
12944 /* port, first parameter output area second parameter pointer to */
12945 /* port third parameter count */
12946 /*-----------------------------------------------------------------*/
12947 static void genOutp( iCode *ic, int nparms, operand **parms)
12949 operand *from , *to , *count;
12954 /* we know it has to be 3 parameters */
12955 assert (nparms == 3);
12957 rsave = newBitVect(16);
12958 /* save DPTR if it needs to be saved */
12959 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12960 if (bitVectBitValue(ic->rMask,i))
12961 rsave = bitVectSetBit(rsave,i);
12963 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12964 ds390_rUmaskForOp (IC_RESULT(ic))));
12971 aopOp (from, ic->next, FALSE, FALSE);
12973 /* get from into DPTR1 */
12974 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12975 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12976 if (options.model == MODEL_FLAT24) {
12977 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12980 freeAsmop (from, NULL, ic, FALSE);
12981 aopOp (to, ic, FALSE, FALSE);
12982 /* get "to" into DPTR */
12983 /* if the operand is already in dptr
12984 then we do nothing else we move the value to dptr */
12985 if (AOP_TYPE (to) != AOP_STR) {
12986 /* if already in DPTR then we need to push */
12987 if (AOP_TYPE(to) == AOP_DPTR) {
12988 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12989 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12990 if (options.model == MODEL_FLAT24)
12991 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12992 emitcode ("pop", "dph");
12993 emitcode ("pop", "dpl");
12995 _startLazyDPSEvaluation ();
12996 /* if this is remateriazable */
12997 if (AOP_TYPE (to) == AOP_IMMD) {
12998 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12999 } else { /* we need to get it byte by byte */
13000 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
13001 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
13002 if (options.model == MODEL_FLAT24) {
13003 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
13006 _endLazyDPSEvaluation ();
13009 freeAsmop (to, NULL, ic, FALSE);
13011 _G.dptrInUse = _G.dptr1InUse = 1;
13012 aopOp (count, ic->next->next, FALSE,FALSE);
13013 lbl =newiTempLabel(NULL);
13015 /* now for the actual copy */
13016 if (AOP_TYPE(count) == AOP_LIT &&
13017 (int) ulFromVal (AOP(count)->aopu.aop_lit) <= 256) {
13018 emitcode (";","OH JOY auto increment with djnz (very fast)");
13019 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
13020 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
13022 emitcode ("movx", "a,@dptr"); /* read data from port */
13023 emitcode ("inc","dps"); /* switch to DPTR2 */
13024 emitcode ("movx", "@dptr,a"); /* save into location */
13025 emitcode ("inc", "dptr"); /* point to next area */
13026 emitcode ("dec","dps"); /* switch to DPTR */
13027 emitcode ("djnz","b,!tlabel",lbl->key+100);
13028 freeAsmop (count, NULL, ic, FALSE);
13030 symbol *lbl1 = newiTempLabel(NULL);
13032 emitcode (";"," Auto increment but no djnz");
13033 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
13034 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
13035 freeAsmop (count, NULL, ic, FALSE);
13036 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
13038 emitcode ("movx", "a,@dptr");
13039 emitcode ("inc", "dptr");
13040 emitcode ("inc","dps"); /* switch to DPTR2 */
13041 emitcode ("movx", "@dptr,a");
13042 emitcode ("dec","dps"); /* switch to DPTR */
13043 emitcode ("mov","a,b");
13044 emitcode ("orl","a,_ap");
13045 emitcode ("jz","!tlabel",lbl1->key+100);
13046 emitcode ("mov","a,_ap");
13047 emitcode ("add","a,#!constbyte",0xFF);
13048 emitcode ("mov","_ap,a");
13049 emitcode ("mov","a,b");
13050 emitcode ("addc","a,#!constbyte",0xFF);
13051 emitcode ("mov","b,a");
13052 emitcode ("sjmp","!tlabel",lbl->key+100);
13055 emitcode ("mov", "dps,#0");
13056 _G.dptrInUse = _G.dptr1InUse = 0;
13057 unsavermask(rsave);
13061 /*-----------------------------------------------------------------*/
13062 /* genSwapW - swap lower & high order bytes */
13063 /*-----------------------------------------------------------------*/
13064 static void genSwapW(iCode *ic, int nparms, operand **parms)
13068 assert (nparms==1);
13071 dest=IC_RESULT(ic);
13073 assert(getSize(operandType(src))==2);
13075 aopOp (src, ic, FALSE, FALSE);
13076 emitcode ("mov","a,%s",aopGet(src,0,FALSE,FALSE,NULL));
13078 MOVB(aopGet(src,1,FALSE,FALSE,"b"));
13080 freeAsmop (src, NULL, ic, FALSE);
13082 aopOp (dest,ic, FALSE, FALSE);
13083 aopPut(dest,"b",0);
13084 aopPut(dest,"a",1);
13085 freeAsmop (dest, NULL, ic, FALSE);
13088 /*-----------------------------------------------------------------*/
13089 /* genMemsetX - gencode for memSetX data */
13090 /*-----------------------------------------------------------------*/
13091 static void genMemsetX(iCode *ic, int nparms, operand **parms)
13093 operand *to , *val , *count;
13099 /* we know it has to be 3 parameters */
13100 assert (nparms == 3);
13106 /* save DPTR if it needs to be saved */
13107 rsave = newBitVect(16);
13108 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
13109 if (bitVectBitValue(ic->rMask,i))
13110 rsave = bitVectSetBit(rsave,i);
13112 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
13113 ds390_rUmaskForOp (IC_RESULT(ic))));
13116 aopOp (to, ic, FALSE, FALSE);
13117 /* get "to" into DPTR */
13118 /* if the operand is already in dptr
13119 then we do nothing else we move the value to dptr */
13120 if (AOP_TYPE (to) != AOP_STR) {
13121 /* if already in DPTR then we need to push */
13122 if (AOP_TYPE(to) == AOP_DPTR) {
13123 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
13124 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
13125 if (options.model == MODEL_FLAT24)
13126 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
13127 emitcode ("pop", "dph");
13128 emitcode ("pop", "dpl");
13130 _startLazyDPSEvaluation ();
13131 /* if this is remateriazable */
13132 if (AOP_TYPE (to) == AOP_IMMD) {
13133 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
13134 } else { /* we need to get it byte by byte */
13135 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
13136 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
13137 if (options.model == MODEL_FLAT24) {
13138 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
13141 _endLazyDPSEvaluation ();
13144 freeAsmop (to, NULL, ic, FALSE);
13146 aopOp (val, ic->next->next, FALSE,FALSE);
13147 aopOp (count, ic->next->next, FALSE,FALSE);
13148 lbl =newiTempLabel(NULL);
13149 /* now for the actual copy */
13150 if (AOP_TYPE(count) == AOP_LIT &&
13151 (int) ulFromVal (AOP(count)->aopu.aop_lit) <= 256) {
13152 l = aopGet(val, 0, FALSE, FALSE, NULL);
13153 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
13156 emitcode ("movx", "@dptr,a");
13157 emitcode ("inc", "dptr");
13158 emitcode ("djnz","b,!tlabel",lbl->key+100);
13160 symbol *lbl1 = newiTempLabel(NULL);
13162 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
13163 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
13165 MOVA (aopGet(val, 0, FALSE, FALSE, NULL));
13166 emitcode ("movx", "@dptr,a");
13167 emitcode ("inc", "dptr");
13168 emitcode ("mov","a,b");
13169 emitcode ("orl","a,_ap");
13170 emitcode ("jz","!tlabel",lbl1->key+100);
13171 emitcode ("mov","a,_ap");
13172 emitcode ("add","a,#!constbyte",0xFF);
13173 emitcode ("mov","_ap,a");
13174 emitcode ("mov","a,b");
13175 emitcode ("addc","a,#!constbyte",0xFF);
13176 emitcode ("mov","b,a");
13177 emitcode ("sjmp","!tlabel",lbl->key+100);
13180 freeAsmop (count, NULL, ic, FALSE);
13181 unsavermask(rsave);
13184 /*-----------------------------------------------------------------*/
13185 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
13186 /*-----------------------------------------------------------------*/
13187 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
13190 operand *pnum, *result;
13193 assert (nparms==1);
13194 /* save registers that need to be saved */
13195 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13196 ds390_rUmaskForOp (IC_RESULT(ic))));
13199 aopOp (pnum, ic, FALSE, FALSE);
13200 emitcode ("mov","a,%s",aopGet(pnum,0,FALSE,FALSE,DP2_RESULT_REG));
13201 freeAsmop (pnum, NULL, ic, FALSE);
13202 emitcode ("lcall","NatLib_LoadPrimitive");
13203 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
13204 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
13205 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
13206 for (i = (size-1) ; i >= 0 ; i-- ) {
13207 emitcode ("push","a%s",javaRet[i]);
13209 for (i=0; i < size ; i++ ) {
13210 emitcode ("pop","a%s",
13211 aopGet(result,i,FALSE,FALSE,DP2_RESULT_REG));
13214 for (i = 0 ; i < size ; i++ ) {
13215 aopPut(result,javaRet[i],i);
13218 freeAsmop (result, NULL, ic, FALSE);
13219 unsavermask(rsave);
13222 /*-----------------------------------------------------------------*/
13223 /* genNatLibLoadPointer - calls TINI api function to load pointer */
13224 /*-----------------------------------------------------------------*/
13225 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
13228 operand *pnum, *result;
13232 assert (nparms==1);
13233 /* save registers that need to be saved */
13234 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13235 ds390_rUmaskForOp (IC_RESULT(ic))));
13238 aopOp (pnum, ic, FALSE, FALSE);
13239 emitcode ("mov","a,%s",aopGet(pnum,0,FALSE,FALSE,DP2_RESULT_REG));
13240 freeAsmop (pnum, NULL, ic, FALSE);
13241 emitcode ("lcall","NatLib_LoadPointer");
13242 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
13243 if (AOP_TYPE(result)!=AOP_STR) {
13244 for (i = 0 ; i < size ; i++ ) {
13245 aopPut(result,fReturn[i],i);
13248 freeAsmop (result, NULL, ic, FALSE);
13249 unsavermask(rsave);
13252 /*-----------------------------------------------------------------*/
13253 /* genNatLibInstallStateBlock - */
13254 /*-----------------------------------------------------------------*/
13255 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
13256 operand **parms, const char *name)
13259 operand *psb, *handle;
13260 assert (nparms==2);
13262 /* save registers that need to be saved */
13263 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13264 ds390_rUmaskForOp (IC_RESULT(ic))));
13268 /* put pointer to state block into DPTR1 */
13269 aopOp (psb, ic, FALSE, FALSE);
13270 if (AOP_TYPE (psb) == AOP_IMMD) {
13271 emitcode ("mov","dps,#1");
13272 emitcode ("mov", "dptr,%s",
13273 aopGet (psb, 0, TRUE, FALSE, DP2_RESULT_REG));
13274 emitcode ("mov","dps,#0");
13276 emitcode ("mov","dpl1,%s",aopGet(psb,0,FALSE,FALSE,DP2_RESULT_REG));
13277 emitcode ("mov","dph1,%s",aopGet(psb,1,FALSE,FALSE,DP2_RESULT_REG));
13278 emitcode ("mov","dpx1,%s",aopGet(psb,2,FALSE,FALSE,DP2_RESULT_REG));
13280 freeAsmop (psb, NULL, ic, FALSE);
13282 /* put libraryID into DPTR */
13283 emitcode ("mov","dptr,#LibraryID");
13285 /* put handle into r3:r2 */
13286 aopOp (handle, ic, FALSE, FALSE);
13287 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13288 emitcode ("push","%s",aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13289 emitcode ("push","%s",aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13290 emitcode ("pop","ar3");
13291 emitcode ("pop","ar2");
13293 emitcode ("mov","r2,%s",aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13294 emitcode ("mov","r3,%s",aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13296 freeAsmop (psb, NULL, ic, FALSE);
13298 /* make the call */
13299 emitcode ("lcall","NatLib_Install%sStateBlock",name);
13301 /* put return value into place*/
13303 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
13305 aopPut(IC_RESULT(ic),"a",0);
13306 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13307 unsavermask(rsave);
13310 /*-----------------------------------------------------------------*/
13311 /* genNatLibRemoveStateBlock - */
13312 /*-----------------------------------------------------------------*/
13313 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
13319 /* save registers that need to be saved */
13320 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13321 ds390_rUmaskForOp (IC_RESULT(ic))));
13323 /* put libraryID into DPTR */
13324 emitcode ("mov","dptr,#LibraryID");
13325 /* make the call */
13326 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
13327 unsavermask(rsave);
13330 /*-----------------------------------------------------------------*/
13331 /* genNatLibGetStateBlock - */
13332 /*-----------------------------------------------------------------*/
13333 static void genNatLibGetStateBlock(iCode *ic,int nparms,
13334 operand **parms,const char *name)
13337 symbol *lbl = newiTempLabel(NULL);
13340 /* save registers that need to be saved */
13341 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13342 ds390_rUmaskForOp (IC_RESULT(ic))));
13344 /* put libraryID into DPTR */
13345 emitcode ("mov","dptr,#LibraryID");
13346 /* make the call */
13347 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
13348 emitcode ("jnz","!tlabel",lbl->key+100);
13350 /* put return value into place */
13351 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
13352 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
13353 emitcode ("push","ar3");
13354 emitcode ("push","ar2");
13355 emitcode ("pop","%s",
13356 aopGet(IC_RESULT(ic),0,FALSE,TRUE,DP2_RESULT_REG));
13357 emitcode ("pop","%s",
13358 aopGet(IC_RESULT(ic),1,FALSE,TRUE,DP2_RESULT_REG));
13360 aopPut(IC_RESULT(ic),"r2",0);
13361 aopPut(IC_RESULT(ic),"r3",1);
13363 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13365 unsavermask(rsave);
13368 /*-----------------------------------------------------------------*/
13369 /* genMMMalloc - */
13370 /*-----------------------------------------------------------------*/
13371 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
13372 int size, const char *name)
13377 symbol *lbl = newiTempLabel(NULL);
13379 assert (nparms == 1);
13380 /* save registers that need to be saved */
13381 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13382 ds390_rUmaskForOp (IC_RESULT(ic))));
13385 aopOp (bsize,ic,FALSE,FALSE);
13387 /* put the size in R4-R2 */
13388 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
13389 emitcode("push","%s",aopGet(bsize,0,FALSE,TRUE,DP2_RESULT_REG));
13390 emitcode("push","%s",aopGet(bsize,1,FALSE,TRUE,DP2_RESULT_REG));
13392 emitcode("push","%s",aopGet(bsize,2,FALSE,TRUE,DP2_RESULT_REG));
13393 emitcode("pop","ar4");
13395 emitcode("pop","ar3");
13396 emitcode("pop","ar2");
13398 emitcode ("mov","r2,%s",aopGet(bsize,0,FALSE,TRUE,DP2_RESULT_REG));
13399 emitcode ("mov","r3,%s",aopGet(bsize,1,FALSE,TRUE,DP2_RESULT_REG));
13401 emitcode("mov","r4,%s",aopGet(bsize,2,FALSE,TRUE,DP2_RESULT_REG));
13404 freeAsmop (bsize, NULL, ic, FALSE);
13406 /* make the call */
13407 emitcode ("lcall","MM_%s",name);
13408 emitcode ("jz","!tlabel",lbl->key+100);
13409 emitcode ("mov","r2,#!constbyte",0xff);
13410 emitcode ("mov","r3,#!constbyte",0xff);
13412 /* we don't care about the pointer : we just save the handle */
13413 rsym = OP_SYMBOL(IC_RESULT(ic));
13414 if (rsym->liveFrom != rsym->liveTo) {
13415 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
13416 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
13417 emitcode ("push","ar3");
13418 emitcode ("push","ar2");
13419 emitcode ("pop","%s",
13420 aopGet(IC_RESULT(ic),0,FALSE,TRUE,DP2_RESULT_REG));
13421 emitcode ("pop","%s",
13422 aopGet(IC_RESULT(ic),1,FALSE,TRUE,DP2_RESULT_REG));
13424 aopPut(IC_RESULT(ic),"r2",0);
13425 aopPut(IC_RESULT(ic),"r3",1);
13427 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13429 unsavermask(rsave);
13432 /*-----------------------------------------------------------------*/
13434 /*-----------------------------------------------------------------*/
13435 static void genMMDeref (iCode *ic,int nparms, operand **parms)
13440 assert (nparms == 1);
13441 /* save registers that need to be saved */
13442 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13443 ds390_rUmaskForOp (IC_RESULT(ic))));
13446 aopOp (handle,ic,FALSE,FALSE);
13448 /* put the size in R4-R2 */
13449 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13450 emitcode("push","%s",
13451 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13452 emitcode("push","%s",
13453 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13454 emitcode("pop","ar3");
13455 emitcode("pop","ar2");
13457 emitcode ("mov","r2,%s",
13458 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13459 emitcode ("mov","r3,%s",
13460 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13462 freeAsmop (handle, NULL, ic, FALSE);
13464 /* make the call */
13465 emitcode ("lcall","MM_Deref");
13468 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13469 if (rsym->liveFrom != rsym->liveTo) {
13470 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13471 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
13472 _startLazyDPSEvaluation ();
13474 aopPut(IC_RESULT(ic),"dpl",0);
13475 aopPut(IC_RESULT(ic),"dph",1);
13476 aopPut(IC_RESULT(ic),"dpx",2);
13478 _endLazyDPSEvaluation ();
13483 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13484 unsavermask(rsave);
13487 /*-----------------------------------------------------------------*/
13488 /* genMMUnrestrictedPersist - */
13489 /*-----------------------------------------------------------------*/
13490 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
13495 assert (nparms == 1);
13496 /* save registers that need to be saved */
13497 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13498 ds390_rUmaskForOp (IC_RESULT(ic))));
13501 aopOp (handle,ic,FALSE,FALSE);
13503 /* put the size in R3-R2 */
13504 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13505 emitcode("push","%s",
13506 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13507 emitcode("push","%s",
13508 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13509 emitcode("pop","ar3");
13510 emitcode("pop","ar2");
13512 emitcode ("mov","r2,%s",
13513 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13514 emitcode ("mov","r3,%s",
13515 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13517 freeAsmop (handle, NULL, ic, FALSE);
13519 /* make the call */
13520 emitcode ("lcall","MM_UnrestrictedPersist");
13523 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13524 if (rsym->liveFrom != rsym->liveTo) {
13525 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13526 aopPut(IC_RESULT(ic),"a",0);
13527 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13530 unsavermask(rsave);
13533 /*-----------------------------------------------------------------*/
13534 /* genSystemExecJavaProcess - */
13535 /*-----------------------------------------------------------------*/
13536 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
13539 operand *handle, *pp;
13541 assert (nparms==2);
13542 /* save registers that need to be saved */
13543 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13544 ds390_rUmaskForOp (IC_RESULT(ic))));
13549 /* put the handle in R3-R2 */
13550 aopOp (handle,ic,FALSE,FALSE);
13551 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13552 emitcode("push","%s",
13553 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13554 emitcode("push","%s",
13555 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13556 emitcode("pop","ar3");
13557 emitcode("pop","ar2");
13559 emitcode ("mov","r2,%s",
13560 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13561 emitcode ("mov","r3,%s",
13562 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13564 freeAsmop (handle, NULL, ic, FALSE);
13566 /* put pointer in DPTR */
13567 aopOp (pp,ic,FALSE,FALSE);
13568 if (AOP_TYPE(pp) == AOP_IMMD) {
13569 emitcode ("mov", "dptr,%s",
13570 aopGet (pp, 0, TRUE, FALSE, NULL));
13571 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
13572 emitcode ("mov","dpl,%s",aopGet(pp,0,FALSE,FALSE,NULL));
13573 emitcode ("mov","dph,%s",aopGet(pp,1,FALSE,FALSE,NULL));
13574 emitcode ("mov","dpx,%s",aopGet(pp,2,FALSE,FALSE,NULL));
13576 freeAsmop (handle, NULL, ic, FALSE);
13578 /* make the call */
13579 emitcode ("lcall","System_ExecJavaProcess");
13581 /* put result in place */
13583 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13584 if (rsym->liveFrom != rsym->liveTo) {
13585 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13586 aopPut(IC_RESULT(ic),"a",0);
13587 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13591 unsavermask(rsave);
13594 /*-----------------------------------------------------------------*/
13595 /* genSystemRTCRegisters - */
13596 /*-----------------------------------------------------------------*/
13597 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
13603 assert (nparms==1);
13604 /* save registers that need to be saved */
13605 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13606 ds390_rUmaskForOp (IC_RESULT(ic))));
13609 /* put pointer in DPTR */
13610 aopOp (pp,ic,FALSE,FALSE);
13611 if (AOP_TYPE (pp) == AOP_IMMD) {
13612 emitcode ("mov","dps,#1");
13613 emitcode ("mov", "dptr,%s",
13614 aopGet (pp, 0, TRUE, FALSE, NULL));
13615 emitcode ("mov","dps,#0");
13617 emitcode ("mov","dpl1,%s",
13618 aopGet(pp,0,FALSE,FALSE,DP2_RESULT_REG));
13619 emitcode ("mov","dph1,%s",
13620 aopGet(pp,1,FALSE,FALSE,DP2_RESULT_REG));
13621 emitcode ("mov","dpx1,%s",
13622 aopGet(pp,2,FALSE,FALSE,DP2_RESULT_REG));
13624 freeAsmop (pp, NULL, ic, FALSE);
13626 /* make the call */
13627 emitcode ("lcall","System_%sRTCRegisters",name);
13629 unsavermask(rsave);
13632 /*-----------------------------------------------------------------*/
13633 /* genSystemThreadSleep - */
13634 /*-----------------------------------------------------------------*/
13635 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
13640 assert (nparms==1);
13641 /* save registers that need to be saved */
13642 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13643 ds390_rUmaskForOp (IC_RESULT(ic))));
13646 aopOp(to,ic,FALSE,FALSE);
13647 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
13648 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
13649 emitcode ("push","%s",
13650 aopGet(to,0,FALSE,TRUE,DP2_RESULT_REG));
13651 emitcode ("push","%s",
13652 aopGet(to,1,FALSE,TRUE,DP2_RESULT_REG));
13653 emitcode ("push","%s",
13654 aopGet(to,2,FALSE,TRUE,DP2_RESULT_REG));
13655 emitcode ("push","%s",
13656 aopGet(to,3,FALSE,TRUE,DP2_RESULT_REG));
13657 emitcode ("pop","ar3");
13658 emitcode ("pop","ar2");
13659 emitcode ("pop","ar1");
13660 emitcode ("pop","ar0");
13662 emitcode ("mov","r0,%s",
13663 aopGet(to,0,FALSE,TRUE,DP2_RESULT_REG));
13664 emitcode ("mov","r1,%s",
13665 aopGet(to,1,FALSE,TRUE,DP2_RESULT_REG));
13666 emitcode ("mov","r2,%s",
13667 aopGet(to,2,FALSE,TRUE,DP2_RESULT_REG));
13668 emitcode ("mov","r3,%s",
13669 aopGet(to,3,FALSE,TRUE,DP2_RESULT_REG));
13671 freeAsmop (to, NULL, ic, FALSE);
13673 /* suspend in acc */
13675 aopOp(s,ic,FALSE,FALSE);
13676 emitcode ("mov","a,%s",
13677 aopGet(s,0,FALSE,TRUE,NULL));
13678 freeAsmop (s, NULL, ic, FALSE);
13680 /* make the call */
13681 emitcode ("lcall","System_%s",name);
13683 unsavermask(rsave);
13686 /*-----------------------------------------------------------------*/
13687 /* genSystemThreadResume - */
13688 /*-----------------------------------------------------------------*/
13689 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
13694 assert (nparms==2);
13695 /* save registers that need to be saved */
13696 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13697 ds390_rUmaskForOp (IC_RESULT(ic))));
13703 aopOp(pid,ic,FALSE,FALSE);
13704 emitcode ("mov","r0,%s",
13705 aopGet(pid,0,FALSE,TRUE,DP2_RESULT_REG));
13706 freeAsmop (pid, NULL, ic, FALSE);
13709 aopOp(tid,ic,FALSE,FALSE);
13710 emitcode ("mov","a,%s",
13711 aopGet(tid,0,FALSE,TRUE,DP2_RESULT_REG));
13712 freeAsmop (tid, NULL, ic, FALSE);
13714 emitcode ("lcall","System_ThreadResume");
13716 /* put result into place */
13718 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13719 if (rsym->liveFrom != rsym->liveTo) {
13720 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13721 aopPut(IC_RESULT(ic),"a",0);
13722 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13725 unsavermask(rsave);
13728 /*-----------------------------------------------------------------*/
13729 /* genSystemProcessResume - */
13730 /*-----------------------------------------------------------------*/
13731 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
13736 assert (nparms==1);
13737 /* save registers that need to be saved */
13738 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13739 ds390_rUmaskForOp (IC_RESULT(ic))));
13744 aopOp(pid,ic,FALSE,FALSE);
13745 emitcode ("mov","a,%s",
13746 aopGet(pid,0,FALSE,TRUE,DP2_RESULT_REG));
13747 freeAsmop (pid, NULL, ic, FALSE);
13749 emitcode ("lcall","System_ProcessResume");
13751 unsavermask(rsave);
13754 /*-----------------------------------------------------------------*/
13756 /*-----------------------------------------------------------------*/
13757 static void genSystem (iCode *ic,int nparms,char *name)
13759 assert(nparms == 0);
13761 emitcode ("lcall","System_%s",name);
13764 /*-----------------------------------------------------------------*/
13765 /* genSystemPoll - */
13766 /*-----------------------------------------------------------------*/
13767 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
13772 assert (nparms==1);
13773 /* save registers that need to be saved */
13774 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13775 ds390_rUmaskForOp (IC_RESULT(ic))));
13778 aopOp (fp,ic,FALSE,FALSE);
13779 if (AOP_TYPE (fp) == AOP_IMMD) {
13780 emitcode ("mov", "dptr,%s",
13781 aopGet (fp, 0, TRUE, FALSE, DP2_RESULT_REG));
13782 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
13783 emitcode ("mov","dpl,%s",
13784 aopGet(fp,0,FALSE,FALSE,DP2_RESULT_REG));
13785 emitcode ("mov","dph,%s",
13786 aopGet(fp,1,FALSE,FALSE,DP2_RESULT_REG));
13787 emitcode ("mov","dpx,%s",
13788 aopGet(fp,2,FALSE,FALSE,DP2_RESULT_REG));
13790 freeAsmop (fp, NULL, ic, FALSE);
13792 emitcode ("lcall","System_%sPoll",name);
13794 /* put result into place */
13796 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13797 if (rsym->liveFrom != rsym->liveTo) {
13798 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13799 aopPut(IC_RESULT(ic),"a",0);
13800 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13803 unsavermask(rsave);
13806 /*-----------------------------------------------------------------*/
13807 /* genSystemGetCurrentID - */
13808 /*-----------------------------------------------------------------*/
13809 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
13811 assert (nparms==0);
13813 emitcode ("lcall","System_GetCurrent%sId",name);
13814 /* put result into place */
13816 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13817 if (rsym->liveFrom != rsym->liveTo) {
13818 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13819 aopPut(IC_RESULT(ic),"a",0);
13820 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13825 /*-----------------------------------------------------------------*/
13826 /* genDjnz - generate decrement & jump if not zero instrucion */
13827 /*-----------------------------------------------------------------*/
13829 genDjnz (iCode * ic, iCode * ifx)
13831 symbol *lbl, *lbl1;
13835 /* if the if condition has a false label
13836 then we cannot save */
13837 if (IC_FALSE (ifx))
13840 /* if the minus is not of the form a = a - 1 */
13841 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
13842 !IS_OP_LITERAL (IC_RIGHT (ic)))
13845 if (operandLitValue (IC_RIGHT (ic)) != 1)
13848 /* if the size of this greater than one then no
13850 if (getSize (operandType (IC_RESULT (ic))) > 1)
13853 /* otherwise we can save BIG */
13855 D (emitcode (";", "genDjnz"));
13857 lbl = newiTempLabel (NULL);
13858 lbl1 = newiTempLabel (NULL);
13860 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
13862 if (AOP_NEEDSACC(IC_RESULT(ic)))
13864 /* If the result is accessed indirectly via
13865 * the accumulator, we must explicitly write
13866 * it back after the decrement.
13868 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE, NULL);
13870 if (strcmp(rByte, "a"))
13872 /* Something is hopelessly wrong */
13873 fprintf(stderr, "*** warning: internal error at %s:%d\n",
13874 __FILE__, __LINE__);
13875 /* We can just give up; the generated code will be inefficient,
13876 * but what the hey.
13878 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13881 emitcode ("dec", "%s", rByte);
13882 aopPut (IC_RESULT (ic), rByte, 0);
13883 emitcode ("jnz", "!tlabel", lbl->key + 100);
13885 else if (IS_AOP_PREG (IC_RESULT (ic)))
13887 emitcode ("dec", "%s",
13888 aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL));
13889 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL));
13890 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13891 ifx->generated = 1;
13892 emitcode ("jnz", "!tlabel", lbl->key + 100);
13896 emitcode ("djnz", "%s,!tlabel", aopGet (IC_RESULT (ic), 0, FALSE, TRUE, NULL),
13899 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
13901 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
13904 if (!ifx->generated)
13905 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13906 ifx->generated = 1;
13910 /*-----------------------------------------------------------------*/
13911 /* genReceive - generate code for a receive iCode */
13912 /*-----------------------------------------------------------------*/
13914 genReceive (iCode * ic)
13916 int size = getSize (operandType (IC_RESULT (ic)));
13920 D (emitcode (";", "genReceive"));
13922 if (ic->argreg == 1)
13924 /* first parameter */
13925 if (AOP_IS_STR(IC_RESULT(ic)))
13927 /* Nothing to do: it's already in the proper place. */
13934 useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
13935 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
13936 IS_TRUE_SYMOP (IC_RESULT (ic)));
13939 aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
13942 /* Sanity checking... */
13943 if (AOP_USESDPTR(IC_RESULT(ic)))
13945 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
13946 "genReceive got unexpected DPTR.");
13948 assignResultValue (IC_RESULT (ic), NULL);
13951 else if (ic->argreg > 12)
13952 { /* bit parameters */
13953 if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
13955 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
13956 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
13957 outBitC(IC_RESULT (ic));
13962 /* second receive onwards */
13963 /* this gets a little tricky since unused receives will be
13964 eliminated, we have saved the reg in the type field . and
13965 we use that to figure out which register to use */
13966 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
13967 rb1off = ic->argreg;
13970 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
13973 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13976 /*-----------------------------------------------------------------*/
13977 /* genDummyRead - generate code for dummy read of volatiles */
13978 /*-----------------------------------------------------------------*/
13980 genDummyRead (iCode * ic)
13985 D (emitcode(";", "genDummyRead"));
13987 op = IC_RIGHT (ic);
13988 if (op && IS_SYMOP (op))
13990 aopOp (op, ic, FALSE, FALSE);
13992 /* if the result is a bit */
13993 if (AOP_TYPE (op) == AOP_CRY)
13994 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13997 /* bit variables done */
13999 size = AOP_SIZE (op);
14003 MOVA (aopGet (op, offset, FALSE, FALSE, FALSE));
14008 freeAsmop (op, NULL, ic, TRUE);
14012 if (op && IS_SYMOP (op))
14014 aopOp (op, ic, FALSE, FALSE);
14016 /* if the result is a bit */
14017 if (AOP_TYPE (op) == AOP_CRY)
14018 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
14021 /* bit variables done */
14023 size = AOP_SIZE (op);
14027 MOVA (aopGet (op, offset, FALSE, FALSE, FALSE));
14032 freeAsmop (op, NULL, ic, TRUE);
14036 /*-----------------------------------------------------------------*/
14037 /* genCritical - generate code for start of a critical sequence */
14038 /*-----------------------------------------------------------------*/
14040 genCritical (iCode *ic)
14042 symbol *tlbl = newiTempLabel (NULL);
14044 D (emitcode(";", "genCritical"));
14046 if (IC_RESULT (ic))
14048 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
14049 aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
14050 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
14051 aopPut (IC_RESULT (ic), zero, 0);
14053 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
14057 emitcode ("setb", "c");
14058 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
14059 emitcode ("clr", "c");
14061 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
14065 /*-----------------------------------------------------------------*/
14066 /* genEndCritical - generate code for end of a critical sequence */
14067 /*-----------------------------------------------------------------*/
14069 genEndCritical (iCode *ic)
14071 D(emitcode(";", "genEndCritical"));
14075 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
14076 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
14078 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
14079 emitcode ("mov", "ea,c");
14083 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE, FALSE));
14084 emitcode ("rrc", "a");
14085 emitcode ("mov", "ea,c");
14087 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
14091 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
14092 emitcode ("mov", "ea,c");
14098 /*-----------------------------------------------------------------*/
14099 /* genBuiltIn - calls the appropriate function to generating code */
14100 /* for a built in function */
14101 /*-----------------------------------------------------------------*/
14102 static void genBuiltIn (iCode *ic)
14104 operand *bi_parms[MAX_BUILTIN_ARGS];
14109 /* get all the arguments for a built in function */
14110 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
14112 /* which function is it */
14113 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
14114 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
14115 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
14116 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
14117 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
14118 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
14119 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
14120 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
14121 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
14122 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
14123 genMemsetX(bi_iCode,nbi_parms,bi_parms);
14124 } else if (strcmp(bif->name,"__builtin_inp")==0) {
14125 genInp(bi_iCode,nbi_parms,bi_parms);
14126 } else if (strcmp(bif->name,"__builtin_outp")==0) {
14127 genOutp(bi_iCode,nbi_parms,bi_parms);
14128 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
14129 genSwapW(bi_iCode,nbi_parms,bi_parms);
14130 /* JavaNative builtIns */
14131 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
14132 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
14133 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
14134 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
14135 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
14136 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
14137 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
14138 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
14139 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
14140 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
14141 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
14142 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
14143 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
14144 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
14145 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
14146 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
14147 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
14148 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
14149 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
14150 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
14151 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
14152 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
14153 } else if (strcmp(bif->name,"MM_Malloc")==0) {
14154 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
14155 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
14156 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
14157 } else if (strcmp(bif->name,"MM_Free")==0) {
14158 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
14159 } else if (strcmp(bif->name,"MM_Deref")==0) {
14160 genMMDeref(bi_iCode,nbi_parms,bi_parms);
14161 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
14162 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
14163 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
14164 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
14165 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
14166 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
14167 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
14168 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
14169 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
14170 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
14171 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
14172 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
14173 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
14174 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
14175 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
14176 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
14177 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
14178 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
14179 } else if (strcmp(bif->name,"System_SaveThread")==0) {
14180 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
14181 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
14182 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
14183 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
14184 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
14185 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
14186 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
14187 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
14188 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
14189 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
14190 genSystem(bi_iCode,nbi_parms,"ProcessYield");
14191 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
14192 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
14193 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
14194 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
14195 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
14196 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
14197 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
14198 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
14199 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
14200 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
14202 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
14208 /*-----------------------------------------------------------------*/
14209 /* gen390Code - generate code for Dallas 390 based controllers */
14210 /*-----------------------------------------------------------------*/
14212 gen390Code (iCode * lic)
14217 _G.currentFunc = NULL;
14218 lineHead = lineCurr = NULL;
14219 dptrn[1][0] = "dpl1";
14220 dptrn[1][1] = "dph1";
14221 dptrn[1][2] = "dpx1";
14223 if (options.model == MODEL_FLAT24) {
14224 fReturnSizeDS390 = 5;
14225 fReturn = fReturn24;
14227 fReturnSizeDS390 = 4;
14228 fReturn = fReturn16;
14229 options.stack10bit=0;
14232 /* print the allocation information */
14233 if (allocInfo && currFunc)
14234 printAllocInfo (currFunc, codeOutBuf);
14236 /* if debug information required */
14237 if (options.debug && currFunc)
14239 debugFile->writeFunction (currFunc, lic);
14241 /* stack pointer name */
14242 if (options.useXstack)
14248 for (ic = lic; ic; ic = ic->next)
14250 _G.current_iCode = ic;
14252 if (ic->lineno && cln != ic->lineno)
14256 debugFile->writeCLine (ic);
14258 if (!options.noCcodeInAsm) {
14259 emitcode (";", "%s:%d: %s", ic->filename, ic->lineno,
14260 printCLine(ic->filename, ic->lineno));
14264 if (options.iCodeInAsm) {
14265 const char *iLine = printILine(ic);
14266 emitcode(";", "ic:%d: %s", ic->key, iLine);
14269 /* if the result is marked as
14270 spilt and rematerializable or code for
14271 this has already been generated then
14273 if (resultRemat (ic) || ic->generated)
14276 /* depending on the operation */
14296 /* IPOP happens only when trying to restore a
14297 spilt live range, if there is an ifx statement
14298 following this pop then the if statement might
14299 be using some of the registers being popped which
14300 would destory the contents of the register so
14301 we need to check for this condition and handle it */
14303 ic->next->op == IFX &&
14304 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
14305 genIfx (ic->next, ic);
14323 genEndFunction (ic);
14343 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
14360 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
14364 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
14371 /* note these two are xlated by algebraic equivalence
14372 during parsing SDCC.y */
14373 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
14374 "got '>=' or '<=' shouldn't have come here");
14378 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
14390 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
14394 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
14398 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
14422 genRightShift (ic);
14425 case GET_VALUE_AT_ADDRESS:
14427 hasInc (IC_LEFT (ic), ic,
14428 getSize (operandType (IC_RESULT (ic)))));
14432 if (POINTER_SET (ic))
14434 hasInc (IC_RESULT (ic), ic,
14435 getSize (operandType (IC_RIGHT (ic)))));
14461 if (ic->builtinSEND)
14464 addSet (&_G.sendSet, ic);
14467 case DUMMY_READ_VOLATILE:
14476 genEndCritical (ic);
14483 #if 0 // obsolete, and buggy for != xdata
14490 /* This should never happen, right? */
14491 fprintf(stderr, "*** Probable error: unsupported op 0x%x (%c) in %s @ %d\n",
14492 ic->op, ic->op, __FILE__, __LINE__);
14498 /* now we are ready to call the
14499 peep hole optimizer */
14500 if (!options.nopeep)
14501 peepHole (&lineHead);
14503 /* now do the actual printing */
14504 printLine (lineHead, codeOutBuf);