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))
1419 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1430 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1436 /* Error case --- will have been caught already */
1442 /*-------------------------------------------------------------------*/
1443 /* aopGet - for fetching value of the aop */
1445 /* Set saveAcc to NULL if you are sure it is OK to clobber the value */
1446 /* in the accumulator. Set it to the name of a free register */
1447 /* if acc must be preserved; the register will be used to preserve */
1448 /* acc temporarily and to return the result byte. */
1449 /*-------------------------------------------------------------------*/
1451 aopGet (operand * oper,
1457 asmop * aop = AOP (oper);
1459 /* offset is greater than
1461 if (offset > (aop->size - 1) &&
1462 aop->type != AOP_LIT)
1465 /* depending on type */
1473 /* if we need to increment it */
1474 while (offset > aop->coff)
1476 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1480 while (offset < aop->coff)
1482 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1489 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1490 return (dname ? "acc" : "a");
1492 SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1493 return Safe_strdup(buffer);
1496 assert(offset <= 3);
1497 return dptrn[aop->aopu.dptr][offset];
1502 if (aop->type == AOP_DPTR2)
1510 // if (aop->type != AOP_DPTR2)
1512 // if (saveAccWarn) { fprintf(stderr, "saveAcc for DPTR...\n"); }
1513 // emitcode(";", "spanky: saveAcc for DPTR");
1516 emitcode ("xch", "a, %s", saveAcc);
1521 while (offset > aop->coff)
1523 emitcode ("inc", "dptr");
1527 while (offset < aop->coff)
1529 emitcode ("lcall", "__decdptr");
1536 emitcode ("clr", "a");
1537 emitcode ("movc", "a,@a+dptr");
1541 emitcode ("movx", "a,@dptr");
1544 if (aop->type == AOP_DPTR2)
1552 emitcode ("xch", "a, %s", saveAcc);
1553 // if (strcmp(saveAcc, "_ap"))
1555 // emitcode(";", "spiffy: non _ap return from aopGet.");
1560 return (dname ? "acc" : "a");
1563 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1565 SNPRINTF(buffer, sizeof(buffer),
1566 "%s",aop->aopu.aop_immd.aop_immd2);
1570 SNPRINTF(buffer, sizeof(buffer),
1571 "#%s", aop->aopu.aop_immd.aop_immd1);
1577 tsprintf(buffer, sizeof(buffer),
1578 "#!his",aop->aopu.aop_immd.aop_immd1);
1581 tsprintf(buffer, sizeof(buffer),
1582 "#!hihis",aop->aopu.aop_immd.aop_immd1);
1585 tsprintf(buffer, sizeof(buffer),
1586 "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1588 default: /* should not need this (just in case) */
1589 SNPRINTF (buffer, sizeof(buffer),
1591 aop->aopu.aop_immd.aop_immd1,
1597 SNPRINTF (buffer, sizeof(buffer),
1599 aop->aopu.aop_immd.aop_immd1);
1601 return Safe_strdup(buffer);
1604 if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
1606 SNPRINTF (buffer, sizeof(buffer),
1608 aop->aopu.aop_dir, offset * 8);
1612 SNPRINTF (buffer, sizeof(buffer),
1619 SNPRINTF (buffer, sizeof(buffer),
1624 return Safe_strdup(buffer);
1628 return aop->aopu.aop_reg[offset]->dname;
1630 return aop->aopu.aop_reg[offset]->name;
1633 emitcode ("clr", "a");
1634 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1635 emitcode ("rlc", "a");
1636 return (dname ? "acc" : "a");
1639 if (!offset && dname)
1641 return aop->aopu.aop_str[offset];
1644 return aopLiteral (aop->aopu.aop_lit, offset);
1648 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1652 return aop->aopu.aop_str[offset];
1656 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1657 "aopget got unsupported aop->type");
1660 return NULL; // not reached, but makes compiler happy.
1663 /*-----------------------------------------------------------------*/
1664 /* aopPut - puts a string for a aop and indicates if acc is in use */
1665 /*-----------------------------------------------------------------*/
1667 aopPut (operand * result, const char *s, int offset)
1669 bool bvolatile = isOperandVolatile (result, FALSE);
1670 bool accuse = FALSE;
1671 asmop * aop = AOP (result);
1673 if (aop->size && offset > (aop->size - 1))
1675 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1676 "aopPut got offset > aop->size");
1680 /* will assign value to value */
1681 /* depending on where it is ofcourse */
1685 MOVA (s); /* read s in case it was volatile */
1690 if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1692 SNPRINTF (buffer, sizeof(buffer),
1694 aop->aopu.aop_dir, offset * 8);
1698 SNPRINTF (buffer, sizeof(buffer),
1700 aop->aopu.aop_dir, offset);
1704 SNPRINTF (buffer, sizeof(buffer),
1709 if (strcmp (buffer, s) || bvolatile)
1711 emitcode ("mov", "%s,%s", buffer, s);
1713 if (!strcmp (buffer, "acc"))
1720 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1721 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1724 strcmp (s, "r0") == 0 ||
1725 strcmp (s, "r1") == 0 ||
1726 strcmp (s, "r2") == 0 ||
1727 strcmp (s, "r3") == 0 ||
1728 strcmp (s, "r4") == 0 ||
1729 strcmp (s, "r5") == 0 ||
1730 strcmp (s, "r6") == 0 ||
1731 strcmp (s, "r7") == 0)
1733 emitcode ("mov", "%s,%s",
1734 aop->aopu.aop_reg[offset]->dname, s);
1738 emitcode ("mov", "%s,%s",
1739 aop->aopu.aop_reg[offset]->name, s);
1745 emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1751 if (aop->type == AOP_DPTR2)
1759 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1760 "aopPut writing to code space");
1764 while (offset > aop->coff)
1767 emitcode ("inc", "dptr");
1770 while (offset < aop->coff)
1773 emitcode ("lcall", "__decdptr");
1778 /* if not in accumulator */
1781 emitcode ("movx", "@dptr,a");
1783 if (aop->type == AOP_DPTR2)
1791 while (offset > aop->coff)
1794 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1796 while (offset < aop->coff)
1799 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1806 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1811 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1813 else if (strcmp (s, "r0") == 0 ||
1814 strcmp (s, "r1") == 0 ||
1815 strcmp (s, "r2") == 0 ||
1816 strcmp (s, "r3") == 0 ||
1817 strcmp (s, "r4") == 0 ||
1818 strcmp (s, "r5") == 0 ||
1819 strcmp (s, "r6") == 0 ||
1820 strcmp (s, "r7") == 0)
1823 SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1824 emitcode ("mov", "@%s,%s",
1825 aop->aopu.aop_ptr->name, buffer);
1829 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1834 if (strcmp (s, "a") == 0)
1835 emitcode ("push", "acc");
1839 emitcode ("push", "acc");
1841 emitcode ("push", s);
1847 /* if not bit variable */
1848 if (!aop->aopu.aop_dir)
1850 /* inefficient: move carry into A and use jz/jnz */
1851 emitcode ("clr", "a");
1852 emitcode ("rlc", "a");
1858 emitcode ("clr", "%s", aop->aopu.aop_dir);
1860 emitcode ("setb", "%s", aop->aopu.aop_dir);
1861 else if (!strcmp (s, "c"))
1862 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1863 else if (strcmp (s, aop->aopu.aop_dir))
1866 /* set C, if a >= 1 */
1867 emitcode ("add", "a,#!constbyte",0xff);
1868 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1875 if (strcmp (aop->aopu.aop_str[offset], s) || bvolatile)
1876 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1882 if (!offset && (strcmp (s, "acc") == 0) && !bvolatile)
1885 if (strcmp (aop->aopu.aop_str[offset], s) && !bvolatile)
1886 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1890 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1891 "aopPut got unsupported aop->type");
1899 /*--------------------------------------------------------------------*/
1900 /* reAdjustPreg - points a register back to where it should (coff==0) */
1901 /*--------------------------------------------------------------------*/
1903 reAdjustPreg (asmop * aop)
1905 if ((aop->coff==0) || (aop->size <= 1))
1913 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1917 if (aop->type == AOP_DPTR2)
1924 emitcode ("lcall", "__decdptr");
1927 if (aop->type == AOP_DPTR2)
1936 /*-----------------------------------------------------------------*/
1937 /* opIsGptr: returns non-zero if the passed operand is */
1938 /* a generic pointer type. */
1939 /*-----------------------------------------------------------------*/
1941 opIsGptr (operand * op)
1943 sym_link *type = operandType (op);
1945 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1952 /*-----------------------------------------------------------------*/
1953 /* getDataSize - get the operand data size */
1954 /*-----------------------------------------------------------------*/
1956 getDataSize (operand * op)
1959 size = AOP_SIZE (op);
1960 if (size == GPTRSIZE)
1962 sym_link *type = operandType (op);
1963 if (IS_GENPTR (type))
1965 /* generic pointer; arithmetic operations
1966 * should ignore the high byte (pointer type).
1974 /*-----------------------------------------------------------------*/
1975 /* outAcc - output Acc */
1976 /*-----------------------------------------------------------------*/
1978 outAcc (operand * result)
1981 size = getDataSize (result);
1984 aopPut (result, "a", 0);
1987 /* unsigned or positive */
1990 aopPut (result, zero, offset++);
1995 /*-----------------------------------------------------------------*/
1996 /* outBitC - output a bit C */
1997 /*-----------------------------------------------------------------*/
1999 outBitC (operand * result)
2001 /* if the result is bit */
2002 if (AOP_TYPE (result) == AOP_CRY)
2004 aopPut (result, "c", 0);
2008 emitcode ("clr", "a");
2009 emitcode ("rlc", "a");
2014 /*-----------------------------------------------------------------*/
2015 /* toBoolean - emit code for orl a,operator(sizeop) */
2016 /*-----------------------------------------------------------------*/
2018 toBoolean (operand * oper)
2020 int size = AOP_SIZE (oper) - 1;
2024 /* The generic part of a generic pointer should
2025 * not participate in it's truth value.
2027 * i.e. 0x10000000 is zero.
2029 if (opIsGptr (oper))
2031 D (emitcode (";", "toBoolean: generic ptr special case."));
2035 _startLazyDPSEvaluation ();
2036 MOVA (aopGet (oper, 0, FALSE, FALSE, NULL));
2037 if (AOP_NEEDSACC (oper) && size && (AOP (oper)->type != AOP_ACC))
2040 emitcode("mov", "b,a");
2043 MOVA (aopGet (oper, offset++, FALSE, FALSE, NULL));
2044 emitcode ("orl", "b,a");
2046 MOVA (aopGet (oper, offset++, FALSE, FALSE, NULL));
2047 emitcode ("orl", "a,b");
2054 emitcode ("orl", "a,%s",
2055 aopGet (oper, offset++, FALSE, FALSE, NULL));
2058 _endLazyDPSEvaluation ();
2062 /*-----------------------------------------------------------------*/
2063 /* genNot - generate code for ! operation */
2064 /*-----------------------------------------------------------------*/
2070 D (emitcode (";", "genNot"));
2072 /* assign asmOps to operand & result */
2073 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2074 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
2076 /* if in bit space then a special case */
2077 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2079 /* if left==result then cpl bit */
2080 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2082 emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2086 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2087 emitcode ("cpl", "c");
2088 outBitC (IC_RESULT (ic));
2093 toBoolean (IC_LEFT (ic));
2095 /* set C, if a == 0 */
2096 tlbl = newiTempLabel (NULL);
2097 emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
2099 outBitC (IC_RESULT (ic));
2102 /* release the aops */
2103 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2104 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2108 /*-----------------------------------------------------------------*/
2109 /* genCpl - generate code for complement */
2110 /*-----------------------------------------------------------------*/
2117 sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
2119 D(emitcode (";", "genCpl"));
2121 /* assign asmOps to operand & result */
2122 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2123 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
2125 /* special case if in bit space */
2126 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2130 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
2131 (SPEC_USIGN (letype) && IS_CHAR (letype)))
2133 /* promotion rules are responsible for this strange result:
2134 bit -> int -> ~int -> bit
2135 uchar -> int -> ~int -> bit
2137 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
2141 tlbl=newiTempLabel(NULL);
2142 l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE, NULL);
2143 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
2144 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
2145 IS_AOP_PREG (IC_LEFT (ic)))
2147 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
2152 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
2155 outBitC (IC_RESULT(ic));
2159 size = AOP_SIZE (IC_RESULT (ic));
2160 _startLazyDPSEvaluation ();
2163 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL);
2165 emitcode ("cpl", "a");
2166 aopPut (IC_RESULT (ic), "a", offset++);
2168 _endLazyDPSEvaluation ();
2172 /* release the aops */
2173 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2174 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2177 /*-----------------------------------------------------------------*/
2178 /* genUminusFloat - unary minus for floating points */
2179 /*-----------------------------------------------------------------*/
2181 genUminusFloat (operand * op, operand * result)
2183 int size, offset = 0;
2186 D (emitcode (";", "genUminusFloat"));
2188 /* for this we just copy and then flip the bit */
2190 _startLazyDPSEvaluation ();
2191 size = AOP_SIZE (op) - 1;
2196 aopGet (op, offset, FALSE, FALSE, NULL),
2201 l = aopGet (op, offset, FALSE, FALSE, NULL);
2204 emitcode ("cpl", "acc.7");
2205 aopPut (result, "a", offset);
2206 _endLazyDPSEvaluation ();
2209 /*-----------------------------------------------------------------*/
2210 /* genUminus - unary minus code generation */
2211 /*-----------------------------------------------------------------*/
2213 genUminus (iCode * ic)
2218 D (emitcode (";", "genUminus"));
2221 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2222 aopOp (IC_RESULT (ic), ic, TRUE, (AOP_TYPE(IC_LEFT (ic)) == AOP_DPTR));
2224 /* if both in bit space then special
2226 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2227 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2230 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2231 emitcode ("cpl", "c");
2232 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2236 optype = operandType (IC_LEFT (ic));
2238 /* if float then do float stuff */
2239 if (IS_FLOAT (optype))
2241 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2245 /* otherwise subtract from zero */
2246 size = AOP_SIZE (IC_LEFT (ic));
2248 _startLazyDPSEvaluation ();
2251 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL);
2252 if (!strcmp (l, "a"))
2256 emitcode ("cpl", "a");
2257 emitcode ("addc", "a,#0");
2263 emitcode ("clr", "a");
2264 emitcode ("subb", "a,%s", l);
2266 aopPut (IC_RESULT (ic), "a", offset++);
2268 _endLazyDPSEvaluation ();
2270 /* if any remaining bytes in the result */
2271 /* we just need to propagate the sign */
2272 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2274 emitcode ("rlc", "a");
2275 emitcode ("subb", "a,acc");
2277 aopPut (IC_RESULT (ic), "a", offset++);
2281 /* release the aops */
2282 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2283 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2286 /*-----------------------------------------------------------------*/
2287 /* savermask - saves registers in the mask */
2288 /*-----------------------------------------------------------------*/
2289 static void savermask(bitVect *rs_mask)
2293 if (options.useXstack)
2295 if (bitVectBitValue (rs_mask, R0_IDX))
2296 emitcode ("mov", "b,r0");
2297 emitcode ("mov", "r0,%s", spname);
2298 for (i = 0; i < ds390_nRegs; i++)
2300 if (bitVectBitValue (rs_mask, i))
2303 emitcode ("mov", "a,b");
2305 emitcode ("mov", "a,%s", REG_WITH_INDEX (i)->name);
2306 emitcode ("movx", "@r0,a");
2307 emitcode ("inc", "r0");
2310 emitcode ("mov", "%s,r0", spname);
2311 if (bitVectBitValue (rs_mask, R0_IDX))
2312 emitcode ("mov", "r0,b");
2316 bool bits_pushed = FALSE;
2317 for (i = 0; i < ds390_nRegs; i++)
2319 if (bitVectBitValue (rs_mask, i))
2321 bits_pushed = pushReg (i, bits_pushed);
2327 /*-----------------------------------------------------------------*/
2328 /* saveRegisters - will look for a call and save the registers */
2329 /*-----------------------------------------------------------------*/
2331 saveRegisters (iCode * lic)
2337 for (ic = lic; ic; ic = ic->next)
2338 if (ic->op == CALL || ic->op == PCALL)
2343 fprintf (stderr, "found parameter push with no function call\n");
2347 /* if the registers have been saved already or don't need to be then
2350 || (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))) && !TARGET_IS_DS400) )
2353 /* special case if DPTR alive across a function call then must save it
2354 even though callee saves */
2355 if (IS_SYMOP(IC_LEFT(ic)) &&
2356 IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type))
2359 rsave = newBitVect(ic->rMask->size);
2360 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2361 if (bitVectBitValue(ic->rMask,i))
2362 rsave = bitVectSetBit(rsave,i);
2364 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2368 /* save the registers in use at this time but skip the
2369 ones for the result */
2370 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2371 ds390_rUmaskForOp (IC_RESULT(ic)));
2377 /*-----------------------------------------------------------------*/
2378 /* usavermask - restore registers with mask */
2379 /*-----------------------------------------------------------------*/
2380 static void unsavermask(bitVect *rs_mask)
2384 if (options.useXstack)
2386 emitcode ("mov", "r0,%s", spname);
2387 for (i = ds390_nRegs; i >= 0; i--)
2389 if (bitVectBitValue (rs_mask, i))
2391 regs * reg = REG_WITH_INDEX (i);
2392 emitcode ("dec", "r0");
2393 emitcode ("movx", "a,@r0");
2396 emitcode ("push", "acc");
2400 emitcode ("mov", "%s,a", reg->name);
2404 emitcode ("mov", "%s,r0", spname);
2405 if (bitVectBitValue (rs_mask, R0_IDX))
2407 emitcode ("pop", "ar0");
2412 bool bits_popped = FALSE;
2413 for (i = ds390_nRegs; i >= 0; i--)
2415 if (bitVectBitValue (rs_mask, i))
2417 bits_popped = popReg (i, bits_popped);
2423 /*-----------------------------------------------------------------*/
2424 /* unsaveRegisters - pop the pushed registers */
2425 /*-----------------------------------------------------------------*/
2427 unsaveRegisters (iCode * ic)
2431 if (IS_SYMOP(IC_LEFT (ic)) &&
2432 IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2434 rsave = newBitVect(ic->rMask->size);
2435 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2436 if (bitVectBitValue(ic->rMask,i))
2437 rsave = bitVectSetBit(rsave,i);
2439 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2441 /* restore the registers in use at this time but skip the
2442 ones for the result */
2443 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2444 ds390_rUmaskForOp (IC_RESULT(ic)));
2450 /*-----------------------------------------------------------------*/
2452 /*-----------------------------------------------------------------*/
2454 pushSide (operand * oper, int size)
2457 _startLazyDPSEvaluation ();
2460 char *l = aopGet (oper, offset++, FALSE, TRUE, NULL);
2461 if (AOP_TYPE (oper) != AOP_REG &&
2462 AOP_TYPE (oper) != AOP_DIR &&
2466 emitcode ("push", "acc");
2470 emitcode ("push", "%s", l);
2473 _endLazyDPSEvaluation ();
2476 /*-----------------------------------------------------------------*/
2477 /* assignResultValue - also indicates if acc is in use afterwards */
2478 /*-----------------------------------------------------------------*/
2480 assignResultValue (operand * oper, operand * func)
2483 unsigned size = AOP_SIZE (oper);
2484 bool accuse = FALSE;
2485 bool pushedA = FALSE;
2487 if (func && IS_BIT (OP_SYM_ETYPE (func)))
2493 if (size == fReturnSizeDS390)
2495 /* I don't think this case can ever happen... */
2496 /* ACC is the last part of this. If writing the result
2497 * uses ACC, we must preserve it.
2499 if (AOP_NEEDSACC(oper))
2501 emitcode(";", "assignResultValue special case for ACC.");
2502 emitcode("push", "acc");
2508 _startLazyDPSEvaluation ();
2511 accuse |= aopPut (oper, fReturn[offset], offset);
2514 _endLazyDPSEvaluation ();
2518 emitcode ("pop", "acc");
2519 accuse |= aopPut (oper, "a", offset);
2525 /*-----------------------------------------------------------------*/
2526 /* genXpush - pushes onto the external stack */
2527 /*-----------------------------------------------------------------*/
2529 genXpush (iCode * ic)
2531 asmop *aop = newAsmop (0);
2533 int size, offset = 0;
2535 D (emitcode (";", "genXpush"));
2537 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2538 r = getFreePtr (ic, &aop, FALSE);
2540 size = AOP_SIZE (IC_LEFT (ic));
2544 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
2545 emitcode ("mov", "%s,_spx", r->name);
2546 emitcode ("inc", "_spx"); // allocate space first
2547 emitcode ("movx", "@%s,a", r->name);
2551 // allocate space first
2552 emitcode ("mov", "%s,_spx", r->name);
2554 emitcode ("add", "a,#%d", size);
2555 emitcode ("mov", "_spx,a");
2557 _startLazyDPSEvaluation ();
2560 MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE, NULL));
2561 emitcode ("movx", "@%s,a", r->name);
2562 emitcode ("inc", "%s", r->name);
2564 _endLazyDPSEvaluation ();
2567 freeAsmop (NULL, aop, ic, TRUE);
2568 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2571 /*-----------------------------------------------------------------*/
2572 /* genIpush - generate code for pushing this gets a little complex */
2573 /*-----------------------------------------------------------------*/
2575 genIpush (iCode * ic)
2577 int size, offset = 0;
2581 D (emitcode (";", "genIpush"));
2583 /* if this is not a parm push : ie. it is spill push
2584 and spill push is always done on the local stack */
2588 /* and the item is spilt then do nothing */
2589 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2592 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2593 size = AOP_SIZE (IC_LEFT (ic));
2594 /* push it on the stack */
2595 _startLazyDPSEvaluation ();
2598 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE, NULL);
2604 emitcode ("push", "%s", l);
2606 _endLazyDPSEvaluation ();
2610 /* this is a parameter push: in this case we call
2611 the routine to find the call and save those
2612 registers that need to be saved */
2615 /* if use external stack then call the external
2616 stack pushing routine */
2617 if (options.useXstack)
2623 /* then do the push */
2624 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2626 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2627 size = AOP_SIZE (IC_LEFT (ic));
2629 _startLazyDPSEvaluation ();
2632 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE, NULL);
2633 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2634 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2637 if (strcmp (l, prev) || *l == '@')
2639 emitcode ("push", "acc");
2643 emitcode ("push", "%s", l);
2647 _endLazyDPSEvaluation ();
2649 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2652 /*-----------------------------------------------------------------*/
2653 /* genIpop - recover the registers: can happen only for spilling */
2654 /*-----------------------------------------------------------------*/
2656 genIpop (iCode * ic)
2660 D (emitcode (";", "genIpop"));
2662 /* if the temp was not pushed then */
2663 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2666 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2667 size = AOP_SIZE (IC_LEFT (ic));
2668 offset = (size - 1);
2669 _startLazyDPSEvaluation ();
2672 emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2673 FALSE, TRUE, NULL));
2675 _endLazyDPSEvaluation ();
2677 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2680 /*-----------------------------------------------------------------*/
2681 /* saveRBank - saves an entire register bank on the stack */
2682 /*-----------------------------------------------------------------*/
2684 saveRBank (int bank, iCode * ic, bool pushPsw)
2687 int count = 8 + (ds390_nBitRegs/8) + (pushPsw ? 1 : 0);
2691 if (options.useXstack)
2695 /* Assume r0 is available for use. */
2696 r = REG_WITH_INDEX (R0_IDX);;
2701 r = getFreePtr (ic, &aop, FALSE);
2703 // allocate space first
2704 emitcode ("mov", "%s,_spx", r->name);
2706 emitcode ("add", "a,#%d", count);
2707 emitcode ("mov", "_spx,a");
2710 for (i = 0; i < 8; i++) /* only R0-R7 needs saving */
2712 if (options.useXstack)
2714 emitcode ("mov", "a,(%s+%d)",
2715 regs390[i].base, 8 * bank + regs390[i].offset);
2716 emitcode ("movx", "@%s,a", r->name);
2718 emitcode ("inc", "%s", r->name);
2721 emitcode ("push", "(%s+%d)",
2722 regs390[i].base, 8 * bank + regs390[i].offset);
2725 if (ds390_nBitRegs > 0)
2727 if (options.useXstack)
2729 emitcode ("mov", "a,bits");
2730 emitcode ("movx", "@%s,a", r->name);
2732 emitcode ("inc", "%s", r->name);
2736 emitcode ("push", "bits");
2743 if (options.useXstack)
2745 emitcode ("mov", "a,psw");
2746 emitcode ("movx", "@%s,a", r->name);
2750 emitcode ("push", "psw");
2753 emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2758 freeAsmop (NULL, aop, ic, TRUE);
2767 /*-----------------------------------------------------------------*/
2768 /* unsaveRBank - restores the register bank from stack */
2769 /*-----------------------------------------------------------------*/
2771 unsaveRBank (int bank, iCode * ic, bool popPsw)
2777 if (options.useXstack)
2781 /* Assume r0 is available for use. */
2782 r = REG_WITH_INDEX (R0_IDX);;
2787 r = getFreePtr (ic, &aop, FALSE);
2789 emitcode ("mov", "%s,_spx", r->name);
2794 if (options.useXstack)
2796 emitcode ("dec", "%s", r->name);
2797 emitcode ("movx", "a,@%s", r->name);
2798 emitcode ("mov", "psw,a");
2802 emitcode ("pop", "psw");
2806 if (ds390_nBitRegs > 0)
2808 if (options.useXstack)
2810 emitcode ("dec", "%s", r->name);
2811 emitcode ("movx", "a,@%s", r->name);
2812 emitcode ("mov", "bits,a");
2816 emitcode ("pop", "bits");
2820 for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2822 if (options.useXstack)
2824 emitcode ("dec", "%s", r->name);
2825 emitcode ("movx", "a,@%s", r->name);
2826 emitcode ("mov", "(%s+%d),a",
2827 regs390[i].base, 8 * bank + regs390[i].offset);
2831 emitcode ("pop", "(%s+%d)",
2832 regs390[i].base, 8 * bank + regs390[i].offset);
2836 if (options.useXstack)
2838 emitcode ("mov", "_spx,%s", r->name);
2843 freeAsmop (NULL, aop, ic, TRUE);
2847 /*-----------------------------------------------------------------*/
2848 /* genSend - gen code for SEND */
2849 /*-----------------------------------------------------------------*/
2850 static void genSend(set *sendSet)
2855 static int rb1_count = 0;
2857 /* first we do all bit parameters */
2858 for (sic = setFirstItem (sendSet); sic;
2859 sic = setNextItem (sendSet))
2861 if (sic->argreg > 12)
2863 int bit = sic->argreg-13;
2865 aopOp (IC_LEFT (sic), sic, FALSE,
2866 (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2868 /* if left is a literal then
2869 we know what the value is */
2870 if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2872 if (((int) operandLitValue (IC_LEFT (sic))))
2873 emitcode ("setb", "b[%d]", bit);
2875 emitcode ("clr", "b[%d]", bit);
2877 else if (AOP_TYPE (IC_LEFT (sic)) == AOP_CRY)
2879 char *l = AOP (IC_LEFT (sic))->aopu.aop_dir;
2880 if (strcmp (l, "c"))
2881 emitcode ("mov", "c,%s", l);
2882 emitcode ("mov", "b[%d],c", bit);
2887 toBoolean (IC_LEFT (sic));
2888 /* set C, if a >= 1 */
2889 emitcode ("add", "a,#0xff");
2890 emitcode ("mov", "b[%d],c", bit);
2895 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2901 saveRegisters (setFirstItem (sendSet));
2902 emitcode ("mov", "bits,b");
2905 /* then we do all other parameters */
2906 for (sic = setFirstItem (sendSet); sic;
2907 sic = setNextItem (sendSet))
2909 if (sic->argreg <= 12)
2911 int size, offset = 0;
2913 size = getSize (operandType (IC_LEFT (sic)));
2914 D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2915 if (sendCount == 0) { /* first parameter */
2916 // we know that dpl(hxb) is the result, so
2918 _startLazyDPSEvaluation ();
2920 aopOp (IC_LEFT (sic), sic, FALSE,
2921 (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2923 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2927 char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE, NULL);
2928 if (strcmp (l, fReturn[offset]))
2930 emitcode ("mov", "%s,%s", fReturn[offset], l);
2934 _endLazyDPSEvaluation ();
2935 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2937 } else { /* if more parameter in registers */
2938 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2940 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (IC_LEFT (sic), offset++,
2941 FALSE, FALSE, NULL));
2943 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2951 adjustEsp(const char *reg)
2953 emitcode ("anl","%s,#3", reg);
2954 if (TARGET_IS_DS400)
2956 emitcode ("orl","%s,#!constbyte",
2958 (options.stack_loc >> 8) & 0xff);
2962 /*-----------------------------------------------------------------*/
2963 /* selectRegBank - emit code to select the register bank */
2964 /*-----------------------------------------------------------------*/
2966 selectRegBank (short bank, bool keepFlags)
2968 /* if f.e. result is in carry */
2971 emitcode ("anl", "psw,#0xE7");
2973 emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2977 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2981 /*-----------------------------------------------------------------*/
2982 /* genCall - generates a call statement */
2983 /*-----------------------------------------------------------------*/
2985 genCall (iCode * ic)
2989 bool restoreBank = FALSE;
2990 bool swapBanks = FALSE;
2991 bool accuse = FALSE;
2992 bool accPushed = FALSE;
2993 bool resultInF0 = FALSE;
2994 bool assignResultGenerated = FALSE;
2996 D (emitcode (";", "genCall"));
2998 /* if we are calling a not _naked function that is not using
2999 the same register bank then we need to save the
3000 destination registers on the stack */
3001 dtype = operandType (IC_LEFT (ic));
3002 etype = getSpec(dtype);
3003 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
3004 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
3005 IFFUNC_ISISR (currFunc->type))
3009 /* This is unexpected; the bank should have been saved in
3012 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
3018 /* if caller saves & we have not saved then */
3022 /* if send set is not empty then assign */
3023 /* We've saved all the registers we care about;
3024 * therefore, we may clobber any register not used
3025 * in the calling convention (i.e. anything not in
3030 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
3031 genSend(reverseSet(_G.sendSet));
3033 genSend(_G.sendSet);
3040 emitcode ("mov", "psw,#!constbyte",
3041 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3045 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
3046 OP_SYMBOL (IC_LEFT (ic))->rname :
3047 OP_SYMBOL (IC_LEFT (ic))->name));
3051 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
3054 /* if we need assign a result value */
3055 if ((IS_ITEMP (IC_RESULT (ic)) &&
3056 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3057 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3058 OP_SYMBOL (IC_RESULT (ic))->accuse ||
3059 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3060 IS_TRUE_SYMOP (IC_RESULT (ic)))
3062 if (isOperandInFarSpace (IC_RESULT (ic))
3063 && getSize (operandType (IC_RESULT (ic))) <= 2)
3065 int size = getSize (operandType (IC_RESULT (ic)));
3066 bool pushedB = FALSE;
3068 /* Special case for 1 or 2 byte return in far space. */
3073 emitcode ("mov", "b,%s", fReturn[1]);
3077 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
3082 aopPut (IC_RESULT (ic), "a", 0);
3086 aopPut (IC_RESULT (ic), "b", 1);
3088 assignResultGenerated = TRUE;
3089 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3093 bool pushedB = pushB ();
3094 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
3097 accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3098 assignResultGenerated = TRUE;
3099 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3103 /* adjust the stack for parameters if required */
3107 if (options.stack10bit) {
3108 if (ic->parmBytes <= 10) {
3109 emitcode(";","stack adjustment for parms");
3110 for (i=0; i < ic->parmBytes ; i++) {
3111 emitcode("pop","acc");
3115 emitcode ("clr","c");
3116 emitcode ("mov","a,sp");
3117 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
3118 emitcode ("mov","sp,a");
3119 emitcode ("mov","a,esp");
3121 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
3122 emitcode ("mov","esp,a");
3126 if (ic->parmBytes > 3)
3130 emitcode ("push", "acc");
3133 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3134 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3135 !assignResultGenerated)
3137 emitcode ("mov", "F0,c");
3141 emitcode ("mov", "a,%s", spname);
3142 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
3143 emitcode ("mov", "%s,a", spname);
3145 /* unsaveRegisters from xstack needs acc, but */
3146 /* unsaveRegisters from stack needs this popped */
3147 if (accPushed && !options.useXstack)
3149 emitcode ("pop", "acc");
3154 for (i = 0; i < ic->parmBytes; i++)
3155 emitcode ("dec", "%s", spname);
3159 /* if we had saved some registers then unsave them */
3160 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3162 if (accuse && !accPushed && options.useXstack)
3164 /* xstack needs acc, but doesn't touch normal stack */
3165 emitcode ("push", "acc");
3168 unsaveRegisters (ic);
3171 /* if register bank was saved then pop them */
3173 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
3175 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
3178 emitcode ("mov", "c,F0");
3180 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
3181 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3182 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3186 emitcode ("pop", "acc");
3189 /*-----------------------------------------------------------------*/
3190 /* genPcall - generates a call by pointer statement */
3191 /*-----------------------------------------------------------------*/
3193 genPcall (iCode * ic)
3197 symbol *rlbl = newiTempLabel (NULL);
3198 bool restoreBank=FALSE;
3199 bool resultInF0 = FALSE;
3201 D (emitcode (";", "genPcall"));
3203 dtype = operandType (IC_LEFT (ic))->next;
3204 etype = getSpec(dtype);
3205 /* if caller saves & we have not saved then */
3209 /* if we are calling a not _naked function that is not using
3210 the same register bank then we need to save the
3211 destination registers on the stack */
3212 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
3213 IFFUNC_ISISR (currFunc->type) &&
3214 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
3215 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3219 /* push the return address on to the stack */
3220 emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
3221 emitcode ("push", "acc");
3222 emitcode ("mov", "a,#!hil", (rlbl->key + 100));
3223 emitcode ("push", "acc");
3225 if (options.model == MODEL_FLAT24)
3227 emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
3228 emitcode ("push", "acc");
3231 /* now push the calling address */
3232 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3234 pushSide (IC_LEFT (ic), FPTRSIZE);
3236 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3238 /* if send set is not empty the assign */
3241 genSend(reverseSet(_G.sendSet));
3246 emitcode ("ret", "");
3250 /* if we need assign a result value */
3251 if ((IS_ITEMP (IC_RESULT (ic)) &&
3252 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3253 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3254 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3255 IS_TRUE_SYMOP (IC_RESULT (ic)))
3259 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
3262 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3264 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3267 /* adjust the stack for parameters if required */
3271 if (options.stack10bit) {
3272 if (ic->parmBytes <= 10) {
3273 emitcode(";","stack adjustment for parms");
3274 for (i=0; i < ic->parmBytes ; i++) {
3275 emitcode("pop","acc");
3278 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3279 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3281 emitcode ("mov", "F0,c");
3286 emitcode ("clr","c");
3287 emitcode ("mov","a,sp");
3288 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
3289 emitcode ("mov","sp,a");
3290 emitcode ("mov","a,esp");
3292 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
3293 emitcode ("mov","esp,a");
3297 if (ic->parmBytes > 3) {
3298 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3299 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3301 emitcode ("mov", "F0,c");
3305 emitcode ("mov", "a,%s", spname);
3306 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
3307 emitcode ("mov", "%s,a", spname);
3310 for (i = 0; i < ic->parmBytes; i++)
3311 emitcode ("dec", "%s", spname);
3314 /* if register bank was saved then unsave them */
3316 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3318 /* if we had saved some registers then unsave them */
3320 unsaveRegisters (ic);
3322 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3325 emitcode ("mov", "c,F0");
3327 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
3328 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3329 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3333 /*-----------------------------------------------------------------*/
3334 /* resultRemat - result is rematerializable */
3335 /*-----------------------------------------------------------------*/
3337 resultRemat (iCode * ic)
3339 if (SKIP_IC (ic) || ic->op == IFX)
3342 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3344 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3345 if (sym->remat && !POINTER_SET (ic))
3352 #if defined(__BORLANDC__) || defined(_MSC_VER)
3353 #define STRCASECMP stricmp
3355 #define STRCASECMP strcasecmp
3358 /*-----------------------------------------------------------------*/
3359 /* inExcludeList - return 1 if the string is in exclude Reg list */
3360 /*-----------------------------------------------------------------*/
3362 regsCmp(void *p1, void *p2)
3364 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3368 inExcludeList (char *s)
3370 const char *p = setFirstItem(options.excludeRegsSet);
3372 if (p == NULL || STRCASECMP(p, "none") == 0)
3376 return isinSetWith(options.excludeRegsSet, s, regsCmp);
3379 /*-----------------------------------------------------------------*/
3380 /* genFunction - generated code for function entry */
3381 /*-----------------------------------------------------------------*/
3383 genFunction (iCode * ic)
3385 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3387 bool switchedPSW = FALSE;
3388 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3390 D (emitcode (";", "genFunction"));
3393 /* create the function header */
3394 emitcode (";", "-----------------------------------------");
3395 emitcode (";", " function %s", sym->name);
3396 emitcode (";", "-----------------------------------------");
3398 emitcode ("", "%s:", sym->rname);
3399 ftype = operandType (IC_LEFT (ic));
3400 _G.currentFunc = sym;
3402 if (IFFUNC_ISNAKED(ftype))
3404 emitcode(";", "naked function: no prologue.");
3408 if (options.stack_probe)
3409 emitcode ("lcall","__stack_probe");
3411 /* here we need to generate the equates for the
3412 register bank if required */
3413 if (FUNC_REGBANK (ftype) != rbank)
3417 rbank = FUNC_REGBANK (ftype);
3418 for (i = 0; i < ds390_nRegs; i++)
3420 if (regs390[i].print) {
3421 if (strcmp (regs390[i].base, "0") == 0)
3422 emitcode ("", "%s !equ !constbyte",
3424 8 * rbank + regs390[i].offset);
3426 emitcode ("", "%s !equ %s + !constbyte",
3429 8 * rbank + regs390[i].offset);
3434 /* if this is an interrupt service routine then
3435 save acc, b, dpl, dph */
3436 if (IFFUNC_ISISR (sym->type))
3438 if (!inExcludeList ("acc"))
3439 emitcode ("push", "acc");
3440 if (!inExcludeList ("b"))
3441 emitcode ("push", "b");
3442 if (!inExcludeList ("dpl"))
3443 emitcode ("push", "dpl");
3444 if (!inExcludeList ("dph"))
3445 emitcode ("push", "dph");
3446 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3448 emitcode ("push", "dpx");
3449 /* Make sure we're using standard DPTR */
3450 emitcode ("push", "dps");
3451 emitcode ("mov", "dps,#0");
3452 if (options.stack10bit)
3454 /* This ISR could conceivably use DPTR2. Better save it. */
3455 emitcode ("push", "dpl1");
3456 emitcode ("push", "dph1");
3457 emitcode ("push", "dpx1");
3458 emitcode ("push", DP2_RESULT_REG);
3461 /* if this isr has no bank i.e. is going to
3462 run with bank 0 , then we need to save more
3464 if (!FUNC_REGBANK (sym->type))
3468 /* if this function does not call any other
3469 function then we can be economical and
3470 save only those registers that are used */
3471 if (!IFFUNC_HASFCALL(sym->type))
3473 /* if any registers used */
3476 bool bits_pushed = FALSE;
3477 /* save the registers used */
3478 for (i = 0; i < sym->regsUsed->size; i++)
3480 if (bitVectBitValue (sym->regsUsed, i))
3481 bits_pushed = pushReg (i, bits_pushed);
3487 /* this function has a function call. We cannot
3488 determine register usage so we will have to push the
3490 saveRBank (0, ic, FALSE);
3491 if (options.parms_in_bank1) {
3492 for (i=0; i < 8 ; i++ ) {
3493 emitcode ("push","%s",rb1regs[i]);
3500 /* This ISR uses a non-zero bank.
3502 * We assume that the bank is available for our
3505 * However, if this ISR calls a function which uses some
3506 * other bank, we must save that bank entirely.
3508 unsigned long banksToSave = 0;
3510 if (IFFUNC_HASFCALL(sym->type))
3513 #define MAX_REGISTER_BANKS 4
3518 for (i = ic; i; i = i->next)
3520 if (i->op == ENDFUNCTION)
3522 /* we got to the end OK. */
3530 dtype = operandType (IC_LEFT(i));
3532 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3534 /* Mark this bank for saving. */
3535 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3537 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3541 banksToSave |= (1 << FUNC_REGBANK(dtype));
3544 /* And note that we don't need to do it in
3552 /* This is a mess; we have no idea what
3553 * register bank the called function might
3556 * The only thing I can think of to do is
3557 * throw a warning and hope.
3559 werror(W_FUNCPTR_IN_USING_ISR);
3563 if (banksToSave && options.useXstack)
3565 /* Since we aren't passing it an ic,
3566 * saveRBank will assume r0 is available to abuse.
3568 * So switch to our (trashable) bank now, so
3569 * the caller's R0 isn't trashed.
3571 emitcode ("push", "psw");
3572 emitcode ("mov", "psw,#!constbyte",
3573 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3577 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3579 if (banksToSave & (1 << ix))
3581 saveRBank(ix, NULL, FALSE);
3585 // TODO: this needs a closer look
3586 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3591 /* if callee-save to be used for this function
3592 then save the registers being used in this function */
3593 if (IFFUNC_CALLEESAVES(sym->type))
3597 /* if any registers used */
3600 bool bits_pushed = FALSE;
3601 /* save the registers used */
3602 for (i = 0; i < sym->regsUsed->size; i++)
3604 if (bitVectBitValue (sym->regsUsed, i))
3606 bits_pushed = pushReg (i, bits_pushed);
3614 /* set the register bank to the desired value */
3615 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3618 emitcode ("push", "psw");
3619 emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3623 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3624 if (options.stack10bit) {
3625 emitcode ("push","_bpx");
3626 emitcode ("push","_bpx+1");
3627 emitcode ("mov","_bpx,%s",spname);
3628 emitcode ("mov","_bpx+1,esp");
3629 adjustEsp("_bpx+1");
3631 if (options.useXstack)
3633 emitcode ("mov", "r0,%s", spname);
3634 emitcode ("mov", "a,_bp");
3635 emitcode ("movx", "@r0,a");
3636 emitcode ("inc", "%s", spname);
3638 /* set up the stack */
3639 emitcode ("push", "_bp"); /* save the callers stack */
3641 emitcode ("mov", "_bp,%s", spname);
3645 /* adjust the stack for the function */
3648 if (options.stack10bit) {
3649 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
3650 assert (sym->recvSize <= 4);
3651 if (sym->stack <= 8) {
3652 while (i--) emitcode ("push","acc");
3655 emitcode ("mov","a,sp");
3656 emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3657 emitcode ("mov","sp,a");
3658 emitcode ("mov","a,esp");
3660 emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3661 emitcode ("mov","esp,a");
3666 werror (W_STACK_OVERFLOW, sym->name);
3668 if (i > 3 && sym->recvSize < 4) {
3670 emitcode ("mov", "a,sp");
3671 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3672 emitcode ("mov", "sp,a");
3676 emitcode ("inc", "sp");
3683 emitcode ("mov", "a,_spx");
3684 emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3685 emitcode ("mov", "_spx,a");
3688 /* if critical function then turn interrupts off */
3689 if (IFFUNC_ISCRITICAL (ftype))
3691 symbol *tlbl = newiTempLabel (NULL);
3692 emitcode ("setb", "c");
3693 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3694 emitcode ("clr", "c");
3696 emitcode ("push", "psw"); /* save old ea via c in psw */
3700 /*-----------------------------------------------------------------*/
3701 /* genEndFunction - generates epilogue for functions */
3702 /*-----------------------------------------------------------------*/
3704 genEndFunction (iCode * ic)
3706 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3707 lineNode *lnp = lineCurr;
3709 bitVect *regsUsedPrologue;
3710 bitVect *regsUnneeded;
3713 D (emitcode (";", "genEndFunction"));
3715 _G.currentFunc = NULL;
3716 if (IFFUNC_ISNAKED(sym->type))
3718 emitcode(";", "naked function: no epilogue.");
3719 if (options.debug && currFunc)
3720 debugFile->writeEndFunction (currFunc, ic, 0);
3724 if (IFFUNC_ISCRITICAL (sym->type))
3726 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3728 emitcode ("rlc", "a"); /* save c in a */
3729 emitcode ("pop", "psw"); /* restore ea via c in psw */
3730 emitcode ("mov", "ea,c");
3731 emitcode ("rrc", "a"); /* restore c from a */
3735 emitcode ("pop", "psw"); /* restore ea via c in psw */
3736 emitcode ("mov", "ea,c");
3740 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3741 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3743 if (options.stack10bit) {
3745 emitcode ("mov", "sp,_bpx", spname);
3746 emitcode ("mov", "esp,_bpx+1", spname);
3749 emitcode ("mov", "%s,_bp", spname);
3753 /* if use external stack but some variables were
3754 added to the local stack then decrement the
3756 if (options.useXstack && sym->stack) {
3757 emitcode ("mov", "a,sp");
3758 emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3759 emitcode ("mov", "sp,a");
3763 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3764 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3766 if (options.useXstack) {
3767 emitcode ("mov", "r0,%s", spname);
3768 emitcode ("movx", "a,@r0");
3769 emitcode ("mov", "_bp,a");
3770 emitcode ("dec", "%s", spname);
3772 if (options.stack10bit) {
3773 emitcode ("pop", "_bpx+1");
3774 emitcode ("pop", "_bpx");
3776 emitcode ("pop", "_bp");
3781 /* restore the register bank */
3782 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3784 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3785 || !options.useXstack)
3787 /* Special case of ISR using non-zero bank with useXstack
3790 emitcode ("pop", "psw");
3794 if (IFFUNC_ISISR (sym->type))
3797 /* now we need to restore the registers */
3798 /* if this isr has no bank i.e. is going to
3799 run with bank 0 , then we need to save more
3801 if (!FUNC_REGBANK (sym->type))
3804 /* if this function does not call any other
3805 function then we can be economical and
3806 save only those registers that are used */
3807 if (!IFFUNC_HASFCALL(sym->type))
3809 /* if any registers used */
3812 bool bits_popped = FALSE;
3813 /* save the registers used */
3814 for (i = sym->regsUsed->size; i >= 0; i--)
3816 if (bitVectBitValue (sym->regsUsed, i))
3817 bits_popped = popReg (i, bits_popped);
3823 /* this function has a function call. We cannot
3824 determine register usage so we will have to pop the
3826 if (options.parms_in_bank1) {
3827 for (i = 7 ; i >= 0 ; i-- ) {
3828 emitcode ("pop","%s",rb1regs[i]);
3831 unsaveRBank (0, ic, FALSE);
3836 /* This ISR uses a non-zero bank.
3838 * Restore any register banks saved by genFunction
3841 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3844 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3846 if (savedBanks & (1 << ix))
3848 unsaveRBank(ix, NULL, FALSE);
3852 if (options.useXstack)
3854 /* Restore bank AFTER calling unsaveRBank,
3855 * since it can trash r0.
3857 emitcode ("pop", "psw");
3861 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3863 if (options.stack10bit)
3865 emitcode ("pop", DP2_RESULT_REG);
3866 emitcode ("pop", "dpx1");
3867 emitcode ("pop", "dph1");
3868 emitcode ("pop", "dpl1");
3870 emitcode ("pop", "dps");
3871 emitcode ("pop", "dpx");
3873 if (!inExcludeList ("dph"))
3874 emitcode ("pop", "dph");
3875 if (!inExcludeList ("dpl"))
3876 emitcode ("pop", "dpl");
3877 if (!inExcludeList ("b"))
3878 emitcode ("pop", "b");
3879 if (!inExcludeList ("acc"))
3880 emitcode ("pop", "acc");
3882 /* if debug then send end of function */
3883 if (options.debug && currFunc)
3885 debugFile->writeEndFunction (currFunc, ic, 1);
3888 emitcode ("reti", "");
3892 if (IFFUNC_CALLEESAVES(sym->type))
3896 /* if any registers used */
3899 /* save the registers used */
3900 for (i = sym->regsUsed->size; i >= 0; i--)
3902 if (bitVectBitValue (sym->regsUsed, i))
3903 emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
3908 /* if debug then send end of function */
3909 if (options.debug && currFunc)
3911 debugFile->writeEndFunction (currFunc, ic, 1);
3914 emitcode ("ret", "");
3917 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3920 /* If this was an interrupt handler using bank 0 that called another */
3921 /* function, then all registers must be saved; nothing to optimized. */
3922 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3923 && !FUNC_REGBANK(sym->type))
3926 /* There are no push/pops to optimize if not callee-saves or ISR */
3927 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3930 /* If there were stack parameters, we cannot optimize without also */
3931 /* fixing all of the stack offsets; this is too dificult to consider. */
3932 if (FUNC_HASSTACKPARM(sym->type))
3935 /* Compute the registers actually used */
3936 regsUsed = newBitVect (ds390_nRegs);
3937 regsUsedPrologue = newBitVect (ds390_nRegs);
3940 if (lnp->ic && lnp->ic->op == FUNCTION)
3941 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3943 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3945 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3946 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3953 if (bitVectBitValue (regsUsedPrologue, DPS_IDX)
3954 && !bitVectBitValue (regsUsed, DPS_IDX))
3956 bitVectUnSetBit (regsUsedPrologue, DPS_IDX);
3959 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3960 && !bitVectBitValue (regsUsed, CND_IDX))
3962 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3963 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3964 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3965 bitVectUnSetBit (regsUsed, CND_IDX);
3968 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3970 /* If this was an interrupt handler that called another function */
3971 /* function, then assume working registers may be modified by it. */
3972 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3974 regsUsed = bitVectSetBit (regsUsed, AP_IDX);
3975 regsUsed = bitVectSetBit (regsUsed, DPX1_IDX);
3976 regsUsed = bitVectSetBit (regsUsed, DPL1_IDX);
3977 regsUsed = bitVectSetBit (regsUsed, DPH1_IDX);
3978 regsUsed = bitVectSetBit (regsUsed, DPX_IDX);
3979 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3980 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3981 regsUsed = bitVectSetBit (regsUsed, DPS_IDX);
3982 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3983 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3984 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3987 /* Remove the unneeded push/pops */
3988 regsUnneeded = newBitVect (ds390_nRegs);
3991 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3993 if (!strncmp(lnp->line, "push", 4))
3995 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3996 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3998 connectLine (lnp->prev, lnp->next);
3999 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4002 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
4004 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
4005 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4007 connectLine (lnp->prev, lnp->next);
4008 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4015 for (idx = 0; idx < regsUnneeded->size; idx++)
4016 if (bitVectBitValue (regsUnneeded, idx))
4017 emitcode (";", "eliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
4019 freeBitVect (regsUnneeded);
4020 freeBitVect (regsUsed);
4021 freeBitVect (regsUsedPrologue);
4024 /*-----------------------------------------------------------------*/
4025 /* genJavaNativeRet - generate code for return JavaNative */
4026 /*-----------------------------------------------------------------*/
4027 static void genJavaNativeRet(iCode *ic)
4031 aopOp (IC_LEFT (ic), ic, FALSE,
4032 AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
4033 size = AOP_SIZE (IC_LEFT (ic));
4037 /* it is assigned to GPR0-R3 then push them */
4038 if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
4039 aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
4040 for (i = 0 ; i < size ; i++ ) {
4041 emitcode ("push","%s",
4042 aopGet(IC_LEFT(ic),i,FALSE,TRUE,DP2_RESULT_REG));
4044 for (i = (size-1) ; i >= 0 ; i--) {
4045 emitcode ("pop","a%s",javaRet[i]);
4048 for (i = 0 ; i < size ; i++)
4049 emitcode ("mov","%s,%s",javaRet[i],
4050 aopGet(IC_LEFT(ic),i,FALSE,TRUE,DP2_RESULT_REG));
4052 for (i = size ; i < 4 ; i++ )
4053 emitcode ("mov","%s,#0",javaRet[i]);
4057 /*-----------------------------------------------------------------*/
4058 /* genRet - generate code for return statement */
4059 /*-----------------------------------------------------------------*/
4063 int size, offset = 0, pushed = 0;
4065 D (emitcode (";", "genRet"));
4067 /* if we have no return value then
4068 just generate the "ret" */
4072 /* if this is a JavaNative function then return
4073 value in different register */
4074 if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
4075 genJavaNativeRet(ic);
4078 /* we have something to return then
4079 move the return value into place */
4080 aopOp (IC_LEFT (ic), ic, FALSE,
4081 (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
4082 size = AOP_SIZE (IC_LEFT (ic));
4084 _startLazyDPSEvaluation ();
4086 if (IS_BIT(_G.currentFunc->etype))
4088 movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4095 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
4097 l = aopGet (IC_LEFT (ic), offset++,
4099 emitcode ("push", "%s", l);
4104 /* Since A is the last element of fReturn,
4105 * it is OK to clobber it in the aopGet.
4107 l = aopGet (IC_LEFT (ic), offset,
4108 FALSE, FALSE, NULL);
4109 if (strcmp (fReturn[offset], l))
4110 emitcode ("mov", "%s,%s", fReturn[offset++], l);
4113 _endLazyDPSEvaluation ();
4118 if (strcmp (fReturn[pushed], "a"))
4119 emitcode ("pop", fReturn[pushed]);
4121 emitcode ("pop", "acc");
4123 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
4126 /* generate a jump to the return label
4127 if the next is not the return statement */
4128 if (!(ic->next && ic->next->op == LABEL &&
4129 IC_LABEL (ic->next) == returnLabel))
4131 emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
4135 /*-----------------------------------------------------------------*/
4136 /* genLabel - generates a label */
4137 /*-----------------------------------------------------------------*/
4139 genLabel (iCode * ic)
4141 /* special case never generate */
4142 if (IC_LABEL (ic) == entryLabel)
4145 D (emitcode (";", "genLabel"));
4147 emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
4150 /*-----------------------------------------------------------------*/
4151 /* genGoto - generates a ljmp */
4152 /*-----------------------------------------------------------------*/
4154 genGoto (iCode * ic)
4156 D (emitcode (";", "genGoto"));
4158 emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
4161 /*-----------------------------------------------------------------*/
4162 /* findLabelBackwards: walks back through the iCode chain looking */
4163 /* for the given label. Returns number of iCode instructions */
4164 /* between that label and given ic. */
4165 /* Returns zero if label not found. */
4166 /*-----------------------------------------------------------------*/
4168 findLabelBackwards (iCode * ic, int key)
4177 /* If we have any pushes or pops, we cannot predict the distance.
4178 I don't like this at all, this should be dealt with in the
4180 if (ic->op == IPUSH || ic->op == IPOP) {
4184 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4186 /* printf("findLabelBackwards = %d\n", count); */
4194 /*-----------------------------------------------------------------*/
4195 /* genPlusIncr :- does addition with increment if possible */
4196 /*-----------------------------------------------------------------*/
4198 genPlusIncr (iCode * ic)
4200 unsigned int icount;
4201 unsigned int size = getDataSize (IC_RESULT (ic));
4203 /* will try to generate an increment */
4204 /* if the right side is not a literal
4206 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4209 /* if the literal value of the right hand side
4210 is greater than 4 then it is not worth it */
4211 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4214 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4215 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4217 emitcode("inc","%s",aopGet(IC_RESULT(ic),0,FALSE,FALSE,NULL));
4221 /* if increment 16 bits in register */
4223 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4224 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4225 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4234 /* If the next instruction is a goto and the goto target
4235 * is <= 5 instructions previous to this, we can generate
4236 * jumps straight to that target.
4238 if (ic->next && ic->next->op == GOTO
4239 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4242 D (emitcode (";", "tail increment optimized (range %d)", labelRange));
4243 tlbl = IC_LABEL (ic->next);
4248 tlbl = newiTempLabel (NULL);
4251 l = aopGet (IC_RESULT (ic), LSB, FALSE, FALSE, NULL);
4252 emitcode ("inc", "%s", l);
4254 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4255 IS_AOP_PREG (IC_RESULT (ic)))
4257 emitcode ("cjne", "%s,%s,!tlabel", l, zero, tlbl->key + 100);
4261 emitcode ("clr", "a");
4262 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4265 l = aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE, NULL);
4266 emitcode ("inc", "%s", l);
4269 if (!strcmp(l, "acc"))
4271 emitcode("jnz", "!tlabel", tlbl->key + 100);
4273 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4274 IS_AOP_PREG (IC_RESULT (ic)))
4276 emitcode ("cjne", "%s,%s,!tlabel", l, zero, tlbl->key + 100);
4280 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4283 l = aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE, NULL);
4284 emitcode ("inc", "%s", l);
4288 if (!strcmp(l, "acc"))
4290 emitcode("jnz", "!tlabel", tlbl->key + 100);
4292 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4293 IS_AOP_PREG (IC_RESULT (ic)))
4295 emitcode ("cjne", "%s,%s,!tlabel", l, zero, tlbl->key + 100);
4299 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4302 l = aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE, NULL);
4303 emitcode ("inc", "%s", l);
4313 if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
4314 !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 &&
4315 options.model == MODEL_FLAT24 )
4317 if (IC_RESULT(ic)->isGptr)
4319 emitcode ("mov", "b,%s", aopGet(IC_LEFT (ic), 3, FALSE, FALSE, NULL));
4323 emitcode ("mov", "dpx,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE, NULL));
4325 emitcode ("mov", "dph,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE, NULL));
4327 emitcode ("mov", "dpl,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4331 emitcode ("inc", "dptr");
4335 if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
4336 AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
4338 emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
4340 emitcode ("inc", "dptr");
4341 emitcode ("mov", "dps,#0");
4345 /* if the sizes are greater than 1 then we cannot */
4346 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4347 AOP_SIZE (IC_LEFT (ic)) > 1)
4350 /* we can if the aops of the left & result match or
4351 if they are in registers and the registers are the
4354 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4355 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4356 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4360 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4361 emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
4362 aopPut (IC_RESULT (ic), "a", 0);
4366 _startLazyDPSEvaluation ();
4369 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4371 _endLazyDPSEvaluation ();
4380 /*-----------------------------------------------------------------*/
4381 /* outBitAcc - output a bit in acc */
4382 /*-----------------------------------------------------------------*/
4384 outBitAcc (operand * result)
4386 symbol *tlbl = newiTempLabel (NULL);
4387 /* if the result is a bit */
4388 if (AOP_TYPE (result) == AOP_CRY)
4390 aopPut (result, "a", 0);
4394 emitcode ("jz", "!tlabel", tlbl->key + 100);
4395 emitcode ("mov", "a,%s", one);
4401 /*-----------------------------------------------------------------*/
4402 /* genPlusBits - generates code for addition of two bits */
4403 /*-----------------------------------------------------------------*/
4405 genPlusBits (iCode * ic)
4407 D (emitcode (";", "genPlusBits"));
4409 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4411 symbol *lbl = newiTempLabel (NULL);
4412 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4413 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4414 emitcode ("cpl", "c");
4416 outBitC (IC_RESULT (ic));
4420 emitcode ("clr", "a");
4421 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4422 emitcode ("rlc", "a");
4423 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4424 emitcode ("addc", "a,%s", zero);
4425 outAcc (IC_RESULT (ic));
4430 adjustArithmeticResult (iCode * ic)
4432 if (opIsGptr (IC_RESULT (ic)) &&
4433 opIsGptr (IC_LEFT (ic)) &&
4434 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4436 aopPut (IC_RESULT (ic),
4437 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE, NULL),
4441 if (opIsGptr (IC_RESULT (ic)) &&
4442 opIsGptr (IC_RIGHT (ic)) &&
4443 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4445 aopPut (IC_RESULT (ic),
4446 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE, NULL),
4450 if (opIsGptr (IC_RESULT (ic)) &&
4451 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4452 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4453 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4454 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4457 SNPRINTF (buffer, sizeof(buffer),
4458 "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4459 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4463 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
4464 // generates the result if possible. If result is generated, returns TRUE; otherwise
4465 // returns false and caller must deal with fact that result isn't aopOp'd.
4466 bool aopOp3(iCode * ic)
4468 bool dp1InUse, dp2InUse;
4471 // First, generate the right opcode. DPTR may be used if neither left nor result are
4474 // D (emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
4475 // AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
4476 // AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
4477 // AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
4479 // D (emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
4480 // AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
4481 // AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
4482 // AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
4485 // Right uses DPTR unless left or result is an AOP_STR; however,
4486 // if right is an AOP_STR, it must use DPTR regardless.
4487 if ((AOP_IS_STR (IC_LEFT (ic)) || AOP_IS_STR (IC_RESULT (ic)))
4488 && !AOP_IS_STR (IC_RIGHT (ic)))
4497 aopOp (IC_RIGHT(ic), ic, FALSE, useDp2);
4499 // if the right used DPTR, left MUST use DPTR2.
4500 // if the right used DPTR2, left MUST use DPTR.
4501 // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
4502 // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
4503 // enabling us to assign DPTR to result.
4505 if (AOP_USESDPTR (IC_RIGHT (ic)))
4509 else if (AOP_USESDPTR2 (IC_RIGHT (ic)))
4515 if (AOP_IS_STR (IC_RESULT (ic)) && !AOP_IS_STR (IC_LEFT (ic)))
4525 aopOp (IC_LEFT (ic), ic, FALSE, useDp2);
4528 // We've op'd the left & right. So, if left or right are the same operand as result,
4529 // we know aopOp will succeed, and we can just do it & bail.
4530 if (isOperandEqual (IC_LEFT (ic), IC_RESULT (ic)))
4532 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4535 if (isOperandEqual (IC_RIGHT (ic), IC_RESULT (ic)))
4537 // D (emitcode(";", "aopOp3: (left | right) & result equal"));
4538 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4542 // Operands may be equivalent (but not equal) if they share a spill location. If
4543 // so, use the same DPTR or DPTR2.
4544 if (operandsEqu (IC_LEFT (ic), IC_RESULT (ic)))
4546 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4549 if (operandsEqu (IC_RIGHT (ic), IC_RESULT (ic)))
4551 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4555 // Note which dptrs are currently in use.
4556 dp1InUse = AOP_USESDPTR (IC_LEFT (ic)) || AOP_USESDPTR (IC_RIGHT (ic));
4557 dp2InUse = AOP_USESDPTR2 (IC_LEFT (ic)) || AOP_USESDPTR2 (IC_RIGHT (ic));
4559 // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot
4561 if (dp1InUse && AOP_IS_STR (IC_RESULT (ic)))
4566 // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
4567 if (dp2InUse && AOP_IS_DPTRn (IC_RESULT (ic)))
4572 // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck
4573 if (dp1InUse && dp2InUse && isOperandInFarSpace (IC_RESULT (ic)))
4578 aopOp (IC_RESULT (ic), ic, TRUE, dp1InUse);
4580 // Some sanity checking...
4581 if (dp1InUse && AOP_USESDPTR (IC_RESULT (ic)))
4584 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
4585 __FILE__, __LINE__, ic->filename, ic->lineno);
4586 emitcode(";", ">>> unexpected DPTR here.");
4589 if (dp2InUse && AOP_USESDPTR2 (IC_RESULT (ic)))
4592 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
4593 __FILE__, __LINE__, ic->filename, ic->lineno);
4594 emitcode(";", ">>> unexpected DPTR2 here.");
4600 // Macro to aopOp all three operands of an ic. If this cannot be done,
4601 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
4602 // will be set TRUE. The caller must then handle the case specially, noting
4603 // that the IC_RESULT operand is not aopOp'd.
4605 #define AOP_OP_3_NOFATAL(ic, rc) \
4606 do { rc = !aopOp3(ic); } while (0)
4608 // aopOp the left & right operands of an ic.
4609 #define AOP_OP_2(ic) \
4610 aopOp (IC_RIGHT (ic), ic, FALSE, AOP_IS_STR (IC_LEFT (ic))); \
4611 aopOp (IC_LEFT (ic), ic, FALSE, AOP_USESDPTR (IC_RIGHT (ic)));
4613 // convienience macro.
4614 #define AOP_SET_LOCALS(ic) \
4615 left = IC_LEFT(ic); \
4616 right = IC_RIGHT(ic); \
4617 result = IC_RESULT(ic);
4620 // Given an integer value of pushedSize bytes on the stack,
4621 // adjust it to be resultSize bytes, either by discarding
4622 // the most significant bytes or by zero-padding.
4624 // On exit from this macro, pushedSize will have been adjusted to
4625 // equal resultSize, and ACC may be trashed.
4626 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
4627 /* If the pushed data is bigger than the result, \
4628 * simply discard unused bytes. Icky, but works. \
4630 while (pushedSize > resultSize) \
4632 D (emitcode (";", "discarding unused result byte.")); \
4633 emitcode ("pop", "acc"); \
4636 if (pushedSize < resultSize) \
4638 emitcode ("clr", "a"); \
4639 /* Conversly, we haven't pushed enough here. \
4640 * just zero-pad, and all is well. \
4642 while (pushedSize < resultSize) \
4644 emitcode("push", "acc"); \
4648 assert(pushedSize == resultSize);
4650 /*-----------------------------------------------------------------*/
4651 /* genPlus - generates code for addition */
4652 /*-----------------------------------------------------------------*/
4654 genPlus (iCode * ic)
4656 int size, offset = 0;
4659 bool swappedLR = FALSE;
4661 D (emitcode (";", "genPlus"));
4663 /* special cases :- */
4664 if ( AOP_IS_STR (IC_LEFT (ic)) &&
4665 isOperandLiteral (IC_RIGHT (ic)) && OP_SYMBOL (IC_RESULT (ic))->ruonly) {
4666 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
4667 size = (int)floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4669 while (size--) emitcode ("inc","dptr");
4671 emitcode ("mov", "a,dpl");
4672 emitcode ("add", "a,#!constbyte", size & 0xff);
4673 emitcode ("mov", "dpl,a");
4674 emitcode ("mov", "a,dph");
4675 emitcode ("addc", "a,#!constbyte", (size >> 8) & 0xff);
4676 emitcode ("mov", "dph,a");
4677 emitcode ("mov", "a,dpx");
4678 emitcode ("addc", "a,#!constbyte", (size >> 16) & 0xff);
4679 emitcode ("mov", "dpx,a");
4681 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4684 if ( IS_SYMOP (IC_LEFT (ic)) &&
4685 OP_SYMBOL (IC_LEFT (ic))->remat &&
4686 isOperandInFarSpace (IC_RIGHT (ic))) {
4687 operand *op = IC_RIGHT(ic);
4688 IC_RIGHT(ic) = IC_LEFT(ic);
4692 AOP_OP_3_NOFATAL (ic, pushResult);
4696 D (emitcode (";", "genPlus: must push result: 3 ops in far space"));
4701 /* if literal, literal on the right or
4702 if left requires ACC or right is already
4704 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4705 ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic)))) ||
4706 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4708 operand *t = IC_RIGHT (ic);
4709 IC_RIGHT (ic) = IC_LEFT (ic);
4712 D (emitcode (";", "Swapped plus args."));
4715 /* if both left & right are in bit
4717 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4718 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4724 /* if left in bit space & right literal */
4725 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4726 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4728 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4729 /* if result in bit space */
4730 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4732 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4733 emitcode ("cpl", "c");
4734 outBitC (IC_RESULT (ic));
4738 size = getDataSize (IC_RESULT (ic));
4739 _startLazyDPSEvaluation ();
4742 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4743 emitcode ("addc", "a,%s", zero);
4744 aopPut (IC_RESULT (ic), "a", offset++);
4746 _endLazyDPSEvaluation ();
4751 /* if I can do an increment instead
4752 of add then GOOD for ME */
4753 if (genPlusIncr (ic) == TRUE)
4755 D (emitcode (";", "did genPlusIncr"));
4760 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4762 _startLazyDPSEvaluation ();
4765 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4767 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
4769 emitcode ("add", "a,%s",
4770 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4772 emitcode ("addc", "a,%s",
4773 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4777 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4779 /* right is going to use ACC or we would have taken the
4782 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4784 D(emitcode(";", "+ AOP_ACC special case."););
4785 emitcode("xch", "a, %s", DP2_RESULT_REG);
4787 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4790 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4793 emitcode("add", "a, %s", DP2_RESULT_REG);
4797 emitcode ("add", "a,%s",
4798 aopGet (IC_LEFT(ic), offset, FALSE, FALSE,
4804 emitcode ("addc", "a,%s",
4805 aopGet (IC_LEFT (ic), offset, FALSE, FALSE,
4811 aopPut (IC_RESULT (ic), "a", offset);
4815 emitcode ("push", "acc");
4819 _endLazyDPSEvaluation ();
4823 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4825 size = getDataSize (IC_LEFT (ic));
4826 rSize = getDataSize (IC_RESULT (ic));
4828 ADJUST_PUSHED_RESULT(size, rSize);
4830 _startLazyDPSEvaluation ();
4833 emitcode ("pop", "acc");
4834 aopPut (IC_RESULT (ic), "a", size);
4836 _endLazyDPSEvaluation ();
4839 adjustArithmeticResult (ic);
4842 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4845 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4846 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4850 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4851 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4855 /*-----------------------------------------------------------------*/
4856 /* genMinusDec :- does subtraction with decrement if possible */
4857 /*-----------------------------------------------------------------*/
4859 genMinusDec (iCode * ic)
4861 unsigned int icount;
4862 unsigned int size = getDataSize (IC_RESULT (ic));
4864 /* will try to generate an increment */
4865 /* if the right side is not a literal
4867 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4870 /* if the literal value of the right hand side
4871 is greater than 4 then it is not worth it */
4872 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4875 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4876 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4878 emitcode("dec","%s",aopGet(IC_RESULT(ic),0,FALSE,FALSE,NULL));
4882 /* if decrement 16 bits in register */
4883 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4884 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4885 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4894 /* If the next instruction is a goto and the goto target
4895 * is <= 5 instructions previous to this, we can generate
4896 * jumps straight to that target.
4898 if (ic->next && ic->next->op == GOTO
4899 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4902 D (emitcode (";", "tail decrement optimized (range %d)", labelRange));
4903 tlbl = IC_LABEL (ic->next);
4908 tlbl = newiTempLabel (NULL);
4912 l = aopGet (IC_RESULT (ic), LSB, FALSE, FALSE, NULL);
4913 emitcode ("dec", "%s", l);
4915 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4916 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4917 IS_AOP_PREG (IC_RESULT (ic)))
4919 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4923 emitcode ("mov", "a,#!constbyte",0xff);
4924 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4926 l = aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE, NULL);
4927 emitcode ("dec", "%s", l);
4930 if (!strcmp(l, "acc"))
4932 emitcode("jnz", "!tlabel", tlbl->key + 100);
4934 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4935 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4936 IS_AOP_PREG (IC_RESULT (ic)))
4938 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4942 emitcode ("mov", "a,#!constbyte",0xff);
4943 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4945 l = aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE, NULL);
4946 emitcode ("dec", "%s", l);
4950 if (!strcmp(l, "acc"))
4952 emitcode("jnz", "!tlabel", tlbl->key + 100);
4954 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4955 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4956 IS_AOP_PREG (IC_RESULT (ic)))
4958 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4962 emitcode ("mov", "a,#!constbyte",0xff);
4963 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4965 l = aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE, NULL);
4966 emitcode ("dec", "%s", l);
4975 /* if the sizes are greater than 1 then we cannot */
4976 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4977 AOP_SIZE (IC_LEFT (ic)) > 1)
4980 /* we can if the aops of the left & result match or
4981 if they are in registers and the registers are the
4984 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4985 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4986 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4990 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4992 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL));
4997 l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL);
5000 _startLazyDPSEvaluation ();
5003 emitcode ("dec", "%s", l);
5005 _endLazyDPSEvaluation ();
5007 if (AOP_NEEDSACC (IC_RESULT (ic)))
5008 aopPut (IC_RESULT (ic), "a", 0);
5016 /*-----------------------------------------------------------------*/
5017 /* addSign - complete with sign */
5018 /*-----------------------------------------------------------------*/
5020 addSign (operand * result, int offset, int sign)
5022 int size = (getDataSize (result) - offset);
5025 _startLazyDPSEvaluation();
5028 emitcode ("rlc", "a");
5029 emitcode ("subb", "a,acc");
5032 aopPut (result, "a", offset++);
5039 aopPut (result, zero, offset++);
5042 _endLazyDPSEvaluation();
5046 /*-----------------------------------------------------------------*/
5047 /* genMinusBits - generates code for subtraction of two bits */
5048 /*-----------------------------------------------------------------*/
5050 genMinusBits (iCode * ic)
5052 symbol *lbl = newiTempLabel (NULL);
5054 D (emitcode (";", "genMinusBits"));
5056 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
5058 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
5059 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
5060 emitcode ("cpl", "c");
5062 outBitC (IC_RESULT (ic));
5066 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
5067 emitcode ("subb", "a,acc");
5068 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
5069 emitcode ("inc", "a");
5071 aopPut (IC_RESULT (ic), "a", 0);
5072 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
5076 /*-----------------------------------------------------------------*/
5077 /* genMinus - generates code for subtraction */
5078 /*-----------------------------------------------------------------*/
5080 genMinus (iCode * ic)
5082 int size, offset = 0;
5087 D (emitcode (";", "genMinus"));
5089 AOP_OP_3_NOFATAL(ic, pushResult);
5093 /* special cases :- */
5094 /* if both left & right are in bit space */
5095 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
5096 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
5102 /* if I can do an decrement instead
5103 of subtract then GOOD for ME */
5104 if (genMinusDec (ic) == TRUE)
5109 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
5111 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
5117 lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5122 /* if literal, add a,#-lit, else normal subb */
5123 _startLazyDPSEvaluation ();
5125 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
5126 if (AOP_USESDPTR(IC_RIGHT(ic))) {
5127 emitcode ("mov","b,%s",
5128 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
5129 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
5130 emitcode ("subb","a,b");
5132 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
5133 emitcode ("subb", "a,%s",
5134 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE,
5138 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
5139 /* first add without previous c */
5141 if (!size && lit==-1) {
5142 emitcode ("dec", "a");
5144 emitcode ("add", "a,#!constbyte",
5145 (unsigned int) (lit & 0x0FFL));
5148 emitcode ("addc", "a,#!constbyte",
5149 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5154 emitcode ("push", "acc");
5156 aopPut (IC_RESULT (ic), "a", offset);
5160 _endLazyDPSEvaluation ();
5164 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
5166 size = getDataSize (IC_LEFT (ic));
5167 rSize = getDataSize (IC_RESULT (ic));
5169 ADJUST_PUSHED_RESULT(size, rSize);
5171 _startLazyDPSEvaluation ();
5174 emitcode ("pop", "acc");
5175 aopPut (IC_RESULT (ic), "a", size);
5177 _endLazyDPSEvaluation ();
5180 adjustArithmeticResult (ic);
5183 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5184 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5185 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5189 /*-----------------------------------------------------------------*/
5190 /* genMultbits :- multiplication of bits */
5191 /*-----------------------------------------------------------------*/
5193 genMultbits (operand * left,
5198 D (emitcode (";", "genMultbits"));
5200 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5201 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5202 aopOp(result, ic, TRUE, FALSE);
5206 /*-----------------------------------------------------------------*/
5207 /* genMultOneByte : 8*8=8/16 bit multiplication */
5208 /*-----------------------------------------------------------------*/
5210 genMultOneByte (operand * left,
5217 bool runtimeSign, compiletimeSign;
5218 bool lUnsigned, rUnsigned, pushedB;
5220 /* (if two literals: the value is computed before) */
5221 /* if one literal, literal on the right */
5222 if (AOP_TYPE (left) == AOP_LIT)
5227 /* emitcode (";", "swapped left and right"); */
5229 /* if no literal, unsigned on the right: shorter code */
5230 if ( AOP_TYPE (right) != AOP_LIT
5231 && SPEC_USIGN (getSpec (operandType (left))))
5238 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5239 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5243 if ((lUnsigned && rUnsigned)
5244 /* sorry, I don't know how to get size
5245 without calling aopOp (result,...);
5246 see Feature Request */
5247 /* || size == 1 */ ) /* no, this is not a bug; with a 1 byte result there's
5248 no need to take care about the signedness! */
5250 /* just an unsigned 8 * 8 = 8 multiply
5252 /* emitcode (";","unsigned"); */
5253 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
5254 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
5255 emitcode ("mul", "ab");
5258 aopOp (result, ic, TRUE, FALSE);
5259 size = AOP_SIZE (result);
5261 if (size < 1 || size > 2)
5263 /* this should never happen */
5264 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
5265 size, __FILE__, lineno);
5269 aopPut (result, "a", 0);
5272 aopPut (result, "b", 1);
5278 /* we have to do a signed multiply */
5279 /* emitcode (";", "signed"); */
5281 /* now sign adjust for both left & right */
5283 /* let's see what's needed: */
5284 /* apply negative sign during runtime */
5285 runtimeSign = FALSE;
5286 /* negative sign from literals */
5287 compiletimeSign = FALSE;
5291 if (AOP_TYPE(left) == AOP_LIT)
5293 /* signed literal */
5294 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5296 compiletimeSign = TRUE;
5299 /* signed but not literal */
5305 if (AOP_TYPE(right) == AOP_LIT)
5307 /* signed literal */
5308 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5310 compiletimeSign ^= TRUE;
5313 /* signed but not literal */
5317 /* initialize F0, which stores the runtime sign */
5320 if (compiletimeSign)
5321 emitcode ("setb", "F0"); /* set sign flag */
5323 emitcode ("clr", "F0"); /* reset sign flag */
5326 /* save the signs of the operands */
5327 if (AOP_TYPE(right) == AOP_LIT)
5329 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5331 if (!rUnsigned && val < 0)
5332 emitcode ("mov", "b,#!constbyte", -val);
5334 emitcode ("mov", "b,#!constbyte", (unsigned char) val);
5336 else /* ! literal */
5338 if (rUnsigned) /* emitcode (";", "signed"); */
5339 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
5342 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
5343 lbl = newiTempLabel (NULL);
5344 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5345 emitcode ("cpl", "F0"); /* complement sign flag */
5346 emitcode ("cpl", "a"); /* 2's complement */
5347 emitcode ("inc", "a");
5349 emitcode ("mov", "b,a");
5353 if (AOP_TYPE(left) == AOP_LIT)
5355 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5357 if (!lUnsigned && val < 0)
5358 emitcode ("mov", "a,#!constbyte", -val);
5360 emitcode ("mov", "a,#!constbyte", (unsigned char) val);
5362 else /* ! literal */
5364 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
5366 if (!lUnsigned) /* emitcode (";", "signed"); */
5368 lbl = newiTempLabel (NULL);
5369 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5370 emitcode ("cpl", "F0"); /* complement sign flag */
5371 emitcode ("cpl", "a"); /* 2's complement */
5372 emitcode ("inc", "a");
5377 /* now the multiplication */
5378 emitcode ("mul", "ab");
5380 aopOp(result, ic, TRUE, FALSE);
5381 size = AOP_SIZE (result);
5383 if (size < 1 || size > 2)
5385 /* this should never happen */
5386 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
5387 size, __FILE__, lineno);
5391 if (runtimeSign || compiletimeSign)
5393 lbl = newiTempLabel (NULL);
5395 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5396 emitcode ("cpl", "a"); /* lsb 2's complement */
5398 emitcode ("inc", "a"); /* inc doesn't set carry flag */
5401 emitcode ("add", "a,#1"); /* this sets carry flag */
5402 emitcode ("xch", "a,b");
5403 emitcode ("cpl", "a"); /* msb 2's complement */
5404 emitcode ("addc", "a,#0");
5405 emitcode ("xch", "a,b");
5409 aopPut (result, "a", 0);
5412 aopPut (result, "b", 1);
5417 /*-----------------------------------------------------------------*/
5418 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
5419 /*-----------------------------------------------------------------*/
5420 static void genMultTwoByte (operand *left, operand *right,
5421 operand *result, iCode *ic)
5423 sym_link *retype = getSpec(operandType(right));
5424 sym_link *letype = getSpec(operandType(left));
5425 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5428 if (AOP_TYPE (left) == AOP_LIT) {
5433 /* save EA bit in F1 */
5434 lbl = newiTempLabel(NULL);
5435 emitcode ("setb","F1");
5436 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5437 emitcode ("clr","F1");
5440 /* load up MB with right */
5442 emitcode("clr","F0");
5443 if (AOP_TYPE(right) == AOP_LIT) {
5444 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5446 emitcode("setb","F0");
5449 emitcode ("mov","mb,#!constbyte",val & 0xff);
5450 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5452 lbl = newiTempLabel(NULL);
5453 emitcode ("mov","b,%s",aopGet(right,0,FALSE,FALSE,NULL));
5454 emitcode ("mov","a,%s",aopGet(right,1,FALSE,FALSE,NULL));
5455 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5456 emitcode ("xch", "a,b");
5457 emitcode ("cpl","a");
5458 emitcode ("add", "a,#1");
5459 emitcode ("xch", "a,b");
5460 emitcode ("cpl", "a"); // msb
5461 emitcode ("addc", "a,#0");
5462 emitcode ("setb","F0");
5464 emitcode ("mov","mb,b");
5465 emitcode ("mov","mb,a");
5468 emitcode ("mov","mb,%s",aopGet(right,0,FALSE,FALSE,NULL));
5469 emitcode ("mov","mb,%s",aopGet(right,1,FALSE,FALSE,NULL));
5471 /* load up MA with left */
5473 lbl = newiTempLabel(NULL);
5474 emitcode ("mov","b,%s",aopGet(left,0,FALSE,FALSE,NULL));
5475 emitcode ("mov","a,%s",aopGet(left,1,FALSE,FALSE,NULL));
5476 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5477 emitcode ("xch", "a,b");
5478 emitcode ("cpl","a");
5479 emitcode ("add", "a,#1");
5480 emitcode ("xch", "a,b");
5481 emitcode ("cpl", "a"); // msb
5482 emitcode ("addc","a,#0");
5483 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5484 emitcode ("setb","F0");
5486 emitcode ("mov","ma,b");
5487 emitcode ("mov","ma,a");
5489 emitcode ("mov","ma,%s",aopGet(left,0,FALSE,FALSE,NULL));
5490 emitcode ("mov","ma,%s",aopGet(left,1,FALSE,FALSE,NULL));
5492 /* wait for multiplication to finish */
5493 lbl = newiTempLabel(NULL);
5495 emitcode("mov","a,mcnt1");
5496 emitcode("anl","a,#!constbyte",0x80);
5497 emitcode("jnz","!tlabel",lbl->key+100);
5499 freeAsmop (left, NULL, ic, TRUE);
5500 freeAsmop (right, NULL, ic,TRUE);
5501 aopOp(result, ic, TRUE, FALSE);
5503 /* if unsigned then simple */
5505 emitcode ("mov","a,ma");
5506 if (AOP_SIZE(result) >= 4) aopPut(result,"a",3);
5507 emitcode ("mov","a,ma");
5508 if (AOP_SIZE(result) >= 3) aopPut(result,"a",2);
5509 aopPut(result,"ma",1);
5510 aopPut(result,"ma",0);
5512 emitcode("push","ma");
5513 emitcode("push","ma");
5514 emitcode("push","ma");
5516 /* negate result if needed */
5517 lbl = newiTempLabel(NULL);
5518 emitcode("jnb","F0,!tlabel",lbl->key+100);
5519 emitcode("cpl","a");
5520 emitcode("add","a,#1");
5522 if (AOP_TYPE(result) == AOP_ACC)
5524 D (emitcode(";", "ACC special case."));
5525 /* We know result is the only live aop, and
5526 * it's obviously not a DPTR2, so AP is available.
5528 emitcode("mov", "%s,acc", DP2_RESULT_REG);
5532 aopPut(result,"a",0);
5535 emitcode("pop","acc");
5536 lbl = newiTempLabel(NULL);
5537 emitcode("jnb","F0,!tlabel",lbl->key+100);
5538 emitcode("cpl","a");
5539 emitcode("addc","a,#0");
5541 aopPut(result,"a",1);
5542 emitcode("pop","acc");
5543 if (AOP_SIZE(result) >= 3) {
5544 lbl = newiTempLabel(NULL);
5545 emitcode("jnb","F0,!tlabel",lbl->key+100);
5546 emitcode("cpl","a");
5547 emitcode("addc","a,#0");
5549 aopPut(result,"a",2);
5551 emitcode("pop","acc");
5552 if (AOP_SIZE(result) >= 4) {
5553 lbl = newiTempLabel(NULL);
5554 emitcode("jnb","F0,!tlabel",lbl->key+100);
5555 emitcode("cpl","a");
5556 emitcode("addc","a,#0");
5558 aopPut(result,"a",3);
5560 if (AOP_TYPE(result) == AOP_ACC)
5562 /* We stashed the result away above. */
5563 emitcode("mov", "acc,%s", DP2_RESULT_REG);
5567 freeAsmop (result, NULL, ic, TRUE);
5569 /* restore EA bit in F1 */
5570 lbl = newiTempLabel(NULL);
5571 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5572 emitcode ("setb","EA");
5577 /*-----------------------------------------------------------------*/
5578 /* genMult - generates code for multiplication */
5579 /*-----------------------------------------------------------------*/
5581 genMult (iCode * ic)
5583 operand *left = IC_LEFT (ic);
5584 operand *right = IC_RIGHT (ic);
5585 operand *result = IC_RESULT (ic);
5587 D (emitcode (";", "genMult"));
5589 /* assign the asmops */
5592 /* special cases first */
5594 if (AOP_TYPE (left) == AOP_CRY &&
5595 AOP_TYPE (right) == AOP_CRY)
5597 genMultbits (left, right, result, ic);
5601 /* if both are of size == 1 */
5602 if (AOP_SIZE (left) == 1 &&
5603 AOP_SIZE (right) == 1)
5605 genMultOneByte (left, right, result, ic);
5609 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5610 /* use the ds390 ARITHMETIC accel UNIT */
5611 genMultTwoByte (left, right, result, ic);
5614 /* should have been converted to function call */
5618 freeAsmop (result, NULL, ic, TRUE);
5619 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5620 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5623 /*-----------------------------------------------------------------*/
5624 /* genDivbits :- division of bits */
5625 /*-----------------------------------------------------------------*/
5627 genDivbits (operand * left,
5635 D(emitcode ("; genDivbits",""));
5639 /* the result must be bit */
5640 LOAD_AB_FOR_DIV (left, right, l);
5641 emitcode ("div", "ab");
5642 emitcode ("rrc", "a");
5643 aopOp(result, ic, TRUE, FALSE);
5647 aopPut (result, "c", 0);
5650 /*-----------------------------------------------------------------*/
5651 /* genDivOneByte : 8 bit division */
5652 /*-----------------------------------------------------------------*/
5654 genDivOneByte (operand * left,
5659 bool lUnsigned, rUnsigned, pushedB;
5660 bool runtimeSign, compiletimeSign;
5665 D(emitcode ("; genDivOneByte",""));
5668 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5669 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5673 /* signed or unsigned */
5674 if (lUnsigned && rUnsigned)
5676 /* unsigned is easy */
5677 LOAD_AB_FOR_DIV (left, right, l);
5678 emitcode ("div", "ab");
5681 aopOp (result, ic, TRUE, FALSE);
5682 aopPut (result, "a", 0);
5685 size = AOP_SIZE (result) - 1;
5688 aopPut (result, zero, offset++);
5694 /* signed is a little bit more difficult */
5696 /* now sign adjust for both left & right */
5698 /* let's see what's needed: */
5699 /* apply negative sign during runtime */
5700 runtimeSign = FALSE;
5701 /* negative sign from literals */
5702 compiletimeSign = FALSE;
5706 if (AOP_TYPE(left) == AOP_LIT)
5708 /* signed literal */
5709 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5711 compiletimeSign = TRUE;
5714 /* signed but not literal */
5720 if (AOP_TYPE(right) == AOP_LIT)
5722 /* signed literal */
5723 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5725 compiletimeSign ^= TRUE;
5728 /* signed but not literal */
5732 /* initialize F0, which stores the runtime sign */
5735 if (compiletimeSign)
5736 emitcode ("setb", "F0"); /* set sign flag */
5738 emitcode ("clr", "F0"); /* reset sign flag */
5741 /* save the signs of the operands */
5742 if (AOP_TYPE(right) == AOP_LIT)
5744 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5746 if (!rUnsigned && val < 0)
5747 emitcode ("mov", "b,#0x%02x", -val);
5749 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5751 else /* ! literal */
5754 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
5757 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
5758 lbl = newiTempLabel (NULL);
5759 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5760 emitcode ("cpl", "F0"); /* complement sign flag */
5761 emitcode ("cpl", "a"); /* 2's complement */
5762 emitcode ("inc", "a");
5764 emitcode ("mov", "b,a");
5768 if (AOP_TYPE(left) == AOP_LIT)
5770 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5772 if (!lUnsigned && val < 0)
5773 emitcode ("mov", "a,#0x%02x", -val);
5775 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5777 else /* ! literal */
5779 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
5783 lbl = newiTempLabel (NULL);
5784 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5785 emitcode ("cpl", "F0"); /* complement sign flag */
5786 emitcode ("cpl", "a"); /* 2's complement */
5787 emitcode ("inc", "a");
5792 /* now the division */
5793 emitcode ("nop", "; workaround for DS80C390 div bug.");
5794 emitcode ("div", "ab");
5796 if (runtimeSign || compiletimeSign)
5798 lbl = newiTempLabel (NULL);
5800 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5801 emitcode ("cpl", "a"); /* lsb 2's complement */
5802 emitcode ("inc", "a");
5806 aopOp (result, ic, TRUE, FALSE);
5807 size = AOP_SIZE (result) - 1;
5811 /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
5812 then the result will be in b, a */
5813 emitcode ("mov", "b,a"); /* 1 */
5814 /* msb is 0x00 or 0xff depending on the sign */
5817 emitcode ("mov", "c,F0");
5818 emitcode ("subb", "a,acc");
5819 emitcode ("xch", "a,b"); /* 2 */
5821 aopPut (result, "b", offset++); /* write msb's */
5823 else /* compiletimeSign */
5825 aopPut (result, "#0xff", offset++); /* write msb's */
5827 aopPut (result, "a", 0); /* 3: write lsb */
5832 aopOp(result, ic, TRUE, FALSE);
5833 size = AOP_SIZE (result) - 1;
5835 aopPut (result, "a", 0);
5837 aopPut (result, zero, offset++);
5843 /*-----------------------------------------------------------------*/
5844 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
5845 /*-----------------------------------------------------------------*/
5846 static void genDivTwoByte (operand *left, operand *right,
5847 operand *result, iCode *ic)
5849 sym_link *retype = getSpec(operandType(right));
5850 sym_link *letype = getSpec(operandType(left));
5851 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5854 /* save EA bit in F1 */
5855 lbl = newiTempLabel(NULL);
5856 emitcode ("setb","F1");
5857 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5858 emitcode ("clr","F1");
5861 /* load up MA with left */
5863 emitcode("clr","F0");
5864 lbl = newiTempLabel(NULL);
5865 emitcode ("mov","b,%s",aopGet(left,0,FALSE,FALSE,NULL));
5866 emitcode ("mov","a,%s",aopGet(left,1,FALSE,FALSE,NULL));
5867 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5868 emitcode ("xch", "a,b");
5869 emitcode ("cpl","a");
5870 emitcode ("add", "a,#1");
5871 emitcode ("xch", "a,b");
5872 emitcode ("cpl", "a"); // msb
5873 emitcode ("addc","a,#0");
5874 emitcode ("setb","F0");
5876 emitcode ("mov","ma,b");
5877 emitcode ("mov","ma,a");
5879 emitcode ("mov","ma,%s",aopGet(left,0,FALSE,FALSE,NULL));
5880 emitcode ("mov","ma,%s",aopGet(left,1,FALSE,FALSE,NULL));
5883 /* load up MB with right */
5885 if (AOP_TYPE(right) == AOP_LIT) {
5886 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5888 lbl = newiTempLabel(NULL);
5889 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5890 emitcode("setb","F0");
5894 emitcode ("mov","mb,#!constbyte",val & 0xff);
5895 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5897 lbl = newiTempLabel(NULL);
5898 emitcode ("mov","b,%s",aopGet(right,0,FALSE,FALSE,NULL));
5899 emitcode ("mov","a,%s",aopGet(right,1,FALSE,FALSE,NULL));
5900 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5901 emitcode ("xch", "a,b");
5902 emitcode ("cpl","a");
5903 emitcode ("add", "a,#1");
5904 emitcode ("xch", "a,b");
5905 emitcode ("cpl", "a"); // msb
5906 emitcode ("addc", "a,#0");
5907 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5908 emitcode ("setb","F0");
5910 emitcode ("mov","mb,b");
5911 emitcode ("mov","mb,a");
5914 emitcode ("mov","mb,%s",aopGet(right,0,FALSE,FALSE,NULL));
5915 emitcode ("mov","mb,%s",aopGet(right,1,FALSE,FALSE,NULL));
5918 /* wait for multiplication to finish */
5919 lbl = newiTempLabel(NULL);
5921 emitcode("mov","a,mcnt1");
5922 emitcode("anl","a,#!constbyte",0x80);
5923 emitcode("jnz","!tlabel",lbl->key+100);
5925 freeAsmop (left, NULL, ic, TRUE);
5926 freeAsmop (right, NULL, ic,TRUE);
5927 aopOp(result, ic, TRUE, FALSE);
5929 /* if unsigned then simple */
5931 aopPut(result,"ma",1);
5932 aopPut(result,"ma",0);
5934 emitcode("push","ma");
5936 /* negate result if needed */
5937 lbl = newiTempLabel(NULL);
5938 emitcode("jnb","F0,!tlabel",lbl->key+100);
5939 emitcode("cpl","a");
5940 emitcode("add","a,#1");
5942 aopPut(result,"a",0);
5943 emitcode("pop","acc");
5944 lbl = newiTempLabel(NULL);
5945 emitcode("jnb","F0,!tlabel",lbl->key+100);
5946 emitcode("cpl","a");
5947 emitcode("addc","a,#0");
5949 aopPut(result,"a",1);
5951 freeAsmop (result, NULL, ic, TRUE);
5952 /* restore EA bit in F1 */
5953 lbl = newiTempLabel(NULL);
5954 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5955 emitcode ("setb","EA");
5960 /*-----------------------------------------------------------------*/
5961 /* genDiv - generates code for division */
5962 /*-----------------------------------------------------------------*/
5966 operand *left = IC_LEFT (ic);
5967 operand *right = IC_RIGHT (ic);
5968 operand *result = IC_RESULT (ic);
5970 D (emitcode (";", "genDiv"));
5972 /* assign the amsops */
5975 /* special cases first */
5977 if (AOP_TYPE (left) == AOP_CRY &&
5978 AOP_TYPE (right) == AOP_CRY)
5980 genDivbits (left, right, result, ic);
5984 /* if both are of size == 1 */
5985 if (AOP_SIZE (left) == 1 &&
5986 AOP_SIZE (right) == 1)
5988 genDivOneByte (left, right, result, ic);
5992 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5993 /* use the ds390 ARITHMETIC accel UNIT */
5994 genDivTwoByte (left, right, result, ic);
5997 /* should have been converted to function call */
6000 freeAsmop (result, NULL, ic, TRUE);
6001 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6002 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6005 /*-----------------------------------------------------------------*/
6006 /* genModbits :- modulus of bits */
6007 /*-----------------------------------------------------------------*/
6009 genModbits (operand * left,
6017 D (emitcode (";", "genModbits"));
6021 /* the result must be bit */
6022 LOAD_AB_FOR_DIV (left, right, l);
6023 emitcode ("div", "ab");
6024 emitcode ("mov", "a,b");
6025 emitcode ("rrc", "a");
6026 aopOp(result, ic, TRUE, FALSE);
6030 aopPut (result, "c", 0);
6033 /*-----------------------------------------------------------------*/
6034 /* genModOneByte : 8 bit modulus */
6035 /*-----------------------------------------------------------------*/
6037 genModOneByte (operand * left,
6042 bool lUnsigned, rUnsigned, pushedB;
6043 bool runtimeSign, compiletimeSign;
6048 D (emitcode (";", "genModOneByte"));
6051 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
6052 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
6056 /* signed or unsigned */
6057 if (lUnsigned && rUnsigned)
6059 /* unsigned is easy */
6060 LOAD_AB_FOR_DIV (left, right, l);
6061 emitcode ("div", "ab");
6062 aopOp (result, ic, TRUE, FALSE);
6063 aopPut (result, "b", 0);
6065 for (size = AOP_SIZE (result) - 1; size--;)
6066 aopPut (result, zero, offset++);
6072 /* signed is a little bit more difficult */
6074 /* now sign adjust for both left & right */
6076 /* modulus: sign of the right operand has no influence on the result! */
6077 if (AOP_TYPE(right) == AOP_LIT)
6079 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
6081 if (!rUnsigned && val < 0)
6082 emitcode ("mov", "b,#0x%02x", -val);
6084 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
6086 else /* not literal */
6089 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
6092 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
6093 lbl = newiTempLabel (NULL);
6094 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
6095 emitcode ("cpl", "a"); /* 2's complement */
6096 emitcode ("inc", "a");
6098 emitcode ("mov", "b,a");
6102 /* let's see what's needed: */
6103 /* apply negative sign during runtime */
6104 runtimeSign = FALSE;
6105 /* negative sign from literals */
6106 compiletimeSign = FALSE;
6108 /* sign adjust left side */
6109 if (AOP_TYPE(left) == AOP_LIT)
6111 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
6113 if (!lUnsigned && val < 0)
6115 compiletimeSign = TRUE; /* set sign flag */
6116 emitcode ("mov", "a,#0x%02x", -val);
6119 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
6121 else /* ! literal */
6123 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
6128 emitcode ("clr", "F0"); /* clear sign flag */
6130 lbl = newiTempLabel (NULL);
6131 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
6132 emitcode ("setb", "F0"); /* set sign flag */
6133 emitcode ("cpl", "a"); /* 2's complement */
6134 emitcode ("inc", "a");
6139 /* now the modulus */
6140 emitcode ("nop", "; workaround for DS80C390 div bug.");
6141 emitcode ("div", "ab");
6143 if (runtimeSign || compiletimeSign)
6145 emitcode ("mov", "a,b");
6146 lbl = newiTempLabel (NULL);
6148 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
6149 emitcode ("cpl", "a"); /* lsb 2's complement */
6150 emitcode ("inc", "a");
6154 aopOp (result, ic, TRUE, FALSE);
6155 size = AOP_SIZE (result) - 1;
6159 /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
6160 then the result will be in b, a */
6161 emitcode ("mov", "b,a"); /* 1 */
6162 /* msb is 0x00 or 0xff depending on the sign */
6165 emitcode ("mov", "c,F0");
6166 emitcode ("subb", "a,acc");
6167 emitcode ("xch", "a,b"); /* 2 */
6169 aopPut (result, "b", offset++); /* write msb's */
6171 else /* compiletimeSign */
6173 aopPut (result, "#0xff", offset++); /* write msb's */
6175 aopPut (result, "a", 0); /* 3: write lsb */
6180 aopOp(result, ic, TRUE, FALSE);
6181 size = AOP_SIZE (result) - 1;
6183 aopPut (result, "b", 0);
6185 aopPut (result, zero, offset++);
6191 /*-----------------------------------------------------------------*/
6192 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
6193 /*-----------------------------------------------------------------*/
6194 static void genModTwoByte (operand *left, operand *right,
6195 operand *result, iCode *ic)
6197 sym_link *retype = getSpec(operandType(right));
6198 sym_link *letype = getSpec(operandType(left));
6199 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
6202 /* load up MA with left */
6203 /* save EA bit in F1 */
6204 lbl = newiTempLabel(NULL);
6205 emitcode ("setb","F1");
6206 emitcode ("jbc","EA,!tlabel",lbl->key+100);
6207 emitcode ("clr","F1");
6211 lbl = newiTempLabel(NULL);
6212 emitcode ("mov","b,%s",aopGet(left,0,FALSE,FALSE,NULL));
6213 emitcode ("mov","a,%s",aopGet(left,1,FALSE,FALSE,NULL));
6214 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
6215 emitcode ("xch", "a,b");
6216 emitcode ("cpl","a");
6217 emitcode ("add", "a,#1");
6218 emitcode ("xch", "a,b");
6219 emitcode ("cpl", "a"); // msb
6220 emitcode ("addc","a,#0");
6222 emitcode ("mov","ma,b");
6223 emitcode ("mov","ma,a");
6225 emitcode ("mov","ma,%s",aopGet(left,0,FALSE,FALSE,NULL));
6226 emitcode ("mov","ma,%s",aopGet(left,1,FALSE,FALSE,NULL));
6229 /* load up MB with right */
6231 if (AOP_TYPE(right) == AOP_LIT) {
6232 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
6236 emitcode ("mov","mb,#!constbyte",val & 0xff);
6237 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
6239 lbl = newiTempLabel(NULL);
6240 emitcode ("mov","b,%s",aopGet(right,0,FALSE,FALSE,NULL));
6241 emitcode ("mov","a,%s",aopGet(right,1,FALSE,FALSE,NULL));
6242 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
6243 emitcode ("xch", "a,b");
6244 emitcode ("cpl","a");
6245 emitcode ("add", "a,#1");
6246 emitcode ("xch", "a,b");
6247 emitcode ("cpl", "a"); // msb
6248 emitcode ("addc", "a,#0");
6250 emitcode ("mov","mb,b");
6251 emitcode ("mov","mb,a");
6254 emitcode ("mov","mb,%s",aopGet(right,0,FALSE,FALSE,NULL));
6255 emitcode ("mov","mb,%s",aopGet(right,1,FALSE,FALSE,NULL));
6258 /* wait for multiplication to finish */
6259 lbl = newiTempLabel(NULL);
6261 emitcode("mov","a,mcnt1");
6262 emitcode("anl","a,#!constbyte",0x80);
6263 emitcode("jnz","!tlabel",lbl->key+100);
6265 freeAsmop (left, NULL, ic, TRUE);
6266 freeAsmop (right, NULL, ic,TRUE);
6267 aopOp(result, ic, TRUE, FALSE);
6269 aopPut(result,"mb",1);
6270 aopPut(result,"mb",0);
6271 freeAsmop (result, NULL, ic, TRUE);
6273 /* restore EA bit in F1 */
6274 lbl = newiTempLabel(NULL);
6275 emitcode ("jnb","F1,!tlabel",lbl->key+100);
6276 emitcode ("setb","EA");
6280 /*-----------------------------------------------------------------*/
6281 /* genMod - generates code for division */
6282 /*-----------------------------------------------------------------*/
6286 operand *left = IC_LEFT (ic);
6287 operand *right = IC_RIGHT (ic);
6288 operand *result = IC_RESULT (ic);
6290 D (emitcode (";", "genMod"));
6292 /* assign the asmops */
6295 /* special cases first */
6297 if (AOP_TYPE (left) == AOP_CRY &&
6298 AOP_TYPE (right) == AOP_CRY)
6300 genModbits (left, right, result, ic);
6304 /* if both are of size == 1 */
6305 if (AOP_SIZE (left) == 1 &&
6306 AOP_SIZE (right) == 1)
6308 genModOneByte (left, right, result, ic);
6312 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
6313 /* use the ds390 ARITHMETIC accel UNIT */
6314 genModTwoByte (left, right, result, ic);
6318 /* should have been converted to function call */
6322 freeAsmop (result, NULL, ic, TRUE);
6323 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6324 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6327 /*-----------------------------------------------------------------*/
6328 /* genIfxJump :- will create a jump depending on the ifx */
6329 /*-----------------------------------------------------------------*/
6331 genIfxJump (iCode * ic, char *jval)
6334 symbol *tlbl = newiTempLabel (NULL);
6337 D (emitcode (";", "genIfxJump"));
6339 /* if true label then we jump if condition
6343 jlbl = IC_TRUE (ic);
6344 inst = ((strcmp (jval, "a") == 0 ? "jz" :
6345 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
6349 /* false label is present */
6350 jlbl = IC_FALSE (ic);
6351 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
6352 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
6354 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
6355 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
6357 emitcode (inst, "!tlabel", tlbl->key + 100);
6358 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
6361 /* mark the icode as generated */
6365 /*-----------------------------------------------------------------*/
6366 /* genCmp :- greater or less than comparison */
6367 /*-----------------------------------------------------------------*/
6369 genCmp (operand * left, operand * right,
6370 iCode * ic, iCode * ifx, int sign)
6372 int size, offset = 0;
6373 unsigned long lit = 0L;
6376 D (emitcode (";", "genCmp"));
6378 result = IC_RESULT (ic);
6380 /* if left & right are bit variables */
6381 if (AOP_TYPE (left) == AOP_CRY &&
6382 AOP_TYPE (right) == AOP_CRY)
6384 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6385 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6389 /* subtract right from left if at the
6390 end the carry flag is set then we know that
6391 left is greater than right */
6392 size = max (AOP_SIZE (left), AOP_SIZE (right));
6394 /* if unsigned char cmp with lit, do cjne left,#right,zz */
6395 if ((size == 1) && !sign &&
6396 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
6398 symbol *lbl = newiTempLabel (NULL);
6399 emitcode ("cjne", "%s,%s,!tlabel",
6400 aopGet (left, offset, FALSE, FALSE, NULL),
6401 aopGet (right, offset, FALSE, FALSE, NULL),
6407 if (AOP_TYPE (right) == AOP_LIT)
6409 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6410 /* optimize if(x < 0) or if(x >= 0) */
6419 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
6421 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6422 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6424 aopOp (result, ic, FALSE, FALSE);
6426 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
6428 freeAsmop (result, NULL, ic, TRUE);
6429 genIfxJump (ifx, "acc.7");
6434 emitcode ("rlc", "a");
6436 goto release_freedLR;
6444 // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
6445 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
6446 // emitcode (";", "genCmp #2");
6447 if (sign && (size == 0))
6449 // emitcode (";", "genCmp #3");
6450 emitcode ("xrl", "a,#!constbyte",0x80);
6451 if (AOP_TYPE (right) == AOP_LIT)
6453 unsigned long lit = (unsigned long)
6454 floatFromVal (AOP (right)->aopu.aop_lit);
6455 // emitcode (";", "genCmp #3.1");
6456 emitcode ("subb", "a,#!constbyte",
6457 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
6461 // emitcode (";", "genCmp #3.2");
6463 MOVB (aopGet (right, offset++, FALSE, FALSE, "b"));
6464 saveAccWarn = DEFAULT_ACC_WARNING;
6465 emitcode ("xrl", "b,#!constbyte",0x80);
6466 emitcode ("subb", "a,b");
6473 // emitcode (";", "genCmp #4");
6475 s = aopGet (right, offset++, FALSE, FALSE, "b");
6476 saveAccWarn = DEFAULT_ACC_WARNING;
6478 emitcode ("subb", "a,%s", s);
6485 /* Don't need the left & right operands any more; do need the result. */
6486 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6487 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6489 aopOp (result, ic, FALSE, FALSE);
6493 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6499 /* if the result is used in the next
6500 ifx conditional branch then generate
6501 code a little differently */
6504 genIfxJump (ifx, "c");
6510 /* leave the result in acc */
6512 freeAsmop (result, NULL, ic, TRUE);
6515 /*-----------------------------------------------------------------*/
6516 /* genCmpGt :- greater than comparison */
6517 /*-----------------------------------------------------------------*/
6519 genCmpGt (iCode * ic, iCode * ifx)
6521 operand *left, *right;
6522 sym_link *letype, *retype;
6525 D (emitcode (";", "genCmpGt"));
6527 left = IC_LEFT (ic);
6528 right = IC_RIGHT (ic);
6530 letype = getSpec (operandType (left));
6531 retype = getSpec (operandType (right));
6532 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6534 /* assign the left & right amsops */
6537 genCmp (right, left, ic, ifx, sign);
6540 /*-----------------------------------------------------------------*/
6541 /* genCmpLt - less than comparisons */
6542 /*-----------------------------------------------------------------*/
6544 genCmpLt (iCode * ic, iCode * ifx)
6546 operand *left, *right;
6547 sym_link *letype, *retype;
6550 D (emitcode (";", "genCmpLt"));
6552 left = IC_LEFT (ic);
6553 right = IC_RIGHT (ic);
6555 letype = getSpec (operandType (left));
6556 retype = getSpec (operandType (right));
6557 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6559 /* assign the left & right amsops */
6562 genCmp (left, right, ic, ifx, sign);
6565 /*-----------------------------------------------------------------*/
6566 /* gencjneshort - compare and jump if not equal */
6567 /*-----------------------------------------------------------------*/
6569 gencjneshort (operand * left, operand * right, symbol * lbl)
6571 int size = max (AOP_SIZE (left), AOP_SIZE (right));
6573 unsigned long lit = 0L;
6575 D (emitcode (";", "gencjneshort"));
6577 /* if the left side is a literal or
6578 if the right is in a pointer register and left
6580 if ((AOP_TYPE (left) == AOP_LIT) ||
6581 (AOP_TYPE (left) == AOP_IMMD) ||
6582 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6589 if (AOP_TYPE (right) == AOP_LIT)
6590 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6592 if (opIsGptr (left) || opIsGptr (right))
6594 /* We are comparing a generic pointer to something.
6595 * Exclude the generic type byte from the comparison.
6598 D (emitcode (";", "cjneshort: generic ptr special case."););
6602 /* if the right side is a literal then anything goes */
6603 if (AOP_TYPE (right) == AOP_LIT &&
6604 AOP_TYPE (left) != AOP_DIR)
6608 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
6609 emitcode ("cjne", "a,%s,!tlabel",
6610 aopGet (right, offset, FALSE, FALSE, NULL),
6616 /* if the right side is in a register or in direct space or
6617 if the left is a pointer register & right is not */
6618 else if (AOP_TYPE (right) == AOP_REG ||
6619 AOP_TYPE (right) == AOP_DIR ||
6620 AOP_TYPE (right) == AOP_LIT ||
6621 AOP_TYPE (right) == AOP_IMMD ||
6622 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6623 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6627 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
6628 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6629 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6630 emitcode ("jnz", "!tlabel", lbl->key + 100);
6632 emitcode ("cjne", "a,%s,!tlabel",
6633 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG),
6640 /* right is a pointer reg need both a & b */
6643 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
6644 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
6645 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
6651 /*-----------------------------------------------------------------*/
6652 /* gencjne - compare and jump if not equal */
6653 /*-----------------------------------------------------------------*/
6655 gencjne (operand * left, operand * right, symbol * lbl)
6657 symbol *tlbl = newiTempLabel (NULL);
6659 D (emitcode (";", "gencjne"));
6661 gencjneshort (left, right, lbl);
6663 emitcode ("mov", "a,%s", one);
6664 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
6666 emitcode ("clr", "a");
6670 /*-----------------------------------------------------------------*/
6671 /* genCmpEq - generates code for equal to */
6672 /*-----------------------------------------------------------------*/
6674 genCmpEq (iCode * ic, iCode * ifx)
6676 operand *left, *right, *result;
6678 D (emitcode (";", "genCmpEq"));
6681 AOP_SET_LOCALS (ic);
6683 /* if literal, literal on the right or
6684 if the right is in a pointer register and left
6686 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6687 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6689 operand *t = IC_RIGHT (ic);
6690 IC_RIGHT (ic) = IC_LEFT (ic);
6694 if (ifx && /* !AOP_SIZE(result) */
6695 OP_SYMBOL (result) &&
6696 OP_SYMBOL (result)->regType == REG_CND)
6699 /* if they are both bit variables */
6700 if (AOP_TYPE (left) == AOP_CRY &&
6701 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6703 if (AOP_TYPE (right) == AOP_LIT)
6705 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6708 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6709 emitcode ("cpl", "c");
6713 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6717 emitcode ("clr", "c");
6719 /* AOP_TYPE(right) == AOP_CRY */
6723 symbol *lbl = newiTempLabel (NULL);
6724 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6725 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6726 emitcode ("cpl", "c");
6729 /* if true label then we jump if condition
6731 tlbl = newiTempLabel (NULL);
6734 emitcode ("jnc", "!tlabel", tlbl->key + 100);
6735 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6739 emitcode ("jc", "!tlabel", tlbl->key + 100);
6740 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6746 tlbl = newiTempLabel (NULL);
6747 gencjneshort (left, right, tlbl);
6750 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6755 symbol *lbl = newiTempLabel (NULL);
6756 emitcode ("sjmp", "!tlabel", lbl->key + 100);
6758 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6762 /* mark the icode as generated */
6765 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6766 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6770 /* if they are both bit variables */
6771 if (AOP_TYPE (left) == AOP_CRY &&
6772 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6774 if (AOP_TYPE (right) == AOP_LIT)
6776 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6779 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6780 emitcode ("cpl", "c");
6784 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6788 emitcode ("clr", "c");
6790 /* AOP_TYPE(right) == AOP_CRY */
6794 symbol *lbl = newiTempLabel (NULL);
6795 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6796 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6797 emitcode ("cpl", "c");
6801 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6802 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6804 aopOp (result, ic, TRUE, FALSE);
6807 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6814 genIfxJump (ifx, "c");
6817 /* if the result is used in an arithmetic operation
6818 then put the result in place */
6823 gencjne (left, right, newiTempLabel (NULL));
6825 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6826 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6828 aopOp (result, ic, TRUE, FALSE);
6830 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6832 aopPut (result, "a", 0);
6837 genIfxJump (ifx, "a");
6840 /* if the result is used in an arithmetic operation
6841 then put the result in place */
6842 if (AOP_TYPE (result) != AOP_CRY)
6844 /* leave the result in acc */
6848 freeAsmop (result, NULL, ic, TRUE);
6851 /*-----------------------------------------------------------------*/
6852 /* ifxForOp - returns the icode containing the ifx for operand */
6853 /*-----------------------------------------------------------------*/
6855 ifxForOp (operand * op, iCode * ic)
6857 /* if true symbol then needs to be assigned */
6858 if (IS_TRUE_SYMOP (op))
6861 /* if this has register type condition and
6862 the next instruction is ifx with the same operand
6863 and live to of the operand is upto the ifx only then */
6865 ic->next->op == IFX &&
6866 IC_COND (ic->next)->key == op->key &&
6867 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6873 /*-----------------------------------------------------------------*/
6874 /* hasInc - operand is incremented before any other use */
6875 /*-----------------------------------------------------------------*/
6877 hasInc (operand *op, iCode *ic, int osize)
6879 sym_link *type = operandType(op);
6880 sym_link *retype = getSpec (type);
6881 iCode *lic = ic->next;
6884 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6885 if (!IS_SYMOP(op)) return NULL;
6887 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6888 if (IS_AGGREGATE(type->next)) return NULL;
6889 if (osize != (isize = getSize(type->next))) return NULL;
6892 /* if operand of the form op = op + <sizeof *op> */
6893 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6894 isOperandEqual(IC_RESULT(lic),op) &&
6895 isOperandLiteral(IC_RIGHT(lic)) &&
6896 operandLitValue(IC_RIGHT(lic)) == isize) {
6899 /* if the operand used or deffed */
6900 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6903 /* if GOTO or IFX */
6904 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6910 /*-----------------------------------------------------------------*/
6911 /* genAndOp - for && operation */
6912 /*-----------------------------------------------------------------*/
6914 genAndOp (iCode * ic)
6916 operand *left, *right, *result;
6919 D (emitcode (";", "genAndOp"));
6921 /* note here that && operations that are in an
6922 if statement are taken away by backPatchLabels
6923 only those used in arthmetic operations remain */
6925 AOP_SET_LOCALS (ic);
6927 /* if both are bit variables */
6928 if (AOP_TYPE (left) == AOP_CRY &&
6929 AOP_TYPE (right) == AOP_CRY)
6931 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6932 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6933 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6934 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6936 aopOp (result,ic,FALSE, FALSE);
6941 tlbl = newiTempLabel (NULL);
6943 emitcode ("jz", "!tlabel", tlbl->key + 100);
6946 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6947 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6949 aopOp (result,ic,FALSE, FALSE);
6953 freeAsmop (result, NULL, ic, TRUE);
6957 /*-----------------------------------------------------------------*/
6958 /* genOrOp - for || operation */
6959 /*-----------------------------------------------------------------*/
6961 genOrOp (iCode * ic)
6963 operand *left, *right, *result;
6966 D (emitcode (";", "genOrOp"));
6968 /* note here that || operations that are in an
6969 if statement are taken away by backPatchLabels
6970 only those used in arthmetic operations remain */
6972 AOP_SET_LOCALS (ic);
6974 /* if both are bit variables */
6975 if (AOP_TYPE (left) == AOP_CRY &&
6976 AOP_TYPE (right) == AOP_CRY)
6978 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6979 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6980 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6981 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6983 aopOp (result,ic,FALSE, FALSE);
6989 tlbl = newiTempLabel (NULL);
6991 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6994 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6995 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6997 aopOp (result,ic,FALSE, FALSE);
7002 freeAsmop (result, NULL, ic, TRUE);
7005 /*-----------------------------------------------------------------*/
7006 /* isLiteralBit - test if lit == 2^n */
7007 /*-----------------------------------------------------------------*/
7009 isLiteralBit (unsigned long lit)
7011 unsigned long pw[32] =
7012 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
7013 0x100L, 0x200L, 0x400L, 0x800L,
7014 0x1000L, 0x2000L, 0x4000L, 0x8000L,
7015 0x10000L, 0x20000L, 0x40000L, 0x80000L,
7016 0x100000L, 0x200000L, 0x400000L, 0x800000L,
7017 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
7018 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
7021 for (idx = 0; idx < 32; idx++)
7027 /*-----------------------------------------------------------------*/
7028 /* continueIfTrue - */
7029 /*-----------------------------------------------------------------*/
7031 continueIfTrue (iCode * ic)
7034 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
7038 /*-----------------------------------------------------------------*/
7040 /*-----------------------------------------------------------------*/
7042 jumpIfTrue (iCode * ic)
7045 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
7049 /*-----------------------------------------------------------------*/
7050 /* jmpTrueOrFalse - */
7051 /*-----------------------------------------------------------------*/
7053 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
7055 // ugly but optimized by peephole
7058 symbol *nlbl = newiTempLabel (NULL);
7059 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
7061 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
7066 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
7072 // Generate code to perform a bit-wise logic operation
7073 // on two operands in far space (assumed to already have been
7074 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
7075 // in far space. This requires pushing the result on the stack
7076 // then popping it into the result.
7078 genFarFarLogicOp(iCode *ic, char *logicOp)
7080 int size, resultSize, compSize;
7084 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
7085 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
7086 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
7088 _startLazyDPSEvaluation();
7089 for (size = compSize; (size--); offset++)
7091 MOVA (aopGet (IC_LEFT(ic), offset, FALSE, FALSE, NULL));
7092 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
7093 MOVA (aopGet (IC_RIGHT(ic), offset, FALSE, FALSE, NULL));
7095 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
7096 emitcode ("push", "acc");
7098 _endLazyDPSEvaluation();
7100 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7101 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7102 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
7104 resultSize = AOP_SIZE(IC_RESULT(ic));
7106 ADJUST_PUSHED_RESULT(compSize, resultSize);
7108 _startLazyDPSEvaluation();
7111 emitcode ("pop", "acc");
7112 aopPut (IC_RESULT (ic), "a", compSize);
7114 _endLazyDPSEvaluation();
7115 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
7119 /*-----------------------------------------------------------------*/
7120 /* genAnd - code for and */
7121 /*-----------------------------------------------------------------*/
7123 genAnd (iCode * ic, iCode * ifx)
7125 operand *left, *right, *result;
7126 int size, offset = 0;
7127 unsigned long lit = 0L;
7132 D (emitcode (";", "genAnd"));
7134 AOP_OP_3_NOFATAL (ic, pushResult);
7135 AOP_SET_LOCALS (ic);
7139 genFarFarLogicOp(ic, "anl");
7144 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7146 AOP_TYPE (left), AOP_TYPE (right));
7147 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7149 AOP_SIZE (left), AOP_SIZE (right));
7152 /* if left is a literal & right is not then exchange them */
7153 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7154 #ifdef LOGIC_OPS_BROKEN
7155 || AOP_NEEDSACC (left)
7159 operand *tmp = right;
7164 /* if result = right then exchange left and right */
7165 if (sameRegs (AOP (result), AOP (right)))
7167 operand *tmp = right;
7172 /* if right is bit then exchange them */
7173 if (AOP_TYPE (right) == AOP_CRY &&
7174 AOP_TYPE (left) != AOP_CRY)
7176 operand *tmp = right;
7180 if (AOP_TYPE (right) == AOP_LIT)
7181 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7183 size = AOP_SIZE (result);
7186 // result = bit & yy;
7187 if (AOP_TYPE (left) == AOP_CRY)
7189 // c = bit & literal;
7190 if (AOP_TYPE (right) == AOP_LIT)
7194 if (size && sameRegs (AOP (result), AOP (left)))
7197 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7202 if (size && (AOP_TYPE (result) == AOP_CRY))
7204 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
7207 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7212 emitcode ("clr", "c");
7217 if (AOP_TYPE (right) == AOP_CRY)
7220 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7221 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
7226 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
7228 emitcode ("rrc", "a");
7229 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
7237 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7238 genIfxJump (ifx, "c");
7242 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7243 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7244 if ((AOP_TYPE (right) == AOP_LIT) &&
7245 (AOP_TYPE (result) == AOP_CRY) &&
7246 (AOP_TYPE (left) != AOP_CRY))
7248 int posbit = isLiteralBit (lit);
7253 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE, NULL));
7257 switch (posbit & 0x07)
7259 case 0: emitcode ("rrc", "a");
7261 case 7: emitcode ("rlc", "a");
7263 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
7272 SNPRINTF (buffer, sizeof(buffer),
7273 "acc.%d", posbit & 0x07);
7274 genIfxJump (ifx, buffer);
7278 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
7285 symbol *tlbl = newiTempLabel (NULL);
7286 int sizel = AOP_SIZE (left);
7288 emitcode ("setb", "c");
7291 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
7293 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7295 if ((posbit = isLiteralBit (bytelit)) != 0)
7296 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
7299 if (bytelit != 0x0FFL)
7300 emitcode ("anl", "a,%s",
7301 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG));
7302 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7307 // bit = left & literal
7310 emitcode ("clr", "c");
7313 // if(left & literal)
7317 jmpTrueOrFalse (ifx, tlbl);
7327 /* if left is same as result */
7328 if (sameRegs (AOP (result), AOP (left)))
7330 for (; size--; offset++)
7332 if (AOP_TYPE (right) == AOP_LIT)
7334 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7335 if (bytelit == 0x0FF)
7337 /* dummy read of volatile operand */
7338 if (isOperandVolatile (left, FALSE))
7339 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7343 else if (bytelit == 0)
7345 aopPut (result, zero, offset);
7347 else if (IS_AOP_PREG (result))
7349 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7350 emitcode ("anl", "a,%s",
7351 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG));
7352 aopPut (result, "a", offset);
7355 emitcode ("anl", "%s,%s",
7356 aopGet (left, offset, FALSE, TRUE, NULL),
7357 aopGet (right, offset, FALSE, FALSE, NULL));
7361 if (AOP_TYPE (left) == AOP_ACC)
7364 emitcode("mov", "a,b");
7365 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7367 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7369 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
7370 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7371 emitcode ("anl", "a,b");
7372 aopPut (result, "a", offset);
7374 else if (aopGetUsesAcc (left, offset))
7376 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7377 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7378 aopPut (result, "a", offset);
7382 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7383 if (IS_AOP_PREG (result))
7385 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7386 aopPut (result, "a", offset);
7389 emitcode ("anl", "%s,a", aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7396 // left & result in different registers
7397 if (AOP_TYPE (result) == AOP_CRY)
7400 // if(size), result in bit
7401 // if(!size && ifx), conditional oper: if(left & right)
7402 symbol *tlbl = newiTempLabel (NULL);
7403 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
7405 emitcode ("setb", "c");
7408 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7409 && AOP_TYPE(left)==AOP_ACC)
7412 emitcode("mov", "a,b");
7413 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, NULL));
7415 else if (AOP_TYPE(left)==AOP_ACC)
7419 bool pushedB = pushB ();
7420 emitcode("mov", "b,a");
7421 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7422 emitcode("anl", "a,b");
7427 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7428 emitcode("anl", "a,b");
7431 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7433 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE, NULL));
7434 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7435 emitcode ("anl", "a,b");
7437 else if (aopGetUsesAcc (left, offset))
7439 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7440 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7444 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7445 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE, DP2_RESULT_REG));
7448 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7458 jmpTrueOrFalse (ifx, tlbl);
7464 for (; (size--); offset++)
7467 // result = left & right
7468 if (AOP_TYPE (right) == AOP_LIT)
7470 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7471 if (bytelit == 0x0FF)
7474 aopGet (left, offset, FALSE, FALSE, NULL),
7478 else if (bytelit == 0)
7480 /* dummy read of volatile operand */
7481 if (isOperandVolatile (left, FALSE))
7482 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7483 aopPut (result, zero, offset);
7486 else if (AOP_TYPE (left) == AOP_ACC)
7490 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, NULL));
7491 aopPut (result, "a", offset);
7496 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE, NULL));
7497 aopPut (result, "b", offset);
7502 // faster than result <- left, anl result,right
7503 // and better if result is SFR
7504 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7505 && AOP_TYPE(left)==AOP_ACC)
7508 emitcode("mov", "a,b");
7509 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, NULL));
7511 else if (AOP_TYPE(left)==AOP_ACC)
7515 bool pushedB = pushB ();
7516 emitcode("mov", "b,a");
7517 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7518 emitcode("anl", "a,b");
7523 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7524 emitcode("anl", "a,b");
7527 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7529 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
7530 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7531 emitcode ("anl", "a,b");
7533 else if (aopGetUsesAcc (left, offset))
7535 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7536 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7540 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7541 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE, DP2_RESULT_REG));
7543 aopPut (result, "a", offset);
7549 freeAsmop (result, NULL, ic, TRUE);
7550 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7551 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7554 /*-----------------------------------------------------------------*/
7555 /* genOr - code for or */
7556 /*-----------------------------------------------------------------*/
7558 genOr (iCode * ic, iCode * ifx)
7560 operand *left, *right, *result;
7561 int size, offset = 0;
7562 unsigned long lit = 0L;
7566 D (emitcode (";", "genOr"));
7568 AOP_OP_3_NOFATAL (ic, pushResult);
7569 AOP_SET_LOCALS (ic);
7573 genFarFarLogicOp(ic, "orl");
7579 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7581 AOP_TYPE (left), AOP_TYPE (right));
7582 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7584 AOP_SIZE (left), AOP_SIZE (right));
7587 /* if left is a literal & right is not then exchange them */
7588 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7589 #ifdef LOGIC_OPS_BROKEN
7590 || AOP_NEEDSACC (left) // I think this is a net loss now.
7594 operand *tmp = right;
7599 /* if result = right then exchange them */
7600 if (sameRegs (AOP (result), AOP (right)))
7602 operand *tmp = right;
7607 /* if right is bit then exchange them */
7608 if (AOP_TYPE (right) == AOP_CRY &&
7609 AOP_TYPE (left) != AOP_CRY)
7611 operand *tmp = right;
7615 if (AOP_TYPE (right) == AOP_LIT)
7616 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7618 size = AOP_SIZE (result);
7622 if (AOP_TYPE (left) == AOP_CRY)
7624 if (AOP_TYPE (right) == AOP_LIT)
7626 // c = bit | literal;
7629 // lit != 0 => result = 1
7630 if (AOP_TYPE (result) == AOP_CRY)
7633 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7635 continueIfTrue (ifx);
7638 emitcode ("setb", "c");
7642 // lit == 0 => result = left
7643 if (size && sameRegs (AOP (result), AOP (left)))
7645 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7650 if (AOP_TYPE (right) == AOP_CRY)
7653 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7654 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7659 symbol *tlbl = newiTempLabel (NULL);
7660 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
7661 emitcode ("setb", "c");
7662 emitcode ("jb", "%s,!tlabel",
7663 AOP (left)->aopu.aop_dir, tlbl->key + 100);
7665 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7666 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7668 jmpTrueOrFalse (ifx, tlbl);
7683 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7684 genIfxJump (ifx, "c");
7688 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7689 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7690 if ((AOP_TYPE (right) == AOP_LIT) &&
7691 (AOP_TYPE (result) == AOP_CRY) &&
7692 (AOP_TYPE (left) != AOP_CRY))
7698 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7700 continueIfTrue (ifx);
7705 // lit = 0, result = boolean(left)
7707 emitcode ("setb", "c");
7711 symbol *tlbl = newiTempLabel (NULL);
7712 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7718 genIfxJump (ifx, "a");
7726 /* if left is same as result */
7727 if (sameRegs (AOP (result), AOP (left)))
7729 for (; size--; offset++)
7731 if (AOP_TYPE (right) == AOP_LIT)
7733 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7736 /* dummy read of volatile operand */
7737 if (isOperandVolatile (left, FALSE))
7738 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7742 else if (bytelit == 0x0FF)
7744 aopPut (result, "#0xFF", offset);
7746 else if (IS_AOP_PREG (left))
7748 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7749 emitcode ("orl", "a,%s",
7750 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7751 aopPut (result, "a", offset);
7755 emitcode ("orl", "%s,%s",
7756 aopGet (left, offset, FALSE, TRUE, NULL),
7757 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7762 if (AOP_TYPE (left) == AOP_ACC)
7765 emitcode("mov", "a,b");
7766 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7768 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7770 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE, NULL));
7771 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7772 emitcode ("orl", "a,b");
7773 aopPut (result, "a", offset);
7775 else if (aopGetUsesAcc (left, offset))
7777 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7778 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7779 aopPut (result, "a", offset);
7783 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7784 if (IS_AOP_PREG (left))
7786 emitcode ("orl", "a,%s",
7787 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7788 aopPut (result, "a", offset);
7792 emitcode ("orl", "%s,a",
7793 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7801 // left & result in different registers
7802 if (AOP_TYPE (result) == AOP_CRY)
7805 // if(size), result in bit
7806 // if(!size && ifx), conditional oper: if(left | right)
7807 symbol *tlbl = newiTempLabel (NULL);
7808 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7810 emitcode ("setb", "c");
7813 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7814 && AOP_TYPE(left)==AOP_ACC)
7817 emitcode("mov", "a,b");
7818 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7820 else if (AOP_TYPE(left)==AOP_ACC)
7824 bool pushedB = pushB ();
7825 emitcode("mov", "b,a");
7826 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7827 emitcode("orl", "a,b");
7832 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7833 emitcode("orl", "a,b");
7836 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7838 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
7839 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7840 emitcode ("orl", "a,b");
7842 else if (aopGetUsesAcc (left, offset))
7844 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7845 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7849 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7850 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE, DP2_RESULT_REG));
7853 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7863 jmpTrueOrFalse (ifx, tlbl);
7869 _startLazyDPSEvaluation();
7870 for (; (size--); offset++)
7873 // result = left | right
7874 if (AOP_TYPE (right) == AOP_LIT)
7876 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7880 aopGet (left, offset, FALSE, FALSE, NULL),
7884 else if (bytelit == 0x0FF)
7886 /* dummy read of volatile operand */
7887 if (isOperandVolatile (left, FALSE))
7888 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7889 aopPut (result, "#0xFF", offset);
7893 // faster than result <- left, orl result,right
7894 // and better if result is SFR
7895 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7896 && AOP_TYPE(left)==AOP_ACC)
7899 emitcode("mov", "a,b");
7900 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7902 else if (AOP_TYPE(left)==AOP_ACC)
7906 bool pushedB = pushB ();
7907 emitcode("mov", "b,a");
7908 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7909 emitcode("orl", "a,b");
7914 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7915 emitcode("orl", "a,b");
7918 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7920 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
7921 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7922 emitcode ("orl", "a,b");
7924 else if (aopGetUsesAcc (left, offset))
7926 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7927 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7931 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7932 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE, DP2_RESULT_REG));
7934 aopPut (result, "a", offset);
7936 _endLazyDPSEvaluation();
7941 freeAsmop (result, NULL, ic, TRUE);
7942 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7943 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7946 /*-----------------------------------------------------------------*/
7947 /* genXor - code for xclusive or */
7948 /*-----------------------------------------------------------------*/
7950 genXor (iCode * ic, iCode * ifx)
7952 operand *left, *right, *result;
7953 int size, offset = 0;
7954 unsigned long lit = 0L;
7958 D (emitcode (";", "genXor"));
7960 AOP_OP_3_NOFATAL (ic, pushResult);
7961 AOP_SET_LOCALS (ic);
7965 genFarFarLogicOp(ic, "xrl");
7970 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7972 AOP_TYPE (left), AOP_TYPE (right));
7973 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7975 AOP_SIZE (left), AOP_SIZE (right));
7978 /* if left is a literal & right is not ||
7979 if left needs acc & right does not */
7980 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7981 #ifdef LOGIC_OPS_BROKEN
7982 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
7986 operand *tmp = right;
7991 /* if result = right then exchange them */
7992 if (sameRegs (AOP (result), AOP (right)))
7994 operand *tmp = right;
7999 /* if right is bit then exchange them */
8000 if (AOP_TYPE (right) == AOP_CRY &&
8001 AOP_TYPE (left) != AOP_CRY)
8003 operand *tmp = right;
8007 if (AOP_TYPE (right) == AOP_LIT)
8008 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8010 size = AOP_SIZE (result);
8014 if (AOP_TYPE (left) == AOP_CRY)
8016 if (AOP_TYPE (right) == AOP_LIT)
8018 // c = bit & literal;
8021 // lit>>1 != 0 => result = 1
8022 if (AOP_TYPE (result) == AOP_CRY)
8025 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
8027 continueIfTrue (ifx);
8030 emitcode ("setb", "c");
8037 // lit == 0, result = left
8038 if (size && sameRegs (AOP (result), AOP (left)))
8040 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
8044 // lit == 1, result = not(left)
8045 if (size && sameRegs (AOP (result), AOP (left)))
8047 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
8052 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
8053 emitcode ("cpl", "c");
8061 symbol *tlbl = newiTempLabel (NULL);
8062 if (AOP_TYPE (right) == AOP_CRY)
8065 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8069 int sizer = AOP_SIZE (right);
8071 // if val>>1 != 0, result = 1
8072 emitcode ("setb", "c");
8075 MOVA (aopGet (right, sizer - 1, FALSE, FALSE, NULL));
8077 // test the msb of the lsb
8078 emitcode ("anl", "a,#!constbyte",0xfe);
8079 emitcode ("jnz", "!tlabel", tlbl->key + 100);
8083 emitcode ("rrc", "a");
8085 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
8086 emitcode ("cpl", "c");
8094 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
8095 genIfxJump (ifx, "c");
8099 /* if left is same as result */
8100 if (sameRegs (AOP (result), AOP (left)))
8102 for (; size--; offset++)
8104 if (AOP_TYPE (right) == AOP_LIT)
8106 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
8109 /* dummy read of volatile operand */
8110 if (isOperandVolatile (left, FALSE))
8111 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8115 else if (IS_AOP_PREG (left))
8117 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8118 emitcode ("xrl", "a,%s",
8119 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG));
8120 aopPut (result, "a", offset);
8124 emitcode ("xrl", "%s,%s",
8125 aopGet (left, offset, FALSE, TRUE, NULL),
8126 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8131 if (AOP_TYPE (left) == AOP_ACC)
8134 emitcode("mov", "a,b");
8135 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8137 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
8139 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
8140 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8141 emitcode ("xrl", "a,b");
8142 aopPut (result, "a", offset);
8144 else if (aopGetUsesAcc (left, offset))
8146 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8147 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8148 aopPut (result, "a", offset);
8152 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
8153 if (IS_AOP_PREG (left))
8155 emitcode ("xrl", "a,%s",
8156 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
8157 aopPut (result, "a", offset);
8160 emitcode ("xrl", "%s,a",
8161 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
8168 // left & result in different registers
8169 if (AOP_TYPE (result) == AOP_CRY)
8172 // if(size), result in bit
8173 // if(!size && ifx), conditional oper: if(left ^ right)
8174 symbol *tlbl = newiTempLabel (NULL);
8175 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
8178 emitcode ("setb", "c");
8181 if ((AOP_TYPE (right) == AOP_LIT) &&
8182 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
8184 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8186 else if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
8187 && AOP_TYPE(left)==AOP_ACC)
8190 emitcode("mov", "a,b");
8191 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8193 else if (AOP_TYPE(left)==AOP_ACC)
8197 bool pushedB = pushB ();
8198 emitcode("mov", "b,a");
8199 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8200 emitcode("xrl", "a,b");
8205 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8206 emitcode("xrl", "a,b");
8209 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
8211 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
8212 MOVA (aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8213 emitcode ("xrl", "a,b");
8215 else if (aopGetUsesAcc (left, offset))
8217 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8218 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8222 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
8223 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
8226 emitcode ("jnz", "!tlabel", tlbl->key + 100);
8236 jmpTrueOrFalse (ifx, tlbl);
8240 for (; (size--); offset++)
8243 // result = left ^ right
8244 if (AOP_TYPE (right) == AOP_LIT)
8246 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
8250 aopGet (left, offset, FALSE, FALSE, NULL),
8254 D (emitcode (";", "better literal XOR."));
8255 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8256 emitcode ("xrl", "a, %s",
8257 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8261 // faster than result <- left, anl result,right
8262 // and better if result is SFR
8263 if (AOP_TYPE (left) == AOP_ACC)
8265 emitcode ("xrl", "a,%s",
8266 aopGet (right, offset,
8267 FALSE, FALSE, DP2_RESULT_REG));
8271 char *rOp = aopGet (right, offset, FALSE, FALSE, NULL);
8272 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
8274 emitcode("mov", "b,a");
8278 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8279 emitcode ("xrl", "a,%s", rOp);
8282 aopPut (result, "a", offset);
8288 freeAsmop (result, NULL, ic, TRUE);
8289 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
8290 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
8293 /*-----------------------------------------------------------------*/
8294 /* genInline - write the inline code out */
8295 /*-----------------------------------------------------------------*/
8297 genInline (iCode * ic)
8299 char *buffer, *bp, *bp1;
8301 D (emitcode (";", "genInline"));
8303 _G.inLine += (!options.asmpeep);
8305 buffer = bp = bp1 = Safe_strdup(IC_INLINE(ic));
8307 /* emit each line as a code */
8318 /* Add \n for labels, not dirs such as c:\mydir */
8319 if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
8333 /* emitcode("",buffer); */
8334 _G.inLine -= (!options.asmpeep);
8337 /*-----------------------------------------------------------------*/
8338 /* genRRC - rotate right with carry */
8339 /*-----------------------------------------------------------------*/
8343 operand *left, *result;
8347 D (emitcode (";", "genRRC"));
8349 /* rotate right with carry */
8350 left = IC_LEFT (ic);
8351 result = IC_RESULT (ic);
8352 aopOp (left, ic, FALSE, FALSE);
8353 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8355 /* move it to the result */
8356 size = AOP_SIZE (result);
8360 _startLazyDPSEvaluation ();
8363 l = aopGet (left, offset, FALSE, FALSE, NULL);
8365 emitcode ("rrc", "a");
8366 if (AOP_SIZE (result) > 1)
8367 aopPut (result, "a", offset--);
8369 _endLazyDPSEvaluation ();
8371 /* now we need to put the carry into the
8372 highest order byte of the result */
8373 if (AOP_SIZE (result) > 1)
8375 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE, NULL);
8378 emitcode ("mov", "acc.7,c");
8379 aopPut (result, "a", AOP_SIZE (result) - 1);
8380 freeAsmop (result, NULL, ic, TRUE);
8381 freeAsmop (left, NULL, ic, TRUE);
8384 /*-----------------------------------------------------------------*/
8385 /* genRLC - generate code for rotate left with carry */
8386 /*-----------------------------------------------------------------*/
8390 operand *left, *result;
8394 D (emitcode (";", "genRLC"));
8396 /* rotate right with carry */
8397 left = IC_LEFT (ic);
8398 result = IC_RESULT (ic);
8399 aopOp (left, ic, FALSE, FALSE);
8400 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8402 /* move it to the result */
8403 size = AOP_SIZE (result);
8407 l = aopGet (left, offset, FALSE, FALSE, NULL);
8409 emitcode ("add", "a,acc");
8410 if (AOP_SIZE (result) > 1)
8412 aopPut (result, "a", offset++);
8415 _startLazyDPSEvaluation ();
8418 l = aopGet (left, offset, FALSE, FALSE, NULL);
8420 emitcode ("rlc", "a");
8421 if (AOP_SIZE (result) > 1)
8422 aopPut (result, "a", offset++);
8424 _endLazyDPSEvaluation ();
8426 /* now we need to put the carry into the
8427 highest order byte of the result */
8428 if (AOP_SIZE (result) > 1)
8430 l = aopGet (result, 0, FALSE, FALSE, NULL);
8433 emitcode ("mov", "acc.0,c");
8434 aopPut (result, "a", 0);
8435 freeAsmop (result, NULL, ic, TRUE);
8436 freeAsmop (left, NULL, ic, TRUE);
8439 /*-----------------------------------------------------------------*/
8440 /* genGetHbit - generates code get highest order bit */
8441 /*-----------------------------------------------------------------*/
8443 genGetHbit (iCode * ic)
8445 operand *left, *result;
8447 D (emitcode (";", "genGetHbit"));
8449 left = IC_LEFT (ic);
8450 result = IC_RESULT (ic);
8451 aopOp (left, ic, FALSE, FALSE);
8452 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8454 /* get the highest order byte into a */
8455 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
8456 if (AOP_TYPE (result) == AOP_CRY)
8458 emitcode ("rlc", "a");
8463 emitcode ("rl", "a");
8464 emitcode ("anl", "a,#1");
8469 freeAsmop (result, NULL, ic, TRUE);
8470 freeAsmop (left, NULL, ic, TRUE);
8473 /*-----------------------------------------------------------------*/
8474 /* genSwap - generates code to swap nibbles or bytes */
8475 /*-----------------------------------------------------------------*/
8477 genSwap (iCode * ic)
8479 operand *left, *result;
8481 D(emitcode ("; genSwap",""));
8483 left = IC_LEFT (ic);
8484 result = IC_RESULT (ic);
8485 aopOp (left, ic, FALSE, FALSE);
8486 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8488 _startLazyDPSEvaluation ();
8489 switch (AOP_SIZE (left))
8491 case 1: /* swap nibbles in byte */
8492 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
8493 emitcode ("swap", "a");
8494 aopPut (result, "a", 0);
8496 case 2: /* swap bytes in word */
8497 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
8499 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
8500 aopPut (result, aopGet (left, 1, FALSE, FALSE, NULL), 0);
8501 aopPut (result, "a", 1);
8503 else if (operandsEqu (left, result))
8506 bool pushedB = FALSE, leftInB = FALSE;
8508 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
8509 if (AOP_NEEDSACC (left) || AOP_NEEDSACC (result))
8512 emitcode ("mov", "b,a");
8516 aopPut (result, aopGet (left, 1, FALSE, FALSE, NULL), 0);
8517 aopPut (result, reg, 1);
8524 aopPut (result, aopGet (left, 1, FALSE, FALSE, NULL), 0);
8525 aopPut (result, aopGet (left, 0, FALSE, FALSE, NULL), 1);
8529 wassertl(FALSE, "unsupported SWAP operand size");
8531 _endLazyDPSEvaluation ();
8533 freeAsmop (result, NULL, ic, TRUE);
8534 freeAsmop (left, NULL, ic, TRUE);
8537 /*-----------------------------------------------------------------*/
8538 /* AccRol - rotate left accumulator by known count */
8539 /*-----------------------------------------------------------------*/
8541 AccRol (int shCount)
8543 shCount &= 0x0007; // shCount : 0..7
8550 emitcode ("rl", "a");
8553 emitcode ("rl", "a");
8554 emitcode ("rl", "a");
8557 emitcode ("swap", "a");
8558 emitcode ("rr", "a");
8561 emitcode ("swap", "a");
8564 emitcode ("swap", "a");
8565 emitcode ("rl", "a");
8568 emitcode ("rr", "a");
8569 emitcode ("rr", "a");
8572 emitcode ("rr", "a");
8577 /*-----------------------------------------------------------------*/
8578 /* AccLsh - left shift accumulator by known count */
8579 /*-----------------------------------------------------------------*/
8581 AccLsh (int shCount)
8586 emitcode ("add", "a,acc");
8587 else if (shCount == 2)
8589 emitcode ("add", "a,acc");
8590 emitcode ("add", "a,acc");
8594 /* rotate left accumulator */
8596 /* and kill the lower order bits */
8597 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
8602 /*-----------------------------------------------------------------*/
8603 /* AccRsh - right shift accumulator by known count */
8604 /*-----------------------------------------------------------------*/
8606 AccRsh (int shCount)
8613 emitcode ("rrc", "a");
8617 /* rotate right accumulator */
8618 AccRol (8 - shCount);
8619 /* and kill the higher order bits */
8620 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
8625 #ifdef BETTER_LITERAL_SHIFT
8626 /*-----------------------------------------------------------------*/
8627 /* AccSRsh - signed right shift accumulator by known count */
8628 /*-----------------------------------------------------------------*/
8630 AccSRsh (int shCount)
8637 emitcode ("mov", "c,acc.7");
8638 emitcode ("rrc", "a");
8640 else if (shCount == 2)
8642 emitcode ("mov", "c,acc.7");
8643 emitcode ("rrc", "a");
8644 emitcode ("mov", "c,acc.7");
8645 emitcode ("rrc", "a");
8649 tlbl = newiTempLabel (NULL);
8650 /* rotate right accumulator */
8651 AccRol (8 - shCount);
8652 /* and kill the higher order bits */
8653 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
8654 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8655 emitcode ("orl", "a,#!constbyte",
8656 (unsigned char) ~SRMask[shCount]);
8663 #ifdef BETTER_LITERAL_SHIFT
8664 /*-----------------------------------------------------------------*/
8665 /* shiftR1Left2Result - shift right one byte from left to result */
8666 /*-----------------------------------------------------------------*/
8668 shiftR1Left2Result (operand * left, int offl,
8669 operand * result, int offr,
8670 int shCount, int sign)
8672 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
8673 /* shift right accumulator */
8678 aopPut (result, "a", offr);
8682 #ifdef BETTER_LITERAL_SHIFT
8683 /*-----------------------------------------------------------------*/
8684 /* shiftL1Left2Result - shift left one byte from left to result */
8685 /*-----------------------------------------------------------------*/
8687 shiftL1Left2Result (operand * left, int offl,
8688 operand * result, int offr, int shCount)
8691 l = aopGet (left, offl, FALSE, FALSE, NULL);
8693 /* shift left accumulator */
8695 aopPut (result, "a", offr);
8699 #ifdef BETTER_LITERAL_SHIFT
8700 /*-----------------------------------------------------------------*/
8701 /* movLeft2Result - move byte from left to result */
8702 /*-----------------------------------------------------------------*/
8704 movLeft2Result (operand * left, int offl,
8705 operand * result, int offr, int sign)
8708 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8710 l = aopGet (left, offl, FALSE, FALSE, NULL);
8712 if (*l == '@' && (IS_AOP_PREG (result)))
8714 emitcode ("mov", "a,%s", l);
8715 aopPut (result, "a", offr);
8721 aopPut (result, l, offr);
8725 /* MSB sign in acc.7 ! */
8726 if (getDataSize (left) == offl + 1)
8729 aopPut (result, "a", offr);
8737 #ifdef BETTER_LITERAL_SHIFT
8738 /*-----------------------------------------------------------------*/
8739 /* AccAXRrl1 - right rotate a:x by 1 */
8740 /*-----------------------------------------------------------------*/
8744 emitcode ("mov", "c,acc.0");
8745 emitcode ("xch", "a,%s", x);
8746 emitcode ("rrc", "a");
8747 emitcode ("xch", "a,%s", x);
8748 emitcode ("rrc", "a");
8752 #ifdef BETTER_LITERAL_SHIFT
8754 /*-----------------------------------------------------------------*/
8755 /* AccAXLrl1 - left rotate a:x by 1 */
8756 /*-----------------------------------------------------------------*/
8760 emitcode ("mov", "c,acc.7");
8761 emitcode ("xch", "a,%s", x);
8762 emitcode ("rlc", "a");
8763 emitcode ("xch", "a,%s", x);
8764 emitcode ("rlc", "a");
8768 #ifdef BETTER_LITERAL_SHIFT
8769 /*-----------------------------------------------------------------*/
8770 /* AccAXRsh1 - right shift c->a:x->c by 1 */
8771 /*-----------------------------------------------------------------*/
8775 emitcode ("rrc", "a");
8776 emitcode ("xch", "a,%s", x);
8777 emitcode ("rrc", "a");
8778 emitcode ("xch", "a,%s", x);
8782 #ifdef BETTER_LITERAL_SHIFT
8783 /*-----------------------------------------------------------------*/
8784 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8785 /*-----------------------------------------------------------------*/
8789 emitcode ("xch", "a,%s", x);
8790 emitcode ("add", "a,acc");
8791 emitcode ("xch", "a,%s", x);
8792 emitcode ("rlc", "a");
8796 #ifdef BETTER_LITERAL_SHIFT
8797 /*-----------------------------------------------------------------*/
8798 /* AccAXLsh - left shift a:x by known count (0..7) */
8799 /*-----------------------------------------------------------------*/
8801 AccAXLsh (char *x, int shCount)
8816 case 5: // AAAAABBB:CCCCCDDD
8818 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8820 emitcode ("anl", "a,#!constbyte",
8821 SLMask[shCount]); // BBB00000:CCCCCDDD
8823 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8825 AccRol (shCount); // DDDCCCCC:BBB00000
8827 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8829 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8831 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8833 emitcode ("anl", "a,#!constbyte",
8834 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8836 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8838 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8841 case 6: // AAAAAABB:CCCCCCDD
8842 emitcode ("anl", "a,#!constbyte",
8843 SRMask[shCount]); // 000000BB:CCCCCCDD
8845 AccAXRrl1 (x); // D000000B:BCCCCCCD
8846 AccAXRrl1 (x); // DD000000:BBCCCCCC
8847 emitcode ("xch", "a,%s", x); // BBCCCCCC:DD000000
8849 emitcode ("mov", "c,acc.0"); // c = B
8850 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8851 emitcode("rrc","a");
8852 emitcode("xch","a,%s", x);
8853 emitcode("rrc","a");
8854 emitcode("mov","c,acc.0"); //<< get correct bit
8855 emitcode("xch","a,%s", x);
8857 emitcode("rrc","a");
8858 emitcode("xch","a,%s", x);
8859 emitcode("rrc","a");
8860 emitcode("xch","a,%s", x);
8863 case 7: // a:x <<= 7
8865 emitcode ("anl", "a,#!constbyte",
8866 SRMask[shCount]); // 0000000B:CCCCCCCD
8868 AccAXRrl1 (x); // D0000000:BCCCCCCC
8870 emitcode ("xch", "a,%s", x); // BCCCCCCC:D0000000
8879 #ifdef BETTER_LITERAL_SHIFT
8881 /*-----------------------------------------------------------------*/
8882 /* AccAXRsh - right shift a:x known count (0..7) */
8883 /*-----------------------------------------------------------------*/
8885 AccAXRsh (char *x, int shCount)
8893 AccAXRsh1 (x); // 0->a:x
8898 AccAXRsh1 (x); // 0->a:x
8901 AccAXRsh1 (x); // 0->a:x
8906 case 5: // AAAAABBB:CCCCCDDD = a:x
8908 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8910 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8912 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8914 emitcode ("anl", "a,#!constbyte",
8915 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8917 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8919 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8921 emitcode ("anl", "a,#!constbyte",
8922 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8924 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8926 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8928 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8931 case 6: // AABBBBBB:CCDDDDDD
8933 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDE
8934 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8936 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8938 emitcode ("anl", "a,#!constbyte",
8939 SRMask[shCount]); // 000000AA:BBBBBBCC
8942 case 7: // ABBBBBBB:CDDDDDDD
8944 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8946 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8948 emitcode ("anl", "a,#!constbyte",
8949 SRMask[shCount]); // 0000000A:BBBBBBBC
8958 #ifdef BETTER_LITERAL_SHIFT
8959 /*-----------------------------------------------------------------*/
8960 /* AccAXRshS - right shift signed a:x known count (0..7) */
8961 /*-----------------------------------------------------------------*/
8963 AccAXRshS (char *x, int shCount)
8971 emitcode ("mov", "c,acc.7");
8972 AccAXRsh1 (x); // s->a:x
8976 emitcode ("mov", "c,acc.7");
8977 AccAXRsh1 (x); // s->a:x
8979 emitcode ("mov", "c,acc.7");
8980 AccAXRsh1 (x); // s->a:x
8985 case 5: // AAAAABBB:CCCCCDDD = a:x
8987 tlbl = newiTempLabel (NULL);
8988 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8990 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8992 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8994 emitcode ("anl", "a,#!constbyte",
8995 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8997 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8999 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
9001 emitcode ("anl", "a,#!constbyte",
9002 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
9004 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
9006 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
9008 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
9010 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
9011 emitcode ("orl", "a,#!constbyte",
9012 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
9015 break; // SSSSAAAA:BBBCCCCC
9017 case 6: // AABBBBBB:CCDDDDDD
9019 tlbl = newiTempLabel (NULL);
9021 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
9022 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
9024 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
9026 emitcode ("anl", "a,#!constbyte",
9027 SRMask[shCount]); // 000000AA:BBBBBBCC
9029 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
9030 emitcode ("orl", "a,#!constbyte",
9031 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
9035 case 7: // ABBBBBBB:CDDDDDDD
9037 tlbl = newiTempLabel (NULL);
9039 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
9041 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
9043 emitcode ("anl", "a,#!constbyte",
9044 SRMask[shCount]); // 0000000A:BBBBBBBC
9046 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
9047 emitcode ("orl", "a,#!constbyte",
9048 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
9058 #ifdef BETTER_LITERAL_SHIFT
9060 _loadLeftIntoAx(char **lsb,
9066 // Get the initial value from left into a pair of registers.
9067 // MSB must be in A, LSB can be any register.
9069 // If the result is held in registers, it is an optimization
9070 // if the LSB can be held in the register which will hold the,
9071 // result LSB since this saves us from having to copy it into
9072 // the result following AccAXLsh.
9074 // If the result is addressed indirectly, this is not a gain.
9075 if (AOP_NEEDSACC(result))
9079 _startLazyDPSEvaluation();
9080 if (AOP_TYPE(left) == AOP_DPTR2)
9083 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE, NULL));
9084 // get LSB in DP2_RESULT_REG.
9085 leftByte = aopGet (left, offl, FALSE, FALSE, DP2_RESULT_REG);
9086 assert(!strcmp(leftByte, DP2_RESULT_REG));
9090 // get LSB into DP2_RESULT_REG
9091 leftByte = aopGet (left, offl, FALSE, FALSE, NULL);
9092 if (strcmp(leftByte, DP2_RESULT_REG))
9095 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
9098 leftByte = aopGet (left, offl + MSB16, FALSE, FALSE, NULL);
9099 assert(strcmp(leftByte, DP2_RESULT_REG));
9102 _endLazyDPSEvaluation();
9103 *lsb = DP2_RESULT_REG;
9107 if (sameRegs (AOP (result), AOP (left)) &&
9108 ((offl + MSB16) == offr))
9110 /* don't crash result[offr] */
9111 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
9112 emitcode ("xch", "a,%s",
9113 aopGet (left, offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
9117 movLeft2Result (left, offl, result, offr, 0);
9118 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE, NULL));
9120 *lsb = aopGet (result, offr, FALSE, FALSE, DP2_RESULT_REG);
9121 assert(strcmp(*lsb,"a"));
9126 _storeAxResults(char *lsb,
9130 _startLazyDPSEvaluation();
9131 if (AOP_NEEDSACC(result))
9133 /* We have to explicitly update the result LSB.
9135 emitcode ("xch","a,%s", lsb);
9136 aopPut (result, "a", offr);
9137 emitcode ("mov","a,%s", lsb);
9139 if (getDataSize (result) > 1)
9141 aopPut (result, "a", offr + MSB16);
9143 _endLazyDPSEvaluation();
9146 /*-----------------------------------------------------------------*/
9147 /* shiftL2Left2Result - shift left two bytes from left to result */
9148 /*-----------------------------------------------------------------*/
9150 shiftL2Left2Result (operand * left, int offl,
9151 operand * result, int offr, int shCount)
9155 _loadLeftIntoAx(&lsb, left, result, offl, offr);
9157 AccAXLsh (lsb, shCount);
9159 _storeAxResults(lsb, result, offr);
9163 #ifdef BETTER_LITERAL_SHIFT
9164 /*-----------------------------------------------------------------*/
9165 /* shiftR2Left2Result - shift right two bytes from left to result */
9166 /*-----------------------------------------------------------------*/
9168 shiftR2Left2Result (operand * left, int offl,
9169 operand * result, int offr,
9170 int shCount, int sign)
9174 _loadLeftIntoAx(&lsb, left, result, offl, offr);
9176 /* a:x >> shCount (x = lsb(result)) */
9179 AccAXRshS(lsb, shCount);
9183 AccAXRsh(lsb, shCount);
9186 _storeAxResults(lsb, result, offr);
9190 /*-----------------------------------------------------------------*/
9191 /* shiftLLeftOrResult - shift left one byte from left, or to result */
9192 /*-----------------------------------------------------------------*/
9194 shiftLLeftOrResult (operand * left, int offl,
9195 operand * result, int offr, int shCount)
9197 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
9198 /* shift left accumulator */
9200 /* or with result */
9201 emitcode ("orl", "a,%s",
9202 aopGet (result, offr, FALSE, FALSE, DP2_RESULT_REG));
9203 /* back to result */
9204 aopPut (result, "a", offr);
9209 /*-----------------------------------------------------------------*/
9210 /* shiftRLeftOrResult - shift right one byte from left,or to result */
9211 /*-----------------------------------------------------------------*/
9213 shiftRLeftOrResult (operand * left, int offl,
9214 operand * result, int offr, int shCount)
9216 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
9217 /* shift right accumulator */
9219 /* or with result */
9220 emitcode ("orl", "a,%s",
9221 aopGet (result, offr, FALSE, FALSE, DP2_RESULT_REG));
9222 /* back to result */
9223 aopPut (result, "a", offr);
9227 #ifdef BETTER_LITERAL_SHIFT
9228 /*-----------------------------------------------------------------*/
9229 /* genlshOne - left shift a one byte quantity by known count */
9230 /*-----------------------------------------------------------------*/
9232 genlshOne (operand * result, operand * left, int shCount)
9234 D (emitcode (";", "genlshOne"));
9236 shiftL1Left2Result (left, LSB, result, LSB, shCount);
9240 #ifdef BETTER_LITERAL_SHIFT
9241 /*-----------------------------------------------------------------*/
9242 /* genlshTwo - left shift two bytes by known amount != 0 */
9243 /*-----------------------------------------------------------------*/
9245 genlshTwo (operand * result, operand * left, int shCount)
9249 D (emitcode (";", "genlshTwo"));
9251 size = getDataSize (result);
9253 /* if shCount >= 8 */
9258 _startLazyDPSEvaluation();
9264 _endLazyDPSEvaluation();
9265 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
9266 aopPut (result, zero, LSB);
9270 movLeft2Result (left, LSB, result, MSB16, 0);
9271 aopPut (result, zero, LSB);
9272 _endLazyDPSEvaluation();
9277 aopPut (result, zero, LSB);
9278 _endLazyDPSEvaluation();
9282 /* 1 <= shCount <= 7 */
9286 shiftL1Left2Result (left, LSB, result, LSB, shCount);
9288 shiftL2Left2Result (left, LSB, result, LSB, shCount);
9295 /*-----------------------------------------------------------------*/
9296 /* shiftLLong - shift left one long from left to result */
9297 /* offl = LSB or MSB16 */
9298 /*-----------------------------------------------------------------*/
9300 shiftLLong (operand * left, operand * result, int offr)
9303 int size = AOP_SIZE (result);
9305 if (size >= LSB + offr)
9307 l = aopGet (left, LSB, FALSE, FALSE, NULL);
9309 emitcode ("add", "a,acc");
9310 if (sameRegs (AOP (left), AOP (result)) &&
9311 size >= MSB16 + offr && offr != LSB)
9312 emitcode ("xch", "a,%s",
9313 aopGet (left, LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
9315 aopPut (result, "a", LSB + offr);
9318 if (size >= MSB16 + offr)
9320 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
9322 l = aopGet (left, MSB16, FALSE, FALSE, TRUE);
9325 emitcode ("rlc", "a");
9326 if (sameRegs (AOP (left), AOP (result)) &&
9327 size >= MSB24 + offr && offr != LSB)
9328 emitcode ("xch", "a,%s",
9329 aopGet (left, MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
9331 aopPut (result, "a", MSB16 + offr);
9334 if (size >= MSB24 + offr)
9336 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
9338 l = aopGet (left, MSB24, FALSE, FALSE, NULL);
9341 emitcode ("rlc", "a");
9342 if (sameRegs (AOP (left), AOP (result)) &&
9343 size >= MSB32 + offr && offr != LSB)
9344 emitcode ("xch", "a,%s",
9345 aopGet (left, MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
9347 aopPut (result, "a", MSB24 + offr);
9350 if (size > MSB32 + offr)
9352 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
9354 l = aopGet (left, MSB32, FALSE, FALSE, NULL);
9357 emitcode ("rlc", "a");
9358 aopPut (result, "a", MSB32 + offr);
9361 aopPut (result, zero, LSB);
9367 /*-----------------------------------------------------------------*/
9368 /* genlshFour - shift four byte by a known amount != 0 */
9369 /*-----------------------------------------------------------------*/
9371 genlshFour (operand * result, operand * left, int shCount)
9375 D (emitcode (";", "genlshFour"));
9377 size = AOP_SIZE (result);
9379 /* if shifting more that 3 bytes */
9384 /* lowest order of left goes to the highest
9385 order of the destination */
9386 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
9388 movLeft2Result (left, LSB, result, MSB32, 0);
9389 aopPut (result, zero, LSB);
9390 aopPut (result, zero, MSB16);
9391 aopPut (result, zero, MSB24);
9395 /* more than two bytes */
9396 else if (shCount >= 16)
9398 /* lower order two bytes goes to higher order two bytes */
9400 /* if some more remaining */
9402 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
9405 movLeft2Result (left, MSB16, result, MSB32, 0);
9406 movLeft2Result (left, LSB, result, MSB24, 0);
9408 aopPut (result, zero, MSB16);
9409 aopPut (result, zero, LSB);
9413 /* if more than 1 byte */
9414 else if (shCount >= 8)
9416 /* lower order three bytes goes to higher order three bytes */
9421 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
9423 movLeft2Result (left, LSB, result, MSB16, 0);
9429 movLeft2Result (left, MSB24, result, MSB32, 0);
9430 movLeft2Result (left, MSB16, result, MSB24, 0);
9431 movLeft2Result (left, LSB, result, MSB16, 0);
9432 aopPut (result, zero, LSB);
9434 else if (shCount == 1)
9435 shiftLLong (left, result, MSB16);
9438 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
9439 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
9440 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
9441 aopPut (result, zero, LSB);
9446 /* 1 <= shCount <= 7 */
9447 else if (shCount <= 2)
9449 shiftLLong (left, result, LSB);
9451 shiftLLong (result, result, LSB);
9453 /* 3 <= shCount <= 7, optimize */
9456 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
9457 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
9458 shiftL2Left2Result (left, LSB, result, LSB, shCount);
9463 #ifdef BETTER_LITERAL_SHIFT
9464 /*-----------------------------------------------------------------*/
9465 /* genLeftShiftLiteral - left shifting by known count */
9466 /*-----------------------------------------------------------------*/
9468 genLeftShiftLiteral (operand * left,
9473 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9476 size = getSize (operandType (result));
9478 D (emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
9480 /* We only handle certain easy cases so far. */
9482 && (shCount < (size * 8))
9486 D(emitcode (";", "genLeftShiftLiteral wimping out"););
9490 freeAsmop (right, NULL, ic, TRUE);
9492 aopOp(left, ic, FALSE, FALSE);
9493 aopOp(result, ic, FALSE, AOP_USESDPTR(left));
9496 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
9498 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
9499 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
9501 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
9504 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
9506 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
9507 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
9509 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
9515 emitcode ("; shift left ", "result %d, left %d", size,
9519 /* I suppose that the left size >= result size */
9522 _startLazyDPSEvaluation();
9525 movLeft2Result (left, size, result, size, 0);
9527 _endLazyDPSEvaluation();
9529 else if (shCount >= (size * 8))
9531 _startLazyDPSEvaluation();
9534 aopPut (result, zero, size);
9536 _endLazyDPSEvaluation();
9543 genlshOne (result, left, shCount);
9547 genlshTwo (result, left, shCount);
9551 genlshFour (result, left, shCount);
9555 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9556 "*** ack! mystery literal shift!\n");
9560 freeAsmop (result, NULL, ic, TRUE);
9561 freeAsmop (left, NULL, ic, TRUE);
9566 /*-----------------------------------------------------------------*/
9567 /* genLeftShift - generates code for left shifting */
9568 /*-----------------------------------------------------------------*/
9570 genLeftShift (iCode * ic)
9572 operand *left, *right, *result;
9575 symbol *tlbl, *tlbl1;
9578 D (emitcode (";", "genLeftShift"));
9580 right = IC_RIGHT (ic);
9581 left = IC_LEFT (ic);
9582 result = IC_RESULT (ic);
9584 aopOp (right, ic, FALSE, FALSE);
9587 #ifdef BETTER_LITERAL_SHIFT
9588 /* if the shift count is known then do it
9589 as efficiently as possible */
9590 if (AOP_TYPE (right) == AOP_LIT)
9592 if (genLeftShiftLiteral (left, right, result, ic))
9599 /* shift count is unknown then we have to form
9600 a loop get the loop count in B : Note: we take
9601 only the lower order byte since shifting
9602 more that 32 bits make no sense anyway, ( the
9603 largest size of an object can be only 32 bits ) */
9606 if (AOP_TYPE (right) == AOP_LIT)
9608 /* Really should be handled by genLeftShiftLiteral,
9609 * but since I'm too lazy to fix that today, at least we can make
9610 * some small improvement.
9612 emitcode("mov", "b,#!constbyte",
9613 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9617 MOVB (aopGet (right, 0, FALSE, FALSE, "b"));
9618 emitcode ("inc", "b");
9620 freeAsmop (right, NULL, ic, TRUE);
9621 aopOp (left, ic, FALSE, FALSE);
9622 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9624 /* now move the left to the result if they are not the same */
9625 if (!sameRegs (AOP (left), AOP (result)) &&
9626 AOP_SIZE (result) > 1)
9629 size = AOP_SIZE (result);
9631 _startLazyDPSEvaluation ();
9634 l = aopGet (left, offset, FALSE, TRUE, NULL);
9635 if (*l == '@' && (IS_AOP_PREG (result)))
9638 emitcode ("mov", "a,%s", l);
9639 aopPut (result, "a", offset);
9642 aopPut (result, l, offset);
9645 _endLazyDPSEvaluation ();
9648 tlbl = newiTempLabel (NULL);
9649 size = AOP_SIZE (result);
9651 tlbl1 = newiTempLabel (NULL);
9653 /* if it is only one byte then */
9656 symbol *tlbl1 = newiTempLabel (NULL);
9658 l = aopGet (left, 0, FALSE, FALSE, NULL);
9660 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9662 emitcode ("add", "a,acc");
9664 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9666 aopPut (result, "a", 0);
9670 reAdjustPreg (AOP (result));
9672 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9674 l = aopGet (result, offset, FALSE, FALSE, NULL);
9676 emitcode ("add", "a,acc");
9677 aopPut (result, "a", offset++);
9678 _startLazyDPSEvaluation ();
9681 l = aopGet (result, offset, FALSE, FALSE, NULL);
9683 emitcode ("rlc", "a");
9684 aopPut (result, "a", offset++);
9686 _endLazyDPSEvaluation ();
9687 reAdjustPreg (AOP (result));
9690 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9693 freeAsmop (result, NULL, ic, TRUE);
9694 freeAsmop (left, NULL, ic, TRUE);
9697 #ifdef BETTER_LITERAL_SHIFT
9698 /*-----------------------------------------------------------------*/
9699 /* genrshOne - right shift a one byte quantity by known count */
9700 /*-----------------------------------------------------------------*/
9702 genrshOne (operand * result, operand * left,
9703 int shCount, int sign)
9705 D (emitcode (";", "genrshOne"));
9707 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9711 #ifdef BETTER_LITERAL_SHIFT
9712 /*-----------------------------------------------------------------*/
9713 /* genrshTwo - right shift two bytes by known amount != 0 */
9714 /*-----------------------------------------------------------------*/
9716 genrshTwo (operand * result, operand * left,
9717 int shCount, int sign)
9719 D (emitcode (";", "genrshTwo"));
9721 /* if shCount >= 8 */
9725 _startLazyDPSEvaluation();
9727 shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
9729 movLeft2Result (left, MSB16, result, LSB, sign);
9730 addSign (result, MSB16, sign);
9731 _endLazyDPSEvaluation();
9734 /* 1 <= shCount <= 7 */
9736 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9740 /*-----------------------------------------------------------------*/
9741 /* shiftRLong - shift right one long from left to result */
9742 /* offl = LSB or MSB16 */
9743 /*-----------------------------------------------------------------*/
9745 shiftRLong (operand * left, int offl,
9746 operand * result, int sign)
9748 bool overlapping = regsInCommon (left, result) || operandsEqu(left, result);
9750 if (overlapping && offl>1)
9752 // we are in big trouble, but this shouldn't happen
9753 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9756 MOVA (aopGet (left, MSB32, FALSE, FALSE, NULL));
9763 emitcode ("rlc", "a");
9764 emitcode ("subb", "a,acc");
9765 emitcode ("xch", "a,%s",
9766 aopGet(left, MSB32, FALSE, FALSE, DP2_RESULT_REG));
9770 aopPut (result, zero, MSB32);
9776 emitcode ("clr", "c");
9780 emitcode ("mov", "c,acc.7");
9783 emitcode ("rrc", "a");
9785 if (overlapping && offl==MSB16)
9787 emitcode ("xch", "a,%s", aopGet (left, MSB24, FALSE, FALSE, DP2_RESULT_REG));
9791 aopPut (result, "a", MSB32 - offl);
9792 MOVA (aopGet (left, MSB24, FALSE, FALSE, NULL));
9795 emitcode ("rrc", "a");
9797 if (overlapping && offl==MSB16)
9799 emitcode ("xch", "a,%s", aopGet (left, MSB16, FALSE, FALSE, DP2_RESULT_REG));
9803 aopPut (result, "a", MSB24 - offl);
9804 MOVA (aopGet (left, MSB16, FALSE, FALSE, NULL));
9807 emitcode ("rrc", "a");
9810 aopPut (result, "a", MSB16 - offl);
9814 if (overlapping && offl==MSB16)
9816 emitcode ("xch", "a,%s", aopGet (left, LSB, FALSE, FALSE, DP2_RESULT_REG));
9820 aopPut (result, "a", MSB16 - offl);
9821 MOVA (aopGet (left, LSB, FALSE, FALSE, NULL));
9823 emitcode ("rrc", "a");
9824 aopPut (result, "a", LSB);
9828 /*-----------------------------------------------------------------*/
9829 /* genrshFour - shift four byte by a known amount != 0 */
9830 /*-----------------------------------------------------------------*/
9832 genrshFour (operand * result, operand * left,
9833 int shCount, int sign)
9835 D (emitcode (";", "genrshFour"));
9837 /* if shifting more that 3 bytes */
9841 _startLazyDPSEvaluation();
9843 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9845 movLeft2Result (left, MSB32, result, LSB, sign);
9846 addSign (result, MSB16, sign);
9847 _endLazyDPSEvaluation();
9849 else if (shCount >= 16)
9852 _startLazyDPSEvaluation();
9854 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9857 movLeft2Result (left, MSB24, result, LSB, 0);
9858 movLeft2Result (left, MSB32, result, MSB16, sign);
9860 addSign (result, MSB24, sign);
9861 _endLazyDPSEvaluation();
9863 else if (shCount >= 8)
9866 _startLazyDPSEvaluation();
9869 shiftRLong (left, MSB16, result, sign);
9871 else if (shCount == 0)
9873 movLeft2Result (left, MSB16, result, LSB, 0);
9874 movLeft2Result (left, MSB24, result, MSB16, 0);
9875 movLeft2Result (left, MSB32, result, MSB24, sign);
9876 addSign (result, MSB32, sign);
9880 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9881 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9882 /* the last shift is signed */
9883 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9884 addSign (result, MSB32, sign);
9886 _endLazyDPSEvaluation();
9890 /* 1 <= shCount <= 7 */
9893 shiftRLong (left, LSB, result, sign);
9895 shiftRLong (result, LSB, result, sign);
9899 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9900 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9901 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9906 #ifdef BETTER_LITERAL_SHIFT
9907 /*-----------------------------------------------------------------*/
9908 /* genRightShiftLiteral - right shifting by known count */
9909 /*-----------------------------------------------------------------*/
9911 genRightShiftLiteral (operand * left,
9917 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9920 size = getSize (operandType (result));
9922 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
9924 /* We only handle certain easy cases so far. */
9926 && (shCount < (size * 8))
9931 D(emitcode (";", "genRightShiftLiteral wimping out"););
9935 freeAsmop (right, NULL, ic, TRUE);
9937 aopOp (left, ic, FALSE, FALSE);
9938 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9941 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9945 /* test the LEFT size !!! */
9947 /* I suppose that the left size >= result size */
9950 size = getDataSize (result);
9951 _startLazyDPSEvaluation();
9953 movLeft2Result (left, size, result, size, 0);
9954 _endLazyDPSEvaluation();
9956 else if (shCount >= (size * 8))
9960 /* get sign in acc.7 */
9961 MOVA (aopGet (left, size - 1, FALSE, FALSE, NULL));
9963 addSign (result, LSB, sign);
9970 genrshOne (result, left, shCount, sign);
9974 genrshTwo (result, left, shCount, sign);
9978 genrshFour (result, left, shCount, sign);
9985 freeAsmop (result, NULL, ic, TRUE);
9986 freeAsmop (left, NULL, ic, TRUE);
9992 /*-----------------------------------------------------------------*/
9993 /* genSignedRightShift - right shift of signed number */
9994 /*-----------------------------------------------------------------*/
9996 genSignedRightShift (iCode * ic)
9998 operand *right, *left, *result;
10001 symbol *tlbl, *tlbl1;
10004 D (emitcode (";", "genSignedRightShift"));
10006 /* we do it the hard way put the shift count in b
10007 and loop thru preserving the sign */
10009 right = IC_RIGHT (ic);
10010 left = IC_LEFT (ic);
10011 result = IC_RESULT (ic);
10013 aopOp (right, ic, FALSE, FALSE);
10015 #ifdef BETTER_LITERAL_SHIFT
10016 if (AOP_TYPE (right) == AOP_LIT)
10018 if (genRightShiftLiteral (left, right, result, ic, 1))
10024 /* shift count is unknown then we have to form
10025 a loop get the loop count in B : Note: we take
10026 only the lower order byte since shifting
10027 more that 32 bits make no sense anyway, ( the
10028 largest size of an object can be only 32 bits ) */
10030 pushedB = pushB ();
10031 if (AOP_TYPE (right) == AOP_LIT)
10033 /* Really should be handled by genRightShiftLiteral,
10034 * but since I'm too lazy to fix that today, at least we can make
10035 * some small improvement.
10037 emitcode("mov", "b,#!constbyte",
10038 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
10042 MOVB (aopGet (right, 0, FALSE, FALSE, "b"));
10043 emitcode ("inc", "b");
10045 freeAsmop (right, NULL, ic, TRUE);
10046 aopOp (left, ic, FALSE, FALSE);
10047 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
10049 /* now move the left to the result if they are not the
10051 if (!sameRegs (AOP (left), AOP (result)) &&
10052 AOP_SIZE (result) > 1)
10055 size = AOP_SIZE (result);
10057 _startLazyDPSEvaluation ();
10060 l = aopGet (left, offset, FALSE, TRUE, NULL);
10061 if (*l == '@' && IS_AOP_PREG (result))
10064 emitcode ("mov", "a,%s", l);
10065 aopPut (result, "a", offset);
10068 aopPut (result, l, offset);
10071 _endLazyDPSEvaluation ();
10074 /* mov the highest order bit to OVR */
10075 tlbl = newiTempLabel (NULL);
10076 tlbl1 = newiTempLabel (NULL);
10078 size = AOP_SIZE (result);
10080 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
10081 emitcode ("rlc", "a");
10082 emitcode ("mov", "ov,c");
10083 /* if it is only one byte then */
10086 l = aopGet (left, 0, FALSE, FALSE, NULL);
10088 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
10090 emitcode ("mov", "c,ov");
10091 emitcode ("rrc", "a");
10093 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
10095 aopPut (result, "a", 0);
10099 reAdjustPreg (AOP (result));
10100 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
10102 emitcode ("mov", "c,ov");
10103 _startLazyDPSEvaluation ();
10106 l = aopGet (result, offset, FALSE, FALSE, NULL);
10108 emitcode ("rrc", "a");
10109 aopPut (result, "a", offset--);
10111 _endLazyDPSEvaluation ();
10112 reAdjustPreg (AOP (result));
10114 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
10118 freeAsmop (result, NULL, ic, TRUE);
10119 freeAsmop (left, NULL, ic, TRUE);
10122 /*-----------------------------------------------------------------*/
10123 /* genRightShift - generate code for right shifting */
10124 /*-----------------------------------------------------------------*/
10126 genRightShift (iCode * ic)
10128 operand *right, *left, *result;
10132 symbol *tlbl, *tlbl1;
10135 D (emitcode (";", "genRightShift"));
10137 /* if signed then we do it the hard way preserve the
10138 sign bit moving it inwards */
10139 letype = getSpec (operandType (IC_LEFT (ic)));
10141 if (!SPEC_USIGN (letype))
10143 genSignedRightShift (ic);
10147 /* signed & unsigned types are treated the same : i.e. the
10148 signed is NOT propagated inwards : quoting from the
10149 ANSI - standard : "for E1 >> E2, is equivalent to division
10150 by 2**E2 if unsigned or if it has a non-negative value,
10151 otherwise the result is implementation defined ", MY definition
10152 is that the sign does not get propagated */
10154 right = IC_RIGHT (ic);
10155 left = IC_LEFT (ic);
10156 result = IC_RESULT (ic);
10158 aopOp (right, ic, FALSE, FALSE);
10160 #ifdef BETTER_LITERAL_SHIFT
10161 /* if the shift count is known then do it
10162 as efficiently as possible */
10163 if (AOP_TYPE (right) == AOP_LIT)
10165 if (genRightShiftLiteral (left, right, result, ic, 0))
10172 /* shift count is unknown then we have to form
10173 a loop get the loop count in B : Note: we take
10174 only the lower order byte since shifting
10175 more that 32 bits make no sense anyway, ( the
10176 largest size of an object can be only 32 bits ) */
10178 pushedB = pushB ();
10179 if (AOP_TYPE (right) == AOP_LIT)
10181 /* Really should be handled by genRightShiftLiteral,
10182 * but since I'm too lazy to fix that today, at least we can make
10183 * some small improvement.
10185 emitcode("mov", "b,#!constbyte",
10186 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
10190 MOVB (aopGet (right, 0, FALSE, FALSE, "b"));
10191 emitcode ("inc", "b");
10193 freeAsmop (right, NULL, ic, TRUE);
10194 aopOp (left, ic, FALSE, FALSE);
10195 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
10197 /* now move the left to the result if they are not the
10199 if (!sameRegs (AOP (left), AOP (result)) &&
10200 AOP_SIZE (result) > 1)
10202 size = AOP_SIZE (result);
10204 _startLazyDPSEvaluation ();
10207 l = aopGet (left, offset, FALSE, TRUE, NULL);
10208 if (*l == '@' && IS_AOP_PREG (result))
10211 emitcode ("mov", "a,%s", l);
10212 aopPut (result, "a", offset);
10215 aopPut (result, l, offset);
10218 _endLazyDPSEvaluation ();
10221 tlbl = newiTempLabel (NULL);
10222 tlbl1 = newiTempLabel (NULL);
10223 size = AOP_SIZE (result);
10226 /* if it is only one byte then */
10229 l = aopGet (left, 0, FALSE, FALSE, NULL);
10231 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
10234 emitcode ("rrc", "a");
10236 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
10238 aopPut (result, "a", 0);
10242 reAdjustPreg (AOP (result));
10243 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
10246 _startLazyDPSEvaluation ();
10249 l = aopGet (result, offset, FALSE, FALSE, NULL);
10251 emitcode ("rrc", "a");
10252 aopPut (result, "a", offset--);
10254 _endLazyDPSEvaluation ();
10255 reAdjustPreg (AOP (result));
10258 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
10262 freeAsmop (result, NULL, ic, TRUE);
10263 freeAsmop (left, NULL, ic, TRUE);
10266 /*-----------------------------------------------------------------*/
10267 /* emitPtrByteGet - emits code to get a byte into A through a */
10268 /* pointer register (R0, R1, or DPTR). The */
10269 /* original value of A can be preserved in B. */
10270 /*-----------------------------------------------------------------*/
10272 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
10279 emitcode ("mov", "b,a");
10280 emitcode ("mov", "a,@%s", rname);
10285 emitcode ("mov", "b,a");
10286 emitcode ("movx", "a,@%s", rname);
10291 emitcode ("mov", "b,a");
10292 emitcode ("movx", "a,@dptr");
10297 emitcode ("mov", "b,a");
10298 emitcode ("clr", "a");
10299 emitcode ("movc", "a,@a+dptr");
10305 emitcode ("push", "b");
10306 emitcode ("push", "acc");
10308 emitcode ("lcall", "__gptrget");
10310 emitcode ("pop", "b");
10315 /*-----------------------------------------------------------------*/
10316 /* emitPtrByteSet - emits code to set a byte from src through a */
10317 /* pointer register (R0, R1, or DPTR). */
10318 /*-----------------------------------------------------------------*/
10320 emitPtrByteSet (char *rname, int p_type, char *src)
10329 emitcode ("mov", "@%s,a", rname);
10332 emitcode ("mov", "@%s,%s", rname, src);
10337 emitcode ("movx", "@%s,a", rname);
10342 emitcode ("movx", "@dptr,a");
10347 emitcode ("lcall", "__gptrput");
10352 /*-----------------------------------------------------------------*/
10353 /* genUnpackBits - generates code for unpacking bits */
10354 /*-----------------------------------------------------------------*/
10356 genUnpackBits (operand * result, char *rname, int ptype)
10358 int offset = 0; /* result byte offset */
10359 int rsize; /* result size */
10360 int rlen = 0; /* remaining bitfield length */
10361 sym_link *etype; /* bitfield type information */
10362 int blen; /* bitfield length */
10363 int bstr; /* bitfield starting bit within byte */
10365 D(emitcode ("; genUnpackBits",""));
10367 etype = getSpec (operandType (result));
10368 rsize = getSize (operandType (result));
10369 blen = SPEC_BLEN (etype);
10370 bstr = SPEC_BSTR (etype);
10372 /* If the bitfield length is less than a byte */
10375 emitPtrByteGet (rname, ptype, FALSE);
10377 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
10378 if (!SPEC_USIGN (etype))
10380 /* signed bitfield */
10381 symbol *tlbl = newiTempLabel (NULL);
10383 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
10384 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
10387 aopPut (result, "a", offset++);
10391 /* Bit field did not fit in a byte. Copy all
10392 but the partial byte at the end. */
10393 for (rlen=blen;rlen>=8;rlen-=8)
10395 emitPtrByteGet (rname, ptype, FALSE);
10396 aopPut (result, "a", offset++);
10398 emitcode ("inc", "%s", rname);
10401 /* Handle the partial byte at the end */
10404 emitPtrByteGet (rname, ptype, FALSE);
10405 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
10406 if (!SPEC_USIGN (etype))
10408 /* signed bitfield */
10409 symbol *tlbl = newiTempLabel (NULL);
10411 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
10412 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
10415 aopPut (result, "a", offset++);
10419 if (offset < rsize)
10423 if (SPEC_USIGN (etype))
10427 /* signed bitfield: sign extension with 0x00 or 0xff */
10428 emitcode ("rlc", "a");
10429 emitcode ("subb", "a,acc");
10435 aopPut (result, source, offset++);
10440 /*-----------------------------------------------------------------*/
10441 /* genDataPointerGet - generates code when ptr offset is known */
10442 /*-----------------------------------------------------------------*/
10444 genDataPointerGet (operand * left,
10450 int size, offset = 0;
10451 aopOp (result, ic, TRUE, FALSE);
10453 /* get the string representation of the name */
10454 l = aopGet (left, 0, FALSE, TRUE, NULL);
10455 size = AOP_SIZE (result);
10456 _startLazyDPSEvaluation ();
10461 SNPRINTF (buffer, sizeof(buffer),
10462 "(%s + %d)", l + 1, offset);
10466 SNPRINTF (buffer, sizeof(buffer),
10469 aopPut (result, buffer, offset++);
10471 _endLazyDPSEvaluation ();
10473 freeAsmop (result, NULL, ic, TRUE);
10474 freeAsmop (left, NULL, ic, TRUE);
10477 /*-----------------------------------------------------------------*/
10478 /* genNearPointerGet - emitcode for near pointer fetch */
10479 /*-----------------------------------------------------------------*/
10481 genNearPointerGet (operand * left,
10489 sym_link *rtype, *retype, *letype;
10490 sym_link *ltype = operandType (left);
10493 rtype = operandType (result);
10494 retype = getSpec (rtype);
10495 letype = getSpec (ltype);
10497 aopOp (left, ic, FALSE, FALSE);
10499 /* if left is rematerialisable and
10500 result is not bitfield variable type and
10501 the left is pointer to data space i.e
10502 lower 128 bytes of space */
10503 if (AOP_TYPE (left) == AOP_IMMD &&
10504 !IS_BITFIELD (retype) &&
10505 !IS_BITFIELD (letype) &&
10506 DCL_TYPE (ltype) == POINTER)
10508 genDataPointerGet (left, result, ic);
10512 /* if the value is already in a pointer register
10513 then don't need anything more */
10514 if (!AOP_INPREG (AOP (left)))
10516 /* otherwise get a free pointer register */
10517 aop = newAsmop (0);
10518 preg = getFreePtr (ic, &aop, FALSE);
10519 emitcode ("mov", "%s,%s",
10521 aopGet (left, 0, FALSE, TRUE, DP2_RESULT_REG));
10522 rname = preg->name;
10525 rname = aopGet (left, 0, FALSE, FALSE, DP2_RESULT_REG);
10527 freeAsmop (left, NULL, ic, TRUE);
10528 aopOp (result, ic, FALSE, FALSE);
10530 /* if bitfield then unpack the bits */
10531 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10532 genUnpackBits (result, rname, POINTER);
10535 /* we have can just get the values */
10536 int size = AOP_SIZE (result);
10541 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
10544 emitcode ("mov", "a,@%s", rname);
10545 aopPut (result, "a", offset);
10549 SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
10550 aopPut (result, buffer, offset);
10554 emitcode ("inc", "%s", rname);
10558 /* now some housekeeping stuff */
10559 if (aop) /* we had to allocate for this iCode */
10561 if (pi) { /* post increment present */
10562 aopPut (left, rname, 0);
10564 freeAsmop (NULL, aop, ic, TRUE);
10568 /* we did not allocate which means left
10569 already in a pointer register, then
10570 if size > 0 && this could be used again
10571 we have to point it back to where it
10573 if (AOP_SIZE (result) > 1 &&
10574 !OP_SYMBOL (left)->remat &&
10575 (OP_SYMBOL (left)->liveTo > ic->seq ||
10579 int size = AOP_SIZE (result) - 1;
10581 emitcode ("dec", "%s", rname);
10586 freeAsmop (result, NULL, ic, TRUE);
10587 if (pi) pi->generated = 1;
10590 /*-----------------------------------------------------------------*/
10591 /* genPagedPointerGet - emitcode for paged pointer fetch */
10592 /*-----------------------------------------------------------------*/
10594 genPagedPointerGet (operand * left,
10602 sym_link *rtype, *retype, *letype;
10604 rtype = operandType (result);
10605 retype = getSpec (rtype);
10606 letype = getSpec (operandType (left));
10607 aopOp (left, ic, FALSE, FALSE);
10609 /* if the value is already in a pointer register
10610 then don't need anything more */
10611 if (!AOP_INPREG (AOP (left)))
10613 /* otherwise get a free pointer register */
10614 aop = newAsmop (0);
10615 preg = getFreePtr (ic, &aop, FALSE);
10616 emitcode ("mov", "%s,%s",
10618 aopGet (left, 0, FALSE, TRUE, NULL));
10619 rname = preg->name;
10622 rname = aopGet (left, 0, FALSE, FALSE, NULL);
10624 freeAsmop (left, NULL, ic, TRUE);
10625 aopOp (result, ic, FALSE, FALSE);
10627 /* if bitfield then unpack the bits */
10628 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10629 genUnpackBits (result, rname, PPOINTER);
10632 /* we have can just get the values */
10633 int size = AOP_SIZE (result);
10639 emitcode ("movx", "a,@%s", rname);
10640 aopPut (result, "a", offset);
10645 emitcode ("inc", "%s", rname);
10649 /* now some housekeeping stuff */
10650 if (aop) /* we had to allocate for this iCode */
10653 aopPut (left, rname, 0);
10654 freeAsmop (NULL, aop, ic, TRUE);
10658 /* we did not allocate which means left
10659 already in a pointer register, then
10660 if size > 0 && this could be used again
10661 we have to point it back to where it
10663 if (AOP_SIZE (result) > 1 &&
10664 !OP_SYMBOL (left)->remat &&
10665 (OP_SYMBOL (left)->liveTo > ic->seq ||
10669 int size = AOP_SIZE (result) - 1;
10671 emitcode ("dec", "%s", rname);
10676 freeAsmop (result, NULL, ic, TRUE);
10677 if (pi) pi->generated = 1;
10680 /*-----------------------------------------------------------------*/
10681 /* genFarPointerGet - get value from far space */
10682 /*-----------------------------------------------------------------*/
10684 genFarPointerGet (operand * left,
10685 operand * result, iCode * ic, iCode *pi)
10687 int size, offset, dopi=1;
10688 sym_link *retype = getSpec (operandType (result));
10689 sym_link *letype = getSpec (operandType (left));
10690 D (emitcode (";", "genFarPointerGet"););
10692 aopOp (left, ic, FALSE, FALSE);
10694 /* if the operand is already in dptr
10695 then we do nothing else we move the value to dptr */
10696 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
10698 /* if this is rematerializable */
10699 if (AOP_TYPE (left) == AOP_IMMD)
10701 emitcode ("mov", "dptr,%s", aopGet (left, 0, TRUE, FALSE, NULL));
10705 /* we need to get it byte by byte */
10706 _startLazyDPSEvaluation ();
10707 if (AOP_TYPE (left) != AOP_DPTR)
10709 emitcode ("mov", "dpl,%s", aopGet (left, 0, FALSE, FALSE, NULL));
10710 emitcode ("mov", "dph,%s", aopGet (left, 1, FALSE, FALSE, NULL));
10711 if (options.model == MODEL_FLAT24)
10712 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10716 /* We need to generate a load to DPTR indirect through DPTR. */
10717 D (emitcode (";", "genFarPointerGet -- indirection special case."););
10718 emitcode ("push", "%s", aopGet (left, 0, FALSE, TRUE, NULL));
10719 emitcode ("push", "%s", aopGet (left, 1, FALSE, TRUE, NULL));
10720 if (options.model == MODEL_FLAT24)
10721 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10722 emitcode ("pop", "dph");
10723 emitcode ("pop", "dpl");
10726 _endLazyDPSEvaluation ();
10729 /* so dptr now contains the address */
10730 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10732 /* if bit then unpack */
10733 if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
10734 if (AOP_INDPTRn(left)) {
10735 genSetDPTR(AOP(left)->aopu.dptr);
10737 genUnpackBits (result, "dptr", FPOINTER);
10738 if (AOP_INDPTRn(left)) {
10743 size = AOP_SIZE (result);
10746 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10748 genSetDPTR(AOP(left)->aopu.dptr);
10749 emitcode ("movx", "a,@dptr");
10750 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10751 emitcode ("inc", "dptr");
10753 aopPut (result, "a", offset++);
10756 _startLazyDPSEvaluation ();
10758 if (AOP_INDPTRn(left)) {
10759 genSetDPTR(AOP(left)->aopu.dptr);
10765 emitcode ("movx", "a,@dptr");
10766 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10767 emitcode ("inc", "dptr");
10769 aopPut (result, "a", offset++);
10771 _endLazyDPSEvaluation ();
10774 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10775 if (!AOP_INDPTRn(left)) {
10776 _startLazyDPSEvaluation ();
10777 aopPut (left, "dpl", 0);
10778 aopPut (left, "dph", 1);
10779 if (options.model == MODEL_FLAT24)
10780 aopPut (left, "dpx", 2);
10781 _endLazyDPSEvaluation ();
10784 } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) &&
10785 AOP_SIZE(result) > 1 &&
10787 (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
10789 size = AOP_SIZE (result) - 1;
10790 if (AOP_INDPTRn(left)) {
10791 genSetDPTR(AOP(left)->aopu.dptr);
10793 while (size--) emitcode ("lcall","__decdptr");
10794 if (AOP_INDPTRn(left)) {
10799 freeAsmop (result, NULL, ic, TRUE);
10800 freeAsmop (left, NULL, ic, TRUE);
10803 /*-----------------------------------------------------------------*/
10804 /* genCodePointerGet - get value from code space */
10805 /*-----------------------------------------------------------------*/
10807 genCodePointerGet (operand * left,
10808 operand * result, iCode * ic, iCode *pi)
10810 int size, offset, dopi=1;
10811 sym_link *retype = getSpec (operandType (result));
10813 aopOp (left, ic, FALSE, FALSE);
10815 /* if the operand is already in dptr
10816 then we do nothing else we move the value to dptr */
10817 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
10819 /* if this is rematerializable */
10820 if (AOP_TYPE (left) == AOP_IMMD)
10822 emitcode ("mov", "dptr,%s", aopGet (left, 0, TRUE, FALSE, NULL));
10825 { /* we need to get it byte by byte */
10826 _startLazyDPSEvaluation ();
10827 if (AOP_TYPE (left) != AOP_DPTR)
10829 emitcode ("mov", "dpl,%s", aopGet (left, 0, FALSE, FALSE, NULL));
10830 emitcode ("mov", "dph,%s", aopGet (left, 1, FALSE, FALSE, NULL));
10831 if (options.model == MODEL_FLAT24)
10832 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10836 /* We need to generate a load to DPTR indirect through DPTR. */
10837 D (emitcode (";", "gencodePointerGet -- indirection special case."););
10838 emitcode ("push", "%s", aopGet (left, 0, FALSE, TRUE, NULL));
10839 emitcode ("push", "%s", aopGet (left, 1, FALSE, TRUE, NULL));
10840 if (options.model == MODEL_FLAT24)
10841 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10842 emitcode ("pop", "dph");
10843 emitcode ("pop", "dpl");
10846 _endLazyDPSEvaluation ();
10849 /* so dptr now contains the address */
10850 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10852 /* if bit then unpack */
10853 if (IS_BITFIELD (retype)) {
10854 if (AOP_INDPTRn(left)) {
10855 genSetDPTR(AOP(left)->aopu.dptr);
10857 genUnpackBits (result, "dptr", CPOINTER);
10858 if (AOP_INDPTRn(left)) {
10863 size = AOP_SIZE (result);
10865 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10867 genSetDPTR(AOP(left)->aopu.dptr);
10868 emitcode ("clr", "a");
10869 emitcode ("movc", "a,@a+dptr");
10870 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10871 emitcode ("inc", "dptr");
10873 aopPut (result, "a", offset++);
10876 _startLazyDPSEvaluation ();
10879 if (AOP_INDPTRn(left)) {
10880 genSetDPTR(AOP(left)->aopu.dptr);
10886 emitcode ("clr", "a");
10887 emitcode ("movc", "a,@a+dptr");
10888 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10889 emitcode ("inc", "dptr");
10890 aopPut (result, "a", offset++);
10892 _endLazyDPSEvaluation ();
10895 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10896 if (!AOP_INDPTRn(left)) {
10897 _startLazyDPSEvaluation ();
10899 aopPut (left, "dpl", 0);
10900 aopPut (left, "dph", 1);
10901 if (options.model == MODEL_FLAT24)
10902 aopPut (left, "dpx", 2);
10904 _endLazyDPSEvaluation ();
10907 } else if (IS_SYMOP(left) &&
10908 (OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
10909 AOP_SIZE(result) > 1 &&
10910 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10912 size = AOP_SIZE (result) - 1;
10913 if (AOP_INDPTRn(left)) {
10914 genSetDPTR(AOP(left)->aopu.dptr);
10916 while (size--) emitcode ("lcall","__decdptr");
10917 if (AOP_INDPTRn(left)) {
10922 freeAsmop (result, NULL, ic, TRUE);
10923 freeAsmop (left, NULL, ic, TRUE);
10926 /*-----------------------------------------------------------------*/
10927 /* genGenPointerGet - get value from generic pointer space */
10928 /*-----------------------------------------------------------------*/
10930 genGenPointerGet (operand * left,
10931 operand * result, iCode * ic, iCode * pi)
10935 sym_link *retype = getSpec (operandType (result));
10936 sym_link *letype = getSpec (operandType (left));
10938 D (emitcode (";", "genGenPointerGet"));
10940 aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
10942 pushedB = pushB ();
10943 /* if the operand is already in dptr
10944 then we do nothing else we move the value to dptr */
10945 if (AOP_TYPE (left) != AOP_STR)
10947 /* if this is rematerializable */
10948 if (AOP_TYPE (left) == AOP_IMMD)
10950 emitcode ("mov", "dptr,%s", aopGet (left, 0, TRUE, FALSE, NULL));
10951 if (AOP(left)->aopu.aop_immd.from_cast_remat)
10953 MOVB (aopGet (left, AOP_SIZE(left)-1, FALSE, FALSE, NULL));
10957 emitcode ("mov", "b,#%d", pointerCode (retype));
10961 { /* we need to get it byte by byte */
10962 _startLazyDPSEvaluation ();
10963 emitcode ("mov", "dpl,%s", aopGet (left,0,FALSE,FALSE,NULL));
10964 emitcode ("mov", "dph,%s", aopGet (left,1,FALSE,FALSE,NULL));
10965 if (options.model == MODEL_FLAT24) {
10966 emitcode ("mov", "dpx,%s", aopGet (left,2,FALSE,FALSE,NULL));
10967 emitcode ("mov", "b,%s", aopGet (left,3,FALSE,FALSE,NULL));
10969 emitcode ("mov", "b,%s", aopGet (left,2,FALSE,FALSE,NULL));
10971 _endLazyDPSEvaluation ();
10975 /* so dptr-b now contains the address */
10976 aopOp (result, ic, FALSE, TRUE);
10978 /* if bit then unpack */
10979 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10981 genUnpackBits (result, "dptr", GPOINTER);
10985 size = AOP_SIZE (result);
10992 // Get two bytes at a time, results in _AP & A.
10993 // dptr will be incremented ONCE by __gptrgetWord.
10995 // Note: any change here must be coordinated
10996 // with the implementation of __gptrgetWord
10997 // in device/lib/_gptrget.c
10998 emitcode ("lcall", "__gptrgetWord");
10999 aopPut (result, DP2_RESULT_REG, offset++);
11000 aopPut (result, "a", offset++);
11005 // Only one byte to get.
11006 emitcode ("lcall", "__gptrget");
11007 aopPut (result, "a", offset++);
11010 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
11012 emitcode ("inc", "dptr");
11017 if (pi && AOP_TYPE (left) != AOP_IMMD) {
11018 _startLazyDPSEvaluation ();
11020 aopPut (left, "dpl", 0);
11021 aopPut (left, "dph", 1);
11022 if (options.model == MODEL_FLAT24) {
11023 aopPut (left, "dpx", 2);
11024 aopPut (left, "b", 3);
11025 } else aopPut (left, "b", 2);
11027 _endLazyDPSEvaluation ();
11030 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
11031 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
11033 size = AOP_SIZE (result) - 1;
11034 while (size--) emitcode ("lcall","__decdptr");
11038 freeAsmop (result, NULL, ic, TRUE);
11039 freeAsmop (left, NULL, ic, TRUE);
11042 /*-----------------------------------------------------------------*/
11043 /* genPointerGet - generate code for pointer get */
11044 /*-----------------------------------------------------------------*/
11046 genPointerGet (iCode * ic, iCode *pi)
11048 operand *left, *result;
11049 sym_link *type, *etype;
11052 D (emitcode (";", "genPointerGet"));
11054 left = IC_LEFT (ic);
11055 result = IC_RESULT (ic);
11057 /* depending on the type of pointer we need to
11058 move it to the correct pointer register */
11059 type = operandType (left);
11060 etype = getSpec (type);
11061 /* if left is of type of pointer then it is simple */
11062 if (IS_PTR (type) && !IS_FUNC (type->next))
11063 p_type = DCL_TYPE (type);
11066 /* we have to go by the storage class */
11067 p_type = PTR_TYPE (SPEC_OCLS (etype));
11070 /* special case when cast remat */
11071 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
11072 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
11074 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
11075 type = operandType (left);
11076 p_type = DCL_TYPE (type);
11078 /* now that we have the pointer type we assign
11079 the pointer values */
11085 genNearPointerGet (left, result, ic, pi);
11089 genPagedPointerGet (left, result, ic, pi);
11093 genFarPointerGet (left, result, ic, pi);
11097 genCodePointerGet (left, result, ic, pi);
11101 genGenPointerGet (left, result, ic, pi);
11107 /*-----------------------------------------------------------------*/
11108 /* genPackBits - generates code for packed bit storage */
11109 /*-----------------------------------------------------------------*/
11111 genPackBits (sym_link * etype,
11113 char *rname, int p_type)
11115 int offset = 0; /* source byte offset */
11116 int rlen = 0; /* remaining bitfield length */
11117 int blen; /* bitfield length */
11118 int bstr; /* bitfield starting bit within byte */
11119 int litval; /* source literal value (if AOP_LIT) */
11120 unsigned char mask; /* bitmask within current byte */
11122 D(emitcode ("; genPackBits",""));
11124 blen = SPEC_BLEN (etype);
11125 bstr = SPEC_BSTR (etype);
11127 /* If the bitfield length is less than a byte */
11130 mask = ((unsigned char) (0xFF << (blen + bstr)) |
11131 (unsigned char) (0xFF >> (8 - bstr)));
11133 if (AOP_TYPE (right) == AOP_LIT)
11135 /* Case with a bitfield length <8 and literal source
11137 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
11139 litval &= (~mask) & 0xff;
11140 emitPtrByteGet (rname, p_type, FALSE);
11141 if ((mask|litval)!=0xff)
11142 emitcode ("anl","a,#!constbyte", mask);
11144 emitcode ("orl","a,#!constbyte", litval);
11148 if ((blen==1) && (p_type!=GPOINTER))
11150 /* Case with a bitfield length == 1 and no generic pointer
11152 if (AOP_TYPE (right) == AOP_CRY)
11153 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
11156 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
11157 emitcode ("rrc","a");
11159 emitPtrByteGet (rname, p_type, FALSE);
11160 emitcode ("mov","acc.%d,c",bstr);
11165 /* Case with a bitfield length < 8 and arbitrary source
11167 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
11168 /* shift and mask source value */
11170 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
11172 pushedB = pushB ();
11173 /* transfer A to B and get next byte */
11174 emitPtrByteGet (rname, p_type, TRUE);
11176 emitcode ("anl", "a,#!constbyte", mask);
11177 emitcode ("orl", "a,b");
11178 if (p_type == GPOINTER)
11179 emitcode ("pop", "b");
11185 emitPtrByteSet (rname, p_type, "a");
11189 /* Bit length is greater than 7 bits. In this case, copy */
11190 /* all except the partial byte at the end */
11191 for (rlen=blen;rlen>=8;rlen-=8)
11193 emitPtrByteSet (rname, p_type,
11194 aopGet (right, offset++, FALSE, TRUE, NULL) );
11196 emitcode ("inc", "%s", rname);
11199 /* If there was a partial byte at the end */
11202 mask = (((unsigned char) -1 << rlen) & 0xff);
11204 if (AOP_TYPE (right) == AOP_LIT)
11206 /* Case with partial byte and literal source
11208 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
11209 litval >>= (blen-rlen);
11210 litval &= (~mask) & 0xff;
11211 emitPtrByteGet (rname, p_type, FALSE);
11212 if ((mask|litval)!=0xff)
11213 emitcode ("anl","a,#!constbyte", mask);
11215 emitcode ("orl","a,#!constbyte", litval);
11220 /* Case with partial byte and arbitrary source
11222 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11223 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
11225 pushedB = pushB ();
11226 /* transfer A to B and get next byte */
11227 emitPtrByteGet (rname, p_type, TRUE);
11229 emitcode ("anl", "a,#!constbyte", mask);
11230 emitcode ("orl", "a,b");
11231 if (p_type == GPOINTER)
11232 emitcode ("pop", "b");
11236 emitPtrByteSet (rname, p_type, "a");
11241 /*-----------------------------------------------------------------*/
11242 /* genDataPointerSet - remat pointer to data space */
11243 /*-----------------------------------------------------------------*/
11245 genDataPointerSet (operand * right,
11249 int size, offset = 0;
11250 char *l, buffer[256];
11252 D (emitcode (";", "genDataPointerSet"));
11254 aopOp (right, ic, FALSE, FALSE);
11256 l = aopGet (result, 0, FALSE, TRUE, NULL);
11257 size = AOP_SIZE (right);
11261 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l + 1, offset);
11263 SNPRINTF (buffer, sizeof(buffer), "%s", l + 1);
11264 emitcode ("mov", "%s,%s", buffer,
11265 aopGet (right, offset++, FALSE, FALSE, NULL));
11268 freeAsmop (result, NULL, ic, TRUE);
11269 freeAsmop (right, NULL, ic, TRUE);
11272 /*-----------------------------------------------------------------*/
11273 /* genNearPointerSet - emitcode for near pointer put */
11274 /*-----------------------------------------------------------------*/
11276 genNearPointerSet (operand * right,
11283 sym_link *retype, *letype;
11284 sym_link *ptype = operandType (result);
11286 D (emitcode (";", "genNearPointerSet"));
11288 retype = getSpec (operandType (right));
11289 letype = getSpec (ptype);
11291 aopOp (result, ic, FALSE, FALSE);
11293 /* if the result is rematerializable &
11294 in data space & not a bit variable */
11295 if (AOP_TYPE (result) == AOP_IMMD &&
11296 DCL_TYPE (ptype) == POINTER &&
11297 !IS_BITVAR (retype) &&
11298 !IS_BITVAR (letype))
11300 genDataPointerSet (right, result, ic);
11304 /* if the value is already in a pointer register
11305 then don't need anything more */
11306 if (!AOP_INPREG (AOP (result)))
11308 /* otherwise get a free pointer register */
11311 aop = newAsmop (0);
11312 preg = getFreePtr (ic, &aop, FALSE);
11313 emitcode ("mov", "%s,%s",
11315 aopGet (result, 0, FALSE, TRUE, NULL));
11316 rname = preg->name;
11320 rname = aopGet (result, 0, FALSE, FALSE, NULL);
11323 aopOp (right, ic, FALSE, FALSE);
11325 /* if bitfield then unpack the bits */
11326 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11327 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
11330 /* we can just get the values */
11331 int size = AOP_SIZE (right);
11336 l = aopGet (right, offset, FALSE, TRUE, NULL);
11337 if ((*l == '@') || (strcmp (l, "acc") == 0))
11340 emitcode ("mov", "@%s,a", rname);
11343 emitcode ("mov", "@%s,%s", rname, l);
11345 emitcode ("inc", "%s", rname);
11350 /* now some housekeeping stuff */
11351 if (aop) /* we had to allocate for this iCode */
11354 aopPut (result, rname, 0);
11355 freeAsmop (NULL, aop, ic, TRUE);
11359 /* we did not allocate which means left
11360 already in a pointer register, then
11361 if size > 0 && this could be used again
11362 we have to point it back to where it
11364 if (AOP_SIZE (right) > 1 &&
11365 !OP_SYMBOL (result)->remat &&
11366 (OP_SYMBOL (result)->liveTo > ic->seq ||
11370 int size = AOP_SIZE (right) - 1;
11372 emitcode ("dec", "%s", rname);
11377 if (pi) pi->generated = 1;
11378 freeAsmop (result, NULL, ic, TRUE);
11379 freeAsmop (right, NULL, ic, TRUE);
11382 /*-----------------------------------------------------------------*/
11383 /* genPagedPointerSet - emitcode for Paged pointer put */
11384 /*-----------------------------------------------------------------*/
11386 genPagedPointerSet (operand * right,
11393 sym_link *retype, *letype;
11395 D (emitcode (";", "genPagedPointerSet"));
11397 retype = getSpec (operandType (right));
11398 letype = getSpec (operandType (result));
11400 aopOp (result, ic, FALSE, FALSE);
11402 /* if the value is already in a pointer register
11403 then don't need anything more */
11404 if (!AOP_INPREG (AOP (result)))
11406 /* otherwise get a free pointer register */
11409 aop = newAsmop (0);
11410 preg = getFreePtr (ic, &aop, FALSE);
11411 emitcode ("mov", "%s,%s",
11413 aopGet (result, 0, FALSE, TRUE, NULL));
11414 rname = preg->name;
11417 rname = aopGet (result, 0, FALSE, FALSE, NULL);
11419 aopOp (right, ic, FALSE, FALSE);
11421 /* if bitfield then unpack the bits */
11422 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11423 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
11426 /* we have can just get the values */
11427 int size = AOP_SIZE (right);
11432 l = aopGet (right, offset, FALSE, TRUE, NULL);
11434 emitcode ("movx", "@%s,a", rname);
11437 emitcode ("inc", "%s", rname);
11443 /* now some housekeeping stuff */
11447 aopPut (result, rname, 0);
11448 /* we had to allocate for this iCode */
11449 freeAsmop (NULL, aop, ic, TRUE);
11453 /* we did not allocate which means left
11454 already in a pointer register, then
11455 if size > 0 && this could be used again
11456 we have to point it back to where it
11458 if (AOP_SIZE (right) > 1 &&
11459 !OP_SYMBOL (result)->remat &&
11460 (OP_SYMBOL (result)->liveTo > ic->seq ||
11464 int size = AOP_SIZE (right) - 1;
11466 emitcode ("dec", "%s", rname);
11471 if (pi) pi->generated = 1;
11472 freeAsmop (result, NULL, ic, TRUE);
11473 freeAsmop (right, NULL, ic, TRUE);
11476 /*-----------------------------------------------------------------*/
11477 /* genFarPointerSet - set value from far space */
11478 /*-----------------------------------------------------------------*/
11480 genFarPointerSet (operand * right,
11481 operand * result, iCode * ic, iCode *pi)
11483 int size, offset, dopi=1;
11484 sym_link *retype = getSpec (operandType (right));
11485 sym_link *letype = getSpec (operandType (result));
11487 aopOp (result, ic, FALSE, FALSE);
11489 /* if the operand is already in dptr
11490 then we do nothing else we move the value to dptr */
11491 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
11493 /* if this is remateriazable */
11494 if (AOP_TYPE (result) == AOP_IMMD)
11495 emitcode ("mov", "dptr,%s",
11496 aopGet (result, 0, TRUE, FALSE, NULL));
11499 /* we need to get it byte by byte */
11500 _startLazyDPSEvaluation ();
11501 if (AOP_TYPE (result) != AOP_DPTR)
11503 emitcode ("mov", "dpl,%s", aopGet (result, 0, FALSE, FALSE, NULL));
11504 emitcode ("mov", "dph,%s", aopGet (result, 1, FALSE, FALSE, NULL));
11505 if (options.model == MODEL_FLAT24)
11506 emitcode ("mov", "dpx,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11510 /* We need to generate a load to DPTR indirect through DPTR. */
11511 D (emitcode (";", "genFarPointerSet -- indirection special case."););
11513 emitcode ("push", "%s", aopGet (result, 0, FALSE, TRUE, NULL));
11514 emitcode ("push", "%s", aopGet (result, 1, FALSE, TRUE, NULL));
11515 if (options.model == MODEL_FLAT24)
11516 emitcode ("mov", "dpx,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11517 emitcode ("pop", "dph");
11518 emitcode ("pop", "dpl");
11521 _endLazyDPSEvaluation ();
11524 /* so dptr now contains the address */
11525 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
11527 /* if bit then unpack */
11528 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11530 if (AOP_INDPTRn(result)) {
11531 genSetDPTR(AOP(result)->aopu.dptr);
11533 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
11534 if (AOP_INDPTRn(result)) {
11538 size = AOP_SIZE (right);
11540 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
11542 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11544 genSetDPTR(AOP(result)->aopu.dptr);
11545 emitcode ("movx", "@dptr,a");
11546 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
11547 emitcode ("inc", "dptr");
11551 _startLazyDPSEvaluation ();
11553 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11555 if (AOP_INDPTRn(result)) {
11556 genSetDPTR(AOP(result)->aopu.dptr);
11562 emitcode ("movx", "@dptr,a");
11563 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
11564 emitcode ("inc", "dptr");
11566 _endLazyDPSEvaluation ();
11570 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
11571 if (!AOP_INDPTRn(result)) {
11572 _startLazyDPSEvaluation ();
11574 aopPut (result,"dpl",0);
11575 aopPut (result,"dph",1);
11576 if (options.model == MODEL_FLAT24)
11577 aopPut (result,"dpx",2);
11579 _endLazyDPSEvaluation ();
11582 } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
11583 AOP_SIZE(right) > 1 &&
11584 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
11586 size = AOP_SIZE (right) - 1;
11587 if (AOP_INDPTRn(result)) {
11588 genSetDPTR(AOP(result)->aopu.dptr);
11590 while (size--) emitcode ("lcall","__decdptr");
11591 if (AOP_INDPTRn(result)) {
11595 freeAsmop (result, NULL, ic, TRUE);
11596 freeAsmop (right, NULL, ic, TRUE);
11599 /*-----------------------------------------------------------------*/
11600 /* genGenPointerSet - set value from generic pointer space */
11601 /*-----------------------------------------------------------------*/
11603 genGenPointerSet (operand * right,
11604 operand * result, iCode * ic, iCode *pi)
11608 sym_link *retype = getSpec (operandType (right));
11609 sym_link *letype = getSpec (operandType (result));
11611 aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
11613 pushedB = pushB ();
11614 /* if the operand is already in dptr
11615 then we do nothing else we move the value to dptr */
11616 if (AOP_TYPE (result) != AOP_STR)
11618 _startLazyDPSEvaluation ();
11619 /* if this is remateriazable */
11620 if (AOP_TYPE (result) == AOP_IMMD)
11622 emitcode ("mov", "dptr,%s", aopGet (result, 0, TRUE, FALSE, NULL));
11623 if (AOP(result)->aopu.aop_immd.from_cast_remat)
11625 MOVB (aopGet (result, AOP_SIZE(result)-1, FALSE, FALSE, NULL));
11630 "b,%s + 1", aopGet (result, 0, TRUE, FALSE, NULL));
11634 { /* we need to get it byte by byte */
11635 emitcode ("mov", "dpl,%s", aopGet (result, 0, FALSE, FALSE, NULL));
11636 emitcode ("mov", "dph,%s", aopGet (result, 1, FALSE, FALSE, NULL));
11637 if (options.model == MODEL_FLAT24) {
11638 emitcode ("mov", "dpx,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11639 emitcode ("mov", "b,%s", aopGet (result, 3, FALSE, FALSE, NULL));
11641 emitcode ("mov", "b,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11644 _endLazyDPSEvaluation ();
11646 /* so dptr + b now contains the address */
11647 aopOp (right, ic, FALSE, TRUE);
11649 /* if bit then unpack */
11650 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11652 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
11656 size = AOP_SIZE (right);
11659 _startLazyDPSEvaluation ();
11664 // Set two bytes at a time, passed in _AP & A.
11665 // dptr will be incremented ONCE by __gptrputWord.
11667 // Note: any change here must be coordinated
11668 // with the implementation of __gptrputWord
11669 // in device/lib/_gptrput.c
11670 emitcode("mov", "_ap, %s",
11671 aopGet (right, offset++, FALSE, FALSE, NULL));
11672 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11676 emitcode ("lcall", "__gptrputWord");
11681 // Only one byte to put.
11682 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11686 emitcode ("lcall", "__gptrput");
11689 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
11691 emitcode ("inc", "dptr");
11694 _endLazyDPSEvaluation ();
11697 if (pi && AOP_TYPE (result) != AOP_IMMD) {
11698 _startLazyDPSEvaluation ();
11700 aopPut (result, "dpl",0);
11701 aopPut (result, "dph",1);
11702 if (options.model == MODEL_FLAT24) {
11703 aopPut (result, "dpx",2);
11704 aopPut (result, "b",3);
11706 aopPut (result, "b",2);
11708 _endLazyDPSEvaluation ();
11711 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
11712 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
11714 size = AOP_SIZE (right) - 1;
11715 while (size--) emitcode ("lcall","__decdptr");
11719 freeAsmop (result, NULL, ic, TRUE);
11720 freeAsmop (right, NULL, ic, TRUE);
11723 /*-----------------------------------------------------------------*/
11724 /* genPointerSet - stores the value into a pointer location */
11725 /*-----------------------------------------------------------------*/
11727 genPointerSet (iCode * ic, iCode *pi)
11729 operand *right, *result;
11730 sym_link *type, *etype;
11733 D (emitcode (";", "genPointerSet"));
11735 right = IC_RIGHT (ic);
11736 result = IC_RESULT (ic);
11738 /* depending on the type of pointer we need to
11739 move it to the correct pointer register */
11740 type = operandType (result);
11741 etype = getSpec (type);
11742 /* if left is of type of pointer then it is simple */
11743 if (IS_PTR (type) && !IS_FUNC (type->next))
11745 p_type = DCL_TYPE (type);
11749 /* we have to go by the storage class */
11750 p_type = PTR_TYPE (SPEC_OCLS (etype));
11753 /* special case when cast remat */
11754 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
11755 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
11756 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
11757 type = operandType (result);
11758 p_type = DCL_TYPE (type);
11761 /* now that we have the pointer type we assign
11762 the pointer values */
11768 genNearPointerSet (right, result, ic, pi);
11772 genPagedPointerSet (right, result, ic, pi);
11776 genFarPointerSet (right, result, ic, pi);
11780 genGenPointerSet (right, result, ic, pi);
11784 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11785 "genPointerSet: illegal pointer type");
11789 /*-----------------------------------------------------------------*/
11790 /* genIfx - generate code for Ifx statement */
11791 /*-----------------------------------------------------------------*/
11793 genIfx (iCode * ic, iCode * popIc)
11795 operand *cond = IC_COND (ic);
11799 D (emitcode (";", "genIfx"));
11801 aopOp (cond, ic, FALSE, FALSE);
11803 /* get the value into acc */
11804 if (AOP_TYPE (cond) != AOP_CRY)
11811 if (AOP(cond)->aopu.aop_dir)
11812 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
11815 /* the result is now in the accumulator or a directly addressable bit */
11816 freeAsmop (cond, NULL, ic, TRUE);
11818 /* if there was something to be popped then do it */
11822 /* if the condition is a bit variable */
11824 genIfxJump (ic, dup);
11825 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
11826 genIfxJump (ic, SPIL_LOC (cond)->rname);
11827 else if (isbit && !IS_ITEMP (cond))
11828 genIfxJump (ic, OP_SYMBOL (cond)->rname);
11830 genIfxJump (ic, "a");
11835 /*-----------------------------------------------------------------*/
11836 /* genAddrOf - generates code for address of */
11837 /*-----------------------------------------------------------------*/
11839 genAddrOf (iCode * ic)
11841 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
11844 D (emitcode (";", "genAddrOf"));
11846 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11848 /* if the operand is on the stack then we
11849 need to get the stack offset of this
11854 /* if 10 bit stack */
11855 if (options.stack10bit) {
11859 tsprintf(buff, sizeof(buff),
11860 "#!constbyte",(options.stack_loc >> 16) & 0xff);
11861 /* if it has an offset then we need to compute it */
11862 /* emitcode ("subb", "a,#!constbyte", */
11863 /* -((sym->stack < 0) ? */
11864 /* ((short) (sym->stack - _G.nRegsSaved)) : */
11865 /* ((short) sym->stack)) & 0xff); */
11866 /* emitcode ("mov","b,a"); */
11867 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
11868 /* ((short) (sym->stack - _G.nRegsSaved)) : */
11869 /* ((short) sym->stack)) >> 8) & 0xff); */
11871 emitcode ("mov", "a,_bpx");
11872 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
11873 ((char) (sym->stack - _G.nRegsSaved)) :
11874 ((char) sym->stack )) & 0xff);
11875 emitcode ("mov", "b,a");
11876 emitcode ("mov", "a,_bpx+1");
11878 offset = (((sym->stack < 0) ?
11879 ((short) (sym->stack - _G.nRegsSaved)) :
11880 ((short) sym->stack )) >> 8) & 0xff;
11882 emitcode ("addc","a,#!constbyte", offset);
11884 aopPut (IC_RESULT (ic), "b", 0);
11885 aopPut (IC_RESULT (ic), "a", 1);
11886 aopPut (IC_RESULT (ic), buff, 2);
11888 /* we can just move _bp */
11889 aopPut (IC_RESULT (ic), "_bpx", 0);
11890 aopPut (IC_RESULT (ic), "_bpx+1", 1);
11891 aopPut (IC_RESULT (ic), buff, 2);
11894 /* if it has an offset then we need to compute it */
11897 emitcode ("mov", "a,_bp");
11898 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
11899 aopPut (IC_RESULT (ic), "a", 0);
11903 /* we can just move _bp */
11904 aopPut (IC_RESULT (ic), "_bp", 0);
11906 /* fill the result with zero */
11907 size = AOP_SIZE (IC_RESULT (ic)) - 1;
11910 if (options.stack10bit && size < (FPTRSIZE - 1)) {
11912 "*** warning: pointer to stack var truncated.\n");
11918 aopPut (IC_RESULT (ic), zero, offset++);
11924 /* object not on stack then we need the name */
11925 size = AOP_SIZE (IC_RESULT (ic));
11930 char s[SDCC_NAME_MAX];
11934 tsprintf(s, sizeof(s), "#!his",sym->rname);
11937 tsprintf(s, sizeof(s), "#!hihis",sym->rname);
11940 tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
11942 default: /* should not need this (just in case) */
11943 SNPRINTF (s, sizeof(s), "#(%s >> %d)",
11950 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11953 aopPut (IC_RESULT (ic), s, offset++);
11957 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11961 #if 0 // obsolete, and buggy for != xdata
11962 /*-----------------------------------------------------------------*/
11963 /* genArrayInit - generates code for address of */
11964 /*-----------------------------------------------------------------*/
11966 genArrayInit (iCode * ic)
11968 literalList *iLoop;
11970 int elementSize = 0, eIndex;
11971 unsigned val, lastVal;
11973 operand *left=IC_LEFT(ic);
11975 D (emitcode (";", "genArrayInit"));
11977 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
11979 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
11981 // Load immediate value into DPTR.
11982 emitcode("mov", "dptr, %s",
11983 aopGet (IC_LEFT(ic), 0, TRUE, FALSE, NULL));
11985 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
11988 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11989 "Unexpected operand to genArrayInit.\n");
11992 // a regression because of SDCCcse.c:1.52
11993 emitcode ("mov", "dpl,%s", aopGet (left, 0, FALSE, FALSE, NULL));
11994 emitcode ("mov", "dph,%s", aopGet (left, 1, FALSE, FALSE, NULL));
11995 if (options.model == MODEL_FLAT24)
11996 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
12000 type = operandType(IC_LEFT(ic));
12002 if (type && type->next)
12004 elementSize = getSize(type->next);
12008 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12009 "can't determine element size in genArrayInit.\n");
12013 iLoop = IC_ARRAYILIST(ic);
12018 bool firstpass = TRUE;
12020 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
12021 iLoop->count, (int)iLoop->literalValue, elementSize);
12027 symbol *tlbl = NULL;
12029 count = ix > 256 ? 256 : ix;
12033 tlbl = newiTempLabel (NULL);
12034 if (firstpass || (count & 0xff))
12036 emitcode("mov", "b, #!constbyte", count & 0xff);
12044 for (eIndex = 0; eIndex < elementSize; eIndex++)
12046 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
12047 if (val != lastVal)
12049 emitcode("mov", "a, #!constbyte", val);
12053 emitcode("movx", "@dptr, a");
12054 emitcode("inc", "dptr");
12059 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
12065 iLoop = iLoop->next;
12068 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
12072 /*-----------------------------------------------------------------*/
12073 /* genFarFarAssign - assignment when both are in far space */
12074 /*-----------------------------------------------------------------*/
12076 genFarFarAssign (operand * result, operand * right, iCode * ic)
12078 int size = AOP_SIZE (right);
12080 symbol *rSym = NULL;
12084 /* quick & easy case. */
12085 D (emitcode(";","genFarFarAssign (1 byte case)"));
12086 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
12087 freeAsmop (right, NULL, ic, FALSE);
12088 /* now assign DPTR to result */
12090 aopOp(result, ic, FALSE, FALSE);
12092 aopPut (result, "a", 0);
12093 freeAsmop(result, NULL, ic, FALSE);
12097 /* See if we've got an underlying symbol to abuse. */
12098 if (IS_SYMOP(result) && OP_SYMBOL(result))
12100 if (IS_TRUE_SYMOP(result))
12102 rSym = OP_SYMBOL(result);
12104 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
12106 rSym = OP_SYMBOL(result)->usl.spillLoc;
12110 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
12112 /* We can use the '390 auto-toggle feature to good effect here. */
12114 D (emitcode(";", "genFarFarAssign (390 auto-toggle fun)"));
12115 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12116 emitcode ("mov", "dptr,#%s", rSym->rname);
12117 /* DP2 = result, DP1 = right, DP1 is current. */
12120 emitcode("movx", "a,@dptr");
12121 emitcode("movx", "@dptr,a");
12124 emitcode("inc", "dptr");
12125 emitcode("inc", "dptr");
12128 emitcode("mov", "dps,#0");
12129 freeAsmop (right, NULL, ic, FALSE);
12131 some alternative code for processors without auto-toggle
12132 no time to test now, so later well put in...kpb
12133 D (emitcode(";", "genFarFarAssign (dual-dptr fun)"));
12134 emitcode("mov", "dps,#1"); /* Select DPTR2. */
12135 emitcode ("mov", "dptr,#%s", rSym->rname);
12136 /* DP2 = result, DP1 = right, DP1 is current. */
12140 emitcode("movx", "a,@dptr");
12142 emitcode("inc", "dptr");
12143 emitcode("inc", "dps");
12144 emitcode("movx", "@dptr,a");
12146 emitcode("inc", "dptr");
12147 emitcode("inc", "dps");
12149 emitcode("mov", "dps,#0");
12150 freeAsmop (right, NULL, ic, FALSE);
12155 D (emitcode (";", "genFarFarAssign"));
12156 aopOp (result, ic, TRUE, TRUE);
12158 _startLazyDPSEvaluation ();
12163 aopGet (right, offset, FALSE, FALSE, NULL), offset);
12166 _endLazyDPSEvaluation ();
12167 freeAsmop (result, NULL, ic, FALSE);
12168 freeAsmop (right, NULL, ic, FALSE);
12172 /*-----------------------------------------------------------------*/
12173 /* genAssign - generate code for assignment */
12174 /*-----------------------------------------------------------------*/
12176 genAssign (iCode * ic)
12178 operand *result, *right;
12180 unsigned long lit = 0L;
12182 D (emitcode (";", "genAssign"));
12184 result = IC_RESULT (ic);
12185 right = IC_RIGHT (ic);
12187 /* if they are the same */
12188 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
12191 aopOp (right, ic, FALSE, FALSE);
12193 emitcode (";", "genAssign: resultIsFar = %s",
12194 isOperandInFarSpace (result) ?
12197 /* special case both in far space */
12198 if ((AOP_TYPE (right) == AOP_DPTR ||
12199 AOP_TYPE (right) == AOP_DPTR2) &&
12200 /* IS_TRUE_SYMOP(result) && */
12201 isOperandInFarSpace (result))
12203 genFarFarAssign (result, right, ic);
12207 aopOp (result, ic, TRUE, FALSE);
12209 /* if they are the same registers */
12210 if (sameRegs (AOP (right), AOP (result)))
12213 /* if the result is a bit */
12214 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
12216 /* if the right size is a literal then
12217 we know what the value is */
12218 if (AOP_TYPE (right) == AOP_LIT)
12220 if (((int) operandLitValue (right)))
12221 aopPut (result, one, 0);
12223 aopPut (result, zero, 0);
12227 /* the right is also a bit variable */
12228 if (AOP_TYPE (right) == AOP_CRY)
12230 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
12231 aopPut (result, "c", 0);
12235 /* we need to or */
12237 aopPut (result, "a", 0);
12241 /* bit variables done */
12243 size = AOP_SIZE (result);
12245 if (AOP_TYPE (right) == AOP_LIT)
12246 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
12249 (AOP_TYPE (result) != AOP_REG) &&
12250 (AOP_TYPE (right) == AOP_LIT) &&
12251 !IS_FLOAT (operandType (right)))
12253 _startLazyDPSEvaluation ();
12254 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
12257 aopGet (right, offset, FALSE, FALSE, NULL),
12262 /* And now fill the rest with zeros. */
12265 emitcode ("clr", "a");
12269 aopPut (result, "a", offset++);
12271 _endLazyDPSEvaluation ();
12275 _startLazyDPSEvaluation ();
12279 aopGet (right, offset, FALSE, FALSE, NULL),
12283 _endLazyDPSEvaluation ();
12287 freeAsmop (result, NULL, ic, TRUE);
12288 freeAsmop (right, NULL, ic, TRUE);
12291 /*-----------------------------------------------------------------*/
12292 /* genJumpTab - generates code for jump table */
12293 /*-----------------------------------------------------------------*/
12295 genJumpTab (iCode * ic)
12300 D (emitcode (";", "genJumpTab"));
12302 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
12303 /* get the condition into accumulator */
12304 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE, NULL);
12306 /* multiply by four! */
12307 emitcode ("add", "a,acc");
12308 emitcode ("add", "a,acc");
12309 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
12311 jtab = newiTempLabel (NULL);
12312 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
12313 emitcode ("jmp", "@a+dptr");
12315 /* now generate the jump labels */
12316 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
12317 jtab = setNextItem (IC_JTLABELS (ic)))
12318 emitcode ("ljmp", "!tlabel", jtab->key + 100);
12322 /*-----------------------------------------------------------------*/
12323 /* genCast - gen code for casting */
12324 /*-----------------------------------------------------------------*/
12326 genCast (iCode * ic)
12328 operand *result = IC_RESULT (ic);
12329 sym_link *ctype = operandType (IC_LEFT (ic));
12330 sym_link *rtype = operandType (IC_RIGHT (ic));
12331 operand *right = IC_RIGHT (ic);
12334 D (emitcode (";", "genCast"));
12336 /* if they are equivalent then do nothing */
12337 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
12340 aopOp (right, ic, FALSE, AOP_IS_STR (result));
12341 aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR));
12343 /* if the result is a bit (and not a bitfield) */
12344 if (IS_BIT (OP_SYMBOL (result)->type))
12346 /* if the right size is a literal then
12347 we know what the value is */
12348 if (AOP_TYPE (right) == AOP_LIT)
12350 if (((int) operandLitValue (right)))
12351 aopPut (result, one, 0);
12353 aopPut (result, zero, 0);
12358 /* the right is also a bit variable */
12359 if (AOP_TYPE (right) == AOP_CRY)
12361 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
12362 aopPut (result, "c", 0);
12366 /* we need to or */
12368 aopPut (result, "a", 0);
12372 /* if they are the same size : or less */
12373 if (AOP_SIZE (result) <= AOP_SIZE (right))
12376 /* if they are in the same place */
12377 if (sameRegs (AOP (right), AOP (result)))
12380 /* if they in different places then copy */
12381 size = AOP_SIZE (result);
12383 _startLazyDPSEvaluation ();
12387 aopGet (right, offset, FALSE, FALSE, NULL),
12391 _endLazyDPSEvaluation ();
12395 /* if the result is of type pointer */
12396 if (IS_PTR (ctype))
12400 sym_link *type = operandType (right);
12402 /* pointer to generic pointer */
12403 if (IS_GENPTR (ctype))
12407 p_type = DCL_TYPE (type);
12411 #if OLD_CAST_BEHAVIOR
12412 /* KV: we are converting a non-pointer type to
12413 * a generic pointer. This (ifdef'd out) code
12414 * says that the resulting generic pointer
12415 * should have the same class as the storage
12416 * location of the non-pointer variable.
12418 * For example, converting an int (which happens
12419 * to be stored in DATA space) to a pointer results
12420 * in a DATA generic pointer; if the original int
12421 * in XDATA space, so will be the resulting pointer.
12423 * I don't like that behavior, and thus this change:
12424 * all such conversions will be forced to XDATA and
12425 * throw a warning. If you want some non-XDATA
12426 * type, or you want to suppress the warning, you
12427 * must go through an intermediate cast, like so:
12429 * char _generic *gp = (char _xdata *)(intVar);
12431 sym_link *etype = getSpec (type);
12433 /* we have to go by the storage class */
12434 if (SPEC_OCLS (etype) != generic)
12436 p_type = PTR_TYPE (SPEC_OCLS (etype));
12441 /* Converting unknown class (i.e. register variable)
12442 * to generic pointer. This is not good, but
12443 * we'll make a guess (and throw a warning).
12446 werror (W_INT_TO_GEN_PTR_CAST);
12450 /* the first two bytes are known */
12451 size = GPTRSIZE - 1;
12453 _startLazyDPSEvaluation ();
12457 aopGet (right, offset, FALSE, FALSE, NULL),
12461 _endLazyDPSEvaluation ();
12463 /* the last byte depending on type */
12465 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
12470 // pointerTypeToGPByte will have bitched.
12474 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%x", gpVal);
12475 aopPut (result, gpValStr, GPTRSIZE - 1);
12480 /* just copy the pointers */
12481 size = AOP_SIZE (result);
12483 _startLazyDPSEvaluation ();
12487 aopGet (right, offset, FALSE, FALSE, NULL),
12491 _endLazyDPSEvaluation ();
12495 /* so we now know that the size of destination is greater
12496 than the size of the source */
12497 /* we move to result for the size of source */
12498 size = AOP_SIZE (right);
12500 _startLazyDPSEvaluation ();
12504 aopGet (right, offset, FALSE, FALSE, NULL),
12508 _endLazyDPSEvaluation ();
12510 /* now depending on the sign of the source && destination */
12511 size = AOP_SIZE (result) - AOP_SIZE (right);
12512 /* if unsigned or not an integral type */
12513 /* also, if the source is a bit, we don't need to sign extend, because
12514 * it can't possibly have set the sign bit.
12516 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
12520 aopPut (result, zero, offset++);
12525 /* we need to extend the sign :{ */
12526 MOVA (aopGet (right, AOP_SIZE (right) - 1,
12527 FALSE, FALSE, NULL));
12528 emitcode ("rlc", "a");
12529 emitcode ("subb", "a,acc");
12531 aopPut (result, "a", offset++);
12534 /* we are done hurray !!!! */
12537 freeAsmop (right, NULL, ic, TRUE);
12538 freeAsmop (result, NULL, ic, TRUE);
12542 /*-----------------------------------------------------------------*/
12543 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
12544 /*-----------------------------------------------------------------*/
12545 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
12547 operand *from , *to , *count;
12552 /* we know it has to be 3 parameters */
12553 assert (nparms == 3);
12555 rsave = newBitVect(16);
12556 /* save DPTR if it needs to be saved */
12557 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12558 if (bitVectBitValue(ic->rMask,i))
12559 rsave = bitVectSetBit(rsave,i);
12561 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12562 ds390_rUmaskForOp (IC_RESULT(ic))));
12569 aopOp (from, ic->next, FALSE, FALSE);
12571 /* get from into DPTR1 */
12572 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12573 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12574 if (options.model == MODEL_FLAT24) {
12575 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12578 freeAsmop (from, NULL, ic, FALSE);
12579 aopOp (to, ic, FALSE, FALSE);
12580 /* get "to" into DPTR */
12581 /* if the operand is already in dptr
12582 then we do nothing else we move the value to dptr */
12583 if (AOP_TYPE (to) != AOP_STR) {
12584 /* if already in DPTR then we need to push */
12585 if (AOP_TYPE(to) == AOP_DPTR) {
12586 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12587 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12588 if (options.model == MODEL_FLAT24)
12589 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12590 emitcode ("pop", "dph");
12591 emitcode ("pop", "dpl");
12593 _startLazyDPSEvaluation ();
12594 /* if this is remateriazable */
12595 if (AOP_TYPE (to) == AOP_IMMD) {
12596 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12597 } else { /* we need to get it byte by byte */
12598 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12599 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12600 if (options.model == MODEL_FLAT24) {
12601 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12604 _endLazyDPSEvaluation ();
12607 freeAsmop (to, NULL, ic, FALSE);
12608 _G.dptrInUse = _G.dptr1InUse = 1;
12609 aopOp (count, ic->next->next, FALSE,FALSE);
12610 lbl =newiTempLabel(NULL);
12612 /* now for the actual copy */
12613 if (AOP_TYPE(count) == AOP_LIT &&
12614 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12615 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12617 emitcode ("lcall","__bi_memcpyc2x_s");
12619 emitcode ("lcall","__bi_memcpyx2x_s");
12621 freeAsmop (count, NULL, ic, FALSE);
12623 symbol *lbl1 = newiTempLabel(NULL);
12625 emitcode (";"," Auto increment but no djnz");
12626 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
12627 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
12628 freeAsmop (count, NULL, ic, FALSE);
12629 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12630 emitcode ("","!tlabeldef",lbl->key+100);
12632 emitcode ("clr","a");
12633 emitcode ("movc", "a,@a+dptr");
12635 emitcode ("movx", "a,@dptr");
12636 emitcode ("movx", "@dptr,a");
12637 emitcode ("inc", "dptr");
12638 emitcode ("inc", "dptr");
12639 emitcode ("mov","a,b");
12640 emitcode ("orl","a,_ap");
12641 emitcode ("jz","!tlabel",lbl1->key+100);
12642 emitcode ("mov","a,_ap");
12643 emitcode ("add","a,#!constbyte",0xFF);
12644 emitcode ("mov","_ap,a");
12645 emitcode ("mov","a,b");
12646 emitcode ("addc","a,#!constbyte",0xFF);
12647 emitcode ("mov","b,a");
12648 emitcode ("sjmp","!tlabel",lbl->key+100);
12649 emitcode ("","!tlabeldef",lbl1->key+100);
12651 emitcode ("mov", "dps,#0");
12652 _G.dptrInUse = _G.dptr1InUse = 0;
12653 unsavermask(rsave);
12657 /*-----------------------------------------------------------------*/
12658 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
12659 /*-----------------------------------------------------------------*/
12660 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
12662 operand *from , *to , *count;
12667 /* we know it has to be 3 parameters */
12668 assert (nparms == 3);
12670 rsave = newBitVect(16);
12671 /* save DPTR if it needs to be saved */
12672 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12673 if (bitVectBitValue(ic->rMask,i))
12674 rsave = bitVectSetBit(rsave,i);
12676 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12677 ds390_rUmaskForOp (IC_RESULT(ic))));
12684 aopOp (from, ic->next, FALSE, FALSE);
12686 /* get from into DPTR1 */
12687 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12688 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12689 if (options.model == MODEL_FLAT24) {
12690 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12693 freeAsmop (from, NULL, ic, FALSE);
12694 aopOp (to, ic, FALSE, FALSE);
12695 /* get "to" into DPTR */
12696 /* if the operand is already in dptr
12697 then we do nothing else we move the value to dptr */
12698 if (AOP_TYPE (to) != AOP_STR) {
12699 /* if already in DPTR then we need to push */
12700 if (AOP_TYPE(to) == AOP_DPTR) {
12701 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12702 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12703 if (options.model == MODEL_FLAT24)
12704 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12705 emitcode ("pop", "dph");
12706 emitcode ("pop", "dpl");
12708 _startLazyDPSEvaluation ();
12709 /* if this is remateriazable */
12710 if (AOP_TYPE (to) == AOP_IMMD) {
12711 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12712 } else { /* we need to get it byte by byte */
12713 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12714 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12715 if (options.model == MODEL_FLAT24) {
12716 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12719 _endLazyDPSEvaluation ();
12722 freeAsmop (to, NULL, ic, FALSE);
12723 _G.dptrInUse = _G.dptr1InUse = 1;
12724 aopOp (count, ic->next->next, FALSE,FALSE);
12725 lbl =newiTempLabel(NULL);
12726 lbl2 =newiTempLabel(NULL);
12728 /* now for the actual compare */
12729 if (AOP_TYPE(count) == AOP_LIT &&
12730 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12731 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12733 emitcode("lcall","__bi_memcmpc2x_s");
12735 emitcode("lcall","__bi_memcmpx2x_s");
12736 freeAsmop (count, NULL, ic, FALSE);
12737 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12738 aopPut(IC_RESULT(ic),"a",0);
12739 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12741 symbol *lbl1 = newiTempLabel(NULL);
12743 emitcode("push","ar0");
12744 emitcode (";"," Auto increment but no djnz");
12745 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
12746 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
12747 freeAsmop (count, NULL, ic, FALSE);
12748 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12749 emitcode ("","!tlabeldef",lbl->key+100);
12751 emitcode ("clr","a");
12752 emitcode ("movc", "a,@a+dptr");
12754 emitcode ("movx", "a,@dptr");
12755 emitcode ("mov","r0,a");
12756 emitcode ("movx", "a,@dptr");
12757 emitcode ("clr","c");
12758 emitcode ("subb","a,r0");
12759 emitcode ("jnz","!tlabel",lbl2->key+100);
12760 emitcode ("inc", "dptr");
12761 emitcode ("inc", "dptr");
12762 emitcode ("mov","a,b");
12763 emitcode ("orl","a,_ap");
12764 emitcode ("jz","!tlabel",lbl1->key+100);
12765 emitcode ("mov","a,_ap");
12766 emitcode ("add","a,#!constbyte",0xFF);
12767 emitcode ("mov","_ap,a");
12768 emitcode ("mov","a,b");
12769 emitcode ("addc","a,#!constbyte",0xFF);
12770 emitcode ("mov","b,a");
12771 emitcode ("sjmp","!tlabel",lbl->key+100);
12772 emitcode ("","!tlabeldef",lbl1->key+100);
12773 emitcode ("clr","a");
12774 emitcode ("","!tlabeldef",lbl2->key+100);
12775 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12776 aopPut(IC_RESULT(ic),"a",0);
12777 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12778 emitcode("pop","ar0");
12779 emitcode ("mov", "dps,#0");
12781 _G.dptrInUse = _G.dptr1InUse = 0;
12782 unsavermask(rsave);
12786 /*-----------------------------------------------------------------*/
12787 /* genInp - gen code for __builtin_inp read data from a mem mapped */
12788 /* port, first parameter output area second parameter pointer to */
12789 /* port third parameter count */
12790 /*-----------------------------------------------------------------*/
12791 static void genInp( iCode *ic, int nparms, operand **parms)
12793 operand *from , *to , *count;
12798 /* we know it has to be 3 parameters */
12799 assert (nparms == 3);
12801 rsave = newBitVect(16);
12802 /* save DPTR if it needs to be saved */
12803 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12804 if (bitVectBitValue(ic->rMask,i))
12805 rsave = bitVectSetBit(rsave,i);
12807 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12808 ds390_rUmaskForOp (IC_RESULT(ic))));
12815 aopOp (from, ic->next, FALSE, FALSE);
12817 /* get from into DPTR1 */
12818 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12819 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12820 if (options.model == MODEL_FLAT24) {
12821 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12824 freeAsmop (from, NULL, ic, FALSE);
12825 aopOp (to, ic, FALSE, FALSE);
12826 /* get "to" into DPTR */
12827 /* if the operand is already in dptr
12828 then we do nothing else we move the value to dptr */
12829 if (AOP_TYPE (to) != AOP_STR) {
12830 /* if already in DPTR then we need to push */
12831 if (AOP_TYPE(to) == AOP_DPTR) {
12832 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12833 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12834 if (options.model == MODEL_FLAT24)
12835 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12836 emitcode ("pop", "dph");
12837 emitcode ("pop", "dpl");
12839 _startLazyDPSEvaluation ();
12840 /* if this is remateriazable */
12841 if (AOP_TYPE (to) == AOP_IMMD) {
12842 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12843 } else { /* we need to get it byte by byte */
12844 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12845 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12846 if (options.model == MODEL_FLAT24) {
12847 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12850 _endLazyDPSEvaluation ();
12853 freeAsmop (to, NULL, ic, FALSE);
12855 _G.dptrInUse = _G.dptr1InUse = 1;
12856 aopOp (count, ic->next->next, FALSE,FALSE);
12857 lbl =newiTempLabel(NULL);
12859 /* now for the actual copy */
12860 if (AOP_TYPE(count) == AOP_LIT &&
12861 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12862 emitcode (";","OH JOY auto increment with djnz (very fast)");
12863 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
12864 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12865 freeAsmop (count, NULL, ic, FALSE);
12866 emitcode ("","!tlabeldef",lbl->key+100);
12867 emitcode ("movx", "a,@dptr"); /* read data from port */
12868 emitcode ("dec","dps"); /* switch to DPTR */
12869 emitcode ("movx", "@dptr,a"); /* save into location */
12870 emitcode ("inc", "dptr"); /* point to next area */
12871 emitcode ("inc","dps"); /* switch to DPTR2 */
12872 emitcode ("djnz","b,!tlabel",lbl->key+100);
12874 symbol *lbl1 = newiTempLabel(NULL);
12876 emitcode (";"," Auto increment but no djnz");
12877 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
12878 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
12879 freeAsmop (count, NULL, ic, FALSE);
12880 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
12881 emitcode ("","!tlabeldef",lbl->key+100);
12882 emitcode ("movx", "a,@dptr");
12883 emitcode ("dec","dps"); /* switch to DPTR */
12884 emitcode ("movx", "@dptr,a");
12885 emitcode ("inc", "dptr");
12886 emitcode ("inc","dps"); /* switch to DPTR2 */
12887 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
12888 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
12889 emitcode ("mov","a,b");
12890 emitcode ("orl","a,_ap");
12891 emitcode ("jz","!tlabel",lbl1->key+100);
12892 emitcode ("mov","a,_ap");
12893 emitcode ("add","a,#!constbyte",0xFF);
12894 emitcode ("mov","_ap,a");
12895 emitcode ("mov","a,b");
12896 emitcode ("addc","a,#!constbyte",0xFF);
12897 emitcode ("mov","b,a");
12898 emitcode ("sjmp","!tlabel",lbl->key+100);
12899 emitcode ("","!tlabeldef",lbl1->key+100);
12901 emitcode ("mov", "dps,#0");
12902 _G.dptrInUse = _G.dptr1InUse = 0;
12903 unsavermask(rsave);
12907 /*-----------------------------------------------------------------*/
12908 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
12909 /* port, first parameter output area second parameter pointer to */
12910 /* port third parameter count */
12911 /*-----------------------------------------------------------------*/
12912 static void genOutp( iCode *ic, int nparms, operand **parms)
12914 operand *from , *to , *count;
12919 /* we know it has to be 3 parameters */
12920 assert (nparms == 3);
12922 rsave = newBitVect(16);
12923 /* save DPTR if it needs to be saved */
12924 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12925 if (bitVectBitValue(ic->rMask,i))
12926 rsave = bitVectSetBit(rsave,i);
12928 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12929 ds390_rUmaskForOp (IC_RESULT(ic))));
12936 aopOp (from, ic->next, FALSE, FALSE);
12938 /* get from into DPTR1 */
12939 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12940 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12941 if (options.model == MODEL_FLAT24) {
12942 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12945 freeAsmop (from, NULL, ic, FALSE);
12946 aopOp (to, ic, FALSE, FALSE);
12947 /* get "to" into DPTR */
12948 /* if the operand is already in dptr
12949 then we do nothing else we move the value to dptr */
12950 if (AOP_TYPE (to) != AOP_STR) {
12951 /* if already in DPTR then we need to push */
12952 if (AOP_TYPE(to) == AOP_DPTR) {
12953 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12954 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12955 if (options.model == MODEL_FLAT24)
12956 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12957 emitcode ("pop", "dph");
12958 emitcode ("pop", "dpl");
12960 _startLazyDPSEvaluation ();
12961 /* if this is remateriazable */
12962 if (AOP_TYPE (to) == AOP_IMMD) {
12963 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12964 } else { /* we need to get it byte by byte */
12965 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12966 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12967 if (options.model == MODEL_FLAT24) {
12968 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12971 _endLazyDPSEvaluation ();
12974 freeAsmop (to, NULL, ic, FALSE);
12976 _G.dptrInUse = _G.dptr1InUse = 1;
12977 aopOp (count, ic->next->next, FALSE,FALSE);
12978 lbl =newiTempLabel(NULL);
12980 /* now for the actual copy */
12981 if (AOP_TYPE(count) == AOP_LIT &&
12982 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12983 emitcode (";","OH JOY auto increment with djnz (very fast)");
12984 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
12985 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12986 emitcode ("","!tlabeldef",lbl->key+100);
12987 emitcode ("movx", "a,@dptr"); /* read data from port */
12988 emitcode ("inc","dps"); /* switch to DPTR2 */
12989 emitcode ("movx", "@dptr,a"); /* save into location */
12990 emitcode ("inc", "dptr"); /* point to next area */
12991 emitcode ("dec","dps"); /* switch to DPTR */
12992 emitcode ("djnz","b,!tlabel",lbl->key+100);
12993 freeAsmop (count, NULL, ic, FALSE);
12995 symbol *lbl1 = newiTempLabel(NULL);
12997 emitcode (";"," Auto increment but no djnz");
12998 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
12999 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
13000 freeAsmop (count, NULL, ic, FALSE);
13001 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
13002 emitcode ("","!tlabeldef",lbl->key+100);
13003 emitcode ("movx", "a,@dptr");
13004 emitcode ("inc", "dptr");
13005 emitcode ("inc","dps"); /* switch to DPTR2 */
13006 emitcode ("movx", "@dptr,a");
13007 emitcode ("dec","dps"); /* switch to DPTR */
13008 emitcode ("mov","a,b");
13009 emitcode ("orl","a,_ap");
13010 emitcode ("jz","!tlabel",lbl1->key+100);
13011 emitcode ("mov","a,_ap");
13012 emitcode ("add","a,#!constbyte",0xFF);
13013 emitcode ("mov","_ap,a");
13014 emitcode ("mov","a,b");
13015 emitcode ("addc","a,#!constbyte",0xFF);
13016 emitcode ("mov","b,a");
13017 emitcode ("sjmp","!tlabel",lbl->key+100);
13018 emitcode ("","!tlabeldef",lbl1->key+100);
13020 emitcode ("mov", "dps,#0");
13021 _G.dptrInUse = _G.dptr1InUse = 0;
13022 unsavermask(rsave);
13026 /*-----------------------------------------------------------------*/
13027 /* genSwapW - swap lower & high order bytes */
13028 /*-----------------------------------------------------------------*/
13029 static void genSwapW(iCode *ic, int nparms, operand **parms)
13033 assert (nparms==1);
13036 dest=IC_RESULT(ic);
13038 assert(getSize(operandType(src))==2);
13040 aopOp (src, ic, FALSE, FALSE);
13041 emitcode ("mov","a,%s",aopGet(src,0,FALSE,FALSE,NULL));
13043 MOVB(aopGet(src,1,FALSE,FALSE,"b"));
13045 freeAsmop (src, NULL, ic, FALSE);
13047 aopOp (dest,ic, FALSE, FALSE);
13048 aopPut(dest,"b",0);
13049 aopPut(dest,"a",1);
13050 freeAsmop (dest, NULL, ic, FALSE);
13053 /*-----------------------------------------------------------------*/
13054 /* genMemsetX - gencode for memSetX data */
13055 /*-----------------------------------------------------------------*/
13056 static void genMemsetX(iCode *ic, int nparms, operand **parms)
13058 operand *to , *val , *count;
13064 /* we know it has to be 3 parameters */
13065 assert (nparms == 3);
13071 /* save DPTR if it needs to be saved */
13072 rsave = newBitVect(16);
13073 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
13074 if (bitVectBitValue(ic->rMask,i))
13075 rsave = bitVectSetBit(rsave,i);
13077 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
13078 ds390_rUmaskForOp (IC_RESULT(ic))));
13081 aopOp (to, ic, FALSE, FALSE);
13082 /* get "to" into DPTR */
13083 /* if the operand is already in dptr
13084 then we do nothing else we move the value to dptr */
13085 if (AOP_TYPE (to) != AOP_STR) {
13086 /* if already in DPTR then we need to push */
13087 if (AOP_TYPE(to) == AOP_DPTR) {
13088 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
13089 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
13090 if (options.model == MODEL_FLAT24)
13091 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
13092 emitcode ("pop", "dph");
13093 emitcode ("pop", "dpl");
13095 _startLazyDPSEvaluation ();
13096 /* if this is remateriazable */
13097 if (AOP_TYPE (to) == AOP_IMMD) {
13098 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
13099 } else { /* we need to get it byte by byte */
13100 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
13101 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
13102 if (options.model == MODEL_FLAT24) {
13103 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
13106 _endLazyDPSEvaluation ();
13109 freeAsmop (to, NULL, ic, FALSE);
13111 aopOp (val, ic->next->next, FALSE,FALSE);
13112 aopOp (count, ic->next->next, FALSE,FALSE);
13113 lbl =newiTempLabel(NULL);
13114 /* now for the actual copy */
13115 if (AOP_TYPE(count) == AOP_LIT &&
13116 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
13117 l = aopGet(val, 0, FALSE, FALSE, NULL);
13118 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
13120 emitcode ("","!tlabeldef",lbl->key+100);
13121 emitcode ("movx", "@dptr,a");
13122 emitcode ("inc", "dptr");
13123 emitcode ("djnz","b,!tlabel",lbl->key+100);
13125 symbol *lbl1 = newiTempLabel(NULL);
13127 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
13128 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
13129 emitcode ("","!tlabeldef",lbl->key+100);
13130 MOVA (aopGet(val, 0, FALSE, FALSE, NULL));
13131 emitcode ("movx", "@dptr,a");
13132 emitcode ("inc", "dptr");
13133 emitcode ("mov","a,b");
13134 emitcode ("orl","a,_ap");
13135 emitcode ("jz","!tlabel",lbl1->key+100);
13136 emitcode ("mov","a,_ap");
13137 emitcode ("add","a,#!constbyte",0xFF);
13138 emitcode ("mov","_ap,a");
13139 emitcode ("mov","a,b");
13140 emitcode ("addc","a,#!constbyte",0xFF);
13141 emitcode ("mov","b,a");
13142 emitcode ("sjmp","!tlabel",lbl->key+100);
13143 emitcode ("","!tlabeldef",lbl1->key+100);
13145 freeAsmop (count, NULL, ic, FALSE);
13146 unsavermask(rsave);
13149 /*-----------------------------------------------------------------*/
13150 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
13151 /*-----------------------------------------------------------------*/
13152 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
13155 operand *pnum, *result;
13158 assert (nparms==1);
13159 /* save registers that need to be saved */
13160 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13161 ds390_rUmaskForOp (IC_RESULT(ic))));
13164 aopOp (pnum, ic, FALSE, FALSE);
13165 emitcode ("mov","a,%s",aopGet(pnum,0,FALSE,FALSE,DP2_RESULT_REG));
13166 freeAsmop (pnum, NULL, ic, FALSE);
13167 emitcode ("lcall","NatLib_LoadPrimitive");
13168 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
13169 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
13170 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
13171 for (i = (size-1) ; i >= 0 ; i-- ) {
13172 emitcode ("push","a%s",javaRet[i]);
13174 for (i=0; i < size ; i++ ) {
13175 emitcode ("pop","a%s",
13176 aopGet(result,i,FALSE,FALSE,DP2_RESULT_REG));
13179 for (i = 0 ; i < size ; i++ ) {
13180 aopPut(result,javaRet[i],i);
13183 freeAsmop (result, NULL, ic, FALSE);
13184 unsavermask(rsave);
13187 /*-----------------------------------------------------------------*/
13188 /* genNatLibLoadPointer - calls TINI api function to load pointer */
13189 /*-----------------------------------------------------------------*/
13190 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
13193 operand *pnum, *result;
13197 assert (nparms==1);
13198 /* save registers that need to be saved */
13199 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13200 ds390_rUmaskForOp (IC_RESULT(ic))));
13203 aopOp (pnum, ic, FALSE, FALSE);
13204 emitcode ("mov","a,%s",aopGet(pnum,0,FALSE,FALSE,DP2_RESULT_REG));
13205 freeAsmop (pnum, NULL, ic, FALSE);
13206 emitcode ("lcall","NatLib_LoadPointer");
13207 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
13208 if (AOP_TYPE(result)!=AOP_STR) {
13209 for (i = 0 ; i < size ; i++ ) {
13210 aopPut(result,fReturn[i],i);
13213 freeAsmop (result, NULL, ic, FALSE);
13214 unsavermask(rsave);
13217 /*-----------------------------------------------------------------*/
13218 /* genNatLibInstallStateBlock - */
13219 /*-----------------------------------------------------------------*/
13220 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
13221 operand **parms, const char *name)
13224 operand *psb, *handle;
13225 assert (nparms==2);
13227 /* save registers that need to be saved */
13228 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13229 ds390_rUmaskForOp (IC_RESULT(ic))));
13233 /* put pointer to state block into DPTR1 */
13234 aopOp (psb, ic, FALSE, FALSE);
13235 if (AOP_TYPE (psb) == AOP_IMMD) {
13236 emitcode ("mov","dps,#1");
13237 emitcode ("mov", "dptr,%s",
13238 aopGet (psb, 0, TRUE, FALSE, DP2_RESULT_REG));
13239 emitcode ("mov","dps,#0");
13241 emitcode ("mov","dpl1,%s",aopGet(psb,0,FALSE,FALSE,DP2_RESULT_REG));
13242 emitcode ("mov","dph1,%s",aopGet(psb,1,FALSE,FALSE,DP2_RESULT_REG));
13243 emitcode ("mov","dpx1,%s",aopGet(psb,2,FALSE,FALSE,DP2_RESULT_REG));
13245 freeAsmop (psb, NULL, ic, FALSE);
13247 /* put libraryID into DPTR */
13248 emitcode ("mov","dptr,#LibraryID");
13250 /* put handle into r3:r2 */
13251 aopOp (handle, ic, FALSE, FALSE);
13252 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13253 emitcode ("push","%s",aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13254 emitcode ("push","%s",aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13255 emitcode ("pop","ar3");
13256 emitcode ("pop","ar2");
13258 emitcode ("mov","r2,%s",aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13259 emitcode ("mov","r3,%s",aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13261 freeAsmop (psb, NULL, ic, FALSE);
13263 /* make the call */
13264 emitcode ("lcall","NatLib_Install%sStateBlock",name);
13266 /* put return value into place*/
13268 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
13270 aopPut(IC_RESULT(ic),"a",0);
13271 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13272 unsavermask(rsave);
13275 /*-----------------------------------------------------------------*/
13276 /* genNatLibRemoveStateBlock - */
13277 /*-----------------------------------------------------------------*/
13278 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
13284 /* save registers that need to be saved */
13285 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13286 ds390_rUmaskForOp (IC_RESULT(ic))));
13288 /* put libraryID into DPTR */
13289 emitcode ("mov","dptr,#LibraryID");
13290 /* make the call */
13291 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
13292 unsavermask(rsave);
13295 /*-----------------------------------------------------------------*/
13296 /* genNatLibGetStateBlock - */
13297 /*-----------------------------------------------------------------*/
13298 static void genNatLibGetStateBlock(iCode *ic,int nparms,
13299 operand **parms,const char *name)
13302 symbol *lbl = newiTempLabel(NULL);
13305 /* save registers that need to be saved */
13306 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13307 ds390_rUmaskForOp (IC_RESULT(ic))));
13309 /* put libraryID into DPTR */
13310 emitcode ("mov","dptr,#LibraryID");
13311 /* make the call */
13312 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
13313 emitcode ("jnz","!tlabel",lbl->key+100);
13315 /* put return value into place */
13316 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
13317 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
13318 emitcode ("push","ar3");
13319 emitcode ("push","ar2");
13320 emitcode ("pop","%s",
13321 aopGet(IC_RESULT(ic),0,FALSE,TRUE,DP2_RESULT_REG));
13322 emitcode ("pop","%s",
13323 aopGet(IC_RESULT(ic),1,FALSE,TRUE,DP2_RESULT_REG));
13325 aopPut(IC_RESULT(ic),"r2",0);
13326 aopPut(IC_RESULT(ic),"r3",1);
13328 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13329 emitcode ("","!tlabeldef",lbl->key+100);
13330 unsavermask(rsave);
13333 /*-----------------------------------------------------------------*/
13334 /* genMMMalloc - */
13335 /*-----------------------------------------------------------------*/
13336 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
13337 int size, const char *name)
13342 symbol *lbl = newiTempLabel(NULL);
13344 assert (nparms == 1);
13345 /* save registers that need to be saved */
13346 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13347 ds390_rUmaskForOp (IC_RESULT(ic))));
13350 aopOp (bsize,ic,FALSE,FALSE);
13352 /* put the size in R4-R2 */
13353 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
13354 emitcode("push","%s",aopGet(bsize,0,FALSE,TRUE,DP2_RESULT_REG));
13355 emitcode("push","%s",aopGet(bsize,1,FALSE,TRUE,DP2_RESULT_REG));
13357 emitcode("push","%s",aopGet(bsize,2,FALSE,TRUE,DP2_RESULT_REG));
13358 emitcode("pop","ar4");
13360 emitcode("pop","ar3");
13361 emitcode("pop","ar2");
13363 emitcode ("mov","r2,%s",aopGet(bsize,0,FALSE,TRUE,DP2_RESULT_REG));
13364 emitcode ("mov","r3,%s",aopGet(bsize,1,FALSE,TRUE,DP2_RESULT_REG));
13366 emitcode("mov","r4,%s",aopGet(bsize,2,FALSE,TRUE,DP2_RESULT_REG));
13369 freeAsmop (bsize, NULL, ic, FALSE);
13371 /* make the call */
13372 emitcode ("lcall","MM_%s",name);
13373 emitcode ("jz","!tlabel",lbl->key+100);
13374 emitcode ("mov","r2,#!constbyte",0xff);
13375 emitcode ("mov","r3,#!constbyte",0xff);
13376 emitcode ("","!tlabeldef",lbl->key+100);
13377 /* we don't care about the pointer : we just save the handle */
13378 rsym = OP_SYMBOL(IC_RESULT(ic));
13379 if (rsym->liveFrom != rsym->liveTo) {
13380 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
13381 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
13382 emitcode ("push","ar3");
13383 emitcode ("push","ar2");
13384 emitcode ("pop","%s",
13385 aopGet(IC_RESULT(ic),0,FALSE,TRUE,DP2_RESULT_REG));
13386 emitcode ("pop","%s",
13387 aopGet(IC_RESULT(ic),1,FALSE,TRUE,DP2_RESULT_REG));
13389 aopPut(IC_RESULT(ic),"r2",0);
13390 aopPut(IC_RESULT(ic),"r3",1);
13392 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13394 unsavermask(rsave);
13397 /*-----------------------------------------------------------------*/
13399 /*-----------------------------------------------------------------*/
13400 static void genMMDeref (iCode *ic,int nparms, operand **parms)
13405 assert (nparms == 1);
13406 /* save registers that need to be saved */
13407 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13408 ds390_rUmaskForOp (IC_RESULT(ic))));
13411 aopOp (handle,ic,FALSE,FALSE);
13413 /* put the size in R4-R2 */
13414 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13415 emitcode("push","%s",
13416 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13417 emitcode("push","%s",
13418 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13419 emitcode("pop","ar3");
13420 emitcode("pop","ar2");
13422 emitcode ("mov","r2,%s",
13423 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13424 emitcode ("mov","r3,%s",
13425 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13427 freeAsmop (handle, NULL, ic, FALSE);
13429 /* make the call */
13430 emitcode ("lcall","MM_Deref");
13433 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13434 if (rsym->liveFrom != rsym->liveTo) {
13435 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13436 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
13437 _startLazyDPSEvaluation ();
13439 aopPut(IC_RESULT(ic),"dpl",0);
13440 aopPut(IC_RESULT(ic),"dph",1);
13441 aopPut(IC_RESULT(ic),"dpx",2);
13443 _endLazyDPSEvaluation ();
13448 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13449 unsavermask(rsave);
13452 /*-----------------------------------------------------------------*/
13453 /* genMMUnrestrictedPersist - */
13454 /*-----------------------------------------------------------------*/
13455 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
13460 assert (nparms == 1);
13461 /* save registers that need to be saved */
13462 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13463 ds390_rUmaskForOp (IC_RESULT(ic))));
13466 aopOp (handle,ic,FALSE,FALSE);
13468 /* put the size in R3-R2 */
13469 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13470 emitcode("push","%s",
13471 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13472 emitcode("push","%s",
13473 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13474 emitcode("pop","ar3");
13475 emitcode("pop","ar2");
13477 emitcode ("mov","r2,%s",
13478 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13479 emitcode ("mov","r3,%s",
13480 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13482 freeAsmop (handle, NULL, ic, FALSE);
13484 /* make the call */
13485 emitcode ("lcall","MM_UnrestrictedPersist");
13488 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13489 if (rsym->liveFrom != rsym->liveTo) {
13490 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13491 aopPut(IC_RESULT(ic),"a",0);
13492 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13495 unsavermask(rsave);
13498 /*-----------------------------------------------------------------*/
13499 /* genSystemExecJavaProcess - */
13500 /*-----------------------------------------------------------------*/
13501 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
13504 operand *handle, *pp;
13506 assert (nparms==2);
13507 /* save registers that need to be saved */
13508 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13509 ds390_rUmaskForOp (IC_RESULT(ic))));
13514 /* put the handle in R3-R2 */
13515 aopOp (handle,ic,FALSE,FALSE);
13516 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13517 emitcode("push","%s",
13518 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13519 emitcode("push","%s",
13520 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13521 emitcode("pop","ar3");
13522 emitcode("pop","ar2");
13524 emitcode ("mov","r2,%s",
13525 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13526 emitcode ("mov","r3,%s",
13527 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13529 freeAsmop (handle, NULL, ic, FALSE);
13531 /* put pointer in DPTR */
13532 aopOp (pp,ic,FALSE,FALSE);
13533 if (AOP_TYPE(pp) == AOP_IMMD) {
13534 emitcode ("mov", "dptr,%s",
13535 aopGet (pp, 0, TRUE, FALSE, NULL));
13536 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
13537 emitcode ("mov","dpl,%s",aopGet(pp,0,FALSE,FALSE,NULL));
13538 emitcode ("mov","dph,%s",aopGet(pp,1,FALSE,FALSE,NULL));
13539 emitcode ("mov","dpx,%s",aopGet(pp,2,FALSE,FALSE,NULL));
13541 freeAsmop (handle, NULL, ic, FALSE);
13543 /* make the call */
13544 emitcode ("lcall","System_ExecJavaProcess");
13546 /* put result in place */
13548 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13549 if (rsym->liveFrom != rsym->liveTo) {
13550 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13551 aopPut(IC_RESULT(ic),"a",0);
13552 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13556 unsavermask(rsave);
13559 /*-----------------------------------------------------------------*/
13560 /* genSystemRTCRegisters - */
13561 /*-----------------------------------------------------------------*/
13562 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
13568 assert (nparms==1);
13569 /* save registers that need to be saved */
13570 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13571 ds390_rUmaskForOp (IC_RESULT(ic))));
13574 /* put pointer in DPTR */
13575 aopOp (pp,ic,FALSE,FALSE);
13576 if (AOP_TYPE (pp) == AOP_IMMD) {
13577 emitcode ("mov","dps,#1");
13578 emitcode ("mov", "dptr,%s",
13579 aopGet (pp, 0, TRUE, FALSE, NULL));
13580 emitcode ("mov","dps,#0");
13582 emitcode ("mov","dpl1,%s",
13583 aopGet(pp,0,FALSE,FALSE,DP2_RESULT_REG));
13584 emitcode ("mov","dph1,%s",
13585 aopGet(pp,1,FALSE,FALSE,DP2_RESULT_REG));
13586 emitcode ("mov","dpx1,%s",
13587 aopGet(pp,2,FALSE,FALSE,DP2_RESULT_REG));
13589 freeAsmop (pp, NULL, ic, FALSE);
13591 /* make the call */
13592 emitcode ("lcall","System_%sRTCRegisters",name);
13594 unsavermask(rsave);
13597 /*-----------------------------------------------------------------*/
13598 /* genSystemThreadSleep - */
13599 /*-----------------------------------------------------------------*/
13600 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
13605 assert (nparms==1);
13606 /* save registers that need to be saved */
13607 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13608 ds390_rUmaskForOp (IC_RESULT(ic))));
13611 aopOp(to,ic,FALSE,FALSE);
13612 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
13613 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
13614 emitcode ("push","%s",
13615 aopGet(to,0,FALSE,TRUE,DP2_RESULT_REG));
13616 emitcode ("push","%s",
13617 aopGet(to,1,FALSE,TRUE,DP2_RESULT_REG));
13618 emitcode ("push","%s",
13619 aopGet(to,2,FALSE,TRUE,DP2_RESULT_REG));
13620 emitcode ("push","%s",
13621 aopGet(to,3,FALSE,TRUE,DP2_RESULT_REG));
13622 emitcode ("pop","ar3");
13623 emitcode ("pop","ar2");
13624 emitcode ("pop","ar1");
13625 emitcode ("pop","ar0");
13627 emitcode ("mov","r0,%s",
13628 aopGet(to,0,FALSE,TRUE,DP2_RESULT_REG));
13629 emitcode ("mov","r1,%s",
13630 aopGet(to,1,FALSE,TRUE,DP2_RESULT_REG));
13631 emitcode ("mov","r2,%s",
13632 aopGet(to,2,FALSE,TRUE,DP2_RESULT_REG));
13633 emitcode ("mov","r3,%s",
13634 aopGet(to,3,FALSE,TRUE,DP2_RESULT_REG));
13636 freeAsmop (to, NULL, ic, FALSE);
13638 /* suspend in acc */
13640 aopOp(s,ic,FALSE,FALSE);
13641 emitcode ("mov","a,%s",
13642 aopGet(s,0,FALSE,TRUE,NULL));
13643 freeAsmop (s, NULL, ic, FALSE);
13645 /* make the call */
13646 emitcode ("lcall","System_%s",name);
13648 unsavermask(rsave);
13651 /*-----------------------------------------------------------------*/
13652 /* genSystemThreadResume - */
13653 /*-----------------------------------------------------------------*/
13654 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
13659 assert (nparms==2);
13660 /* save registers that need to be saved */
13661 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13662 ds390_rUmaskForOp (IC_RESULT(ic))));
13668 aopOp(pid,ic,FALSE,FALSE);
13669 emitcode ("mov","r0,%s",
13670 aopGet(pid,0,FALSE,TRUE,DP2_RESULT_REG));
13671 freeAsmop (pid, NULL, ic, FALSE);
13674 aopOp(tid,ic,FALSE,FALSE);
13675 emitcode ("mov","a,%s",
13676 aopGet(tid,0,FALSE,TRUE,DP2_RESULT_REG));
13677 freeAsmop (tid, NULL, ic, FALSE);
13679 emitcode ("lcall","System_ThreadResume");
13681 /* put result into place */
13683 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13684 if (rsym->liveFrom != rsym->liveTo) {
13685 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13686 aopPut(IC_RESULT(ic),"a",0);
13687 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13690 unsavermask(rsave);
13693 /*-----------------------------------------------------------------*/
13694 /* genSystemProcessResume - */
13695 /*-----------------------------------------------------------------*/
13696 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
13701 assert (nparms==1);
13702 /* save registers that need to be saved */
13703 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13704 ds390_rUmaskForOp (IC_RESULT(ic))));
13709 aopOp(pid,ic,FALSE,FALSE);
13710 emitcode ("mov","a,%s",
13711 aopGet(pid,0,FALSE,TRUE,DP2_RESULT_REG));
13712 freeAsmop (pid, NULL, ic, FALSE);
13714 emitcode ("lcall","System_ProcessResume");
13716 unsavermask(rsave);
13719 /*-----------------------------------------------------------------*/
13721 /*-----------------------------------------------------------------*/
13722 static void genSystem (iCode *ic,int nparms,char *name)
13724 assert(nparms == 0);
13726 emitcode ("lcall","System_%s",name);
13729 /*-----------------------------------------------------------------*/
13730 /* genSystemPoll - */
13731 /*-----------------------------------------------------------------*/
13732 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
13737 assert (nparms==1);
13738 /* save registers that need to be saved */
13739 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13740 ds390_rUmaskForOp (IC_RESULT(ic))));
13743 aopOp (fp,ic,FALSE,FALSE);
13744 if (AOP_TYPE (fp) == AOP_IMMD) {
13745 emitcode ("mov", "dptr,%s",
13746 aopGet (fp, 0, TRUE, FALSE, DP2_RESULT_REG));
13747 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
13748 emitcode ("mov","dpl,%s",
13749 aopGet(fp,0,FALSE,FALSE,DP2_RESULT_REG));
13750 emitcode ("mov","dph,%s",
13751 aopGet(fp,1,FALSE,FALSE,DP2_RESULT_REG));
13752 emitcode ("mov","dpx,%s",
13753 aopGet(fp,2,FALSE,FALSE,DP2_RESULT_REG));
13755 freeAsmop (fp, NULL, ic, FALSE);
13757 emitcode ("lcall","System_%sPoll",name);
13759 /* put result into place */
13761 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13762 if (rsym->liveFrom != rsym->liveTo) {
13763 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13764 aopPut(IC_RESULT(ic),"a",0);
13765 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13768 unsavermask(rsave);
13771 /*-----------------------------------------------------------------*/
13772 /* genSystemGetCurrentID - */
13773 /*-----------------------------------------------------------------*/
13774 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
13776 assert (nparms==0);
13778 emitcode ("lcall","System_GetCurrent%sId",name);
13779 /* put result into place */
13781 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13782 if (rsym->liveFrom != rsym->liveTo) {
13783 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13784 aopPut(IC_RESULT(ic),"a",0);
13785 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13790 /*-----------------------------------------------------------------*/
13791 /* genDjnz - generate decrement & jump if not zero instrucion */
13792 /*-----------------------------------------------------------------*/
13794 genDjnz (iCode * ic, iCode * ifx)
13796 symbol *lbl, *lbl1;
13800 /* if the if condition has a false label
13801 then we cannot save */
13802 if (IC_FALSE (ifx))
13805 /* if the minus is not of the form a = a - 1 */
13806 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
13807 !IS_OP_LITERAL (IC_RIGHT (ic)))
13810 if (operandLitValue (IC_RIGHT (ic)) != 1)
13813 /* if the size of this greater than one then no
13815 if (getSize (operandType (IC_RESULT (ic))) > 1)
13818 /* otherwise we can save BIG */
13820 D (emitcode (";", "genDjnz"));
13822 lbl = newiTempLabel (NULL);
13823 lbl1 = newiTempLabel (NULL);
13825 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
13827 if (AOP_NEEDSACC(IC_RESULT(ic)))
13829 /* If the result is accessed indirectly via
13830 * the accumulator, we must explicitly write
13831 * it back after the decrement.
13833 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE, NULL);
13835 if (strcmp(rByte, "a"))
13837 /* Something is hopelessly wrong */
13838 fprintf(stderr, "*** warning: internal error at %s:%d\n",
13839 __FILE__, __LINE__);
13840 /* We can just give up; the generated code will be inefficient,
13841 * but what the hey.
13843 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13846 emitcode ("dec", "%s", rByte);
13847 aopPut (IC_RESULT (ic), rByte, 0);
13848 emitcode ("jnz", "!tlabel", lbl->key + 100);
13850 else if (IS_AOP_PREG (IC_RESULT (ic)))
13852 emitcode ("dec", "%s",
13853 aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL));
13854 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL));
13855 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13856 ifx->generated = 1;
13857 emitcode ("jnz", "!tlabel", lbl->key + 100);
13861 emitcode ("djnz", "%s,!tlabel", aopGet (IC_RESULT (ic), 0, FALSE, TRUE, NULL),
13864 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
13866 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
13869 if (!ifx->generated)
13870 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13871 ifx->generated = 1;
13875 /*-----------------------------------------------------------------*/
13876 /* genReceive - generate code for a receive iCode */
13877 /*-----------------------------------------------------------------*/
13879 genReceive (iCode * ic)
13881 int size = getSize (operandType (IC_RESULT (ic)));
13885 D (emitcode (";", "genReceive"));
13887 if (ic->argreg == 1)
13889 /* first parameter */
13890 if (AOP_IS_STR(IC_RESULT(ic)))
13892 /* Nothing to do: it's already in the proper place. */
13899 useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
13900 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
13901 IS_TRUE_SYMOP (IC_RESULT (ic)));
13904 aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
13907 /* Sanity checking... */
13908 if (AOP_USESDPTR(IC_RESULT(ic)))
13910 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
13911 "genReceive got unexpected DPTR.");
13913 assignResultValue (IC_RESULT (ic), NULL);
13916 else if (ic->argreg > 12)
13917 { /* bit parameters */
13918 if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
13920 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
13921 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
13922 outBitC(IC_RESULT (ic));
13927 /* second receive onwards */
13928 /* this gets a little tricky since unused receives will be
13929 eliminated, we have saved the reg in the type field . and
13930 we use that to figure out which register to use */
13931 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
13932 rb1off = ic->argreg;
13935 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
13938 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13941 /*-----------------------------------------------------------------*/
13942 /* genDummyRead - generate code for dummy read of volatiles */
13943 /*-----------------------------------------------------------------*/
13945 genDummyRead (iCode * ic)
13950 D (emitcode(";", "genDummyRead"));
13952 op = IC_RIGHT (ic);
13953 if (op && IS_SYMOP (op))
13955 aopOp (op, ic, FALSE, FALSE);
13957 /* if the result is a bit */
13958 if (AOP_TYPE (op) == AOP_CRY)
13959 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13962 /* bit variables done */
13964 size = AOP_SIZE (op);
13968 MOVA (aopGet (op, offset, FALSE, FALSE, FALSE));
13973 freeAsmop (op, NULL, ic, TRUE);
13977 if (op && IS_SYMOP (op))
13979 aopOp (op, ic, FALSE, FALSE);
13981 /* if the result is a bit */
13982 if (AOP_TYPE (op) == AOP_CRY)
13983 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13986 /* bit variables done */
13988 size = AOP_SIZE (op);
13992 MOVA (aopGet (op, offset, FALSE, FALSE, FALSE));
13997 freeAsmop (op, NULL, ic, TRUE);
14001 /*-----------------------------------------------------------------*/
14002 /* genCritical - generate code for start of a critical sequence */
14003 /*-----------------------------------------------------------------*/
14005 genCritical (iCode *ic)
14007 symbol *tlbl = newiTempLabel (NULL);
14009 D (emitcode(";", "genCritical"));
14011 if (IC_RESULT (ic))
14013 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
14014 aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
14015 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
14016 aopPut (IC_RESULT (ic), zero, 0);
14018 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
14022 emitcode ("setb", "c");
14023 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
14024 emitcode ("clr", "c");
14026 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
14030 /*-----------------------------------------------------------------*/
14031 /* genEndCritical - generate code for end of a critical sequence */
14032 /*-----------------------------------------------------------------*/
14034 genEndCritical (iCode *ic)
14036 D(emitcode("; genEndCritical",""));
14040 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
14041 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
14043 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
14044 emitcode ("mov", "ea,c");
14048 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE, FALSE));
14049 emitcode ("rrc", "a");
14050 emitcode ("mov", "ea,c");
14052 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
14056 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
14057 emitcode ("mov", "ea,c");
14063 /*-----------------------------------------------------------------*/
14064 /* genBuiltIn - calls the appropriate function to generating code */
14065 /* for a built in function */
14066 /*-----------------------------------------------------------------*/
14067 static void genBuiltIn (iCode *ic)
14069 operand *bi_parms[MAX_BUILTIN_ARGS];
14074 /* get all the arguments for a built in function */
14075 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
14077 /* which function is it */
14078 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
14079 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
14080 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
14081 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
14082 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
14083 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
14084 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
14085 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
14086 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
14087 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
14088 genMemsetX(bi_iCode,nbi_parms,bi_parms);
14089 } else if (strcmp(bif->name,"__builtin_inp")==0) {
14090 genInp(bi_iCode,nbi_parms,bi_parms);
14091 } else if (strcmp(bif->name,"__builtin_outp")==0) {
14092 genOutp(bi_iCode,nbi_parms,bi_parms);
14093 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
14094 genSwapW(bi_iCode,nbi_parms,bi_parms);
14095 /* JavaNative builtIns */
14096 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
14097 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
14098 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
14099 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
14100 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
14101 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
14102 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
14103 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
14104 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
14105 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
14106 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
14107 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
14108 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
14109 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
14110 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
14111 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
14112 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
14113 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
14114 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
14115 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
14116 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
14117 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
14118 } else if (strcmp(bif->name,"MM_Malloc")==0) {
14119 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
14120 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
14121 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
14122 } else if (strcmp(bif->name,"MM_Free")==0) {
14123 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
14124 } else if (strcmp(bif->name,"MM_Deref")==0) {
14125 genMMDeref(bi_iCode,nbi_parms,bi_parms);
14126 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
14127 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
14128 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
14129 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
14130 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
14131 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
14132 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
14133 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
14134 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
14135 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
14136 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
14137 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
14138 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
14139 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
14140 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
14141 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
14142 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
14143 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
14144 } else if (strcmp(bif->name,"System_SaveThread")==0) {
14145 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
14146 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
14147 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
14148 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
14149 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
14150 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
14151 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
14152 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
14153 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
14154 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
14155 genSystem(bi_iCode,nbi_parms,"ProcessYield");
14156 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
14157 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
14158 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
14159 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
14160 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
14161 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
14162 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
14163 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
14164 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
14165 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
14167 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
14173 /*-----------------------------------------------------------------*/
14174 /* gen390Code - generate code for Dallas 390 based controllers */
14175 /*-----------------------------------------------------------------*/
14177 gen390Code (iCode * lic)
14182 _G.currentFunc = NULL;
14183 lineHead = lineCurr = NULL;
14184 dptrn[1][0] = "dpl1";
14185 dptrn[1][1] = "dph1";
14186 dptrn[1][2] = "dpx1";
14188 if (options.model == MODEL_FLAT24) {
14189 fReturnSizeDS390 = 5;
14190 fReturn = fReturn24;
14192 fReturnSizeDS390 = 4;
14193 fReturn = fReturn16;
14194 options.stack10bit=0;
14197 /* print the allocation information */
14198 if (allocInfo && currFunc)
14199 printAllocInfo (currFunc, codeOutFile);
14201 /* if debug information required */
14202 if (options.debug && currFunc)
14204 debugFile->writeFunction (currFunc, lic);
14206 /* stack pointer name */
14207 if (options.useXstack)
14213 for (ic = lic; ic; ic = ic->next)
14215 _G.current_iCode = ic;
14217 if (ic->lineno && cln != ic->lineno)
14221 debugFile->writeCLine (ic);
14223 if (!options.noCcodeInAsm) {
14224 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
14225 printCLine(ic->filename, ic->lineno));
14229 if (options.iCodeInAsm) {
14230 emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
14232 /* if the result is marked as
14233 spilt and rematerializable or code for
14234 this has already been generated then
14236 if (resultRemat (ic) || ic->generated)
14239 /* depending on the operation */
14259 /* IPOP happens only when trying to restore a
14260 spilt live range, if there is an ifx statement
14261 following this pop then the if statement might
14262 be using some of the registers being popped which
14263 would destory the contents of the register so
14264 we need to check for this condition and handle it */
14266 ic->next->op == IFX &&
14267 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
14268 genIfx (ic->next, ic);
14286 genEndFunction (ic);
14306 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
14323 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
14327 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
14334 /* note these two are xlated by algebraic equivalence
14335 during parsing SDCC.y */
14336 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
14337 "got '>=' or '<=' shouldn't have come here");
14341 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
14353 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
14357 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
14361 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
14385 genRightShift (ic);
14388 case GET_VALUE_AT_ADDRESS:
14390 hasInc (IC_LEFT (ic), ic,
14391 getSize (operandType (IC_RESULT (ic)))));
14395 if (POINTER_SET (ic))
14397 hasInc (IC_RESULT (ic), ic,
14398 getSize (operandType (IC_RIGHT (ic)))));
14424 if (ic->builtinSEND)
14427 addSet (&_G.sendSet, ic);
14430 case DUMMY_READ_VOLATILE:
14439 genEndCritical (ic);
14446 #if 0 // obsolete, and buggy for != xdata
14458 /* now we are ready to call the
14459 peep hole optimizer */
14460 if (!options.nopeep)
14461 peepHole (&lineHead);
14463 /* now do the actual printing */
14464 printLine (lineHead, codeOutFile);