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 -------------------------------------------------------------------------*/
35 #include "SDCCglobl.h"
43 #define BETTER_LITERAL_SHIFT
45 char *aopLiteral (value * val, int offset);
48 /* this is the down and dirty file with all kinds of
49 kludgy & hacky stuff. This is what it is all about
50 CODE GENERATION for a specific MCU . some of the
51 routines may be reusable, will have to see */
53 static char *zero = "#0";
54 static char *one = "#1";
57 #define TR_DPTR(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_DPTR1 %s ", s); }
58 #define TR_AP(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_AP %s ", s); }
60 unsigned fReturnSizeDS390 = 5;
61 static char *fReturn24[] =
62 {"dpl", "dph", "dpx", "b", "a"};
63 static char *fReturn16[] =
64 {"dpl", "dph", "b", "a"};
65 static char **fReturn = fReturn24;
66 static char *accUse[] =
68 static char *dptrn[2][3];
69 static char *javaRet[] = { "r0","r1","r2","r3"};
70 static short rbank = -1;
72 #define REG_WITH_INDEX ds390_regWithIdx
74 #define AOP(op) op->aop
75 #define AOP_TYPE(op) AOP(op)->type
76 #define AOP_SIZE(op) AOP(op)->size
77 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
78 AOP_TYPE(x) == AOP_R0))
80 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
81 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
84 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
85 (x->aopu.aop_reg[0] == REG_WITH_INDEX(R0_IDX) || \
86 x->aopu.aop_reg[0] == REG_WITH_INDEX(R1_IDX) )))
87 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
88 #define AOP_USESDPTR(x) ((AOP_TYPE(x) == AOP_DPTR) || (AOP_TYPE(x) == AOP_STR))
89 #define AOP_USESDPTR2(x) ((AOP_TYPE(x) == AOP_DPTR2) || (AOP_TYPE(x) == AOP_DPTRn))
91 // The following two macros can be used even if the aop has not yet been aopOp'd.
92 #define AOP_IS_STR(x) (IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
93 #define AOP_IS_DPTRn(x) (IS_SYMOP(x) && OP_SYMBOL(x)->dptr)
95 /* Workaround for DS80C390 bug: div ab may return bogus results
96 * if A is accessed in instruction immediately before the div.
98 * Will be fixed in B4 rev of processor, Dallas claims.
101 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
102 if (!AOP_NEEDSACC(RIGHT)) \
104 /* We can load A first, then B, since \
105 * B (the RIGHT operand) won't clobber A, \
106 * thus avoiding touching A right before the div. \
108 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
109 L = aopGet(LEFT,0,FALSE,FALSE,NULL); \
111 L = aopGet(RIGHT,0,FALSE,FALSE,"b"); \
116 /* Just stuff in a nop after loading A. */ \
117 emitcode("mov","b,%s",aopGet(RIGHT,0,FALSE,FALSE,NULL));\
118 L = aopGet(LEFT,0,FALSE,FALSE,NULL); \
120 emitcode("nop", "; workaround for DS80C390 div bug."); \
123 #define R0INB _G.bu.bs.r0InB
124 #define R1INB _G.bu.bs.r1InB
125 #define OPINB _G.bu.bs.OpInB
126 #define BINUSE _G.bu.BInUse
136 short r0InB : 2;//2 so we can see it overflow
137 short r1InB : 2;//2 so we can see it overflow
138 short OpInB : 2;//2 so we can see it overflow
149 iCode *current_iCode;
154 static char *rb1regs[] = {
155 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7",
156 "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7"
159 static void saveRBank (int, iCode *, bool);
161 #define RESULTONSTACK(x) \
162 (IC_RESULT(x) && IC_RESULT(x)->aop && \
163 IC_RESULT(x)->aop->type == AOP_STK )
165 #define MOVA(x) mova(x) /* use function to avoid multiple eval */
166 #define MOVB(x) movb(x)
168 #define CLRC emitcode("clr","c")
169 #define SETC emitcode("setb","c")
171 // A scratch register which will be used to hold
172 // result bytes from operands in far space via DPTR2.
173 #define DP2_RESULT_REG "_ap"
175 static lineNode *lineHead = NULL;
176 static lineNode *lineCurr = NULL;
178 static unsigned char SLMask[] =
179 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
180 0xE0, 0xC0, 0x80, 0x00};
181 static unsigned char SRMask[] =
182 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
183 0x07, 0x03, 0x01, 0x00};
189 #define PROTECT_SP {if (options.protect_sp_update) { \
190 symbol *lbl = newiTempLabel(NULL); \
191 emitcode ("setb","F1"); \
192 emitcode ("jbc","EA,!tlabel",lbl->key+100); \
193 emitcode ("clr","F1"); \
194 emitcode ("","!tlabeldef",lbl->key+100); \
196 #define UNPROTECT_SP { if (options.protect_sp_update) { \
197 emitcode ("mov","EA,F1"); \
200 static int _currentDPS; /* Current processor DPS. */
201 static int _desiredDPS; /* DPS value compiler thinks we should be using. */
202 static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */
204 /*-----------------------------------------------------------------*/
205 /* emitcode - writes the code into a file : for now it is simple */
206 /*-----------------------------------------------------------------*/
208 emitcode (char *inst, const char *fmt,...)
211 char lb[INITIAL_INLINEASM];
220 SNPRINTF (lb, sizeof(lb), "%s\t", inst);
224 SNPRINTF (lb, sizeof(lb), "%s", inst);
227 tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb), fmt, ap);
231 tvsprintf (lb, sizeof(lb), fmt, ap);
234 while (isspace ((unsigned char)*lbp))
241 lineCurr = (lineCurr ?
242 connectLine (lineCurr, newLineNode (lb)) :
243 (lineHead = newLineNode (lb)));
246 lineCurr->isInline = _G.inLine;
247 lineCurr->isDebug = _G.debugLine;
248 lineCurr->ic = _G.current_iCode;
249 lineCurr->aln = ds390newAsmLineNode(_currentDPS);
254 emitLabel (symbol *tlbl)
256 emitcode ("", "!tlabeldef", tlbl->key + 100);
259 /*-----------------------------------------------------------------*/
260 /* ds390_emitDebuggerSymbol - associate the current code location */
261 /* with a debugger symbol */
262 /*-----------------------------------------------------------------*/
264 ds390_emitDebuggerSymbol (char * debugSym)
267 emitcode ("", "%s ==.", debugSym);
271 /*-----------------------------------------------------------------*/
272 /* mova - moves specified value into accumulator */
273 /*-----------------------------------------------------------------*/
277 /* do some early peephole optimization */
278 if (!strncmp(x, "a", 2) || !strncmp(x, "acc", 4))
281 emitcode("mov", "a,%s", x);
284 /*-----------------------------------------------------------------*/
285 /* movb - moves specified value into register b */
286 /*-----------------------------------------------------------------*/
290 /* do some early peephole optimization */
291 if (!strncmp(x, "b", 2))
294 emitcode("mov","b,%s", x);
297 /*-----------------------------------------------------------------*/
298 /* movc - moves specified value into the carry */
299 /*-----------------------------------------------------------------*/
307 else if (strcmp (s, "c"))
308 {/* it's not in carry already */
310 /* set C, if a >= 1 */
311 emitcode ("add", "a,#0xff");
315 /*-----------------------------------------------------------------*/
316 /* pushB - saves register B if necessary */
317 /*-----------------------------------------------------------------*/
321 bool pushedB = FALSE;
325 emitcode ("push", "b");
326 // printf("B was in use !\n");
336 /*-----------------------------------------------------------------*/
337 /* popB - restores value of register B if necessary */
338 /*-----------------------------------------------------------------*/
344 emitcode ("pop", "b");
352 /*-----------------------------------------------------------------*/
353 /* pushReg - saves register */
354 /*-----------------------------------------------------------------*/
356 pushReg (int index, bool bits_pushed)
358 regs * reg = REG_WITH_INDEX (index);
359 if (reg->type == REG_BIT)
362 emitcode ("push", "%s", reg->base);
366 emitcode ("push", "%s", reg->dname);
370 /*-----------------------------------------------------------------*/
371 /* popReg - restores register */
372 /*-----------------------------------------------------------------*/
374 popReg (int index, bool bits_popped)
376 regs * reg = REG_WITH_INDEX (index);
377 if (reg->type == REG_BIT)
380 emitcode ("pop", "%s", reg->base);
384 emitcode ("pop", "%s", reg->dname);
388 /*-----------------------------------------------------------------*/
389 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
390 /*-----------------------------------------------------------------*/
392 getFreePtr (iCode * ic, asmop ** aopp, bool result)
397 /* the logic: if r0 & r1 used in the instruction
398 then we are in trouble otherwise */
400 /* first check if r0 & r1 are used by this
401 instruction, in which case we are in trouble */
402 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
403 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
408 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
409 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
411 /* if no usage of r0 then return it */
414 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
415 (*aopp)->type = AOP_R0;
417 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
420 /* if no usage of r1 then return it */
423 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
424 (*aopp)->type = AOP_R1;
426 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R1_IDX);
429 /* now we know they both have usage */
430 /* if r0 not used in this instruction */
433 /* push it if not already pushed */
436 emitcode ("push", "%s",
437 REG_WITH_INDEX (R0_IDX)->dname);
441 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
442 (*aopp)->type = AOP_R0;
444 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
447 /* if r1 not used then */
451 /* push it if not already pushed */
454 emitcode ("push", "%s",
455 REG_WITH_INDEX (R1_IDX)->dname);
459 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
460 (*aopp)->type = AOP_R1;
461 return REG_WITH_INDEX (R1_IDX);
465 /* I said end of world, but not quite end of world yet */
466 /* if this is a result then we can push it on the stack */
469 (*aopp)->type = AOP_STK;
473 /* now this is REALLY the end of the world */
474 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
475 "getFreePtr should never reach here");
478 return NULL; // notreached, but makes compiler happy.
482 /*-----------------------------------------------------------------*/
483 /* genSetDPTR: generate code to select which DPTR is in use (zero */
484 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */
485 /* alternate DPTR (DPL1/DPH1/DPX1). */
486 /*-----------------------------------------------------------------*/
491 /* If we are doing lazy evaluation, simply note the desired
492 * change, but don't emit any code yet.
502 emitcode ("mov", "dps,#0");
507 emitcode ("mov", "dps,#1");
511 /*------------------------------------------------------------------*/
512 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
514 /* Any code that operates on DPTR (NB: not on the individual */
515 /* components, like DPH) *must* call _flushLazyDPS() before using */
516 /* DPTR within a lazy DPS evaluation block. */
518 /* Note that aopPut and aopGet already contain the proper calls to */
519 /* _flushLazyDPS, so it is safe to use these calls within a lazy */
520 /* DPS evaluation block. */
522 /* Also, _flushLazyDPS must be called before any flow control */
523 /* operations that could potentially branch out of the block. */
525 /* Lazy DPS evaluation is simply an optimization (though an */
526 /* important one), so if in doubt, leave it out. */
527 /*------------------------------------------------------------------*/
529 _startLazyDPSEvaluation (void)
533 #ifdef BETTER_LITERAL_SHIFT
540 /*------------------------------------------------------------------*/
541 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
542 /* desired one. Call before using DPTR within a lazy DPS evaluation */
544 /*------------------------------------------------------------------*/
554 if (_desiredDPS != _currentDPS)
558 emitcode ("inc", "dps");
562 emitcode ("dec", "dps");
564 _currentDPS = _desiredDPS;
568 /*-----------------------------------------------------------------*/
569 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
571 /* Forces us back to the safe state (standard DPTR selected). */
572 /*-----------------------------------------------------------------*/
574 _endLazyDPSEvaluation (void)
576 #ifdef BETTER_LITERAL_SHIFT
594 /*-----------------------------------------------------------------*/
595 /* newAsmop - creates a new asmOp */
596 /*-----------------------------------------------------------------*/
598 newAsmop (short type)
602 aop = Safe_calloc (1, sizeof (asmop));
608 /*-----------------------------------------------------------------*/
609 /* pointerCode - returns the code for a pointer type */
610 /*-----------------------------------------------------------------*/
612 pointerCode (sym_link * etype)
615 return PTR_TYPE (SPEC_OCLS (etype));
619 /*-----------------------------------------------------------------*/
620 /* leftRightUseAcc - returns size of accumulator use by operands */
621 /*-----------------------------------------------------------------*/
623 leftRightUseAcc(iCode *ic)
632 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
633 "null iCode pointer");
640 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
643 size = getSize (OP_SYMBOL (op)->type);
648 else if (ic->op == JUMPTABLE)
651 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
654 size = getSize (OP_SYMBOL (op)->type);
662 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
665 size = getSize (OP_SYMBOL (op)->type);
670 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
673 size = getSize (OP_SYMBOL (op)->type);
685 /*-----------------------------------------------------------------*/
686 /* aopForSym - for a true symbol */
687 /*-----------------------------------------------------------------*/
689 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
693 bool accuse = leftRightUseAcc (ic) || _G.accInUse;
694 char *dpl = useDP2 ? "dpl1" : "dpl";
695 char *dph = useDP2 ? "dph1" : "dph";
696 char *dpx = useDP2 ? "dpx1" : "dpx";
698 wassertl (ic != NULL, "Got a null iCode");
699 wassertl (sym != NULL, "Got a null symbol");
701 space = SPEC_OCLS (sym->etype);
703 /* if already has one */
706 if ((sym->aop->type == AOP_DPTR && useDP2)
707 || (sym->aop->type == AOP_DPTR2 && !useDP2))
711 sym->aop->allocated++;
716 /* assign depending on the storage class */
717 /* if it is on the stack or indirectly addressable */
718 /* space we need to assign either r0 or r1 to it */
719 if ((sym->onStack && !options.stack10bit) || sym->iaccess)
721 sym->aop = aop = newAsmop (0);
722 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
723 aop->size = getSize (sym->type);
725 /* now assign the address of the variable to
726 the pointer register */
727 if (aop->type != AOP_STK)
731 signed char offset = ((sym->stack < 0) ?
732 ((signed char) (sym->stack - _G.nRegsSaved)) :
733 ((signed char) sym->stack)) & 0xff;
735 if ((abs(offset) <= 3) ||
736 (accuse && (abs(offset) <= 7)))
738 emitcode ("mov", "%s,_bp",
739 aop->aopu.aop_ptr->name);
742 emitcode ("dec", aop->aopu.aop_ptr->name);
747 emitcode ("inc", aop->aopu.aop_ptr->name);
754 emitcode ("push", "acc");
755 emitcode ("mov", "a,_bp");
756 emitcode ("add", "a,#!constbyte", offset);
757 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
759 emitcode ("pop", "acc");
764 emitcode ("mov", "%s,#%s",
765 aop->aopu.aop_ptr->name,
768 aop->paged = space->paged;
771 aop->aopu.aop_stk = sym->stack;
775 if (sym->onStack && options.stack10bit)
777 short stack_val = -((sym->stack < 0) ?
778 ((short) (sym->stack - _G.nRegsSaved)) :
779 ((short) sym->stack)) ;
781 emitcode ("push",dpl);
782 emitcode ("push",dph);
783 emitcode ("push",dpx);
785 /* It's on the 10 bit stack, which is located in
788 if (stack_val < 0 && stack_val > -5)
789 { /* between -5 & -1 */
790 if (options.model == MODEL_FLAT24)
792 emitcode ("mov", "%s,#!constbyte", dpx,
793 (options.stack_loc >> 16) & 0xff);
795 emitcode ("mov", "%s,_bpx+1", dph);
796 emitcode ("mov", "%s,_bpx", dpl);
798 emitcode ("mov","dps,#1");
800 stack_val = -stack_val;
801 while (stack_val--) {
802 emitcode ("inc","dptr");
805 emitcode("mov","dps,#0");
811 emitcode ("push", "acc");
813 emitcode ("mov", "a,_bpx");
814 emitcode ("clr","c");
815 emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
816 emitcode ("mov","%s,a", dpl);
817 emitcode ("mov","a,_bpx+1");
818 emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
819 emitcode ("mov", "%s,a", dph);
820 if (options.model == MODEL_FLAT24)
822 emitcode ("mov", "%s,#!constbyte", dpx,
823 (options.stack_loc >> 16) & 0xff);
827 emitcode ("pop", "acc");
829 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
830 aop->size = getSize (sym->type);
834 /* if in bit space */
835 if (IN_BITSPACE (space))
837 sym->aop = aop = newAsmop (AOP_CRY);
838 aop->aopu.aop_dir = sym->rname;
839 aop->size = getSize (sym->type);
842 /* if it is in direct space */
843 if (IN_DIRSPACE (space))
845 sym->aop = aop = newAsmop (AOP_DIR);
846 aop->aopu.aop_dir = sym->rname;
847 aop->size = getSize (sym->type);
851 /* special case for a function */
852 if (IS_FUNC (sym->type) && !(sym->isitmp))
854 sym->aop = aop = newAsmop (AOP_IMMD);
855 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
856 aop->size = FPTRSIZE;
860 /* only remaining is far space */
861 /* in which case DPTR gets the address */
862 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
867 emitcode ("mov", "dptr,#%s", sym->rname);
872 emitcode ("mov", "dptr,#%s", sym->rname);
874 aop->size = getSize (sym->type);
876 /* if it is in code space */
877 if (IN_CODESPACE (space))
883 /*-----------------------------------------------------------------*/
884 /* aopForRemat - rematerialzes an object */
885 /*-----------------------------------------------------------------*/
887 aopForRemat (symbol * sym)
889 iCode *ic = sym->rematiCode;
890 asmop *aop = newAsmop (AOP_IMMD);
897 val += (int) operandLitValue (IC_RIGHT (ic));
898 else if (ic->op == '-')
899 val -= (int) operandLitValue (IC_RIGHT (ic));
900 else if (IS_CAST_ICODE(ic)) {
901 sym_link *from_type = operandType(IC_RIGHT(ic));
902 aop->aopu.aop_immd.from_cast_remat = 1;
903 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
904 ptr_type = pointerTypeToGPByte (DCL_TYPE(from_type), NULL, NULL);
908 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
913 SNPRINTF (buffer, sizeof(buffer),
915 OP_SYMBOL (IC_LEFT (ic))->rname,
916 val >= 0 ? '+' : '-',
917 abs (val) & 0xffffff);
921 if (IS_ASSIGN_ICODE(ic) && isOperandLiteral(IC_RIGHT(ic)))
923 SNPRINTF(buffer, sizeof(buffer),
924 "0x%x",(int) operandLitValue (IC_RIGHT (ic)));
928 strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
932 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
933 /* set immd2 field if required */
934 if (aop->aopu.aop_immd.from_cast_remat)
936 tsprintf(buffer, sizeof(buffer), "#!constbyte",ptr_type);
937 aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
943 /*-----------------------------------------------------------------*/
944 /* aopHasRegs - returns true if aop has regs between from-to */
945 /*-----------------------------------------------------------------*/
946 static int aopHasRegs(asmop *aop, int from, int to)
950 if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
952 for (; size < aop->size ; size++) {
954 for (reg = from ; reg <= to ; reg++)
955 if (aop->aopu.aop_reg[size] == REG_WITH_INDEX(reg)) return 1;
960 /*-----------------------------------------------------------------*/
961 /* regsInCommon - two operands have some registers in common */
962 /*-----------------------------------------------------------------*/
964 regsInCommon (operand * op1, operand * op2)
969 /* if they have registers in common */
970 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
973 sym1 = OP_SYMBOL (op1);
974 sym2 = OP_SYMBOL (op2);
976 if (sym1->nRegs == 0 || sym2->nRegs == 0)
979 for (i = 0; i < sym1->nRegs; i++)
985 for (j = 0; j < sym2->nRegs; j++)
990 if (sym2->regs[j] == sym1->regs[i])
998 /*-----------------------------------------------------------------*/
999 /* operandsEqu - equivalent */
1000 /*-----------------------------------------------------------------*/
1002 operandsEqu (operand * op1, operand * op2)
1004 symbol *sym1, *sym2;
1006 /* if they're not symbols */
1007 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
1010 sym1 = OP_SYMBOL (op1);
1011 sym2 = OP_SYMBOL (op2);
1013 /* if both are itemps & one is spilt
1014 and the other is not then false */
1015 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
1016 sym1->isspilt != sym2->isspilt)
1019 /* if they are the same */
1023 /* if they have the same rname */
1024 if (sym1->rname[0] && sym2->rname[0] &&
1025 strcmp (sym1->rname, sym2->rname) == 0 &&
1026 !(IS_PARM (op2) && IS_ITEMP (op1)))
1029 /* if left is a tmp & right is not */
1030 if (IS_ITEMP (op1) &&
1033 (sym1->usl.spillLoc == sym2))
1036 if (IS_ITEMP (op2) &&
1040 (sym2->usl.spillLoc == sym1))
1043 /* are they spilt to the same location */
1044 if (IS_ITEMP (op2) &&
1048 (sym1->usl.spillLoc == sym2->usl.spillLoc))
1054 /*-----------------------------------------------------------------*/
1055 /* sameRegs - two asmops have the same registers */
1056 /*-----------------------------------------------------------------*/
1058 sameRegs (asmop * aop1, asmop * aop2)
1064 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
1071 if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
1074 if (aop1->type != aop2->type)
1077 if (aop1->size != aop2->size)
1080 for (i = 0; i < aop1->size; i++)
1081 if (aop1->aopu.aop_reg[i] != aop2->aopu.aop_reg[i])
1087 /*-----------------------------------------------------------------*/
1088 /* aopOp - allocates an asmop for an operand : */
1089 /*-----------------------------------------------------------------*/
1091 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
1100 /* if this a literal */
1101 if (IS_OP_LITERAL (op))
1103 op->aop = aop = newAsmop (AOP_LIT);
1104 aop->aopu.aop_lit = op->operand.valOperand;
1105 aop->size = getSize (operandType (op));
1109 /* if already has a asmop then continue */
1112 if ((op->aop->type == AOP_DPTR && useDP2)
1113 || (op->aop->type == AOP_DPTR2 && !useDP2))
1117 op->aop->allocated++;
1122 /* if the underlying symbol has a aop */
1123 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
1125 op->aop = OP_SYMBOL (op)->aop;
1126 if ((op->aop->type == AOP_DPTR && useDP2)
1127 || (op->aop->type == AOP_DPTR2 && !useDP2))
1131 op->aop->allocated++;
1136 /* if this is a true symbol */
1137 if (IS_TRUE_SYMOP (op))
1139 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
1143 /* this is a temporary : this has
1149 e) can be a return use only */
1151 sym = OP_SYMBOL (op);
1153 /* if the type is a conditional */
1154 if (sym->regType == REG_CND)
1156 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
1161 /* if it is spilt then two situations
1163 b) has a spill location */
1164 if (sym->isspilt || sym->nRegs == 0)
1167 /* rematerialize it NOW */
1170 sym->aop = op->aop = aop =
1172 aop->size = getSize (sym->type);
1179 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
1180 aop->size = getSize (sym->type);
1181 for (i = 0; i < 2; i++)
1182 aop->aopu.aop_str[i] = accUse[i];
1192 /* a AOP_STR uses DPTR, but DPTR is already in use;
1195 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
1198 aop = op->aop = sym->aop = newAsmop (AOP_STR);
1199 aop->size = getSize (sym->type);
1200 for (i = 0; i < fReturnSizeDS390; i++)
1201 aop->aopu.aop_str[i] = fReturn[i];
1205 if (sym->dptr) { /* has been allocated to a DPTRn */
1206 aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
1207 aop->size = getSize (sym->type);
1208 aop->aopu.dptr = sym->dptr;
1212 if (sym->usl.spillLoc)
1214 asmop *oldAsmOp = NULL;
1216 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1218 /* force a new aop if sizes differ */
1219 oldAsmOp = sym->usl.spillLoc->aop;
1220 sym->usl.spillLoc->aop = NULL;
1222 sym->aop = op->aop = aop =
1223 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
1224 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1226 /* Don't reuse the new aop, go with the last one */
1227 sym->usl.spillLoc->aop = oldAsmOp;
1229 aop->size = getSize (sym->type);
1233 /* else must be a dummy iTemp */
1234 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1235 aop->size = getSize (sym->type);
1239 /* if the type is a bit register */
1240 if (sym->regType == REG_BIT)
1242 sym->aop = op->aop = aop = newAsmop (AOP_CRY);
1243 aop->size = sym->nRegs;//1???
1244 aop->aopu.aop_reg[0] = sym->regs[0];
1245 aop->aopu.aop_dir = sym->regs[0]->name;
1249 /* must be in a register */
1250 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1251 aop->size = sym->nRegs;
1252 for (i = 0; i < sym->nRegs; i++)
1253 aop->aopu.aop_reg[i] = sym->regs[i];
1256 /*-----------------------------------------------------------------*/
1257 /* freeAsmop - free up the asmop given to an operand */
1258 /*----------------------------------------------------------------*/
1260 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1277 /* depending on the asmop type only three cases need work
1278 AOP_R0, AOP_R1 & AOP_STK */
1286 emitcode ("pop", "ar0");
1290 bitVectUnSetBit (ic->rUsed, R0_IDX);
1298 emitcode ("pop", "ar1");
1302 bitVectUnSetBit (ic->rUsed, R1_IDX);
1308 int stk = aop->aopu.aop_stk + aop->size;
1309 bitVectUnSetBit (ic->rUsed, R0_IDX);
1310 bitVectUnSetBit (ic->rUsed, R1_IDX);
1312 getFreePtr (ic, &aop, FALSE);
1314 if (options.stack10bit)
1316 /* I'm not sure what to do here yet... */
1319 "*** Warning: probably generating bad code for "
1320 "10 bit stack mode.\n");
1325 emitcode ("mov", "a,_bp");
1326 emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
1327 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1331 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1336 emitcode ("pop", "acc");
1337 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1340 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1343 freeAsmop (op, NULL, ic, TRUE);
1346 emitcode ("pop", "ar1");
1351 emitcode ("pop", "ar0");
1356 if (_G.dptr1InUse) {
1357 emitcode ("pop","dpx1");
1358 emitcode ("pop","dph1");
1359 emitcode ("pop","dpl1");
1364 emitcode ("pop","dpx");
1365 emitcode ("pop","dph");
1366 emitcode ("pop","dpl");
1372 /* all other cases just dealloc */
1378 OP_SYMBOL (op)->aop = NULL;
1379 /* if the symbol has a spill */
1381 SPIL_LOC (op)->aop = NULL;
1386 #define DEFAULT_ACC_WARNING 0
1387 static int saveAccWarn = DEFAULT_ACC_WARNING;
1390 /*-----------------------------------------------------------------*/
1391 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
1392 /* clobber the accumulator */
1393 /*-----------------------------------------------------------------*/
1395 aopGetUsesAcc (operand * oper, int offset)
1397 asmop * aop = AOP (oper);
1399 if (offset > (aop->size - 1))
1417 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1428 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1434 /* Error case --- will have been caught already */
1440 /*-------------------------------------------------------------------*/
1441 /* aopGet - for fetching value of the aop */
1443 /* Set saveAcc to NULL if you are sure it is OK to clobber the value */
1444 /* in the accumulator. Set it to the name of a free register */
1445 /* if acc must be preserved; the register will be used to preserve */
1446 /* acc temporarily and to return the result byte. */
1447 /*-------------------------------------------------------------------*/
1449 aopGet (operand * oper,
1455 asmop * aop = AOP (oper);
1457 /* offset is greater than
1459 if (offset > (aop->size - 1) &&
1460 aop->type != AOP_LIT)
1463 /* depending on type */
1471 /* if we need to increment it */
1472 while (offset > aop->coff)
1474 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1478 while (offset < aop->coff)
1480 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1487 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1488 return (dname ? "acc" : "a");
1490 SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1491 return Safe_strdup(buffer);
1494 assert(offset <= 3);
1495 return dptrn[aop->aopu.dptr][offset];
1500 if (aop->type == AOP_DPTR2)
1508 // if (aop->type != AOP_DPTR2)
1510 // if (saveAccWarn) { fprintf(stderr, "saveAcc for DPTR...\n"); }
1511 // emitcode(";", "spanky: saveAcc for DPTR");
1514 emitcode ("xch", "a, %s", saveAcc);
1519 while (offset > aop->coff)
1521 emitcode ("inc", "dptr");
1525 while (offset < aop->coff)
1527 emitcode ("lcall", "__decdptr");
1534 emitcode ("clr", "a");
1535 emitcode ("movc", "a,@a+dptr");
1539 emitcode ("movx", "a,@dptr");
1542 if (aop->type == AOP_DPTR2)
1550 emitcode ("xch", "a, %s", saveAcc);
1551 // if (strcmp(saveAcc, "_ap"))
1553 // emitcode(";", "spiffy: non _ap return from aopGet.");
1558 return (dname ? "acc" : "a");
1561 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1563 SNPRINTF(buffer, sizeof(buffer),
1564 "%s",aop->aopu.aop_immd.aop_immd2);
1568 SNPRINTF(buffer, sizeof(buffer),
1569 "#%s", aop->aopu.aop_immd.aop_immd1);
1575 tsprintf(buffer, sizeof(buffer),
1576 "#!his",aop->aopu.aop_immd.aop_immd1);
1579 tsprintf(buffer, sizeof(buffer),
1580 "#!hihis",aop->aopu.aop_immd.aop_immd1);
1583 tsprintf(buffer, sizeof(buffer),
1584 "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1586 default: /* should not need this (just in case) */
1587 SNPRINTF (buffer, sizeof(buffer),
1589 aop->aopu.aop_immd.aop_immd1,
1595 SNPRINTF (buffer, sizeof(buffer),
1597 aop->aopu.aop_immd.aop_immd1);
1599 return Safe_strdup(buffer);
1602 if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
1604 SNPRINTF (buffer, sizeof(buffer),
1606 aop->aopu.aop_dir, offset * 8);
1610 SNPRINTF (buffer, sizeof(buffer),
1617 SNPRINTF (buffer, sizeof(buffer),
1622 return Safe_strdup(buffer);
1626 return aop->aopu.aop_reg[offset]->dname;
1628 return aop->aopu.aop_reg[offset]->name;
1631 emitcode ("clr", "a");
1632 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1633 emitcode ("rlc", "a");
1634 return (dname ? "acc" : "a");
1637 if (!offset && dname)
1639 return aop->aopu.aop_str[offset];
1642 return aopLiteral (aop->aopu.aop_lit, offset);
1646 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1650 return aop->aopu.aop_str[offset];
1654 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1655 "aopget got unsupported aop->type");
1658 return NULL; // not reached, but makes compiler happy.
1661 /*-----------------------------------------------------------------*/
1662 /* aopPut - puts a string for a aop and indicates if acc is in use */
1663 /*-----------------------------------------------------------------*/
1665 aopPut (operand * result, const char *s, int offset)
1667 bool bvolatile = isOperandVolatile (result, FALSE);
1668 bool accuse = FALSE;
1669 asmop * aop = AOP (result);
1671 if (aop->size && offset > (aop->size - 1))
1673 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1674 "aopPut got offset > aop->size");
1678 /* will assign value to value */
1679 /* depending on where it is ofcourse */
1683 MOVA (s); /* read s in case it was volatile */
1688 if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1690 SNPRINTF (buffer, sizeof(buffer),
1692 aop->aopu.aop_dir, offset * 8);
1696 SNPRINTF (buffer, sizeof(buffer),
1698 aop->aopu.aop_dir, offset);
1702 SNPRINTF (buffer, sizeof(buffer),
1707 if (strcmp (buffer, s) || bvolatile)
1709 emitcode ("mov", "%s,%s", buffer, s);
1711 if (!strcmp (buffer, "acc"))
1718 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1719 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1722 strcmp (s, "r0") == 0 ||
1723 strcmp (s, "r1") == 0 ||
1724 strcmp (s, "r2") == 0 ||
1725 strcmp (s, "r3") == 0 ||
1726 strcmp (s, "r4") == 0 ||
1727 strcmp (s, "r5") == 0 ||
1728 strcmp (s, "r6") == 0 ||
1729 strcmp (s, "r7") == 0)
1731 emitcode ("mov", "%s,%s",
1732 aop->aopu.aop_reg[offset]->dname, s);
1736 emitcode ("mov", "%s,%s",
1737 aop->aopu.aop_reg[offset]->name, s);
1743 emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1749 if (aop->type == AOP_DPTR2)
1757 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1758 "aopPut writing to code space");
1762 while (offset > aop->coff)
1765 emitcode ("inc", "dptr");
1768 while (offset < aop->coff)
1771 emitcode ("lcall", "__decdptr");
1776 /* if not in accumulator */
1779 emitcode ("movx", "@dptr,a");
1781 if (aop->type == AOP_DPTR2)
1789 while (offset > aop->coff)
1792 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1794 while (offset < aop->coff)
1797 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1804 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1809 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1811 else if (strcmp (s, "r0") == 0 ||
1812 strcmp (s, "r1") == 0 ||
1813 strcmp (s, "r2") == 0 ||
1814 strcmp (s, "r3") == 0 ||
1815 strcmp (s, "r4") == 0 ||
1816 strcmp (s, "r5") == 0 ||
1817 strcmp (s, "r6") == 0 ||
1818 strcmp (s, "r7") == 0)
1821 SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1822 emitcode ("mov", "@%s,%s",
1823 aop->aopu.aop_ptr->name, buffer);
1827 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1832 if (strcmp (s, "a") == 0)
1833 emitcode ("push", "acc");
1837 emitcode ("push", "acc");
1839 emitcode ("push", s);
1845 /* if not bit variable */
1846 if (!aop->aopu.aop_dir)
1848 /* inefficient: move carry into A and use jz/jnz */
1849 emitcode ("clr", "a");
1850 emitcode ("rlc", "a");
1856 emitcode ("clr", "%s", aop->aopu.aop_dir);
1858 emitcode ("setb", "%s", aop->aopu.aop_dir);
1859 else if (!strcmp (s, "c"))
1860 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1861 else if (strcmp (s, aop->aopu.aop_dir))
1864 /* set C, if a >= 1 */
1865 emitcode ("add", "a,#!constbyte",0xff);
1866 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1873 if (strcmp (aop->aopu.aop_str[offset], s) || bvolatile)
1874 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1880 if (!offset && (strcmp (s, "acc") == 0) && !bvolatile)
1883 if (strcmp (aop->aopu.aop_str[offset], s) && !bvolatile)
1884 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1888 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1889 "aopPut got unsupported aop->type");
1897 /*--------------------------------------------------------------------*/
1898 /* reAdjustPreg - points a register back to where it should (coff==0) */
1899 /*--------------------------------------------------------------------*/
1901 reAdjustPreg (asmop * aop)
1903 if ((aop->coff==0) || (aop->size <= 1))
1911 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1915 if (aop->type == AOP_DPTR2)
1922 emitcode ("lcall", "__decdptr");
1925 if (aop->type == AOP_DPTR2)
1934 /*-----------------------------------------------------------------*/
1935 /* opIsGptr: returns non-zero if the passed operand is */
1936 /* a generic pointer type. */
1937 /*-----------------------------------------------------------------*/
1939 opIsGptr (operand * op)
1941 sym_link *type = operandType (op);
1943 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1950 /*-----------------------------------------------------------------*/
1951 /* getDataSize - get the operand data size */
1952 /*-----------------------------------------------------------------*/
1954 getDataSize (operand * op)
1957 size = AOP_SIZE (op);
1958 if (size == GPTRSIZE)
1960 sym_link *type = operandType (op);
1961 if (IS_GENPTR (type))
1963 /* generic pointer; arithmetic operations
1964 * should ignore the high byte (pointer type).
1972 /*-----------------------------------------------------------------*/
1973 /* outAcc - output Acc */
1974 /*-----------------------------------------------------------------*/
1976 outAcc (operand * result)
1979 size = getDataSize (result);
1982 aopPut (result, "a", 0);
1985 /* unsigned or positive */
1988 aopPut (result, zero, offset++);
1993 /*-----------------------------------------------------------------*/
1994 /* outBitC - output a bit C */
1995 /*-----------------------------------------------------------------*/
1997 outBitC (operand * result)
1999 /* if the result is bit */
2000 if (AOP_TYPE (result) == AOP_CRY)
2002 aopPut (result, "c", 0);
2006 emitcode ("clr", "a");
2007 emitcode ("rlc", "a");
2012 /*-----------------------------------------------------------------*/
2013 /* toBoolean - emit code for orl a,operator(sizeop) */
2014 /*-----------------------------------------------------------------*/
2016 toBoolean (operand * oper)
2018 int size = AOP_SIZE (oper) - 1;
2022 /* The generic part of a generic pointer should
2023 * not participate in it's truth value.
2025 * i.e. 0x10000000 is zero.
2027 if (opIsGptr (oper))
2029 D (emitcode (";", "toBoolean: generic ptr special case."));
2033 _startLazyDPSEvaluation ();
2034 MOVA (aopGet (oper, 0, FALSE, FALSE, NULL));
2035 if (AOP_NEEDSACC (oper) && size && (AOP (oper)->type != AOP_ACC))
2038 emitcode("mov", "b,a");
2041 MOVA (aopGet (oper, offset++, FALSE, FALSE, NULL));
2042 emitcode ("orl", "b,a");
2044 MOVA (aopGet (oper, offset++, FALSE, FALSE, NULL));
2045 emitcode ("orl", "a,b");
2052 emitcode ("orl", "a,%s",
2053 aopGet (oper, offset++, FALSE, FALSE, NULL));
2056 _endLazyDPSEvaluation ();
2060 /*-----------------------------------------------------------------*/
2061 /* genNot - generate code for ! operation */
2062 /*-----------------------------------------------------------------*/
2068 D (emitcode (";", "genNot"));
2070 /* assign asmOps to operand & result */
2071 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2072 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
2074 /* if in bit space then a special case */
2075 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2077 /* if left==result then cpl bit */
2078 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2080 emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2084 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2085 emitcode ("cpl", "c");
2086 outBitC (IC_RESULT (ic));
2091 toBoolean (IC_LEFT (ic));
2093 /* set C, if a == 0 */
2094 tlbl = newiTempLabel (NULL);
2095 emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
2097 outBitC (IC_RESULT (ic));
2100 /* release the aops */
2101 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2102 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2106 /*-----------------------------------------------------------------*/
2107 /* genCpl - generate code for complement */
2108 /*-----------------------------------------------------------------*/
2115 sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
2117 D(emitcode (";", "genCpl"));
2119 /* assign asmOps to operand & result */
2120 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2121 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
2123 /* special case if in bit space */
2124 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2128 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
2129 (SPEC_USIGN (letype) && IS_CHAR (letype)))
2131 /* promotion rules are responsible for this strange result:
2132 bit -> int -> ~int -> bit
2133 uchar -> int -> ~int -> bit
2135 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
2139 tlbl=newiTempLabel(NULL);
2140 l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE, NULL);
2141 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
2142 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
2143 IS_AOP_PREG (IC_LEFT (ic)))
2145 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
2150 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
2153 outBitC (IC_RESULT(ic));
2157 size = AOP_SIZE (IC_RESULT (ic));
2158 _startLazyDPSEvaluation ();
2161 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL);
2163 emitcode ("cpl", "a");
2164 aopPut (IC_RESULT (ic), "a", offset++);
2166 _endLazyDPSEvaluation ();
2170 /* release the aops */
2171 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2172 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2175 /*-----------------------------------------------------------------*/
2176 /* genUminusFloat - unary minus for floating points */
2177 /*-----------------------------------------------------------------*/
2179 genUminusFloat (operand * op, operand * result)
2181 int size, offset = 0;
2184 D (emitcode (";", "genUminusFloat"));
2186 /* for this we just copy and then flip the bit */
2188 _startLazyDPSEvaluation ();
2189 size = AOP_SIZE (op) - 1;
2194 aopGet (op, offset, FALSE, FALSE, NULL),
2199 l = aopGet (op, offset, FALSE, FALSE, NULL);
2202 emitcode ("cpl", "acc.7");
2203 aopPut (result, "a", offset);
2204 _endLazyDPSEvaluation ();
2207 /*-----------------------------------------------------------------*/
2208 /* genUminus - unary minus code generation */
2209 /*-----------------------------------------------------------------*/
2211 genUminus (iCode * ic)
2216 D (emitcode (";", "genUminus"));
2219 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2220 aopOp (IC_RESULT (ic), ic, TRUE, (AOP_TYPE(IC_LEFT (ic)) == AOP_DPTR));
2222 /* if both in bit space then special
2224 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2225 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2228 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2229 emitcode ("cpl", "c");
2230 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2234 optype = operandType (IC_LEFT (ic));
2236 /* if float then do float stuff */
2237 if (IS_FLOAT (optype))
2239 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2243 /* otherwise subtract from zero */
2244 size = AOP_SIZE (IC_LEFT (ic));
2246 _startLazyDPSEvaluation ();
2249 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL);
2250 if (!strcmp (l, "a"))
2254 emitcode ("cpl", "a");
2255 emitcode ("addc", "a,#0");
2261 emitcode ("clr", "a");
2262 emitcode ("subb", "a,%s", l);
2264 aopPut (IC_RESULT (ic), "a", offset++);
2266 _endLazyDPSEvaluation ();
2268 /* if any remaining bytes in the result */
2269 /* we just need to propagate the sign */
2270 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2272 emitcode ("rlc", "a");
2273 emitcode ("subb", "a,acc");
2275 aopPut (IC_RESULT (ic), "a", offset++);
2279 /* release the aops */
2280 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2281 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2284 /*-----------------------------------------------------------------*/
2285 /* savermask - saves registers in the mask */
2286 /*-----------------------------------------------------------------*/
2287 static void savermask(bitVect *rs_mask)
2291 if (options.useXstack)
2293 if (bitVectBitValue (rs_mask, R0_IDX))
2294 emitcode ("mov", "b,r0");
2295 emitcode ("mov", "r0,%s", spname);
2296 for (i = 0; i < ds390_nRegs; i++)
2298 if (bitVectBitValue (rs_mask, i))
2301 emitcode ("mov", "a,b");
2303 emitcode ("mov", "a,%s", REG_WITH_INDEX (i)->name);
2304 emitcode ("movx", "@r0,a");
2305 emitcode ("inc", "r0");
2308 emitcode ("mov", "%s,r0", spname);
2309 if (bitVectBitValue (rs_mask, R0_IDX))
2310 emitcode ("mov", "r0,b");
2314 bool bits_pushed = FALSE;
2315 for (i = 0; i < ds390_nRegs; i++)
2317 if (bitVectBitValue (rs_mask, i))
2319 bits_pushed = pushReg (i, bits_pushed);
2325 /*-----------------------------------------------------------------*/
2326 /* saveRegisters - will look for a call and save the registers */
2327 /*-----------------------------------------------------------------*/
2329 saveRegisters (iCode * lic)
2335 for (ic = lic; ic; ic = ic->next)
2336 if (ic->op == CALL || ic->op == PCALL)
2341 fprintf (stderr, "found parameter push with no function call\n");
2345 /* if the registers have been saved already or don't need to be then
2348 || (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))) && !TARGET_IS_DS400) )
2351 /* special case if DPTR alive across a function call then must save it
2352 even though callee saves */
2353 if (IS_SYMOP(IC_LEFT(ic)) &&
2354 IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type))
2357 rsave = newBitVect(ic->rMask->size);
2358 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2359 if (bitVectBitValue(ic->rMask,i))
2360 rsave = bitVectSetBit(rsave,i);
2362 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2366 /* save the registers in use at this time but skip the
2367 ones for the result */
2368 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2369 ds390_rUmaskForOp (IC_RESULT(ic)));
2375 /*-----------------------------------------------------------------*/
2376 /* usavermask - restore registers with mask */
2377 /*-----------------------------------------------------------------*/
2378 static void unsavermask(bitVect *rs_mask)
2382 if (options.useXstack)
2384 emitcode ("mov", "r0,%s", spname);
2385 for (i = ds390_nRegs; i >= 0; i--)
2387 if (bitVectBitValue (rs_mask, i))
2389 regs * reg = REG_WITH_INDEX (i);
2390 emitcode ("dec", "r0");
2391 emitcode ("movx", "a,@r0");
2394 emitcode ("push", "acc");
2398 emitcode ("mov", "%s,a", reg->name);
2402 emitcode ("mov", "%s,r0", spname);
2403 if (bitVectBitValue (rs_mask, R0_IDX))
2405 emitcode ("pop", "ar0");
2410 bool bits_popped = FALSE;
2411 for (i = ds390_nRegs; i >= 0; i--)
2413 if (bitVectBitValue (rs_mask, i))
2415 bits_popped = popReg (i, bits_popped);
2421 /*-----------------------------------------------------------------*/
2422 /* unsaveRegisters - pop the pushed registers */
2423 /*-----------------------------------------------------------------*/
2425 unsaveRegisters (iCode * ic)
2429 if (IS_SYMOP(IC_LEFT (ic)) &&
2430 IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2432 rsave = newBitVect(ic->rMask->size);
2433 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2434 if (bitVectBitValue(ic->rMask,i))
2435 rsave = bitVectSetBit(rsave,i);
2437 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2439 /* restore the registers in use at this time but skip the
2440 ones for the result */
2441 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2442 ds390_rUmaskForOp (IC_RESULT(ic)));
2448 /*-----------------------------------------------------------------*/
2450 /*-----------------------------------------------------------------*/
2452 pushSide (operand * oper, int size)
2455 _startLazyDPSEvaluation ();
2458 char *l = aopGet (oper, offset++, FALSE, TRUE, NULL);
2459 if (AOP_TYPE (oper) != AOP_REG &&
2460 AOP_TYPE (oper) != AOP_DIR &&
2464 emitcode ("push", "acc");
2468 emitcode ("push", "%s", l);
2471 _endLazyDPSEvaluation ();
2474 /*-----------------------------------------------------------------*/
2475 /* assignResultValue - also indicates if acc is in use afterwards */
2476 /*-----------------------------------------------------------------*/
2478 assignResultValue (operand * oper, operand * func)
2481 unsigned size = AOP_SIZE (oper);
2482 bool accuse = FALSE;
2483 bool pushedA = FALSE;
2485 if (func && IS_BIT (OP_SYM_ETYPE (func)))
2491 if (size == fReturnSizeDS390)
2493 /* I don't think this case can ever happen... */
2494 /* ACC is the last part of this. If writing the result
2495 * uses ACC, we must preserve it.
2497 if (AOP_NEEDSACC(oper))
2499 emitcode(";", "assignResultValue special case for ACC.");
2500 emitcode("push", "acc");
2506 _startLazyDPSEvaluation ();
2509 accuse |= aopPut (oper, fReturn[offset], offset);
2512 _endLazyDPSEvaluation ();
2516 emitcode ("pop", "acc");
2517 accuse |= aopPut (oper, "a", offset);
2523 /*-----------------------------------------------------------------*/
2524 /* genXpush - pushes onto the external stack */
2525 /*-----------------------------------------------------------------*/
2527 genXpush (iCode * ic)
2529 asmop *aop = newAsmop (0);
2531 int size, offset = 0;
2533 D (emitcode (";", "genXpush"));
2535 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2536 r = getFreePtr (ic, &aop, FALSE);
2538 size = AOP_SIZE (IC_LEFT (ic));
2542 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
2543 emitcode ("mov", "%s,_spx", r->name);
2544 emitcode ("inc", "_spx"); // allocate space first
2545 emitcode ("movx", "@%s,a", r->name);
2549 // allocate space first
2550 emitcode ("mov", "%s,_spx", r->name);
2552 emitcode ("add", "a,#%d", size);
2553 emitcode ("mov", "_spx,a");
2555 _startLazyDPSEvaluation ();
2558 MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE, NULL));
2559 emitcode ("movx", "@%s,a", r->name);
2560 emitcode ("inc", "%s", r->name);
2562 _endLazyDPSEvaluation ();
2565 freeAsmop (NULL, aop, ic, TRUE);
2566 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2569 /*-----------------------------------------------------------------*/
2570 /* genIpush - generate code for pushing this gets a little complex */
2571 /*-----------------------------------------------------------------*/
2573 genIpush (iCode * ic)
2575 int size, offset = 0;
2579 D (emitcode (";", "genIpush"));
2581 /* if this is not a parm push : ie. it is spill push
2582 and spill push is always done on the local stack */
2586 /* and the item is spilt then do nothing */
2587 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2590 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2591 size = AOP_SIZE (IC_LEFT (ic));
2592 /* push it on the stack */
2593 _startLazyDPSEvaluation ();
2596 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE, NULL);
2602 emitcode ("push", "%s", l);
2604 _endLazyDPSEvaluation ();
2608 /* this is a parameter push: in this case we call
2609 the routine to find the call and save those
2610 registers that need to be saved */
2613 /* if use external stack then call the external
2614 stack pushing routine */
2615 if (options.useXstack)
2621 /* then do the push */
2622 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2624 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2625 size = AOP_SIZE (IC_LEFT (ic));
2627 _startLazyDPSEvaluation ();
2630 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE, NULL);
2631 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2632 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2635 if (strcmp (l, prev) || *l == '@')
2637 emitcode ("push", "acc");
2641 emitcode ("push", "%s", l);
2645 _endLazyDPSEvaluation ();
2647 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2650 /*-----------------------------------------------------------------*/
2651 /* genIpop - recover the registers: can happen only for spilling */
2652 /*-----------------------------------------------------------------*/
2654 genIpop (iCode * ic)
2658 D (emitcode (";", "genIpop"));
2660 /* if the temp was not pushed then */
2661 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2664 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2665 size = AOP_SIZE (IC_LEFT (ic));
2666 offset = (size - 1);
2667 _startLazyDPSEvaluation ();
2670 emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2671 FALSE, TRUE, NULL));
2673 _endLazyDPSEvaluation ();
2675 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2678 /*-----------------------------------------------------------------*/
2679 /* saveRBank - saves an entire register bank on the stack */
2680 /*-----------------------------------------------------------------*/
2682 saveRBank (int bank, iCode * ic, bool pushPsw)
2685 int count = 8 + (ds390_nBitRegs/8) + (pushPsw ? 1 : 0);
2689 if (options.useXstack)
2693 /* Assume r0 is available for use. */
2694 r = REG_WITH_INDEX (R0_IDX);;
2699 r = getFreePtr (ic, &aop, FALSE);
2701 // allocate space first
2702 emitcode ("mov", "%s,_spx", r->name);
2704 emitcode ("add", "a,#%d", count);
2705 emitcode ("mov", "_spx,a");
2708 for (i = 0; i < 8; i++) /* only R0-R7 needs saving */
2710 if (options.useXstack)
2712 emitcode ("mov", "a,(%s+%d)",
2713 regs390[i].base, 8 * bank + regs390[i].offset);
2714 emitcode ("movx", "@%s,a", r->name);
2716 emitcode ("inc", "%s", r->name);
2719 emitcode ("push", "(%s+%d)",
2720 regs390[i].base, 8 * bank + regs390[i].offset);
2723 if (ds390_nBitRegs > 0)
2725 if (options.useXstack)
2727 emitcode ("mov", "a,bits");
2728 emitcode ("movx", "@%s,a", r->name);
2730 emitcode ("inc", "%s", r->name);
2734 emitcode ("push", "bits");
2741 if (options.useXstack)
2743 emitcode ("mov", "a,psw");
2744 emitcode ("movx", "@%s,a", r->name);
2748 emitcode ("push", "psw");
2751 emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2756 freeAsmop (NULL, aop, ic, TRUE);
2765 /*-----------------------------------------------------------------*/
2766 /* unsaveRBank - restores the register bank from stack */
2767 /*-----------------------------------------------------------------*/
2769 unsaveRBank (int bank, iCode * ic, bool popPsw)
2775 if (options.useXstack)
2779 /* Assume r0 is available for use. */
2780 r = REG_WITH_INDEX (R0_IDX);;
2785 r = getFreePtr (ic, &aop, FALSE);
2787 emitcode ("mov", "%s,_spx", r->name);
2792 if (options.useXstack)
2794 emitcode ("dec", "%s", r->name);
2795 emitcode ("movx", "a,@%s", r->name);
2796 emitcode ("mov", "psw,a");
2800 emitcode ("pop", "psw");
2804 if (ds390_nBitRegs > 0)
2806 if (options.useXstack)
2808 emitcode ("dec", "%s", r->name);
2809 emitcode ("movx", "a,@%s", r->name);
2810 emitcode ("mov", "bits,a");
2814 emitcode ("pop", "bits");
2818 for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2820 if (options.useXstack)
2822 emitcode ("dec", "%s", r->name);
2823 emitcode ("movx", "a,@%s", r->name);
2824 emitcode ("mov", "(%s+%d),a",
2825 regs390[i].base, 8 * bank + regs390[i].offset);
2829 emitcode ("pop", "(%s+%d)",
2830 regs390[i].base, 8 * bank + regs390[i].offset);
2834 if (options.useXstack)
2836 emitcode ("mov", "_spx,%s", r->name);
2841 freeAsmop (NULL, aop, ic, TRUE);
2845 /*-----------------------------------------------------------------*/
2846 /* genSend - gen code for SEND */
2847 /*-----------------------------------------------------------------*/
2848 static void genSend(set *sendSet)
2853 static int rb1_count = 0;
2855 /* first we do all bit parameters */
2856 for (sic = setFirstItem (sendSet); sic;
2857 sic = setNextItem (sendSet))
2859 if (sic->argreg > 12)
2861 int bit = sic->argreg-13;
2863 aopOp (IC_LEFT (sic), sic, FALSE,
2864 (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2866 /* if left is a literal then
2867 we know what the value is */
2868 if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2870 if (((int) operandLitValue (IC_LEFT (sic))))
2871 emitcode ("setb", "b[%d]", bit);
2873 emitcode ("clr", "b[%d]", bit);
2875 else if (AOP_TYPE (IC_LEFT (sic)) == AOP_CRY)
2877 char *l = AOP (IC_LEFT (sic))->aopu.aop_dir;
2878 if (strcmp (l, "c"))
2879 emitcode ("mov", "c,%s", l);
2880 emitcode ("mov", "b[%d],c", bit);
2885 toBoolean (IC_LEFT (sic));
2886 /* set C, if a >= 1 */
2887 emitcode ("add", "a,#0xff");
2888 emitcode ("mov", "b[%d],c", bit);
2893 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2899 saveRegisters (setFirstItem (sendSet));
2900 emitcode ("mov", "bits,b");
2903 /* then we do all other parameters */
2904 for (sic = setFirstItem (sendSet); sic;
2905 sic = setNextItem (sendSet))
2907 if (sic->argreg <= 12)
2909 int size, offset = 0;
2911 size = getSize (operandType (IC_LEFT (sic)));
2912 D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2913 if (sendCount == 0) { /* first parameter */
2914 // we know that dpl(hxb) is the result, so
2916 _startLazyDPSEvaluation ();
2918 aopOp (IC_LEFT (sic), sic, FALSE,
2919 (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2921 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2925 char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE, NULL);
2926 if (strcmp (l, fReturn[offset]))
2928 emitcode ("mov", "%s,%s", fReturn[offset], l);
2932 _endLazyDPSEvaluation ();
2933 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2935 } else { /* if more parameter in registers */
2936 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2938 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (IC_LEFT (sic), offset++,
2939 FALSE, FALSE, NULL));
2941 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2949 adjustEsp(const char *reg)
2951 emitcode ("anl","%s,#3", reg);
2952 if (TARGET_IS_DS400)
2954 emitcode ("orl","%s,#!constbyte",
2956 (options.stack_loc >> 8) & 0xff);
2960 /*-----------------------------------------------------------------*/
2961 /* selectRegBank - emit code to select the register bank */
2962 /*-----------------------------------------------------------------*/
2964 selectRegBank (short bank, bool keepFlags)
2966 /* if f.e. result is in carry */
2969 emitcode ("anl", "psw,#0xE7");
2971 emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2975 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2979 /*-----------------------------------------------------------------*/
2980 /* genCall - generates a call statement */
2981 /*-----------------------------------------------------------------*/
2983 genCall (iCode * ic)
2987 bool restoreBank = FALSE;
2988 bool swapBanks = FALSE;
2989 bool accuse = FALSE;
2990 bool accPushed = FALSE;
2991 bool resultInF0 = FALSE;
2992 bool assignResultGenerated = FALSE;
2994 D (emitcode (";", "genCall"));
2996 /* if we are calling a not _naked function that is not using
2997 the same register bank then we need to save the
2998 destination registers on the stack */
2999 dtype = operandType (IC_LEFT (ic));
3000 etype = getSpec(dtype);
3001 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
3002 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
3003 IFFUNC_ISISR (currFunc->type))
3007 /* This is unexpected; the bank should have been saved in
3010 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
3016 /* if caller saves & we have not saved then */
3020 /* if send set is not empty then assign */
3021 /* We've saved all the registers we care about;
3022 * therefore, we may clobber any register not used
3023 * in the calling convention (i.e. anything not in
3028 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
3029 genSend(reverseSet(_G.sendSet));
3031 genSend(_G.sendSet);
3038 emitcode ("mov", "psw,#!constbyte",
3039 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3043 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
3044 OP_SYMBOL (IC_LEFT (ic))->rname :
3045 OP_SYMBOL (IC_LEFT (ic))->name));
3049 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
3052 /* if we need assign a result value */
3053 if ((IS_ITEMP (IC_RESULT (ic)) &&
3054 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3055 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3056 OP_SYMBOL (IC_RESULT (ic))->accuse ||
3057 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3058 IS_TRUE_SYMOP (IC_RESULT (ic)))
3060 if (isOperandInFarSpace (IC_RESULT (ic))
3061 && getSize (operandType (IC_RESULT (ic))) <= 2)
3063 int size = getSize (operandType (IC_RESULT (ic)));
3064 bool pushedB = FALSE;
3066 /* Special case for 1 or 2 byte return in far space. */
3071 emitcode ("mov", "b,%s", fReturn[1]);
3075 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
3080 aopPut (IC_RESULT (ic), "a", 0);
3084 aopPut (IC_RESULT (ic), "b", 1);
3086 assignResultGenerated = TRUE;
3087 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3091 bool pushedB = pushB ();
3092 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
3095 accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3096 assignResultGenerated = TRUE;
3097 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3101 /* adjust the stack for parameters if required */
3105 if (options.stack10bit) {
3106 if (ic->parmBytes <= 10) {
3107 emitcode(";","stack adjustment for parms");
3108 for (i=0; i < ic->parmBytes ; i++) {
3109 emitcode("pop","acc");
3113 emitcode ("clr","c");
3114 emitcode ("mov","a,sp");
3115 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
3116 emitcode ("mov","sp,a");
3117 emitcode ("mov","a,esp");
3119 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
3120 emitcode ("mov","esp,a");
3124 if (ic->parmBytes > 3)
3128 emitcode ("push", "acc");
3131 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3132 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3133 !assignResultGenerated)
3135 emitcode ("mov", "F0,c");
3139 emitcode ("mov", "a,%s", spname);
3140 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
3141 emitcode ("mov", "%s,a", spname);
3143 /* unsaveRegisters from xstack needs acc, but */
3144 /* unsaveRegisters from stack needs this popped */
3145 if (accPushed && !options.useXstack)
3147 emitcode ("pop", "acc");
3152 for (i = 0; i < ic->parmBytes; i++)
3153 emitcode ("dec", "%s", spname);
3157 /* if we had saved some registers then unsave them */
3158 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3160 if (accuse && !accPushed && options.useXstack)
3162 /* xstack needs acc, but doesn't touch normal stack */
3163 emitcode ("push", "acc");
3166 unsaveRegisters (ic);
3169 /* if register bank was saved then pop them */
3171 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
3173 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
3176 emitcode ("mov", "c,F0");
3178 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
3179 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3180 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3184 emitcode ("pop", "acc");
3187 /*-----------------------------------------------------------------*/
3188 /* genPcall - generates a call by pointer statement */
3189 /*-----------------------------------------------------------------*/
3191 genPcall (iCode * ic)
3195 symbol *rlbl = newiTempLabel (NULL);
3196 bool restoreBank=FALSE;
3197 bool resultInF0 = FALSE;
3199 D (emitcode (";", "genPcall"));
3201 dtype = operandType (IC_LEFT (ic))->next;
3202 etype = getSpec(dtype);
3203 /* if caller saves & we have not saved then */
3207 /* if we are calling a not _naked function that is not using
3208 the same register bank then we need to save the
3209 destination registers on the stack */
3210 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
3211 IFFUNC_ISISR (currFunc->type) &&
3212 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
3213 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3217 /* push the return address on to the stack */
3218 emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
3219 emitcode ("push", "acc");
3220 emitcode ("mov", "a,#!hil", (rlbl->key + 100));
3221 emitcode ("push", "acc");
3223 if (options.model == MODEL_FLAT24)
3225 emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
3226 emitcode ("push", "acc");
3229 /* now push the calling address */
3230 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3232 pushSide (IC_LEFT (ic), FPTRSIZE);
3234 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3236 /* if send set is not empty the assign */
3239 genSend(reverseSet(_G.sendSet));
3244 emitcode ("ret", "");
3248 /* if we need assign a result value */
3249 if ((IS_ITEMP (IC_RESULT (ic)) &&
3250 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3251 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3252 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3253 IS_TRUE_SYMOP (IC_RESULT (ic)))
3257 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
3260 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3262 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3265 /* adjust the stack for parameters if required */
3269 if (options.stack10bit) {
3270 if (ic->parmBytes <= 10) {
3271 emitcode(";","stack adjustment for parms");
3272 for (i=0; i < ic->parmBytes ; i++) {
3273 emitcode("pop","acc");
3276 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3277 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3279 emitcode ("mov", "F0,c");
3284 emitcode ("clr","c");
3285 emitcode ("mov","a,sp");
3286 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
3287 emitcode ("mov","sp,a");
3288 emitcode ("mov","a,esp");
3290 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
3291 emitcode ("mov","esp,a");
3295 if (ic->parmBytes > 3) {
3296 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3297 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3299 emitcode ("mov", "F0,c");
3303 emitcode ("mov", "a,%s", spname);
3304 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
3305 emitcode ("mov", "%s,a", spname);
3308 for (i = 0; i < ic->parmBytes; i++)
3309 emitcode ("dec", "%s", spname);
3312 /* if register bank was saved then unsave them */
3314 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3316 /* if we had saved some registers then unsave them */
3318 unsaveRegisters (ic);
3320 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3323 emitcode ("mov", "c,F0");
3325 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
3326 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3327 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3331 /*-----------------------------------------------------------------*/
3332 /* resultRemat - result is rematerializable */
3333 /*-----------------------------------------------------------------*/
3335 resultRemat (iCode * ic)
3337 if (SKIP_IC (ic) || ic->op == IFX)
3340 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3342 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3343 if (sym->remat && !POINTER_SET (ic))
3350 #if defined(__BORLANDC__) || defined(_MSC_VER)
3351 #define STRCASECMP stricmp
3353 #define STRCASECMP strcasecmp
3356 /*-----------------------------------------------------------------*/
3357 /* inExcludeList - return 1 if the string is in exclude Reg list */
3358 /*-----------------------------------------------------------------*/
3360 regsCmp(void *p1, void *p2)
3362 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3366 inExcludeList (char *s)
3368 const char *p = setFirstItem(options.excludeRegsSet);
3370 if (p == NULL || STRCASECMP(p, "none") == 0)
3374 return isinSetWith(options.excludeRegsSet, s, regsCmp);
3377 /*-----------------------------------------------------------------*/
3378 /* genFunction - generated code for function entry */
3379 /*-----------------------------------------------------------------*/
3381 genFunction (iCode * ic)
3383 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3385 bool switchedPSW = FALSE;
3386 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3388 D (emitcode (";", "genFunction"));
3391 /* create the function header */
3392 emitcode (";", "-----------------------------------------");
3393 emitcode (";", " function %s", sym->name);
3394 emitcode (";", "-----------------------------------------");
3396 emitcode ("", "%s:", sym->rname);
3397 ftype = operandType (IC_LEFT (ic));
3398 _G.currentFunc = sym;
3400 if (IFFUNC_ISNAKED(ftype))
3402 emitcode(";", "naked function: no prologue.");
3406 if (options.stack_probe)
3407 emitcode ("lcall","__stack_probe");
3409 /* here we need to generate the equates for the
3410 register bank if required */
3411 if (FUNC_REGBANK (ftype) != rbank)
3415 rbank = FUNC_REGBANK (ftype);
3416 for (i = 0; i < ds390_nRegs; i++)
3418 if (regs390[i].print) {
3419 if (strcmp (regs390[i].base, "0") == 0)
3420 emitcode ("", "%s !equ !constbyte",
3422 8 * rbank + regs390[i].offset);
3424 emitcode ("", "%s !equ %s + !constbyte",
3427 8 * rbank + regs390[i].offset);
3432 /* if this is an interrupt service routine then
3433 save acc, b, dpl, dph */
3434 if (IFFUNC_ISISR (sym->type))
3436 if (!inExcludeList ("acc"))
3437 emitcode ("push", "acc");
3438 if (!inExcludeList ("b"))
3439 emitcode ("push", "b");
3440 if (!inExcludeList ("dpl"))
3441 emitcode ("push", "dpl");
3442 if (!inExcludeList ("dph"))
3443 emitcode ("push", "dph");
3444 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3446 emitcode ("push", "dpx");
3447 /* Make sure we're using standard DPTR */
3448 emitcode ("push", "dps");
3449 emitcode ("mov", "dps,#0");
3450 if (options.stack10bit)
3452 /* This ISR could conceivably use DPTR2. Better save it. */
3453 emitcode ("push", "dpl1");
3454 emitcode ("push", "dph1");
3455 emitcode ("push", "dpx1");
3456 emitcode ("push", DP2_RESULT_REG);
3459 /* if this isr has no bank i.e. is going to
3460 run with bank 0 , then we need to save more
3462 if (!FUNC_REGBANK (sym->type))
3466 /* if this function does not call any other
3467 function then we can be economical and
3468 save only those registers that are used */
3469 if (!IFFUNC_HASFCALL(sym->type))
3471 /* if any registers used */
3474 bool bits_pushed = FALSE;
3475 /* save the registers used */
3476 for (i = 0; i < sym->regsUsed->size; i++)
3478 if (bitVectBitValue (sym->regsUsed, i))
3479 bits_pushed = pushReg (i, bits_pushed);
3485 /* this function has a function call. We cannot
3486 determine register usage so we will have to push the
3488 saveRBank (0, ic, FALSE);
3489 if (options.parms_in_bank1) {
3490 for (i=0; i < 8 ; i++ ) {
3491 emitcode ("push","%s",rb1regs[i]);
3498 /* This ISR uses a non-zero bank.
3500 * We assume that the bank is available for our
3503 * However, if this ISR calls a function which uses some
3504 * other bank, we must save that bank entirely.
3506 unsigned long banksToSave = 0;
3508 if (IFFUNC_HASFCALL(sym->type))
3511 #define MAX_REGISTER_BANKS 4
3516 for (i = ic; i; i = i->next)
3518 if (i->op == ENDFUNCTION)
3520 /* we got to the end OK. */
3528 dtype = operandType (IC_LEFT(i));
3530 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3532 /* Mark this bank for saving. */
3533 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3535 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3539 banksToSave |= (1 << FUNC_REGBANK(dtype));
3542 /* And note that we don't need to do it in
3550 /* This is a mess; we have no idea what
3551 * register bank the called function might
3554 * The only thing I can think of to do is
3555 * throw a warning and hope.
3557 werror(W_FUNCPTR_IN_USING_ISR);
3561 if (banksToSave && options.useXstack)
3563 /* Since we aren't passing it an ic,
3564 * saveRBank will assume r0 is available to abuse.
3566 * So switch to our (trashable) bank now, so
3567 * the caller's R0 isn't trashed.
3569 emitcode ("push", "psw");
3570 emitcode ("mov", "psw,#!constbyte",
3571 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3575 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3577 if (banksToSave & (1 << ix))
3579 saveRBank(ix, NULL, FALSE);
3583 // TODO: this needs a closer look
3584 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3589 /* if callee-save to be used for this function
3590 then save the registers being used in this function */
3591 if (IFFUNC_CALLEESAVES(sym->type))
3595 /* if any registers used */
3598 bool bits_pushed = FALSE;
3599 /* save the registers used */
3600 for (i = 0; i < sym->regsUsed->size; i++)
3602 if (bitVectBitValue (sym->regsUsed, i))
3604 bits_pushed = pushReg (i, bits_pushed);
3612 /* set the register bank to the desired value */
3613 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3616 emitcode ("push", "psw");
3617 emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3621 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3622 if (options.stack10bit) {
3623 emitcode ("push","_bpx");
3624 emitcode ("push","_bpx+1");
3625 emitcode ("mov","_bpx,%s",spname);
3626 emitcode ("mov","_bpx+1,esp");
3627 adjustEsp("_bpx+1");
3629 if (options.useXstack)
3631 emitcode ("mov", "r0,%s", spname);
3632 emitcode ("mov", "a,_bp");
3633 emitcode ("movx", "@r0,a");
3634 emitcode ("inc", "%s", spname);
3636 /* set up the stack */
3637 emitcode ("push", "_bp"); /* save the callers stack */
3639 emitcode ("mov", "_bp,%s", spname);
3643 /* adjust the stack for the function */
3646 if (options.stack10bit) {
3647 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
3648 assert (sym->recvSize <= 4);
3649 if (sym->stack <= 8) {
3650 while (i--) emitcode ("push","acc");
3653 emitcode ("mov","a,sp");
3654 emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3655 emitcode ("mov","sp,a");
3656 emitcode ("mov","a,esp");
3658 emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3659 emitcode ("mov","esp,a");
3664 werror (W_STACK_OVERFLOW, sym->name);
3666 if (i > 3 && sym->recvSize < 4) {
3668 emitcode ("mov", "a,sp");
3669 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3670 emitcode ("mov", "sp,a");
3674 emitcode ("inc", "sp");
3681 emitcode ("mov", "a,_spx");
3682 emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3683 emitcode ("mov", "_spx,a");
3686 /* if critical function then turn interrupts off */
3687 if (IFFUNC_ISCRITICAL (ftype))
3689 symbol *tlbl = newiTempLabel (NULL);
3690 emitcode ("setb", "c");
3691 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3692 emitcode ("clr", "c");
3694 emitcode ("push", "psw"); /* save old ea via c in psw */
3698 /*-----------------------------------------------------------------*/
3699 /* genEndFunction - generates epilogue for functions */
3700 /*-----------------------------------------------------------------*/
3702 genEndFunction (iCode * ic)
3704 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3705 lineNode *lnp = lineCurr;
3707 bitVect *regsUsedPrologue;
3708 bitVect *regsUnneeded;
3711 D (emitcode (";", "genEndFunction"));
3713 _G.currentFunc = NULL;
3714 if (IFFUNC_ISNAKED(sym->type))
3716 emitcode(";", "naked function: no epilogue.");
3717 if (options.debug && currFunc)
3718 debugFile->writeEndFunction (currFunc, ic, 0);
3722 if (IFFUNC_ISCRITICAL (sym->type))
3724 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3726 emitcode ("rlc", "a"); /* save c in a */
3727 emitcode ("pop", "psw"); /* restore ea via c in psw */
3728 emitcode ("mov", "ea,c");
3729 emitcode ("rrc", "a"); /* restore c from a */
3733 emitcode ("pop", "psw"); /* restore ea via c in psw */
3734 emitcode ("mov", "ea,c");
3738 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3739 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3741 if (options.stack10bit) {
3743 emitcode ("mov", "sp,_bpx", spname);
3744 emitcode ("mov", "esp,_bpx+1", spname);
3747 emitcode ("mov", "%s,_bp", spname);
3751 /* if use external stack but some variables were
3752 added to the local stack then decrement the
3754 if (options.useXstack && sym->stack) {
3755 emitcode ("mov", "a,sp");
3756 emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3757 emitcode ("mov", "sp,a");
3761 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3762 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3764 if (options.useXstack) {
3765 emitcode ("mov", "r0,%s", spname);
3766 emitcode ("movx", "a,@r0");
3767 emitcode ("mov", "_bp,a");
3768 emitcode ("dec", "%s", spname);
3770 if (options.stack10bit) {
3771 emitcode ("pop", "_bpx+1");
3772 emitcode ("pop", "_bpx");
3774 emitcode ("pop", "_bp");
3779 /* restore the register bank */
3780 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3782 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3783 || !options.useXstack)
3785 /* Special case of ISR using non-zero bank with useXstack
3788 emitcode ("pop", "psw");
3792 if (IFFUNC_ISISR (sym->type))
3795 /* now we need to restore the registers */
3796 /* if this isr has no bank i.e. is going to
3797 run with bank 0 , then we need to save more
3799 if (!FUNC_REGBANK (sym->type))
3802 /* if this function does not call any other
3803 function then we can be economical and
3804 save only those registers that are used */
3805 if (!IFFUNC_HASFCALL(sym->type))
3807 /* if any registers used */
3810 bool bits_popped = FALSE;
3811 /* save the registers used */
3812 for (i = sym->regsUsed->size; i >= 0; i--)
3814 if (bitVectBitValue (sym->regsUsed, i))
3815 bits_popped = popReg (i, bits_popped);
3821 /* this function has a function call. We cannot
3822 determine register usage so we will have to pop the
3824 if (options.parms_in_bank1) {
3825 for (i = 7 ; i >= 0 ; i-- ) {
3826 emitcode ("pop","%s",rb1regs[i]);
3829 unsaveRBank (0, ic, FALSE);
3834 /* This ISR uses a non-zero bank.
3836 * Restore any register banks saved by genFunction
3839 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3842 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3844 if (savedBanks & (1 << ix))
3846 unsaveRBank(ix, NULL, FALSE);
3850 if (options.useXstack)
3852 /* Restore bank AFTER calling unsaveRBank,
3853 * since it can trash r0.
3855 emitcode ("pop", "psw");
3859 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3861 if (options.stack10bit)
3863 emitcode ("pop", DP2_RESULT_REG);
3864 emitcode ("pop", "dpx1");
3865 emitcode ("pop", "dph1");
3866 emitcode ("pop", "dpl1");
3868 emitcode ("pop", "dps");
3869 emitcode ("pop", "dpx");
3871 if (!inExcludeList ("dph"))
3872 emitcode ("pop", "dph");
3873 if (!inExcludeList ("dpl"))
3874 emitcode ("pop", "dpl");
3875 if (!inExcludeList ("b"))
3876 emitcode ("pop", "b");
3877 if (!inExcludeList ("acc"))
3878 emitcode ("pop", "acc");
3880 /* if debug then send end of function */
3881 if (options.debug && currFunc)
3883 debugFile->writeEndFunction (currFunc, ic, 1);
3886 emitcode ("reti", "");
3890 if (IFFUNC_CALLEESAVES(sym->type))
3894 /* if any registers used */
3897 /* save the registers used */
3898 for (i = sym->regsUsed->size; i >= 0; i--)
3900 if (bitVectBitValue (sym->regsUsed, i))
3901 emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
3906 /* if debug then send end of function */
3907 if (options.debug && currFunc)
3909 debugFile->writeEndFunction (currFunc, ic, 1);
3912 emitcode ("ret", "");
3915 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3918 /* If this was an interrupt handler using bank 0 that called another */
3919 /* function, then all registers must be saved; nothing to optimized. */
3920 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3921 && !FUNC_REGBANK(sym->type))
3924 /* There are no push/pops to optimize if not callee-saves or ISR */
3925 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3928 /* If there were stack parameters, we cannot optimize without also */
3929 /* fixing all of the stack offsets; this is too dificult to consider. */
3930 if (FUNC_HASSTACKPARM(sym->type))
3933 /* Compute the registers actually used */
3934 regsUsed = newBitVect (ds390_nRegs);
3935 regsUsedPrologue = newBitVect (ds390_nRegs);
3938 if (lnp->ic && lnp->ic->op == FUNCTION)
3939 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3941 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3943 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3944 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3951 if (bitVectBitValue (regsUsedPrologue, DPS_IDX)
3952 && !bitVectBitValue (regsUsed, DPS_IDX))
3954 bitVectUnSetBit (regsUsedPrologue, DPS_IDX);
3957 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3958 && !bitVectBitValue (regsUsed, CND_IDX))
3960 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3961 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3962 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3963 bitVectUnSetBit (regsUsed, CND_IDX);
3966 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3968 /* If this was an interrupt handler that called another function */
3969 /* function, then assume working registers may be modified by it. */
3970 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3972 regsUsed = bitVectSetBit (regsUsed, AP_IDX);
3973 regsUsed = bitVectSetBit (regsUsed, DPX1_IDX);
3974 regsUsed = bitVectSetBit (regsUsed, DPL1_IDX);
3975 regsUsed = bitVectSetBit (regsUsed, DPH1_IDX);
3976 regsUsed = bitVectSetBit (regsUsed, DPX_IDX);
3977 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3978 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3979 regsUsed = bitVectSetBit (regsUsed, DPS_IDX);
3980 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3981 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3982 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3985 /* Remove the unneeded push/pops */
3986 regsUnneeded = newBitVect (ds390_nRegs);
3989 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3991 if (!strncmp(lnp->line, "push", 4))
3993 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3994 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3996 connectLine (lnp->prev, lnp->next);
3997 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4000 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
4002 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
4003 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4005 connectLine (lnp->prev, lnp->next);
4006 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4013 for (idx = 0; idx < regsUnneeded->size; idx++)
4014 if (bitVectBitValue (regsUnneeded, idx))
4015 emitcode (";", "eliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
4017 freeBitVect (regsUnneeded);
4018 freeBitVect (regsUsed);
4019 freeBitVect (regsUsedPrologue);
4022 /*-----------------------------------------------------------------*/
4023 /* genJavaNativeRet - generate code for return JavaNative */
4024 /*-----------------------------------------------------------------*/
4025 static void genJavaNativeRet(iCode *ic)
4029 aopOp (IC_LEFT (ic), ic, FALSE,
4030 AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
4031 size = AOP_SIZE (IC_LEFT (ic));
4035 /* it is assigned to GPR0-R3 then push them */
4036 if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
4037 aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
4038 for (i = 0 ; i < size ; i++ ) {
4039 emitcode ("push","%s",
4040 aopGet(IC_LEFT(ic),i,FALSE,TRUE,DP2_RESULT_REG));
4042 for (i = (size-1) ; i >= 0 ; i--) {
4043 emitcode ("pop","a%s",javaRet[i]);
4046 for (i = 0 ; i < size ; i++)
4047 emitcode ("mov","%s,%s",javaRet[i],
4048 aopGet(IC_LEFT(ic),i,FALSE,TRUE,DP2_RESULT_REG));
4050 for (i = size ; i < 4 ; i++ )
4051 emitcode ("mov","%s,#0",javaRet[i]);
4055 /*-----------------------------------------------------------------*/
4056 /* genRet - generate code for return statement */
4057 /*-----------------------------------------------------------------*/
4061 int size, offset = 0, pushed = 0;
4063 D (emitcode (";", "genRet"));
4065 /* if we have no return value then
4066 just generate the "ret" */
4070 /* if this is a JavaNative function then return
4071 value in different register */
4072 if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
4073 genJavaNativeRet(ic);
4076 /* we have something to return then
4077 move the return value into place */
4078 aopOp (IC_LEFT (ic), ic, FALSE,
4079 (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
4080 size = AOP_SIZE (IC_LEFT (ic));
4082 _startLazyDPSEvaluation ();
4084 if (IS_BIT(_G.currentFunc->etype))
4086 movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4093 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
4095 l = aopGet (IC_LEFT (ic), offset++,
4097 emitcode ("push", "%s", l);
4102 /* Since A is the last element of fReturn,
4103 * it is OK to clobber it in the aopGet.
4105 l = aopGet (IC_LEFT (ic), offset,
4106 FALSE, FALSE, NULL);
4107 if (strcmp (fReturn[offset], l))
4108 emitcode ("mov", "%s,%s", fReturn[offset++], l);
4111 _endLazyDPSEvaluation ();
4116 if (strcmp (fReturn[pushed], "a"))
4117 emitcode ("pop", fReturn[pushed]);
4119 emitcode ("pop", "acc");
4121 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
4124 /* generate a jump to the return label
4125 if the next is not the return statement */
4126 if (!(ic->next && ic->next->op == LABEL &&
4127 IC_LABEL (ic->next) == returnLabel))
4129 emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
4133 /*-----------------------------------------------------------------*/
4134 /* genLabel - generates a label */
4135 /*-----------------------------------------------------------------*/
4137 genLabel (iCode * ic)
4139 /* special case never generate */
4140 if (IC_LABEL (ic) == entryLabel)
4143 D (emitcode (";", "genLabel"));
4145 emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
4148 /*-----------------------------------------------------------------*/
4149 /* genGoto - generates a ljmp */
4150 /*-----------------------------------------------------------------*/
4152 genGoto (iCode * ic)
4154 D (emitcode (";", "genGoto"));
4156 emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
4159 /*-----------------------------------------------------------------*/
4160 /* findLabelBackwards: walks back through the iCode chain looking */
4161 /* for the given label. Returns number of iCode instructions */
4162 /* between that label and given ic. */
4163 /* Returns zero if label not found. */
4164 /*-----------------------------------------------------------------*/
4166 findLabelBackwards (iCode * ic, int key)
4175 /* If we have any pushes or pops, we cannot predict the distance.
4176 I don't like this at all, this should be dealt with in the
4178 if (ic->op == IPUSH || ic->op == IPOP) {
4182 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4184 /* printf("findLabelBackwards = %d\n", count); */
4192 /*-----------------------------------------------------------------*/
4193 /* genPlusIncr :- does addition with increment if possible */
4194 /*-----------------------------------------------------------------*/
4196 genPlusIncr (iCode * ic)
4198 unsigned int icount;
4199 unsigned int size = getDataSize (IC_RESULT (ic));
4201 /* will try to generate an increment */
4202 /* if the right side is not a literal
4204 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4207 /* if the literal value of the right hand side
4208 is greater than 4 then it is not worth it */
4209 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4212 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4213 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4215 emitcode("inc","%s",aopGet(IC_RESULT(ic),0,FALSE,FALSE,NULL));
4219 /* if increment 16 bits in register */
4221 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4222 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4223 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4232 /* If the next instruction is a goto and the goto target
4233 * is <= 5 instructions previous to this, we can generate
4234 * jumps straight to that target.
4236 if (ic->next && ic->next->op == GOTO
4237 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4240 D (emitcode (";", "tail increment optimized (range %d)", labelRange));
4241 tlbl = IC_LABEL (ic->next);
4246 tlbl = newiTempLabel (NULL);
4249 l = aopGet (IC_RESULT (ic), LSB, FALSE, FALSE, NULL);
4250 emitcode ("inc", "%s", l);
4252 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4253 IS_AOP_PREG (IC_RESULT (ic)))
4255 emitcode ("cjne", "%s,%s,!tlabel", l, zero, tlbl->key + 100);
4259 emitcode ("clr", "a");
4260 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4263 l = aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE, NULL);
4264 emitcode ("inc", "%s", l);
4267 if (!strcmp(l, "acc"))
4269 emitcode("jnz", "!tlabel", tlbl->key + 100);
4271 else 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 ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4281 l = aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE, NULL);
4282 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), MSB32, FALSE, FALSE, NULL);
4301 emitcode ("inc", "%s", l);
4311 if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
4312 !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 &&
4313 options.model == MODEL_FLAT24 )
4315 if (IC_RESULT(ic)->isGptr)
4317 emitcode ("mov", "b,%s", aopGet(IC_LEFT (ic), 3, FALSE, FALSE, NULL));
4321 emitcode ("mov", "dpx,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE, NULL));
4323 emitcode ("mov", "dph,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE, NULL));
4325 emitcode ("mov", "dpl,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4329 emitcode ("inc", "dptr");
4333 if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
4334 AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
4336 emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
4338 emitcode ("inc", "dptr");
4339 emitcode ("mov", "dps,#0");
4343 /* if the sizes are greater than 1 then we cannot */
4344 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4345 AOP_SIZE (IC_LEFT (ic)) > 1)
4348 /* we can if the aops of the left & result match or
4349 if they are in registers and the registers are the
4352 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4353 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4354 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4358 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4359 emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
4360 aopPut (IC_RESULT (ic), "a", 0);
4364 _startLazyDPSEvaluation ();
4367 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4369 _endLazyDPSEvaluation ();
4378 /*-----------------------------------------------------------------*/
4379 /* outBitAcc - output a bit in acc */
4380 /*-----------------------------------------------------------------*/
4382 outBitAcc (operand * result)
4384 symbol *tlbl = newiTempLabel (NULL);
4385 /* if the result is a bit */
4386 if (AOP_TYPE (result) == AOP_CRY)
4388 aopPut (result, "a", 0);
4392 emitcode ("jz", "!tlabel", tlbl->key + 100);
4393 emitcode ("mov", "a,%s", one);
4399 /*-----------------------------------------------------------------*/
4400 /* genPlusBits - generates code for addition of two bits */
4401 /*-----------------------------------------------------------------*/
4403 genPlusBits (iCode * ic)
4405 D (emitcode (";", "genPlusBits"));
4407 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4409 symbol *lbl = newiTempLabel (NULL);
4410 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4411 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4412 emitcode ("cpl", "c");
4414 outBitC (IC_RESULT (ic));
4418 emitcode ("clr", "a");
4419 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4420 emitcode ("rlc", "a");
4421 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4422 emitcode ("addc", "a,%s", zero);
4423 outAcc (IC_RESULT (ic));
4428 adjustArithmeticResult (iCode * ic)
4430 if (opIsGptr (IC_RESULT (ic)) &&
4431 opIsGptr (IC_LEFT (ic)) &&
4432 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4434 aopPut (IC_RESULT (ic),
4435 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE, NULL),
4439 if (opIsGptr (IC_RESULT (ic)) &&
4440 opIsGptr (IC_RIGHT (ic)) &&
4441 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4443 aopPut (IC_RESULT (ic),
4444 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE, NULL),
4448 if (opIsGptr (IC_RESULT (ic)) &&
4449 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4450 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4451 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4452 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4455 SNPRINTF (buffer, sizeof(buffer),
4456 "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4457 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4461 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
4462 // generates the result if possible. If result is generated, returns TRUE; otherwise
4463 // returns false and caller must deal with fact that result isn't aopOp'd.
4464 bool aopOp3(iCode * ic)
4466 bool dp1InUse, dp2InUse;
4469 // First, generate the right opcode. DPTR may be used if neither left nor result are
4472 // D (emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
4473 // AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
4474 // AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
4475 // AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
4477 // D (emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
4478 // AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
4479 // AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
4480 // AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
4483 // Right uses DPTR unless left or result is an AOP_STR; however,
4484 // if right is an AOP_STR, it must use DPTR regardless.
4485 if ((AOP_IS_STR (IC_LEFT (ic)) || AOP_IS_STR (IC_RESULT (ic)))
4486 && !AOP_IS_STR (IC_RIGHT (ic)))
4495 aopOp (IC_RIGHT(ic), ic, FALSE, useDp2);
4497 // if the right used DPTR, left MUST use DPTR2.
4498 // if the right used DPTR2, left MUST use DPTR.
4499 // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
4500 // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
4501 // enabling us to assign DPTR to result.
4503 if (AOP_USESDPTR (IC_RIGHT (ic)))
4507 else if (AOP_USESDPTR2 (IC_RIGHT (ic)))
4513 if (AOP_IS_STR (IC_RESULT (ic)) && !AOP_IS_STR (IC_LEFT (ic)))
4523 aopOp (IC_LEFT (ic), ic, FALSE, useDp2);
4526 // We've op'd the left & right. So, if left or right are the same operand as result,
4527 // we know aopOp will succeed, and we can just do it & bail.
4528 if (isOperandEqual (IC_LEFT (ic), IC_RESULT (ic)))
4530 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4533 if (isOperandEqual (IC_RIGHT (ic), IC_RESULT (ic)))
4535 // D (emitcode(";", "aopOp3: (left | right) & result equal"));
4536 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4540 // Operands may be equivalent (but not equal) if they share a spill location. If
4541 // so, use the same DPTR or DPTR2.
4542 if (operandsEqu (IC_LEFT (ic), IC_RESULT (ic)))
4544 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4547 if (operandsEqu (IC_RIGHT (ic), IC_RESULT (ic)))
4549 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4553 // Note which dptrs are currently in use.
4554 dp1InUse = AOP_USESDPTR (IC_LEFT (ic)) || AOP_USESDPTR (IC_RIGHT (ic));
4555 dp2InUse = AOP_USESDPTR2 (IC_LEFT (ic)) || AOP_USESDPTR2 (IC_RIGHT (ic));
4557 // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot
4559 if (dp1InUse && AOP_IS_STR (IC_RESULT (ic)))
4564 // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
4565 if (dp2InUse && AOP_IS_DPTRn (IC_RESULT (ic)))
4570 // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck
4571 if (dp1InUse && dp2InUse && isOperandInFarSpace (IC_RESULT (ic)))
4576 aopOp (IC_RESULT (ic), ic, TRUE, dp1InUse);
4578 // Some sanity checking...
4579 if (dp1InUse && AOP_USESDPTR (IC_RESULT (ic)))
4582 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
4583 __FILE__, __LINE__, ic->filename, ic->lineno);
4584 emitcode(";", ">>> unexpected DPTR here.");
4587 if (dp2InUse && AOP_USESDPTR2 (IC_RESULT (ic)))
4590 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
4591 __FILE__, __LINE__, ic->filename, ic->lineno);
4592 emitcode(";", ">>> unexpected DPTR2 here.");
4598 // Macro to aopOp all three operands of an ic. If this cannot be done,
4599 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
4600 // will be set TRUE. The caller must then handle the case specially, noting
4601 // that the IC_RESULT operand is not aopOp'd.
4603 #define AOP_OP_3_NOFATAL(ic, rc) \
4604 do { rc = !aopOp3(ic); } while (0)
4606 // aopOp the left & right operands of an ic.
4607 #define AOP_OP_2(ic) \
4608 aopOp (IC_RIGHT (ic), ic, FALSE, AOP_IS_STR (IC_LEFT (ic))); \
4609 aopOp (IC_LEFT (ic), ic, FALSE, AOP_USESDPTR (IC_RIGHT (ic)));
4611 // convienience macro.
4612 #define AOP_SET_LOCALS(ic) \
4613 left = IC_LEFT(ic); \
4614 right = IC_RIGHT(ic); \
4615 result = IC_RESULT(ic);
4618 // Given an integer value of pushedSize bytes on the stack,
4619 // adjust it to be resultSize bytes, either by discarding
4620 // the most significant bytes or by zero-padding.
4622 // On exit from this macro, pushedSize will have been adjusted to
4623 // equal resultSize, and ACC may be trashed.
4624 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
4625 /* If the pushed data is bigger than the result, \
4626 * simply discard unused bytes. Icky, but works. \
4628 while (pushedSize > resultSize) \
4630 D (emitcode (";", "discarding unused result byte.")); \
4631 emitcode ("pop", "acc"); \
4634 if (pushedSize < resultSize) \
4636 emitcode ("clr", "a"); \
4637 /* Conversly, we haven't pushed enough here. \
4638 * just zero-pad, and all is well. \
4640 while (pushedSize < resultSize) \
4642 emitcode("push", "acc"); \
4646 assert(pushedSize == resultSize);
4648 /*-----------------------------------------------------------------*/
4649 /* genPlus - generates code for addition */
4650 /*-----------------------------------------------------------------*/
4652 genPlus (iCode * ic)
4654 int size, offset = 0;
4657 bool swappedLR = FALSE;
4659 D (emitcode (";", "genPlus"));
4661 /* special cases :- */
4662 if ( AOP_IS_STR (IC_LEFT (ic)) &&
4663 isOperandLiteral (IC_RIGHT (ic)) && OP_SYMBOL (IC_RESULT (ic))->ruonly) {
4664 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
4665 size = (int)floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4667 while (size--) emitcode ("inc","dptr");
4669 emitcode ("mov", "a,dpl");
4670 emitcode ("add", "a,#!constbyte", size & 0xff);
4671 emitcode ("mov", "dpl,a");
4672 emitcode ("mov", "a,dph");
4673 emitcode ("addc", "a,#!constbyte", (size >> 8) & 0xff);
4674 emitcode ("mov", "dph,a");
4675 emitcode ("mov", "a,dpx");
4676 emitcode ("addc", "a,#!constbyte", (size >> 16) & 0xff);
4677 emitcode ("mov", "dpx,a");
4679 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4682 if ( IS_SYMOP (IC_LEFT (ic)) &&
4683 OP_SYMBOL (IC_LEFT (ic))->remat &&
4684 isOperandInFarSpace (IC_RIGHT (ic))) {
4685 operand *op = IC_RIGHT(ic);
4686 IC_RIGHT(ic) = IC_LEFT(ic);
4690 AOP_OP_3_NOFATAL (ic, pushResult);
4694 D (emitcode (";", "genPlus: must push result: 3 ops in far space"));
4699 /* if literal, literal on the right or
4700 if left requires ACC or right is already
4702 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4703 ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic)))) ||
4704 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4706 operand *t = IC_RIGHT (ic);
4707 IC_RIGHT (ic) = IC_LEFT (ic);
4710 D (emitcode (";", "Swapped plus args."));
4713 /* if both left & right are in bit
4715 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4716 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4722 /* if left in bit space & right literal */
4723 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4724 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4726 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4727 /* if result in bit space */
4728 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4730 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4731 emitcode ("cpl", "c");
4732 outBitC (IC_RESULT (ic));
4736 size = getDataSize (IC_RESULT (ic));
4737 _startLazyDPSEvaluation ();
4740 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4741 emitcode ("addc", "a,%s", zero);
4742 aopPut (IC_RESULT (ic), "a", offset++);
4744 _endLazyDPSEvaluation ();
4749 /* if I can do an increment instead
4750 of add then GOOD for ME */
4751 if (genPlusIncr (ic) == TRUE)
4753 D (emitcode (";", "did genPlusIncr"));
4758 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4760 _startLazyDPSEvaluation ();
4763 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4765 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
4767 emitcode ("add", "a,%s",
4768 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4770 emitcode ("addc", "a,%s",
4771 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4775 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4777 /* right is going to use ACC or we would have taken the
4780 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4782 D(emitcode(";", "+ AOP_ACC special case."););
4783 emitcode("xch", "a, %s", DP2_RESULT_REG);
4785 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4788 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4791 emitcode("add", "a, %s", DP2_RESULT_REG);
4795 emitcode ("add", "a,%s",
4796 aopGet (IC_LEFT(ic), offset, FALSE, FALSE,
4802 emitcode ("addc", "a,%s",
4803 aopGet (IC_LEFT (ic), offset, FALSE, FALSE,
4809 aopPut (IC_RESULT (ic), "a", offset);
4813 emitcode ("push", "acc");
4817 _endLazyDPSEvaluation ();
4821 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4823 size = getDataSize (IC_LEFT (ic));
4824 rSize = getDataSize (IC_RESULT (ic));
4826 ADJUST_PUSHED_RESULT(size, rSize);
4828 _startLazyDPSEvaluation ();
4831 emitcode ("pop", "acc");
4832 aopPut (IC_RESULT (ic), "a", size);
4834 _endLazyDPSEvaluation ();
4837 adjustArithmeticResult (ic);
4840 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4843 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4844 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4848 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4849 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4853 /*-----------------------------------------------------------------*/
4854 /* genMinusDec :- does subtraction with decrement if possible */
4855 /*-----------------------------------------------------------------*/
4857 genMinusDec (iCode * ic)
4859 unsigned int icount;
4860 unsigned int size = getDataSize (IC_RESULT (ic));
4862 /* will try to generate an increment */
4863 /* if the right side is not a literal
4865 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4868 /* if the literal value of the right hand side
4869 is greater than 4 then it is not worth it */
4870 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4873 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4874 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4876 emitcode("dec","%s",aopGet(IC_RESULT(ic),0,FALSE,FALSE,NULL));
4880 /* if decrement 16 bits in register */
4881 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4882 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4883 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4892 /* If the next instruction is a goto and the goto target
4893 * is <= 5 instructions previous to this, we can generate
4894 * jumps straight to that target.
4896 if (ic->next && ic->next->op == GOTO
4897 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4900 D (emitcode (";", "tail decrement optimized (range %d)", labelRange));
4901 tlbl = IC_LABEL (ic->next);
4906 tlbl = newiTempLabel (NULL);
4910 l = aopGet (IC_RESULT (ic), LSB, FALSE, FALSE, NULL);
4911 emitcode ("dec", "%s", l);
4913 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4914 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4915 IS_AOP_PREG (IC_RESULT (ic)))
4917 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4921 emitcode ("mov", "a,#!constbyte",0xff);
4922 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4924 l = aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE, NULL);
4925 emitcode ("dec", "%s", l);
4928 if (!strcmp(l, "acc"))
4930 emitcode("jnz", "!tlabel", tlbl->key + 100);
4932 else 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), MSB24, FALSE, FALSE, NULL);
4944 emitcode ("dec", "%s", l);
4948 if (!strcmp(l, "acc"))
4950 emitcode("jnz", "!tlabel", tlbl->key + 100);
4952 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4953 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4954 IS_AOP_PREG (IC_RESULT (ic)))
4956 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4960 emitcode ("mov", "a,#!constbyte",0xff);
4961 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4963 l = aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE, NULL);
4964 emitcode ("dec", "%s", l);
4973 /* if the sizes are greater than 1 then we cannot */
4974 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4975 AOP_SIZE (IC_LEFT (ic)) > 1)
4978 /* we can if the aops of the left & result match or
4979 if they are in registers and the registers are the
4982 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4983 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4984 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4988 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4990 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL));
4995 l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL);
4998 _startLazyDPSEvaluation ();
5001 emitcode ("dec", "%s", l);
5003 _endLazyDPSEvaluation ();
5005 if (AOP_NEEDSACC (IC_RESULT (ic)))
5006 aopPut (IC_RESULT (ic), "a", 0);
5014 /*-----------------------------------------------------------------*/
5015 /* addSign - complete with sign */
5016 /*-----------------------------------------------------------------*/
5018 addSign (operand * result, int offset, int sign)
5020 int size = (getDataSize (result) - offset);
5023 _startLazyDPSEvaluation();
5026 emitcode ("rlc", "a");
5027 emitcode ("subb", "a,acc");
5030 aopPut (result, "a", offset++);
5037 aopPut (result, zero, offset++);
5040 _endLazyDPSEvaluation();
5044 /*-----------------------------------------------------------------*/
5045 /* genMinusBits - generates code for subtraction of two bits */
5046 /*-----------------------------------------------------------------*/
5048 genMinusBits (iCode * ic)
5050 symbol *lbl = newiTempLabel (NULL);
5052 D (emitcode (";", "genMinusBits"));
5054 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
5056 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
5057 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
5058 emitcode ("cpl", "c");
5060 outBitC (IC_RESULT (ic));
5064 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
5065 emitcode ("subb", "a,acc");
5066 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
5067 emitcode ("inc", "a");
5069 aopPut (IC_RESULT (ic), "a", 0);
5070 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
5074 /*-----------------------------------------------------------------*/
5075 /* genMinus - generates code for subtraction */
5076 /*-----------------------------------------------------------------*/
5078 genMinus (iCode * ic)
5080 int size, offset = 0;
5085 D (emitcode (";", "genMinus"));
5087 AOP_OP_3_NOFATAL(ic, pushResult);
5091 /* special cases :- */
5092 /* if both left & right are in bit space */
5093 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
5094 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
5100 /* if I can do an decrement instead
5101 of subtract then GOOD for ME */
5102 if (genMinusDec (ic) == TRUE)
5107 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
5109 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
5115 lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5120 /* if literal, add a,#-lit, else normal subb */
5121 _startLazyDPSEvaluation ();
5123 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
5124 if (AOP_USESDPTR(IC_RIGHT(ic))) {
5125 emitcode ("mov","b,%s",
5126 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
5127 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
5128 emitcode ("subb","a,b");
5130 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
5131 emitcode ("subb", "a,%s",
5132 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE,
5136 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
5137 /* first add without previous c */
5139 if (!size && lit==-1) {
5140 emitcode ("dec", "a");
5142 emitcode ("add", "a,#!constbyte",
5143 (unsigned int) (lit & 0x0FFL));
5146 emitcode ("addc", "a,#!constbyte",
5147 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5152 emitcode ("push", "acc");
5154 aopPut (IC_RESULT (ic), "a", offset);
5158 _endLazyDPSEvaluation ();
5162 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
5164 size = getDataSize (IC_LEFT (ic));
5165 rSize = getDataSize (IC_RESULT (ic));
5167 ADJUST_PUSHED_RESULT(size, rSize);
5169 _startLazyDPSEvaluation ();
5172 emitcode ("pop", "acc");
5173 aopPut (IC_RESULT (ic), "a", size);
5175 _endLazyDPSEvaluation ();
5178 adjustArithmeticResult (ic);
5181 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5182 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5183 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5187 /*-----------------------------------------------------------------*/
5188 /* genMultbits :- multiplication of bits */
5189 /*-----------------------------------------------------------------*/
5191 genMultbits (operand * left,
5196 D (emitcode (";", "genMultbits"));
5198 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5199 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5200 aopOp(result, ic, TRUE, FALSE);
5204 /*-----------------------------------------------------------------*/
5205 /* genMultOneByte : 8*8=8/16 bit multiplication */
5206 /*-----------------------------------------------------------------*/
5208 genMultOneByte (operand * left,
5215 bool runtimeSign, compiletimeSign;
5216 bool lUnsigned, rUnsigned, pushedB;
5218 /* (if two literals: the value is computed before) */
5219 /* if one literal, literal on the right */
5220 if (AOP_TYPE (left) == AOP_LIT)
5225 /* emitcode (";", "swapped left and right"); */
5227 /* if no literal, unsigned on the right: shorter code */
5228 if ( AOP_TYPE (right) != AOP_LIT
5229 && SPEC_USIGN (getSpec (operandType (left))))
5236 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5237 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5241 if ((lUnsigned && rUnsigned)
5242 /* sorry, I don't know how to get size
5243 without calling aopOp (result,...);
5244 see Feature Request */
5245 /* || size == 1 */ ) /* no, this is not a bug; with a 1 byte result there's
5246 no need to take care about the signedness! */
5248 /* just an unsigned 8 * 8 = 8 multiply
5250 /* emitcode (";","unsigned"); */
5251 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
5252 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
5253 emitcode ("mul", "ab");
5256 aopOp (result, ic, TRUE, FALSE);
5257 size = AOP_SIZE (result);
5259 if (size < 1 || size > 2)
5261 /* this should never happen */
5262 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
5263 size, __FILE__, lineno);
5267 aopPut (result, "a", 0);
5270 aopPut (result, "b", 1);
5276 /* we have to do a signed multiply */
5277 /* emitcode (";", "signed"); */
5279 /* now sign adjust for both left & right */
5281 /* let's see what's needed: */
5282 /* apply negative sign during runtime */
5283 runtimeSign = FALSE;
5284 /* negative sign from literals */
5285 compiletimeSign = FALSE;
5289 if (AOP_TYPE(left) == AOP_LIT)
5291 /* signed literal */
5292 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5294 compiletimeSign = TRUE;
5297 /* signed but not literal */
5303 if (AOP_TYPE(right) == AOP_LIT)
5305 /* signed literal */
5306 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5308 compiletimeSign ^= TRUE;
5311 /* signed but not literal */
5315 /* initialize F0, which stores the runtime sign */
5318 if (compiletimeSign)
5319 emitcode ("setb", "F0"); /* set sign flag */
5321 emitcode ("clr", "F0"); /* reset sign flag */
5324 /* save the signs of the operands */
5325 if (AOP_TYPE(right) == AOP_LIT)
5327 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5329 if (!rUnsigned && val < 0)
5330 emitcode ("mov", "b,#!constbyte", -val);
5332 emitcode ("mov", "b,#!constbyte", (unsigned char) val);
5334 else /* ! literal */
5336 if (rUnsigned) /* emitcode (";", "signed"); */
5337 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
5340 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
5341 lbl = newiTempLabel (NULL);
5342 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5343 emitcode ("cpl", "F0"); /* complement sign flag */
5344 emitcode ("cpl", "a"); /* 2's complement */
5345 emitcode ("inc", "a");
5347 emitcode ("mov", "b,a");
5351 if (AOP_TYPE(left) == AOP_LIT)
5353 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5355 if (!lUnsigned && val < 0)
5356 emitcode ("mov", "a,#!constbyte", -val);
5358 emitcode ("mov", "a,#!constbyte", (unsigned char) val);
5360 else /* ! literal */
5362 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
5364 if (!lUnsigned) /* emitcode (";", "signed"); */
5366 lbl = newiTempLabel (NULL);
5367 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5368 emitcode ("cpl", "F0"); /* complement sign flag */
5369 emitcode ("cpl", "a"); /* 2's complement */
5370 emitcode ("inc", "a");
5375 /* now the multiplication */
5376 emitcode ("mul", "ab");
5378 aopOp(result, ic, TRUE, FALSE);
5379 size = AOP_SIZE (result);
5381 if (size < 1 || size > 2)
5383 /* this should never happen */
5384 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
5385 size, __FILE__, lineno);
5389 if (runtimeSign || compiletimeSign)
5391 lbl = newiTempLabel (NULL);
5393 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5394 emitcode ("cpl", "a"); /* lsb 2's complement */
5396 emitcode ("inc", "a"); /* inc doesn't set carry flag */
5399 emitcode ("add", "a,#1"); /* this sets carry flag */
5400 emitcode ("xch", "a,b");
5401 emitcode ("cpl", "a"); /* msb 2's complement */
5402 emitcode ("addc", "a,#0");
5403 emitcode ("xch", "a,b");
5407 aopPut (result, "a", 0);
5410 aopPut (result, "b", 1);
5415 /*-----------------------------------------------------------------*/
5416 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
5417 /*-----------------------------------------------------------------*/
5418 static void genMultTwoByte (operand *left, operand *right,
5419 operand *result, iCode *ic)
5421 sym_link *retype = getSpec(operandType(right));
5422 sym_link *letype = getSpec(operandType(left));
5423 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5426 if (AOP_TYPE (left) == AOP_LIT) {
5431 /* save EA bit in F1 */
5432 lbl = newiTempLabel(NULL);
5433 emitcode ("setb","F1");
5434 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5435 emitcode ("clr","F1");
5438 /* load up MB with right */
5440 emitcode("clr","F0");
5441 if (AOP_TYPE(right) == AOP_LIT) {
5442 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5444 emitcode("setb","F0");
5447 emitcode ("mov","mb,#!constbyte",val & 0xff);
5448 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5450 lbl = newiTempLabel(NULL);
5451 emitcode ("mov","b,%s",aopGet(right,0,FALSE,FALSE,NULL));
5452 emitcode ("mov","a,%s",aopGet(right,1,FALSE,FALSE,NULL));
5453 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5454 emitcode ("xch", "a,b");
5455 emitcode ("cpl","a");
5456 emitcode ("add", "a,#1");
5457 emitcode ("xch", "a,b");
5458 emitcode ("cpl", "a"); // msb
5459 emitcode ("addc", "a,#0");
5460 emitcode ("setb","F0");
5462 emitcode ("mov","mb,b");
5463 emitcode ("mov","mb,a");
5466 emitcode ("mov","mb,%s",aopGet(right,0,FALSE,FALSE,NULL));
5467 emitcode ("mov","mb,%s",aopGet(right,1,FALSE,FALSE,NULL));
5469 /* load up MA with left */
5471 lbl = newiTempLabel(NULL);
5472 emitcode ("mov","b,%s",aopGet(left,0,FALSE,FALSE,NULL));
5473 emitcode ("mov","a,%s",aopGet(left,1,FALSE,FALSE,NULL));
5474 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5475 emitcode ("xch", "a,b");
5476 emitcode ("cpl","a");
5477 emitcode ("add", "a,#1");
5478 emitcode ("xch", "a,b");
5479 emitcode ("cpl", "a"); // msb
5480 emitcode ("addc","a,#0");
5481 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5482 emitcode ("setb","F0");
5484 emitcode ("mov","ma,b");
5485 emitcode ("mov","ma,a");
5487 emitcode ("mov","ma,%s",aopGet(left,0,FALSE,FALSE,NULL));
5488 emitcode ("mov","ma,%s",aopGet(left,1,FALSE,FALSE,NULL));
5490 /* wait for multiplication to finish */
5491 lbl = newiTempLabel(NULL);
5493 emitcode("mov","a,mcnt1");
5494 emitcode("anl","a,#!constbyte",0x80);
5495 emitcode("jnz","!tlabel",lbl->key+100);
5497 freeAsmop (left, NULL, ic, TRUE);
5498 freeAsmop (right, NULL, ic,TRUE);
5499 aopOp(result, ic, TRUE, FALSE);
5501 /* if unsigned then simple */
5503 emitcode ("mov","a,ma");
5504 if (AOP_SIZE(result) >= 4) aopPut(result,"a",3);
5505 emitcode ("mov","a,ma");
5506 if (AOP_SIZE(result) >= 3) aopPut(result,"a",2);
5507 aopPut(result,"ma",1);
5508 aopPut(result,"ma",0);
5510 emitcode("push","ma");
5511 emitcode("push","ma");
5512 emitcode("push","ma");
5514 /* negate result if needed */
5515 lbl = newiTempLabel(NULL);
5516 emitcode("jnb","F0,!tlabel",lbl->key+100);
5517 emitcode("cpl","a");
5518 emitcode("add","a,#1");
5520 if (AOP_TYPE(result) == AOP_ACC)
5522 D (emitcode(";", "ACC special case."));
5523 /* We know result is the only live aop, and
5524 * it's obviously not a DPTR2, so AP is available.
5526 emitcode("mov", "%s,acc", DP2_RESULT_REG);
5530 aopPut(result,"a",0);
5533 emitcode("pop","acc");
5534 lbl = newiTempLabel(NULL);
5535 emitcode("jnb","F0,!tlabel",lbl->key+100);
5536 emitcode("cpl","a");
5537 emitcode("addc","a,#0");
5539 aopPut(result,"a",1);
5540 emitcode("pop","acc");
5541 if (AOP_SIZE(result) >= 3) {
5542 lbl = newiTempLabel(NULL);
5543 emitcode("jnb","F0,!tlabel",lbl->key+100);
5544 emitcode("cpl","a");
5545 emitcode("addc","a,#0");
5547 aopPut(result,"a",2);
5549 emitcode("pop","acc");
5550 if (AOP_SIZE(result) >= 4) {
5551 lbl = newiTempLabel(NULL);
5552 emitcode("jnb","F0,!tlabel",lbl->key+100);
5553 emitcode("cpl","a");
5554 emitcode("addc","a,#0");
5556 aopPut(result,"a",3);
5558 if (AOP_TYPE(result) == AOP_ACC)
5560 /* We stashed the result away above. */
5561 emitcode("mov", "acc,%s", DP2_RESULT_REG);
5565 freeAsmop (result, NULL, ic, TRUE);
5567 /* restore EA bit in F1 */
5568 lbl = newiTempLabel(NULL);
5569 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5570 emitcode ("setb","EA");
5575 /*-----------------------------------------------------------------*/
5576 /* genMult - generates code for multiplication */
5577 /*-----------------------------------------------------------------*/
5579 genMult (iCode * ic)
5581 operand *left = IC_LEFT (ic);
5582 operand *right = IC_RIGHT (ic);
5583 operand *result = IC_RESULT (ic);
5585 D (emitcode (";", "genMult"));
5587 /* assign the asmops */
5590 /* special cases first */
5592 if (AOP_TYPE (left) == AOP_CRY &&
5593 AOP_TYPE (right) == AOP_CRY)
5595 genMultbits (left, right, result, ic);
5599 /* if both are of size == 1 */
5600 if (AOP_SIZE (left) == 1 &&
5601 AOP_SIZE (right) == 1)
5603 genMultOneByte (left, right, result, ic);
5607 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5608 /* use the ds390 ARITHMETIC accel UNIT */
5609 genMultTwoByte (left, right, result, ic);
5612 /* should have been converted to function call */
5616 freeAsmop (result, NULL, ic, TRUE);
5617 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5618 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5621 /*-----------------------------------------------------------------*/
5622 /* genDivbits :- division of bits */
5623 /*-----------------------------------------------------------------*/
5625 genDivbits (operand * left,
5633 D(emitcode ("; genDivbits",""));
5637 /* the result must be bit */
5638 LOAD_AB_FOR_DIV (left, right, l);
5639 emitcode ("div", "ab");
5640 emitcode ("rrc", "a");
5641 aopOp(result, ic, TRUE, FALSE);
5645 aopPut (result, "c", 0);
5648 /*-----------------------------------------------------------------*/
5649 /* genDivOneByte : 8 bit division */
5650 /*-----------------------------------------------------------------*/
5652 genDivOneByte (operand * left,
5657 bool lUnsigned, rUnsigned, pushedB;
5658 bool runtimeSign, compiletimeSign;
5663 D(emitcode ("; genDivOneByte",""));
5666 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5667 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5671 /* signed or unsigned */
5672 if (lUnsigned && rUnsigned)
5674 /* unsigned is easy */
5675 LOAD_AB_FOR_DIV (left, right, l);
5676 emitcode ("div", "ab");
5679 aopOp (result, ic, TRUE, FALSE);
5680 aopPut (result, "a", 0);
5683 size = AOP_SIZE (result) - 1;
5686 aopPut (result, zero, offset++);
5692 /* signed is a little bit more difficult */
5694 /* now sign adjust for both left & right */
5696 /* let's see what's needed: */
5697 /* apply negative sign during runtime */
5698 runtimeSign = FALSE;
5699 /* negative sign from literals */
5700 compiletimeSign = FALSE;
5704 if (AOP_TYPE(left) == AOP_LIT)
5706 /* signed literal */
5707 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5709 compiletimeSign = TRUE;
5712 /* signed but not literal */
5718 if (AOP_TYPE(right) == AOP_LIT)
5720 /* signed literal */
5721 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5723 compiletimeSign ^= TRUE;
5726 /* signed but not literal */
5730 /* initialize F0, which stores the runtime sign */
5733 if (compiletimeSign)
5734 emitcode ("setb", "F0"); /* set sign flag */
5736 emitcode ("clr", "F0"); /* reset sign flag */
5739 /* save the signs of the operands */
5740 if (AOP_TYPE(right) == AOP_LIT)
5742 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5744 if (!rUnsigned && val < 0)
5745 emitcode ("mov", "b,#0x%02x", -val);
5747 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5749 else /* ! literal */
5752 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
5755 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
5756 lbl = newiTempLabel (NULL);
5757 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5758 emitcode ("cpl", "F0"); /* complement sign flag */
5759 emitcode ("cpl", "a"); /* 2's complement */
5760 emitcode ("inc", "a");
5762 emitcode ("mov", "b,a");
5766 if (AOP_TYPE(left) == AOP_LIT)
5768 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5770 if (!lUnsigned && val < 0)
5771 emitcode ("mov", "a,#0x%02x", -val);
5773 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5775 else /* ! literal */
5777 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
5781 lbl = newiTempLabel (NULL);
5782 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5783 emitcode ("cpl", "F0"); /* complement sign flag */
5784 emitcode ("cpl", "a"); /* 2's complement */
5785 emitcode ("inc", "a");
5790 /* now the division */
5791 emitcode ("nop", "; workaround for DS80C390 div bug.");
5792 emitcode ("div", "ab");
5794 if (runtimeSign || compiletimeSign)
5796 lbl = newiTempLabel (NULL);
5798 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5799 emitcode ("cpl", "a"); /* lsb 2's complement */
5800 emitcode ("inc", "a");
5804 aopOp (result, ic, TRUE, FALSE);
5805 size = AOP_SIZE (result) - 1;
5809 /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
5810 then the result will be in b, a */
5811 emitcode ("mov", "b,a"); /* 1 */
5812 /* msb is 0x00 or 0xff depending on the sign */
5815 emitcode ("mov", "c,F0");
5816 emitcode ("subb", "a,acc");
5817 emitcode ("xch", "a,b"); /* 2 */
5819 aopPut (result, "b", offset++); /* write msb's */
5821 else /* compiletimeSign */
5823 aopPut (result, "#0xff", offset++); /* write msb's */
5825 aopPut (result, "a", 0); /* 3: write lsb */
5830 aopOp(result, ic, TRUE, FALSE);
5831 size = AOP_SIZE (result) - 1;
5833 aopPut (result, "a", 0);
5835 aopPut (result, zero, offset++);
5841 /*-----------------------------------------------------------------*/
5842 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
5843 /*-----------------------------------------------------------------*/
5844 static void genDivTwoByte (operand *left, operand *right,
5845 operand *result, iCode *ic)
5847 sym_link *retype = getSpec(operandType(right));
5848 sym_link *letype = getSpec(operandType(left));
5849 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5852 /* save EA bit in F1 */
5853 lbl = newiTempLabel(NULL);
5854 emitcode ("setb","F1");
5855 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5856 emitcode ("clr","F1");
5859 /* load up MA with left */
5861 emitcode("clr","F0");
5862 lbl = newiTempLabel(NULL);
5863 emitcode ("mov","b,%s",aopGet(left,0,FALSE,FALSE,NULL));
5864 emitcode ("mov","a,%s",aopGet(left,1,FALSE,FALSE,NULL));
5865 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5866 emitcode ("xch", "a,b");
5867 emitcode ("cpl","a");
5868 emitcode ("add", "a,#1");
5869 emitcode ("xch", "a,b");
5870 emitcode ("cpl", "a"); // msb
5871 emitcode ("addc","a,#0");
5872 emitcode ("setb","F0");
5874 emitcode ("mov","ma,b");
5875 emitcode ("mov","ma,a");
5877 emitcode ("mov","ma,%s",aopGet(left,0,FALSE,FALSE,NULL));
5878 emitcode ("mov","ma,%s",aopGet(left,1,FALSE,FALSE,NULL));
5881 /* load up MB with right */
5883 if (AOP_TYPE(right) == AOP_LIT) {
5884 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5886 lbl = newiTempLabel(NULL);
5887 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5888 emitcode("setb","F0");
5892 emitcode ("mov","mb,#!constbyte",val & 0xff);
5893 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5895 lbl = newiTempLabel(NULL);
5896 emitcode ("mov","b,%s",aopGet(right,0,FALSE,FALSE,NULL));
5897 emitcode ("mov","a,%s",aopGet(right,1,FALSE,FALSE,NULL));
5898 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5899 emitcode ("xch", "a,b");
5900 emitcode ("cpl","a");
5901 emitcode ("add", "a,#1");
5902 emitcode ("xch", "a,b");
5903 emitcode ("cpl", "a"); // msb
5904 emitcode ("addc", "a,#0");
5905 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5906 emitcode ("setb","F0");
5908 emitcode ("mov","mb,b");
5909 emitcode ("mov","mb,a");
5912 emitcode ("mov","mb,%s",aopGet(right,0,FALSE,FALSE,NULL));
5913 emitcode ("mov","mb,%s",aopGet(right,1,FALSE,FALSE,NULL));
5916 /* wait for multiplication to finish */
5917 lbl = newiTempLabel(NULL);
5919 emitcode("mov","a,mcnt1");
5920 emitcode("anl","a,#!constbyte",0x80);
5921 emitcode("jnz","!tlabel",lbl->key+100);
5923 freeAsmop (left, NULL, ic, TRUE);
5924 freeAsmop (right, NULL, ic,TRUE);
5925 aopOp(result, ic, TRUE, FALSE);
5927 /* if unsigned then simple */
5929 aopPut(result,"ma",1);
5930 aopPut(result,"ma",0);
5932 emitcode("push","ma");
5934 /* negate result if needed */
5935 lbl = newiTempLabel(NULL);
5936 emitcode("jnb","F0,!tlabel",lbl->key+100);
5937 emitcode("cpl","a");
5938 emitcode("add","a,#1");
5940 aopPut(result,"a",0);
5941 emitcode("pop","acc");
5942 lbl = newiTempLabel(NULL);
5943 emitcode("jnb","F0,!tlabel",lbl->key+100);
5944 emitcode("cpl","a");
5945 emitcode("addc","a,#0");
5947 aopPut(result,"a",1);
5949 freeAsmop (result, NULL, ic, TRUE);
5950 /* restore EA bit in F1 */
5951 lbl = newiTempLabel(NULL);
5952 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5953 emitcode ("setb","EA");
5958 /*-----------------------------------------------------------------*/
5959 /* genDiv - generates code for division */
5960 /*-----------------------------------------------------------------*/
5964 operand *left = IC_LEFT (ic);
5965 operand *right = IC_RIGHT (ic);
5966 operand *result = IC_RESULT (ic);
5968 D (emitcode (";", "genDiv"));
5970 /* assign the amsops */
5973 /* special cases first */
5975 if (AOP_TYPE (left) == AOP_CRY &&
5976 AOP_TYPE (right) == AOP_CRY)
5978 genDivbits (left, right, result, ic);
5982 /* if both are of size == 1 */
5983 if (AOP_SIZE (left) == 1 &&
5984 AOP_SIZE (right) == 1)
5986 genDivOneByte (left, right, result, ic);
5990 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5991 /* use the ds390 ARITHMETIC accel UNIT */
5992 genDivTwoByte (left, right, result, ic);
5995 /* should have been converted to function call */
5998 freeAsmop (result, NULL, ic, TRUE);
5999 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6000 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6003 /*-----------------------------------------------------------------*/
6004 /* genModbits :- modulus of bits */
6005 /*-----------------------------------------------------------------*/
6007 genModbits (operand * left,
6015 D (emitcode (";", "genModbits"));
6019 /* the result must be bit */
6020 LOAD_AB_FOR_DIV (left, right, l);
6021 emitcode ("div", "ab");
6022 emitcode ("mov", "a,b");
6023 emitcode ("rrc", "a");
6024 aopOp(result, ic, TRUE, FALSE);
6028 aopPut (result, "c", 0);
6031 /*-----------------------------------------------------------------*/
6032 /* genModOneByte : 8 bit modulus */
6033 /*-----------------------------------------------------------------*/
6035 genModOneByte (operand * left,
6040 bool lUnsigned, rUnsigned, pushedB;
6041 bool runtimeSign, compiletimeSign;
6046 D (emitcode (";", "genModOneByte"));
6049 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
6050 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
6054 /* signed or unsigned */
6055 if (lUnsigned && rUnsigned)
6057 /* unsigned is easy */
6058 LOAD_AB_FOR_DIV (left, right, l);
6059 emitcode ("div", "ab");
6060 aopOp (result, ic, TRUE, FALSE);
6061 aopPut (result, "b", 0);
6063 for (size = AOP_SIZE (result) - 1; size--;)
6064 aopPut (result, zero, offset++);
6070 /* signed is a little bit more difficult */
6072 /* now sign adjust for both left & right */
6074 /* modulus: sign of the right operand has no influence on the result! */
6075 if (AOP_TYPE(right) == AOP_LIT)
6077 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
6079 if (!rUnsigned && val < 0)
6080 emitcode ("mov", "b,#0x%02x", -val);
6082 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
6084 else /* not literal */
6087 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
6090 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
6091 lbl = newiTempLabel (NULL);
6092 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
6093 emitcode ("cpl", "a"); /* 2's complement */
6094 emitcode ("inc", "a");
6096 emitcode ("mov", "b,a");
6100 /* let's see what's needed: */
6101 /* apply negative sign during runtime */
6102 runtimeSign = FALSE;
6103 /* negative sign from literals */
6104 compiletimeSign = FALSE;
6106 /* sign adjust left side */
6107 if (AOP_TYPE(left) == AOP_LIT)
6109 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
6111 if (!lUnsigned && val < 0)
6113 compiletimeSign = TRUE; /* set sign flag */
6114 emitcode ("mov", "a,#0x%02x", -val);
6117 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
6119 else /* ! literal */
6121 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
6126 emitcode ("clr", "F0"); /* clear sign flag */
6128 lbl = newiTempLabel (NULL);
6129 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
6130 emitcode ("setb", "F0"); /* set sign flag */
6131 emitcode ("cpl", "a"); /* 2's complement */
6132 emitcode ("inc", "a");
6137 /* now the modulus */
6138 emitcode ("nop", "; workaround for DS80C390 div bug.");
6139 emitcode ("div", "ab");
6141 if (runtimeSign || compiletimeSign)
6143 emitcode ("mov", "a,b");
6144 lbl = newiTempLabel (NULL);
6146 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
6147 emitcode ("cpl", "a"); /* lsb 2's complement */
6148 emitcode ("inc", "a");
6152 aopOp (result, ic, TRUE, FALSE);
6153 size = AOP_SIZE (result) - 1;
6157 /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
6158 then the result will be in b, a */
6159 emitcode ("mov", "b,a"); /* 1 */
6160 /* msb is 0x00 or 0xff depending on the sign */
6163 emitcode ("mov", "c,F0");
6164 emitcode ("subb", "a,acc");
6165 emitcode ("xch", "a,b"); /* 2 */
6167 aopPut (result, "b", offset++); /* write msb's */
6169 else /* compiletimeSign */
6171 aopPut (result, "#0xff", offset++); /* write msb's */
6173 aopPut (result, "a", 0); /* 3: write lsb */
6178 aopOp(result, ic, TRUE, FALSE);
6179 size = AOP_SIZE (result) - 1;
6181 aopPut (result, "b", 0);
6183 aopPut (result, zero, offset++);
6189 /*-----------------------------------------------------------------*/
6190 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
6191 /*-----------------------------------------------------------------*/
6192 static void genModTwoByte (operand *left, operand *right,
6193 operand *result, iCode *ic)
6195 sym_link *retype = getSpec(operandType(right));
6196 sym_link *letype = getSpec(operandType(left));
6197 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
6200 /* load up MA with left */
6201 /* save EA bit in F1 */
6202 lbl = newiTempLabel(NULL);
6203 emitcode ("setb","F1");
6204 emitcode ("jbc","EA,!tlabel",lbl->key+100);
6205 emitcode ("clr","F1");
6209 lbl = newiTempLabel(NULL);
6210 emitcode ("mov","b,%s",aopGet(left,0,FALSE,FALSE,NULL));
6211 emitcode ("mov","a,%s",aopGet(left,1,FALSE,FALSE,NULL));
6212 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
6213 emitcode ("xch", "a,b");
6214 emitcode ("cpl","a");
6215 emitcode ("add", "a,#1");
6216 emitcode ("xch", "a,b");
6217 emitcode ("cpl", "a"); // msb
6218 emitcode ("addc","a,#0");
6220 emitcode ("mov","ma,b");
6221 emitcode ("mov","ma,a");
6223 emitcode ("mov","ma,%s",aopGet(left,0,FALSE,FALSE,NULL));
6224 emitcode ("mov","ma,%s",aopGet(left,1,FALSE,FALSE,NULL));
6227 /* load up MB with right */
6229 if (AOP_TYPE(right) == AOP_LIT) {
6230 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
6234 emitcode ("mov","mb,#!constbyte",val & 0xff);
6235 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
6237 lbl = newiTempLabel(NULL);
6238 emitcode ("mov","b,%s",aopGet(right,0,FALSE,FALSE,NULL));
6239 emitcode ("mov","a,%s",aopGet(right,1,FALSE,FALSE,NULL));
6240 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
6241 emitcode ("xch", "a,b");
6242 emitcode ("cpl","a");
6243 emitcode ("add", "a,#1");
6244 emitcode ("xch", "a,b");
6245 emitcode ("cpl", "a"); // msb
6246 emitcode ("addc", "a,#0");
6248 emitcode ("mov","mb,b");
6249 emitcode ("mov","mb,a");
6252 emitcode ("mov","mb,%s",aopGet(right,0,FALSE,FALSE,NULL));
6253 emitcode ("mov","mb,%s",aopGet(right,1,FALSE,FALSE,NULL));
6256 /* wait for multiplication to finish */
6257 lbl = newiTempLabel(NULL);
6259 emitcode("mov","a,mcnt1");
6260 emitcode("anl","a,#!constbyte",0x80);
6261 emitcode("jnz","!tlabel",lbl->key+100);
6263 freeAsmop (left, NULL, ic, TRUE);
6264 freeAsmop (right, NULL, ic,TRUE);
6265 aopOp(result, ic, TRUE, FALSE);
6267 aopPut(result,"mb",1);
6268 aopPut(result,"mb",0);
6269 freeAsmop (result, NULL, ic, TRUE);
6271 /* restore EA bit in F1 */
6272 lbl = newiTempLabel(NULL);
6273 emitcode ("jnb","F1,!tlabel",lbl->key+100);
6274 emitcode ("setb","EA");
6278 /*-----------------------------------------------------------------*/
6279 /* genMod - generates code for division */
6280 /*-----------------------------------------------------------------*/
6284 operand *left = IC_LEFT (ic);
6285 operand *right = IC_RIGHT (ic);
6286 operand *result = IC_RESULT (ic);
6288 D (emitcode (";", "genMod"));
6290 /* assign the asmops */
6293 /* special cases first */
6295 if (AOP_TYPE (left) == AOP_CRY &&
6296 AOP_TYPE (right) == AOP_CRY)
6298 genModbits (left, right, result, ic);
6302 /* if both are of size == 1 */
6303 if (AOP_SIZE (left) == 1 &&
6304 AOP_SIZE (right) == 1)
6306 genModOneByte (left, right, result, ic);
6310 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
6311 /* use the ds390 ARITHMETIC accel UNIT */
6312 genModTwoByte (left, right, result, ic);
6316 /* should have been converted to function call */
6320 freeAsmop (result, NULL, ic, TRUE);
6321 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6322 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6325 /*-----------------------------------------------------------------*/
6326 /* genIfxJump :- will create a jump depending on the ifx */
6327 /*-----------------------------------------------------------------*/
6329 genIfxJump (iCode * ic, char *jval)
6332 symbol *tlbl = newiTempLabel (NULL);
6335 D (emitcode (";", "genIfxJump"));
6337 /* if true label then we jump if condition
6341 jlbl = IC_TRUE (ic);
6342 inst = ((strcmp (jval, "a") == 0 ? "jz" :
6343 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
6347 /* false label is present */
6348 jlbl = IC_FALSE (ic);
6349 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
6350 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
6352 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
6353 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
6355 emitcode (inst, "!tlabel", tlbl->key + 100);
6356 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
6359 /* mark the icode as generated */
6363 /*-----------------------------------------------------------------*/
6364 /* genCmp :- greater or less than comparison */
6365 /*-----------------------------------------------------------------*/
6367 genCmp (operand * left, operand * right,
6368 iCode * ic, iCode * ifx, int sign)
6370 int size, offset = 0;
6371 unsigned long lit = 0L;
6374 D (emitcode (";", "genCmp"));
6376 result = IC_RESULT (ic);
6378 /* if left & right are bit variables */
6379 if (AOP_TYPE (left) == AOP_CRY &&
6380 AOP_TYPE (right) == AOP_CRY)
6382 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6383 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6387 /* subtract right from left if at the
6388 end the carry flag is set then we know that
6389 left is greater than right */
6390 size = max (AOP_SIZE (left), AOP_SIZE (right));
6392 /* if unsigned char cmp with lit, do cjne left,#right,zz */
6393 if ((size == 1) && !sign &&
6394 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
6396 symbol *lbl = newiTempLabel (NULL);
6397 emitcode ("cjne", "%s,%s,!tlabel",
6398 aopGet (left, offset, FALSE, FALSE, NULL),
6399 aopGet (right, offset, FALSE, FALSE, NULL),
6405 if (AOP_TYPE (right) == AOP_LIT)
6407 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6408 /* optimize if(x < 0) or if(x >= 0) */
6417 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
6419 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6420 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6422 aopOp (result, ic, FALSE, FALSE);
6424 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
6426 freeAsmop (result, NULL, ic, TRUE);
6427 genIfxJump (ifx, "acc.7");
6432 emitcode ("rlc", "a");
6434 goto release_freedLR;
6442 // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
6443 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
6444 // emitcode (";", "genCmp #2");
6445 if (sign && (size == 0))
6447 // emitcode (";", "genCmp #3");
6448 emitcode ("xrl", "a,#!constbyte",0x80);
6449 if (AOP_TYPE (right) == AOP_LIT)
6451 unsigned long lit = (unsigned long)
6452 floatFromVal (AOP (right)->aopu.aop_lit);
6453 // emitcode (";", "genCmp #3.1");
6454 emitcode ("subb", "a,#!constbyte",
6455 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
6459 // emitcode (";", "genCmp #3.2");
6461 MOVB (aopGet (right, offset++, FALSE, FALSE, "b"));
6462 saveAccWarn = DEFAULT_ACC_WARNING;
6463 emitcode ("xrl", "b,#!constbyte",0x80);
6464 emitcode ("subb", "a,b");
6471 // emitcode (";", "genCmp #4");
6473 s = aopGet (right, offset++, FALSE, FALSE, "b");
6474 saveAccWarn = DEFAULT_ACC_WARNING;
6476 emitcode ("subb", "a,%s", s);
6483 /* Don't need the left & right operands any more; do need the result. */
6484 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6485 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6487 aopOp (result, ic, FALSE, FALSE);
6491 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6497 /* if the result is used in the next
6498 ifx conditional branch then generate
6499 code a little differently */
6502 genIfxJump (ifx, "c");
6508 /* leave the result in acc */
6510 freeAsmop (result, NULL, ic, TRUE);
6513 /*-----------------------------------------------------------------*/
6514 /* genCmpGt :- greater than comparison */
6515 /*-----------------------------------------------------------------*/
6517 genCmpGt (iCode * ic, iCode * ifx)
6519 operand *left, *right;
6520 sym_link *letype, *retype;
6523 D (emitcode (";", "genCmpGt"));
6525 left = IC_LEFT (ic);
6526 right = IC_RIGHT (ic);
6528 letype = getSpec (operandType (left));
6529 retype = getSpec (operandType (right));
6530 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6532 /* assign the left & right amsops */
6535 genCmp (right, left, ic, ifx, sign);
6538 /*-----------------------------------------------------------------*/
6539 /* genCmpLt - less than comparisons */
6540 /*-----------------------------------------------------------------*/
6542 genCmpLt (iCode * ic, iCode * ifx)
6544 operand *left, *right;
6545 sym_link *letype, *retype;
6548 D (emitcode (";", "genCmpLt"));
6550 left = IC_LEFT (ic);
6551 right = IC_RIGHT (ic);
6553 letype = getSpec (operandType (left));
6554 retype = getSpec (operandType (right));
6555 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6557 /* assign the left & right amsops */
6560 genCmp (left, right, ic, ifx, sign);
6563 /*-----------------------------------------------------------------*/
6564 /* gencjneshort - compare and jump if not equal */
6565 /*-----------------------------------------------------------------*/
6567 gencjneshort (operand * left, operand * right, symbol * lbl)
6569 int size = max (AOP_SIZE (left), AOP_SIZE (right));
6571 unsigned long lit = 0L;
6573 D (emitcode (";", "gencjneshort"));
6575 /* if the left side is a literal or
6576 if the right is in a pointer register and left
6578 if ((AOP_TYPE (left) == AOP_LIT) ||
6579 (AOP_TYPE (left) == AOP_IMMD) ||
6580 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6587 if (AOP_TYPE (right) == AOP_LIT)
6588 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6590 if (opIsGptr (left) || opIsGptr (right))
6592 /* We are comparing a generic pointer to something.
6593 * Exclude the generic type byte from the comparison.
6596 D (emitcode (";", "cjneshort: generic ptr special case."););
6600 /* if the right side is a literal then anything goes */
6601 if (AOP_TYPE (right) == AOP_LIT &&
6602 AOP_TYPE (left) != AOP_DIR)
6606 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
6607 emitcode ("cjne", "a,%s,!tlabel",
6608 aopGet (right, offset, FALSE, FALSE, NULL),
6614 /* if the right side is in a register or in direct space or
6615 if the left is a pointer register & right is not */
6616 else if (AOP_TYPE (right) == AOP_REG ||
6617 AOP_TYPE (right) == AOP_DIR ||
6618 AOP_TYPE (right) == AOP_LIT ||
6619 AOP_TYPE (right) == AOP_IMMD ||
6620 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6621 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6625 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
6626 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6627 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6628 emitcode ("jnz", "!tlabel", lbl->key + 100);
6630 emitcode ("cjne", "a,%s,!tlabel",
6631 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG),
6638 /* right is a pointer reg need both a & b */
6641 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
6642 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
6643 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
6649 /*-----------------------------------------------------------------*/
6650 /* gencjne - compare and jump if not equal */
6651 /*-----------------------------------------------------------------*/
6653 gencjne (operand * left, operand * right, symbol * lbl)
6655 symbol *tlbl = newiTempLabel (NULL);
6657 D (emitcode (";", "gencjne"));
6659 gencjneshort (left, right, lbl);
6661 emitcode ("mov", "a,%s", one);
6662 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
6664 emitcode ("clr", "a");
6668 /*-----------------------------------------------------------------*/
6669 /* genCmpEq - generates code for equal to */
6670 /*-----------------------------------------------------------------*/
6672 genCmpEq (iCode * ic, iCode * ifx)
6674 operand *left, *right, *result;
6676 D (emitcode (";", "genCmpEq"));
6679 AOP_SET_LOCALS (ic);
6681 /* if literal, literal on the right or
6682 if the right is in a pointer register and left
6684 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6685 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6687 operand *t = IC_RIGHT (ic);
6688 IC_RIGHT (ic) = IC_LEFT (ic);
6692 if (ifx && /* !AOP_SIZE(result) */
6693 OP_SYMBOL (result) &&
6694 OP_SYMBOL (result)->regType == REG_CND)
6697 /* if they are both bit variables */
6698 if (AOP_TYPE (left) == AOP_CRY &&
6699 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6701 if (AOP_TYPE (right) == AOP_LIT)
6703 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6706 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6707 emitcode ("cpl", "c");
6711 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6715 emitcode ("clr", "c");
6717 /* AOP_TYPE(right) == AOP_CRY */
6721 symbol *lbl = newiTempLabel (NULL);
6722 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6723 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6724 emitcode ("cpl", "c");
6727 /* if true label then we jump if condition
6729 tlbl = newiTempLabel (NULL);
6732 emitcode ("jnc", "!tlabel", tlbl->key + 100);
6733 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6737 emitcode ("jc", "!tlabel", tlbl->key + 100);
6738 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6744 tlbl = newiTempLabel (NULL);
6745 gencjneshort (left, right, tlbl);
6748 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6753 symbol *lbl = newiTempLabel (NULL);
6754 emitcode ("sjmp", "!tlabel", lbl->key + 100);
6756 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6760 /* mark the icode as generated */
6763 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6764 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6768 /* if they are both bit variables */
6769 if (AOP_TYPE (left) == AOP_CRY &&
6770 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6772 if (AOP_TYPE (right) == AOP_LIT)
6774 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6777 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6778 emitcode ("cpl", "c");
6782 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6786 emitcode ("clr", "c");
6788 /* AOP_TYPE(right) == AOP_CRY */
6792 symbol *lbl = newiTempLabel (NULL);
6793 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6794 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6795 emitcode ("cpl", "c");
6799 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6800 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6802 aopOp (result, ic, TRUE, FALSE);
6805 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6812 genIfxJump (ifx, "c");
6815 /* if the result is used in an arithmetic operation
6816 then put the result in place */
6821 gencjne (left, right, newiTempLabel (NULL));
6823 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6824 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6826 aopOp (result, ic, TRUE, FALSE);
6828 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6830 aopPut (result, "a", 0);
6835 genIfxJump (ifx, "a");
6838 /* if the result is used in an arithmetic operation
6839 then put the result in place */
6840 if (AOP_TYPE (result) != AOP_CRY)
6842 /* leave the result in acc */
6846 freeAsmop (result, NULL, ic, TRUE);
6849 /*-----------------------------------------------------------------*/
6850 /* ifxForOp - returns the icode containing the ifx for operand */
6851 /*-----------------------------------------------------------------*/
6853 ifxForOp (operand * op, iCode * ic)
6855 /* if true symbol then needs to be assigned */
6856 if (IS_TRUE_SYMOP (op))
6859 /* if this has register type condition and
6860 the next instruction is ifx with the same operand
6861 and live to of the operand is upto the ifx only then */
6863 ic->next->op == IFX &&
6864 IC_COND (ic->next)->key == op->key &&
6865 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6871 /*-----------------------------------------------------------------*/
6872 /* hasInc - operand is incremented before any other use */
6873 /*-----------------------------------------------------------------*/
6875 hasInc (operand *op, iCode *ic, int osize)
6877 sym_link *type = operandType(op);
6878 sym_link *retype = getSpec (type);
6879 iCode *lic = ic->next;
6882 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6883 if (!IS_SYMOP(op)) return NULL;
6885 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6886 if (IS_AGGREGATE(type->next)) return NULL;
6887 if (osize != (isize = getSize(type->next))) return NULL;
6890 /* if operand of the form op = op + <sizeof *op> */
6891 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6892 isOperandEqual(IC_RESULT(lic),op) &&
6893 isOperandLiteral(IC_RIGHT(lic)) &&
6894 operandLitValue(IC_RIGHT(lic)) == isize) {
6897 /* if the operand used or deffed */
6898 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6901 /* if GOTO or IFX */
6902 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6908 /*-----------------------------------------------------------------*/
6909 /* genAndOp - for && operation */
6910 /*-----------------------------------------------------------------*/
6912 genAndOp (iCode * ic)
6914 operand *left, *right, *result;
6917 D (emitcode (";", "genAndOp"));
6919 /* note here that && operations that are in an
6920 if statement are taken away by backPatchLabels
6921 only those used in arthmetic operations remain */
6923 AOP_SET_LOCALS (ic);
6925 /* if both are bit variables */
6926 if (AOP_TYPE (left) == AOP_CRY &&
6927 AOP_TYPE (right) == AOP_CRY)
6929 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6930 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6931 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6932 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6934 aopOp (result,ic,FALSE, FALSE);
6939 tlbl = newiTempLabel (NULL);
6941 emitcode ("jz", "!tlabel", tlbl->key + 100);
6944 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6945 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6947 aopOp (result,ic,FALSE, FALSE);
6951 freeAsmop (result, NULL, ic, TRUE);
6955 /*-----------------------------------------------------------------*/
6956 /* genOrOp - for || operation */
6957 /*-----------------------------------------------------------------*/
6959 genOrOp (iCode * ic)
6961 operand *left, *right, *result;
6964 D (emitcode (";", "genOrOp"));
6966 /* note here that || operations that are in an
6967 if statement are taken away by backPatchLabels
6968 only those used in arthmetic operations remain */
6970 AOP_SET_LOCALS (ic);
6972 /* if both are bit variables */
6973 if (AOP_TYPE (left) == AOP_CRY &&
6974 AOP_TYPE (right) == AOP_CRY)
6976 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6977 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6978 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6979 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6981 aopOp (result,ic,FALSE, FALSE);
6987 tlbl = newiTempLabel (NULL);
6989 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6992 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6993 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6995 aopOp (result,ic,FALSE, FALSE);
7000 freeAsmop (result, NULL, ic, TRUE);
7003 /*-----------------------------------------------------------------*/
7004 /* isLiteralBit - test if lit == 2^n */
7005 /*-----------------------------------------------------------------*/
7007 isLiteralBit (unsigned long lit)
7009 unsigned long pw[32] =
7010 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
7011 0x100L, 0x200L, 0x400L, 0x800L,
7012 0x1000L, 0x2000L, 0x4000L, 0x8000L,
7013 0x10000L, 0x20000L, 0x40000L, 0x80000L,
7014 0x100000L, 0x200000L, 0x400000L, 0x800000L,
7015 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
7016 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
7019 for (idx = 0; idx < 32; idx++)
7025 /*-----------------------------------------------------------------*/
7026 /* continueIfTrue - */
7027 /*-----------------------------------------------------------------*/
7029 continueIfTrue (iCode * ic)
7032 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
7036 /*-----------------------------------------------------------------*/
7038 /*-----------------------------------------------------------------*/
7040 jumpIfTrue (iCode * ic)
7043 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
7047 /*-----------------------------------------------------------------*/
7048 /* jmpTrueOrFalse - */
7049 /*-----------------------------------------------------------------*/
7051 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
7053 // ugly but optimized by peephole
7056 symbol *nlbl = newiTempLabel (NULL);
7057 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
7059 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
7064 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
7070 // Generate code to perform a bit-wise logic operation
7071 // on two operands in far space (assumed to already have been
7072 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
7073 // in far space. This requires pushing the result on the stack
7074 // then popping it into the result.
7076 genFarFarLogicOp(iCode *ic, char *logicOp)
7078 int size, resultSize, compSize;
7082 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
7083 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
7084 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
7086 _startLazyDPSEvaluation();
7087 for (size = compSize; (size--); offset++)
7089 MOVA (aopGet (IC_LEFT(ic), offset, FALSE, FALSE, NULL));
7090 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
7091 MOVA (aopGet (IC_RIGHT(ic), offset, FALSE, FALSE, NULL));
7093 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
7094 emitcode ("push", "acc");
7096 _endLazyDPSEvaluation();
7098 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7099 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7100 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
7102 resultSize = AOP_SIZE(IC_RESULT(ic));
7104 ADJUST_PUSHED_RESULT(compSize, resultSize);
7106 _startLazyDPSEvaluation();
7109 emitcode ("pop", "acc");
7110 aopPut (IC_RESULT (ic), "a", compSize);
7112 _endLazyDPSEvaluation();
7113 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
7117 /*-----------------------------------------------------------------*/
7118 /* genAnd - code for and */
7119 /*-----------------------------------------------------------------*/
7121 genAnd (iCode * ic, iCode * ifx)
7123 operand *left, *right, *result;
7124 int size, offset = 0;
7125 unsigned long lit = 0L;
7130 D (emitcode (";", "genAnd"));
7132 AOP_OP_3_NOFATAL (ic, pushResult);
7133 AOP_SET_LOCALS (ic);
7137 genFarFarLogicOp(ic, "anl");
7142 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7144 AOP_TYPE (left), AOP_TYPE (right));
7145 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7147 AOP_SIZE (left), AOP_SIZE (right));
7150 /* if left is a literal & right is not then exchange them */
7151 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7152 #ifdef LOGIC_OPS_BROKEN
7153 || AOP_NEEDSACC (left)
7157 operand *tmp = right;
7162 /* if result = right then exchange left and right */
7163 if (sameRegs (AOP (result), AOP (right)))
7165 operand *tmp = right;
7170 /* if right is bit then exchange them */
7171 if (AOP_TYPE (right) == AOP_CRY &&
7172 AOP_TYPE (left) != AOP_CRY)
7174 operand *tmp = right;
7178 if (AOP_TYPE (right) == AOP_LIT)
7179 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7181 size = AOP_SIZE (result);
7184 // result = bit & yy;
7185 if (AOP_TYPE (left) == AOP_CRY)
7187 // c = bit & literal;
7188 if (AOP_TYPE (right) == AOP_LIT)
7192 if (size && sameRegs (AOP (result), AOP (left)))
7195 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7200 if (size && (AOP_TYPE (result) == AOP_CRY))
7202 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
7205 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7210 emitcode ("clr", "c");
7215 if (AOP_TYPE (right) == AOP_CRY)
7218 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7219 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
7224 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
7226 emitcode ("rrc", "a");
7227 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
7235 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7236 genIfxJump (ifx, "c");
7240 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7241 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7242 if ((AOP_TYPE (right) == AOP_LIT) &&
7243 (AOP_TYPE (result) == AOP_CRY) &&
7244 (AOP_TYPE (left) != AOP_CRY))
7246 int posbit = isLiteralBit (lit);
7251 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE, NULL));
7255 switch (posbit & 0x07)
7257 case 0: emitcode ("rrc", "a");
7259 case 7: emitcode ("rlc", "a");
7261 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
7270 SNPRINTF (buffer, sizeof(buffer),
7271 "acc.%d", posbit & 0x07);
7272 genIfxJump (ifx, buffer);
7276 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
7283 symbol *tlbl = newiTempLabel (NULL);
7284 int sizel = AOP_SIZE (left);
7286 emitcode ("setb", "c");
7289 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
7291 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7293 if ((posbit = isLiteralBit (bytelit)) != 0)
7294 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
7297 if (bytelit != 0x0FFL)
7298 emitcode ("anl", "a,%s",
7299 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG));
7300 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7305 // bit = left & literal
7308 emitcode ("clr", "c");
7311 // if(left & literal)
7315 jmpTrueOrFalse (ifx, tlbl);
7325 /* if left is same as result */
7326 if (sameRegs (AOP (result), AOP (left)))
7328 for (; size--; offset++)
7330 if (AOP_TYPE (right) == AOP_LIT)
7332 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7333 if (bytelit == 0x0FF)
7335 /* dummy read of volatile operand */
7336 if (isOperandVolatile (left, FALSE))
7337 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7341 else if (bytelit == 0)
7343 aopPut (result, zero, offset);
7345 else if (IS_AOP_PREG (result))
7347 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7348 emitcode ("anl", "a,%s",
7349 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG));
7350 aopPut (result, "a", offset);
7353 emitcode ("anl", "%s,%s",
7354 aopGet (left, offset, FALSE, TRUE, NULL),
7355 aopGet (right, offset, FALSE, FALSE, NULL));
7359 if (AOP_TYPE (left) == AOP_ACC)
7362 emitcode("mov", "a,b");
7363 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7365 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7367 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
7368 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7369 emitcode ("anl", "a,b");
7370 aopPut (result, "a", offset);
7372 else if (aopGetUsesAcc (left, offset))
7374 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7375 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7376 aopPut (result, "a", offset);
7380 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7381 if (IS_AOP_PREG (result))
7383 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7384 aopPut (result, "a", offset);
7387 emitcode ("anl", "%s,a", aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7394 // left & result in different registers
7395 if (AOP_TYPE (result) == AOP_CRY)
7398 // if(size), result in bit
7399 // if(!size && ifx), conditional oper: if(left & right)
7400 symbol *tlbl = newiTempLabel (NULL);
7401 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
7403 emitcode ("setb", "c");
7406 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7407 && AOP_TYPE(left)==AOP_ACC)
7410 emitcode("mov", "a,b");
7411 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, NULL));
7413 else if (AOP_TYPE(left)==AOP_ACC)
7417 bool pushedB = pushB ();
7418 emitcode("mov", "b,a");
7419 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7420 emitcode("anl", "a,b");
7425 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7426 emitcode("anl", "a,b");
7429 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7431 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE, NULL));
7432 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7433 emitcode ("anl", "a,b");
7435 else if (aopGetUsesAcc (left, offset))
7437 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7438 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7442 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7443 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE, DP2_RESULT_REG));
7446 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7456 jmpTrueOrFalse (ifx, tlbl);
7462 for (; (size--); offset++)
7465 // result = left & right
7466 if (AOP_TYPE (right) == AOP_LIT)
7468 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7469 if (bytelit == 0x0FF)
7472 aopGet (left, offset, FALSE, FALSE, NULL),
7476 else if (bytelit == 0)
7478 /* dummy read of volatile operand */
7479 if (isOperandVolatile (left, FALSE))
7480 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7481 aopPut (result, zero, offset);
7484 else if (AOP_TYPE (left) == AOP_ACC)
7488 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, NULL));
7489 aopPut (result, "a", offset);
7494 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE, NULL));
7495 aopPut (result, "b", offset);
7500 // faster than result <- left, anl result,right
7501 // and better if result is SFR
7502 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7503 && AOP_TYPE(left)==AOP_ACC)
7506 emitcode("mov", "a,b");
7507 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, NULL));
7509 else if (AOP_TYPE(left)==AOP_ACC)
7513 bool pushedB = pushB ();
7514 emitcode("mov", "b,a");
7515 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7516 emitcode("anl", "a,b");
7521 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7522 emitcode("anl", "a,b");
7525 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7527 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
7528 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7529 emitcode ("anl", "a,b");
7531 else if (aopGetUsesAcc (left, offset))
7533 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7534 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7538 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7539 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE, DP2_RESULT_REG));
7541 aopPut (result, "a", offset);
7547 freeAsmop (result, NULL, ic, TRUE);
7548 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7549 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7552 /*-----------------------------------------------------------------*/
7553 /* genOr - code for or */
7554 /*-----------------------------------------------------------------*/
7556 genOr (iCode * ic, iCode * ifx)
7558 operand *left, *right, *result;
7559 int size, offset = 0;
7560 unsigned long lit = 0L;
7564 D (emitcode (";", "genOr"));
7566 AOP_OP_3_NOFATAL (ic, pushResult);
7567 AOP_SET_LOCALS (ic);
7571 genFarFarLogicOp(ic, "orl");
7577 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7579 AOP_TYPE (left), AOP_TYPE (right));
7580 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7582 AOP_SIZE (left), AOP_SIZE (right));
7585 /* if left is a literal & right is not then exchange them */
7586 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7587 #ifdef LOGIC_OPS_BROKEN
7588 || AOP_NEEDSACC (left) // I think this is a net loss now.
7592 operand *tmp = right;
7597 /* if result = right then exchange them */
7598 if (sameRegs (AOP (result), AOP (right)))
7600 operand *tmp = right;
7605 /* if right is bit then exchange them */
7606 if (AOP_TYPE (right) == AOP_CRY &&
7607 AOP_TYPE (left) != AOP_CRY)
7609 operand *tmp = right;
7613 if (AOP_TYPE (right) == AOP_LIT)
7614 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7616 size = AOP_SIZE (result);
7620 if (AOP_TYPE (left) == AOP_CRY)
7622 if (AOP_TYPE (right) == AOP_LIT)
7624 // c = bit | literal;
7627 // lit != 0 => result = 1
7628 if (AOP_TYPE (result) == AOP_CRY)
7631 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7633 continueIfTrue (ifx);
7636 emitcode ("setb", "c");
7640 // lit == 0 => result = left
7641 if (size && sameRegs (AOP (result), AOP (left)))
7643 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7648 if (AOP_TYPE (right) == AOP_CRY)
7651 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7652 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7657 symbol *tlbl = newiTempLabel (NULL);
7658 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
7659 emitcode ("setb", "c");
7660 emitcode ("jb", "%s,!tlabel",
7661 AOP (left)->aopu.aop_dir, tlbl->key + 100);
7663 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7664 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7666 jmpTrueOrFalse (ifx, tlbl);
7681 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7682 genIfxJump (ifx, "c");
7686 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7687 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7688 if ((AOP_TYPE (right) == AOP_LIT) &&
7689 (AOP_TYPE (result) == AOP_CRY) &&
7690 (AOP_TYPE (left) != AOP_CRY))
7696 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7698 continueIfTrue (ifx);
7703 // lit = 0, result = boolean(left)
7705 emitcode ("setb", "c");
7709 symbol *tlbl = newiTempLabel (NULL);
7710 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7716 genIfxJump (ifx, "a");
7724 /* if left is same as result */
7725 if (sameRegs (AOP (result), AOP (left)))
7727 for (; size--; offset++)
7729 if (AOP_TYPE (right) == AOP_LIT)
7731 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7734 /* dummy read of volatile operand */
7735 if (isOperandVolatile (left, FALSE))
7736 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7740 else if (bytelit == 0x0FF)
7742 aopPut (result, "#0xFF", offset);
7744 else if (IS_AOP_PREG (left))
7746 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7747 emitcode ("orl", "a,%s",
7748 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7749 aopPut (result, "a", offset);
7753 emitcode ("orl", "%s,%s",
7754 aopGet (left, offset, FALSE, TRUE, NULL),
7755 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7760 if (AOP_TYPE (left) == AOP_ACC)
7763 emitcode("mov", "a,b");
7764 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7766 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7768 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE, NULL));
7769 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7770 emitcode ("orl", "a,b");
7771 aopPut (result, "a", offset);
7773 else if (aopGetUsesAcc (left, offset))
7775 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7776 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7777 aopPut (result, "a", offset);
7781 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7782 if (IS_AOP_PREG (left))
7784 emitcode ("orl", "a,%s",
7785 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7786 aopPut (result, "a", offset);
7790 emitcode ("orl", "%s,a",
7791 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7799 // left & result in different registers
7800 if (AOP_TYPE (result) == AOP_CRY)
7803 // if(size), result in bit
7804 // if(!size && ifx), conditional oper: if(left | right)
7805 symbol *tlbl = newiTempLabel (NULL);
7806 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7808 emitcode ("setb", "c");
7811 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7812 && AOP_TYPE(left)==AOP_ACC)
7815 emitcode("mov", "a,b");
7816 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7818 else if (AOP_TYPE(left)==AOP_ACC)
7822 bool pushedB = pushB ();
7823 emitcode("mov", "b,a");
7824 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7825 emitcode("orl", "a,b");
7830 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7831 emitcode("orl", "a,b");
7834 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7836 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
7837 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7838 emitcode ("orl", "a,b");
7840 else if (aopGetUsesAcc (left, offset))
7842 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7843 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7847 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7848 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE, DP2_RESULT_REG));
7851 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7861 jmpTrueOrFalse (ifx, tlbl);
7867 _startLazyDPSEvaluation();
7868 for (; (size--); offset++)
7871 // result = left | right
7872 if (AOP_TYPE (right) == AOP_LIT)
7874 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7878 aopGet (left, offset, FALSE, FALSE, NULL),
7882 else if (bytelit == 0x0FF)
7884 /* dummy read of volatile operand */
7885 if (isOperandVolatile (left, FALSE))
7886 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7887 aopPut (result, "#0xFF", offset);
7891 // faster than result <- left, orl result,right
7892 // and better if result is SFR
7893 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7894 && AOP_TYPE(left)==AOP_ACC)
7897 emitcode("mov", "a,b");
7898 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7900 else if (AOP_TYPE(left)==AOP_ACC)
7904 bool pushedB = pushB ();
7905 emitcode("mov", "b,a");
7906 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7907 emitcode("orl", "a,b");
7912 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7913 emitcode("orl", "a,b");
7916 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7918 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
7919 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7920 emitcode ("orl", "a,b");
7922 else if (aopGetUsesAcc (left, offset))
7924 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7925 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7929 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7930 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE, DP2_RESULT_REG));
7932 aopPut (result, "a", offset);
7934 _endLazyDPSEvaluation();
7939 freeAsmop (result, NULL, ic, TRUE);
7940 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7941 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7944 /*-----------------------------------------------------------------*/
7945 /* genXor - code for xclusive or */
7946 /*-----------------------------------------------------------------*/
7948 genXor (iCode * ic, iCode * ifx)
7950 operand *left, *right, *result;
7951 int size, offset = 0;
7952 unsigned long lit = 0L;
7956 D (emitcode (";", "genXor"));
7958 AOP_OP_3_NOFATAL (ic, pushResult);
7959 AOP_SET_LOCALS (ic);
7963 genFarFarLogicOp(ic, "xrl");
7968 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7970 AOP_TYPE (left), AOP_TYPE (right));
7971 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7973 AOP_SIZE (left), AOP_SIZE (right));
7976 /* if left is a literal & right is not ||
7977 if left needs acc & right does not */
7978 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7979 #ifdef LOGIC_OPS_BROKEN
7980 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
7984 operand *tmp = right;
7989 /* if result = right then exchange them */
7990 if (sameRegs (AOP (result), AOP (right)))
7992 operand *tmp = right;
7997 /* if right is bit then exchange them */
7998 if (AOP_TYPE (right) == AOP_CRY &&
7999 AOP_TYPE (left) != AOP_CRY)
8001 operand *tmp = right;
8005 if (AOP_TYPE (right) == AOP_LIT)
8006 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8008 size = AOP_SIZE (result);
8012 if (AOP_TYPE (left) == AOP_CRY)
8014 if (AOP_TYPE (right) == AOP_LIT)
8016 // c = bit & literal;
8019 // lit>>1 != 0 => result = 1
8020 if (AOP_TYPE (result) == AOP_CRY)
8023 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
8025 continueIfTrue (ifx);
8028 emitcode ("setb", "c");
8035 // lit == 0, result = left
8036 if (size && sameRegs (AOP (result), AOP (left)))
8038 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
8042 // lit == 1, result = not(left)
8043 if (size && sameRegs (AOP (result), AOP (left)))
8045 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
8050 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
8051 emitcode ("cpl", "c");
8059 symbol *tlbl = newiTempLabel (NULL);
8060 if (AOP_TYPE (right) == AOP_CRY)
8063 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8067 int sizer = AOP_SIZE (right);
8069 // if val>>1 != 0, result = 1
8070 emitcode ("setb", "c");
8073 MOVA (aopGet (right, sizer - 1, FALSE, FALSE, NULL));
8075 // test the msb of the lsb
8076 emitcode ("anl", "a,#!constbyte",0xfe);
8077 emitcode ("jnz", "!tlabel", tlbl->key + 100);
8081 emitcode ("rrc", "a");
8083 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
8084 emitcode ("cpl", "c");
8092 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
8093 genIfxJump (ifx, "c");
8097 /* if left is same as result */
8098 if (sameRegs (AOP (result), AOP (left)))
8100 for (; size--; offset++)
8102 if (AOP_TYPE (right) == AOP_LIT)
8104 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
8107 /* dummy read of volatile operand */
8108 if (isOperandVolatile (left, FALSE))
8109 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8113 else if (IS_AOP_PREG (left))
8115 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8116 emitcode ("xrl", "a,%s",
8117 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG));
8118 aopPut (result, "a", offset);
8122 emitcode ("xrl", "%s,%s",
8123 aopGet (left, offset, FALSE, TRUE, NULL),
8124 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8129 if (AOP_TYPE (left) == AOP_ACC)
8132 emitcode("mov", "a,b");
8133 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8135 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
8137 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
8138 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8139 emitcode ("xrl", "a,b");
8140 aopPut (result, "a", offset);
8142 else if (aopGetUsesAcc (left, offset))
8144 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8145 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8146 aopPut (result, "a", offset);
8150 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
8151 if (IS_AOP_PREG (left))
8153 emitcode ("xrl", "a,%s",
8154 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
8155 aopPut (result, "a", offset);
8158 emitcode ("xrl", "%s,a",
8159 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
8166 // left & result in different registers
8167 if (AOP_TYPE (result) == AOP_CRY)
8170 // if(size), result in bit
8171 // if(!size && ifx), conditional oper: if(left ^ right)
8172 symbol *tlbl = newiTempLabel (NULL);
8173 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
8176 emitcode ("setb", "c");
8179 if ((AOP_TYPE (right) == AOP_LIT) &&
8180 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
8182 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8184 else if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
8185 && AOP_TYPE(left)==AOP_ACC)
8188 emitcode("mov", "a,b");
8189 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8191 else if (AOP_TYPE(left)==AOP_ACC)
8195 bool pushedB = pushB ();
8196 emitcode("mov", "b,a");
8197 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8198 emitcode("xrl", "a,b");
8203 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8204 emitcode("xrl", "a,b");
8207 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
8209 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
8210 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8211 emitcode ("xrl", "a,b");
8213 else if (aopGetUsesAcc (left, offset))
8215 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8216 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8220 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
8221 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
8224 emitcode ("jnz", "!tlabel", tlbl->key + 100);
8234 jmpTrueOrFalse (ifx, tlbl);
8238 for (; (size--); offset++)
8241 // result = left ^ right
8242 if (AOP_TYPE (right) == AOP_LIT)
8244 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
8248 aopGet (left, offset, FALSE, FALSE, NULL),
8252 D (emitcode (";", "better literal XOR."));
8253 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8254 emitcode ("xrl", "a, %s",
8255 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8259 // faster than result <- left, anl result,right
8260 // and better if result is SFR
8261 if (AOP_TYPE (left) == AOP_ACC)
8263 emitcode ("xrl", "a,%s",
8264 aopGet (right, offset,
8265 FALSE, FALSE, DP2_RESULT_REG));
8269 char *rOp = aopGet (right, offset, FALSE, FALSE, NULL);
8270 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
8272 emitcode("mov", "b,a");
8276 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8277 emitcode ("xrl", "a,%s", rOp);
8280 aopPut (result, "a", offset);
8286 freeAsmop (result, NULL, ic, TRUE);
8287 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
8288 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
8291 /*-----------------------------------------------------------------*/
8292 /* genInline - write the inline code out */
8293 /*-----------------------------------------------------------------*/
8295 genInline (iCode * ic)
8297 char *buffer, *bp, *bp1;
8299 D (emitcode (";", "genInline"));
8301 _G.inLine += (!options.asmpeep);
8303 buffer = bp = bp1 = Safe_strdup(IC_INLINE(ic));
8305 /* emit each line as a code */
8316 /* Add \n for labels, not dirs such as c:\mydir */
8317 if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
8331 /* emitcode("",buffer); */
8332 _G.inLine -= (!options.asmpeep);
8335 /*-----------------------------------------------------------------*/
8336 /* genRRC - rotate right with carry */
8337 /*-----------------------------------------------------------------*/
8341 operand *left, *result;
8345 D (emitcode (";", "genRRC"));
8347 /* rotate right with carry */
8348 left = IC_LEFT (ic);
8349 result = IC_RESULT (ic);
8350 aopOp (left, ic, FALSE, FALSE);
8351 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8353 /* move it to the result */
8354 size = AOP_SIZE (result);
8358 _startLazyDPSEvaluation ();
8361 l = aopGet (left, offset, FALSE, FALSE, NULL);
8363 emitcode ("rrc", "a");
8364 if (AOP_SIZE (result) > 1)
8365 aopPut (result, "a", offset--);
8367 _endLazyDPSEvaluation ();
8369 /* now we need to put the carry into the
8370 highest order byte of the result */
8371 if (AOP_SIZE (result) > 1)
8373 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE, NULL);
8376 emitcode ("mov", "acc.7,c");
8377 aopPut (result, "a", AOP_SIZE (result) - 1);
8378 freeAsmop (result, NULL, ic, TRUE);
8379 freeAsmop (left, NULL, ic, TRUE);
8382 /*-----------------------------------------------------------------*/
8383 /* genRLC - generate code for rotate left with carry */
8384 /*-----------------------------------------------------------------*/
8388 operand *left, *result;
8392 D (emitcode (";", "genRLC"));
8394 /* rotate right with carry */
8395 left = IC_LEFT (ic);
8396 result = IC_RESULT (ic);
8397 aopOp (left, ic, FALSE, FALSE);
8398 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8400 /* move it to the result */
8401 size = AOP_SIZE (result);
8405 l = aopGet (left, offset, FALSE, FALSE, NULL);
8407 emitcode ("add", "a,acc");
8408 if (AOP_SIZE (result) > 1)
8410 aopPut (result, "a", offset++);
8413 _startLazyDPSEvaluation ();
8416 l = aopGet (left, offset, FALSE, FALSE, NULL);
8418 emitcode ("rlc", "a");
8419 if (AOP_SIZE (result) > 1)
8420 aopPut (result, "a", offset++);
8422 _endLazyDPSEvaluation ();
8424 /* now we need to put the carry into the
8425 highest order byte of the result */
8426 if (AOP_SIZE (result) > 1)
8428 l = aopGet (result, 0, FALSE, FALSE, NULL);
8431 emitcode ("mov", "acc.0,c");
8432 aopPut (result, "a", 0);
8433 freeAsmop (result, NULL, ic, TRUE);
8434 freeAsmop (left, NULL, ic, TRUE);
8437 /*-----------------------------------------------------------------*/
8438 /* genGetHbit - generates code get highest order bit */
8439 /*-----------------------------------------------------------------*/
8441 genGetHbit (iCode * ic)
8443 operand *left, *result;
8445 D (emitcode (";", "genGetHbit"));
8447 left = IC_LEFT (ic);
8448 result = IC_RESULT (ic);
8449 aopOp (left, ic, FALSE, FALSE);
8450 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8452 /* get the highest order byte into a */
8453 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
8454 if (AOP_TYPE (result) == AOP_CRY)
8456 emitcode ("rlc", "a");
8461 emitcode ("rl", "a");
8462 emitcode ("anl", "a,#1");
8467 freeAsmop (result, NULL, ic, TRUE);
8468 freeAsmop (left, NULL, ic, TRUE);
8471 /*-----------------------------------------------------------------*/
8472 /* genSwap - generates code to swap nibbles or bytes */
8473 /*-----------------------------------------------------------------*/
8475 genSwap (iCode * ic)
8477 operand *left, *result;
8479 D(emitcode ("; genSwap",""));
8481 left = IC_LEFT (ic);
8482 result = IC_RESULT (ic);
8483 aopOp (left, ic, FALSE, FALSE);
8484 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8486 _startLazyDPSEvaluation ();
8487 switch (AOP_SIZE (left))
8489 case 1: /* swap nibbles in byte */
8490 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
8491 emitcode ("swap", "a");
8492 aopPut (result, "a", 0);
8494 case 2: /* swap bytes in word */
8495 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
8497 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
8498 aopPut (result, aopGet (left, 1, FALSE, FALSE, NULL), 0);
8499 aopPut (result, "a", 1);
8501 else if (operandsEqu (left, result))
8504 bool pushedB = FALSE, leftInB = FALSE;
8506 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
8507 if (AOP_NEEDSACC (left) || AOP_NEEDSACC (result))
8510 emitcode ("mov", "b,a");
8514 aopPut (result, aopGet (left, 1, FALSE, FALSE, NULL), 0);
8515 aopPut (result, reg, 1);
8522 aopPut (result, aopGet (left, 1, FALSE, FALSE, NULL), 0);
8523 aopPut (result, aopGet (left, 0, FALSE, FALSE, NULL), 1);
8527 wassertl(FALSE, "unsupported SWAP operand size");
8529 _endLazyDPSEvaluation ();
8531 freeAsmop (result, NULL, ic, TRUE);
8532 freeAsmop (left, NULL, ic, TRUE);
8535 /*-----------------------------------------------------------------*/
8536 /* AccRol - rotate left accumulator by known count */
8537 /*-----------------------------------------------------------------*/
8539 AccRol (int shCount)
8541 shCount &= 0x0007; // shCount : 0..7
8548 emitcode ("rl", "a");
8551 emitcode ("rl", "a");
8552 emitcode ("rl", "a");
8555 emitcode ("swap", "a");
8556 emitcode ("rr", "a");
8559 emitcode ("swap", "a");
8562 emitcode ("swap", "a");
8563 emitcode ("rl", "a");
8566 emitcode ("rr", "a");
8567 emitcode ("rr", "a");
8570 emitcode ("rr", "a");
8575 /*-----------------------------------------------------------------*/
8576 /* AccLsh - left shift accumulator by known count */
8577 /*-----------------------------------------------------------------*/
8579 AccLsh (int shCount)
8584 emitcode ("add", "a,acc");
8585 else if (shCount == 2)
8587 emitcode ("add", "a,acc");
8588 emitcode ("add", "a,acc");
8592 /* rotate left accumulator */
8594 /* and kill the lower order bits */
8595 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
8600 /*-----------------------------------------------------------------*/
8601 /* AccRsh - right shift accumulator by known count */
8602 /*-----------------------------------------------------------------*/
8604 AccRsh (int shCount)
8611 emitcode ("rrc", "a");
8615 /* rotate right accumulator */
8616 AccRol (8 - shCount);
8617 /* and kill the higher order bits */
8618 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
8623 #ifdef BETTER_LITERAL_SHIFT
8624 /*-----------------------------------------------------------------*/
8625 /* AccSRsh - signed right shift accumulator by known count */
8626 /*-----------------------------------------------------------------*/
8628 AccSRsh (int shCount)
8635 emitcode ("mov", "c,acc.7");
8636 emitcode ("rrc", "a");
8638 else if (shCount == 2)
8640 emitcode ("mov", "c,acc.7");
8641 emitcode ("rrc", "a");
8642 emitcode ("mov", "c,acc.7");
8643 emitcode ("rrc", "a");
8647 tlbl = newiTempLabel (NULL);
8648 /* rotate right accumulator */
8649 AccRol (8 - shCount);
8650 /* and kill the higher order bits */
8651 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
8652 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8653 emitcode ("orl", "a,#!constbyte",
8654 (unsigned char) ~SRMask[shCount]);
8661 #ifdef BETTER_LITERAL_SHIFT
8662 /*-----------------------------------------------------------------*/
8663 /* shiftR1Left2Result - shift right one byte from left to result */
8664 /*-----------------------------------------------------------------*/
8666 shiftR1Left2Result (operand * left, int offl,
8667 operand * result, int offr,
8668 int shCount, int sign)
8670 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
8671 /* shift right accumulator */
8676 aopPut (result, "a", offr);
8680 #ifdef BETTER_LITERAL_SHIFT
8681 /*-----------------------------------------------------------------*/
8682 /* shiftL1Left2Result - shift left one byte from left to result */
8683 /*-----------------------------------------------------------------*/
8685 shiftL1Left2Result (operand * left, int offl,
8686 operand * result, int offr, int shCount)
8689 l = aopGet (left, offl, FALSE, FALSE, NULL);
8691 /* shift left accumulator */
8693 aopPut (result, "a", offr);
8697 #ifdef BETTER_LITERAL_SHIFT
8698 /*-----------------------------------------------------------------*/
8699 /* movLeft2Result - move byte from left to result */
8700 /*-----------------------------------------------------------------*/
8702 movLeft2Result (operand * left, int offl,
8703 operand * result, int offr, int sign)
8706 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8708 l = aopGet (left, offl, FALSE, FALSE, NULL);
8710 if (*l == '@' && (IS_AOP_PREG (result)))
8712 emitcode ("mov", "a,%s", l);
8713 aopPut (result, "a", offr);
8719 aopPut (result, l, offr);
8723 /* MSB sign in acc.7 ! */
8724 if (getDataSize (left) == offl + 1)
8727 aopPut (result, "a", offr);
8735 #ifdef BETTER_LITERAL_SHIFT
8736 /*-----------------------------------------------------------------*/
8737 /* AccAXRrl1 - right rotate a:x by 1 */
8738 /*-----------------------------------------------------------------*/
8742 emitcode ("mov", "c,acc.0");
8743 emitcode ("xch", "a,%s", x);
8744 emitcode ("rrc", "a");
8745 emitcode ("xch", "a,%s", x);
8746 emitcode ("rrc", "a");
8750 #ifdef BETTER_LITERAL_SHIFT
8752 /*-----------------------------------------------------------------*/
8753 /* AccAXLrl1 - left rotate a:x by 1 */
8754 /*-----------------------------------------------------------------*/
8758 emitcode ("mov", "c,acc.7");
8759 emitcode ("xch", "a,%s", x);
8760 emitcode ("rlc", "a");
8761 emitcode ("xch", "a,%s", x);
8762 emitcode ("rlc", "a");
8766 #ifdef BETTER_LITERAL_SHIFT
8767 /*-----------------------------------------------------------------*/
8768 /* AccAXRsh1 - right shift c->a:x->c by 1 */
8769 /*-----------------------------------------------------------------*/
8773 emitcode ("rrc", "a");
8774 emitcode ("xch", "a,%s", x);
8775 emitcode ("rrc", "a");
8776 emitcode ("xch", "a,%s", x);
8780 #ifdef BETTER_LITERAL_SHIFT
8781 /*-----------------------------------------------------------------*/
8782 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8783 /*-----------------------------------------------------------------*/
8787 emitcode ("xch", "a,%s", x);
8788 emitcode ("add", "a,acc");
8789 emitcode ("xch", "a,%s", x);
8790 emitcode ("rlc", "a");
8794 #ifdef BETTER_LITERAL_SHIFT
8795 /*-----------------------------------------------------------------*/
8796 /* AccAXLsh - left shift a:x by known count (0..7) */
8797 /*-----------------------------------------------------------------*/
8799 AccAXLsh (char *x, int shCount)
8814 case 5: // AAAAABBB:CCCCCDDD
8816 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8818 emitcode ("anl", "a,#!constbyte",
8819 SLMask[shCount]); // BBB00000:CCCCCDDD
8821 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8823 AccRol (shCount); // DDDCCCCC:BBB00000
8825 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8827 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8829 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8831 emitcode ("anl", "a,#!constbyte",
8832 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8834 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8836 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8839 case 6: // AAAAAABB:CCCCCCDD
8840 emitcode ("anl", "a,#!constbyte",
8841 SRMask[shCount]); // 000000BB:CCCCCCDD
8843 AccAXRrl1 (x); // D000000B:BCCCCCCD
8844 AccAXRrl1 (x); // DD000000:BBCCCCCC
8845 emitcode ("xch", "a,%s", x); // BBCCCCCC:DD000000
8847 emitcode ("mov", "c,acc.0"); // c = B
8848 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8849 emitcode("rrc","a");
8850 emitcode("xch","a,%s", x);
8851 emitcode("rrc","a");
8852 emitcode("mov","c,acc.0"); //<< get correct bit
8853 emitcode("xch","a,%s", x);
8855 emitcode("rrc","a");
8856 emitcode("xch","a,%s", x);
8857 emitcode("rrc","a");
8858 emitcode("xch","a,%s", x);
8861 case 7: // a:x <<= 7
8863 emitcode ("anl", "a,#!constbyte",
8864 SRMask[shCount]); // 0000000B:CCCCCCCD
8866 AccAXRrl1 (x); // D0000000:BCCCCCCC
8868 emitcode ("xch", "a,%s", x); // BCCCCCCC:D0000000
8877 #ifdef BETTER_LITERAL_SHIFT
8879 /*-----------------------------------------------------------------*/
8880 /* AccAXRsh - right shift a:x known count (0..7) */
8881 /*-----------------------------------------------------------------*/
8883 AccAXRsh (char *x, int shCount)
8891 AccAXRsh1 (x); // 0->a:x
8896 AccAXRsh1 (x); // 0->a:x
8899 AccAXRsh1 (x); // 0->a:x
8904 case 5: // AAAAABBB:CCCCCDDD = a:x
8906 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8908 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8910 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8912 emitcode ("anl", "a,#!constbyte",
8913 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8915 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8917 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8919 emitcode ("anl", "a,#!constbyte",
8920 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8922 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8924 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8926 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8929 case 6: // AABBBBBB:CCDDDDDD
8931 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDE
8932 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8934 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8936 emitcode ("anl", "a,#!constbyte",
8937 SRMask[shCount]); // 000000AA:BBBBBBCC
8940 case 7: // ABBBBBBB:CDDDDDDD
8942 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8944 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8946 emitcode ("anl", "a,#!constbyte",
8947 SRMask[shCount]); // 0000000A:BBBBBBBC
8956 #ifdef BETTER_LITERAL_SHIFT
8957 /*-----------------------------------------------------------------*/
8958 /* AccAXRshS - right shift signed a:x known count (0..7) */
8959 /*-----------------------------------------------------------------*/
8961 AccAXRshS (char *x, int shCount)
8969 emitcode ("mov", "c,acc.7");
8970 AccAXRsh1 (x); // s->a:x
8974 emitcode ("mov", "c,acc.7");
8975 AccAXRsh1 (x); // s->a:x
8977 emitcode ("mov", "c,acc.7");
8978 AccAXRsh1 (x); // s->a:x
8983 case 5: // AAAAABBB:CCCCCDDD = a:x
8985 tlbl = newiTempLabel (NULL);
8986 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8988 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8990 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8992 emitcode ("anl", "a,#!constbyte",
8993 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8995 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8997 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8999 emitcode ("anl", "a,#!constbyte",
9000 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
9002 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
9004 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
9006 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
9008 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
9009 emitcode ("orl", "a,#!constbyte",
9010 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
9013 break; // SSSSAAAA:BBBCCCCC
9015 case 6: // AABBBBBB:CCDDDDDD
9017 tlbl = newiTempLabel (NULL);
9019 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
9020 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
9022 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
9024 emitcode ("anl", "a,#!constbyte",
9025 SRMask[shCount]); // 000000AA:BBBBBBCC
9027 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
9028 emitcode ("orl", "a,#!constbyte",
9029 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
9033 case 7: // ABBBBBBB:CDDDDDDD
9035 tlbl = newiTempLabel (NULL);
9037 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
9039 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
9041 emitcode ("anl", "a,#!constbyte",
9042 SRMask[shCount]); // 0000000A:BBBBBBBC
9044 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
9045 emitcode ("orl", "a,#!constbyte",
9046 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
9056 #ifdef BETTER_LITERAL_SHIFT
9058 _loadLeftIntoAx(char **lsb,
9064 // Get the initial value from left into a pair of registers.
9065 // MSB must be in A, LSB can be any register.
9067 // If the result is held in registers, it is an optimization
9068 // if the LSB can be held in the register which will hold the,
9069 // result LSB since this saves us from having to copy it into
9070 // the result following AccAXLsh.
9072 // If the result is addressed indirectly, this is not a gain.
9073 if (AOP_NEEDSACC(result))
9077 _startLazyDPSEvaluation();
9078 if (AOP_TYPE(left) == AOP_DPTR2)
9081 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE, NULL));
9082 // get LSB in DP2_RESULT_REG.
9083 leftByte = aopGet (left, offl, FALSE, FALSE, DP2_RESULT_REG);
9084 assert(!strcmp(leftByte, DP2_RESULT_REG));
9088 // get LSB into DP2_RESULT_REG
9089 leftByte = aopGet (left, offl, FALSE, FALSE, NULL);
9090 if (strcmp(leftByte, DP2_RESULT_REG))
9093 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
9096 leftByte = aopGet (left, offl + MSB16, FALSE, FALSE, NULL);
9097 assert(strcmp(leftByte, DP2_RESULT_REG));
9100 _endLazyDPSEvaluation();
9101 *lsb = DP2_RESULT_REG;
9105 if (sameRegs (AOP (result), AOP (left)) &&
9106 ((offl + MSB16) == offr))
9108 /* don't crash result[offr] */
9109 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
9110 emitcode ("xch", "a,%s",
9111 aopGet (left, offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
9115 movLeft2Result (left, offl, result, offr, 0);
9116 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE, NULL));
9118 *lsb = aopGet (result, offr, FALSE, FALSE, DP2_RESULT_REG);
9119 assert(strcmp(*lsb,"a"));
9124 _storeAxResults(char *lsb,
9128 _startLazyDPSEvaluation();
9129 if (AOP_NEEDSACC(result))
9131 /* We have to explicitly update the result LSB.
9133 emitcode ("xch","a,%s", lsb);
9134 aopPut (result, "a", offr);
9135 emitcode ("mov","a,%s", lsb);
9137 if (getDataSize (result) > 1)
9139 aopPut (result, "a", offr + MSB16);
9141 _endLazyDPSEvaluation();
9144 /*-----------------------------------------------------------------*/
9145 /* shiftL2Left2Result - shift left two bytes from left to result */
9146 /*-----------------------------------------------------------------*/
9148 shiftL2Left2Result (operand * left, int offl,
9149 operand * result, int offr, int shCount)
9153 _loadLeftIntoAx(&lsb, left, result, offl, offr);
9155 AccAXLsh (lsb, shCount);
9157 _storeAxResults(lsb, result, offr);
9161 #ifdef BETTER_LITERAL_SHIFT
9162 /*-----------------------------------------------------------------*/
9163 /* shiftR2Left2Result - shift right two bytes from left to result */
9164 /*-----------------------------------------------------------------*/
9166 shiftR2Left2Result (operand * left, int offl,
9167 operand * result, int offr,
9168 int shCount, int sign)
9172 _loadLeftIntoAx(&lsb, left, result, offl, offr);
9174 /* a:x >> shCount (x = lsb(result)) */
9177 AccAXRshS(lsb, shCount);
9181 AccAXRsh(lsb, shCount);
9184 _storeAxResults(lsb, result, offr);
9188 /*-----------------------------------------------------------------*/
9189 /* shiftLLeftOrResult - shift left one byte from left, or to result */
9190 /*-----------------------------------------------------------------*/
9192 shiftLLeftOrResult (operand * left, int offl,
9193 operand * result, int offr, int shCount)
9195 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
9196 /* shift left accumulator */
9198 /* or with result */
9199 emitcode ("orl", "a,%s",
9200 aopGet (result, offr, FALSE, FALSE, DP2_RESULT_REG));
9201 /* back to result */
9202 aopPut (result, "a", offr);
9207 /*-----------------------------------------------------------------*/
9208 /* shiftRLeftOrResult - shift right one byte from left,or to result */
9209 /*-----------------------------------------------------------------*/
9211 shiftRLeftOrResult (operand * left, int offl,
9212 operand * result, int offr, int shCount)
9214 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
9215 /* shift right accumulator */
9217 /* or with result */
9218 emitcode ("orl", "a,%s",
9219 aopGet (result, offr, FALSE, FALSE, DP2_RESULT_REG));
9220 /* back to result */
9221 aopPut (result, "a", offr);
9225 #ifdef BETTER_LITERAL_SHIFT
9226 /*-----------------------------------------------------------------*/
9227 /* genlshOne - left shift a one byte quantity by known count */
9228 /*-----------------------------------------------------------------*/
9230 genlshOne (operand * result, operand * left, int shCount)
9232 D (emitcode (";", "genlshOne"));
9234 shiftL1Left2Result (left, LSB, result, LSB, shCount);
9238 #ifdef BETTER_LITERAL_SHIFT
9239 /*-----------------------------------------------------------------*/
9240 /* genlshTwo - left shift two bytes by known amount != 0 */
9241 /*-----------------------------------------------------------------*/
9243 genlshTwo (operand * result, operand * left, int shCount)
9247 D (emitcode (";", "genlshTwo"));
9249 size = getDataSize (result);
9251 /* if shCount >= 8 */
9256 _startLazyDPSEvaluation();
9262 _endLazyDPSEvaluation();
9263 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
9264 aopPut (result, zero, LSB);
9268 movLeft2Result (left, LSB, result, MSB16, 0);
9269 aopPut (result, zero, LSB);
9270 _endLazyDPSEvaluation();
9275 aopPut (result, zero, LSB);
9276 _endLazyDPSEvaluation();
9280 /* 1 <= shCount <= 7 */
9284 shiftL1Left2Result (left, LSB, result, LSB, shCount);
9286 shiftL2Left2Result (left, LSB, result, LSB, shCount);
9293 /*-----------------------------------------------------------------*/
9294 /* shiftLLong - shift left one long from left to result */
9295 /* offl = LSB or MSB16 */
9296 /*-----------------------------------------------------------------*/
9298 shiftLLong (operand * left, operand * result, int offr)
9301 int size = AOP_SIZE (result);
9303 if (size >= LSB + offr)
9305 l = aopGet (left, LSB, FALSE, FALSE, NULL);
9307 emitcode ("add", "a,acc");
9308 if (sameRegs (AOP (left), AOP (result)) &&
9309 size >= MSB16 + offr && offr != LSB)
9310 emitcode ("xch", "a,%s",
9311 aopGet (left, LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
9313 aopPut (result, "a", LSB + offr);
9316 if (size >= MSB16 + offr)
9318 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
9320 l = aopGet (left, MSB16, FALSE, FALSE, TRUE);
9323 emitcode ("rlc", "a");
9324 if (sameRegs (AOP (left), AOP (result)) &&
9325 size >= MSB24 + offr && offr != LSB)
9326 emitcode ("xch", "a,%s",
9327 aopGet (left, MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
9329 aopPut (result, "a", MSB16 + offr);
9332 if (size >= MSB24 + offr)
9334 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
9336 l = aopGet (left, MSB24, FALSE, FALSE, NULL);
9339 emitcode ("rlc", "a");
9340 if (sameRegs (AOP (left), AOP (result)) &&
9341 size >= MSB32 + offr && offr != LSB)
9342 emitcode ("xch", "a,%s",
9343 aopGet (left, MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
9345 aopPut (result, "a", MSB24 + offr);
9348 if (size > MSB32 + offr)
9350 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
9352 l = aopGet (left, MSB32, FALSE, FALSE, NULL);
9355 emitcode ("rlc", "a");
9356 aopPut (result, "a", MSB32 + offr);
9359 aopPut (result, zero, LSB);
9365 /*-----------------------------------------------------------------*/
9366 /* genlshFour - shift four byte by a known amount != 0 */
9367 /*-----------------------------------------------------------------*/
9369 genlshFour (operand * result, operand * left, int shCount)
9373 D (emitcode (";", "genlshFour"));
9375 size = AOP_SIZE (result);
9377 /* if shifting more that 3 bytes */
9382 /* lowest order of left goes to the highest
9383 order of the destination */
9384 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
9386 movLeft2Result (left, LSB, result, MSB32, 0);
9387 aopPut (result, zero, LSB);
9388 aopPut (result, zero, MSB16);
9389 aopPut (result, zero, MSB24);
9393 /* more than two bytes */
9394 else if (shCount >= 16)
9396 /* lower order two bytes goes to higher order two bytes */
9398 /* if some more remaining */
9400 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
9403 movLeft2Result (left, MSB16, result, MSB32, 0);
9404 movLeft2Result (left, LSB, result, MSB24, 0);
9406 aopPut (result, zero, MSB16);
9407 aopPut (result, zero, LSB);
9411 /* if more than 1 byte */
9412 else if (shCount >= 8)
9414 /* lower order three bytes goes to higher order three bytes */
9419 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
9421 movLeft2Result (left, LSB, result, MSB16, 0);
9427 movLeft2Result (left, MSB24, result, MSB32, 0);
9428 movLeft2Result (left, MSB16, result, MSB24, 0);
9429 movLeft2Result (left, LSB, result, MSB16, 0);
9430 aopPut (result, zero, LSB);
9432 else if (shCount == 1)
9433 shiftLLong (left, result, MSB16);
9436 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
9437 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
9438 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
9439 aopPut (result, zero, LSB);
9444 /* 1 <= shCount <= 7 */
9445 else if (shCount <= 2)
9447 shiftLLong (left, result, LSB);
9449 shiftLLong (result, result, LSB);
9451 /* 3 <= shCount <= 7, optimize */
9454 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
9455 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
9456 shiftL2Left2Result (left, LSB, result, LSB, shCount);
9461 #ifdef BETTER_LITERAL_SHIFT
9462 /*-----------------------------------------------------------------*/
9463 /* genLeftShiftLiteral - left shifting by known count */
9464 /*-----------------------------------------------------------------*/
9466 genLeftShiftLiteral (operand * left,
9471 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9474 size = getSize (operandType (result));
9476 D (emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
9478 /* We only handle certain easy cases so far. */
9480 && (shCount < (size * 8))
9484 D(emitcode (";", "genLeftShiftLiteral wimping out"););
9488 freeAsmop (right, NULL, ic, TRUE);
9490 aopOp(left, ic, FALSE, FALSE);
9491 aopOp(result, ic, FALSE, AOP_USESDPTR(left));
9494 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
9496 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
9497 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
9499 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
9502 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
9504 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
9505 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
9507 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
9513 emitcode ("; shift left ", "result %d, left %d", size,
9517 /* I suppose that the left size >= result size */
9520 _startLazyDPSEvaluation();
9523 movLeft2Result (left, size, result, size, 0);
9525 _endLazyDPSEvaluation();
9527 else if (shCount >= (size * 8))
9529 _startLazyDPSEvaluation();
9532 aopPut (result, zero, size);
9534 _endLazyDPSEvaluation();
9541 genlshOne (result, left, shCount);
9545 genlshTwo (result, left, shCount);
9549 genlshFour (result, left, shCount);
9553 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9554 "*** ack! mystery literal shift!\n");
9558 freeAsmop (result, NULL, ic, TRUE);
9559 freeAsmop (left, NULL, ic, TRUE);
9564 /*-----------------------------------------------------------------*/
9565 /* genLeftShift - generates code for left shifting */
9566 /*-----------------------------------------------------------------*/
9568 genLeftShift (iCode * ic)
9570 operand *left, *right, *result;
9573 symbol *tlbl, *tlbl1;
9576 D (emitcode (";", "genLeftShift"));
9578 right = IC_RIGHT (ic);
9579 left = IC_LEFT (ic);
9580 result = IC_RESULT (ic);
9582 aopOp (right, ic, FALSE, FALSE);
9585 #ifdef BETTER_LITERAL_SHIFT
9586 /* if the shift count is known then do it
9587 as efficiently as possible */
9588 if (AOP_TYPE (right) == AOP_LIT)
9590 if (genLeftShiftLiteral (left, right, result, ic))
9597 /* shift count is unknown then we have to form
9598 a loop get the loop count in B : Note: we take
9599 only the lower order byte since shifting
9600 more that 32 bits make no sense anyway, ( the
9601 largest size of an object can be only 32 bits ) */
9604 if (AOP_TYPE (right) == AOP_LIT)
9606 /* Really should be handled by genLeftShiftLiteral,
9607 * but since I'm too lazy to fix that today, at least we can make
9608 * some small improvement.
9610 emitcode("mov", "b,#!constbyte",
9611 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9615 MOVB (aopGet (right, 0, FALSE, FALSE, "b"));
9616 emitcode ("inc", "b");
9618 freeAsmop (right, NULL, ic, TRUE);
9619 aopOp (left, ic, FALSE, FALSE);
9620 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9622 /* now move the left to the result if they are not the same */
9623 if (!sameRegs (AOP (left), AOP (result)) &&
9624 AOP_SIZE (result) > 1)
9627 size = AOP_SIZE (result);
9629 _startLazyDPSEvaluation ();
9632 l = aopGet (left, offset, FALSE, TRUE, NULL);
9633 if (*l == '@' && (IS_AOP_PREG (result)))
9636 emitcode ("mov", "a,%s", l);
9637 aopPut (result, "a", offset);
9640 aopPut (result, l, offset);
9643 _endLazyDPSEvaluation ();
9646 tlbl = newiTempLabel (NULL);
9647 size = AOP_SIZE (result);
9649 tlbl1 = newiTempLabel (NULL);
9651 /* if it is only one byte then */
9654 symbol *tlbl1 = newiTempLabel (NULL);
9656 l = aopGet (left, 0, FALSE, FALSE, NULL);
9658 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9660 emitcode ("add", "a,acc");
9662 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9664 aopPut (result, "a", 0);
9668 reAdjustPreg (AOP (result));
9670 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9672 l = aopGet (result, offset, FALSE, FALSE, NULL);
9674 emitcode ("add", "a,acc");
9675 aopPut (result, "a", offset++);
9676 _startLazyDPSEvaluation ();
9679 l = aopGet (result, offset, FALSE, FALSE, NULL);
9681 emitcode ("rlc", "a");
9682 aopPut (result, "a", offset++);
9684 _endLazyDPSEvaluation ();
9685 reAdjustPreg (AOP (result));
9688 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9691 freeAsmop (result, NULL, ic, TRUE);
9692 freeAsmop (left, NULL, ic, TRUE);
9695 #ifdef BETTER_LITERAL_SHIFT
9696 /*-----------------------------------------------------------------*/
9697 /* genrshOne - right shift a one byte quantity by known count */
9698 /*-----------------------------------------------------------------*/
9700 genrshOne (operand * result, operand * left,
9701 int shCount, int sign)
9703 D (emitcode (";", "genrshOne"));
9705 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9709 #ifdef BETTER_LITERAL_SHIFT
9710 /*-----------------------------------------------------------------*/
9711 /* genrshTwo - right shift two bytes by known amount != 0 */
9712 /*-----------------------------------------------------------------*/
9714 genrshTwo (operand * result, operand * left,
9715 int shCount, int sign)
9717 D (emitcode (";", "genrshTwo"));
9719 /* if shCount >= 8 */
9723 _startLazyDPSEvaluation();
9725 shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
9727 movLeft2Result (left, MSB16, result, LSB, sign);
9728 addSign (result, MSB16, sign);
9729 _endLazyDPSEvaluation();
9732 /* 1 <= shCount <= 7 */
9734 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9738 /*-----------------------------------------------------------------*/
9739 /* shiftRLong - shift right one long from left to result */
9740 /* offl = LSB or MSB16 */
9741 /*-----------------------------------------------------------------*/
9743 shiftRLong (operand * left, int offl,
9744 operand * result, int sign)
9746 bool overlapping = regsInCommon (left, result) || operandsEqu(left, result);
9748 if (overlapping && offl>1)
9750 // we are in big trouble, but this shouldn't happen
9751 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9754 MOVA (aopGet (left, MSB32, FALSE, FALSE, NULL));
9761 emitcode ("rlc", "a");
9762 emitcode ("subb", "a,acc");
9763 emitcode ("xch", "a,%s",
9764 aopGet(left, MSB32, FALSE, FALSE, DP2_RESULT_REG));
9768 aopPut (result, zero, MSB32);
9774 emitcode ("clr", "c");
9778 emitcode ("mov", "c,acc.7");
9781 emitcode ("rrc", "a");
9783 if (overlapping && offl==MSB16)
9785 emitcode ("xch", "a,%s", aopGet (left, MSB24, FALSE, FALSE, DP2_RESULT_REG));
9789 aopPut (result, "a", MSB32 - offl);
9790 MOVA (aopGet (left, MSB24, FALSE, FALSE, NULL));
9793 emitcode ("rrc", "a");
9795 if (overlapping && offl==MSB16)
9797 emitcode ("xch", "a,%s", aopGet (left, MSB16, FALSE, FALSE, DP2_RESULT_REG));
9801 aopPut (result, "a", MSB24 - offl);
9802 MOVA (aopGet (left, MSB16, FALSE, FALSE, NULL));
9805 emitcode ("rrc", "a");
9808 aopPut (result, "a", MSB16 - offl);
9812 if (overlapping && offl==MSB16)
9814 emitcode ("xch", "a,%s", aopGet (left, LSB, FALSE, FALSE, DP2_RESULT_REG));
9818 aopPut (result, "a", MSB16 - offl);
9819 MOVA (aopGet (left, LSB, FALSE, FALSE, NULL));
9821 emitcode ("rrc", "a");
9822 aopPut (result, "a", LSB);
9826 /*-----------------------------------------------------------------*/
9827 /* genrshFour - shift four byte by a known amount != 0 */
9828 /*-----------------------------------------------------------------*/
9830 genrshFour (operand * result, operand * left,
9831 int shCount, int sign)
9833 D (emitcode (";", "genrshFour"));
9835 /* if shifting more that 3 bytes */
9839 _startLazyDPSEvaluation();
9841 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9843 movLeft2Result (left, MSB32, result, LSB, sign);
9844 addSign (result, MSB16, sign);
9845 _endLazyDPSEvaluation();
9847 else if (shCount >= 16)
9850 _startLazyDPSEvaluation();
9852 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9855 movLeft2Result (left, MSB24, result, LSB, 0);
9856 movLeft2Result (left, MSB32, result, MSB16, sign);
9858 addSign (result, MSB24, sign);
9859 _endLazyDPSEvaluation();
9861 else if (shCount >= 8)
9864 _startLazyDPSEvaluation();
9867 shiftRLong (left, MSB16, result, sign);
9869 else if (shCount == 0)
9871 movLeft2Result (left, MSB16, result, LSB, 0);
9872 movLeft2Result (left, MSB24, result, MSB16, 0);
9873 movLeft2Result (left, MSB32, result, MSB24, sign);
9874 addSign (result, MSB32, sign);
9878 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9879 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9880 /* the last shift is signed */
9881 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9882 addSign (result, MSB32, sign);
9884 _endLazyDPSEvaluation();
9888 /* 1 <= shCount <= 7 */
9891 shiftRLong (left, LSB, result, sign);
9893 shiftRLong (result, LSB, result, sign);
9897 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9898 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9899 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9904 #ifdef BETTER_LITERAL_SHIFT
9905 /*-----------------------------------------------------------------*/
9906 /* genRightShiftLiteral - right shifting by known count */
9907 /*-----------------------------------------------------------------*/
9909 genRightShiftLiteral (operand * left,
9915 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9918 size = getSize (operandType (result));
9920 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
9922 /* We only handle certain easy cases so far. */
9924 && (shCount < (size * 8))
9929 D(emitcode (";", "genRightShiftLiteral wimping out"););
9933 freeAsmop (right, NULL, ic, TRUE);
9935 aopOp (left, ic, FALSE, FALSE);
9936 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9939 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9943 /* test the LEFT size !!! */
9945 /* I suppose that the left size >= result size */
9948 size = getDataSize (result);
9949 _startLazyDPSEvaluation();
9951 movLeft2Result (left, size, result, size, 0);
9952 _endLazyDPSEvaluation();
9954 else if (shCount >= (size * 8))
9958 /* get sign in acc.7 */
9959 MOVA (aopGet (left, size - 1, FALSE, FALSE, NULL));
9961 addSign (result, LSB, sign);
9968 genrshOne (result, left, shCount, sign);
9972 genrshTwo (result, left, shCount, sign);
9976 genrshFour (result, left, shCount, sign);
9983 freeAsmop (result, NULL, ic, TRUE);
9984 freeAsmop (left, NULL, ic, TRUE);
9990 /*-----------------------------------------------------------------*/
9991 /* genSignedRightShift - right shift of signed number */
9992 /*-----------------------------------------------------------------*/
9994 genSignedRightShift (iCode * ic)
9996 operand *right, *left, *result;
9999 symbol *tlbl, *tlbl1;
10002 D (emitcode (";", "genSignedRightShift"));
10004 /* we do it the hard way put the shift count in b
10005 and loop thru preserving the sign */
10007 right = IC_RIGHT (ic);
10008 left = IC_LEFT (ic);
10009 result = IC_RESULT (ic);
10011 aopOp (right, ic, FALSE, FALSE);
10013 #ifdef BETTER_LITERAL_SHIFT
10014 if (AOP_TYPE (right) == AOP_LIT)
10016 if (genRightShiftLiteral (left, right, result, ic, 1))
10022 /* shift count is unknown then we have to form
10023 a loop get the loop count in B : Note: we take
10024 only the lower order byte since shifting
10025 more that 32 bits make no sense anyway, ( the
10026 largest size of an object can be only 32 bits ) */
10028 pushedB = pushB ();
10029 if (AOP_TYPE (right) == AOP_LIT)
10031 /* Really should be handled by genRightShiftLiteral,
10032 * but since I'm too lazy to fix that today, at least we can make
10033 * some small improvement.
10035 emitcode("mov", "b,#!constbyte",
10036 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
10040 MOVB (aopGet (right, 0, FALSE, FALSE, "b"));
10041 emitcode ("inc", "b");
10043 freeAsmop (right, NULL, ic, TRUE);
10044 aopOp (left, ic, FALSE, FALSE);
10045 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
10047 /* now move the left to the result if they are not the
10049 if (!sameRegs (AOP (left), AOP (result)) &&
10050 AOP_SIZE (result) > 1)
10053 size = AOP_SIZE (result);
10055 _startLazyDPSEvaluation ();
10058 l = aopGet (left, offset, FALSE, TRUE, NULL);
10059 if (*l == '@' && IS_AOP_PREG (result))
10062 emitcode ("mov", "a,%s", l);
10063 aopPut (result, "a", offset);
10066 aopPut (result, l, offset);
10069 _endLazyDPSEvaluation ();
10072 /* mov the highest order bit to OVR */
10073 tlbl = newiTempLabel (NULL);
10074 tlbl1 = newiTempLabel (NULL);
10076 size = AOP_SIZE (result);
10078 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
10079 emitcode ("rlc", "a");
10080 emitcode ("mov", "ov,c");
10081 /* if it is only one byte then */
10084 l = aopGet (left, 0, FALSE, FALSE, NULL);
10086 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
10088 emitcode ("mov", "c,ov");
10089 emitcode ("rrc", "a");
10091 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
10093 aopPut (result, "a", 0);
10097 reAdjustPreg (AOP (result));
10098 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
10100 emitcode ("mov", "c,ov");
10101 _startLazyDPSEvaluation ();
10104 l = aopGet (result, offset, FALSE, FALSE, NULL);
10106 emitcode ("rrc", "a");
10107 aopPut (result, "a", offset--);
10109 _endLazyDPSEvaluation ();
10110 reAdjustPreg (AOP (result));
10112 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
10116 freeAsmop (result, NULL, ic, TRUE);
10117 freeAsmop (left, NULL, ic, TRUE);
10120 /*-----------------------------------------------------------------*/
10121 /* genRightShift - generate code for right shifting */
10122 /*-----------------------------------------------------------------*/
10124 genRightShift (iCode * ic)
10126 operand *right, *left, *result;
10130 symbol *tlbl, *tlbl1;
10133 D (emitcode (";", "genRightShift"));
10135 /* if signed then we do it the hard way preserve the
10136 sign bit moving it inwards */
10137 letype = getSpec (operandType (IC_LEFT (ic)));
10139 if (!SPEC_USIGN (letype))
10141 genSignedRightShift (ic);
10145 /* signed & unsigned types are treated the same : i.e. the
10146 signed is NOT propagated inwards : quoting from the
10147 ANSI - standard : "for E1 >> E2, is equivalent to division
10148 by 2**E2 if unsigned or if it has a non-negative value,
10149 otherwise the result is implementation defined ", MY definition
10150 is that the sign does not get propagated */
10152 right = IC_RIGHT (ic);
10153 left = IC_LEFT (ic);
10154 result = IC_RESULT (ic);
10156 aopOp (right, ic, FALSE, FALSE);
10158 #ifdef BETTER_LITERAL_SHIFT
10159 /* if the shift count is known then do it
10160 as efficiently as possible */
10161 if (AOP_TYPE (right) == AOP_LIT)
10163 if (genRightShiftLiteral (left, right, result, ic, 0))
10170 /* shift count is unknown then we have to form
10171 a loop get the loop count in B : Note: we take
10172 only the lower order byte since shifting
10173 more that 32 bits make no sense anyway, ( the
10174 largest size of an object can be only 32 bits ) */
10176 pushedB = pushB ();
10177 if (AOP_TYPE (right) == AOP_LIT)
10179 /* Really should be handled by genRightShiftLiteral,
10180 * but since I'm too lazy to fix that today, at least we can make
10181 * some small improvement.
10183 emitcode("mov", "b,#!constbyte",
10184 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
10188 MOVB (aopGet (right, 0, FALSE, FALSE, "b"));
10189 emitcode ("inc", "b");
10191 freeAsmop (right, NULL, ic, TRUE);
10192 aopOp (left, ic, FALSE, FALSE);
10193 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
10195 /* now move the left to the result if they are not the
10197 if (!sameRegs (AOP (left), AOP (result)) &&
10198 AOP_SIZE (result) > 1)
10200 size = AOP_SIZE (result);
10202 _startLazyDPSEvaluation ();
10205 l = aopGet (left, offset, FALSE, TRUE, NULL);
10206 if (*l == '@' && IS_AOP_PREG (result))
10209 emitcode ("mov", "a,%s", l);
10210 aopPut (result, "a", offset);
10213 aopPut (result, l, offset);
10216 _endLazyDPSEvaluation ();
10219 tlbl = newiTempLabel (NULL);
10220 tlbl1 = newiTempLabel (NULL);
10221 size = AOP_SIZE (result);
10224 /* if it is only one byte then */
10227 l = aopGet (left, 0, FALSE, FALSE, NULL);
10229 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
10232 emitcode ("rrc", "a");
10234 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
10236 aopPut (result, "a", 0);
10240 reAdjustPreg (AOP (result));
10241 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
10244 _startLazyDPSEvaluation ();
10247 l = aopGet (result, offset, FALSE, FALSE, NULL);
10249 emitcode ("rrc", "a");
10250 aopPut (result, "a", offset--);
10252 _endLazyDPSEvaluation ();
10253 reAdjustPreg (AOP (result));
10256 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
10260 freeAsmop (result, NULL, ic, TRUE);
10261 freeAsmop (left, NULL, ic, TRUE);
10264 /*-----------------------------------------------------------------*/
10265 /* emitPtrByteGet - emits code to get a byte into A through a */
10266 /* pointer register (R0, R1, or DPTR). The */
10267 /* original value of A can be preserved in B. */
10268 /*-----------------------------------------------------------------*/
10270 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
10277 emitcode ("mov", "b,a");
10278 emitcode ("mov", "a,@%s", rname);
10283 emitcode ("mov", "b,a");
10284 emitcode ("movx", "a,@%s", rname);
10289 emitcode ("mov", "b,a");
10290 emitcode ("movx", "a,@dptr");
10295 emitcode ("mov", "b,a");
10296 emitcode ("clr", "a");
10297 emitcode ("movc", "a,@a+dptr");
10303 emitcode ("push", "b");
10304 emitcode ("push", "acc");
10306 emitcode ("lcall", "__gptrget");
10308 emitcode ("pop", "b");
10313 /*-----------------------------------------------------------------*/
10314 /* emitPtrByteSet - emits code to set a byte from src through a */
10315 /* pointer register (R0, R1, or DPTR). */
10316 /*-----------------------------------------------------------------*/
10318 emitPtrByteSet (char *rname, int p_type, char *src)
10327 emitcode ("mov", "@%s,a", rname);
10330 emitcode ("mov", "@%s,%s", rname, src);
10335 emitcode ("movx", "@%s,a", rname);
10340 emitcode ("movx", "@dptr,a");
10345 emitcode ("lcall", "__gptrput");
10350 /*-----------------------------------------------------------------*/
10351 /* genUnpackBits - generates code for unpacking bits */
10352 /*-----------------------------------------------------------------*/
10354 genUnpackBits (operand * result, char *rname, int ptype)
10356 int offset = 0; /* result byte offset */
10357 int rsize; /* result size */
10358 int rlen = 0; /* remaining bitfield length */
10359 sym_link *etype; /* bitfield type information */
10360 int blen; /* bitfield length */
10361 int bstr; /* bitfield starting bit within byte */
10363 D(emitcode ("; genUnpackBits",""));
10365 etype = getSpec (operandType (result));
10366 rsize = getSize (operandType (result));
10367 blen = SPEC_BLEN (etype);
10368 bstr = SPEC_BSTR (etype);
10370 /* If the bitfield length is less than a byte */
10373 emitPtrByteGet (rname, ptype, FALSE);
10375 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
10376 if (!SPEC_USIGN (etype))
10378 /* signed bitfield */
10379 symbol *tlbl = newiTempLabel (NULL);
10381 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
10382 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
10385 aopPut (result, "a", offset++);
10389 /* Bit field did not fit in a byte. Copy all
10390 but the partial byte at the end. */
10391 for (rlen=blen;rlen>=8;rlen-=8)
10393 emitPtrByteGet (rname, ptype, FALSE);
10394 aopPut (result, "a", offset++);
10396 emitcode ("inc", "%s", rname);
10399 /* Handle the partial byte at the end */
10402 emitPtrByteGet (rname, ptype, FALSE);
10403 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
10404 if (!SPEC_USIGN (etype))
10406 /* signed bitfield */
10407 symbol *tlbl = newiTempLabel (NULL);
10409 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
10410 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
10413 aopPut (result, "a", offset++);
10417 if (offset < rsize)
10421 if (SPEC_USIGN (etype))
10425 /* signed bitfield: sign extension with 0x00 or 0xff */
10426 emitcode ("rlc", "a");
10427 emitcode ("subb", "a,acc");
10433 aopPut (result, source, offset++);
10438 /*-----------------------------------------------------------------*/
10439 /* genDataPointerGet - generates code when ptr offset is known */
10440 /*-----------------------------------------------------------------*/
10442 genDataPointerGet (operand * left,
10448 int size, offset = 0;
10449 aopOp (result, ic, TRUE, FALSE);
10451 /* get the string representation of the name */
10452 l = aopGet (left, 0, FALSE, TRUE, NULL);
10453 size = AOP_SIZE (result);
10454 _startLazyDPSEvaluation ();
10459 SNPRINTF (buffer, sizeof(buffer),
10460 "(%s + %d)", l + 1, offset);
10464 SNPRINTF (buffer, sizeof(buffer),
10467 aopPut (result, buffer, offset++);
10469 _endLazyDPSEvaluation ();
10471 freeAsmop (result, NULL, ic, TRUE);
10472 freeAsmop (left, NULL, ic, TRUE);
10475 /*-----------------------------------------------------------------*/
10476 /* genNearPointerGet - emitcode for near pointer fetch */
10477 /*-----------------------------------------------------------------*/
10479 genNearPointerGet (operand * left,
10487 sym_link *rtype, *retype, *letype;
10488 sym_link *ltype = operandType (left);
10491 rtype = operandType (result);
10492 retype = getSpec (rtype);
10493 letype = getSpec (ltype);
10495 aopOp (left, ic, FALSE, FALSE);
10497 /* if left is rematerialisable and
10498 result is not bitfield variable type and
10499 the left is pointer to data space i.e
10500 lower 128 bytes of space */
10501 if (AOP_TYPE (left) == AOP_IMMD &&
10502 !IS_BITFIELD (retype) &&
10503 !IS_BITFIELD (letype) &&
10504 DCL_TYPE (ltype) == POINTER)
10506 genDataPointerGet (left, result, ic);
10510 /* if the value is already in a pointer register
10511 then don't need anything more */
10512 if (!AOP_INPREG (AOP (left)))
10514 /* otherwise get a free pointer register */
10515 aop = newAsmop (0);
10516 preg = getFreePtr (ic, &aop, FALSE);
10517 emitcode ("mov", "%s,%s",
10519 aopGet (left, 0, FALSE, TRUE, DP2_RESULT_REG));
10520 rname = preg->name;
10523 rname = aopGet (left, 0, FALSE, FALSE, DP2_RESULT_REG);
10525 freeAsmop (left, NULL, ic, TRUE);
10526 aopOp (result, ic, FALSE, FALSE);
10528 /* if bitfield then unpack the bits */
10529 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10530 genUnpackBits (result, rname, POINTER);
10533 /* we have can just get the values */
10534 int size = AOP_SIZE (result);
10539 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
10542 emitcode ("mov", "a,@%s", rname);
10543 aopPut (result, "a", offset);
10547 SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
10548 aopPut (result, buffer, offset);
10552 emitcode ("inc", "%s", rname);
10556 /* now some housekeeping stuff */
10557 if (aop) /* we had to allocate for this iCode */
10559 if (pi) { /* post increment present */
10560 aopPut (left, rname, 0);
10562 freeAsmop (NULL, aop, ic, TRUE);
10566 /* we did not allocate which means left
10567 already in a pointer register, then
10568 if size > 0 && this could be used again
10569 we have to point it back to where it
10571 if (AOP_SIZE (result) > 1 &&
10572 !OP_SYMBOL (left)->remat &&
10573 (OP_SYMBOL (left)->liveTo > ic->seq ||
10577 int size = AOP_SIZE (result) - 1;
10579 emitcode ("dec", "%s", rname);
10584 freeAsmop (result, NULL, ic, TRUE);
10585 if (pi) pi->generated = 1;
10588 /*-----------------------------------------------------------------*/
10589 /* genPagedPointerGet - emitcode for paged pointer fetch */
10590 /*-----------------------------------------------------------------*/
10592 genPagedPointerGet (operand * left,
10600 sym_link *rtype, *retype, *letype;
10602 rtype = operandType (result);
10603 retype = getSpec (rtype);
10604 letype = getSpec (operandType (left));
10605 aopOp (left, ic, FALSE, FALSE);
10607 /* if the value is already in a pointer register
10608 then don't need anything more */
10609 if (!AOP_INPREG (AOP (left)))
10611 /* otherwise get a free pointer register */
10612 aop = newAsmop (0);
10613 preg = getFreePtr (ic, &aop, FALSE);
10614 emitcode ("mov", "%s,%s",
10616 aopGet (left, 0, FALSE, TRUE, NULL));
10617 rname = preg->name;
10620 rname = aopGet (left, 0, FALSE, FALSE, NULL);
10622 freeAsmop (left, NULL, ic, TRUE);
10623 aopOp (result, ic, FALSE, FALSE);
10625 /* if bitfield then unpack the bits */
10626 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10627 genUnpackBits (result, rname, PPOINTER);
10630 /* we have can just get the values */
10631 int size = AOP_SIZE (result);
10637 emitcode ("movx", "a,@%s", rname);
10638 aopPut (result, "a", offset);
10643 emitcode ("inc", "%s", rname);
10647 /* now some housekeeping stuff */
10648 if (aop) /* we had to allocate for this iCode */
10651 aopPut (left, rname, 0);
10652 freeAsmop (NULL, aop, ic, TRUE);
10656 /* we did not allocate which means left
10657 already in a pointer register, then
10658 if size > 0 && this could be used again
10659 we have to point it back to where it
10661 if (AOP_SIZE (result) > 1 &&
10662 !OP_SYMBOL (left)->remat &&
10663 (OP_SYMBOL (left)->liveTo > ic->seq ||
10667 int size = AOP_SIZE (result) - 1;
10669 emitcode ("dec", "%s", rname);
10674 freeAsmop (result, NULL, ic, TRUE);
10675 if (pi) pi->generated = 1;
10678 /*-----------------------------------------------------------------*/
10679 /* genFarPointerGet - get value from far space */
10680 /*-----------------------------------------------------------------*/
10682 genFarPointerGet (operand * left,
10683 operand * result, iCode * ic, iCode *pi)
10685 int size, offset, dopi=1;
10686 sym_link *retype = getSpec (operandType (result));
10687 sym_link *letype = getSpec (operandType (left));
10688 D (emitcode (";", "genFarPointerGet"););
10690 aopOp (left, ic, FALSE, FALSE);
10692 /* if the operand is already in dptr
10693 then we do nothing else we move the value to dptr */
10694 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
10696 /* if this is rematerializable */
10697 if (AOP_TYPE (left) == AOP_IMMD)
10699 emitcode ("mov", "dptr,%s", aopGet (left, 0, TRUE, FALSE, NULL));
10703 /* we need to get it byte by byte */
10704 _startLazyDPSEvaluation ();
10705 if (AOP_TYPE (left) != AOP_DPTR)
10707 emitcode ("mov", "dpl,%s", aopGet (left, 0, FALSE, FALSE, NULL));
10708 emitcode ("mov", "dph,%s", aopGet (left, 1, FALSE, FALSE, NULL));
10709 if (options.model == MODEL_FLAT24)
10710 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10714 /* We need to generate a load to DPTR indirect through DPTR. */
10715 D (emitcode (";", "genFarPointerGet -- indirection special case."););
10716 emitcode ("push", "%s", aopGet (left, 0, FALSE, TRUE, NULL));
10717 emitcode ("push", "%s", aopGet (left, 1, FALSE, TRUE, NULL));
10718 if (options.model == MODEL_FLAT24)
10719 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10720 emitcode ("pop", "dph");
10721 emitcode ("pop", "dpl");
10724 _endLazyDPSEvaluation ();
10727 /* so dptr now contains the address */
10728 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10730 /* if bit then unpack */
10731 if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
10732 if (AOP_INDPTRn(left)) {
10733 genSetDPTR(AOP(left)->aopu.dptr);
10735 genUnpackBits (result, "dptr", FPOINTER);
10736 if (AOP_INDPTRn(left)) {
10741 size = AOP_SIZE (result);
10744 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10746 genSetDPTR(AOP(left)->aopu.dptr);
10747 emitcode ("movx", "a,@dptr");
10748 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10749 emitcode ("inc", "dptr");
10751 aopPut (result, "a", offset++);
10754 _startLazyDPSEvaluation ();
10756 if (AOP_INDPTRn(left)) {
10757 genSetDPTR(AOP(left)->aopu.dptr);
10763 emitcode ("movx", "a,@dptr");
10764 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10765 emitcode ("inc", "dptr");
10767 aopPut (result, "a", offset++);
10769 _endLazyDPSEvaluation ();
10772 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10773 if (!AOP_INDPTRn(left)) {
10774 _startLazyDPSEvaluation ();
10775 aopPut (left, "dpl", 0);
10776 aopPut (left, "dph", 1);
10777 if (options.model == MODEL_FLAT24)
10778 aopPut (left, "dpx", 2);
10779 _endLazyDPSEvaluation ();
10782 } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) &&
10783 AOP_SIZE(result) > 1 &&
10785 (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
10787 size = AOP_SIZE (result) - 1;
10788 if (AOP_INDPTRn(left)) {
10789 genSetDPTR(AOP(left)->aopu.dptr);
10791 while (size--) emitcode ("lcall","__decdptr");
10792 if (AOP_INDPTRn(left)) {
10797 freeAsmop (result, NULL, ic, TRUE);
10798 freeAsmop (left, NULL, ic, TRUE);
10801 /*-----------------------------------------------------------------*/
10802 /* genCodePointerGet - get value from code space */
10803 /*-----------------------------------------------------------------*/
10805 genCodePointerGet (operand * left,
10806 operand * result, iCode * ic, iCode *pi)
10808 int size, offset, dopi=1;
10809 sym_link *retype = getSpec (operandType (result));
10811 aopOp (left, ic, FALSE, FALSE);
10813 /* if the operand is already in dptr
10814 then we do nothing else we move the value to dptr */
10815 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
10817 /* if this is rematerializable */
10818 if (AOP_TYPE (left) == AOP_IMMD)
10820 emitcode ("mov", "dptr,%s", aopGet (left, 0, TRUE, FALSE, NULL));
10823 { /* we need to get it byte by byte */
10824 _startLazyDPSEvaluation ();
10825 if (AOP_TYPE (left) != AOP_DPTR)
10827 emitcode ("mov", "dpl,%s", aopGet (left, 0, FALSE, FALSE, NULL));
10828 emitcode ("mov", "dph,%s", aopGet (left, 1, FALSE, FALSE, NULL));
10829 if (options.model == MODEL_FLAT24)
10830 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10834 /* We need to generate a load to DPTR indirect through DPTR. */
10835 D (emitcode (";", "gencodePointerGet -- indirection special case."););
10836 emitcode ("push", "%s", aopGet (left, 0, FALSE, TRUE, NULL));
10837 emitcode ("push", "%s", aopGet (left, 1, FALSE, TRUE, NULL));
10838 if (options.model == MODEL_FLAT24)
10839 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10840 emitcode ("pop", "dph");
10841 emitcode ("pop", "dpl");
10844 _endLazyDPSEvaluation ();
10847 /* so dptr now contains the address */
10848 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10850 /* if bit then unpack */
10851 if (IS_BITFIELD (retype)) {
10852 if (AOP_INDPTRn(left)) {
10853 genSetDPTR(AOP(left)->aopu.dptr);
10855 genUnpackBits (result, "dptr", CPOINTER);
10856 if (AOP_INDPTRn(left)) {
10861 size = AOP_SIZE (result);
10863 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10865 genSetDPTR(AOP(left)->aopu.dptr);
10866 emitcode ("clr", "a");
10867 emitcode ("movc", "a,@a+dptr");
10868 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10869 emitcode ("inc", "dptr");
10871 aopPut (result, "a", offset++);
10874 _startLazyDPSEvaluation ();
10877 if (AOP_INDPTRn(left)) {
10878 genSetDPTR(AOP(left)->aopu.dptr);
10884 emitcode ("clr", "a");
10885 emitcode ("movc", "a,@a+dptr");
10886 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10887 emitcode ("inc", "dptr");
10888 aopPut (result, "a", offset++);
10890 _endLazyDPSEvaluation ();
10893 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10894 if (!AOP_INDPTRn(left)) {
10895 _startLazyDPSEvaluation ();
10897 aopPut (left, "dpl", 0);
10898 aopPut (left, "dph", 1);
10899 if (options.model == MODEL_FLAT24)
10900 aopPut (left, "dpx", 2);
10902 _endLazyDPSEvaluation ();
10905 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
10906 AOP_SIZE(result) > 1 &&
10907 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10909 size = AOP_SIZE (result) - 1;
10910 if (AOP_INDPTRn(left)) {
10911 genSetDPTR(AOP(left)->aopu.dptr);
10913 while (size--) emitcode ("lcall","__decdptr");
10914 if (AOP_INDPTRn(left)) {
10919 freeAsmop (result, NULL, ic, TRUE);
10920 freeAsmop (left, NULL, ic, TRUE);
10923 /*-----------------------------------------------------------------*/
10924 /* genGenPointerGet - get value from generic pointer space */
10925 /*-----------------------------------------------------------------*/
10927 genGenPointerGet (operand * left,
10928 operand * result, iCode * ic, iCode * pi)
10932 sym_link *retype = getSpec (operandType (result));
10933 sym_link *letype = getSpec (operandType (left));
10935 D (emitcode (";", "genGenPointerGet"));
10937 aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
10939 pushedB = pushB ();
10940 /* if the operand is already in dptr
10941 then we do nothing else we move the value to dptr */
10942 if (AOP_TYPE (left) != AOP_STR)
10944 /* if this is rematerializable */
10945 if (AOP_TYPE (left) == AOP_IMMD)
10947 emitcode ("mov", "dptr,%s", aopGet (left, 0, TRUE, FALSE, NULL));
10948 if (AOP(left)->aopu.aop_immd.from_cast_remat)
10950 MOVB (aopGet (left, AOP_SIZE(left)-1, FALSE, FALSE, NULL));
10954 emitcode ("mov", "b,#%d", pointerCode (retype));
10958 { /* we need to get it byte by byte */
10959 _startLazyDPSEvaluation ();
10960 emitcode ("mov", "dpl,%s", aopGet (left,0,FALSE,FALSE,NULL));
10961 emitcode ("mov", "dph,%s", aopGet (left,1,FALSE,FALSE,NULL));
10962 if (options.model == MODEL_FLAT24) {
10963 emitcode ("mov", "dpx,%s", aopGet (left,2,FALSE,FALSE,NULL));
10964 emitcode ("mov", "b,%s", aopGet (left,3,FALSE,FALSE,NULL));
10966 emitcode ("mov", "b,%s", aopGet (left,2,FALSE,FALSE,NULL));
10968 _endLazyDPSEvaluation ();
10972 /* so dptr-b now contains the address */
10973 aopOp (result, ic, FALSE, TRUE);
10975 /* if bit then unpack */
10976 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10978 genUnpackBits (result, "dptr", GPOINTER);
10982 size = AOP_SIZE (result);
10989 // Get two bytes at a time, results in _AP & A.
10990 // dptr will be incremented ONCE by __gptrgetWord.
10992 // Note: any change here must be coordinated
10993 // with the implementation of __gptrgetWord
10994 // in device/lib/_gptrget.c
10995 emitcode ("lcall", "__gptrgetWord");
10996 aopPut (result, DP2_RESULT_REG, offset++);
10997 aopPut (result, "a", offset++);
11002 // Only one byte to get.
11003 emitcode ("lcall", "__gptrget");
11004 aopPut (result, "a", offset++);
11007 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
11009 emitcode ("inc", "dptr");
11014 if (pi && AOP_TYPE (left) != AOP_IMMD) {
11015 _startLazyDPSEvaluation ();
11017 aopPut (left, "dpl", 0);
11018 aopPut (left, "dph", 1);
11019 if (options.model == MODEL_FLAT24) {
11020 aopPut (left, "dpx", 2);
11021 aopPut (left, "b", 3);
11022 } else aopPut (left, "b", 2);
11024 _endLazyDPSEvaluation ();
11027 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
11028 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
11030 size = AOP_SIZE (result) - 1;
11031 while (size--) emitcode ("lcall","__decdptr");
11035 freeAsmop (result, NULL, ic, TRUE);
11036 freeAsmop (left, NULL, ic, TRUE);
11039 /*-----------------------------------------------------------------*/
11040 /* genPointerGet - generate code for pointer get */
11041 /*-----------------------------------------------------------------*/
11043 genPointerGet (iCode * ic, iCode *pi)
11045 operand *left, *result;
11046 sym_link *type, *etype;
11049 D (emitcode (";", "genPointerGet"));
11051 left = IC_LEFT (ic);
11052 result = IC_RESULT (ic);
11054 /* depending on the type of pointer we need to
11055 move it to the correct pointer register */
11056 type = operandType (left);
11057 etype = getSpec (type);
11058 /* if left is of type of pointer then it is simple */
11059 if (IS_PTR (type) && !IS_FUNC (type->next))
11060 p_type = DCL_TYPE (type);
11063 /* we have to go by the storage class */
11064 p_type = PTR_TYPE (SPEC_OCLS (etype));
11067 /* special case when cast remat */
11068 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
11069 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
11071 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
11072 type = operandType (left);
11073 p_type = DCL_TYPE (type);
11075 /* now that we have the pointer type we assign
11076 the pointer values */
11082 genNearPointerGet (left, result, ic, pi);
11086 genPagedPointerGet (left, result, ic, pi);
11090 genFarPointerGet (left, result, ic, pi);
11094 genCodePointerGet (left, result, ic, pi);
11098 genGenPointerGet (left, result, ic, pi);
11104 /*-----------------------------------------------------------------*/
11105 /* genPackBits - generates code for packed bit storage */
11106 /*-----------------------------------------------------------------*/
11108 genPackBits (sym_link * etype,
11110 char *rname, int p_type)
11112 int offset = 0; /* source byte offset */
11113 int rlen = 0; /* remaining bitfield length */
11114 int blen; /* bitfield length */
11115 int bstr; /* bitfield starting bit within byte */
11116 int litval; /* source literal value (if AOP_LIT) */
11117 unsigned char mask; /* bitmask within current byte */
11119 D(emitcode ("; genPackBits",""));
11121 blen = SPEC_BLEN (etype);
11122 bstr = SPEC_BSTR (etype);
11124 /* If the bitfield length is less than a byte */
11127 mask = ((unsigned char) (0xFF << (blen + bstr)) |
11128 (unsigned char) (0xFF >> (8 - bstr)));
11130 if (AOP_TYPE (right) == AOP_LIT)
11132 /* Case with a bitfield length <8 and literal source
11134 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
11136 litval &= (~mask) & 0xff;
11137 emitPtrByteGet (rname, p_type, FALSE);
11138 if ((mask|litval)!=0xff)
11139 emitcode ("anl","a,#!constbyte", mask);
11141 emitcode ("orl","a,#!constbyte", litval);
11145 if ((blen==1) && (p_type!=GPOINTER))
11147 /* Case with a bitfield length == 1 and no generic pointer
11149 if (AOP_TYPE (right) == AOP_CRY)
11150 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
11153 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
11154 emitcode ("rrc","a");
11156 emitPtrByteGet (rname, p_type, FALSE);
11157 emitcode ("mov","acc.%d,c",bstr);
11162 /* Case with a bitfield length < 8 and arbitrary source
11164 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
11165 /* shift and mask source value */
11167 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
11169 pushedB = pushB ();
11170 /* transfer A to B and get next byte */
11171 emitPtrByteGet (rname, p_type, TRUE);
11173 emitcode ("anl", "a,#!constbyte", mask);
11174 emitcode ("orl", "a,b");
11175 if (p_type == GPOINTER)
11176 emitcode ("pop", "b");
11182 emitPtrByteSet (rname, p_type, "a");
11186 /* Bit length is greater than 7 bits. In this case, copy */
11187 /* all except the partial byte at the end */
11188 for (rlen=blen;rlen>=8;rlen-=8)
11190 emitPtrByteSet (rname, p_type,
11191 aopGet (right, offset++, FALSE, TRUE, NULL) );
11193 emitcode ("inc", "%s", rname);
11196 /* If there was a partial byte at the end */
11199 mask = (((unsigned char) -1 << rlen) & 0xff);
11201 if (AOP_TYPE (right) == AOP_LIT)
11203 /* Case with partial byte and literal source
11205 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
11206 litval >>= (blen-rlen);
11207 litval &= (~mask) & 0xff;
11208 emitPtrByteGet (rname, p_type, FALSE);
11209 if ((mask|litval)!=0xff)
11210 emitcode ("anl","a,#!constbyte", mask);
11212 emitcode ("orl","a,#!constbyte", litval);
11217 /* Case with partial byte and arbitrary source
11219 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11220 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
11222 pushedB = pushB ();
11223 /* transfer A to B and get next byte */
11224 emitPtrByteGet (rname, p_type, TRUE);
11226 emitcode ("anl", "a,#!constbyte", mask);
11227 emitcode ("orl", "a,b");
11228 if (p_type == GPOINTER)
11229 emitcode ("pop", "b");
11233 emitPtrByteSet (rname, p_type, "a");
11238 /*-----------------------------------------------------------------*/
11239 /* genDataPointerSet - remat pointer to data space */
11240 /*-----------------------------------------------------------------*/
11242 genDataPointerSet (operand * right,
11246 int size, offset = 0;
11247 char *l, buffer[256];
11249 D (emitcode (";", "genDataPointerSet"));
11251 aopOp (right, ic, FALSE, FALSE);
11253 l = aopGet (result, 0, FALSE, TRUE, NULL);
11254 size = AOP_SIZE (right);
11258 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l + 1, offset);
11260 SNPRINTF (buffer, sizeof(buffer), "%s", l + 1);
11261 emitcode ("mov", "%s,%s", buffer,
11262 aopGet (right, offset++, FALSE, FALSE, NULL));
11265 freeAsmop (result, NULL, ic, TRUE);
11266 freeAsmop (right, NULL, ic, TRUE);
11269 /*-----------------------------------------------------------------*/
11270 /* genNearPointerSet - emitcode for near pointer put */
11271 /*-----------------------------------------------------------------*/
11273 genNearPointerSet (operand * right,
11280 sym_link *retype, *letype;
11281 sym_link *ptype = operandType (result);
11283 D (emitcode (";", "genNearPointerSet"));
11285 retype = getSpec (operandType (right));
11286 letype = getSpec (ptype);
11288 aopOp (result, ic, FALSE, FALSE);
11290 /* if the result is rematerializable &
11291 in data space & not a bit variable */
11292 if (AOP_TYPE (result) == AOP_IMMD &&
11293 DCL_TYPE (ptype) == POINTER &&
11294 !IS_BITVAR (retype) &&
11295 !IS_BITVAR (letype))
11297 genDataPointerSet (right, result, ic);
11301 /* if the value is already in a pointer register
11302 then don't need anything more */
11303 if (!AOP_INPREG (AOP (result)))
11305 /* otherwise get a free pointer register */
11308 aop = newAsmop (0);
11309 preg = getFreePtr (ic, &aop, FALSE);
11310 emitcode ("mov", "%s,%s",
11312 aopGet (result, 0, FALSE, TRUE, NULL));
11313 rname = preg->name;
11317 rname = aopGet (result, 0, FALSE, FALSE, NULL);
11320 aopOp (right, ic, FALSE, FALSE);
11322 /* if bitfield then unpack the bits */
11323 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11324 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
11327 /* we can just get the values */
11328 int size = AOP_SIZE (right);
11333 l = aopGet (right, offset, FALSE, TRUE, NULL);
11334 if ((*l == '@') || (strcmp (l, "acc") == 0))
11337 emitcode ("mov", "@%s,a", rname);
11340 emitcode ("mov", "@%s,%s", rname, l);
11342 emitcode ("inc", "%s", rname);
11347 /* now some housekeeping stuff */
11348 if (aop) /* we had to allocate for this iCode */
11351 aopPut (result, rname, 0);
11352 freeAsmop (NULL, aop, ic, TRUE);
11356 /* we did not allocate which means left
11357 already in a pointer register, then
11358 if size > 0 && this could be used again
11359 we have to point it back to where it
11361 if (AOP_SIZE (right) > 1 &&
11362 !OP_SYMBOL (result)->remat &&
11363 (OP_SYMBOL (result)->liveTo > ic->seq ||
11367 int size = AOP_SIZE (right) - 1;
11369 emitcode ("dec", "%s", rname);
11374 if (pi) pi->generated = 1;
11375 freeAsmop (result, NULL, ic, TRUE);
11376 freeAsmop (right, NULL, ic, TRUE);
11379 /*-----------------------------------------------------------------*/
11380 /* genPagedPointerSet - emitcode for Paged pointer put */
11381 /*-----------------------------------------------------------------*/
11383 genPagedPointerSet (operand * right,
11390 sym_link *retype, *letype;
11392 D (emitcode (";", "genPagedPointerSet"));
11394 retype = getSpec (operandType (right));
11395 letype = getSpec (operandType (result));
11397 aopOp (result, ic, FALSE, FALSE);
11399 /* if the value is already in a pointer register
11400 then don't need anything more */
11401 if (!AOP_INPREG (AOP (result)))
11403 /* otherwise get a free pointer register */
11406 aop = newAsmop (0);
11407 preg = getFreePtr (ic, &aop, FALSE);
11408 emitcode ("mov", "%s,%s",
11410 aopGet (result, 0, FALSE, TRUE, NULL));
11411 rname = preg->name;
11414 rname = aopGet (result, 0, FALSE, FALSE, NULL);
11416 aopOp (right, ic, FALSE, FALSE);
11418 /* if bitfield then unpack the bits */
11419 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11420 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
11423 /* we have can just get the values */
11424 int size = AOP_SIZE (right);
11429 l = aopGet (right, offset, FALSE, TRUE, NULL);
11431 emitcode ("movx", "@%s,a", rname);
11434 emitcode ("inc", "%s", rname);
11440 /* now some housekeeping stuff */
11444 aopPut (result, rname, 0);
11445 /* we had to allocate for this iCode */
11446 freeAsmop (NULL, aop, ic, TRUE);
11450 /* we did not allocate which means left
11451 already in a pointer register, then
11452 if size > 0 && this could be used again
11453 we have to point it back to where it
11455 if (AOP_SIZE (right) > 1 &&
11456 !OP_SYMBOL (result)->remat &&
11457 (OP_SYMBOL (result)->liveTo > ic->seq ||
11461 int size = AOP_SIZE (right) - 1;
11463 emitcode ("dec", "%s", rname);
11468 if (pi) pi->generated = 1;
11469 freeAsmop (result, NULL, ic, TRUE);
11470 freeAsmop (right, NULL, ic, TRUE);
11473 /*-----------------------------------------------------------------*/
11474 /* genFarPointerSet - set value from far space */
11475 /*-----------------------------------------------------------------*/
11477 genFarPointerSet (operand * right,
11478 operand * result, iCode * ic, iCode *pi)
11480 int size, offset, dopi=1;
11481 sym_link *retype = getSpec (operandType (right));
11482 sym_link *letype = getSpec (operandType (result));
11484 aopOp (result, ic, FALSE, FALSE);
11486 /* if the operand is already in dptr
11487 then we do nothing else we move the value to dptr */
11488 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
11490 /* if this is remateriazable */
11491 if (AOP_TYPE (result) == AOP_IMMD)
11492 emitcode ("mov", "dptr,%s",
11493 aopGet (result, 0, TRUE, FALSE, NULL));
11496 /* we need to get it byte by byte */
11497 _startLazyDPSEvaluation ();
11498 if (AOP_TYPE (result) != AOP_DPTR)
11500 emitcode ("mov", "dpl,%s", aopGet (result, 0, FALSE, FALSE, NULL));
11501 emitcode ("mov", "dph,%s", aopGet (result, 1, FALSE, FALSE, NULL));
11502 if (options.model == MODEL_FLAT24)
11503 emitcode ("mov", "dpx,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11507 /* We need to generate a load to DPTR indirect through DPTR. */
11508 D (emitcode (";", "genFarPointerSet -- indirection special case."););
11510 emitcode ("push", "%s", aopGet (result, 0, FALSE, TRUE, NULL));
11511 emitcode ("push", "%s", aopGet (result, 1, FALSE, TRUE, NULL));
11512 if (options.model == MODEL_FLAT24)
11513 emitcode ("mov", "dpx,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11514 emitcode ("pop", "dph");
11515 emitcode ("pop", "dpl");
11518 _endLazyDPSEvaluation ();
11521 /* so dptr now contains the address */
11522 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
11524 /* if bit then unpack */
11525 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11527 if (AOP_INDPTRn(result)) {
11528 genSetDPTR(AOP(result)->aopu.dptr);
11530 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
11531 if (AOP_INDPTRn(result)) {
11535 size = AOP_SIZE (right);
11537 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
11539 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11541 genSetDPTR(AOP(result)->aopu.dptr);
11542 emitcode ("movx", "@dptr,a");
11543 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
11544 emitcode ("inc", "dptr");
11548 _startLazyDPSEvaluation ();
11550 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11552 if (AOP_INDPTRn(result)) {
11553 genSetDPTR(AOP(result)->aopu.dptr);
11559 emitcode ("movx", "@dptr,a");
11560 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
11561 emitcode ("inc", "dptr");
11563 _endLazyDPSEvaluation ();
11567 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
11568 if (!AOP_INDPTRn(result)) {
11569 _startLazyDPSEvaluation ();
11571 aopPut (result,"dpl",0);
11572 aopPut (result,"dph",1);
11573 if (options.model == MODEL_FLAT24)
11574 aopPut (result,"dpx",2);
11576 _endLazyDPSEvaluation ();
11579 } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
11580 AOP_SIZE(right) > 1 &&
11581 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
11583 size = AOP_SIZE (right) - 1;
11584 if (AOP_INDPTRn(result)) {
11585 genSetDPTR(AOP(result)->aopu.dptr);
11587 while (size--) emitcode ("lcall","__decdptr");
11588 if (AOP_INDPTRn(result)) {
11592 freeAsmop (result, NULL, ic, TRUE);
11593 freeAsmop (right, NULL, ic, TRUE);
11596 /*-----------------------------------------------------------------*/
11597 /* genGenPointerSet - set value from generic pointer space */
11598 /*-----------------------------------------------------------------*/
11600 genGenPointerSet (operand * right,
11601 operand * result, iCode * ic, iCode *pi)
11605 sym_link *retype = getSpec (operandType (right));
11606 sym_link *letype = getSpec (operandType (result));
11608 aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
11610 pushedB = pushB ();
11611 /* if the operand is already in dptr
11612 then we do nothing else we move the value to dptr */
11613 if (AOP_TYPE (result) != AOP_STR)
11615 _startLazyDPSEvaluation ();
11616 /* if this is remateriazable */
11617 if (AOP_TYPE (result) == AOP_IMMD)
11619 emitcode ("mov", "dptr,%s", aopGet (result, 0, TRUE, FALSE, NULL));
11620 if (AOP(result)->aopu.aop_immd.from_cast_remat)
11622 MOVB (aopGet (result, AOP_SIZE(result)-1, FALSE, FALSE, NULL));
11627 "b,%s + 1", aopGet (result, 0, TRUE, FALSE, NULL));
11631 { /* we need to get it byte by byte */
11632 emitcode ("mov", "dpl,%s", aopGet (result, 0, FALSE, FALSE, NULL));
11633 emitcode ("mov", "dph,%s", aopGet (result, 1, FALSE, FALSE, NULL));
11634 if (options.model == MODEL_FLAT24) {
11635 emitcode ("mov", "dpx,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11636 emitcode ("mov", "b,%s", aopGet (result, 3, FALSE, FALSE, NULL));
11638 emitcode ("mov", "b,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11641 _endLazyDPSEvaluation ();
11643 /* so dptr + b now contains the address */
11644 aopOp (right, ic, FALSE, TRUE);
11646 /* if bit then unpack */
11647 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11649 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
11653 size = AOP_SIZE (right);
11656 _startLazyDPSEvaluation ();
11661 // Set two bytes at a time, passed in _AP & A.
11662 // dptr will be incremented ONCE by __gptrputWord.
11664 // Note: any change here must be coordinated
11665 // with the implementation of __gptrputWord
11666 // in device/lib/_gptrput.c
11667 emitcode("mov", "_ap, %s",
11668 aopGet (right, offset++, FALSE, FALSE, NULL));
11669 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11673 emitcode ("lcall", "__gptrputWord");
11678 // Only one byte to put.
11679 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11683 emitcode ("lcall", "__gptrput");
11686 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
11688 emitcode ("inc", "dptr");
11691 _endLazyDPSEvaluation ();
11694 if (pi && AOP_TYPE (result) != AOP_IMMD) {
11695 _startLazyDPSEvaluation ();
11697 aopPut (result, "dpl",0);
11698 aopPut (result, "dph",1);
11699 if (options.model == MODEL_FLAT24) {
11700 aopPut (result, "dpx",2);
11701 aopPut (result, "b",3);
11703 aopPut (result, "b",2);
11705 _endLazyDPSEvaluation ();
11708 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
11709 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
11711 size = AOP_SIZE (right) - 1;
11712 while (size--) emitcode ("lcall","__decdptr");
11716 freeAsmop (result, NULL, ic, TRUE);
11717 freeAsmop (right, NULL, ic, TRUE);
11720 /*-----------------------------------------------------------------*/
11721 /* genPointerSet - stores the value into a pointer location */
11722 /*-----------------------------------------------------------------*/
11724 genPointerSet (iCode * ic, iCode *pi)
11726 operand *right, *result;
11727 sym_link *type, *etype;
11730 D (emitcode (";", "genPointerSet"));
11732 right = IC_RIGHT (ic);
11733 result = IC_RESULT (ic);
11735 /* depending on the type of pointer we need to
11736 move it to the correct pointer register */
11737 type = operandType (result);
11738 etype = getSpec (type);
11739 /* if left is of type of pointer then it is simple */
11740 if (IS_PTR (type) && !IS_FUNC (type->next))
11742 p_type = DCL_TYPE (type);
11746 /* we have to go by the storage class */
11747 p_type = PTR_TYPE (SPEC_OCLS (etype));
11750 /* special case when cast remat */
11751 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
11752 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
11753 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
11754 type = operandType (result);
11755 p_type = DCL_TYPE (type);
11758 /* now that we have the pointer type we assign
11759 the pointer values */
11765 genNearPointerSet (right, result, ic, pi);
11769 genPagedPointerSet (right, result, ic, pi);
11773 genFarPointerSet (right, result, ic, pi);
11777 genGenPointerSet (right, result, ic, pi);
11781 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11782 "genPointerSet: illegal pointer type");
11786 /*-----------------------------------------------------------------*/
11787 /* genIfx - generate code for Ifx statement */
11788 /*-----------------------------------------------------------------*/
11790 genIfx (iCode * ic, iCode * popIc)
11792 operand *cond = IC_COND (ic);
11796 D (emitcode (";", "genIfx"));
11798 aopOp (cond, ic, FALSE, FALSE);
11800 /* get the value into acc */
11801 if (AOP_TYPE (cond) != AOP_CRY)
11808 if (AOP(cond)->aopu.aop_dir)
11809 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
11812 /* the result is now in the accumulator or a directly addressable bit */
11813 freeAsmop (cond, NULL, ic, TRUE);
11815 /* if there was something to be popped then do it */
11819 /* if the condition is a bit variable */
11821 genIfxJump (ic, dup);
11822 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
11823 genIfxJump (ic, SPIL_LOC (cond)->rname);
11824 else if (isbit && !IS_ITEMP (cond))
11825 genIfxJump (ic, OP_SYMBOL (cond)->rname);
11827 genIfxJump (ic, "a");
11832 /*-----------------------------------------------------------------*/
11833 /* genAddrOf - generates code for address of */
11834 /*-----------------------------------------------------------------*/
11836 genAddrOf (iCode * ic)
11838 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
11841 D (emitcode (";", "genAddrOf"));
11843 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11845 /* if the operand is on the stack then we
11846 need to get the stack offset of this
11851 /* if 10 bit stack */
11852 if (options.stack10bit) {
11856 tsprintf(buff, sizeof(buff),
11857 "#!constbyte",(options.stack_loc >> 16) & 0xff);
11858 /* if it has an offset then we need to compute it */
11859 /* emitcode ("subb", "a,#!constbyte", */
11860 /* -((sym->stack < 0) ? */
11861 /* ((short) (sym->stack - _G.nRegsSaved)) : */
11862 /* ((short) sym->stack)) & 0xff); */
11863 /* emitcode ("mov","b,a"); */
11864 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
11865 /* ((short) (sym->stack - _G.nRegsSaved)) : */
11866 /* ((short) sym->stack)) >> 8) & 0xff); */
11868 emitcode ("mov", "a,_bpx");
11869 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
11870 ((char) (sym->stack - _G.nRegsSaved)) :
11871 ((char) sym->stack )) & 0xff);
11872 emitcode ("mov", "b,a");
11873 emitcode ("mov", "a,_bpx+1");
11875 offset = (((sym->stack < 0) ?
11876 ((short) (sym->stack - _G.nRegsSaved)) :
11877 ((short) sym->stack )) >> 8) & 0xff;
11879 emitcode ("addc","a,#!constbyte", offset);
11881 aopPut (IC_RESULT (ic), "b", 0);
11882 aopPut (IC_RESULT (ic), "a", 1);
11883 aopPut (IC_RESULT (ic), buff, 2);
11885 /* we can just move _bp */
11886 aopPut (IC_RESULT (ic), "_bpx", 0);
11887 aopPut (IC_RESULT (ic), "_bpx+1", 1);
11888 aopPut (IC_RESULT (ic), buff, 2);
11891 /* if it has an offset then we need to compute it */
11894 emitcode ("mov", "a,_bp");
11895 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
11896 aopPut (IC_RESULT (ic), "a", 0);
11900 /* we can just move _bp */
11901 aopPut (IC_RESULT (ic), "_bp", 0);
11903 /* fill the result with zero */
11904 size = AOP_SIZE (IC_RESULT (ic)) - 1;
11907 if (options.stack10bit && size < (FPTRSIZE - 1)) {
11909 "*** warning: pointer to stack var truncated.\n");
11915 aopPut (IC_RESULT (ic), zero, offset++);
11921 /* object not on stack then we need the name */
11922 size = AOP_SIZE (IC_RESULT (ic));
11927 char s[SDCC_NAME_MAX];
11931 tsprintf(s, sizeof(s), "#!his",sym->rname);
11934 tsprintf(s, sizeof(s), "#!hihis",sym->rname);
11937 tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
11939 default: /* should not need this (just in case) */
11940 SNPRINTF (s, sizeof(s), "#(%s >> %d)",
11947 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11950 aopPut (IC_RESULT (ic), s, offset++);
11954 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11958 #if 0 // obsolete, and buggy for != xdata
11959 /*-----------------------------------------------------------------*/
11960 /* genArrayInit - generates code for address of */
11961 /*-----------------------------------------------------------------*/
11963 genArrayInit (iCode * ic)
11965 literalList *iLoop;
11967 int elementSize = 0, eIndex;
11968 unsigned val, lastVal;
11970 operand *left=IC_LEFT(ic);
11972 D (emitcode (";", "genArrayInit"));
11974 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
11976 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
11978 // Load immediate value into DPTR.
11979 emitcode("mov", "dptr, %s",
11980 aopGet (IC_LEFT(ic), 0, TRUE, FALSE, NULL));
11982 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
11985 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11986 "Unexpected operand to genArrayInit.\n");
11989 // a regression because of SDCCcse.c:1.52
11990 emitcode ("mov", "dpl,%s", aopGet (left, 0, FALSE, FALSE, NULL));
11991 emitcode ("mov", "dph,%s", aopGet (left, 1, FALSE, FALSE, NULL));
11992 if (options.model == MODEL_FLAT24)
11993 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
11997 type = operandType(IC_LEFT(ic));
11999 if (type && type->next)
12001 elementSize = getSize(type->next);
12005 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12006 "can't determine element size in genArrayInit.\n");
12010 iLoop = IC_ARRAYILIST(ic);
12015 bool firstpass = TRUE;
12017 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
12018 iLoop->count, (int)iLoop->literalValue, elementSize);
12024 symbol *tlbl = NULL;
12026 count = ix > 256 ? 256 : ix;
12030 tlbl = newiTempLabel (NULL);
12031 if (firstpass || (count & 0xff))
12033 emitcode("mov", "b, #!constbyte", count & 0xff);
12041 for (eIndex = 0; eIndex < elementSize; eIndex++)
12043 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
12044 if (val != lastVal)
12046 emitcode("mov", "a, #!constbyte", val);
12050 emitcode("movx", "@dptr, a");
12051 emitcode("inc", "dptr");
12056 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
12062 iLoop = iLoop->next;
12065 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
12069 /*-----------------------------------------------------------------*/
12070 /* genFarFarAssign - assignment when both are in far space */
12071 /*-----------------------------------------------------------------*/
12073 genFarFarAssign (operand * result, operand * right, iCode * ic)
12075 int size = AOP_SIZE (right);
12077 symbol *rSym = NULL;
12081 /* quick & easy case. */
12082 D (emitcode(";","genFarFarAssign (1 byte case)"));
12083 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
12084 freeAsmop (right, NULL, ic, FALSE);
12085 /* now assign DPTR to result */
12087 aopOp(result, ic, FALSE, FALSE);
12089 aopPut (result, "a", 0);
12090 freeAsmop(result, NULL, ic, FALSE);
12094 /* See if we've got an underlying symbol to abuse. */
12095 if (IS_SYMOP(result) && OP_SYMBOL(result))
12097 if (IS_TRUE_SYMOP(result))
12099 rSym = OP_SYMBOL(result);
12101 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
12103 rSym = OP_SYMBOL(result)->usl.spillLoc;
12107 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
12109 /* We can use the '390 auto-toggle feature to good effect here. */
12111 D (emitcode(";", "genFarFarAssign (390 auto-toggle fun)"));
12112 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12113 emitcode ("mov", "dptr,#%s", rSym->rname);
12114 /* DP2 = result, DP1 = right, DP1 is current. */
12117 emitcode("movx", "a,@dptr");
12118 emitcode("movx", "@dptr,a");
12121 emitcode("inc", "dptr");
12122 emitcode("inc", "dptr");
12125 emitcode("mov", "dps,#0");
12126 freeAsmop (right, NULL, ic, FALSE);
12128 some alternative code for processors without auto-toggle
12129 no time to test now, so later well put in...kpb
12130 D (emitcode(";", "genFarFarAssign (dual-dptr fun)"));
12131 emitcode("mov", "dps,#1"); /* Select DPTR2. */
12132 emitcode ("mov", "dptr,#%s", rSym->rname);
12133 /* DP2 = result, DP1 = right, DP1 is current. */
12137 emitcode("movx", "a,@dptr");
12139 emitcode("inc", "dptr");
12140 emitcode("inc", "dps");
12141 emitcode("movx", "@dptr,a");
12143 emitcode("inc", "dptr");
12144 emitcode("inc", "dps");
12146 emitcode("mov", "dps,#0");
12147 freeAsmop (right, NULL, ic, FALSE);
12152 D (emitcode (";", "genFarFarAssign"));
12153 aopOp (result, ic, TRUE, TRUE);
12155 _startLazyDPSEvaluation ();
12160 aopGet (right, offset, FALSE, FALSE, NULL), offset);
12163 _endLazyDPSEvaluation ();
12164 freeAsmop (result, NULL, ic, FALSE);
12165 freeAsmop (right, NULL, ic, FALSE);
12169 /*-----------------------------------------------------------------*/
12170 /* genAssign - generate code for assignment */
12171 /*-----------------------------------------------------------------*/
12173 genAssign (iCode * ic)
12175 operand *result, *right;
12177 unsigned long lit = 0L;
12179 D (emitcode (";", "genAssign"));
12181 result = IC_RESULT (ic);
12182 right = IC_RIGHT (ic);
12184 /* if they are the same */
12185 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
12188 aopOp (right, ic, FALSE, FALSE);
12190 emitcode (";", "genAssign: resultIsFar = %s",
12191 isOperandInFarSpace (result) ?
12194 /* special case both in far space */
12195 if ((AOP_TYPE (right) == AOP_DPTR ||
12196 AOP_TYPE (right) == AOP_DPTR2) &&
12197 /* IS_TRUE_SYMOP(result) && */
12198 isOperandInFarSpace (result))
12200 genFarFarAssign (result, right, ic);
12204 aopOp (result, ic, TRUE, FALSE);
12206 /* if they are the same registers */
12207 if (sameRegs (AOP (right), AOP (result)))
12210 /* if the result is a bit */
12211 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
12213 /* if the right size is a literal then
12214 we know what the value is */
12215 if (AOP_TYPE (right) == AOP_LIT)
12217 if (((int) operandLitValue (right)))
12218 aopPut (result, one, 0);
12220 aopPut (result, zero, 0);
12224 /* the right is also a bit variable */
12225 if (AOP_TYPE (right) == AOP_CRY)
12227 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
12228 aopPut (result, "c", 0);
12232 /* we need to or */
12234 aopPut (result, "a", 0);
12238 /* bit variables done */
12240 size = AOP_SIZE (result);
12242 if (AOP_TYPE (right) == AOP_LIT)
12243 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
12246 (AOP_TYPE (result) != AOP_REG) &&
12247 (AOP_TYPE (right) == AOP_LIT) &&
12248 !IS_FLOAT (operandType (right)))
12250 _startLazyDPSEvaluation ();
12251 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
12254 aopGet (right, offset, FALSE, FALSE, NULL),
12259 /* And now fill the rest with zeros. */
12262 emitcode ("clr", "a");
12266 aopPut (result, "a", offset++);
12268 _endLazyDPSEvaluation ();
12272 _startLazyDPSEvaluation ();
12276 aopGet (right, offset, FALSE, FALSE, NULL),
12280 _endLazyDPSEvaluation ();
12284 freeAsmop (result, NULL, ic, TRUE);
12285 freeAsmop (right, NULL, ic, TRUE);
12288 /*-----------------------------------------------------------------*/
12289 /* genJumpTab - generates code for jump table */
12290 /*-----------------------------------------------------------------*/
12292 genJumpTab (iCode * ic)
12297 D (emitcode (";", "genJumpTab"));
12299 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
12300 /* get the condition into accumulator */
12301 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE, NULL);
12303 /* multiply by four! */
12304 emitcode ("add", "a,acc");
12305 emitcode ("add", "a,acc");
12306 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
12308 jtab = newiTempLabel (NULL);
12309 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
12310 emitcode ("jmp", "@a+dptr");
12312 /* now generate the jump labels */
12313 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
12314 jtab = setNextItem (IC_JTLABELS (ic)))
12315 emitcode ("ljmp", "!tlabel", jtab->key + 100);
12319 /*-----------------------------------------------------------------*/
12320 /* genCast - gen code for casting */
12321 /*-----------------------------------------------------------------*/
12323 genCast (iCode * ic)
12325 operand *result = IC_RESULT (ic);
12326 sym_link *ctype = operandType (IC_LEFT (ic));
12327 sym_link *rtype = operandType (IC_RIGHT (ic));
12328 operand *right = IC_RIGHT (ic);
12331 D (emitcode (";", "genCast"));
12333 /* if they are equivalent then do nothing */
12334 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
12337 aopOp (right, ic, FALSE, AOP_IS_STR (result));
12338 aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR));
12340 /* if the result is a bit (and not a bitfield) */
12341 if (IS_BIT (OP_SYMBOL (result)->type))
12343 /* if the right size is a literal then
12344 we know what the value is */
12345 if (AOP_TYPE (right) == AOP_LIT)
12347 if (((int) operandLitValue (right)))
12348 aopPut (result, one, 0);
12350 aopPut (result, zero, 0);
12355 /* the right is also a bit variable */
12356 if (AOP_TYPE (right) == AOP_CRY)
12358 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
12359 aopPut (result, "c", 0);
12363 /* we need to or */
12365 aopPut (result, "a", 0);
12369 /* if they are the same size : or less */
12370 if (AOP_SIZE (result) <= AOP_SIZE (right))
12373 /* if they are in the same place */
12374 if (sameRegs (AOP (right), AOP (result)))
12377 /* if they in different places then copy */
12378 size = AOP_SIZE (result);
12380 _startLazyDPSEvaluation ();
12384 aopGet (right, offset, FALSE, FALSE, NULL),
12388 _endLazyDPSEvaluation ();
12392 /* if the result is of type pointer */
12393 if (IS_PTR (ctype))
12397 sym_link *type = operandType (right);
12399 /* pointer to generic pointer */
12400 if (IS_GENPTR (ctype))
12404 p_type = DCL_TYPE (type);
12408 #if OLD_CAST_BEHAVIOR
12409 /* KV: we are converting a non-pointer type to
12410 * a generic pointer. This (ifdef'd out) code
12411 * says that the resulting generic pointer
12412 * should have the same class as the storage
12413 * location of the non-pointer variable.
12415 * For example, converting an int (which happens
12416 * to be stored in DATA space) to a pointer results
12417 * in a DATA generic pointer; if the original int
12418 * in XDATA space, so will be the resulting pointer.
12420 * I don't like that behavior, and thus this change:
12421 * all such conversions will be forced to XDATA and
12422 * throw a warning. If you want some non-XDATA
12423 * type, or you want to suppress the warning, you
12424 * must go through an intermediate cast, like so:
12426 * char _generic *gp = (char _xdata *)(intVar);
12428 sym_link *etype = getSpec (type);
12430 /* we have to go by the storage class */
12431 if (SPEC_OCLS (etype) != generic)
12433 p_type = PTR_TYPE (SPEC_OCLS (etype));
12438 /* Converting unknown class (i.e. register variable)
12439 * to generic pointer. This is not good, but
12440 * we'll make a guess (and throw a warning).
12443 werror (W_INT_TO_GEN_PTR_CAST);
12447 /* the first two bytes are known */
12448 size = GPTRSIZE - 1;
12450 _startLazyDPSEvaluation ();
12454 aopGet (right, offset, FALSE, FALSE, NULL),
12458 _endLazyDPSEvaluation ();
12460 /* the last byte depending on type */
12462 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
12467 // pointerTypeToGPByte will have bitched.
12471 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%x", gpVal);
12472 aopPut (result, gpValStr, GPTRSIZE - 1);
12477 /* just copy the pointers */
12478 size = AOP_SIZE (result);
12480 _startLazyDPSEvaluation ();
12484 aopGet (right, offset, FALSE, FALSE, NULL),
12488 _endLazyDPSEvaluation ();
12492 /* so we now know that the size of destination is greater
12493 than the size of the source */
12494 /* we move to result for the size of source */
12495 size = AOP_SIZE (right);
12497 _startLazyDPSEvaluation ();
12501 aopGet (right, offset, FALSE, FALSE, NULL),
12505 _endLazyDPSEvaluation ();
12507 /* now depending on the sign of the source && destination */
12508 size = AOP_SIZE (result) - AOP_SIZE (right);
12509 /* if unsigned or not an integral type */
12510 /* also, if the source is a bit, we don't need to sign extend, because
12511 * it can't possibly have set the sign bit.
12513 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
12517 aopPut (result, zero, offset++);
12522 /* we need to extend the sign :{ */
12523 MOVA (aopGet (right, AOP_SIZE (right) - 1,
12524 FALSE, FALSE, NULL));
12525 emitcode ("rlc", "a");
12526 emitcode ("subb", "a,acc");
12528 aopPut (result, "a", offset++);
12531 /* we are done hurray !!!! */
12534 freeAsmop (right, NULL, ic, TRUE);
12535 freeAsmop (result, NULL, ic, TRUE);
12539 /*-----------------------------------------------------------------*/
12540 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
12541 /*-----------------------------------------------------------------*/
12542 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
12544 operand *from , *to , *count;
12549 /* we know it has to be 3 parameters */
12550 assert (nparms == 3);
12552 rsave = newBitVect(16);
12553 /* save DPTR if it needs to be saved */
12554 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12555 if (bitVectBitValue(ic->rMask,i))
12556 rsave = bitVectSetBit(rsave,i);
12558 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12559 ds390_rUmaskForOp (IC_RESULT(ic))));
12566 aopOp (from, ic->next, FALSE, FALSE);
12568 /* get from into DPTR1 */
12569 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12570 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12571 if (options.model == MODEL_FLAT24) {
12572 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12575 freeAsmop (from, NULL, ic, FALSE);
12576 aopOp (to, ic, FALSE, FALSE);
12577 /* get "to" into DPTR */
12578 /* if the operand is already in dptr
12579 then we do nothing else we move the value to dptr */
12580 if (AOP_TYPE (to) != AOP_STR) {
12581 /* if already in DPTR then we need to push */
12582 if (AOP_TYPE(to) == AOP_DPTR) {
12583 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12584 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12585 if (options.model == MODEL_FLAT24)
12586 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12587 emitcode ("pop", "dph");
12588 emitcode ("pop", "dpl");
12590 _startLazyDPSEvaluation ();
12591 /* if this is remateriazable */
12592 if (AOP_TYPE (to) == AOP_IMMD) {
12593 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12594 } else { /* we need to get it byte by byte */
12595 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12596 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12597 if (options.model == MODEL_FLAT24) {
12598 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12601 _endLazyDPSEvaluation ();
12604 freeAsmop (to, NULL, ic, FALSE);
12605 _G.dptrInUse = _G.dptr1InUse = 1;
12606 aopOp (count, ic->next->next, FALSE,FALSE);
12607 lbl =newiTempLabel(NULL);
12609 /* now for the actual copy */
12610 if (AOP_TYPE(count) == AOP_LIT &&
12611 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12612 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12614 emitcode ("lcall","__bi_memcpyc2x_s");
12616 emitcode ("lcall","__bi_memcpyx2x_s");
12618 freeAsmop (count, NULL, ic, FALSE);
12620 symbol *lbl1 = newiTempLabel(NULL);
12622 emitcode (";"," Auto increment but no djnz");
12623 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
12624 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
12625 freeAsmop (count, NULL, ic, FALSE);
12626 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12627 emitcode ("","!tlabeldef",lbl->key+100);
12629 emitcode ("clr","a");
12630 emitcode ("movc", "a,@a+dptr");
12632 emitcode ("movx", "a,@dptr");
12633 emitcode ("movx", "@dptr,a");
12634 emitcode ("inc", "dptr");
12635 emitcode ("inc", "dptr");
12636 emitcode ("mov","a,b");
12637 emitcode ("orl","a,_ap");
12638 emitcode ("jz","!tlabel",lbl1->key+100);
12639 emitcode ("mov","a,_ap");
12640 emitcode ("add","a,#!constbyte",0xFF);
12641 emitcode ("mov","_ap,a");
12642 emitcode ("mov","a,b");
12643 emitcode ("addc","a,#!constbyte",0xFF);
12644 emitcode ("mov","b,a");
12645 emitcode ("sjmp","!tlabel",lbl->key+100);
12646 emitcode ("","!tlabeldef",lbl1->key+100);
12648 emitcode ("mov", "dps,#0");
12649 _G.dptrInUse = _G.dptr1InUse = 0;
12650 unsavermask(rsave);
12654 /*-----------------------------------------------------------------*/
12655 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
12656 /*-----------------------------------------------------------------*/
12657 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
12659 operand *from , *to , *count;
12664 /* we know it has to be 3 parameters */
12665 assert (nparms == 3);
12667 rsave = newBitVect(16);
12668 /* save DPTR if it needs to be saved */
12669 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12670 if (bitVectBitValue(ic->rMask,i))
12671 rsave = bitVectSetBit(rsave,i);
12673 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12674 ds390_rUmaskForOp (IC_RESULT(ic))));
12681 aopOp (from, ic->next, FALSE, FALSE);
12683 /* get from into DPTR1 */
12684 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12685 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12686 if (options.model == MODEL_FLAT24) {
12687 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12690 freeAsmop (from, NULL, ic, FALSE);
12691 aopOp (to, ic, FALSE, FALSE);
12692 /* get "to" into DPTR */
12693 /* if the operand is already in dptr
12694 then we do nothing else we move the value to dptr */
12695 if (AOP_TYPE (to) != AOP_STR) {
12696 /* if already in DPTR then we need to push */
12697 if (AOP_TYPE(to) == AOP_DPTR) {
12698 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12699 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12700 if (options.model == MODEL_FLAT24)
12701 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12702 emitcode ("pop", "dph");
12703 emitcode ("pop", "dpl");
12705 _startLazyDPSEvaluation ();
12706 /* if this is remateriazable */
12707 if (AOP_TYPE (to) == AOP_IMMD) {
12708 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12709 } else { /* we need to get it byte by byte */
12710 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12711 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12712 if (options.model == MODEL_FLAT24) {
12713 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12716 _endLazyDPSEvaluation ();
12719 freeAsmop (to, NULL, ic, FALSE);
12720 _G.dptrInUse = _G.dptr1InUse = 1;
12721 aopOp (count, ic->next->next, FALSE,FALSE);
12722 lbl =newiTempLabel(NULL);
12723 lbl2 =newiTempLabel(NULL);
12725 /* now for the actual compare */
12726 if (AOP_TYPE(count) == AOP_LIT &&
12727 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12728 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12730 emitcode("lcall","__bi_memcmpc2x_s");
12732 emitcode("lcall","__bi_memcmpx2x_s");
12733 freeAsmop (count, NULL, ic, FALSE);
12734 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12735 aopPut(IC_RESULT(ic),"a",0);
12736 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12738 symbol *lbl1 = newiTempLabel(NULL);
12740 emitcode("push","ar0");
12741 emitcode (";"," Auto increment but no djnz");
12742 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
12743 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
12744 freeAsmop (count, NULL, ic, FALSE);
12745 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12746 emitcode ("","!tlabeldef",lbl->key+100);
12748 emitcode ("clr","a");
12749 emitcode ("movc", "a,@a+dptr");
12751 emitcode ("movx", "a,@dptr");
12752 emitcode ("mov","r0,a");
12753 emitcode ("movx", "a,@dptr");
12754 emitcode ("clr","c");
12755 emitcode ("subb","a,r0");
12756 emitcode ("jnz","!tlabel",lbl2->key+100);
12757 emitcode ("inc", "dptr");
12758 emitcode ("inc", "dptr");
12759 emitcode ("mov","a,b");
12760 emitcode ("orl","a,_ap");
12761 emitcode ("jz","!tlabel",lbl1->key+100);
12762 emitcode ("mov","a,_ap");
12763 emitcode ("add","a,#!constbyte",0xFF);
12764 emitcode ("mov","_ap,a");
12765 emitcode ("mov","a,b");
12766 emitcode ("addc","a,#!constbyte",0xFF);
12767 emitcode ("mov","b,a");
12768 emitcode ("sjmp","!tlabel",lbl->key+100);
12769 emitcode ("","!tlabeldef",lbl1->key+100);
12770 emitcode ("clr","a");
12771 emitcode ("","!tlabeldef",lbl2->key+100);
12772 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12773 aopPut(IC_RESULT(ic),"a",0);
12774 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12775 emitcode("pop","ar0");
12776 emitcode ("mov", "dps,#0");
12778 _G.dptrInUse = _G.dptr1InUse = 0;
12779 unsavermask(rsave);
12783 /*-----------------------------------------------------------------*/
12784 /* genInp - gen code for __builtin_inp read data from a mem mapped */
12785 /* port, first parameter output area second parameter pointer to */
12786 /* port third parameter count */
12787 /*-----------------------------------------------------------------*/
12788 static void genInp( iCode *ic, int nparms, operand **parms)
12790 operand *from , *to , *count;
12795 /* we know it has to be 3 parameters */
12796 assert (nparms == 3);
12798 rsave = newBitVect(16);
12799 /* save DPTR if it needs to be saved */
12800 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12801 if (bitVectBitValue(ic->rMask,i))
12802 rsave = bitVectSetBit(rsave,i);
12804 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12805 ds390_rUmaskForOp (IC_RESULT(ic))));
12812 aopOp (from, ic->next, FALSE, FALSE);
12814 /* get from into DPTR1 */
12815 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12816 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12817 if (options.model == MODEL_FLAT24) {
12818 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12821 freeAsmop (from, NULL, ic, FALSE);
12822 aopOp (to, ic, FALSE, FALSE);
12823 /* get "to" into DPTR */
12824 /* if the operand is already in dptr
12825 then we do nothing else we move the value to dptr */
12826 if (AOP_TYPE (to) != AOP_STR) {
12827 /* if already in DPTR then we need to push */
12828 if (AOP_TYPE(to) == AOP_DPTR) {
12829 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12830 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12831 if (options.model == MODEL_FLAT24)
12832 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12833 emitcode ("pop", "dph");
12834 emitcode ("pop", "dpl");
12836 _startLazyDPSEvaluation ();
12837 /* if this is remateriazable */
12838 if (AOP_TYPE (to) == AOP_IMMD) {
12839 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12840 } else { /* we need to get it byte by byte */
12841 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12842 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12843 if (options.model == MODEL_FLAT24) {
12844 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12847 _endLazyDPSEvaluation ();
12850 freeAsmop (to, NULL, ic, FALSE);
12852 _G.dptrInUse = _G.dptr1InUse = 1;
12853 aopOp (count, ic->next->next, FALSE,FALSE);
12854 lbl =newiTempLabel(NULL);
12856 /* now for the actual copy */
12857 if (AOP_TYPE(count) == AOP_LIT &&
12858 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12859 emitcode (";","OH JOY auto increment with djnz (very fast)");
12860 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
12861 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12862 freeAsmop (count, NULL, ic, FALSE);
12863 emitcode ("","!tlabeldef",lbl->key+100);
12864 emitcode ("movx", "a,@dptr"); /* read data from port */
12865 emitcode ("dec","dps"); /* switch to DPTR */
12866 emitcode ("movx", "@dptr,a"); /* save into location */
12867 emitcode ("inc", "dptr"); /* point to next area */
12868 emitcode ("inc","dps"); /* switch to DPTR2 */
12869 emitcode ("djnz","b,!tlabel",lbl->key+100);
12871 symbol *lbl1 = newiTempLabel(NULL);
12873 emitcode (";"," Auto increment but no djnz");
12874 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
12875 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
12876 freeAsmop (count, NULL, ic, FALSE);
12877 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
12878 emitcode ("","!tlabeldef",lbl->key+100);
12879 emitcode ("movx", "a,@dptr");
12880 emitcode ("dec","dps"); /* switch to DPTR */
12881 emitcode ("movx", "@dptr,a");
12882 emitcode ("inc", "dptr");
12883 emitcode ("inc","dps"); /* switch to DPTR2 */
12884 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
12885 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
12886 emitcode ("mov","a,b");
12887 emitcode ("orl","a,_ap");
12888 emitcode ("jz","!tlabel",lbl1->key+100);
12889 emitcode ("mov","a,_ap");
12890 emitcode ("add","a,#!constbyte",0xFF);
12891 emitcode ("mov","_ap,a");
12892 emitcode ("mov","a,b");
12893 emitcode ("addc","a,#!constbyte",0xFF);
12894 emitcode ("mov","b,a");
12895 emitcode ("sjmp","!tlabel",lbl->key+100);
12896 emitcode ("","!tlabeldef",lbl1->key+100);
12898 emitcode ("mov", "dps,#0");
12899 _G.dptrInUse = _G.dptr1InUse = 0;
12900 unsavermask(rsave);
12904 /*-----------------------------------------------------------------*/
12905 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
12906 /* port, first parameter output area second parameter pointer to */
12907 /* port third parameter count */
12908 /*-----------------------------------------------------------------*/
12909 static void genOutp( iCode *ic, int nparms, operand **parms)
12911 operand *from , *to , *count;
12916 /* we know it has to be 3 parameters */
12917 assert (nparms == 3);
12919 rsave = newBitVect(16);
12920 /* save DPTR if it needs to be saved */
12921 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12922 if (bitVectBitValue(ic->rMask,i))
12923 rsave = bitVectSetBit(rsave,i);
12925 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12926 ds390_rUmaskForOp (IC_RESULT(ic))));
12933 aopOp (from, ic->next, FALSE, FALSE);
12935 /* get from into DPTR1 */
12936 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12937 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12938 if (options.model == MODEL_FLAT24) {
12939 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12942 freeAsmop (from, NULL, ic, FALSE);
12943 aopOp (to, ic, FALSE, FALSE);
12944 /* get "to" into DPTR */
12945 /* if the operand is already in dptr
12946 then we do nothing else we move the value to dptr */
12947 if (AOP_TYPE (to) != AOP_STR) {
12948 /* if already in DPTR then we need to push */
12949 if (AOP_TYPE(to) == AOP_DPTR) {
12950 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12951 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12952 if (options.model == MODEL_FLAT24)
12953 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12954 emitcode ("pop", "dph");
12955 emitcode ("pop", "dpl");
12957 _startLazyDPSEvaluation ();
12958 /* if this is remateriazable */
12959 if (AOP_TYPE (to) == AOP_IMMD) {
12960 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12961 } else { /* we need to get it byte by byte */
12962 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12963 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12964 if (options.model == MODEL_FLAT24) {
12965 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12968 _endLazyDPSEvaluation ();
12971 freeAsmop (to, NULL, ic, FALSE);
12973 _G.dptrInUse = _G.dptr1InUse = 1;
12974 aopOp (count, ic->next->next, FALSE,FALSE);
12975 lbl =newiTempLabel(NULL);
12977 /* now for the actual copy */
12978 if (AOP_TYPE(count) == AOP_LIT &&
12979 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12980 emitcode (";","OH JOY auto increment with djnz (very fast)");
12981 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
12982 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12983 emitcode ("","!tlabeldef",lbl->key+100);
12984 emitcode ("movx", "a,@dptr"); /* read data from port */
12985 emitcode ("inc","dps"); /* switch to DPTR2 */
12986 emitcode ("movx", "@dptr,a"); /* save into location */
12987 emitcode ("inc", "dptr"); /* point to next area */
12988 emitcode ("dec","dps"); /* switch to DPTR */
12989 emitcode ("djnz","b,!tlabel",lbl->key+100);
12990 freeAsmop (count, NULL, ic, FALSE);
12992 symbol *lbl1 = newiTempLabel(NULL);
12994 emitcode (";"," Auto increment but no djnz");
12995 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
12996 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
12997 freeAsmop (count, NULL, ic, FALSE);
12998 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
12999 emitcode ("","!tlabeldef",lbl->key+100);
13000 emitcode ("movx", "a,@dptr");
13001 emitcode ("inc", "dptr");
13002 emitcode ("inc","dps"); /* switch to DPTR2 */
13003 emitcode ("movx", "@dptr,a");
13004 emitcode ("dec","dps"); /* switch to DPTR */
13005 emitcode ("mov","a,b");
13006 emitcode ("orl","a,_ap");
13007 emitcode ("jz","!tlabel",lbl1->key+100);
13008 emitcode ("mov","a,_ap");
13009 emitcode ("add","a,#!constbyte",0xFF);
13010 emitcode ("mov","_ap,a");
13011 emitcode ("mov","a,b");
13012 emitcode ("addc","a,#!constbyte",0xFF);
13013 emitcode ("mov","b,a");
13014 emitcode ("sjmp","!tlabel",lbl->key+100);
13015 emitcode ("","!tlabeldef",lbl1->key+100);
13017 emitcode ("mov", "dps,#0");
13018 _G.dptrInUse = _G.dptr1InUse = 0;
13019 unsavermask(rsave);
13023 /*-----------------------------------------------------------------*/
13024 /* genSwapW - swap lower & high order bytes */
13025 /*-----------------------------------------------------------------*/
13026 static void genSwapW(iCode *ic, int nparms, operand **parms)
13030 assert (nparms==1);
13033 dest=IC_RESULT(ic);
13035 assert(getSize(operandType(src))==2);
13037 aopOp (src, ic, FALSE, FALSE);
13038 emitcode ("mov","a,%s",aopGet(src,0,FALSE,FALSE,NULL));
13040 MOVB(aopGet(src,1,FALSE,FALSE,"b"));
13042 freeAsmop (src, NULL, ic, FALSE);
13044 aopOp (dest,ic, FALSE, FALSE);
13045 aopPut(dest,"b",0);
13046 aopPut(dest,"a",1);
13047 freeAsmop (dest, NULL, ic, FALSE);
13050 /*-----------------------------------------------------------------*/
13051 /* genMemsetX - gencode for memSetX data */
13052 /*-----------------------------------------------------------------*/
13053 static void genMemsetX(iCode *ic, int nparms, operand **parms)
13055 operand *to , *val , *count;
13061 /* we know it has to be 3 parameters */
13062 assert (nparms == 3);
13068 /* save DPTR if it needs to be saved */
13069 rsave = newBitVect(16);
13070 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
13071 if (bitVectBitValue(ic->rMask,i))
13072 rsave = bitVectSetBit(rsave,i);
13074 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
13075 ds390_rUmaskForOp (IC_RESULT(ic))));
13078 aopOp (to, ic, FALSE, FALSE);
13079 /* get "to" into DPTR */
13080 /* if the operand is already in dptr
13081 then we do nothing else we move the value to dptr */
13082 if (AOP_TYPE (to) != AOP_STR) {
13083 /* if already in DPTR then we need to push */
13084 if (AOP_TYPE(to) == AOP_DPTR) {
13085 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
13086 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
13087 if (options.model == MODEL_FLAT24)
13088 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
13089 emitcode ("pop", "dph");
13090 emitcode ("pop", "dpl");
13092 _startLazyDPSEvaluation ();
13093 /* if this is remateriazable */
13094 if (AOP_TYPE (to) == AOP_IMMD) {
13095 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
13096 } else { /* we need to get it byte by byte */
13097 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
13098 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
13099 if (options.model == MODEL_FLAT24) {
13100 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
13103 _endLazyDPSEvaluation ();
13106 freeAsmop (to, NULL, ic, FALSE);
13108 aopOp (val, ic->next->next, FALSE,FALSE);
13109 aopOp (count, ic->next->next, FALSE,FALSE);
13110 lbl =newiTempLabel(NULL);
13111 /* now for the actual copy */
13112 if (AOP_TYPE(count) == AOP_LIT &&
13113 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
13114 l = aopGet(val, 0, FALSE, FALSE, NULL);
13115 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
13117 emitcode ("","!tlabeldef",lbl->key+100);
13118 emitcode ("movx", "@dptr,a");
13119 emitcode ("inc", "dptr");
13120 emitcode ("djnz","b,!tlabel",lbl->key+100);
13122 symbol *lbl1 = newiTempLabel(NULL);
13124 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
13125 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
13126 emitcode ("","!tlabeldef",lbl->key+100);
13127 MOVA (aopGet(val, 0, FALSE, FALSE, NULL));
13128 emitcode ("movx", "@dptr,a");
13129 emitcode ("inc", "dptr");
13130 emitcode ("mov","a,b");
13131 emitcode ("orl","a,_ap");
13132 emitcode ("jz","!tlabel",lbl1->key+100);
13133 emitcode ("mov","a,_ap");
13134 emitcode ("add","a,#!constbyte",0xFF);
13135 emitcode ("mov","_ap,a");
13136 emitcode ("mov","a,b");
13137 emitcode ("addc","a,#!constbyte",0xFF);
13138 emitcode ("mov","b,a");
13139 emitcode ("sjmp","!tlabel",lbl->key+100);
13140 emitcode ("","!tlabeldef",lbl1->key+100);
13142 freeAsmop (count, NULL, ic, FALSE);
13143 unsavermask(rsave);
13146 /*-----------------------------------------------------------------*/
13147 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
13148 /*-----------------------------------------------------------------*/
13149 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
13152 operand *pnum, *result;
13155 assert (nparms==1);
13156 /* save registers that need to be saved */
13157 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13158 ds390_rUmaskForOp (IC_RESULT(ic))));
13161 aopOp (pnum, ic, FALSE, FALSE);
13162 emitcode ("mov","a,%s",aopGet(pnum,0,FALSE,FALSE,DP2_RESULT_REG));
13163 freeAsmop (pnum, NULL, ic, FALSE);
13164 emitcode ("lcall","NatLib_LoadPrimitive");
13165 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
13166 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
13167 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
13168 for (i = (size-1) ; i >= 0 ; i-- ) {
13169 emitcode ("push","a%s",javaRet[i]);
13171 for (i=0; i < size ; i++ ) {
13172 emitcode ("pop","a%s",
13173 aopGet(result,i,FALSE,FALSE,DP2_RESULT_REG));
13176 for (i = 0 ; i < size ; i++ ) {
13177 aopPut(result,javaRet[i],i);
13180 freeAsmop (result, NULL, ic, FALSE);
13181 unsavermask(rsave);
13184 /*-----------------------------------------------------------------*/
13185 /* genNatLibLoadPointer - calls TINI api function to load pointer */
13186 /*-----------------------------------------------------------------*/
13187 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
13190 operand *pnum, *result;
13194 assert (nparms==1);
13195 /* save registers that need to be saved */
13196 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13197 ds390_rUmaskForOp (IC_RESULT(ic))));
13200 aopOp (pnum, ic, FALSE, FALSE);
13201 emitcode ("mov","a,%s",aopGet(pnum,0,FALSE,FALSE,DP2_RESULT_REG));
13202 freeAsmop (pnum, NULL, ic, FALSE);
13203 emitcode ("lcall","NatLib_LoadPointer");
13204 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
13205 if (AOP_TYPE(result)!=AOP_STR) {
13206 for (i = 0 ; i < size ; i++ ) {
13207 aopPut(result,fReturn[i],i);
13210 freeAsmop (result, NULL, ic, FALSE);
13211 unsavermask(rsave);
13214 /*-----------------------------------------------------------------*/
13215 /* genNatLibInstallStateBlock - */
13216 /*-----------------------------------------------------------------*/
13217 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
13218 operand **parms, const char *name)
13221 operand *psb, *handle;
13222 assert (nparms==2);
13224 /* save registers that need to be saved */
13225 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13226 ds390_rUmaskForOp (IC_RESULT(ic))));
13230 /* put pointer to state block into DPTR1 */
13231 aopOp (psb, ic, FALSE, FALSE);
13232 if (AOP_TYPE (psb) == AOP_IMMD) {
13233 emitcode ("mov","dps,#1");
13234 emitcode ("mov", "dptr,%s",
13235 aopGet (psb, 0, TRUE, FALSE, DP2_RESULT_REG));
13236 emitcode ("mov","dps,#0");
13238 emitcode ("mov","dpl1,%s",aopGet(psb,0,FALSE,FALSE,DP2_RESULT_REG));
13239 emitcode ("mov","dph1,%s",aopGet(psb,1,FALSE,FALSE,DP2_RESULT_REG));
13240 emitcode ("mov","dpx1,%s",aopGet(psb,2,FALSE,FALSE,DP2_RESULT_REG));
13242 freeAsmop (psb, NULL, ic, FALSE);
13244 /* put libraryID into DPTR */
13245 emitcode ("mov","dptr,#LibraryID");
13247 /* put handle into r3:r2 */
13248 aopOp (handle, ic, FALSE, FALSE);
13249 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13250 emitcode ("push","%s",aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13251 emitcode ("push","%s",aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13252 emitcode ("pop","ar3");
13253 emitcode ("pop","ar2");
13255 emitcode ("mov","r2,%s",aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13256 emitcode ("mov","r3,%s",aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13258 freeAsmop (psb, NULL, ic, FALSE);
13260 /* make the call */
13261 emitcode ("lcall","NatLib_Install%sStateBlock",name);
13263 /* put return value into place*/
13265 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
13267 aopPut(IC_RESULT(ic),"a",0);
13268 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13269 unsavermask(rsave);
13272 /*-----------------------------------------------------------------*/
13273 /* genNatLibRemoveStateBlock - */
13274 /*-----------------------------------------------------------------*/
13275 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
13281 /* save registers that need to be saved */
13282 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13283 ds390_rUmaskForOp (IC_RESULT(ic))));
13285 /* put libraryID into DPTR */
13286 emitcode ("mov","dptr,#LibraryID");
13287 /* make the call */
13288 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
13289 unsavermask(rsave);
13292 /*-----------------------------------------------------------------*/
13293 /* genNatLibGetStateBlock - */
13294 /*-----------------------------------------------------------------*/
13295 static void genNatLibGetStateBlock(iCode *ic,int nparms,
13296 operand **parms,const char *name)
13299 symbol *lbl = newiTempLabel(NULL);
13302 /* save registers that need to be saved */
13303 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13304 ds390_rUmaskForOp (IC_RESULT(ic))));
13306 /* put libraryID into DPTR */
13307 emitcode ("mov","dptr,#LibraryID");
13308 /* make the call */
13309 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
13310 emitcode ("jnz","!tlabel",lbl->key+100);
13312 /* put return value into place */
13313 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
13314 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
13315 emitcode ("push","ar3");
13316 emitcode ("push","ar2");
13317 emitcode ("pop","%s",
13318 aopGet(IC_RESULT(ic),0,FALSE,TRUE,DP2_RESULT_REG));
13319 emitcode ("pop","%s",
13320 aopGet(IC_RESULT(ic),1,FALSE,TRUE,DP2_RESULT_REG));
13322 aopPut(IC_RESULT(ic),"r2",0);
13323 aopPut(IC_RESULT(ic),"r3",1);
13325 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13326 emitcode ("","!tlabeldef",lbl->key+100);
13327 unsavermask(rsave);
13330 /*-----------------------------------------------------------------*/
13331 /* genMMMalloc - */
13332 /*-----------------------------------------------------------------*/
13333 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
13334 int size, const char *name)
13339 symbol *lbl = newiTempLabel(NULL);
13341 assert (nparms == 1);
13342 /* save registers that need to be saved */
13343 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13344 ds390_rUmaskForOp (IC_RESULT(ic))));
13347 aopOp (bsize,ic,FALSE,FALSE);
13349 /* put the size in R4-R2 */
13350 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
13351 emitcode("push","%s",aopGet(bsize,0,FALSE,TRUE,DP2_RESULT_REG));
13352 emitcode("push","%s",aopGet(bsize,1,FALSE,TRUE,DP2_RESULT_REG));
13354 emitcode("push","%s",aopGet(bsize,2,FALSE,TRUE,DP2_RESULT_REG));
13355 emitcode("pop","ar4");
13357 emitcode("pop","ar3");
13358 emitcode("pop","ar2");
13360 emitcode ("mov","r2,%s",aopGet(bsize,0,FALSE,TRUE,DP2_RESULT_REG));
13361 emitcode ("mov","r3,%s",aopGet(bsize,1,FALSE,TRUE,DP2_RESULT_REG));
13363 emitcode("mov","r4,%s",aopGet(bsize,2,FALSE,TRUE,DP2_RESULT_REG));
13366 freeAsmop (bsize, NULL, ic, FALSE);
13368 /* make the call */
13369 emitcode ("lcall","MM_%s",name);
13370 emitcode ("jz","!tlabel",lbl->key+100);
13371 emitcode ("mov","r2,#!constbyte",0xff);
13372 emitcode ("mov","r3,#!constbyte",0xff);
13373 emitcode ("","!tlabeldef",lbl->key+100);
13374 /* we don't care about the pointer : we just save the handle */
13375 rsym = OP_SYMBOL(IC_RESULT(ic));
13376 if (rsym->liveFrom != rsym->liveTo) {
13377 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
13378 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
13379 emitcode ("push","ar3");
13380 emitcode ("push","ar2");
13381 emitcode ("pop","%s",
13382 aopGet(IC_RESULT(ic),0,FALSE,TRUE,DP2_RESULT_REG));
13383 emitcode ("pop","%s",
13384 aopGet(IC_RESULT(ic),1,FALSE,TRUE,DP2_RESULT_REG));
13386 aopPut(IC_RESULT(ic),"r2",0);
13387 aopPut(IC_RESULT(ic),"r3",1);
13389 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13391 unsavermask(rsave);
13394 /*-----------------------------------------------------------------*/
13396 /*-----------------------------------------------------------------*/
13397 static void genMMDeref (iCode *ic,int nparms, operand **parms)
13402 assert (nparms == 1);
13403 /* save registers that need to be saved */
13404 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13405 ds390_rUmaskForOp (IC_RESULT(ic))));
13408 aopOp (handle,ic,FALSE,FALSE);
13410 /* put the size in R4-R2 */
13411 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13412 emitcode("push","%s",
13413 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13414 emitcode("push","%s",
13415 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13416 emitcode("pop","ar3");
13417 emitcode("pop","ar2");
13419 emitcode ("mov","r2,%s",
13420 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13421 emitcode ("mov","r3,%s",
13422 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13424 freeAsmop (handle, NULL, ic, FALSE);
13426 /* make the call */
13427 emitcode ("lcall","MM_Deref");
13430 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13431 if (rsym->liveFrom != rsym->liveTo) {
13432 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13433 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
13434 _startLazyDPSEvaluation ();
13436 aopPut(IC_RESULT(ic),"dpl",0);
13437 aopPut(IC_RESULT(ic),"dph",1);
13438 aopPut(IC_RESULT(ic),"dpx",2);
13440 _endLazyDPSEvaluation ();
13445 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13446 unsavermask(rsave);
13449 /*-----------------------------------------------------------------*/
13450 /* genMMUnrestrictedPersist - */
13451 /*-----------------------------------------------------------------*/
13452 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
13457 assert (nparms == 1);
13458 /* save registers that need to be saved */
13459 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13460 ds390_rUmaskForOp (IC_RESULT(ic))));
13463 aopOp (handle,ic,FALSE,FALSE);
13465 /* put the size in R3-R2 */
13466 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13467 emitcode("push","%s",
13468 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13469 emitcode("push","%s",
13470 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13471 emitcode("pop","ar3");
13472 emitcode("pop","ar2");
13474 emitcode ("mov","r2,%s",
13475 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13476 emitcode ("mov","r3,%s",
13477 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13479 freeAsmop (handle, NULL, ic, FALSE);
13481 /* make the call */
13482 emitcode ("lcall","MM_UnrestrictedPersist");
13485 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13486 if (rsym->liveFrom != rsym->liveTo) {
13487 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13488 aopPut(IC_RESULT(ic),"a",0);
13489 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13492 unsavermask(rsave);
13495 /*-----------------------------------------------------------------*/
13496 /* genSystemExecJavaProcess - */
13497 /*-----------------------------------------------------------------*/
13498 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
13501 operand *handle, *pp;
13503 assert (nparms==2);
13504 /* save registers that need to be saved */
13505 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13506 ds390_rUmaskForOp (IC_RESULT(ic))));
13511 /* put the handle in R3-R2 */
13512 aopOp (handle,ic,FALSE,FALSE);
13513 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13514 emitcode("push","%s",
13515 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13516 emitcode("push","%s",
13517 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13518 emitcode("pop","ar3");
13519 emitcode("pop","ar2");
13521 emitcode ("mov","r2,%s",
13522 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13523 emitcode ("mov","r3,%s",
13524 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13526 freeAsmop (handle, NULL, ic, FALSE);
13528 /* put pointer in DPTR */
13529 aopOp (pp,ic,FALSE,FALSE);
13530 if (AOP_TYPE(pp) == AOP_IMMD) {
13531 emitcode ("mov", "dptr,%s",
13532 aopGet (pp, 0, TRUE, FALSE, NULL));
13533 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
13534 emitcode ("mov","dpl,%s",aopGet(pp,0,FALSE,FALSE,NULL));
13535 emitcode ("mov","dph,%s",aopGet(pp,1,FALSE,FALSE,NULL));
13536 emitcode ("mov","dpx,%s",aopGet(pp,2,FALSE,FALSE,NULL));
13538 freeAsmop (handle, NULL, ic, FALSE);
13540 /* make the call */
13541 emitcode ("lcall","System_ExecJavaProcess");
13543 /* put result in place */
13545 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13546 if (rsym->liveFrom != rsym->liveTo) {
13547 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13548 aopPut(IC_RESULT(ic),"a",0);
13549 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13553 unsavermask(rsave);
13556 /*-----------------------------------------------------------------*/
13557 /* genSystemRTCRegisters - */
13558 /*-----------------------------------------------------------------*/
13559 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
13565 assert (nparms==1);
13566 /* save registers that need to be saved */
13567 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13568 ds390_rUmaskForOp (IC_RESULT(ic))));
13571 /* put pointer in DPTR */
13572 aopOp (pp,ic,FALSE,FALSE);
13573 if (AOP_TYPE (pp) == AOP_IMMD) {
13574 emitcode ("mov","dps,#1");
13575 emitcode ("mov", "dptr,%s",
13576 aopGet (pp, 0, TRUE, FALSE, NULL));
13577 emitcode ("mov","dps,#0");
13579 emitcode ("mov","dpl1,%s",
13580 aopGet(pp,0,FALSE,FALSE,DP2_RESULT_REG));
13581 emitcode ("mov","dph1,%s",
13582 aopGet(pp,1,FALSE,FALSE,DP2_RESULT_REG));
13583 emitcode ("mov","dpx1,%s",
13584 aopGet(pp,2,FALSE,FALSE,DP2_RESULT_REG));
13586 freeAsmop (pp, NULL, ic, FALSE);
13588 /* make the call */
13589 emitcode ("lcall","System_%sRTCRegisters",name);
13591 unsavermask(rsave);
13594 /*-----------------------------------------------------------------*/
13595 /* genSystemThreadSleep - */
13596 /*-----------------------------------------------------------------*/
13597 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
13602 assert (nparms==1);
13603 /* save registers that need to be saved */
13604 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13605 ds390_rUmaskForOp (IC_RESULT(ic))));
13608 aopOp(to,ic,FALSE,FALSE);
13609 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
13610 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
13611 emitcode ("push","%s",
13612 aopGet(to,0,FALSE,TRUE,DP2_RESULT_REG));
13613 emitcode ("push","%s",
13614 aopGet(to,1,FALSE,TRUE,DP2_RESULT_REG));
13615 emitcode ("push","%s",
13616 aopGet(to,2,FALSE,TRUE,DP2_RESULT_REG));
13617 emitcode ("push","%s",
13618 aopGet(to,3,FALSE,TRUE,DP2_RESULT_REG));
13619 emitcode ("pop","ar3");
13620 emitcode ("pop","ar2");
13621 emitcode ("pop","ar1");
13622 emitcode ("pop","ar0");
13624 emitcode ("mov","r0,%s",
13625 aopGet(to,0,FALSE,TRUE,DP2_RESULT_REG));
13626 emitcode ("mov","r1,%s",
13627 aopGet(to,1,FALSE,TRUE,DP2_RESULT_REG));
13628 emitcode ("mov","r2,%s",
13629 aopGet(to,2,FALSE,TRUE,DP2_RESULT_REG));
13630 emitcode ("mov","r3,%s",
13631 aopGet(to,3,FALSE,TRUE,DP2_RESULT_REG));
13633 freeAsmop (to, NULL, ic, FALSE);
13635 /* suspend in acc */
13637 aopOp(s,ic,FALSE,FALSE);
13638 emitcode ("mov","a,%s",
13639 aopGet(s,0,FALSE,TRUE,NULL));
13640 freeAsmop (s, NULL, ic, FALSE);
13642 /* make the call */
13643 emitcode ("lcall","System_%s",name);
13645 unsavermask(rsave);
13648 /*-----------------------------------------------------------------*/
13649 /* genSystemThreadResume - */
13650 /*-----------------------------------------------------------------*/
13651 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
13656 assert (nparms==2);
13657 /* save registers that need to be saved */
13658 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13659 ds390_rUmaskForOp (IC_RESULT(ic))));
13665 aopOp(pid,ic,FALSE,FALSE);
13666 emitcode ("mov","r0,%s",
13667 aopGet(pid,0,FALSE,TRUE,DP2_RESULT_REG));
13668 freeAsmop (pid, NULL, ic, FALSE);
13671 aopOp(tid,ic,FALSE,FALSE);
13672 emitcode ("mov","a,%s",
13673 aopGet(tid,0,FALSE,TRUE,DP2_RESULT_REG));
13674 freeAsmop (tid, NULL, ic, FALSE);
13676 emitcode ("lcall","System_ThreadResume");
13678 /* put result into place */
13680 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13681 if (rsym->liveFrom != rsym->liveTo) {
13682 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13683 aopPut(IC_RESULT(ic),"a",0);
13684 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13687 unsavermask(rsave);
13690 /*-----------------------------------------------------------------*/
13691 /* genSystemProcessResume - */
13692 /*-----------------------------------------------------------------*/
13693 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
13698 assert (nparms==1);
13699 /* save registers that need to be saved */
13700 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13701 ds390_rUmaskForOp (IC_RESULT(ic))));
13706 aopOp(pid,ic,FALSE,FALSE);
13707 emitcode ("mov","a,%s",
13708 aopGet(pid,0,FALSE,TRUE,DP2_RESULT_REG));
13709 freeAsmop (pid, NULL, ic, FALSE);
13711 emitcode ("lcall","System_ProcessResume");
13713 unsavermask(rsave);
13716 /*-----------------------------------------------------------------*/
13718 /*-----------------------------------------------------------------*/
13719 static void genSystem (iCode *ic,int nparms,char *name)
13721 assert(nparms == 0);
13723 emitcode ("lcall","System_%s",name);
13726 /*-----------------------------------------------------------------*/
13727 /* genSystemPoll - */
13728 /*-----------------------------------------------------------------*/
13729 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
13734 assert (nparms==1);
13735 /* save registers that need to be saved */
13736 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13737 ds390_rUmaskForOp (IC_RESULT(ic))));
13740 aopOp (fp,ic,FALSE,FALSE);
13741 if (AOP_TYPE (fp) == AOP_IMMD) {
13742 emitcode ("mov", "dptr,%s",
13743 aopGet (fp, 0, TRUE, FALSE, DP2_RESULT_REG));
13744 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
13745 emitcode ("mov","dpl,%s",
13746 aopGet(fp,0,FALSE,FALSE,DP2_RESULT_REG));
13747 emitcode ("mov","dph,%s",
13748 aopGet(fp,1,FALSE,FALSE,DP2_RESULT_REG));
13749 emitcode ("mov","dpx,%s",
13750 aopGet(fp,2,FALSE,FALSE,DP2_RESULT_REG));
13752 freeAsmop (fp, NULL, ic, FALSE);
13754 emitcode ("lcall","System_%sPoll",name);
13756 /* put result into place */
13758 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13759 if (rsym->liveFrom != rsym->liveTo) {
13760 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13761 aopPut(IC_RESULT(ic),"a",0);
13762 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13765 unsavermask(rsave);
13768 /*-----------------------------------------------------------------*/
13769 /* genSystemGetCurrentID - */
13770 /*-----------------------------------------------------------------*/
13771 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
13773 assert (nparms==0);
13775 emitcode ("lcall","System_GetCurrent%sId",name);
13776 /* put result into place */
13778 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13779 if (rsym->liveFrom != rsym->liveTo) {
13780 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13781 aopPut(IC_RESULT(ic),"a",0);
13782 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13787 /*-----------------------------------------------------------------*/
13788 /* genDjnz - generate decrement & jump if not zero instrucion */
13789 /*-----------------------------------------------------------------*/
13791 genDjnz (iCode * ic, iCode * ifx)
13793 symbol *lbl, *lbl1;
13797 /* if the if condition has a false label
13798 then we cannot save */
13799 if (IC_FALSE (ifx))
13802 /* if the minus is not of the form a = a - 1 */
13803 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
13804 !IS_OP_LITERAL (IC_RIGHT (ic)))
13807 if (operandLitValue (IC_RIGHT (ic)) != 1)
13810 /* if the size of this greater than one then no
13812 if (getSize (operandType (IC_RESULT (ic))) > 1)
13815 /* otherwise we can save BIG */
13817 D (emitcode (";", "genDjnz"));
13819 lbl = newiTempLabel (NULL);
13820 lbl1 = newiTempLabel (NULL);
13822 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
13824 if (AOP_NEEDSACC(IC_RESULT(ic)))
13826 /* If the result is accessed indirectly via
13827 * the accumulator, we must explicitly write
13828 * it back after the decrement.
13830 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE, NULL);
13832 if (strcmp(rByte, "a"))
13834 /* Something is hopelessly wrong */
13835 fprintf(stderr, "*** warning: internal error at %s:%d\n",
13836 __FILE__, __LINE__);
13837 /* We can just give up; the generated code will be inefficient,
13838 * but what the hey.
13840 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13843 emitcode ("dec", "%s", rByte);
13844 aopPut (IC_RESULT (ic), rByte, 0);
13845 emitcode ("jnz", "!tlabel", lbl->key + 100);
13847 else if (IS_AOP_PREG (IC_RESULT (ic)))
13849 emitcode ("dec", "%s",
13850 aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL));
13851 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL));
13852 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13853 ifx->generated = 1;
13854 emitcode ("jnz", "!tlabel", lbl->key + 100);
13858 emitcode ("djnz", "%s,!tlabel", aopGet (IC_RESULT (ic), 0, FALSE, TRUE, NULL),
13861 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
13863 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
13866 if (!ifx->generated)
13867 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13868 ifx->generated = 1;
13872 /*-----------------------------------------------------------------*/
13873 /* genReceive - generate code for a receive iCode */
13874 /*-----------------------------------------------------------------*/
13876 genReceive (iCode * ic)
13878 int size = getSize (operandType (IC_RESULT (ic)));
13882 D (emitcode (";", "genReceive"));
13884 if (ic->argreg == 1)
13886 /* first parameter */
13887 if (AOP_IS_STR(IC_RESULT(ic)))
13889 /* Nothing to do: it's already in the proper place. */
13896 useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
13897 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
13898 IS_TRUE_SYMOP (IC_RESULT (ic)));
13901 aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
13904 /* Sanity checking... */
13905 if (AOP_USESDPTR(IC_RESULT(ic)))
13907 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
13908 "genReceive got unexpected DPTR.");
13910 assignResultValue (IC_RESULT (ic), NULL);
13913 else if (ic->argreg > 12)
13914 { /* bit parameters */
13915 if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
13917 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
13918 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
13919 outBitC(IC_RESULT (ic));
13924 /* second receive onwards */
13925 /* this gets a little tricky since unused receives will be
13926 eliminated, we have saved the reg in the type field . and
13927 we use that to figure out which register to use */
13928 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
13929 rb1off = ic->argreg;
13932 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
13935 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13938 /*-----------------------------------------------------------------*/
13939 /* genDummyRead - generate code for dummy read of volatiles */
13940 /*-----------------------------------------------------------------*/
13942 genDummyRead (iCode * ic)
13947 D (emitcode(";", "genDummyRead"));
13949 op = IC_RIGHT (ic);
13950 if (op && IS_SYMOP (op))
13952 aopOp (op, ic, FALSE, FALSE);
13954 /* if the result is a bit */
13955 if (AOP_TYPE (op) == AOP_CRY)
13956 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13959 /* bit variables done */
13961 size = AOP_SIZE (op);
13965 MOVA (aopGet (op, offset, FALSE, FALSE, FALSE));
13970 freeAsmop (op, NULL, ic, TRUE);
13974 if (op && IS_SYMOP (op))
13976 aopOp (op, ic, FALSE, FALSE);
13978 /* if the result is a bit */
13979 if (AOP_TYPE (op) == AOP_CRY)
13980 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13983 /* bit variables done */
13985 size = AOP_SIZE (op);
13989 MOVA (aopGet (op, offset, FALSE, FALSE, FALSE));
13994 freeAsmop (op, NULL, ic, TRUE);
13998 /*-----------------------------------------------------------------*/
13999 /* genCritical - generate code for start of a critical sequence */
14000 /*-----------------------------------------------------------------*/
14002 genCritical (iCode *ic)
14004 symbol *tlbl = newiTempLabel (NULL);
14006 D (emitcode(";", "genCritical"));
14008 if (IC_RESULT (ic))
14010 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
14011 aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
14012 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
14013 aopPut (IC_RESULT (ic), zero, 0);
14015 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
14019 emitcode ("setb", "c");
14020 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
14021 emitcode ("clr", "c");
14023 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
14027 /*-----------------------------------------------------------------*/
14028 /* genEndCritical - generate code for end of a critical sequence */
14029 /*-----------------------------------------------------------------*/
14031 genEndCritical (iCode *ic)
14033 D(emitcode("; genEndCritical",""));
14037 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
14038 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
14040 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
14041 emitcode ("mov", "ea,c");
14045 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE, FALSE));
14046 emitcode ("rrc", "a");
14047 emitcode ("mov", "ea,c");
14049 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
14053 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
14054 emitcode ("mov", "ea,c");
14060 /*-----------------------------------------------------------------*/
14061 /* genBuiltIn - calls the appropriate function to generating code */
14062 /* for a built in function */
14063 /*-----------------------------------------------------------------*/
14064 static void genBuiltIn (iCode *ic)
14066 operand *bi_parms[MAX_BUILTIN_ARGS];
14071 /* get all the arguments for a built in function */
14072 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
14074 /* which function is it */
14075 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
14076 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
14077 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
14078 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
14079 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
14080 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
14081 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
14082 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
14083 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
14084 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
14085 genMemsetX(bi_iCode,nbi_parms,bi_parms);
14086 } else if (strcmp(bif->name,"__builtin_inp")==0) {
14087 genInp(bi_iCode,nbi_parms,bi_parms);
14088 } else if (strcmp(bif->name,"__builtin_outp")==0) {
14089 genOutp(bi_iCode,nbi_parms,bi_parms);
14090 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
14091 genSwapW(bi_iCode,nbi_parms,bi_parms);
14092 /* JavaNative builtIns */
14093 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
14094 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
14095 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
14096 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
14097 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
14098 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
14099 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
14100 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
14101 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
14102 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
14103 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
14104 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
14105 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
14106 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
14107 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
14108 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
14109 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
14110 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
14111 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
14112 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
14113 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
14114 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
14115 } else if (strcmp(bif->name,"MM_Malloc")==0) {
14116 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
14117 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
14118 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
14119 } else if (strcmp(bif->name,"MM_Free")==0) {
14120 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
14121 } else if (strcmp(bif->name,"MM_Deref")==0) {
14122 genMMDeref(bi_iCode,nbi_parms,bi_parms);
14123 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
14124 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
14125 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
14126 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
14127 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
14128 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
14129 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
14130 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
14131 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
14132 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
14133 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
14134 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
14135 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
14136 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
14137 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
14138 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
14139 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
14140 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
14141 } else if (strcmp(bif->name,"System_SaveThread")==0) {
14142 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
14143 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
14144 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
14145 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
14146 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
14147 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
14148 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
14149 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
14150 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
14151 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
14152 genSystem(bi_iCode,nbi_parms,"ProcessYield");
14153 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
14154 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
14155 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
14156 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
14157 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
14158 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
14159 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
14160 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
14161 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
14162 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
14164 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
14170 /*-----------------------------------------------------------------*/
14171 /* gen390Code - generate code for Dallas 390 based controllers */
14172 /*-----------------------------------------------------------------*/
14174 gen390Code (iCode * lic)
14179 _G.currentFunc = NULL;
14180 lineHead = lineCurr = NULL;
14181 dptrn[1][0] = "dpl1";
14182 dptrn[1][1] = "dph1";
14183 dptrn[1][2] = "dpx1";
14185 if (options.model == MODEL_FLAT24) {
14186 fReturnSizeDS390 = 5;
14187 fReturn = fReturn24;
14189 fReturnSizeDS390 = 4;
14190 fReturn = fReturn16;
14191 options.stack10bit=0;
14194 /* print the allocation information */
14195 if (allocInfo && currFunc)
14196 printAllocInfo (currFunc, codeOutFile);
14198 /* if debug information required */
14199 if (options.debug && currFunc)
14201 debugFile->writeFunction (currFunc, lic);
14203 /* stack pointer name */
14204 if (options.useXstack)
14210 for (ic = lic; ic; ic = ic->next)
14212 _G.current_iCode = ic;
14214 if (ic->lineno && cln != ic->lineno)
14218 debugFile->writeCLine (ic);
14220 if (!options.noCcodeInAsm) {
14221 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
14222 printCLine(ic->filename, ic->lineno));
14226 if (options.iCodeInAsm) {
14227 emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
14229 /* if the result is marked as
14230 spilt and rematerializable or code for
14231 this has already been generated then
14233 if (resultRemat (ic) || ic->generated)
14236 /* depending on the operation */
14256 /* IPOP happens only when trying to restore a
14257 spilt live range, if there is an ifx statement
14258 following this pop then the if statement might
14259 be using some of the registers being popped which
14260 would destory the contents of the register so
14261 we need to check for this condition and handle it */
14263 ic->next->op == IFX &&
14264 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
14265 genIfx (ic->next, ic);
14283 genEndFunction (ic);
14303 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
14320 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
14324 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
14331 /* note these two are xlated by algebraic equivalence
14332 during parsing SDCC.y */
14333 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
14334 "got '>=' or '<=' shouldn't have come here");
14338 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
14350 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
14354 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
14358 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
14382 genRightShift (ic);
14385 case GET_VALUE_AT_ADDRESS:
14387 hasInc (IC_LEFT (ic), ic,
14388 getSize (operandType (IC_RESULT (ic)))));
14392 if (POINTER_SET (ic))
14394 hasInc (IC_RESULT (ic), ic,
14395 getSize (operandType (IC_RIGHT (ic)))));
14421 if (ic->builtinSEND)
14424 addSet (&_G.sendSet, ic);
14427 case DUMMY_READ_VOLATILE:
14436 genEndCritical (ic);
14443 #if 0 // obsolete, and buggy for != xdata
14455 /* now we are ready to call the
14456 peep hole optimizer */
14457 if (!options.nopeep)
14458 peepHole (&lineHead);
14460 /* now do the actual printing */
14461 printLine (lineHead, codeOutFile);