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 char offset = ((sym->stack < 0) ?
732 ((char) (sym->stack - _G.nRegsSaved)) :
733 ((char) sym->stack)) & 0xff;
735 if ((abs(offset) <= 3) ||
736 (accuse && (abs(offset) <= 7)))
738 emitcode ("mov", "%s,_bp",
739 aop->aopu.aop_ptr->name);
742 emitcode ("dec", aop->aopu.aop_ptr->name);
747 emitcode ("inc", aop->aopu.aop_ptr->name);
754 emitcode ("push", "acc");
755 emitcode ("mov", "a,_bp");
756 emitcode ("add", "a,#!constbyte", offset);
757 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
759 emitcode ("pop", "acc");
764 emitcode ("mov", "%s,#%s",
765 aop->aopu.aop_ptr->name,
768 aop->paged = space->paged;
771 aop->aopu.aop_stk = sym->stack;
775 if (sym->onStack && options.stack10bit)
777 short stack_val = -((sym->stack < 0) ?
778 ((short) (sym->stack - _G.nRegsSaved)) :
779 ((short) sym->stack)) ;
781 emitcode ("push",dpl);
782 emitcode ("push",dph);
783 emitcode ("push",dpx);
785 /* It's on the 10 bit stack, which is located in
788 if (stack_val < 0 && stack_val > -5)
789 { /* between -5 & -1 */
790 if (options.model == MODEL_FLAT24)
792 emitcode ("mov", "%s,#!constbyte", dpx,
793 (options.stack_loc >> 16) & 0xff);
795 emitcode ("mov", "%s,_bpx+1", dph);
796 emitcode ("mov", "%s,_bpx", dpl);
798 emitcode ("mov","dps,#1");
800 stack_val = -stack_val;
801 while (stack_val--) {
802 emitcode ("inc","dptr");
805 emitcode("mov","dps,#0");
811 emitcode ("push", "acc");
813 emitcode ("mov", "a,_bpx");
814 emitcode ("clr","c");
815 emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
816 emitcode ("mov","%s,a", dpl);
817 emitcode ("mov","a,_bpx+1");
818 emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
819 emitcode ("mov", "%s,a", dph);
820 if (options.model == MODEL_FLAT24)
822 emitcode ("mov", "%s,#!constbyte", dpx,
823 (options.stack_loc >> 16) & 0xff);
827 emitcode ("pop", "acc");
829 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
830 aop->size = getSize (sym->type);
834 /* if in bit space */
835 if (IN_BITSPACE (space))
837 sym->aop = aop = newAsmop (AOP_CRY);
838 aop->aopu.aop_dir = sym->rname;
839 aop->size = getSize (sym->type);
842 /* if it is in direct space */
843 if (IN_DIRSPACE (space))
845 sym->aop = aop = newAsmop (AOP_DIR);
846 aop->aopu.aop_dir = sym->rname;
847 aop->size = getSize (sym->type);
851 /* special case for a function */
852 if (IS_FUNC (sym->type) && !(sym->isitmp))
854 sym->aop = aop = newAsmop (AOP_IMMD);
855 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
856 aop->size = FPTRSIZE;
860 /* only remaining is far space */
861 /* in which case DPTR gets the address */
862 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
867 emitcode ("mov", "dptr,#%s", sym->rname);
872 emitcode ("mov", "dptr,#%s", sym->rname);
874 aop->size = getSize (sym->type);
876 /* if it is in code space */
877 if (IN_CODESPACE (space))
883 /*-----------------------------------------------------------------*/
884 /* aopForRemat - rematerialzes an object */
885 /*-----------------------------------------------------------------*/
887 aopForRemat (symbol * sym)
889 iCode *ic = sym->rematiCode;
890 asmop *aop = newAsmop (AOP_IMMD);
897 val += (int) operandLitValue (IC_RIGHT (ic));
898 else if (ic->op == '-')
899 val -= (int) operandLitValue (IC_RIGHT (ic));
900 else if (IS_CAST_ICODE(ic)) {
901 sym_link *from_type = operandType(IC_RIGHT(ic));
902 aop->aopu.aop_immd.from_cast_remat = 1;
903 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
904 ptr_type = pointerTypeToGPByte (DCL_TYPE(from_type), NULL, NULL);
908 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
913 SNPRINTF (buffer, sizeof(buffer),
915 OP_SYMBOL (IC_LEFT (ic))->rname,
916 val >= 0 ? '+' : '-',
917 abs (val) & 0xffffff);
921 if (IS_ASSIGN_ICODE(ic) && isOperandLiteral(IC_RIGHT(ic)))
923 SNPRINTF(buffer, sizeof(buffer),
924 "0x%x",(int) operandLitValue (IC_RIGHT (ic)));
928 strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
932 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
933 /* set immd2 field if required */
934 if (aop->aopu.aop_immd.from_cast_remat)
936 tsprintf(buffer, sizeof(buffer), "#!constbyte",ptr_type);
937 aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
943 /*-----------------------------------------------------------------*/
944 /* aopHasRegs - returns true if aop has regs between from-to */
945 /*-----------------------------------------------------------------*/
946 static int aopHasRegs(asmop *aop, int from, int to)
950 if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
952 for (; size < aop->size ; size++) {
954 for (reg = from ; reg <= to ; reg++)
955 if (aop->aopu.aop_reg[size] == REG_WITH_INDEX(reg)) return 1;
960 /*-----------------------------------------------------------------*/
961 /* regsInCommon - two operands have some registers in common */
962 /*-----------------------------------------------------------------*/
964 regsInCommon (operand * op1, operand * op2)
969 /* if they have registers in common */
970 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
973 sym1 = OP_SYMBOL (op1);
974 sym2 = OP_SYMBOL (op2);
976 if (sym1->nRegs == 0 || sym2->nRegs == 0)
979 for (i = 0; i < sym1->nRegs; i++)
985 for (j = 0; j < sym2->nRegs; j++)
990 if (sym2->regs[j] == sym1->regs[i])
998 /*-----------------------------------------------------------------*/
999 /* operandsEqu - equivalent */
1000 /*-----------------------------------------------------------------*/
1002 operandsEqu (operand * op1, operand * op2)
1004 symbol *sym1, *sym2;
1006 /* if they're not symbols */
1007 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
1010 sym1 = OP_SYMBOL (op1);
1011 sym2 = OP_SYMBOL (op2);
1013 /* if both are itemps & one is spilt
1014 and the other is not then false */
1015 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
1016 sym1->isspilt != sym2->isspilt)
1019 /* if they are the same */
1023 /* if they have the same rname */
1024 if (sym1->rname[0] && sym2->rname[0] &&
1025 strcmp (sym1->rname, sym2->rname) == 0 &&
1026 !(IS_PARM (op2) && IS_ITEMP (op1)))
1029 /* if left is a tmp & right is not */
1030 if (IS_ITEMP (op1) &&
1033 (sym1->usl.spillLoc == sym2))
1036 if (IS_ITEMP (op2) &&
1040 (sym2->usl.spillLoc == sym1))
1043 /* are they spilt to the same location */
1044 if (IS_ITEMP (op2) &&
1048 (sym1->usl.spillLoc == sym2->usl.spillLoc))
1054 /*-----------------------------------------------------------------*/
1055 /* sameRegs - two asmops have the same registers */
1056 /*-----------------------------------------------------------------*/
1058 sameRegs (asmop * aop1, asmop * aop2)
1064 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
1071 if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
1074 if (aop1->type != aop2->type)
1077 if (aop1->size != aop2->size)
1080 for (i = 0; i < aop1->size; i++)
1081 if (aop1->aopu.aop_reg[i] != aop2->aopu.aop_reg[i])
1087 /*-----------------------------------------------------------------*/
1088 /* aopOp - allocates an asmop for an operand : */
1089 /*-----------------------------------------------------------------*/
1091 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
1100 /* if this a literal */
1101 if (IS_OP_LITERAL (op))
1103 op->aop = aop = newAsmop (AOP_LIT);
1104 aop->aopu.aop_lit = op->operand.valOperand;
1105 aop->size = getSize (operandType (op));
1109 /* if already has a asmop then continue */
1112 if ((op->aop->type == AOP_DPTR && useDP2)
1113 || (op->aop->type == AOP_DPTR2 && !useDP2))
1117 op->aop->allocated++;
1122 /* if the underlying symbol has a aop */
1123 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
1125 op->aop = OP_SYMBOL (op)->aop;
1126 if ((op->aop->type == AOP_DPTR && useDP2)
1127 || (op->aop->type == AOP_DPTR2 && !useDP2))
1131 op->aop->allocated++;
1136 /* if this is a true symbol */
1137 if (IS_TRUE_SYMOP (op))
1139 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
1143 /* this is a temporary : this has
1149 e) can be a return use only */
1151 sym = OP_SYMBOL (op);
1153 /* if the type is a conditional */
1154 if (sym->regType == REG_CND)
1156 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
1161 /* if it is spilt then two situations
1163 b) has a spill location */
1164 if (sym->isspilt || sym->nRegs == 0)
1167 /* rematerialize it NOW */
1170 sym->aop = op->aop = aop =
1172 aop->size = getSize (sym->type);
1179 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
1180 aop->size = getSize (sym->type);
1181 for (i = 0; i < 2; i++)
1182 aop->aopu.aop_str[i] = accUse[i];
1192 /* a AOP_STR uses DPTR, but DPTR is already in use;
1195 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
1198 aop = op->aop = sym->aop = newAsmop (AOP_STR);
1199 aop->size = getSize (sym->type);
1200 for (i = 0; i < fReturnSizeDS390; i++)
1201 aop->aopu.aop_str[i] = fReturn[i];
1205 if (sym->dptr) { /* has been allocated to a DPTRn */
1206 aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
1207 aop->size = getSize (sym->type);
1208 aop->aopu.dptr = sym->dptr;
1212 if (sym->usl.spillLoc)
1214 asmop *oldAsmOp = NULL;
1216 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1218 /* force a new aop if sizes differ */
1219 oldAsmOp = sym->usl.spillLoc->aop;
1220 sym->usl.spillLoc->aop = NULL;
1222 sym->aop = op->aop = aop =
1223 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
1224 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1226 /* Don't reuse the new aop, go with the last one */
1227 sym->usl.spillLoc->aop = oldAsmOp;
1229 aop->size = getSize (sym->type);
1233 /* else must be a dummy iTemp */
1234 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1235 aop->size = getSize (sym->type);
1239 /* if the type is a bit register */
1240 if (sym->regType == REG_BIT)
1242 sym->aop = op->aop = aop = newAsmop (AOP_CRY);
1243 aop->size = sym->nRegs;//1???
1244 aop->aopu.aop_reg[0] = sym->regs[0];
1245 aop->aopu.aop_dir = sym->regs[0]->name;
1249 /* must be in a register */
1250 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1251 aop->size = sym->nRegs;
1252 for (i = 0; i < sym->nRegs; i++)
1253 aop->aopu.aop_reg[i] = sym->regs[i];
1256 /*-----------------------------------------------------------------*/
1257 /* freeAsmop - free up the asmop given to an operand */
1258 /*----------------------------------------------------------------*/
1260 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1277 /* depending on the asmop type only three cases need work
1278 AOP_R0, AOP_R1 & AOP_STK */
1286 emitcode ("pop", "ar0");
1290 bitVectUnSetBit (ic->rUsed, R0_IDX);
1298 emitcode ("pop", "ar1");
1302 bitVectUnSetBit (ic->rUsed, R1_IDX);
1308 int stk = aop->aopu.aop_stk + aop->size;
1309 bitVectUnSetBit (ic->rUsed, R0_IDX);
1310 bitVectUnSetBit (ic->rUsed, R1_IDX);
1312 getFreePtr (ic, &aop, FALSE);
1314 if (options.stack10bit)
1316 /* I'm not sure what to do here yet... */
1319 "*** Warning: probably generating bad code for "
1320 "10 bit stack mode.\n");
1325 emitcode ("mov", "a,_bp");
1326 emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
1327 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1331 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1336 emitcode ("pop", "acc");
1337 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1340 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1343 freeAsmop (op, NULL, ic, TRUE);
1346 emitcode ("pop", "ar1");
1351 emitcode ("pop", "ar0");
1356 if (_G.dptr1InUse) {
1357 emitcode ("pop","dpx1");
1358 emitcode ("pop","dph1");
1359 emitcode ("pop","dpl1");
1364 emitcode ("pop","dpx");
1365 emitcode ("pop","dph");
1366 emitcode ("pop","dpl");
1372 /* all other cases just dealloc */
1378 OP_SYMBOL (op)->aop = NULL;
1379 /* if the symbol has a spill */
1381 SPIL_LOC (op)->aop = NULL;
1386 #define DEFAULT_ACC_WARNING 0
1387 static int saveAccWarn = DEFAULT_ACC_WARNING;
1390 /*-----------------------------------------------------------------*/
1391 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
1392 /* clobber the accumulator */
1393 /*-----------------------------------------------------------------*/
1395 aopGetUsesAcc (operand * oper, int offset)
1397 asmop * aop = AOP (oper);
1399 if (offset > (aop->size - 1))
1417 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1428 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1434 /* Error case --- will have been caught already */
1440 /*-------------------------------------------------------------------*/
1441 /* aopGet - for fetching value of the aop */
1443 /* Set saveAcc to NULL if you are sure it is OK to clobber the value */
1444 /* in the accumulator. Set it to the name of a free register */
1445 /* if acc must be preserved; the register will be used to preserve */
1446 /* acc temporarily and to return the result byte. */
1447 /*-------------------------------------------------------------------*/
1449 aopGet (operand * oper,
1455 asmop * aop = AOP (oper);
1457 /* offset is greater than
1459 if (offset > (aop->size - 1) &&
1460 aop->type != AOP_LIT)
1463 /* depending on type */
1471 /* if we need to increment it */
1472 while (offset > aop->coff)
1474 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1478 while (offset < aop->coff)
1480 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1487 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1488 return (dname ? "acc" : "a");
1490 SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1491 return Safe_strdup(buffer);
1494 assert(offset <= 3);
1495 return dptrn[aop->aopu.dptr][offset];
1500 if (aop->type == AOP_DPTR2)
1508 // if (aop->type != AOP_DPTR2)
1510 // if (saveAccWarn) { fprintf(stderr, "saveAcc for DPTR...\n"); }
1511 // emitcode(";", "spanky: saveAcc for DPTR");
1514 emitcode ("xch", "a, %s", saveAcc);
1519 while (offset > aop->coff)
1521 emitcode ("inc", "dptr");
1525 while (offset < aop->coff)
1527 emitcode ("lcall", "__decdptr");
1534 emitcode ("clr", "a");
1535 emitcode ("movc", "a,@a+dptr");
1539 emitcode ("movx", "a,@dptr");
1542 if (aop->type == AOP_DPTR2)
1550 emitcode ("xch", "a, %s", saveAcc);
1551 // if (strcmp(saveAcc, "_ap"))
1553 // emitcode(";", "spiffy: non _ap return from aopGet.");
1558 return (dname ? "acc" : "a");
1561 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1563 SNPRINTF(buffer, sizeof(buffer),
1564 "%s",aop->aopu.aop_immd.aop_immd2);
1568 SNPRINTF(buffer, sizeof(buffer),
1569 "#%s", aop->aopu.aop_immd.aop_immd1);
1575 tsprintf(buffer, sizeof(buffer),
1576 "#!his",aop->aopu.aop_immd.aop_immd1);
1579 tsprintf(buffer, sizeof(buffer),
1580 "#!hihis",aop->aopu.aop_immd.aop_immd1);
1583 tsprintf(buffer, sizeof(buffer),
1584 "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1586 default: /* should not need this (just in case) */
1587 SNPRINTF (buffer, sizeof(buffer),
1589 aop->aopu.aop_immd.aop_immd1,
1595 SNPRINTF (buffer, sizeof(buffer),
1597 aop->aopu.aop_immd.aop_immd1);
1599 return Safe_strdup(buffer);
1602 if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
1604 SNPRINTF (buffer, sizeof(buffer),
1606 aop->aopu.aop_dir, offset * 8);
1610 SNPRINTF (buffer, sizeof(buffer),
1617 SNPRINTF (buffer, sizeof(buffer),
1622 return Safe_strdup(buffer);
1626 return aop->aopu.aop_reg[offset]->dname;
1628 return aop->aopu.aop_reg[offset]->name;
1631 emitcode ("clr", "a");
1632 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1633 emitcode ("rlc", "a");
1634 return (dname ? "acc" : "a");
1637 if (!offset && dname)
1639 return aop->aopu.aop_str[offset];
1642 return aopLiteral (aop->aopu.aop_lit, offset);
1646 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1650 return aop->aopu.aop_str[offset];
1654 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1655 "aopget got unsupported aop->type");
1658 return NULL; // not reached, but makes compiler happy.
1661 /*-----------------------------------------------------------------*/
1662 /* aopPutUsesAcc - indicates ahead of time whether aopPut() will */
1663 /* clobber the accumulator */
1664 /*-----------------------------------------------------------------*/
1666 aopPutUsesAcc (operand * oper, const char *s, int offset)
1668 asmop * aop = AOP (oper);
1670 if (offset > (aop->size - 1))
1680 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1686 return ((aop->paged) || (*s == '@'));
1690 return (!aop->aopu.aop_dir || strcmp(s, aop->aopu.aop_dir));
1698 /* Error case --- will have been caught already */
1704 /*-----------------------------------------------------------------*/
1705 /* aopPut - puts a string for a aop and indicates if acc is in use */
1706 /*-----------------------------------------------------------------*/
1708 aopPut (operand * result, const char *s, int offset)
1710 bool bvolatile = isOperandVolatile (result, FALSE);
1711 bool accuse = FALSE;
1712 asmop * aop = AOP (result);
1714 if (aop->size && offset > (aop->size - 1))
1716 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1717 "aopPut got offset > aop->size");
1721 /* will assign value to value */
1722 /* depending on where it is ofcourse */
1726 MOVA (s); /* read s in case it was volatile */
1731 if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1733 SNPRINTF (buffer, sizeof(buffer),
1735 aop->aopu.aop_dir, offset * 8);
1739 SNPRINTF (buffer, sizeof(buffer),
1741 aop->aopu.aop_dir, offset);
1745 SNPRINTF (buffer, sizeof(buffer),
1750 if (strcmp (buffer, s) || bvolatile)
1752 emitcode ("mov", "%s,%s", buffer, s);
1754 if (!strcmp (buffer, "acc"))
1761 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1762 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1765 strcmp (s, "r0") == 0 ||
1766 strcmp (s, "r1") == 0 ||
1767 strcmp (s, "r2") == 0 ||
1768 strcmp (s, "r3") == 0 ||
1769 strcmp (s, "r4") == 0 ||
1770 strcmp (s, "r5") == 0 ||
1771 strcmp (s, "r6") == 0 ||
1772 strcmp (s, "r7") == 0)
1774 emitcode ("mov", "%s,%s",
1775 aop->aopu.aop_reg[offset]->dname, s);
1779 emitcode ("mov", "%s,%s",
1780 aop->aopu.aop_reg[offset]->name, s);
1786 emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1792 if (aop->type == AOP_DPTR2)
1800 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1801 "aopPut writing to code space");
1805 while (offset > aop->coff)
1808 emitcode ("inc", "dptr");
1811 while (offset < aop->coff)
1814 emitcode ("lcall", "__decdptr");
1819 /* if not in accumulator */
1822 emitcode ("movx", "@dptr,a");
1824 if (aop->type == AOP_DPTR2)
1832 while (offset > aop->coff)
1835 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1837 while (offset < aop->coff)
1840 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1847 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1852 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1854 else if (strcmp (s, "r0") == 0 ||
1855 strcmp (s, "r1") == 0 ||
1856 strcmp (s, "r2") == 0 ||
1857 strcmp (s, "r3") == 0 ||
1858 strcmp (s, "r4") == 0 ||
1859 strcmp (s, "r5") == 0 ||
1860 strcmp (s, "r6") == 0 ||
1861 strcmp (s, "r7") == 0)
1864 SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1865 emitcode ("mov", "@%s,%s",
1866 aop->aopu.aop_ptr->name, buffer);
1870 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1875 if (strcmp (s, "a") == 0)
1876 emitcode ("push", "acc");
1880 emitcode ("push", "acc");
1882 emitcode ("push", s);
1888 /* if not bit variable */
1889 if (!aop->aopu.aop_dir)
1891 /* inefficient: move carry into A and use jz/jnz */
1892 emitcode ("clr", "a");
1893 emitcode ("rlc", "a");
1899 emitcode ("clr", "%s", aop->aopu.aop_dir);
1901 emitcode ("setb", "%s", aop->aopu.aop_dir);
1902 else if (!strcmp (s, "c"))
1903 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1904 else if (strcmp (s, aop->aopu.aop_dir))
1907 /* set C, if a >= 1 */
1908 emitcode ("add", "a,#!constbyte",0xff);
1909 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1916 if (strcmp (aop->aopu.aop_str[offset], s) || bvolatile)
1917 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1923 if (!offset && (strcmp (s, "acc") == 0) && !bvolatile)
1926 if (strcmp (aop->aopu.aop_str[offset], s) && !bvolatile)
1927 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1931 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1932 "aopPut got unsupported aop->type");
1940 /*--------------------------------------------------------------------*/
1941 /* reAdjustPreg - points a register back to where it should (coff==0) */
1942 /*--------------------------------------------------------------------*/
1944 reAdjustPreg (asmop * aop)
1946 if ((aop->coff==0) || (aop->size <= 1))
1954 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1958 if (aop->type == AOP_DPTR2)
1965 emitcode ("lcall", "__decdptr");
1968 if (aop->type == AOP_DPTR2)
1977 /*-----------------------------------------------------------------*/
1978 /* opIsGptr: returns non-zero if the passed operand is */
1979 /* a generic pointer type. */
1980 /*-----------------------------------------------------------------*/
1982 opIsGptr (operand * op)
1984 sym_link *type = operandType (op);
1986 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1993 /*-----------------------------------------------------------------*/
1994 /* getDataSize - get the operand data size */
1995 /*-----------------------------------------------------------------*/
1997 getDataSize (operand * op)
2000 size = AOP_SIZE (op);
2001 if (size == GPTRSIZE)
2003 sym_link *type = operandType (op);
2004 if (IS_GENPTR (type))
2006 /* generic pointer; arithmetic operations
2007 * should ignore the high byte (pointer type).
2015 /*-----------------------------------------------------------------*/
2016 /* outAcc - output Acc */
2017 /*-----------------------------------------------------------------*/
2019 outAcc (operand * result)
2022 size = getDataSize (result);
2025 aopPut (result, "a", 0);
2028 /* unsigned or positive */
2031 aopPut (result, zero, offset++);
2036 /*-----------------------------------------------------------------*/
2037 /* outBitC - output a bit C */
2038 /*-----------------------------------------------------------------*/
2040 outBitC (operand * result)
2042 /* if the result is bit */
2043 if (AOP_TYPE (result) == AOP_CRY)
2045 aopPut (result, "c", 0);
2049 emitcode ("clr", "a");
2050 emitcode ("rlc", "a");
2055 /*-----------------------------------------------------------------*/
2056 /* toBoolean - emit code for orl a,operator(sizeop) */
2057 /*-----------------------------------------------------------------*/
2059 toBoolean (operand * oper)
2061 int size = AOP_SIZE (oper) - 1;
2065 /* The generic part of a generic pointer should
2066 * not participate in it's truth value.
2068 * i.e. 0x10000000 is zero.
2070 if (opIsGptr (oper))
2072 D (emitcode (";", "toBoolean: generic ptr special case."));
2076 _startLazyDPSEvaluation ();
2077 MOVA (aopGet (oper, 0, FALSE, FALSE, NULL));
2078 if (AOP_NEEDSACC (oper) && size && (AOP (oper)->type != AOP_ACC))
2081 emitcode("mov", "b,a");
2084 MOVA (aopGet (oper, offset++, FALSE, FALSE, NULL));
2085 emitcode ("orl", "b,a");
2087 MOVA (aopGet (oper, offset++, FALSE, FALSE, NULL));
2088 emitcode ("orl", "a,b");
2095 emitcode ("orl", "a,%s",
2096 aopGet (oper, offset++, FALSE, FALSE, NULL));
2099 _endLazyDPSEvaluation ();
2103 /*-----------------------------------------------------------------*/
2104 /* genNot - generate code for ! operation */
2105 /*-----------------------------------------------------------------*/
2111 D (emitcode (";", "genNot"));
2113 /* assign asmOps to operand & result */
2114 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2115 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
2117 /* if in bit space then a special case */
2118 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2120 /* if left==result then cpl bit */
2121 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2123 emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2127 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2128 emitcode ("cpl", "c");
2129 outBitC (IC_RESULT (ic));
2134 toBoolean (IC_LEFT (ic));
2136 /* set C, if a == 0 */
2137 tlbl = newiTempLabel (NULL);
2138 emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
2140 outBitC (IC_RESULT (ic));
2143 /* release the aops */
2144 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2145 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2149 /*-----------------------------------------------------------------*/
2150 /* genCpl - generate code for complement */
2151 /*-----------------------------------------------------------------*/
2158 sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
2160 D(emitcode (";", "genCpl"));
2162 /* assign asmOps to operand & result */
2163 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2164 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
2166 /* special case if in bit space */
2167 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2171 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
2172 (SPEC_USIGN (letype) && IS_CHAR (letype)))
2174 /* promotion rules are responsible for this strange result:
2175 bit -> int -> ~int -> bit
2176 uchar -> int -> ~int -> bit
2178 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
2182 tlbl=newiTempLabel(NULL);
2183 l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE, NULL);
2184 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
2185 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
2186 IS_AOP_PREG (IC_LEFT (ic)))
2188 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
2193 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
2196 outBitC (IC_RESULT(ic));
2200 size = AOP_SIZE (IC_RESULT (ic));
2201 _startLazyDPSEvaluation ();
2204 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL);
2206 emitcode ("cpl", "a");
2207 aopPut (IC_RESULT (ic), "a", offset++);
2209 _endLazyDPSEvaluation ();
2213 /* release the aops */
2214 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2215 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2218 /*-----------------------------------------------------------------*/
2219 /* genUminusFloat - unary minus for floating points */
2220 /*-----------------------------------------------------------------*/
2222 genUminusFloat (operand * op, operand * result)
2224 int size, offset = 0;
2227 D (emitcode (";", "genUminusFloat"));
2229 /* for this we just copy and then flip the bit */
2231 _startLazyDPSEvaluation ();
2232 size = AOP_SIZE (op) - 1;
2237 aopGet (op, offset, FALSE, FALSE, NULL),
2242 l = aopGet (op, offset, FALSE, FALSE, NULL);
2245 emitcode ("cpl", "acc.7");
2246 aopPut (result, "a", offset);
2247 _endLazyDPSEvaluation ();
2250 /*-----------------------------------------------------------------*/
2251 /* genUminus - unary minus code generation */
2252 /*-----------------------------------------------------------------*/
2254 genUminus (iCode * ic)
2259 D (emitcode (";", "genUminus"));
2262 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2263 aopOp (IC_RESULT (ic), ic, TRUE, (AOP_TYPE(IC_LEFT (ic)) == AOP_DPTR));
2265 /* if both in bit space then special
2267 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2268 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2271 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2272 emitcode ("cpl", "c");
2273 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2277 optype = operandType (IC_LEFT (ic));
2279 /* if float then do float stuff */
2280 if (IS_FLOAT (optype))
2282 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2286 /* otherwise subtract from zero */
2287 size = AOP_SIZE (IC_LEFT (ic));
2289 _startLazyDPSEvaluation ();
2292 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL);
2293 if (!strcmp (l, "a"))
2297 emitcode ("cpl", "a");
2298 emitcode ("addc", "a,#0");
2304 emitcode ("clr", "a");
2305 emitcode ("subb", "a,%s", l);
2307 aopPut (IC_RESULT (ic), "a", offset++);
2309 _endLazyDPSEvaluation ();
2311 /* if any remaining bytes in the result */
2312 /* we just need to propagate the sign */
2313 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2315 emitcode ("rlc", "a");
2316 emitcode ("subb", "a,acc");
2318 aopPut (IC_RESULT (ic), "a", offset++);
2322 /* release the aops */
2323 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2324 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2327 /*-----------------------------------------------------------------*/
2328 /* savermask - saves registers in the mask */
2329 /*-----------------------------------------------------------------*/
2330 static void savermask(bitVect *rs_mask)
2333 if (options.useXstack)
2335 if (bitVectBitValue (rs_mask, R0_IDX))
2336 emitcode ("mov", "b,r0");
2337 emitcode ("mov", "r0,%s", spname);
2338 for (i = 0; i < ds390_nRegs; i++)
2340 if (bitVectBitValue (rs_mask, i))
2343 emitcode ("mov", "a,b");
2345 emitcode ("mov", "a,%s", REG_WITH_INDEX (i)->name);
2346 emitcode ("movx", "@r0,a");
2347 emitcode ("inc", "r0");
2350 emitcode ("mov", "%s,r0", spname);
2351 if (bitVectBitValue (rs_mask, R0_IDX))
2352 emitcode ("mov", "r0,b");
2356 bool bits_pushed = FALSE;
2357 for (i = 0; i < ds390_nRegs; i++)
2359 if (bitVectBitValue (rs_mask, i))
2361 bits_pushed = pushReg (i, bits_pushed);
2367 /*-----------------------------------------------------------------*/
2368 /* saveRegisters - will look for a call and save the registers */
2369 /*-----------------------------------------------------------------*/
2371 saveRegisters (iCode * lic)
2377 for (ic = lic; ic; ic = ic->next)
2378 if (ic->op == CALL || ic->op == PCALL)
2383 fprintf (stderr, "found parameter push with no function call\n");
2387 /* if the registers have been saved already or don't need to be then
2390 || (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))) && !TARGET_IS_DS400) )
2393 /* special case if DPTR alive across a function call then must save it
2394 even though callee saves */
2395 if (IS_SYMOP(IC_LEFT(ic)) &&
2396 IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type))
2399 rsave = newBitVect(ic->rMask->size);
2400 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2401 if (bitVectBitValue(ic->rMask,i))
2402 rsave = bitVectSetBit(rsave,i);
2404 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2408 /* save the registers in use at this time but skip the
2409 ones for the result */
2410 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2411 ds390_rUmaskForOp (IC_RESULT(ic)));
2417 /*-----------------------------------------------------------------*/
2418 /* usavermask - restore registers with mask */
2419 /*-----------------------------------------------------------------*/
2420 static void unsavermask(bitVect *rs_mask)
2423 if (options.useXstack) {
2424 emitcode ("mov", "r0,%s", spname);
2425 for (i = ds390_nRegs; i >= 0; i--)
2427 if (bitVectBitValue (rs_mask, i))
2429 regs * reg = REG_WITH_INDEX (i);
2430 emitcode ("dec", "r0");
2431 emitcode ("movx", "a,@r0");
2434 emitcode ("push", "acc");
2438 emitcode ("mov", "%s,a", reg->name);
2442 emitcode ("mov", "%s,r0", spname);
2443 if (bitVectBitValue (rs_mask, R0_IDX))
2445 emitcode ("pop", "ar0");
2450 bool bits_popped = FALSE;
2451 for (i = ds390_nRegs; i >= 0; i--)
2453 if (bitVectBitValue (rs_mask, i))
2455 bits_popped = popReg (i, bits_popped);
2461 /*-----------------------------------------------------------------*/
2462 /* unsaveRegisters - pop the pushed registers */
2463 /*-----------------------------------------------------------------*/
2465 unsaveRegisters (iCode * ic)
2469 if (IS_SYMOP(IC_LEFT (ic)) &&
2470 IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2472 rsave = newBitVect(ic->rMask->size);
2473 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2474 if (bitVectBitValue(ic->rMask,i))
2475 rsave = bitVectSetBit(rsave,i);
2477 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2479 /* restore the registers in use at this time but skip the
2480 ones for the result */
2481 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2482 ds390_rUmaskForOp (IC_RESULT(ic)));
2488 /*-----------------------------------------------------------------*/
2490 /*-----------------------------------------------------------------*/
2492 pushSide (operand * oper, int size)
2495 _startLazyDPSEvaluation ();
2498 char *l = aopGet (oper, offset++, FALSE, TRUE, NULL);
2499 if (AOP_TYPE (oper) != AOP_REG &&
2500 AOP_TYPE (oper) != AOP_DIR &&
2504 emitcode ("push", "acc");
2508 emitcode ("push", "%s", l);
2511 _endLazyDPSEvaluation ();
2514 /*-----------------------------------------------------------------*/
2515 /* assignResultValue - also indicates if acc is in use afterwards */
2516 /*-----------------------------------------------------------------*/
2518 assignResultValue (operand * oper, operand * func)
2521 unsigned size = AOP_SIZE (oper);
2522 bool accuse = FALSE;
2523 bool pushedA = FALSE;
2525 if (func && IS_BIT (OP_SYM_ETYPE (func)))
2531 if (size == fReturnSizeDS390)
2533 /* I don't think this case can ever happen... */
2534 /* ACC is the last part of this. If writing the result
2535 * uses ACC, we must preserve it.
2537 if (AOP_NEEDSACC(oper))
2539 emitcode(";", "assignResultValue special case for ACC.");
2540 emitcode("push", "acc");
2546 _startLazyDPSEvaluation ();
2549 accuse |= aopPut (oper, fReturn[offset], offset);
2552 _endLazyDPSEvaluation ();
2556 emitcode ("pop", "acc");
2557 accuse |= aopPut (oper, "a", offset);
2563 /*-----------------------------------------------------------------*/
2564 /* genXpush - pushes onto the external stack */
2565 /*-----------------------------------------------------------------*/
2567 genXpush (iCode * ic)
2569 asmop *aop = newAsmop (0);
2571 int size, offset = 0;
2573 D (emitcode (";", "genXpush"));
2575 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2576 r = getFreePtr (ic, &aop, FALSE);
2578 size = AOP_SIZE (IC_LEFT (ic));
2582 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
2583 emitcode ("mov", "%s,_spx", r->name);
2584 emitcode ("inc", "_spx"); // allocate space first
2585 emitcode ("movx", "@%s,a", r->name);
2589 // allocate space first
2590 emitcode ("mov", "%s,_spx", r->name);
2592 emitcode ("add", "a,#%d", size);
2593 emitcode ("mov", "_spx,a");
2595 _startLazyDPSEvaluation ();
2598 MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE, NULL));
2599 emitcode ("movx", "@%s,a", r->name);
2600 emitcode ("inc", "%s", r->name);
2602 _endLazyDPSEvaluation ();
2605 freeAsmop (NULL, aop, ic, TRUE);
2606 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2609 /*-----------------------------------------------------------------*/
2610 /* genIpush - generate code for pushing this gets a little complex */
2611 /*-----------------------------------------------------------------*/
2613 genIpush (iCode * ic)
2615 int size, offset = 0;
2619 D (emitcode (";", "genIpush"));
2621 /* if this is not a parm push : ie. it is spill push
2622 and spill push is always done on the local stack */
2626 /* and the item is spilt then do nothing */
2627 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2630 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2631 size = AOP_SIZE (IC_LEFT (ic));
2632 /* push it on the stack */
2633 _startLazyDPSEvaluation ();
2636 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE, NULL);
2642 emitcode ("push", "%s", l);
2644 _endLazyDPSEvaluation ();
2648 /* this is a parameter push: in this case we call
2649 the routine to find the call and save those
2650 registers that need to be saved */
2653 /* if use external stack then call the external
2654 stack pushing routine */
2655 if (options.useXstack)
2661 /* then do the push */
2662 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2664 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2665 size = AOP_SIZE (IC_LEFT (ic));
2667 _startLazyDPSEvaluation ();
2670 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE, NULL);
2671 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2672 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2675 if (strcmp (l, prev) || *l == '@')
2677 emitcode ("push", "acc");
2681 emitcode ("push", "%s", l);
2685 _endLazyDPSEvaluation ();
2687 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2690 /*-----------------------------------------------------------------*/
2691 /* genIpop - recover the registers: can happen only for spilling */
2692 /*-----------------------------------------------------------------*/
2694 genIpop (iCode * ic)
2698 D (emitcode (";", "genIpop"));
2700 /* if the temp was not pushed then */
2701 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2704 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2705 size = AOP_SIZE (IC_LEFT (ic));
2706 offset = (size - 1);
2707 _startLazyDPSEvaluation ();
2710 emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2711 FALSE, TRUE, NULL));
2713 _endLazyDPSEvaluation ();
2715 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2718 /*-----------------------------------------------------------------*/
2719 /* saveRBank - saves an entire register bank on the stack */
2720 /*-----------------------------------------------------------------*/
2722 saveRBank (int bank, iCode * ic, bool pushPsw)
2725 int count = 8 + (ds390_nBitRegs/8) + (pushPsw ? 1 : 0);
2729 if (options.useXstack)
2733 /* Assume r0 is available for use. */
2734 r = REG_WITH_INDEX (R0_IDX);;
2739 r = getFreePtr (ic, &aop, FALSE);
2741 // allocate space first
2742 emitcode ("mov", "%s,_spx", r->name);
2744 emitcode ("add", "a,#%d", count);
2745 emitcode ("mov", "_spx,a");
2748 for (i = 0; i < 8; i++) /* only R0-R7 needs saving */
2750 if (options.useXstack)
2752 emitcode ("mov", "a,(%s+%d)",
2753 regs390[i].base, 8 * bank + regs390[i].offset);
2754 emitcode ("movx", "@%s,a", r->name);
2756 emitcode ("inc", "%s", r->name);
2759 emitcode ("push", "(%s+%d)",
2760 regs390[i].base, 8 * bank + regs390[i].offset);
2763 if (ds390_nBitRegs > 0)
2765 if (options.useXstack)
2767 emitcode ("mov", "a,bits");
2768 emitcode ("movx", "@%s,a", r->name);
2770 emitcode ("inc", "%s", r->name);
2774 emitcode ("push", "bits");
2781 if (options.useXstack)
2783 emitcode ("mov", "a,psw");
2784 emitcode ("movx", "@%s,a", r->name);
2788 emitcode ("push", "psw");
2791 emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2796 freeAsmop (NULL, aop, ic, TRUE);
2805 /*-----------------------------------------------------------------*/
2806 /* unsaveRBank - restores the register bank from stack */
2807 /*-----------------------------------------------------------------*/
2809 unsaveRBank (int bank, iCode * ic, bool popPsw)
2815 if (options.useXstack)
2819 /* Assume r0 is available for use. */
2820 r = REG_WITH_INDEX (R0_IDX);;
2825 r = getFreePtr (ic, &aop, FALSE);
2827 emitcode ("mov", "%s,_spx", r->name);
2832 if (options.useXstack)
2834 emitcode ("dec", "%s", r->name);
2835 emitcode ("movx", "a,@%s", r->name);
2836 emitcode ("mov", "psw,a");
2840 emitcode ("pop", "psw");
2844 if (ds390_nBitRegs > 0)
2846 if (options.useXstack)
2848 emitcode ("dec", "%s", r->name);
2849 emitcode ("movx", "a,@%s", r->name);
2850 emitcode ("mov", "bits,a");
2854 emitcode ("pop", "bits");
2858 for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2860 if (options.useXstack)
2862 emitcode ("dec", "%s", r->name);
2863 emitcode ("movx", "a,@%s", r->name);
2864 emitcode ("mov", "(%s+%d),a",
2865 regs390[i].base, 8 * bank + regs390[i].offset);
2869 emitcode ("pop", "(%s+%d)",
2870 regs390[i].base, 8 * bank + regs390[i].offset);
2874 if (options.useXstack)
2876 emitcode ("mov", "_spx,%s", r->name);
2881 freeAsmop (NULL, aop, ic, TRUE);
2885 /*-----------------------------------------------------------------*/
2886 /* genSend - gen code for SEND */
2887 /*-----------------------------------------------------------------*/
2888 static void genSend(set *sendSet)
2893 static int rb1_count = 0;
2895 /* first we do all bit parameters */
2896 for (sic = setFirstItem (sendSet); sic;
2897 sic = setNextItem (sendSet))
2899 if (sic->argreg > 12)
2901 int bit = sic->argreg-13;
2903 aopOp (IC_LEFT (sic), sic, FALSE,
2904 (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2906 /* if left is a literal then
2907 we know what the value is */
2908 if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2910 if (((int) operandLitValue (IC_LEFT (sic))))
2911 emitcode ("setb", "b[%d]", bit);
2913 emitcode ("clr", "b[%d]", bit);
2915 else if (AOP_TYPE (IC_LEFT (sic)) == AOP_CRY)
2917 char *l = AOP (IC_LEFT (sic))->aopu.aop_dir;
2918 if (strcmp (l, "c"))
2919 emitcode ("mov", "c,%s", l);
2920 emitcode ("mov", "b[%d],c", bit);
2925 toBoolean (IC_LEFT (sic));
2926 /* set C, if a >= 1 */
2927 emitcode ("add", "a,#0xff");
2928 emitcode ("mov", "b[%d],c", bit);
2933 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2939 saveRegisters (setFirstItem (sendSet));
2940 emitcode ("mov", "bits,b");
2943 /* then we do all other parameters */
2944 for (sic = setFirstItem (sendSet); sic;
2945 sic = setNextItem (sendSet))
2947 if (sic->argreg <= 12)
2949 int size, offset = 0;
2951 size = getSize (operandType (IC_LEFT (sic)));
2952 D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2953 if (sendCount == 0) { /* first parameter */
2954 // we know that dpl(hxb) is the result, so
2956 _startLazyDPSEvaluation ();
2958 aopOp (IC_LEFT (sic), sic, FALSE,
2959 (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2961 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2965 char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE, NULL);
2966 if (strcmp (l, fReturn[offset]))
2968 emitcode ("mov", "%s,%s", fReturn[offset], l);
2972 _endLazyDPSEvaluation ();
2973 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2975 } else { /* if more parameter in registers */
2976 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2978 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (IC_LEFT (sic), offset++,
2979 FALSE, FALSE, NULL));
2981 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2989 adjustEsp(const char *reg)
2991 emitcode ("anl","%s,#3", reg);
2992 if (TARGET_IS_DS400)
2994 emitcode ("orl","%s,#!constbyte",
2996 (options.stack_loc >> 8) & 0xff);
3000 /*-----------------------------------------------------------------*/
3001 /* selectRegBank - emit code to select the register bank */
3002 /*-----------------------------------------------------------------*/
3004 selectRegBank (short bank, bool keepFlags)
3006 /* if f.e. result is in carry */
3009 emitcode ("anl", "psw,#0xE7");
3011 emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
3015 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
3019 /*-----------------------------------------------------------------*/
3020 /* genCall - generates a call statement */
3021 /*-----------------------------------------------------------------*/
3023 genCall (iCode * ic)
3027 bool restoreBank = FALSE;
3028 bool swapBanks = FALSE;
3029 bool accuse = FALSE;
3030 bool accPushed = FALSE;
3031 bool resultInF0 = FALSE;
3032 bool assignResultGenerated = FALSE;
3034 D (emitcode (";", "genCall"));
3036 /* if we are calling a not _naked function that is not using
3037 the same register bank then we need to save the
3038 destination registers on the stack */
3039 dtype = operandType (IC_LEFT (ic));
3040 etype = getSpec(dtype);
3041 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
3042 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
3043 IFFUNC_ISISR (currFunc->type))
3047 /* This is unexpected; the bank should have been saved in
3050 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
3056 /* if caller saves & we have not saved then */
3060 /* if send set is not empty then assign */
3061 /* We've saved all the registers we care about;
3062 * therefore, we may clobber any register not used
3063 * in the calling convention (i.e. anything not in
3068 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
3069 genSend(reverseSet(_G.sendSet));
3071 genSend(_G.sendSet);
3078 emitcode ("mov", "psw,#!constbyte",
3079 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3083 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
3084 OP_SYMBOL (IC_LEFT (ic))->rname :
3085 OP_SYMBOL (IC_LEFT (ic))->name));
3089 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
3092 /* if we need assign a result value */
3093 if ((IS_ITEMP (IC_RESULT (ic)) &&
3094 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3095 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3096 OP_SYMBOL (IC_RESULT (ic))->accuse ||
3097 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3098 IS_TRUE_SYMOP (IC_RESULT (ic)))
3100 if (isOperandInFarSpace (IC_RESULT (ic))
3101 && getSize (operandType (IC_RESULT (ic))) <= 2)
3103 int size = getSize (operandType (IC_RESULT (ic)));
3104 bool pushedB = FALSE;
3106 /* Special case for 1 or 2 byte return in far space. */
3111 emitcode ("mov", "b,%s", fReturn[1]);
3115 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
3120 aopPut (IC_RESULT (ic), "a", 0);
3124 aopPut (IC_RESULT (ic), "b", 1);
3126 assignResultGenerated = TRUE;
3127 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3131 bool pushedB = pushB ();
3132 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
3135 accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3136 assignResultGenerated = TRUE;
3137 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3141 /* adjust the stack for parameters if required */
3145 if (options.stack10bit) {
3146 if (ic->parmBytes <= 10) {
3147 emitcode(";","stack adjustment for parms");
3148 for (i=0; i < ic->parmBytes ; i++) {
3149 emitcode("pop","acc");
3153 emitcode ("clr","c");
3154 emitcode ("mov","a,sp");
3155 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
3156 emitcode ("mov","sp,a");
3157 emitcode ("mov","a,esp");
3159 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
3160 emitcode ("mov","esp,a");
3164 if (ic->parmBytes > 3)
3168 emitcode ("push", "acc");
3171 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3172 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3173 !assignResultGenerated)
3175 emitcode ("mov", "F0,c");
3179 emitcode ("mov", "a,%s", spname);
3180 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
3181 emitcode ("mov", "%s,a", spname);
3183 /* unsaveRegisters from xstack needs acc, but */
3184 /* unsaveRegisters from stack needs this popped */
3185 if (accPushed && !options.useXstack)
3187 emitcode ("pop", "acc");
3192 for (i = 0; i < ic->parmBytes; i++)
3193 emitcode ("dec", "%s", spname);
3197 /* if we had saved some registers then unsave them */
3198 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3200 if (accuse && !accPushed && options.useXstack)
3202 /* xstack needs acc, but doesn't touch normal stack */
3203 emitcode ("push", "acc");
3206 unsaveRegisters (ic);
3209 /* if register bank was saved then pop them */
3211 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
3213 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
3216 emitcode ("mov", "c,F0");
3218 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
3219 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3220 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3224 emitcode ("pop", "acc");
3227 /*-----------------------------------------------------------------*/
3228 /* genPcall - generates a call by pointer statement */
3229 /*-----------------------------------------------------------------*/
3231 genPcall (iCode * ic)
3235 symbol *rlbl = newiTempLabel (NULL);
3236 bool restoreBank=FALSE;
3237 bool resultInF0 = FALSE;
3239 D (emitcode (";", "genPcall"));
3241 dtype = operandType (IC_LEFT (ic))->next;
3242 etype = getSpec(dtype);
3243 /* if caller saves & we have not saved then */
3247 /* if we are calling a not _naked function that is not using
3248 the same register bank then we need to save the
3249 destination registers on the stack */
3250 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
3251 IFFUNC_ISISR (currFunc->type) &&
3252 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
3253 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3257 /* push the return address on to the stack */
3258 emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
3259 emitcode ("push", "acc");
3260 emitcode ("mov", "a,#!hil", (rlbl->key + 100));
3261 emitcode ("push", "acc");
3263 if (options.model == MODEL_FLAT24)
3265 emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
3266 emitcode ("push", "acc");
3269 /* now push the calling address */
3270 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3272 pushSide (IC_LEFT (ic), FPTRSIZE);
3274 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3276 /* if send set is not empty the assign */
3279 genSend(reverseSet(_G.sendSet));
3284 emitcode ("ret", "");
3288 /* if we need assign a result value */
3289 if ((IS_ITEMP (IC_RESULT (ic)) &&
3290 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3291 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3292 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3293 IS_TRUE_SYMOP (IC_RESULT (ic)))
3297 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
3300 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3302 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3305 /* adjust the stack for parameters if required */
3309 if (options.stack10bit) {
3310 if (ic->parmBytes <= 10) {
3311 emitcode(";","stack adjustment for parms");
3312 for (i=0; i < ic->parmBytes ; i++) {
3313 emitcode("pop","acc");
3316 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3317 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3319 emitcode ("mov", "F0,c");
3324 emitcode ("clr","c");
3325 emitcode ("mov","a,sp");
3326 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
3327 emitcode ("mov","sp,a");
3328 emitcode ("mov","a,esp");
3330 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
3331 emitcode ("mov","esp,a");
3335 if (ic->parmBytes > 3) {
3336 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3337 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3339 emitcode ("mov", "F0,c");
3343 emitcode ("mov", "a,%s", spname);
3344 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
3345 emitcode ("mov", "%s,a", spname);
3348 for (i = 0; i < ic->parmBytes; i++)
3349 emitcode ("dec", "%s", spname);
3352 /* if register bank was saved then unsave them */
3354 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3356 /* if we had saved some registers then unsave them */
3358 unsaveRegisters (ic);
3360 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3363 emitcode ("mov", "c,F0");
3365 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
3366 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3367 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3371 /*-----------------------------------------------------------------*/
3372 /* resultRemat - result is rematerializable */
3373 /*-----------------------------------------------------------------*/
3375 resultRemat (iCode * ic)
3377 if (SKIP_IC (ic) || ic->op == IFX)
3380 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3382 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3383 if (sym->remat && !POINTER_SET (ic))
3390 #if defined(__BORLANDC__) || defined(_MSC_VER)
3391 #define STRCASECMP stricmp
3393 #define STRCASECMP strcasecmp
3396 /*-----------------------------------------------------------------*/
3397 /* inExcludeList - return 1 if the string is in exclude Reg list */
3398 /*-----------------------------------------------------------------*/
3400 regsCmp(void *p1, void *p2)
3402 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3406 inExcludeList (char *s)
3408 const char *p = setFirstItem(options.excludeRegsSet);
3410 if (p == NULL || STRCASECMP(p, "none") == 0)
3414 return isinSetWith(options.excludeRegsSet, s, regsCmp);
3417 /*-----------------------------------------------------------------*/
3418 /* genFunction - generated code for function entry */
3419 /*-----------------------------------------------------------------*/
3421 genFunction (iCode * ic)
3423 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3425 bool switchedPSW = FALSE;
3426 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3428 D (emitcode (";", "genFunction"));
3431 /* create the function header */
3432 emitcode (";", "-----------------------------------------");
3433 emitcode (";", " function %s", sym->name);
3434 emitcode (";", "-----------------------------------------");
3436 emitcode ("", "%s:", sym->rname);
3437 ftype = operandType (IC_LEFT (ic));
3438 _G.currentFunc = sym;
3440 if (IFFUNC_ISNAKED(ftype))
3442 emitcode(";", "naked function: no prologue.");
3446 if (options.stack_probe)
3447 emitcode ("lcall","__stack_probe");
3449 /* here we need to generate the equates for the
3450 register bank if required */
3451 if (FUNC_REGBANK (ftype) != rbank)
3455 rbank = FUNC_REGBANK (ftype);
3456 for (i = 0; i < ds390_nRegs; i++)
3458 if (regs390[i].print) {
3459 if (strcmp (regs390[i].base, "0") == 0)
3460 emitcode ("", "%s !equ !constbyte",
3462 8 * rbank + regs390[i].offset);
3464 emitcode ("", "%s !equ %s + !constbyte",
3467 8 * rbank + regs390[i].offset);
3472 /* if this is an interrupt service routine then
3473 save acc, b, dpl, dph */
3474 if (IFFUNC_ISISR (sym->type))
3476 if (!inExcludeList ("acc"))
3477 emitcode ("push", "acc");
3478 if (!inExcludeList ("b"))
3479 emitcode ("push", "b");
3480 if (!inExcludeList ("dpl"))
3481 emitcode ("push", "dpl");
3482 if (!inExcludeList ("dph"))
3483 emitcode ("push", "dph");
3484 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3486 emitcode ("push", "dpx");
3487 /* Make sure we're using standard DPTR */
3488 emitcode ("push", "dps");
3489 emitcode ("mov", "dps,#0");
3490 if (options.stack10bit)
3492 /* This ISR could conceivably use DPTR2. Better save it. */
3493 emitcode ("push", "dpl1");
3494 emitcode ("push", "dph1");
3495 emitcode ("push", "dpx1");
3496 emitcode ("push", DP2_RESULT_REG);
3499 /* if this isr has no bank i.e. is going to
3500 run with bank 0 , then we need to save more
3502 if (!FUNC_REGBANK (sym->type))
3506 /* if this function does not call any other
3507 function then we can be economical and
3508 save only those registers that are used */
3509 if (!IFFUNC_HASFCALL(sym->type))
3511 /* if any registers used */
3514 bool bits_pushed = FALSE;
3515 /* save the registers used */
3516 for (i = 0; i < sym->regsUsed->size; i++)
3518 if (bitVectBitValue (sym->regsUsed, i))
3519 bits_pushed = pushReg (i, bits_pushed);
3525 /* this function has a function call. We cannot
3526 determine register usage so we will have to push the
3528 saveRBank (0, ic, FALSE);
3529 if (options.parms_in_bank1) {
3530 for (i=0; i < 8 ; i++ ) {
3531 emitcode ("push","%s",rb1regs[i]);
3538 /* This ISR uses a non-zero bank.
3540 * We assume that the bank is available for our
3543 * However, if this ISR calls a function which uses some
3544 * other bank, we must save that bank entirely.
3546 unsigned long banksToSave = 0;
3548 if (IFFUNC_HASFCALL(sym->type))
3551 #define MAX_REGISTER_BANKS 4
3556 for (i = ic; i; i = i->next)
3558 if (i->op == ENDFUNCTION)
3560 /* we got to the end OK. */
3568 dtype = operandType (IC_LEFT(i));
3570 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3572 /* Mark this bank for saving. */
3573 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3575 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3579 banksToSave |= (1 << FUNC_REGBANK(dtype));
3582 /* And note that we don't need to do it in
3590 /* This is a mess; we have no idea what
3591 * register bank the called function might
3594 * The only thing I can think of to do is
3595 * throw a warning and hope.
3597 werror(W_FUNCPTR_IN_USING_ISR);
3601 if (banksToSave && options.useXstack)
3603 /* Since we aren't passing it an ic,
3604 * saveRBank will assume r0 is available to abuse.
3606 * So switch to our (trashable) bank now, so
3607 * the caller's R0 isn't trashed.
3609 emitcode ("push", "psw");
3610 emitcode ("mov", "psw,#!constbyte",
3611 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3615 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3617 if (banksToSave & (1 << ix))
3619 saveRBank(ix, NULL, FALSE);
3623 // TODO: this needs a closer look
3624 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3629 /* if callee-save to be used for this function
3630 then save the registers being used in this function */
3631 if (IFFUNC_CALLEESAVES(sym->type))
3635 /* if any registers used */
3638 bool bits_pushed = FALSE;
3639 /* save the registers used */
3640 for (i = 0; i < sym->regsUsed->size; i++)
3642 if (bitVectBitValue (sym->regsUsed, i))
3644 bits_pushed = pushReg (i, bits_pushed);
3652 /* set the register bank to the desired value */
3653 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3656 emitcode ("push", "psw");
3657 emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3661 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3662 if (options.stack10bit) {
3663 emitcode ("push","_bpx");
3664 emitcode ("push","_bpx+1");
3665 emitcode ("mov","_bpx,%s",spname);
3666 emitcode ("mov","_bpx+1,esp");
3667 adjustEsp("_bpx+1");
3669 if (options.useXstack)
3671 emitcode ("mov", "r0,%s", spname);
3672 emitcode ("mov", "a,_bp");
3673 emitcode ("movx", "@r0,a");
3674 emitcode ("inc", "%s", spname);
3676 /* set up the stack */
3677 emitcode ("push", "_bp"); /* save the callers stack */
3679 emitcode ("mov", "_bp,%s", spname);
3683 /* adjust the stack for the function */
3686 if (options.stack10bit) {
3687 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
3688 assert (sym->recvSize <= 4);
3689 if (sym->stack <= 8) {
3690 while (i--) emitcode ("push","acc");
3693 emitcode ("mov","a,sp");
3694 emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3695 emitcode ("mov","sp,a");
3696 emitcode ("mov","a,esp");
3698 emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3699 emitcode ("mov","esp,a");
3704 werror (W_STACK_OVERFLOW, sym->name);
3706 if (i > 3 && sym->recvSize < 4) {
3708 emitcode ("mov", "a,sp");
3709 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3710 emitcode ("mov", "sp,a");
3714 emitcode ("inc", "sp");
3721 emitcode ("mov", "a,_spx");
3722 emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3723 emitcode ("mov", "_spx,a");
3726 /* if critical function then turn interrupts off */
3727 if (IFFUNC_ISCRITICAL (ftype))
3729 symbol *tlbl = newiTempLabel (NULL);
3730 emitcode ("setb", "c");
3731 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3732 emitcode ("clr", "c");
3734 emitcode ("push", "psw"); /* save old ea via c in psw */
3738 /*-----------------------------------------------------------------*/
3739 /* genEndFunction - generates epilogue for functions */
3740 /*-----------------------------------------------------------------*/
3742 genEndFunction (iCode * ic)
3744 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3745 lineNode *lnp = lineCurr;
3747 bitVect *regsUsedPrologue;
3748 bitVect *regsUnneeded;
3751 D (emitcode (";", "genEndFunction"));
3753 _G.currentFunc = NULL;
3754 if (IFFUNC_ISNAKED(sym->type))
3756 emitcode(";", "naked function: no epilogue.");
3757 if (options.debug && currFunc)
3758 debugFile->writeEndFunction (currFunc, ic, 0);
3762 if (IFFUNC_ISCRITICAL (sym->type))
3764 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3766 emitcode ("rlc", "a"); /* save c in a */
3767 emitcode ("pop", "psw"); /* restore ea via c in psw */
3768 emitcode ("mov", "ea,c");
3769 emitcode ("rrc", "a"); /* restore c from a */
3773 emitcode ("pop", "psw"); /* restore ea via c in psw */
3774 emitcode ("mov", "ea,c");
3778 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3779 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3781 if (options.stack10bit) {
3783 emitcode ("mov", "sp,_bpx", spname);
3784 emitcode ("mov", "esp,_bpx+1", spname);
3787 emitcode ("mov", "%s,_bp", spname);
3791 /* if use external stack but some variables were
3792 added to the local stack then decrement the
3794 if (options.useXstack && sym->stack) {
3795 emitcode ("mov", "a,sp");
3796 emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3797 emitcode ("mov", "sp,a");
3801 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3802 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3804 if (options.useXstack) {
3805 emitcode ("mov", "r0,%s", spname);
3806 emitcode ("movx", "a,@r0");
3807 emitcode ("mov", "_bp,a");
3808 emitcode ("dec", "%s", spname);
3810 if (options.stack10bit) {
3811 emitcode ("pop", "_bpx+1");
3812 emitcode ("pop", "_bpx");
3814 emitcode ("pop", "_bp");
3819 /* restore the register bank */
3820 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3822 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3823 || !options.useXstack)
3825 /* Special case of ISR using non-zero bank with useXstack
3828 emitcode ("pop", "psw");
3832 if (IFFUNC_ISISR (sym->type))
3835 /* now we need to restore the registers */
3836 /* if this isr has no bank i.e. is going to
3837 run with bank 0 , then we need to save more
3839 if (!FUNC_REGBANK (sym->type))
3842 /* if this function does not call any other
3843 function then we can be economical and
3844 save only those registers that are used */
3845 if (!IFFUNC_HASFCALL(sym->type))
3847 /* if any registers used */
3850 bool bits_popped = FALSE;
3851 /* save the registers used */
3852 for (i = sym->regsUsed->size; i >= 0; i--)
3854 if (bitVectBitValue (sym->regsUsed, i))
3855 bits_popped = popReg (i, bits_popped);
3861 /* this function has a function call. We cannot
3862 determine register usage so we will have to pop the
3864 if (options.parms_in_bank1) {
3865 for (i = 7 ; i >= 0 ; i-- ) {
3866 emitcode ("pop","%s",rb1regs[i]);
3869 unsaveRBank (0, ic, FALSE);
3874 /* This ISR uses a non-zero bank.
3876 * Restore any register banks saved by genFunction
3879 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3882 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3884 if (savedBanks & (1 << ix))
3886 unsaveRBank(ix, NULL, FALSE);
3890 if (options.useXstack)
3892 /* Restore bank AFTER calling unsaveRBank,
3893 * since it can trash r0.
3895 emitcode ("pop", "psw");
3899 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3901 if (options.stack10bit)
3903 emitcode ("pop", DP2_RESULT_REG);
3904 emitcode ("pop", "dpx1");
3905 emitcode ("pop", "dph1");
3906 emitcode ("pop", "dpl1");
3908 emitcode ("pop", "dps");
3909 emitcode ("pop", "dpx");
3911 if (!inExcludeList ("dph"))
3912 emitcode ("pop", "dph");
3913 if (!inExcludeList ("dpl"))
3914 emitcode ("pop", "dpl");
3915 if (!inExcludeList ("b"))
3916 emitcode ("pop", "b");
3917 if (!inExcludeList ("acc"))
3918 emitcode ("pop", "acc");
3920 /* if debug then send end of function */
3921 if (options.debug && currFunc)
3923 debugFile->writeEndFunction (currFunc, ic, 1);
3926 emitcode ("reti", "");
3930 if (IFFUNC_CALLEESAVES(sym->type))
3934 /* if any registers used */
3937 /* save the registers used */
3938 for (i = sym->regsUsed->size; i >= 0; i--)
3940 if (bitVectBitValue (sym->regsUsed, i))
3941 emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
3946 /* if debug then send end of function */
3947 if (options.debug && currFunc)
3949 debugFile->writeEndFunction (currFunc, ic, 1);
3952 emitcode ("ret", "");
3955 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3958 /* If this was an interrupt handler using bank 0 that called another */
3959 /* function, then all registers must be saved; nothing to optimized. */
3960 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3961 && !FUNC_REGBANK(sym->type))
3964 /* There are no push/pops to optimize if not callee-saves or ISR */
3965 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3968 /* If there were stack parameters, we cannot optimize without also */
3969 /* fixing all of the stack offsets; this is too dificult to consider. */
3970 if (FUNC_HASSTACKPARM(sym->type))
3973 /* Compute the registers actually used */
3974 regsUsed = newBitVect (ds390_nRegs);
3975 regsUsedPrologue = newBitVect (ds390_nRegs);
3978 if (lnp->ic && lnp->ic->op == FUNCTION)
3979 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3981 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3983 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3984 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3991 if (bitVectBitValue (regsUsedPrologue, DPS_IDX)
3992 && !bitVectBitValue (regsUsed, DPS_IDX))
3994 bitVectUnSetBit (regsUsedPrologue, DPS_IDX);
3997 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3998 && !bitVectBitValue (regsUsed, CND_IDX))
4000 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
4001 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
4002 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
4003 bitVectUnSetBit (regsUsed, CND_IDX);
4006 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
4008 /* If this was an interrupt handler that called another function */
4009 /* function, then assume working registers may be modified by it. */
4010 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
4012 regsUsed = bitVectSetBit (regsUsed, AP_IDX);
4013 regsUsed = bitVectSetBit (regsUsed, DPX1_IDX);
4014 regsUsed = bitVectSetBit (regsUsed, DPL1_IDX);
4015 regsUsed = bitVectSetBit (regsUsed, DPH1_IDX);
4016 regsUsed = bitVectSetBit (regsUsed, DPX_IDX);
4017 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
4018 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
4019 regsUsed = bitVectSetBit (regsUsed, DPS_IDX);
4020 regsUsed = bitVectSetBit (regsUsed, B_IDX);
4021 regsUsed = bitVectSetBit (regsUsed, A_IDX);
4022 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
4025 /* Remove the unneeded push/pops */
4026 regsUnneeded = newBitVect (ds390_nRegs);
4029 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
4031 if (!strncmp(lnp->line, "push", 4))
4033 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
4034 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4036 connectLine (lnp->prev, lnp->next);
4037 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4040 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
4042 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
4043 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4045 connectLine (lnp->prev, lnp->next);
4046 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4053 for (idx = 0; idx < regsUnneeded->size; idx++)
4054 if (bitVectBitValue (regsUnneeded, idx))
4055 emitcode (";", "eliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
4057 freeBitVect (regsUnneeded);
4058 freeBitVect (regsUsed);
4059 freeBitVect (regsUsedPrologue);
4062 /*-----------------------------------------------------------------*/
4063 /* genJavaNativeRet - generate code for return JavaNative */
4064 /*-----------------------------------------------------------------*/
4065 static void genJavaNativeRet(iCode *ic)
4069 aopOp (IC_LEFT (ic), ic, FALSE,
4070 AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
4071 size = AOP_SIZE (IC_LEFT (ic));
4075 /* it is assigned to GPR0-R3 then push them */
4076 if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
4077 aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
4078 for (i = 0 ; i < size ; i++ ) {
4079 emitcode ("push","%s",
4080 aopGet(IC_LEFT(ic),i,FALSE,TRUE,DP2_RESULT_REG));
4082 for (i = (size-1) ; i >= 0 ; i--) {
4083 emitcode ("pop","a%s",javaRet[i]);
4086 for (i = 0 ; i < size ; i++)
4087 emitcode ("mov","%s,%s",javaRet[i],
4088 aopGet(IC_LEFT(ic),i,FALSE,TRUE,DP2_RESULT_REG));
4090 for (i = size ; i < 4 ; i++ )
4091 emitcode ("mov","%s,#0",javaRet[i]);
4095 /*-----------------------------------------------------------------*/
4096 /* genRet - generate code for return statement */
4097 /*-----------------------------------------------------------------*/
4101 int size, offset = 0, pushed = 0;
4103 D (emitcode (";", "genRet"));
4105 /* if we have no return value then
4106 just generate the "ret" */
4110 /* if this is a JavaNative function then return
4111 value in different register */
4112 if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
4113 genJavaNativeRet(ic);
4116 /* we have something to return then
4117 move the return value into place */
4118 aopOp (IC_LEFT (ic), ic, FALSE,
4119 (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
4120 size = AOP_SIZE (IC_LEFT (ic));
4122 _startLazyDPSEvaluation ();
4124 if (IS_BIT(_G.currentFunc->etype))
4126 movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4133 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
4135 l = aopGet (IC_LEFT (ic), offset++,
4137 emitcode ("push", "%s", l);
4142 /* Since A is the last element of fReturn,
4143 * it is OK to clobber it in the aopGet.
4145 l = aopGet (IC_LEFT (ic), offset,
4146 FALSE, FALSE, NULL);
4147 if (strcmp (fReturn[offset], l))
4148 emitcode ("mov", "%s,%s", fReturn[offset++], l);
4151 _endLazyDPSEvaluation ();
4156 if (strcmp (fReturn[pushed], "a"))
4157 emitcode ("pop", fReturn[pushed]);
4159 emitcode ("pop", "acc");
4161 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
4164 /* generate a jump to the return label
4165 if the next is not the return statement */
4166 if (!(ic->next && ic->next->op == LABEL &&
4167 IC_LABEL (ic->next) == returnLabel))
4169 emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
4173 /*-----------------------------------------------------------------*/
4174 /* genLabel - generates a label */
4175 /*-----------------------------------------------------------------*/
4177 genLabel (iCode * ic)
4179 /* special case never generate */
4180 if (IC_LABEL (ic) == entryLabel)
4183 D (emitcode (";", "genLabel"));
4185 emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
4188 /*-----------------------------------------------------------------*/
4189 /* genGoto - generates a ljmp */
4190 /*-----------------------------------------------------------------*/
4192 genGoto (iCode * ic)
4194 D (emitcode (";", "genGoto"));
4196 emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
4199 /*-----------------------------------------------------------------*/
4200 /* findLabelBackwards: walks back through the iCode chain looking */
4201 /* for the given label. Returns number of iCode instructions */
4202 /* between that label and given ic. */
4203 /* Returns zero if label not found. */
4204 /*-----------------------------------------------------------------*/
4206 findLabelBackwards (iCode * ic, int key)
4215 /* If we have any pushes or pops, we cannot predict the distance.
4216 I don't like this at all, this should be dealt with in the
4218 if (ic->op == IPUSH || ic->op == IPOP) {
4222 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4224 /* printf("findLabelBackwards = %d\n", count); */
4232 /*-----------------------------------------------------------------*/
4233 /* genPlusIncr :- does addition with increment if possible */
4234 /*-----------------------------------------------------------------*/
4236 genPlusIncr (iCode * ic)
4238 unsigned int icount;
4239 unsigned int size = getDataSize (IC_RESULT (ic));
4241 /* will try to generate an increment */
4242 /* if the right side is not a literal
4244 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4247 /* if the literal value of the right hand side
4248 is greater than 4 then it is not worth it */
4249 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4252 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4253 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4255 emitcode("inc","%s",aopGet(IC_RESULT(ic),0,FALSE,FALSE,NULL));
4259 /* if increment 16 bits in register */
4261 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4262 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4263 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4272 /* If the next instruction is a goto and the goto target
4273 * is <= 5 instructions previous to this, we can generate
4274 * jumps straight to that target.
4276 if (ic->next && ic->next->op == GOTO
4277 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4280 D (emitcode (";", "tail increment optimized (range %d)", labelRange));
4281 tlbl = IC_LABEL (ic->next);
4286 tlbl = newiTempLabel (NULL);
4289 l = aopGet (IC_RESULT (ic), LSB, FALSE, FALSE, NULL);
4290 emitcode ("inc", "%s", l);
4292 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 ("clr", "a");
4300 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4303 l = aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE, NULL);
4304 emitcode ("inc", "%s", l);
4307 if (!strcmp(l, "acc"))
4309 emitcode("jnz", "!tlabel", tlbl->key + 100);
4311 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4312 IS_AOP_PREG (IC_RESULT (ic)))
4314 emitcode ("cjne", "%s,%s,!tlabel", l, zero, tlbl->key + 100);
4318 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4321 l = aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE, NULL);
4322 emitcode ("inc", "%s", l);
4326 if (!strcmp(l, "acc"))
4328 emitcode("jnz", "!tlabel", tlbl->key + 100);
4330 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4331 IS_AOP_PREG (IC_RESULT (ic)))
4333 emitcode ("cjne", "%s,%s,!tlabel", l, zero, tlbl->key + 100);
4337 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4340 l = aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE, NULL);
4341 emitcode ("inc", "%s", l);
4351 if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
4352 !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 &&
4353 options.model == MODEL_FLAT24 )
4355 if (IC_RESULT(ic)->isGptr)
4357 emitcode ("mov", "b,%s", aopGet(IC_LEFT (ic), 3, FALSE, FALSE, NULL));
4361 emitcode ("mov", "dpx,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE, NULL));
4363 emitcode ("mov", "dph,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE, NULL));
4365 emitcode ("mov", "dpl,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4369 emitcode ("inc", "dptr");
4373 if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
4374 AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
4376 emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
4378 emitcode ("inc", "dptr");
4379 emitcode ("mov", "dps,#0");
4383 /* if the sizes are greater than 1 then we cannot */
4384 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4385 AOP_SIZE (IC_LEFT (ic)) > 1)
4388 /* we can if the aops of the left & result match or
4389 if they are in registers and the registers are the
4392 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4393 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4394 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4398 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4399 emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
4400 aopPut (IC_RESULT (ic), "a", 0);
4404 _startLazyDPSEvaluation ();
4407 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4409 _endLazyDPSEvaluation ();
4418 /*-----------------------------------------------------------------*/
4419 /* outBitAcc - output a bit in acc */
4420 /*-----------------------------------------------------------------*/
4422 outBitAcc (operand * result)
4424 symbol *tlbl = newiTempLabel (NULL);
4425 /* if the result is a bit */
4426 if (AOP_TYPE (result) == AOP_CRY)
4428 aopPut (result, "a", 0);
4432 emitcode ("jz", "!tlabel", tlbl->key + 100);
4433 emitcode ("mov", "a,%s", one);
4439 /*-----------------------------------------------------------------*/
4440 /* genPlusBits - generates code for addition of two bits */
4441 /*-----------------------------------------------------------------*/
4443 genPlusBits (iCode * ic)
4445 D (emitcode (";", "genPlusBits"));
4447 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4449 symbol *lbl = newiTempLabel (NULL);
4450 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4451 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4452 emitcode ("cpl", "c");
4454 outBitC (IC_RESULT (ic));
4458 emitcode ("clr", "a");
4459 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4460 emitcode ("rlc", "a");
4461 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4462 emitcode ("addc", "a,%s", zero);
4463 outAcc (IC_RESULT (ic));
4468 adjustArithmeticResult (iCode * ic)
4470 if (opIsGptr (IC_RESULT (ic)) &&
4471 opIsGptr (IC_LEFT (ic)) &&
4472 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4474 aopPut (IC_RESULT (ic),
4475 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE, NULL),
4479 if (opIsGptr (IC_RESULT (ic)) &&
4480 opIsGptr (IC_RIGHT (ic)) &&
4481 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4483 aopPut (IC_RESULT (ic),
4484 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE, NULL),
4488 if (opIsGptr (IC_RESULT (ic)) &&
4489 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4490 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4491 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4492 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4495 SNPRINTF (buffer, sizeof(buffer),
4496 "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4497 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4501 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
4502 // generates the result if possible. If result is generated, returns TRUE; otherwise
4503 // returns false and caller must deal with fact that result isn't aopOp'd.
4504 bool aopOp3(iCode * ic)
4506 bool dp1InUse, dp2InUse;
4509 // First, generate the right opcode. DPTR may be used if neither left nor result are
4512 // D (emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
4513 // AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
4514 // AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
4515 // AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
4517 // D (emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
4518 // AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
4519 // AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
4520 // AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
4523 // Right uses DPTR unless left or result is an AOP_STR; however,
4524 // if right is an AOP_STR, it must use DPTR regardless.
4525 if ((AOP_IS_STR (IC_LEFT (ic)) || AOP_IS_STR (IC_RESULT (ic)))
4526 && !AOP_IS_STR (IC_RIGHT (ic)))
4535 aopOp (IC_RIGHT(ic), ic, FALSE, useDp2);
4537 // if the right used DPTR, left MUST use DPTR2.
4538 // if the right used DPTR2, left MUST use DPTR.
4539 // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
4540 // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
4541 // enabling us to assign DPTR to result.
4543 if (AOP_USESDPTR (IC_RIGHT (ic)))
4547 else if (AOP_USESDPTR2 (IC_RIGHT (ic)))
4553 if (AOP_IS_STR (IC_RESULT (ic)) && !AOP_IS_STR (IC_LEFT (ic)))
4563 aopOp (IC_LEFT (ic), ic, FALSE, useDp2);
4566 // We've op'd the left & right. So, if left or right are the same operand as result,
4567 // we know aopOp will succeed, and we can just do it & bail.
4568 if (isOperandEqual (IC_LEFT (ic), IC_RESULT (ic)))
4570 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4573 if (isOperandEqual (IC_RIGHT (ic), IC_RESULT (ic)))
4575 // D (emitcode(";", "aopOp3: (left | right) & result equal"));
4576 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4580 // Operands may be equivalent (but not equal) if they share a spill location. If
4581 // so, use the same DPTR or DPTR2.
4582 if (operandsEqu (IC_LEFT (ic), IC_RESULT (ic)))
4584 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4587 if (operandsEqu (IC_RIGHT (ic), IC_RESULT (ic)))
4589 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4593 // Note which dptrs are currently in use.
4594 dp1InUse = AOP_USESDPTR (IC_LEFT (ic)) || AOP_USESDPTR (IC_RIGHT (ic));
4595 dp2InUse = AOP_USESDPTR2 (IC_LEFT (ic)) || AOP_USESDPTR2 (IC_RIGHT (ic));
4597 // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot
4599 if (dp1InUse && AOP_IS_STR (IC_RESULT (ic)))
4604 // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
4605 if (dp2InUse && AOP_IS_DPTRn (IC_RESULT (ic)))
4610 // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck
4611 if (dp1InUse && dp2InUse && isOperandInFarSpace (IC_RESULT (ic)))
4616 aopOp (IC_RESULT (ic), ic, TRUE, dp1InUse);
4618 // Some sanity checking...
4619 if (dp1InUse && AOP_USESDPTR (IC_RESULT (ic)))
4622 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
4623 __FILE__, __LINE__, ic->filename, ic->lineno);
4624 emitcode(";", ">>> unexpected DPTR here.");
4627 if (dp2InUse && AOP_USESDPTR2 (IC_RESULT (ic)))
4630 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
4631 __FILE__, __LINE__, ic->filename, ic->lineno);
4632 emitcode(";", ">>> unexpected DPTR2 here.");
4638 // Macro to aopOp all three operands of an ic. If this cannot be done,
4639 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
4640 // will be set TRUE. The caller must then handle the case specially, noting
4641 // that the IC_RESULT operand is not aopOp'd.
4643 #define AOP_OP_3_NOFATAL(ic, rc) \
4644 do { rc = !aopOp3(ic); } while (0)
4646 // aopOp the left & right operands of an ic.
4647 #define AOP_OP_2(ic) \
4648 aopOp (IC_RIGHT (ic), ic, FALSE, AOP_IS_STR (IC_LEFT (ic))); \
4649 aopOp (IC_LEFT (ic), ic, FALSE, AOP_USESDPTR (IC_RIGHT (ic)));
4651 // convienience macro.
4652 #define AOP_SET_LOCALS(ic) \
4653 left = IC_LEFT(ic); \
4654 right = IC_RIGHT(ic); \
4655 result = IC_RESULT(ic);
4658 // Given an integer value of pushedSize bytes on the stack,
4659 // adjust it to be resultSize bytes, either by discarding
4660 // the most significant bytes or by zero-padding.
4662 // On exit from this macro, pushedSize will have been adjusted to
4663 // equal resultSize, and ACC may be trashed.
4664 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
4665 /* If the pushed data is bigger than the result, \
4666 * simply discard unused bytes. Icky, but works. \
4668 while (pushedSize > resultSize) \
4670 D (emitcode (";", "discarding unused result byte.")); \
4671 emitcode ("pop", "acc"); \
4674 if (pushedSize < resultSize) \
4676 emitcode ("clr", "a"); \
4677 /* Conversly, we haven't pushed enough here. \
4678 * just zero-pad, and all is well. \
4680 while (pushedSize < resultSize) \
4682 emitcode("push", "acc"); \
4686 assert(pushedSize == resultSize);
4688 /*-----------------------------------------------------------------*/
4689 /* genPlus - generates code for addition */
4690 /*-----------------------------------------------------------------*/
4692 genPlus (iCode * ic)
4694 int size, offset = 0;
4697 bool swappedLR = FALSE;
4699 D (emitcode (";", "genPlus"));
4701 /* special cases :- */
4702 if ( AOP_IS_STR (IC_LEFT (ic)) &&
4703 isOperandLiteral (IC_RIGHT (ic)) && OP_SYMBOL (IC_RESULT (ic))->ruonly) {
4704 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
4705 size = (int)floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4707 while (size--) emitcode ("inc","dptr");
4709 emitcode ("mov", "a,dpl");
4710 emitcode ("add", "a,#!constbyte", size & 0xff);
4711 emitcode ("mov", "dpl,a");
4712 emitcode ("mov", "a,dph");
4713 emitcode ("addc", "a,#!constbyte", (size >> 8) & 0xff);
4714 emitcode ("mov", "dph,a");
4715 emitcode ("mov", "a,dpx");
4716 emitcode ("addc", "a,#!constbyte", (size >> 16) & 0xff);
4717 emitcode ("mov", "dpx,a");
4719 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4722 if ( IS_SYMOP (IC_LEFT (ic)) &&
4723 OP_SYMBOL (IC_LEFT (ic))->remat &&
4724 isOperandInFarSpace (IC_RIGHT (ic))) {
4725 operand *op = IC_RIGHT(ic);
4726 IC_RIGHT(ic) = IC_LEFT(ic);
4730 AOP_OP_3_NOFATAL (ic, pushResult);
4734 D (emitcode (";", "genPlus: must push result: 3 ops in far space"));
4739 /* if literal, literal on the right or
4740 if left requires ACC or right is already
4742 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4743 ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic)))) ||
4744 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4746 operand *t = IC_RIGHT (ic);
4747 IC_RIGHT (ic) = IC_LEFT (ic);
4750 D (emitcode (";", "Swapped plus args."));
4753 /* if both left & right are in bit
4755 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4756 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4762 /* if left in bit space & right literal */
4763 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4764 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4766 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4767 /* if result in bit space */
4768 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4770 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4771 emitcode ("cpl", "c");
4772 outBitC (IC_RESULT (ic));
4776 size = getDataSize (IC_RESULT (ic));
4777 _startLazyDPSEvaluation ();
4780 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4781 emitcode ("addc", "a,%s", zero);
4782 aopPut (IC_RESULT (ic), "a", offset++);
4784 _endLazyDPSEvaluation ();
4789 /* if I can do an increment instead
4790 of add then GOOD for ME */
4791 if (genPlusIncr (ic) == TRUE)
4793 D (emitcode (";", "did genPlusIncr"));
4798 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4800 _startLazyDPSEvaluation ();
4803 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4805 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
4807 emitcode ("add", "a,%s",
4808 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4810 emitcode ("addc", "a,%s",
4811 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4815 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4817 /* right is going to use ACC or we would have taken the
4820 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4822 D(emitcode(";", "+ AOP_ACC special case."););
4823 emitcode("xch", "a, %s", DP2_RESULT_REG);
4825 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4828 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4831 emitcode("add", "a, %s", DP2_RESULT_REG);
4835 emitcode ("add", "a,%s",
4836 aopGet (IC_LEFT(ic), offset, FALSE, FALSE,
4842 emitcode ("addc", "a,%s",
4843 aopGet (IC_LEFT (ic), offset, FALSE, FALSE,
4849 aopPut (IC_RESULT (ic), "a", offset);
4853 emitcode ("push", "acc");
4857 _endLazyDPSEvaluation ();
4861 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4863 size = getDataSize (IC_LEFT (ic));
4864 rSize = getDataSize (IC_RESULT (ic));
4866 ADJUST_PUSHED_RESULT(size, rSize);
4868 _startLazyDPSEvaluation ();
4871 emitcode ("pop", "acc");
4872 aopPut (IC_RESULT (ic), "a", size);
4874 _endLazyDPSEvaluation ();
4877 adjustArithmeticResult (ic);
4880 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4883 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4884 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4888 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4889 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4893 /*-----------------------------------------------------------------*/
4894 /* genMinusDec :- does subtraction with decrement if possible */
4895 /*-----------------------------------------------------------------*/
4897 genMinusDec (iCode * ic)
4899 unsigned int icount;
4900 unsigned int size = getDataSize (IC_RESULT (ic));
4902 /* will try to generate an increment */
4903 /* if the right side is not a literal
4905 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4908 /* if the literal value of the right hand side
4909 is greater than 4 then it is not worth it */
4910 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4913 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4914 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4916 emitcode("dec","%s",aopGet(IC_RESULT(ic),0,FALSE,FALSE,NULL));
4920 /* if decrement 16 bits in register */
4921 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4922 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4923 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4932 /* If the next instruction is a goto and the goto target
4933 * is <= 5 instructions previous to this, we can generate
4934 * jumps straight to that target.
4936 if (ic->next && ic->next->op == GOTO
4937 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4940 D (emitcode (";", "tail decrement optimized (range %d)", labelRange));
4941 tlbl = IC_LABEL (ic->next);
4946 tlbl = newiTempLabel (NULL);
4950 l = aopGet (IC_RESULT (ic), LSB, FALSE, FALSE, NULL);
4951 emitcode ("dec", "%s", l);
4953 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4954 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4955 IS_AOP_PREG (IC_RESULT (ic)))
4957 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4961 emitcode ("mov", "a,#!constbyte",0xff);
4962 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4964 l = aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE, NULL);
4965 emitcode ("dec", "%s", l);
4968 if (!strcmp(l, "acc"))
4970 emitcode("jnz", "!tlabel", tlbl->key + 100);
4972 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4973 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4974 IS_AOP_PREG (IC_RESULT (ic)))
4976 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4980 emitcode ("mov", "a,#!constbyte",0xff);
4981 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4983 l = aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE, NULL);
4984 emitcode ("dec", "%s", l);
4988 if (!strcmp(l, "acc"))
4990 emitcode("jnz", "!tlabel", tlbl->key + 100);
4992 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4993 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4994 IS_AOP_PREG (IC_RESULT (ic)))
4996 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
5000 emitcode ("mov", "a,#!constbyte",0xff);
5001 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
5003 l = aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE, NULL);
5004 emitcode ("dec", "%s", l);
5013 /* if the sizes are greater than 1 then we cannot */
5014 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
5015 AOP_SIZE (IC_LEFT (ic)) > 1)
5018 /* we can if the aops of the left & result match or
5019 if they are in registers and the registers are the
5022 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
5023 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
5024 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
5028 if (aopGetUsesAcc (IC_LEFT (ic), 0))
5030 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL));
5035 l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL);
5038 _startLazyDPSEvaluation ();
5041 emitcode ("dec", "%s", l);
5043 _endLazyDPSEvaluation ();
5045 if (AOP_NEEDSACC (IC_RESULT (ic)))
5046 aopPut (IC_RESULT (ic), "a", 0);
5054 /*-----------------------------------------------------------------*/
5055 /* addSign - complete with sign */
5056 /*-----------------------------------------------------------------*/
5058 addSign (operand * result, int offset, int sign)
5060 int size = (getDataSize (result) - offset);
5063 _startLazyDPSEvaluation();
5066 emitcode ("rlc", "a");
5067 emitcode ("subb", "a,acc");
5070 aopPut (result, "a", offset++);
5077 aopPut (result, zero, offset++);
5080 _endLazyDPSEvaluation();
5084 /*-----------------------------------------------------------------*/
5085 /* genMinusBits - generates code for subtraction of two bits */
5086 /*-----------------------------------------------------------------*/
5088 genMinusBits (iCode * ic)
5090 symbol *lbl = newiTempLabel (NULL);
5092 D (emitcode (";", "genMinusBits"));
5094 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
5096 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
5097 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
5098 emitcode ("cpl", "c");
5100 outBitC (IC_RESULT (ic));
5104 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
5105 emitcode ("subb", "a,acc");
5106 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
5107 emitcode ("inc", "a");
5109 aopPut (IC_RESULT (ic), "a", 0);
5110 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
5114 /*-----------------------------------------------------------------*/
5115 /* genMinus - generates code for subtraction */
5116 /*-----------------------------------------------------------------*/
5118 genMinus (iCode * ic)
5120 int size, offset = 0;
5125 D (emitcode (";", "genMinus"));
5127 AOP_OP_3_NOFATAL(ic, pushResult);
5131 /* special cases :- */
5132 /* if both left & right are in bit space */
5133 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
5134 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
5140 /* if I can do an decrement instead
5141 of subtract then GOOD for ME */
5142 if (genMinusDec (ic) == TRUE)
5147 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
5149 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
5155 lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5160 /* if literal, add a,#-lit, else normal subb */
5161 _startLazyDPSEvaluation ();
5163 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
5164 if (AOP_USESDPTR(IC_RIGHT(ic))) {
5165 emitcode ("mov","b,%s",
5166 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
5167 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
5168 emitcode ("subb","a,b");
5170 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
5171 emitcode ("subb", "a,%s",
5172 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE,
5176 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
5177 /* first add without previous c */
5179 if (!size && lit==-1) {
5180 emitcode ("dec", "a");
5182 emitcode ("add", "a,#!constbyte",
5183 (unsigned int) (lit & 0x0FFL));
5186 emitcode ("addc", "a,#!constbyte",
5187 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5192 emitcode ("push", "acc");
5194 aopPut (IC_RESULT (ic), "a", offset);
5198 _endLazyDPSEvaluation ();
5202 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
5204 size = getDataSize (IC_LEFT (ic));
5205 rSize = getDataSize (IC_RESULT (ic));
5207 ADJUST_PUSHED_RESULT(size, rSize);
5209 _startLazyDPSEvaluation ();
5212 emitcode ("pop", "acc");
5213 aopPut (IC_RESULT (ic), "a", size);
5215 _endLazyDPSEvaluation ();
5218 adjustArithmeticResult (ic);
5221 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5222 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5223 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5227 /*-----------------------------------------------------------------*/
5228 /* genMultbits :- multiplication of bits */
5229 /*-----------------------------------------------------------------*/
5231 genMultbits (operand * left,
5236 D (emitcode (";", "genMultbits"));
5238 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5239 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5240 aopOp(result, ic, TRUE, FALSE);
5244 /*-----------------------------------------------------------------*/
5245 /* genMultOneByte : 8*8=8/16 bit multiplication */
5246 /*-----------------------------------------------------------------*/
5248 genMultOneByte (operand * left,
5255 bool runtimeSign, compiletimeSign;
5256 bool lUnsigned, rUnsigned, pushedB;
5258 /* (if two literals: the value is computed before) */
5259 /* if one literal, literal on the right */
5260 if (AOP_TYPE (left) == AOP_LIT)
5265 /* emitcode (";", "swapped left and right"); */
5267 /* if no literal, unsigned on the right: shorter code */
5268 if ( AOP_TYPE (right) != AOP_LIT
5269 && SPEC_USIGN (getSpec (operandType (left))))
5276 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5277 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5281 if ((lUnsigned && rUnsigned)
5282 /* sorry, I don't know how to get size
5283 without calling aopOp (result,...);
5284 see Feature Request */
5285 /* || size == 1 */ ) /* no, this is not a bug; with a 1 byte result there's
5286 no need to take care about the signedness! */
5288 /* just an unsigned 8 * 8 = 8 multiply
5290 /* emitcode (";","unsigned"); */
5291 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
5292 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
5293 emitcode ("mul", "ab");
5296 aopOp (result, ic, TRUE, FALSE);
5297 size = AOP_SIZE (result);
5299 if (size < 1 || size > 2)
5301 /* this should never happen */
5302 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
5303 size, __FILE__, lineno);
5307 aopPut (result, "a", 0);
5310 aopPut (result, "b", 1);
5316 /* we have to do a signed multiply */
5317 /* emitcode (";", "signed"); */
5319 /* now sign adjust for both left & right */
5321 /* let's see what's needed: */
5322 /* apply negative sign during runtime */
5323 runtimeSign = FALSE;
5324 /* negative sign from literals */
5325 compiletimeSign = FALSE;
5329 if (AOP_TYPE(left) == AOP_LIT)
5331 /* signed literal */
5332 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5334 compiletimeSign = TRUE;
5337 /* signed but not literal */
5343 if (AOP_TYPE(right) == AOP_LIT)
5345 /* signed literal */
5346 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5348 compiletimeSign ^= TRUE;
5351 /* signed but not literal */
5355 /* initialize F0, which stores the runtime sign */
5358 if (compiletimeSign)
5359 emitcode ("setb", "F0"); /* set sign flag */
5361 emitcode ("clr", "F0"); /* reset sign flag */
5364 /* save the signs of the operands */
5365 if (AOP_TYPE(right) == AOP_LIT)
5367 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5369 if (!rUnsigned && val < 0)
5370 emitcode ("mov", "b,#!constbyte", -val);
5372 emitcode ("mov", "b,#!constbyte", (unsigned char) val);
5374 else /* ! literal */
5376 if (rUnsigned) /* emitcode (";", "signed"); */
5377 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
5380 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
5381 lbl = newiTempLabel (NULL);
5382 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5383 emitcode ("cpl", "F0"); /* complement sign flag */
5384 emitcode ("cpl", "a"); /* 2's complement */
5385 emitcode ("inc", "a");
5387 emitcode ("mov", "b,a");
5391 if (AOP_TYPE(left) == AOP_LIT)
5393 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5395 if (!lUnsigned && val < 0)
5396 emitcode ("mov", "a,#!constbyte", -val);
5398 emitcode ("mov", "a,#!constbyte", (unsigned char) val);
5400 else /* ! literal */
5402 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
5404 if (!lUnsigned) /* emitcode (";", "signed"); */
5406 lbl = newiTempLabel (NULL);
5407 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5408 emitcode ("cpl", "F0"); /* complement sign flag */
5409 emitcode ("cpl", "a"); /* 2's complement */
5410 emitcode ("inc", "a");
5415 /* now the multiplication */
5416 emitcode ("mul", "ab");
5418 aopOp(result, ic, TRUE, FALSE);
5419 size = AOP_SIZE (result);
5421 if (size < 1 || size > 2)
5423 /* this should never happen */
5424 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
5425 size, __FILE__, lineno);
5429 if (runtimeSign || compiletimeSign)
5431 lbl = newiTempLabel (NULL);
5433 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5434 emitcode ("cpl", "a"); /* lsb 2's complement */
5436 emitcode ("inc", "a"); /* inc doesn't set carry flag */
5439 emitcode ("add", "a,#1"); /* this sets carry flag */
5440 emitcode ("xch", "a,b");
5441 emitcode ("cpl", "a"); /* msb 2's complement */
5442 emitcode ("addc", "a,#0");
5443 emitcode ("xch", "a,b");
5447 aopPut (result, "a", 0);
5450 aopPut (result, "b", 1);
5455 /*-----------------------------------------------------------------*/
5456 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
5457 /*-----------------------------------------------------------------*/
5458 static void genMultTwoByte (operand *left, operand *right,
5459 operand *result, iCode *ic)
5461 sym_link *retype = getSpec(operandType(right));
5462 sym_link *letype = getSpec(operandType(left));
5463 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5466 if (AOP_TYPE (left) == AOP_LIT) {
5471 /* save EA bit in F1 */
5472 lbl = newiTempLabel(NULL);
5473 emitcode ("setb","F1");
5474 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5475 emitcode ("clr","F1");
5478 /* load up MB with right */
5480 emitcode("clr","F0");
5481 if (AOP_TYPE(right) == AOP_LIT) {
5482 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5484 emitcode("setb","F0");
5487 emitcode ("mov","mb,#!constbyte",val & 0xff);
5488 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5490 lbl = newiTempLabel(NULL);
5491 emitcode ("mov","b,%s",aopGet(right,0,FALSE,FALSE,NULL));
5492 emitcode ("mov","a,%s",aopGet(right,1,FALSE,FALSE,NULL));
5493 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5494 emitcode ("xch", "a,b");
5495 emitcode ("cpl","a");
5496 emitcode ("add", "a,#1");
5497 emitcode ("xch", "a,b");
5498 emitcode ("cpl", "a"); // msb
5499 emitcode ("addc", "a,#0");
5500 emitcode ("setb","F0");
5502 emitcode ("mov","mb,b");
5503 emitcode ("mov","mb,a");
5506 emitcode ("mov","mb,%s",aopGet(right,0,FALSE,FALSE,NULL));
5507 emitcode ("mov","mb,%s",aopGet(right,1,FALSE,FALSE,NULL));
5509 /* load up MA with left */
5511 lbl = newiTempLabel(NULL);
5512 emitcode ("mov","b,%s",aopGet(left,0,FALSE,FALSE,NULL));
5513 emitcode ("mov","a,%s",aopGet(left,1,FALSE,FALSE,NULL));
5514 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5515 emitcode ("xch", "a,b");
5516 emitcode ("cpl","a");
5517 emitcode ("add", "a,#1");
5518 emitcode ("xch", "a,b");
5519 emitcode ("cpl", "a"); // msb
5520 emitcode ("addc","a,#0");
5521 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5522 emitcode ("setb","F0");
5524 emitcode ("mov","ma,b");
5525 emitcode ("mov","ma,a");
5527 emitcode ("mov","ma,%s",aopGet(left,0,FALSE,FALSE,NULL));
5528 emitcode ("mov","ma,%s",aopGet(left,1,FALSE,FALSE,NULL));
5530 /* wait for multiplication to finish */
5531 lbl = newiTempLabel(NULL);
5533 emitcode("mov","a,mcnt1");
5534 emitcode("anl","a,#!constbyte",0x80);
5535 emitcode("jnz","!tlabel",lbl->key+100);
5537 freeAsmop (left, NULL, ic, TRUE);
5538 freeAsmop (right, NULL, ic,TRUE);
5539 aopOp(result, ic, TRUE, FALSE);
5541 /* if unsigned then simple */
5543 emitcode ("mov","a,ma");
5544 if (AOP_SIZE(result) >= 4) aopPut(result,"a",3);
5545 emitcode ("mov","a,ma");
5546 if (AOP_SIZE(result) >= 3) aopPut(result,"a",2);
5547 aopPut(result,"ma",1);
5548 aopPut(result,"ma",0);
5550 emitcode("push","ma");
5551 emitcode("push","ma");
5552 emitcode("push","ma");
5554 /* negate result if needed */
5555 lbl = newiTempLabel(NULL);
5556 emitcode("jnb","F0,!tlabel",lbl->key+100);
5557 emitcode("cpl","a");
5558 emitcode("add","a,#1");
5560 if (AOP_TYPE(result) == AOP_ACC)
5562 D (emitcode(";", "ACC special case."));
5563 /* We know result is the only live aop, and
5564 * it's obviously not a DPTR2, so AP is available.
5566 emitcode("mov", "%s,acc", DP2_RESULT_REG);
5570 aopPut(result,"a",0);
5573 emitcode("pop","acc");
5574 lbl = newiTempLabel(NULL);
5575 emitcode("jnb","F0,!tlabel",lbl->key+100);
5576 emitcode("cpl","a");
5577 emitcode("addc","a,#0");
5579 aopPut(result,"a",1);
5580 emitcode("pop","acc");
5581 if (AOP_SIZE(result) >= 3) {
5582 lbl = newiTempLabel(NULL);
5583 emitcode("jnb","F0,!tlabel",lbl->key+100);
5584 emitcode("cpl","a");
5585 emitcode("addc","a,#0");
5587 aopPut(result,"a",2);
5589 emitcode("pop","acc");
5590 if (AOP_SIZE(result) >= 4) {
5591 lbl = newiTempLabel(NULL);
5592 emitcode("jnb","F0,!tlabel",lbl->key+100);
5593 emitcode("cpl","a");
5594 emitcode("addc","a,#0");
5596 aopPut(result,"a",3);
5598 if (AOP_TYPE(result) == AOP_ACC)
5600 /* We stashed the result away above. */
5601 emitcode("mov", "acc,%s", DP2_RESULT_REG);
5605 freeAsmop (result, NULL, ic, TRUE);
5607 /* restore EA bit in F1 */
5608 lbl = newiTempLabel(NULL);
5609 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5610 emitcode ("setb","EA");
5615 /*-----------------------------------------------------------------*/
5616 /* genMult - generates code for multiplication */
5617 /*-----------------------------------------------------------------*/
5619 genMult (iCode * ic)
5621 operand *left = IC_LEFT (ic);
5622 operand *right = IC_RIGHT (ic);
5623 operand *result = IC_RESULT (ic);
5625 D (emitcode (";", "genMult"));
5627 /* assign the asmops */
5630 /* special cases first */
5632 if (AOP_TYPE (left) == AOP_CRY &&
5633 AOP_TYPE (right) == AOP_CRY)
5635 genMultbits (left, right, result, ic);
5639 /* if both are of size == 1 */
5640 if (AOP_SIZE (left) == 1 &&
5641 AOP_SIZE (right) == 1)
5643 genMultOneByte (left, right, result, ic);
5647 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5648 /* use the ds390 ARITHMETIC accel UNIT */
5649 genMultTwoByte (left, right, result, ic);
5652 /* should have been converted to function call */
5656 freeAsmop (result, NULL, ic, TRUE);
5657 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5658 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5661 /*-----------------------------------------------------------------*/
5662 /* genDivbits :- division of bits */
5663 /*-----------------------------------------------------------------*/
5665 genDivbits (operand * left,
5673 D(emitcode ("; genDivbits",""));
5677 /* the result must be bit */
5678 LOAD_AB_FOR_DIV (left, right, l);
5679 emitcode ("div", "ab");
5680 emitcode ("rrc", "a");
5681 aopOp(result, ic, TRUE, FALSE);
5685 aopPut (result, "c", 0);
5688 /*-----------------------------------------------------------------*/
5689 /* genDivOneByte : 8 bit division */
5690 /*-----------------------------------------------------------------*/
5692 genDivOneByte (operand * left,
5697 bool lUnsigned, rUnsigned, pushedB;
5698 bool runtimeSign, compiletimeSign;
5703 D(emitcode ("; genDivOneByte",""));
5706 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5707 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5711 /* signed or unsigned */
5712 if (lUnsigned && rUnsigned)
5714 /* unsigned is easy */
5715 LOAD_AB_FOR_DIV (left, right, l);
5716 emitcode ("div", "ab");
5719 aopOp (result, ic, TRUE, FALSE);
5720 aopPut (result, "a", 0);
5723 size = AOP_SIZE (result) - 1;
5726 aopPut (result, zero, offset++);
5732 /* signed is a little bit more difficult */
5734 /* now sign adjust for both left & right */
5736 /* let's see what's needed: */
5737 /* apply negative sign during runtime */
5738 runtimeSign = FALSE;
5739 /* negative sign from literals */
5740 compiletimeSign = FALSE;
5744 if (AOP_TYPE(left) == AOP_LIT)
5746 /* signed literal */
5747 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5749 compiletimeSign = TRUE;
5752 /* signed but not literal */
5758 if (AOP_TYPE(right) == AOP_LIT)
5760 /* signed literal */
5761 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5763 compiletimeSign ^= TRUE;
5766 /* signed but not literal */
5770 /* initialize F0, which stores the runtime sign */
5773 if (compiletimeSign)
5774 emitcode ("setb", "F0"); /* set sign flag */
5776 emitcode ("clr", "F0"); /* reset sign flag */
5779 /* save the signs of the operands */
5780 if (AOP_TYPE(right) == AOP_LIT)
5782 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5784 if (!rUnsigned && val < 0)
5785 emitcode ("mov", "b,#0x%02x", -val);
5787 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5789 else /* ! literal */
5792 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
5795 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
5796 lbl = newiTempLabel (NULL);
5797 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5798 emitcode ("cpl", "F0"); /* complement sign flag */
5799 emitcode ("cpl", "a"); /* 2's complement */
5800 emitcode ("inc", "a");
5802 emitcode ("mov", "b,a");
5806 if (AOP_TYPE(left) == AOP_LIT)
5808 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5810 if (!lUnsigned && val < 0)
5811 emitcode ("mov", "a,#0x%02x", -val);
5813 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5815 else /* ! literal */
5817 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
5821 lbl = newiTempLabel (NULL);
5822 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5823 emitcode ("cpl", "F0"); /* complement sign flag */
5824 emitcode ("cpl", "a"); /* 2's complement */
5825 emitcode ("inc", "a");
5830 /* now the division */
5831 emitcode ("nop", "; workaround for DS80C390 div bug.");
5832 emitcode ("div", "ab");
5834 if (runtimeSign || compiletimeSign)
5836 lbl = newiTempLabel (NULL);
5838 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5839 emitcode ("cpl", "a"); /* lsb 2's complement */
5840 emitcode ("inc", "a");
5844 aopOp (result, ic, TRUE, FALSE);
5845 size = AOP_SIZE (result) - 1;
5849 /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
5850 then the result will be in b, a */
5851 emitcode ("mov", "b,a"); /* 1 */
5852 /* msb is 0x00 or 0xff depending on the sign */
5855 emitcode ("mov", "c,F0");
5856 emitcode ("subb", "a,acc");
5857 emitcode ("xch", "a,b"); /* 2 */
5859 aopPut (result, "b", offset++); /* write msb's */
5861 else /* compiletimeSign */
5863 aopPut (result, "#0xff", offset++); /* write msb's */
5865 aopPut (result, "a", 0); /* 3: write lsb */
5870 aopOp(result, ic, TRUE, FALSE);
5871 size = AOP_SIZE (result) - 1;
5873 aopPut (result, "a", 0);
5875 aopPut (result, zero, offset++);
5881 /*-----------------------------------------------------------------*/
5882 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
5883 /*-----------------------------------------------------------------*/
5884 static void genDivTwoByte (operand *left, operand *right,
5885 operand *result, iCode *ic)
5887 sym_link *retype = getSpec(operandType(right));
5888 sym_link *letype = getSpec(operandType(left));
5889 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5892 /* save EA bit in F1 */
5893 lbl = newiTempLabel(NULL);
5894 emitcode ("setb","F1");
5895 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5896 emitcode ("clr","F1");
5899 /* load up MA with left */
5901 emitcode("clr","F0");
5902 lbl = newiTempLabel(NULL);
5903 emitcode ("mov","b,%s",aopGet(left,0,FALSE,FALSE,NULL));
5904 emitcode ("mov","a,%s",aopGet(left,1,FALSE,FALSE,NULL));
5905 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5906 emitcode ("xch", "a,b");
5907 emitcode ("cpl","a");
5908 emitcode ("add", "a,#1");
5909 emitcode ("xch", "a,b");
5910 emitcode ("cpl", "a"); // msb
5911 emitcode ("addc","a,#0");
5912 emitcode ("setb","F0");
5914 emitcode ("mov","ma,b");
5915 emitcode ("mov","ma,a");
5917 emitcode ("mov","ma,%s",aopGet(left,0,FALSE,FALSE,NULL));
5918 emitcode ("mov","ma,%s",aopGet(left,1,FALSE,FALSE,NULL));
5921 /* load up MB with right */
5923 if (AOP_TYPE(right) == AOP_LIT) {
5924 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5926 lbl = newiTempLabel(NULL);
5927 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5928 emitcode("setb","F0");
5932 emitcode ("mov","mb,#!constbyte",val & 0xff);
5933 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5935 lbl = newiTempLabel(NULL);
5936 emitcode ("mov","b,%s",aopGet(right,0,FALSE,FALSE,NULL));
5937 emitcode ("mov","a,%s",aopGet(right,1,FALSE,FALSE,NULL));
5938 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5939 emitcode ("xch", "a,b");
5940 emitcode ("cpl","a");
5941 emitcode ("add", "a,#1");
5942 emitcode ("xch", "a,b");
5943 emitcode ("cpl", "a"); // msb
5944 emitcode ("addc", "a,#0");
5945 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5946 emitcode ("setb","F0");
5948 emitcode ("mov","mb,b");
5949 emitcode ("mov","mb,a");
5952 emitcode ("mov","mb,%s",aopGet(right,0,FALSE,FALSE,NULL));
5953 emitcode ("mov","mb,%s",aopGet(right,1,FALSE,FALSE,NULL));
5956 /* wait for multiplication to finish */
5957 lbl = newiTempLabel(NULL);
5959 emitcode("mov","a,mcnt1");
5960 emitcode("anl","a,#!constbyte",0x80);
5961 emitcode("jnz","!tlabel",lbl->key+100);
5963 freeAsmop (left, NULL, ic, TRUE);
5964 freeAsmop (right, NULL, ic,TRUE);
5965 aopOp(result, ic, TRUE, FALSE);
5967 /* if unsigned then simple */
5969 aopPut(result,"ma",1);
5970 aopPut(result,"ma",0);
5972 emitcode("push","ma");
5974 /* negate result if needed */
5975 lbl = newiTempLabel(NULL);
5976 emitcode("jnb","F0,!tlabel",lbl->key+100);
5977 emitcode("cpl","a");
5978 emitcode("add","a,#1");
5980 aopPut(result,"a",0);
5981 emitcode("pop","acc");
5982 lbl = newiTempLabel(NULL);
5983 emitcode("jnb","F0,!tlabel",lbl->key+100);
5984 emitcode("cpl","a");
5985 emitcode("addc","a,#0");
5987 aopPut(result,"a",1);
5989 freeAsmop (result, NULL, ic, TRUE);
5990 /* restore EA bit in F1 */
5991 lbl = newiTempLabel(NULL);
5992 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5993 emitcode ("setb","EA");
5998 /*-----------------------------------------------------------------*/
5999 /* genDiv - generates code for division */
6000 /*-----------------------------------------------------------------*/
6004 operand *left = IC_LEFT (ic);
6005 operand *right = IC_RIGHT (ic);
6006 operand *result = IC_RESULT (ic);
6008 D (emitcode (";", "genDiv"));
6010 /* assign the amsops */
6013 /* special cases first */
6015 if (AOP_TYPE (left) == AOP_CRY &&
6016 AOP_TYPE (right) == AOP_CRY)
6018 genDivbits (left, right, result, ic);
6022 /* if both are of size == 1 */
6023 if (AOP_SIZE (left) == 1 &&
6024 AOP_SIZE (right) == 1)
6026 genDivOneByte (left, right, result, ic);
6030 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
6031 /* use the ds390 ARITHMETIC accel UNIT */
6032 genDivTwoByte (left, right, result, ic);
6035 /* should have been converted to function call */
6038 freeAsmop (result, NULL, ic, TRUE);
6039 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6040 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6043 /*-----------------------------------------------------------------*/
6044 /* genModbits :- modulus of bits */
6045 /*-----------------------------------------------------------------*/
6047 genModbits (operand * left,
6055 D (emitcode (";", "genModbits"));
6059 /* the result must be bit */
6060 LOAD_AB_FOR_DIV (left, right, l);
6061 emitcode ("div", "ab");
6062 emitcode ("mov", "a,b");
6063 emitcode ("rrc", "a");
6064 aopOp(result, ic, TRUE, FALSE);
6068 aopPut (result, "c", 0);
6071 /*-----------------------------------------------------------------*/
6072 /* genModOneByte : 8 bit modulus */
6073 /*-----------------------------------------------------------------*/
6075 genModOneByte (operand * left,
6080 bool lUnsigned, rUnsigned, pushedB;
6081 bool runtimeSign, compiletimeSign;
6086 D (emitcode (";", "genModOneByte"));
6089 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
6090 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
6094 /* signed or unsigned */
6095 if (lUnsigned && rUnsigned)
6097 /* unsigned is easy */
6098 LOAD_AB_FOR_DIV (left, right, l);
6099 emitcode ("div", "ab");
6100 aopOp (result, ic, TRUE, FALSE);
6101 aopPut (result, "b", 0);
6103 for (size = AOP_SIZE (result) - 1; size--;)
6104 aopPut (result, zero, offset++);
6110 /* signed is a little bit more difficult */
6112 /* now sign adjust for both left & right */
6114 /* modulus: sign of the right operand has no influence on the result! */
6115 if (AOP_TYPE(right) == AOP_LIT)
6117 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
6119 if (!rUnsigned && val < 0)
6120 emitcode ("mov", "b,#0x%02x", -val);
6122 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
6124 else /* not literal */
6127 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
6130 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
6131 lbl = newiTempLabel (NULL);
6132 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
6133 emitcode ("cpl", "a"); /* 2's complement */
6134 emitcode ("inc", "a");
6136 emitcode ("mov", "b,a");
6140 /* let's see what's needed: */
6141 /* apply negative sign during runtime */
6142 runtimeSign = FALSE;
6143 /* negative sign from literals */
6144 compiletimeSign = FALSE;
6146 /* sign adjust left side */
6147 if (AOP_TYPE(left) == AOP_LIT)
6149 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
6151 if (!lUnsigned && val < 0)
6153 compiletimeSign = TRUE; /* set sign flag */
6154 emitcode ("mov", "a,#0x%02x", -val);
6157 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
6159 else /* ! literal */
6161 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
6166 emitcode ("clr", "F0"); /* clear sign flag */
6168 lbl = newiTempLabel (NULL);
6169 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
6170 emitcode ("setb", "F0"); /* set sign flag */
6171 emitcode ("cpl", "a"); /* 2's complement */
6172 emitcode ("inc", "a");
6177 /* now the modulus */
6178 emitcode ("nop", "; workaround for DS80C390 div bug.");
6179 emitcode ("div", "ab");
6181 if (runtimeSign || compiletimeSign)
6183 emitcode ("mov", "a,b");
6184 lbl = newiTempLabel (NULL);
6186 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
6187 emitcode ("cpl", "a"); /* lsb 2's complement */
6188 emitcode ("inc", "a");
6192 aopOp (result, ic, TRUE, FALSE);
6193 size = AOP_SIZE (result) - 1;
6197 /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
6198 then the result will be in b, a */
6199 emitcode ("mov", "b,a"); /* 1 */
6200 /* msb is 0x00 or 0xff depending on the sign */
6203 emitcode ("mov", "c,F0");
6204 emitcode ("subb", "a,acc");
6205 emitcode ("xch", "a,b"); /* 2 */
6207 aopPut (result, "b", offset++); /* write msb's */
6209 else /* compiletimeSign */
6211 aopPut (result, "#0xff", offset++); /* write msb's */
6213 aopPut (result, "a", 0); /* 3: write lsb */
6218 aopOp(result, ic, TRUE, FALSE);
6219 size = AOP_SIZE (result) - 1;
6221 aopPut (result, "b", 0);
6223 aopPut (result, zero, offset++);
6229 /*-----------------------------------------------------------------*/
6230 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
6231 /*-----------------------------------------------------------------*/
6232 static void genModTwoByte (operand *left, operand *right,
6233 operand *result, iCode *ic)
6235 sym_link *retype = getSpec(operandType(right));
6236 sym_link *letype = getSpec(operandType(left));
6237 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
6240 /* load up MA with left */
6241 /* save EA bit in F1 */
6242 lbl = newiTempLabel(NULL);
6243 emitcode ("setb","F1");
6244 emitcode ("jbc","EA,!tlabel",lbl->key+100);
6245 emitcode ("clr","F1");
6249 lbl = newiTempLabel(NULL);
6250 emitcode ("mov","b,%s",aopGet(left,0,FALSE,FALSE,NULL));
6251 emitcode ("mov","a,%s",aopGet(left,1,FALSE,FALSE,NULL));
6252 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
6253 emitcode ("xch", "a,b");
6254 emitcode ("cpl","a");
6255 emitcode ("add", "a,#1");
6256 emitcode ("xch", "a,b");
6257 emitcode ("cpl", "a"); // msb
6258 emitcode ("addc","a,#0");
6260 emitcode ("mov","ma,b");
6261 emitcode ("mov","ma,a");
6263 emitcode ("mov","ma,%s",aopGet(left,0,FALSE,FALSE,NULL));
6264 emitcode ("mov","ma,%s",aopGet(left,1,FALSE,FALSE,NULL));
6267 /* load up MB with right */
6269 if (AOP_TYPE(right) == AOP_LIT) {
6270 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
6274 emitcode ("mov","mb,#!constbyte",val & 0xff);
6275 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
6277 lbl = newiTempLabel(NULL);
6278 emitcode ("mov","b,%s",aopGet(right,0,FALSE,FALSE,NULL));
6279 emitcode ("mov","a,%s",aopGet(right,1,FALSE,FALSE,NULL));
6280 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
6281 emitcode ("xch", "a,b");
6282 emitcode ("cpl","a");
6283 emitcode ("add", "a,#1");
6284 emitcode ("xch", "a,b");
6285 emitcode ("cpl", "a"); // msb
6286 emitcode ("addc", "a,#0");
6288 emitcode ("mov","mb,b");
6289 emitcode ("mov","mb,a");
6292 emitcode ("mov","mb,%s",aopGet(right,0,FALSE,FALSE,NULL));
6293 emitcode ("mov","mb,%s",aopGet(right,1,FALSE,FALSE,NULL));
6296 /* wait for multiplication to finish */
6297 lbl = newiTempLabel(NULL);
6299 emitcode("mov","a,mcnt1");
6300 emitcode("anl","a,#!constbyte",0x80);
6301 emitcode("jnz","!tlabel",lbl->key+100);
6303 freeAsmop (left, NULL, ic, TRUE);
6304 freeAsmop (right, NULL, ic,TRUE);
6305 aopOp(result, ic, TRUE, FALSE);
6307 aopPut(result,"mb",1);
6308 aopPut(result,"mb",0);
6309 freeAsmop (result, NULL, ic, TRUE);
6311 /* restore EA bit in F1 */
6312 lbl = newiTempLabel(NULL);
6313 emitcode ("jnb","F1,!tlabel",lbl->key+100);
6314 emitcode ("setb","EA");
6318 /*-----------------------------------------------------------------*/
6319 /* genMod - generates code for division */
6320 /*-----------------------------------------------------------------*/
6324 operand *left = IC_LEFT (ic);
6325 operand *right = IC_RIGHT (ic);
6326 operand *result = IC_RESULT (ic);
6328 D (emitcode (";", "genMod"));
6330 /* assign the asmops */
6333 /* special cases first */
6335 if (AOP_TYPE (left) == AOP_CRY &&
6336 AOP_TYPE (right) == AOP_CRY)
6338 genModbits (left, right, result, ic);
6342 /* if both are of size == 1 */
6343 if (AOP_SIZE (left) == 1 &&
6344 AOP_SIZE (right) == 1)
6346 genModOneByte (left, right, result, ic);
6350 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
6351 /* use the ds390 ARITHMETIC accel UNIT */
6352 genModTwoByte (left, right, result, ic);
6356 /* should have been converted to function call */
6360 freeAsmop (result, NULL, ic, TRUE);
6361 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6362 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6365 /*-----------------------------------------------------------------*/
6366 /* genIfxJump :- will create a jump depending on the ifx */
6367 /*-----------------------------------------------------------------*/
6369 genIfxJump (iCode * ic, char *jval)
6372 symbol *tlbl = newiTempLabel (NULL);
6375 D (emitcode (";", "genIfxJump"));
6377 /* if true label then we jump if condition
6381 jlbl = IC_TRUE (ic);
6382 inst = ((strcmp (jval, "a") == 0 ? "jz" :
6383 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
6387 /* false label is present */
6388 jlbl = IC_FALSE (ic);
6389 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
6390 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
6392 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
6393 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
6395 emitcode (inst, "!tlabel", tlbl->key + 100);
6396 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
6399 /* mark the icode as generated */
6403 /*-----------------------------------------------------------------*/
6404 /* genCmp :- greater or less than comparison */
6405 /*-----------------------------------------------------------------*/
6407 genCmp (operand * left, operand * right,
6408 iCode * ic, iCode * ifx, int sign)
6410 int size, offset = 0;
6411 unsigned long lit = 0L;
6414 D (emitcode (";", "genCmp"));
6416 result = IC_RESULT (ic);
6418 /* if left & right are bit variables */
6419 if (AOP_TYPE (left) == AOP_CRY &&
6420 AOP_TYPE (right) == AOP_CRY)
6422 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6423 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6427 /* subtract right from left if at the
6428 end the carry flag is set then we know that
6429 left is greater than right */
6430 size = max (AOP_SIZE (left), AOP_SIZE (right));
6432 /* if unsigned char cmp with lit, do cjne left,#right,zz */
6433 if ((size == 1) && !sign &&
6434 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
6436 symbol *lbl = newiTempLabel (NULL);
6437 emitcode ("cjne", "%s,%s,!tlabel",
6438 aopGet (left, offset, FALSE, FALSE, NULL),
6439 aopGet (right, offset, FALSE, FALSE, NULL),
6445 if (AOP_TYPE (right) == AOP_LIT)
6447 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6448 /* optimize if(x < 0) or if(x >= 0) */
6457 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
6459 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6460 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6462 aopOp (result, ic, FALSE, FALSE);
6464 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
6466 freeAsmop (result, NULL, ic, TRUE);
6467 genIfxJump (ifx, "acc.7");
6472 emitcode ("rlc", "a");
6474 goto release_freedLR;
6482 // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
6483 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
6484 // emitcode (";", "genCmp #2");
6485 if (sign && (size == 0))
6487 // emitcode (";", "genCmp #3");
6488 emitcode ("xrl", "a,#!constbyte",0x80);
6489 if (AOP_TYPE (right) == AOP_LIT)
6491 unsigned long lit = (unsigned long)
6492 floatFromVal (AOP (right)->aopu.aop_lit);
6493 // emitcode (";", "genCmp #3.1");
6494 emitcode ("subb", "a,#!constbyte",
6495 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
6499 // emitcode (";", "genCmp #3.2");
6501 MOVB (aopGet (right, offset++, FALSE, FALSE, "b"));
6502 saveAccWarn = DEFAULT_ACC_WARNING;
6503 emitcode ("xrl", "b,#!constbyte",0x80);
6504 emitcode ("subb", "a,b");
6511 // emitcode (";", "genCmp #4");
6513 s = aopGet (right, offset++, FALSE, FALSE, "b");
6514 saveAccWarn = DEFAULT_ACC_WARNING;
6516 emitcode ("subb", "a,%s", s);
6523 /* Don't need the left & right operands any more; do need the result. */
6524 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6525 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6527 aopOp (result, ic, FALSE, FALSE);
6531 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6537 /* if the result is used in the next
6538 ifx conditional branch then generate
6539 code a little differently */
6542 genIfxJump (ifx, "c");
6548 /* leave the result in acc */
6550 freeAsmop (result, NULL, ic, TRUE);
6553 /*-----------------------------------------------------------------*/
6554 /* genCmpGt :- greater than comparison */
6555 /*-----------------------------------------------------------------*/
6557 genCmpGt (iCode * ic, iCode * ifx)
6559 operand *left, *right;
6560 sym_link *letype, *retype;
6563 D (emitcode (";", "genCmpGt"));
6565 left = IC_LEFT (ic);
6566 right = IC_RIGHT (ic);
6568 letype = getSpec (operandType (left));
6569 retype = getSpec (operandType (right));
6570 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6572 /* assign the left & right amsops */
6575 genCmp (right, left, ic, ifx, sign);
6578 /*-----------------------------------------------------------------*/
6579 /* genCmpLt - less than comparisons */
6580 /*-----------------------------------------------------------------*/
6582 genCmpLt (iCode * ic, iCode * ifx)
6584 operand *left, *right;
6585 sym_link *letype, *retype;
6588 D (emitcode (";", "genCmpLt"));
6590 left = IC_LEFT (ic);
6591 right = IC_RIGHT (ic);
6593 letype = getSpec (operandType (left));
6594 retype = getSpec (operandType (right));
6595 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6597 /* assign the left & right amsops */
6600 genCmp (left, right, ic, ifx, sign);
6603 /*-----------------------------------------------------------------*/
6604 /* gencjneshort - compare and jump if not equal */
6605 /*-----------------------------------------------------------------*/
6607 gencjneshort (operand * left, operand * right, symbol * lbl)
6609 int size = max (AOP_SIZE (left), AOP_SIZE (right));
6611 unsigned long lit = 0L;
6613 D (emitcode (";", "gencjneshort"));
6615 /* if the left side is a literal or
6616 if the right is in a pointer register and left
6618 if ((AOP_TYPE (left) == AOP_LIT) ||
6619 (AOP_TYPE (left) == AOP_IMMD) ||
6620 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6627 if (AOP_TYPE (right) == AOP_LIT)
6628 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6630 if (opIsGptr (left) || opIsGptr (right))
6632 /* We are comparing a generic pointer to something.
6633 * Exclude the generic type byte from the comparison.
6636 D (emitcode (";", "cjneshort: generic ptr special case."););
6640 /* if the right side is a literal then anything goes */
6641 if (AOP_TYPE (right) == AOP_LIT &&
6642 AOP_TYPE (left) != AOP_DIR)
6646 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
6647 emitcode ("cjne", "a,%s,!tlabel",
6648 aopGet (right, offset, FALSE, FALSE, NULL),
6654 /* if the right side is in a register or in direct space or
6655 if the left is a pointer register & right is not */
6656 else if (AOP_TYPE (right) == AOP_REG ||
6657 AOP_TYPE (right) == AOP_DIR ||
6658 AOP_TYPE (right) == AOP_LIT ||
6659 AOP_TYPE (right) == AOP_IMMD ||
6660 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6661 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6665 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
6666 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6667 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6668 emitcode ("jnz", "!tlabel", lbl->key + 100);
6670 emitcode ("cjne", "a,%s,!tlabel",
6671 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG),
6678 /* right is a pointer reg need both a & b */
6681 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
6682 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
6683 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
6689 /*-----------------------------------------------------------------*/
6690 /* gencjne - compare and jump if not equal */
6691 /*-----------------------------------------------------------------*/
6693 gencjne (operand * left, operand * right, symbol * lbl)
6695 symbol *tlbl = newiTempLabel (NULL);
6697 D (emitcode (";", "gencjne"));
6699 gencjneshort (left, right, lbl);
6701 emitcode ("mov", "a,%s", one);
6702 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
6704 emitcode ("clr", "a");
6708 /*-----------------------------------------------------------------*/
6709 /* genCmpEq - generates code for equal to */
6710 /*-----------------------------------------------------------------*/
6712 genCmpEq (iCode * ic, iCode * ifx)
6714 operand *left, *right, *result;
6716 D (emitcode (";", "genCmpEq"));
6719 AOP_SET_LOCALS (ic);
6721 /* if literal, literal on the right or
6722 if the right is in a pointer register and left
6724 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6725 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6727 operand *t = IC_RIGHT (ic);
6728 IC_RIGHT (ic) = IC_LEFT (ic);
6732 if (ifx && /* !AOP_SIZE(result) */
6733 OP_SYMBOL (result) &&
6734 OP_SYMBOL (result)->regType == REG_CND)
6737 /* if they are both bit variables */
6738 if (AOP_TYPE (left) == AOP_CRY &&
6739 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6741 if (AOP_TYPE (right) == AOP_LIT)
6743 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6746 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6747 emitcode ("cpl", "c");
6751 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6755 emitcode ("clr", "c");
6757 /* AOP_TYPE(right) == AOP_CRY */
6761 symbol *lbl = newiTempLabel (NULL);
6762 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6763 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6764 emitcode ("cpl", "c");
6767 /* if true label then we jump if condition
6769 tlbl = newiTempLabel (NULL);
6772 emitcode ("jnc", "!tlabel", tlbl->key + 100);
6773 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6777 emitcode ("jc", "!tlabel", tlbl->key + 100);
6778 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6784 tlbl = newiTempLabel (NULL);
6785 gencjneshort (left, right, tlbl);
6788 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6793 symbol *lbl = newiTempLabel (NULL);
6794 emitcode ("sjmp", "!tlabel", lbl->key + 100);
6796 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6800 /* mark the icode as generated */
6803 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6804 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6808 /* if they are both bit variables */
6809 if (AOP_TYPE (left) == AOP_CRY &&
6810 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6812 if (AOP_TYPE (right) == AOP_LIT)
6814 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6817 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6818 emitcode ("cpl", "c");
6822 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6826 emitcode ("clr", "c");
6828 /* AOP_TYPE(right) == AOP_CRY */
6832 symbol *lbl = newiTempLabel (NULL);
6833 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6834 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6835 emitcode ("cpl", "c");
6839 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6840 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6842 aopOp (result, ic, TRUE, FALSE);
6845 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6852 genIfxJump (ifx, "c");
6855 /* if the result is used in an arithmetic operation
6856 then put the result in place */
6861 gencjne (left, right, newiTempLabel (NULL));
6863 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6864 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6866 aopOp (result, ic, TRUE, FALSE);
6868 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6870 aopPut (result, "a", 0);
6875 genIfxJump (ifx, "a");
6878 /* if the result is used in an arithmetic operation
6879 then put the result in place */
6880 if (AOP_TYPE (result) != AOP_CRY)
6882 /* leave the result in acc */
6886 freeAsmop (result, NULL, ic, TRUE);
6889 /*-----------------------------------------------------------------*/
6890 /* ifxForOp - returns the icode containing the ifx for operand */
6891 /*-----------------------------------------------------------------*/
6893 ifxForOp (operand * op, iCode * ic)
6895 /* if true symbol then needs to be assigned */
6896 if (IS_TRUE_SYMOP (op))
6899 /* if this has register type condition and
6900 the next instruction is ifx with the same operand
6901 and live to of the operand is upto the ifx only then */
6903 ic->next->op == IFX &&
6904 IC_COND (ic->next)->key == op->key &&
6905 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6911 /*-----------------------------------------------------------------*/
6912 /* hasInc - operand is incremented before any other use */
6913 /*-----------------------------------------------------------------*/
6915 hasInc (operand *op, iCode *ic, int osize)
6917 sym_link *type = operandType(op);
6918 sym_link *retype = getSpec (type);
6919 iCode *lic = ic->next;
6922 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6923 if (!IS_SYMOP(op)) return NULL;
6925 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6926 if (IS_AGGREGATE(type->next)) return NULL;
6927 if (osize != (isize = getSize(type->next))) return NULL;
6930 /* if operand of the form op = op + <sizeof *op> */
6931 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6932 isOperandEqual(IC_RESULT(lic),op) &&
6933 isOperandLiteral(IC_RIGHT(lic)) &&
6934 operandLitValue(IC_RIGHT(lic)) == isize) {
6937 /* if the operand used or deffed */
6938 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6941 /* if GOTO or IFX */
6942 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6948 /*-----------------------------------------------------------------*/
6949 /* genAndOp - for && operation */
6950 /*-----------------------------------------------------------------*/
6952 genAndOp (iCode * ic)
6954 operand *left, *right, *result;
6957 D (emitcode (";", "genAndOp"));
6959 /* note here that && operations that are in an
6960 if statement are taken away by backPatchLabels
6961 only those used in arthmetic operations remain */
6963 AOP_SET_LOCALS (ic);
6965 /* if both are bit variables */
6966 if (AOP_TYPE (left) == AOP_CRY &&
6967 AOP_TYPE (right) == AOP_CRY)
6969 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6970 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6971 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6972 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6974 aopOp (result,ic,FALSE, FALSE);
6979 tlbl = newiTempLabel (NULL);
6981 emitcode ("jz", "!tlabel", tlbl->key + 100);
6984 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6985 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6987 aopOp (result,ic,FALSE, FALSE);
6991 freeAsmop (result, NULL, ic, TRUE);
6995 /*-----------------------------------------------------------------*/
6996 /* genOrOp - for || operation */
6997 /*-----------------------------------------------------------------*/
6999 genOrOp (iCode * ic)
7001 operand *left, *right, *result;
7004 D (emitcode (";", "genOrOp"));
7006 /* note here that || operations that are in an
7007 if statement are taken away by backPatchLabels
7008 only those used in arthmetic operations remain */
7010 AOP_SET_LOCALS (ic);
7012 /* if both are bit variables */
7013 if (AOP_TYPE (left) == AOP_CRY &&
7014 AOP_TYPE (right) == AOP_CRY)
7016 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7017 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
7018 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7019 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7021 aopOp (result,ic,FALSE, FALSE);
7027 tlbl = newiTempLabel (NULL);
7029 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7032 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7033 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7035 aopOp (result,ic,FALSE, FALSE);
7040 freeAsmop (result, NULL, ic, TRUE);
7043 /*-----------------------------------------------------------------*/
7044 /* isLiteralBit - test if lit == 2^n */
7045 /*-----------------------------------------------------------------*/
7047 isLiteralBit (unsigned long lit)
7049 unsigned long pw[32] =
7050 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
7051 0x100L, 0x200L, 0x400L, 0x800L,
7052 0x1000L, 0x2000L, 0x4000L, 0x8000L,
7053 0x10000L, 0x20000L, 0x40000L, 0x80000L,
7054 0x100000L, 0x200000L, 0x400000L, 0x800000L,
7055 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
7056 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
7059 for (idx = 0; idx < 32; idx++)
7065 /*-----------------------------------------------------------------*/
7066 /* continueIfTrue - */
7067 /*-----------------------------------------------------------------*/
7069 continueIfTrue (iCode * ic)
7072 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
7076 /*-----------------------------------------------------------------*/
7078 /*-----------------------------------------------------------------*/
7080 jumpIfTrue (iCode * ic)
7083 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
7087 /*-----------------------------------------------------------------*/
7088 /* jmpTrueOrFalse - */
7089 /*-----------------------------------------------------------------*/
7091 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
7093 // ugly but optimized by peephole
7096 symbol *nlbl = newiTempLabel (NULL);
7097 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
7099 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
7104 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
7110 // Generate code to perform a bit-wise logic operation
7111 // on two operands in far space (assumed to already have been
7112 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
7113 // in far space. This requires pushing the result on the stack
7114 // then popping it into the result.
7116 genFarFarLogicOp(iCode *ic, char *logicOp)
7118 int size, resultSize, compSize;
7122 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
7123 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
7124 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
7126 _startLazyDPSEvaluation();
7127 for (size = compSize; (size--); offset++)
7129 MOVA (aopGet (IC_LEFT(ic), offset, FALSE, FALSE, NULL));
7130 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
7131 MOVA (aopGet (IC_RIGHT(ic), offset, FALSE, FALSE, NULL));
7133 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
7134 emitcode ("push", "acc");
7136 _endLazyDPSEvaluation();
7138 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7139 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7140 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
7142 resultSize = AOP_SIZE(IC_RESULT(ic));
7144 ADJUST_PUSHED_RESULT(compSize, resultSize);
7146 _startLazyDPSEvaluation();
7149 emitcode ("pop", "acc");
7150 aopPut (IC_RESULT (ic), "a", compSize);
7152 _endLazyDPSEvaluation();
7153 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
7157 /*-----------------------------------------------------------------*/
7158 /* genAnd - code for and */
7159 /*-----------------------------------------------------------------*/
7161 genAnd (iCode * ic, iCode * ifx)
7163 operand *left, *right, *result;
7164 int size, offset = 0;
7165 unsigned long lit = 0L;
7170 D (emitcode (";", "genAnd"));
7172 AOP_OP_3_NOFATAL (ic, pushResult);
7173 AOP_SET_LOCALS (ic);
7177 genFarFarLogicOp(ic, "anl");
7182 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7184 AOP_TYPE (left), AOP_TYPE (right));
7185 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7187 AOP_SIZE (left), AOP_SIZE (right));
7190 /* if left is a literal & right is not then exchange them */
7191 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7192 #ifdef LOGIC_OPS_BROKEN
7193 || AOP_NEEDSACC (left)
7197 operand *tmp = right;
7202 /* if result = right then exchange left and right */
7203 if (sameRegs (AOP (result), AOP (right)))
7205 operand *tmp = right;
7210 /* if right is bit then exchange them */
7211 if (AOP_TYPE (right) == AOP_CRY &&
7212 AOP_TYPE (left) != AOP_CRY)
7214 operand *tmp = right;
7218 if (AOP_TYPE (right) == AOP_LIT)
7219 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7221 size = AOP_SIZE (result);
7224 // result = bit & yy;
7225 if (AOP_TYPE (left) == AOP_CRY)
7227 // c = bit & literal;
7228 if (AOP_TYPE (right) == AOP_LIT)
7232 if (size && sameRegs (AOP (result), AOP (left)))
7235 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7240 if (size && (AOP_TYPE (result) == AOP_CRY))
7242 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
7245 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7250 emitcode ("clr", "c");
7255 if (AOP_TYPE (right) == AOP_CRY)
7258 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7259 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
7264 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
7266 emitcode ("rrc", "a");
7267 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
7275 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7276 genIfxJump (ifx, "c");
7280 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7281 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7282 if ((AOP_TYPE (right) == AOP_LIT) &&
7283 (AOP_TYPE (result) == AOP_CRY) &&
7284 (AOP_TYPE (left) != AOP_CRY))
7286 int posbit = isLiteralBit (lit);
7291 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE, NULL));
7295 switch (posbit & 0x07)
7297 case 0: emitcode ("rrc", "a");
7299 case 7: emitcode ("rlc", "a");
7301 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
7310 SNPRINTF (buffer, sizeof(buffer),
7311 "acc.%d", posbit & 0x07);
7312 genIfxJump (ifx, buffer);
7316 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
7323 symbol *tlbl = newiTempLabel (NULL);
7324 int sizel = AOP_SIZE (left);
7326 emitcode ("setb", "c");
7329 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
7331 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7333 if ((posbit = isLiteralBit (bytelit)) != 0)
7334 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
7337 if (bytelit != 0x0FFL)
7338 emitcode ("anl", "a,%s",
7339 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG));
7340 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7345 // bit = left & literal
7348 emitcode ("clr", "c");
7351 // if(left & literal)
7355 jmpTrueOrFalse (ifx, tlbl);
7365 /* if left is same as result */
7366 if (sameRegs (AOP (result), AOP (left)))
7368 for (; size--; offset++)
7370 if (AOP_TYPE (right) == AOP_LIT)
7372 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7373 if (bytelit == 0x0FF)
7375 /* dummy read of volatile operand */
7376 if (isOperandVolatile (left, FALSE))
7377 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7381 else if (bytelit == 0)
7383 aopPut (result, zero, offset);
7385 else if (IS_AOP_PREG (result))
7387 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7388 emitcode ("anl", "a,%s",
7389 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG));
7390 aopPut (result, "a", offset);
7393 emitcode ("anl", "%s,%s",
7394 aopGet (left, offset, FALSE, TRUE, NULL),
7395 aopGet (right, offset, FALSE, FALSE, NULL));
7399 if (AOP_TYPE (left) == AOP_ACC)
7400 emitcode ("anl", "a,%s",
7401 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7404 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7405 if (IS_AOP_PREG (result))
7407 emitcode ("anl", "a,%s",
7408 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7409 aopPut (result, "a", offset);
7412 emitcode ("anl", "%s,a",
7413 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7420 // left & result in different registers
7421 if (AOP_TYPE (result) == AOP_CRY)
7424 // if(size), result in bit
7425 // if(!size && ifx), conditional oper: if(left & right)
7426 symbol *tlbl = newiTempLabel (NULL);
7427 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
7429 emitcode ("setb", "c");
7432 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7433 emitcode ("anl", "a,%s",
7434 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7436 if (AOP_TYPE(left)==AOP_ACC)
7438 bool pushedB = pushB ();
7439 emitcode("mov", "b,a");
7440 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7441 emitcode("anl", "a,b");
7446 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7447 emitcode ("anl", "a,%s",
7448 aopGet (left, offset, FALSE, FALSE, DP2_RESULT_REG));
7451 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7461 jmpTrueOrFalse (ifx, tlbl);
7467 for (; (size--); offset++)
7470 // result = left & right
7471 if (AOP_TYPE (right) == AOP_LIT)
7473 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7474 if (bytelit == 0x0FF)
7477 aopGet (left, offset, FALSE, FALSE, NULL),
7481 else if (bytelit == 0)
7483 /* dummy read of volatile operand */
7484 if (isOperandVolatile (left, FALSE))
7485 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7486 aopPut (result, zero, offset);
7489 D (emitcode (";", "better literal AND."));
7490 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7491 emitcode ("anl", "a, %s", aopGet (right, offset,
7492 FALSE, FALSE, DP2_RESULT_REG));
7497 // faster than result <- left, anl result,right
7498 // and better if result is SFR
7499 if (AOP_TYPE (left) == AOP_ACC)
7501 emitcode ("anl", "a,%s",
7502 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7506 char *rOp = aopGet (right, offset, FALSE, FALSE, NULL);
7507 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7509 emitcode("mov", "b,a");
7513 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7514 emitcode ("anl", "a,%s", rOp);
7517 aopPut (result, "a", offset);
7523 freeAsmop (result, NULL, ic, TRUE);
7524 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7525 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7528 /*-----------------------------------------------------------------*/
7529 /* genOr - code for or */
7530 /*-----------------------------------------------------------------*/
7532 genOr (iCode * ic, iCode * ifx)
7534 operand *left, *right, *result;
7535 int size, offset = 0;
7536 unsigned long lit = 0L;
7540 D (emitcode (";", "genOr"));
7542 AOP_OP_3_NOFATAL (ic, pushResult);
7543 AOP_SET_LOCALS (ic);
7547 genFarFarLogicOp(ic, "orl");
7553 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7555 AOP_TYPE (left), AOP_TYPE (right));
7556 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7558 AOP_SIZE (left), AOP_SIZE (right));
7561 /* if left is a literal & right is not then exchange them */
7562 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7563 #ifdef LOGIC_OPS_BROKEN
7564 || AOP_NEEDSACC (left) // I think this is a net loss now.
7568 operand *tmp = right;
7573 /* if result = right then exchange them */
7574 if (sameRegs (AOP (result), AOP (right)))
7576 operand *tmp = right;
7581 /* if right is bit then exchange them */
7582 if (AOP_TYPE (right) == AOP_CRY &&
7583 AOP_TYPE (left) != AOP_CRY)
7585 operand *tmp = right;
7589 if (AOP_TYPE (right) == AOP_LIT)
7590 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7592 size = AOP_SIZE (result);
7596 if (AOP_TYPE (left) == AOP_CRY)
7598 if (AOP_TYPE (right) == AOP_LIT)
7600 // c = bit | literal;
7603 // lit != 0 => result = 1
7604 if (AOP_TYPE (result) == AOP_CRY)
7607 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7609 continueIfTrue (ifx);
7612 emitcode ("setb", "c");
7616 // lit == 0 => result = left
7617 if (size && sameRegs (AOP (result), AOP (left)))
7619 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7624 if (AOP_TYPE (right) == AOP_CRY)
7627 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7628 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7633 symbol *tlbl = newiTempLabel (NULL);
7634 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
7635 emitcode ("setb", "c");
7636 emitcode ("jb", "%s,!tlabel",
7637 AOP (left)->aopu.aop_dir, tlbl->key + 100);
7639 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7640 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7642 jmpTrueOrFalse (ifx, tlbl);
7657 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7658 genIfxJump (ifx, "c");
7662 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7663 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7664 if ((AOP_TYPE (right) == AOP_LIT) &&
7665 (AOP_TYPE (result) == AOP_CRY) &&
7666 (AOP_TYPE (left) != AOP_CRY))
7672 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7674 continueIfTrue (ifx);
7679 // lit = 0, result = boolean(left)
7681 emitcode ("setb", "c");
7685 symbol *tlbl = newiTempLabel (NULL);
7686 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7692 genIfxJump (ifx, "a");
7700 /* if left is same as result */
7701 if (sameRegs (AOP (result), AOP (left)))
7703 for (; size--; offset++)
7705 if (AOP_TYPE (right) == AOP_LIT)
7707 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7710 /* dummy read of volatile operand */
7711 if (isOperandVolatile (left, FALSE))
7712 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7716 else if (bytelit == 0x0FF)
7718 aopPut (result, "#0xFF", offset);
7720 else if (IS_AOP_PREG (left))
7722 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7723 emitcode ("orl", "a,%s",
7724 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7725 aopPut (result, "a", offset);
7729 emitcode ("orl", "%s,%s",
7730 aopGet (left, offset, FALSE, TRUE, NULL),
7731 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7736 if (AOP_TYPE (left) == AOP_ACC)
7738 emitcode ("orl", "a,%s",
7739 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7743 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7744 if (IS_AOP_PREG (left))
7746 emitcode ("orl", "a,%s",
7747 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7748 aopPut (result, "a", offset);
7752 emitcode ("orl", "%s,a",
7753 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7761 // left & result in different registers
7762 if (AOP_TYPE (result) == AOP_CRY)
7765 // if(size), result in bit
7766 // if(!size && ifx), conditional oper: if(left | right)
7767 symbol *tlbl = newiTempLabel (NULL);
7768 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7770 emitcode ("setb", "c");
7773 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7774 emitcode ("orl", "a,%s",
7775 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7777 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7778 emitcode ("orl", "a,%s",
7779 aopGet (left, offset, FALSE, FALSE, DP2_RESULT_REG));
7781 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7791 jmpTrueOrFalse (ifx, tlbl);
7797 _startLazyDPSEvaluation();
7798 for (; (size--); offset++)
7801 // result = left | right
7802 if (AOP_TYPE (right) == AOP_LIT)
7804 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7808 aopGet (left, offset, FALSE, FALSE, NULL),
7812 else if (bytelit == 0x0FF)
7814 /* dummy read of volatile operand */
7815 if (isOperandVolatile (left, FALSE))
7816 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7817 aopPut (result, "#0xFF", offset);
7820 D (emitcode (";", "better literal OR."));
7821 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7822 emitcode ("orl", "a, %s",
7823 aopGet (right, offset,
7824 FALSE, FALSE, DP2_RESULT_REG));
7829 // faster than result <- left, anl result,right
7830 // and better if result is SFR
7831 if (AOP_TYPE (left) == AOP_ACC)
7833 emitcode ("orl", "a,%s",
7834 aopGet (right, offset,
7835 FALSE, FALSE, DP2_RESULT_REG));
7839 char *rOp = aopGet (right, offset, FALSE, FALSE, NULL);
7841 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7843 emitcode("mov", "b,a");
7847 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7848 emitcode ("orl", "a,%s", rOp);
7851 aopPut (result, "a", offset);
7853 _endLazyDPSEvaluation();
7858 freeAsmop (result, NULL, ic, TRUE);
7859 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7860 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7863 /*-----------------------------------------------------------------*/
7864 /* genXor - code for xclusive or */
7865 /*-----------------------------------------------------------------*/
7867 genXor (iCode * ic, iCode * ifx)
7869 operand *left, *right, *result;
7870 int size, offset = 0;
7871 unsigned long lit = 0L;
7875 D (emitcode (";", "genXor"));
7877 AOP_OP_3_NOFATAL (ic, pushResult);
7878 AOP_SET_LOCALS (ic);
7882 genFarFarLogicOp(ic, "xrl");
7887 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7889 AOP_TYPE (left), AOP_TYPE (right));
7890 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7892 AOP_SIZE (left), AOP_SIZE (right));
7895 /* if left is a literal & right is not ||
7896 if left needs acc & right does not */
7897 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7898 #ifdef LOGIC_OPS_BROKEN
7899 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
7903 operand *tmp = right;
7908 /* if result = right then exchange them */
7909 if (sameRegs (AOP (result), AOP (right)))
7911 operand *tmp = right;
7916 /* if right is bit then exchange them */
7917 if (AOP_TYPE (right) == AOP_CRY &&
7918 AOP_TYPE (left) != AOP_CRY)
7920 operand *tmp = right;
7924 if (AOP_TYPE (right) == AOP_LIT)
7925 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7927 size = AOP_SIZE (result);
7931 if (AOP_TYPE (left) == AOP_CRY)
7933 if (AOP_TYPE (right) == AOP_LIT)
7935 // c = bit & literal;
7938 // lit>>1 != 0 => result = 1
7939 if (AOP_TYPE (result) == AOP_CRY)
7942 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7944 continueIfTrue (ifx);
7947 emitcode ("setb", "c");
7954 // lit == 0, result = left
7955 if (size && sameRegs (AOP (result), AOP (left)))
7957 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7961 // lit == 1, result = not(left)
7962 if (size && sameRegs (AOP (result), AOP (left)))
7964 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7969 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7970 emitcode ("cpl", "c");
7979 symbol *tlbl = newiTempLabel (NULL);
7980 if (AOP_TYPE (right) == AOP_CRY)
7983 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7987 int sizer = AOP_SIZE (right);
7989 // if val>>1 != 0, result = 1
7990 emitcode ("setb", "c");
7993 MOVA (aopGet (right, sizer - 1, FALSE, FALSE, NULL));
7995 // test the msb of the lsb
7996 emitcode ("anl", "a,#!constbyte",0xfe);
7997 emitcode ("jnz", "!tlabel", tlbl->key + 100);
8001 emitcode ("rrc", "a");
8003 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
8004 emitcode ("cpl", "c");
8012 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
8013 genIfxJump (ifx, "c");
8017 /* if left is same as result */
8018 if (sameRegs (AOP (result), AOP (left)))
8020 for (; size--; offset++)
8022 if (AOP_TYPE (right) == AOP_LIT)
8024 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
8027 /* dummy read of volatile operand */
8028 if (isOperandVolatile (left, FALSE))
8029 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8033 else if (IS_AOP_PREG (left))
8035 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8036 emitcode ("xrl", "a,%s",
8037 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG));
8038 aopPut (result, "a", offset);
8042 emitcode ("xrl", "%s,%s",
8043 aopGet (left, offset, FALSE, TRUE, NULL),
8044 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8049 if (AOP_TYPE (left) == AOP_ACC)
8050 emitcode ("xrl", "a,%s",
8051 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8054 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
8055 if (IS_AOP_PREG (left))
8057 emitcode ("xrl", "a,%s",
8058 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
8059 aopPut (result, "a", offset);
8062 emitcode ("xrl", "%s,a",
8063 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
8070 // left & result in different registers
8071 if (AOP_TYPE (result) == AOP_CRY)
8074 // if(size), result in bit
8075 // if(!size && ifx), conditional oper: if(left ^ right)
8076 symbol *tlbl = newiTempLabel (NULL);
8077 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
8080 emitcode ("setb", "c");
8083 if ((AOP_TYPE (right) == AOP_LIT) &&
8084 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
8086 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8090 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
8091 emitcode ("xrl", "a,%s",
8092 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8094 char *rOp = aopGet (right, offset, FALSE, FALSE, NULL);
8095 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
8097 emitcode("mov", "b,a");
8101 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8102 emitcode ("xrl", "a,%s", rOp);
8105 emitcode ("jnz", "!tlabel", tlbl->key + 100);
8115 jmpTrueOrFalse (ifx, tlbl);
8119 for (; (size--); offset++)
8122 // result = left ^ right
8123 if (AOP_TYPE (right) == AOP_LIT)
8125 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
8129 aopGet (left, offset, FALSE, FALSE, NULL),
8133 D (emitcode (";", "better literal XOR."));
8134 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8135 emitcode ("xrl", "a, %s",
8136 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8140 // faster than result <- left, anl result,right
8141 // and better if result is SFR
8142 if (AOP_TYPE (left) == AOP_ACC)
8144 emitcode ("xrl", "a,%s",
8145 aopGet (right, offset,
8146 FALSE, FALSE, DP2_RESULT_REG));
8150 char *rOp = aopGet (right, offset, FALSE, FALSE, NULL);
8151 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
8153 emitcode("mov", "b,a");
8157 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8158 emitcode ("xrl", "a,%s", rOp);
8161 aopPut (result, "a", offset);
8167 freeAsmop (result, NULL, ic, TRUE);
8168 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
8169 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
8172 /*-----------------------------------------------------------------*/
8173 /* genInline - write the inline code out */
8174 /*-----------------------------------------------------------------*/
8176 genInline (iCode * ic)
8178 char *buffer, *bp, *bp1;
8180 D (emitcode (";", "genInline"));
8182 _G.inLine += (!options.asmpeep);
8184 buffer = bp = bp1 = Safe_strdup(IC_INLINE(ic));
8186 /* emit each line as a code */
8197 /* Add \n for labels, not dirs such as c:\mydir */
8198 if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
8212 /* emitcode("",buffer); */
8213 _G.inLine -= (!options.asmpeep);
8216 /*-----------------------------------------------------------------*/
8217 /* genRRC - rotate right with carry */
8218 /*-----------------------------------------------------------------*/
8222 operand *left, *result;
8226 D (emitcode (";", "genRRC"));
8228 /* rotate right with carry */
8229 left = IC_LEFT (ic);
8230 result = IC_RESULT (ic);
8231 aopOp (left, ic, FALSE, FALSE);
8232 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8234 /* move it to the result */
8235 size = AOP_SIZE (result);
8239 _startLazyDPSEvaluation ();
8242 l = aopGet (left, offset, FALSE, FALSE, NULL);
8244 emitcode ("rrc", "a");
8245 if (AOP_SIZE (result) > 1)
8246 aopPut (result, "a", offset--);
8248 _endLazyDPSEvaluation ();
8250 /* now we need to put the carry into the
8251 highest order byte of the result */
8252 if (AOP_SIZE (result) > 1)
8254 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE, NULL);
8257 emitcode ("mov", "acc.7,c");
8258 aopPut (result, "a", AOP_SIZE (result) - 1);
8259 freeAsmop (result, NULL, ic, TRUE);
8260 freeAsmop (left, NULL, ic, TRUE);
8263 /*-----------------------------------------------------------------*/
8264 /* genRLC - generate code for rotate left with carry */
8265 /*-----------------------------------------------------------------*/
8269 operand *left, *result;
8273 D (emitcode (";", "genRLC"));
8275 /* rotate right with carry */
8276 left = IC_LEFT (ic);
8277 result = IC_RESULT (ic);
8278 aopOp (left, ic, FALSE, FALSE);
8279 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8281 /* move it to the result */
8282 size = AOP_SIZE (result);
8286 l = aopGet (left, offset, FALSE, FALSE, NULL);
8288 emitcode ("add", "a,acc");
8289 if (AOP_SIZE (result) > 1)
8291 aopPut (result, "a", offset++);
8294 _startLazyDPSEvaluation ();
8297 l = aopGet (left, offset, FALSE, FALSE, NULL);
8299 emitcode ("rlc", "a");
8300 if (AOP_SIZE (result) > 1)
8301 aopPut (result, "a", offset++);
8303 _endLazyDPSEvaluation ();
8305 /* now we need to put the carry into the
8306 highest order byte of the result */
8307 if (AOP_SIZE (result) > 1)
8309 l = aopGet (result, 0, FALSE, FALSE, NULL);
8312 emitcode ("mov", "acc.0,c");
8313 aopPut (result, "a", 0);
8314 freeAsmop (result, NULL, ic, TRUE);
8315 freeAsmop (left, NULL, ic, TRUE);
8318 /*-----------------------------------------------------------------*/
8319 /* genGetHbit - generates code get highest order bit */
8320 /*-----------------------------------------------------------------*/
8322 genGetHbit (iCode * ic)
8324 operand *left, *result;
8326 D (emitcode (";", "genGetHbit"));
8328 left = IC_LEFT (ic);
8329 result = IC_RESULT (ic);
8330 aopOp (left, ic, FALSE, FALSE);
8331 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8333 /* get the highest order byte into a */
8334 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
8335 if (AOP_TYPE (result) == AOP_CRY)
8337 emitcode ("rlc", "a");
8342 emitcode ("rl", "a");
8343 emitcode ("anl", "a,#1");
8348 freeAsmop (result, NULL, ic, TRUE);
8349 freeAsmop (left, NULL, ic, TRUE);
8352 /*-----------------------------------------------------------------*/
8353 /* genSwap - generates code to swap nibbles or bytes */
8354 /*-----------------------------------------------------------------*/
8356 genSwap (iCode * ic)
8358 operand *left, *result;
8360 D(emitcode ("; genSwap",""));
8362 left = IC_LEFT (ic);
8363 result = IC_RESULT (ic);
8364 aopOp (left, ic, FALSE, FALSE);
8365 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8367 _startLazyDPSEvaluation ();
8368 switch (AOP_SIZE (left))
8370 case 1: /* swap nibbles in byte */
8371 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
8372 emitcode ("swap", "a");
8373 aopPut (result, "a", 0);
8375 case 2: /* swap bytes in word */
8376 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
8378 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
8379 aopPut (result, aopGet (left, 1, FALSE, FALSE, NULL), 0);
8380 aopPut (result, "a", 1);
8382 else if (operandsEqu (left, result))
8385 bool pushedB = FALSE, leftInB = FALSE;
8387 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
8388 if (AOP_NEEDSACC (left) || AOP_NEEDSACC (result))
8391 emitcode ("mov", "b,a");
8395 aopPut (result, aopGet (left, 1, FALSE, FALSE, NULL), 0);
8396 aopPut (result, reg, 1);
8403 aopPut (result, aopGet (left, 1, FALSE, FALSE, NULL), 0);
8404 aopPut (result, aopGet (left, 0, FALSE, FALSE, NULL), 1);
8408 wassertl(FALSE, "unsupported SWAP operand size");
8410 _endLazyDPSEvaluation ();
8412 freeAsmop (result, NULL, ic, TRUE);
8413 freeAsmop (left, NULL, ic, TRUE);
8416 /*-----------------------------------------------------------------*/
8417 /* AccRol - rotate left accumulator by known count */
8418 /*-----------------------------------------------------------------*/
8420 AccRol (int shCount)
8422 shCount &= 0x0007; // shCount : 0..7
8429 emitcode ("rl", "a");
8432 emitcode ("rl", "a");
8433 emitcode ("rl", "a");
8436 emitcode ("swap", "a");
8437 emitcode ("rr", "a");
8440 emitcode ("swap", "a");
8443 emitcode ("swap", "a");
8444 emitcode ("rl", "a");
8447 emitcode ("rr", "a");
8448 emitcode ("rr", "a");
8451 emitcode ("rr", "a");
8456 /*-----------------------------------------------------------------*/
8457 /* AccLsh - left shift accumulator by known count */
8458 /*-----------------------------------------------------------------*/
8460 AccLsh (int shCount)
8465 emitcode ("add", "a,acc");
8466 else if (shCount == 2)
8468 emitcode ("add", "a,acc");
8469 emitcode ("add", "a,acc");
8473 /* rotate left accumulator */
8475 /* and kill the lower order bits */
8476 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
8481 /*-----------------------------------------------------------------*/
8482 /* AccRsh - right shift accumulator by known count */
8483 /*-----------------------------------------------------------------*/
8485 AccRsh (int shCount)
8492 emitcode ("rrc", "a");
8496 /* rotate right accumulator */
8497 AccRol (8 - shCount);
8498 /* and kill the higher order bits */
8499 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
8504 #ifdef BETTER_LITERAL_SHIFT
8505 /*-----------------------------------------------------------------*/
8506 /* AccSRsh - signed right shift accumulator by known count */
8507 /*-----------------------------------------------------------------*/
8509 AccSRsh (int shCount)
8516 emitcode ("mov", "c,acc.7");
8517 emitcode ("rrc", "a");
8519 else if (shCount == 2)
8521 emitcode ("mov", "c,acc.7");
8522 emitcode ("rrc", "a");
8523 emitcode ("mov", "c,acc.7");
8524 emitcode ("rrc", "a");
8528 tlbl = newiTempLabel (NULL);
8529 /* rotate right accumulator */
8530 AccRol (8 - shCount);
8531 /* and kill the higher order bits */
8532 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
8533 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8534 emitcode ("orl", "a,#!constbyte",
8535 (unsigned char) ~SRMask[shCount]);
8542 #ifdef BETTER_LITERAL_SHIFT
8543 /*-----------------------------------------------------------------*/
8544 /* shiftR1Left2Result - shift right one byte from left to result */
8545 /*-----------------------------------------------------------------*/
8547 shiftR1Left2Result (operand * left, int offl,
8548 operand * result, int offr,
8549 int shCount, int sign)
8551 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
8552 /* shift right accumulator */
8557 aopPut (result, "a", offr);
8561 #ifdef BETTER_LITERAL_SHIFT
8562 /*-----------------------------------------------------------------*/
8563 /* shiftL1Left2Result - shift left one byte from left to result */
8564 /*-----------------------------------------------------------------*/
8566 shiftL1Left2Result (operand * left, int offl,
8567 operand * result, int offr, int shCount)
8570 l = aopGet (left, offl, FALSE, FALSE, NULL);
8572 /* shift left accumulator */
8574 aopPut (result, "a", offr);
8578 #ifdef BETTER_LITERAL_SHIFT
8579 /*-----------------------------------------------------------------*/
8580 /* movLeft2Result - move byte from left to result */
8581 /*-----------------------------------------------------------------*/
8583 movLeft2Result (operand * left, int offl,
8584 operand * result, int offr, int sign)
8587 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8589 l = aopGet (left, offl, FALSE, FALSE, NULL);
8591 if (*l == '@' && (IS_AOP_PREG (result)))
8593 emitcode ("mov", "a,%s", l);
8594 aopPut (result, "a", offr);
8600 aopPut (result, l, offr);
8604 /* MSB sign in acc.7 ! */
8605 if (getDataSize (left) == offl + 1)
8608 aopPut (result, "a", offr);
8616 #ifdef BETTER_LITERAL_SHIFT
8617 /*-----------------------------------------------------------------*/
8618 /* AccAXRrl1 - right rotate a:x by 1 */
8619 /*-----------------------------------------------------------------*/
8623 emitcode ("mov", "c,acc.0");
8624 emitcode ("xch", "a,%s", x);
8625 emitcode ("rrc", "a");
8626 emitcode ("xch", "a,%s", x);
8627 emitcode ("rrc", "a");
8631 #ifdef BETTER_LITERAL_SHIFT
8633 /*-----------------------------------------------------------------*/
8634 /* AccAXLrl1 - left rotate a:x by 1 */
8635 /*-----------------------------------------------------------------*/
8639 emitcode ("mov", "c,acc.7");
8640 emitcode ("xch", "a,%s", x);
8641 emitcode ("rlc", "a");
8642 emitcode ("xch", "a,%s", x);
8643 emitcode ("rlc", "a");
8647 #ifdef BETTER_LITERAL_SHIFT
8648 /*-----------------------------------------------------------------*/
8649 /* AccAXRsh1 - right shift c->a:x->c by 1 */
8650 /*-----------------------------------------------------------------*/
8654 emitcode ("rrc", "a");
8655 emitcode ("xch", "a,%s", x);
8656 emitcode ("rrc", "a");
8657 emitcode ("xch", "a,%s", x);
8661 #ifdef BETTER_LITERAL_SHIFT
8662 /*-----------------------------------------------------------------*/
8663 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8664 /*-----------------------------------------------------------------*/
8668 emitcode ("xch", "a,%s", x);
8669 emitcode ("add", "a,acc");
8670 emitcode ("xch", "a,%s", x);
8671 emitcode ("rlc", "a");
8675 #ifdef BETTER_LITERAL_SHIFT
8676 /*-----------------------------------------------------------------*/
8677 /* AccAXLsh - left shift a:x by known count (0..7) */
8678 /*-----------------------------------------------------------------*/
8680 AccAXLsh (char *x, int shCount)
8695 case 5: // AAAAABBB:CCCCCDDD
8697 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8699 emitcode ("anl", "a,#!constbyte",
8700 SLMask[shCount]); // BBB00000:CCCCCDDD
8702 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8704 AccRol (shCount); // DDDCCCCC:BBB00000
8706 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8708 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8710 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8712 emitcode ("anl", "a,#!constbyte",
8713 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8715 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8717 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8720 case 6: // AAAAAABB:CCCCCCDD
8721 emitcode ("anl", "a,#!constbyte",
8722 SRMask[shCount]); // 000000BB:CCCCCCDD
8724 AccAXRrl1 (x); // D000000B:BCCCCCCD
8725 AccAXRrl1 (x); // DD000000:BBCCCCCC
8726 emitcode ("xch", "a,%s", x); // BBCCCCCC:DD000000
8728 emitcode ("mov", "c,acc.0"); // c = B
8729 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8730 emitcode("rrc","a");
8731 emitcode("xch","a,%s", x);
8732 emitcode("rrc","a");
8733 emitcode("mov","c,acc.0"); //<< get correct bit
8734 emitcode("xch","a,%s", x);
8736 emitcode("rrc","a");
8737 emitcode("xch","a,%s", x);
8738 emitcode("rrc","a");
8739 emitcode("xch","a,%s", x);
8742 case 7: // a:x <<= 7
8744 emitcode ("anl", "a,#!constbyte",
8745 SRMask[shCount]); // 0000000B:CCCCCCCD
8747 AccAXRrl1 (x); // D0000000:BCCCCCCC
8749 emitcode ("xch", "a,%s", x); // BCCCCCCC:D0000000
8758 #ifdef BETTER_LITERAL_SHIFT
8760 /*-----------------------------------------------------------------*/
8761 /* AccAXRsh - right shift a:x known count (0..7) */
8762 /*-----------------------------------------------------------------*/
8764 AccAXRsh (char *x, int shCount)
8772 AccAXRsh1 (x); // 0->a:x
8777 AccAXRsh1 (x); // 0->a:x
8780 AccAXRsh1 (x); // 0->a:x
8785 case 5: // AAAAABBB:CCCCCDDD = a:x
8787 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8789 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8791 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8793 emitcode ("anl", "a,#!constbyte",
8794 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8796 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8798 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8800 emitcode ("anl", "a,#!constbyte",
8801 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8803 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8805 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8807 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8810 case 6: // AABBBBBB:CCDDDDDD
8812 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDE
8813 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8815 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8817 emitcode ("anl", "a,#!constbyte",
8818 SRMask[shCount]); // 000000AA:BBBBBBCC
8821 case 7: // ABBBBBBB:CDDDDDDD
8823 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8825 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8827 emitcode ("anl", "a,#!constbyte",
8828 SRMask[shCount]); // 0000000A:BBBBBBBC
8837 #ifdef BETTER_LITERAL_SHIFT
8838 /*-----------------------------------------------------------------*/
8839 /* AccAXRshS - right shift signed a:x known count (0..7) */
8840 /*-----------------------------------------------------------------*/
8842 AccAXRshS (char *x, int shCount)
8850 emitcode ("mov", "c,acc.7");
8851 AccAXRsh1 (x); // s->a:x
8855 emitcode ("mov", "c,acc.7");
8856 AccAXRsh1 (x); // s->a:x
8858 emitcode ("mov", "c,acc.7");
8859 AccAXRsh1 (x); // s->a:x
8864 case 5: // AAAAABBB:CCCCCDDD = a:x
8866 tlbl = newiTempLabel (NULL);
8867 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8869 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8871 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8873 emitcode ("anl", "a,#!constbyte",
8874 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8876 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8878 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8880 emitcode ("anl", "a,#!constbyte",
8881 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8883 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8885 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8887 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8889 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8890 emitcode ("orl", "a,#!constbyte",
8891 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8894 break; // SSSSAAAA:BBBCCCCC
8896 case 6: // AABBBBBB:CCDDDDDD
8898 tlbl = newiTempLabel (NULL);
8900 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8901 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8903 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8905 emitcode ("anl", "a,#!constbyte",
8906 SRMask[shCount]); // 000000AA:BBBBBBCC
8908 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8909 emitcode ("orl", "a,#!constbyte",
8910 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8914 case 7: // ABBBBBBB:CDDDDDDD
8916 tlbl = newiTempLabel (NULL);
8918 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8920 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8922 emitcode ("anl", "a,#!constbyte",
8923 SRMask[shCount]); // 0000000A:BBBBBBBC
8925 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8926 emitcode ("orl", "a,#!constbyte",
8927 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8937 #ifdef BETTER_LITERAL_SHIFT
8939 _loadLeftIntoAx(char **lsb,
8945 // Get the initial value from left into a pair of registers.
8946 // MSB must be in A, LSB can be any register.
8948 // If the result is held in registers, it is an optimization
8949 // if the LSB can be held in the register which will hold the,
8950 // result LSB since this saves us from having to copy it into
8951 // the result following AccAXLsh.
8953 // If the result is addressed indirectly, this is not a gain.
8954 if (AOP_NEEDSACC(result))
8958 _startLazyDPSEvaluation();
8959 if (AOP_TYPE(left) == AOP_DPTR2)
8962 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE, NULL));
8963 // get LSB in DP2_RESULT_REG.
8964 leftByte = aopGet (left, offl, FALSE, FALSE, DP2_RESULT_REG);
8965 assert(!strcmp(leftByte, DP2_RESULT_REG));
8969 // get LSB into DP2_RESULT_REG
8970 leftByte = aopGet (left, offl, FALSE, FALSE, NULL);
8971 if (strcmp(leftByte, DP2_RESULT_REG))
8974 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
8977 leftByte = aopGet (left, offl + MSB16, FALSE, FALSE, NULL);
8978 assert(strcmp(leftByte, DP2_RESULT_REG));
8981 _endLazyDPSEvaluation();
8982 *lsb = DP2_RESULT_REG;
8986 if (sameRegs (AOP (result), AOP (left)) &&
8987 ((offl + MSB16) == offr))
8989 /* don't crash result[offr] */
8990 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
8991 emitcode ("xch", "a,%s",
8992 aopGet (left, offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
8996 movLeft2Result (left, offl, result, offr, 0);
8997 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE, NULL));
8999 *lsb = aopGet (result, offr, FALSE, FALSE, DP2_RESULT_REG);
9000 assert(strcmp(*lsb,"a"));
9005 _storeAxResults(char *lsb,
9009 _startLazyDPSEvaluation();
9010 if (AOP_NEEDSACC(result))
9012 /* We have to explicitly update the result LSB.
9014 emitcode ("xch","a,%s", lsb);
9015 aopPut (result, "a", offr);
9016 emitcode ("mov","a,%s", lsb);
9018 if (getDataSize (result) > 1)
9020 aopPut (result, "a", offr + MSB16);
9022 _endLazyDPSEvaluation();
9025 /*-----------------------------------------------------------------*/
9026 /* shiftL2Left2Result - shift left two bytes from left to result */
9027 /*-----------------------------------------------------------------*/
9029 shiftL2Left2Result (operand * left, int offl,
9030 operand * result, int offr, int shCount)
9034 _loadLeftIntoAx(&lsb, left, result, offl, offr);
9036 AccAXLsh (lsb, shCount);
9038 _storeAxResults(lsb, result, offr);
9042 #ifdef BETTER_LITERAL_SHIFT
9043 /*-----------------------------------------------------------------*/
9044 /* shiftR2Left2Result - shift right two bytes from left to result */
9045 /*-----------------------------------------------------------------*/
9047 shiftR2Left2Result (operand * left, int offl,
9048 operand * result, int offr,
9049 int shCount, int sign)
9053 _loadLeftIntoAx(&lsb, left, result, offl, offr);
9055 /* a:x >> shCount (x = lsb(result)) */
9058 AccAXRshS(lsb, shCount);
9062 AccAXRsh(lsb, shCount);
9065 _storeAxResults(lsb, result, offr);
9069 /*-----------------------------------------------------------------*/
9070 /* shiftLLeftOrResult - shift left one byte from left, or to result */
9071 /*-----------------------------------------------------------------*/
9073 shiftLLeftOrResult (operand * left, int offl,
9074 operand * result, int offr, int shCount)
9076 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
9077 /* shift left accumulator */
9079 /* or with result */
9080 emitcode ("orl", "a,%s",
9081 aopGet (result, offr, FALSE, FALSE, DP2_RESULT_REG));
9082 /* back to result */
9083 aopPut (result, "a", offr);
9088 /*-----------------------------------------------------------------*/
9089 /* shiftRLeftOrResult - shift right one byte from left,or to result */
9090 /*-----------------------------------------------------------------*/
9092 shiftRLeftOrResult (operand * left, int offl,
9093 operand * result, int offr, int shCount)
9095 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
9096 /* shift right accumulator */
9098 /* or with result */
9099 emitcode ("orl", "a,%s",
9100 aopGet (result, offr, FALSE, FALSE, DP2_RESULT_REG));
9101 /* back to result */
9102 aopPut (result, "a", offr);
9106 #ifdef BETTER_LITERAL_SHIFT
9107 /*-----------------------------------------------------------------*/
9108 /* genlshOne - left shift a one byte quantity by known count */
9109 /*-----------------------------------------------------------------*/
9111 genlshOne (operand * result, operand * left, int shCount)
9113 D (emitcode (";", "genlshOne"));
9115 shiftL1Left2Result (left, LSB, result, LSB, shCount);
9119 #ifdef BETTER_LITERAL_SHIFT
9120 /*-----------------------------------------------------------------*/
9121 /* genlshTwo - left shift two bytes by known amount != 0 */
9122 /*-----------------------------------------------------------------*/
9124 genlshTwo (operand * result, operand * left, int shCount)
9128 D (emitcode (";", "genlshTwo"));
9130 size = getDataSize (result);
9132 /* if shCount >= 8 */
9137 _startLazyDPSEvaluation();
9143 _endLazyDPSEvaluation();
9144 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
9145 aopPut (result, zero, LSB);
9149 movLeft2Result (left, LSB, result, MSB16, 0);
9150 aopPut (result, zero, LSB);
9151 _endLazyDPSEvaluation();
9156 aopPut (result, zero, LSB);
9157 _endLazyDPSEvaluation();
9161 /* 1 <= shCount <= 7 */
9165 shiftL1Left2Result (left, LSB, result, LSB, shCount);
9167 shiftL2Left2Result (left, LSB, result, LSB, shCount);
9174 /*-----------------------------------------------------------------*/
9175 /* shiftLLong - shift left one long from left to result */
9176 /* offl = LSB or MSB16 */
9177 /*-----------------------------------------------------------------*/
9179 shiftLLong (operand * left, operand * result, int offr)
9182 int size = AOP_SIZE (result);
9184 if (size >= LSB + offr)
9186 l = aopGet (left, LSB, FALSE, FALSE, NULL);
9188 emitcode ("add", "a,acc");
9189 if (sameRegs (AOP (left), AOP (result)) &&
9190 size >= MSB16 + offr && offr != LSB)
9191 emitcode ("xch", "a,%s",
9192 aopGet (left, LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
9194 aopPut (result, "a", LSB + offr);
9197 if (size >= MSB16 + offr)
9199 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
9201 l = aopGet (left, MSB16, FALSE, FALSE, TRUE);
9204 emitcode ("rlc", "a");
9205 if (sameRegs (AOP (left), AOP (result)) &&
9206 size >= MSB24 + offr && offr != LSB)
9207 emitcode ("xch", "a,%s",
9208 aopGet (left, MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
9210 aopPut (result, "a", MSB16 + offr);
9213 if (size >= MSB24 + offr)
9215 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
9217 l = aopGet (left, MSB24, FALSE, FALSE, NULL);
9220 emitcode ("rlc", "a");
9221 if (sameRegs (AOP (left), AOP (result)) &&
9222 size >= MSB32 + offr && offr != LSB)
9223 emitcode ("xch", "a,%s",
9224 aopGet (left, MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
9226 aopPut (result, "a", MSB24 + offr);
9229 if (size > MSB32 + offr)
9231 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
9233 l = aopGet (left, MSB32, FALSE, FALSE, NULL);
9236 emitcode ("rlc", "a");
9237 aopPut (result, "a", MSB32 + offr);
9240 aopPut (result, zero, LSB);
9246 /*-----------------------------------------------------------------*/
9247 /* genlshFour - shift four byte by a known amount != 0 */
9248 /*-----------------------------------------------------------------*/
9250 genlshFour (operand * result, operand * left, int shCount)
9254 D (emitcode (";", "genlshFour"));
9256 size = AOP_SIZE (result);
9258 /* if shifting more that 3 bytes */
9263 /* lowest order of left goes to the highest
9264 order of the destination */
9265 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
9267 movLeft2Result (left, LSB, result, MSB32, 0);
9268 aopPut (result, zero, LSB);
9269 aopPut (result, zero, MSB16);
9270 aopPut (result, zero, MSB24);
9274 /* more than two bytes */
9275 else if (shCount >= 16)
9277 /* lower order two bytes goes to higher order two bytes */
9279 /* if some more remaining */
9281 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
9284 movLeft2Result (left, MSB16, result, MSB32, 0);
9285 movLeft2Result (left, LSB, result, MSB24, 0);
9287 aopPut (result, zero, MSB16);
9288 aopPut (result, zero, LSB);
9292 /* if more than 1 byte */
9293 else if (shCount >= 8)
9295 /* lower order three bytes goes to higher order three bytes */
9300 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
9302 movLeft2Result (left, LSB, result, MSB16, 0);
9308 movLeft2Result (left, MSB24, result, MSB32, 0);
9309 movLeft2Result (left, MSB16, result, MSB24, 0);
9310 movLeft2Result (left, LSB, result, MSB16, 0);
9311 aopPut (result, zero, LSB);
9313 else if (shCount == 1)
9314 shiftLLong (left, result, MSB16);
9317 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
9318 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
9319 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
9320 aopPut (result, zero, LSB);
9325 /* 1 <= shCount <= 7 */
9326 else if (shCount <= 2)
9328 shiftLLong (left, result, LSB);
9330 shiftLLong (result, result, LSB);
9332 /* 3 <= shCount <= 7, optimize */
9335 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
9336 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
9337 shiftL2Left2Result (left, LSB, result, LSB, shCount);
9342 #ifdef BETTER_LITERAL_SHIFT
9343 /*-----------------------------------------------------------------*/
9344 /* genLeftShiftLiteral - left shifting by known count */
9345 /*-----------------------------------------------------------------*/
9347 genLeftShiftLiteral (operand * left,
9352 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9355 size = getSize (operandType (result));
9357 D (emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
9359 /* We only handle certain easy cases so far. */
9361 && (shCount < (size * 8))
9365 D(emitcode (";", "genLeftShiftLiteral wimping out"););
9369 freeAsmop (right, NULL, ic, TRUE);
9371 aopOp(left, ic, FALSE, FALSE);
9372 aopOp(result, ic, FALSE, AOP_USESDPTR(left));
9375 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
9377 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
9378 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
9380 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
9383 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
9385 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
9386 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
9388 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
9394 emitcode ("; shift left ", "result %d, left %d", size,
9398 /* I suppose that the left size >= result size */
9401 _startLazyDPSEvaluation();
9404 movLeft2Result (left, size, result, size, 0);
9406 _endLazyDPSEvaluation();
9408 else if (shCount >= (size * 8))
9410 _startLazyDPSEvaluation();
9413 aopPut (result, zero, size);
9415 _endLazyDPSEvaluation();
9422 genlshOne (result, left, shCount);
9426 genlshTwo (result, left, shCount);
9430 genlshFour (result, left, shCount);
9434 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9435 "*** ack! mystery literal shift!\n");
9439 freeAsmop (result, NULL, ic, TRUE);
9440 freeAsmop (left, NULL, ic, TRUE);
9445 /*-----------------------------------------------------------------*/
9446 /* genLeftShift - generates code for left shifting */
9447 /*-----------------------------------------------------------------*/
9449 genLeftShift (iCode * ic)
9451 operand *left, *right, *result;
9454 symbol *tlbl, *tlbl1;
9457 D (emitcode (";", "genLeftShift"));
9459 right = IC_RIGHT (ic);
9460 left = IC_LEFT (ic);
9461 result = IC_RESULT (ic);
9463 aopOp (right, ic, FALSE, FALSE);
9466 #ifdef BETTER_LITERAL_SHIFT
9467 /* if the shift count is known then do it
9468 as efficiently as possible */
9469 if (AOP_TYPE (right) == AOP_LIT)
9471 if (genLeftShiftLiteral (left, right, result, ic))
9478 /* shift count is unknown then we have to form
9479 a loop get the loop count in B : Note: we take
9480 only the lower order byte since shifting
9481 more that 32 bits make no sense anyway, ( the
9482 largest size of an object can be only 32 bits ) */
9485 if (AOP_TYPE (right) == AOP_LIT)
9487 /* Really should be handled by genLeftShiftLiteral,
9488 * but since I'm too lazy to fix that today, at least we can make
9489 * some small improvement.
9491 emitcode("mov", "b,#!constbyte",
9492 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9496 MOVB (aopGet (right, 0, FALSE, FALSE, "b"));
9497 emitcode ("inc", "b");
9499 freeAsmop (right, NULL, ic, TRUE);
9500 aopOp (left, ic, FALSE, FALSE);
9501 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9503 /* now move the left to the result if they are not the same */
9504 if (!sameRegs (AOP (left), AOP (result)) &&
9505 AOP_SIZE (result) > 1)
9508 size = AOP_SIZE (result);
9510 _startLazyDPSEvaluation ();
9513 l = aopGet (left, offset, FALSE, TRUE, NULL);
9514 if (*l == '@' && (IS_AOP_PREG (result)))
9517 emitcode ("mov", "a,%s", l);
9518 aopPut (result, "a", offset);
9521 aopPut (result, l, offset);
9524 _endLazyDPSEvaluation ();
9527 tlbl = newiTempLabel (NULL);
9528 size = AOP_SIZE (result);
9530 tlbl1 = newiTempLabel (NULL);
9532 /* if it is only one byte then */
9535 symbol *tlbl1 = newiTempLabel (NULL);
9537 l = aopGet (left, 0, FALSE, FALSE, NULL);
9539 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9541 emitcode ("add", "a,acc");
9543 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9545 aopPut (result, "a", 0);
9549 reAdjustPreg (AOP (result));
9551 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9553 l = aopGet (result, offset, FALSE, FALSE, NULL);
9555 emitcode ("add", "a,acc");
9556 aopPut (result, "a", offset++);
9557 _startLazyDPSEvaluation ();
9560 l = aopGet (result, offset, FALSE, FALSE, NULL);
9562 emitcode ("rlc", "a");
9563 aopPut (result, "a", offset++);
9565 _endLazyDPSEvaluation ();
9566 reAdjustPreg (AOP (result));
9569 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9572 freeAsmop (result, NULL, ic, TRUE);
9573 freeAsmop (left, NULL, ic, TRUE);
9576 #ifdef BETTER_LITERAL_SHIFT
9577 /*-----------------------------------------------------------------*/
9578 /* genrshOne - right shift a one byte quantity by known count */
9579 /*-----------------------------------------------------------------*/
9581 genrshOne (operand * result, operand * left,
9582 int shCount, int sign)
9584 D (emitcode (";", "genrshOne"));
9586 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9590 #ifdef BETTER_LITERAL_SHIFT
9591 /*-----------------------------------------------------------------*/
9592 /* genrshTwo - right shift two bytes by known amount != 0 */
9593 /*-----------------------------------------------------------------*/
9595 genrshTwo (operand * result, operand * left,
9596 int shCount, int sign)
9598 D (emitcode (";", "genrshTwo"));
9600 /* if shCount >= 8 */
9604 _startLazyDPSEvaluation();
9606 shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
9608 movLeft2Result (left, MSB16, result, LSB, sign);
9609 addSign (result, MSB16, sign);
9610 _endLazyDPSEvaluation();
9613 /* 1 <= shCount <= 7 */
9615 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9619 /*-----------------------------------------------------------------*/
9620 /* shiftRLong - shift right one long from left to result */
9621 /* offl = LSB or MSB16 */
9622 /*-----------------------------------------------------------------*/
9624 shiftRLong (operand * left, int offl,
9625 operand * result, int sign)
9627 int isSameRegs=sameRegs(AOP(left),AOP(result));
9629 if (isSameRegs && offl>1) {
9630 // we are in big trouble, but this shouldn't happen
9631 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9634 MOVA (aopGet (left, MSB32, FALSE, FALSE, NULL));
9641 emitcode ("rlc", "a");
9642 emitcode ("subb", "a,acc");
9643 emitcode ("xch", "a,%s",
9644 aopGet(left, MSB32, FALSE, FALSE, DP2_RESULT_REG));
9648 aopPut (result, zero, MSB32);
9654 emitcode ("clr", "c");
9658 emitcode ("mov", "c,acc.7");
9661 emitcode ("rrc", "a");
9663 if (isSameRegs && offl==MSB16) {
9665 "a,%s",aopGet (left, MSB24, FALSE, FALSE, DP2_RESULT_REG));
9667 aopPut (result, "a", MSB32);
9668 MOVA (aopGet (left, MSB24, FALSE, FALSE, NULL));
9671 emitcode ("rrc", "a");
9672 if (isSameRegs && offl==1) {
9673 emitcode ("xch", "a,%s",
9674 aopGet (left, MSB16, FALSE, FALSE, DP2_RESULT_REG));
9676 aopPut (result, "a", MSB24);
9677 MOVA (aopGet (left, MSB16, FALSE, FALSE, NULL));
9679 emitcode ("rrc", "a");
9680 aopPut (result, "a", MSB16 - offl);
9684 MOVA (aopGet (left, LSB, FALSE, FALSE, NULL));
9685 emitcode ("rrc", "a");
9686 aopPut (result, "a", LSB);
9690 /*-----------------------------------------------------------------*/
9691 /* genrshFour - shift four byte by a known amount != 0 */
9692 /*-----------------------------------------------------------------*/
9694 genrshFour (operand * result, operand * left,
9695 int shCount, int sign)
9697 D (emitcode (";", "genrshFour"));
9699 /* if shifting more that 3 bytes */
9703 _startLazyDPSEvaluation();
9705 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9707 movLeft2Result (left, MSB32, result, LSB, sign);
9708 addSign (result, MSB16, sign);
9709 _endLazyDPSEvaluation();
9711 else if (shCount >= 16)
9714 _startLazyDPSEvaluation();
9716 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9719 movLeft2Result (left, MSB24, result, LSB, 0);
9720 movLeft2Result (left, MSB32, result, MSB16, sign);
9722 addSign (result, MSB24, sign);
9723 _endLazyDPSEvaluation();
9725 else if (shCount >= 8)
9728 _startLazyDPSEvaluation();
9731 shiftRLong (left, MSB16, result, sign);
9733 else if (shCount == 0)
9735 movLeft2Result (left, MSB16, result, LSB, 0);
9736 movLeft2Result (left, MSB24, result, MSB16, 0);
9737 movLeft2Result (left, MSB32, result, MSB24, sign);
9738 addSign (result, MSB32, sign);
9742 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9743 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9744 /* the last shift is signed */
9745 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9746 addSign (result, MSB32, sign);
9748 _endLazyDPSEvaluation();
9752 /* 1 <= shCount <= 7 */
9755 shiftRLong (left, LSB, result, sign);
9757 shiftRLong (result, LSB, result, sign);
9761 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9762 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9763 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9768 #ifdef BETTER_LITERAL_SHIFT
9769 /*-----------------------------------------------------------------*/
9770 /* genRightShiftLiteral - right shifting by known count */
9771 /*-----------------------------------------------------------------*/
9773 genRightShiftLiteral (operand * left,
9779 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9782 size = getSize (operandType (result));
9784 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
9786 /* We only handle certain easy cases so far. */
9788 && (shCount < (size * 8))
9793 D(emitcode (";", "genRightShiftLiteral wimping out"););
9797 freeAsmop (right, NULL, ic, TRUE);
9799 aopOp (left, ic, FALSE, FALSE);
9800 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9803 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9807 /* test the LEFT size !!! */
9809 /* I suppose that the left size >= result size */
9812 size = getDataSize (result);
9813 _startLazyDPSEvaluation();
9815 movLeft2Result (left, size, result, size, 0);
9816 _endLazyDPSEvaluation();
9818 else if (shCount >= (size * 8))
9822 /* get sign in acc.7 */
9823 MOVA (aopGet (left, size - 1, FALSE, FALSE, NULL));
9825 addSign (result, LSB, sign);
9832 genrshOne (result, left, shCount, sign);
9836 genrshTwo (result, left, shCount, sign);
9840 genrshFour (result, left, shCount, sign);
9847 freeAsmop (result, NULL, ic, TRUE);
9848 freeAsmop (left, NULL, ic, TRUE);
9854 /*-----------------------------------------------------------------*/
9855 /* genSignedRightShift - right shift of signed number */
9856 /*-----------------------------------------------------------------*/
9858 genSignedRightShift (iCode * ic)
9860 operand *right, *left, *result;
9863 symbol *tlbl, *tlbl1;
9866 D (emitcode (";", "genSignedRightShift"));
9868 /* we do it the hard way put the shift count in b
9869 and loop thru preserving the sign */
9871 right = IC_RIGHT (ic);
9872 left = IC_LEFT (ic);
9873 result = IC_RESULT (ic);
9875 aopOp (right, ic, FALSE, FALSE);
9877 #ifdef BETTER_LITERAL_SHIFT
9878 if (AOP_TYPE (right) == AOP_LIT)
9880 if (genRightShiftLiteral (left, right, result, ic, 1))
9886 /* shift count is unknown then we have to form
9887 a loop get the loop count in B : Note: we take
9888 only the lower order byte since shifting
9889 more that 32 bits make no sense anyway, ( the
9890 largest size of an object can be only 32 bits ) */
9893 if (AOP_TYPE (right) == AOP_LIT)
9895 /* Really should be handled by genRightShiftLiteral,
9896 * but since I'm too lazy to fix that today, at least we can make
9897 * some small improvement.
9899 emitcode("mov", "b,#!constbyte",
9900 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9904 MOVB (aopGet (right, 0, FALSE, FALSE, "b"));
9905 emitcode ("inc", "b");
9907 freeAsmop (right, NULL, ic, TRUE);
9908 aopOp (left, ic, FALSE, FALSE);
9909 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9911 /* now move the left to the result if they are not the
9913 if (!sameRegs (AOP (left), AOP (result)) &&
9914 AOP_SIZE (result) > 1)
9917 size = AOP_SIZE (result);
9919 _startLazyDPSEvaluation ();
9922 l = aopGet (left, offset, FALSE, TRUE, NULL);
9923 if (*l == '@' && IS_AOP_PREG (result))
9926 emitcode ("mov", "a,%s", l);
9927 aopPut (result, "a", offset);
9930 aopPut (result, l, offset);
9933 _endLazyDPSEvaluation ();
9936 /* mov the highest order bit to OVR */
9937 tlbl = newiTempLabel (NULL);
9938 tlbl1 = newiTempLabel (NULL);
9940 size = AOP_SIZE (result);
9942 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
9943 emitcode ("rlc", "a");
9944 emitcode ("mov", "ov,c");
9945 /* if it is only one byte then */
9948 l = aopGet (left, 0, FALSE, FALSE, NULL);
9950 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9952 emitcode ("mov", "c,ov");
9953 emitcode ("rrc", "a");
9955 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9957 aopPut (result, "a", 0);
9961 reAdjustPreg (AOP (result));
9962 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9964 emitcode ("mov", "c,ov");
9965 _startLazyDPSEvaluation ();
9968 l = aopGet (result, offset, FALSE, FALSE, NULL);
9970 emitcode ("rrc", "a");
9971 aopPut (result, "a", offset--);
9973 _endLazyDPSEvaluation ();
9974 reAdjustPreg (AOP (result));
9976 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9980 freeAsmop (result, NULL, ic, TRUE);
9981 freeAsmop (left, NULL, ic, TRUE);
9984 /*-----------------------------------------------------------------*/
9985 /* genRightShift - generate code for right shifting */
9986 /*-----------------------------------------------------------------*/
9988 genRightShift (iCode * ic)
9990 operand *right, *left, *result;
9994 symbol *tlbl, *tlbl1;
9997 D (emitcode (";", "genRightShift"));
9999 /* if signed then we do it the hard way preserve the
10000 sign bit moving it inwards */
10001 letype = getSpec (operandType (IC_LEFT (ic)));
10003 if (!SPEC_USIGN (letype))
10005 genSignedRightShift (ic);
10009 /* signed & unsigned types are treated the same : i.e. the
10010 signed is NOT propagated inwards : quoting from the
10011 ANSI - standard : "for E1 >> E2, is equivalent to division
10012 by 2**E2 if unsigned or if it has a non-negative value,
10013 otherwise the result is implementation defined ", MY definition
10014 is that the sign does not get propagated */
10016 right = IC_RIGHT (ic);
10017 left = IC_LEFT (ic);
10018 result = IC_RESULT (ic);
10020 aopOp (right, ic, FALSE, FALSE);
10022 #ifdef BETTER_LITERAL_SHIFT
10023 /* if the shift count is known then do it
10024 as efficiently as possible */
10025 if (AOP_TYPE (right) == AOP_LIT)
10027 if (genRightShiftLiteral (left, right, result, ic, 0))
10034 /* shift count is unknown then we have to form
10035 a loop get the loop count in B : Note: we take
10036 only the lower order byte since shifting
10037 more that 32 bits make no sense anyway, ( the
10038 largest size of an object can be only 32 bits ) */
10040 pushedB = pushB ();
10041 if (AOP_TYPE (right) == AOP_LIT)
10043 /* Really should be handled by genRightShiftLiteral,
10044 * but since I'm too lazy to fix that today, at least we can make
10045 * some small improvement.
10047 emitcode("mov", "b,#!constbyte",
10048 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
10052 MOVB (aopGet (right, 0, FALSE, FALSE, "b"));
10053 emitcode ("inc", "b");
10055 freeAsmop (right, NULL, ic, TRUE);
10056 aopOp (left, ic, FALSE, FALSE);
10057 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
10059 /* now move the left to the result if they are not the
10061 if (!sameRegs (AOP (left), AOP (result)) &&
10062 AOP_SIZE (result) > 1)
10064 size = AOP_SIZE (result);
10066 _startLazyDPSEvaluation ();
10069 l = aopGet (left, offset, FALSE, TRUE, NULL);
10070 if (*l == '@' && IS_AOP_PREG (result))
10073 emitcode ("mov", "a,%s", l);
10074 aopPut (result, "a", offset);
10077 aopPut (result, l, offset);
10080 _endLazyDPSEvaluation ();
10083 tlbl = newiTempLabel (NULL);
10084 tlbl1 = newiTempLabel (NULL);
10085 size = AOP_SIZE (result);
10088 /* if it is only one byte then */
10091 l = aopGet (left, 0, FALSE, FALSE, NULL);
10093 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
10096 emitcode ("rrc", "a");
10098 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
10100 aopPut (result, "a", 0);
10104 reAdjustPreg (AOP (result));
10105 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
10108 _startLazyDPSEvaluation ();
10111 l = aopGet (result, offset, FALSE, FALSE, NULL);
10113 emitcode ("rrc", "a");
10114 aopPut (result, "a", offset--);
10116 _endLazyDPSEvaluation ();
10117 reAdjustPreg (AOP (result));
10120 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
10124 freeAsmop (result, NULL, ic, TRUE);
10125 freeAsmop (left, NULL, ic, TRUE);
10128 /*-----------------------------------------------------------------*/
10129 /* emitPtrByteGet - emits code to get a byte into A through a */
10130 /* pointer register (R0, R1, or DPTR). The */
10131 /* original value of A can be preserved in B. */
10132 /*-----------------------------------------------------------------*/
10134 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
10141 emitcode ("mov", "b,a");
10142 emitcode ("mov", "a,@%s", rname);
10147 emitcode ("mov", "b,a");
10148 emitcode ("movx", "a,@%s", rname);
10153 emitcode ("mov", "b,a");
10154 emitcode ("movx", "a,@dptr");
10159 emitcode ("mov", "b,a");
10160 emitcode ("clr", "a");
10161 emitcode ("movc", "a,@a+dptr");
10167 emitcode ("push", "b");
10168 emitcode ("push", "acc");
10170 emitcode ("lcall", "__gptrget");
10172 emitcode ("pop", "b");
10177 /*-----------------------------------------------------------------*/
10178 /* emitPtrByteSet - emits code to set a byte from src through a */
10179 /* pointer register (R0, R1, or DPTR). */
10180 /*-----------------------------------------------------------------*/
10182 emitPtrByteSet (char *rname, int p_type, char *src)
10191 emitcode ("mov", "@%s,a", rname);
10194 emitcode ("mov", "@%s,%s", rname, src);
10199 emitcode ("movx", "@%s,a", rname);
10204 emitcode ("movx", "@dptr,a");
10209 emitcode ("lcall", "__gptrput");
10214 /*-----------------------------------------------------------------*/
10215 /* genUnpackBits - generates code for unpacking bits */
10216 /*-----------------------------------------------------------------*/
10218 genUnpackBits (operand * result, char *rname, int ptype)
10220 int offset = 0; /* result byte offset */
10221 int rsize; /* result size */
10222 int rlen = 0; /* remaining bitfield length */
10223 sym_link *etype; /* bitfield type information */
10224 int blen; /* bitfield length */
10225 int bstr; /* bitfield starting bit within byte */
10227 D(emitcode ("; genUnpackBits",""));
10229 etype = getSpec (operandType (result));
10230 rsize = getSize (operandType (result));
10231 blen = SPEC_BLEN (etype);
10232 bstr = SPEC_BSTR (etype);
10234 /* If the bitfield length is less than a byte */
10237 emitPtrByteGet (rname, ptype, FALSE);
10239 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
10240 if (!SPEC_USIGN (etype))
10242 /* signed bitfield */
10243 symbol *tlbl = newiTempLabel (NULL);
10245 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
10246 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
10249 aopPut (result, "a", offset++);
10253 /* Bit field did not fit in a byte. Copy all
10254 but the partial byte at the end. */
10255 for (rlen=blen;rlen>=8;rlen-=8)
10257 emitPtrByteGet (rname, ptype, FALSE);
10258 aopPut (result, "a", offset++);
10260 emitcode ("inc", "%s", rname);
10263 /* Handle the partial byte at the end */
10266 emitPtrByteGet (rname, ptype, FALSE);
10267 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
10268 if (!SPEC_USIGN (etype))
10270 /* signed bitfield */
10271 symbol *tlbl = newiTempLabel (NULL);
10273 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
10274 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
10277 aopPut (result, "a", offset++);
10281 if (offset < rsize)
10285 if (SPEC_USIGN (etype))
10289 /* signed bitfield: sign extension with 0x00 or 0xff */
10290 emitcode ("rlc", "a");
10291 emitcode ("subb", "a,acc");
10297 aopPut (result, source, offset++);
10302 /*-----------------------------------------------------------------*/
10303 /* genDataPointerGet - generates code when ptr offset is known */
10304 /*-----------------------------------------------------------------*/
10306 genDataPointerGet (operand * left,
10312 int size, offset = 0;
10313 aopOp (result, ic, TRUE, FALSE);
10315 /* get the string representation of the name */
10316 l = aopGet (left, 0, FALSE, TRUE, NULL);
10317 size = AOP_SIZE (result);
10318 _startLazyDPSEvaluation ();
10323 SNPRINTF (buffer, sizeof(buffer),
10324 "(%s + %d)", l + 1, offset);
10328 SNPRINTF (buffer, sizeof(buffer),
10331 aopPut (result, buffer, offset++);
10333 _endLazyDPSEvaluation ();
10335 freeAsmop (result, NULL, ic, TRUE);
10336 freeAsmop (left, NULL, ic, TRUE);
10339 /*-----------------------------------------------------------------*/
10340 /* genNearPointerGet - emitcode for near pointer fetch */
10341 /*-----------------------------------------------------------------*/
10343 genNearPointerGet (operand * left,
10351 sym_link *rtype, *retype, *letype;
10352 sym_link *ltype = operandType (left);
10355 rtype = operandType (result);
10356 retype = getSpec (rtype);
10357 letype = getSpec (ltype);
10359 aopOp (left, ic, FALSE, FALSE);
10361 /* if left is rematerialisable and
10362 result is not bitfield variable type and
10363 the left is pointer to data space i.e
10364 lower 128 bytes of space */
10365 if (AOP_TYPE (left) == AOP_IMMD &&
10366 !IS_BITFIELD (retype) &&
10367 !IS_BITFIELD (letype) &&
10368 DCL_TYPE (ltype) == POINTER)
10370 genDataPointerGet (left, result, ic);
10374 /* if the value is already in a pointer register
10375 then don't need anything more */
10376 if (!AOP_INPREG (AOP (left)))
10378 /* otherwise get a free pointer register */
10379 aop = newAsmop (0);
10380 preg = getFreePtr (ic, &aop, FALSE);
10381 emitcode ("mov", "%s,%s",
10383 aopGet (left, 0, FALSE, TRUE, DP2_RESULT_REG));
10384 rname = preg->name;
10387 rname = aopGet (left, 0, FALSE, FALSE, DP2_RESULT_REG);
10389 freeAsmop (left, NULL, ic, TRUE);
10390 aopOp (result, ic, FALSE, FALSE);
10392 /* if bitfield then unpack the bits */
10393 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10394 genUnpackBits (result, rname, POINTER);
10397 /* we have can just get the values */
10398 int size = AOP_SIZE (result);
10403 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
10406 emitcode ("mov", "a,@%s", rname);
10407 aopPut (result, "a", offset);
10411 SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
10412 aopPut (result, buffer, offset);
10416 emitcode ("inc", "%s", rname);
10420 /* now some housekeeping stuff */
10421 if (aop) /* we had to allocate for this iCode */
10423 if (pi) { /* post increment present */
10424 aopPut (left, rname, 0);
10426 freeAsmop (NULL, aop, ic, TRUE);
10430 /* we did not allocate which means left
10431 already in a pointer register, then
10432 if size > 0 && this could be used again
10433 we have to point it back to where it
10435 if (AOP_SIZE (result) > 1 &&
10436 !OP_SYMBOL (left)->remat &&
10437 (OP_SYMBOL (left)->liveTo > ic->seq ||
10441 int size = AOP_SIZE (result) - 1;
10443 emitcode ("dec", "%s", rname);
10448 freeAsmop (result, NULL, ic, TRUE);
10449 if (pi) pi->generated = 1;
10452 /*-----------------------------------------------------------------*/
10453 /* genPagedPointerGet - emitcode for paged pointer fetch */
10454 /*-----------------------------------------------------------------*/
10456 genPagedPointerGet (operand * left,
10464 sym_link *rtype, *retype, *letype;
10466 rtype = operandType (result);
10467 retype = getSpec (rtype);
10468 letype = getSpec (operandType (left));
10469 aopOp (left, ic, FALSE, FALSE);
10471 /* if the value is already in a pointer register
10472 then don't need anything more */
10473 if (!AOP_INPREG (AOP (left)))
10475 /* otherwise get a free pointer register */
10476 aop = newAsmop (0);
10477 preg = getFreePtr (ic, &aop, FALSE);
10478 emitcode ("mov", "%s,%s",
10480 aopGet (left, 0, FALSE, TRUE, NULL));
10481 rname = preg->name;
10484 rname = aopGet (left, 0, FALSE, FALSE, NULL);
10486 freeAsmop (left, NULL, ic, TRUE);
10487 aopOp (result, ic, FALSE, FALSE);
10489 /* if bitfield then unpack the bits */
10490 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10491 genUnpackBits (result, rname, PPOINTER);
10494 /* we have can just get the values */
10495 int size = AOP_SIZE (result);
10501 emitcode ("movx", "a,@%s", rname);
10502 aopPut (result, "a", offset);
10507 emitcode ("inc", "%s", rname);
10511 /* now some housekeeping stuff */
10512 if (aop) /* we had to allocate for this iCode */
10515 aopPut (left, rname, 0);
10516 freeAsmop (NULL, aop, ic, TRUE);
10520 /* we did not allocate which means left
10521 already in a pointer register, then
10522 if size > 0 && this could be used again
10523 we have to point it back to where it
10525 if (AOP_SIZE (result) > 1 &&
10526 !OP_SYMBOL (left)->remat &&
10527 (OP_SYMBOL (left)->liveTo > ic->seq ||
10531 int size = AOP_SIZE (result) - 1;
10533 emitcode ("dec", "%s", rname);
10538 freeAsmop (result, NULL, ic, TRUE);
10539 if (pi) pi->generated = 1;
10542 /*-----------------------------------------------------------------*/
10543 /* genFarPointerGet - get value from far space */
10544 /*-----------------------------------------------------------------*/
10546 genFarPointerGet (operand * left,
10547 operand * result, iCode * ic, iCode *pi)
10549 int size, offset, dopi=1;
10550 sym_link *retype = getSpec (operandType (result));
10551 sym_link *letype = getSpec (operandType (left));
10552 D (emitcode (";", "genFarPointerGet"););
10554 aopOp (left, ic, FALSE, FALSE);
10556 /* if the operand is already in dptr
10557 then we do nothing else we move the value to dptr */
10558 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
10560 /* if this is rematerializable */
10561 if (AOP_TYPE (left) == AOP_IMMD)
10563 emitcode ("mov", "dptr,%s", aopGet (left, 0, TRUE, FALSE, NULL));
10567 /* we need to get it byte by byte */
10568 _startLazyDPSEvaluation ();
10569 if (AOP_TYPE (left) != AOP_DPTR)
10571 emitcode ("mov", "dpl,%s", aopGet (left, 0, FALSE, FALSE, NULL));
10572 emitcode ("mov", "dph,%s", aopGet (left, 1, FALSE, FALSE, NULL));
10573 if (options.model == MODEL_FLAT24)
10574 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10578 /* We need to generate a load to DPTR indirect through DPTR. */
10579 D (emitcode (";", "genFarPointerGet -- indirection special case."););
10580 emitcode ("push", "%s", aopGet (left, 0, FALSE, TRUE, NULL));
10581 emitcode ("push", "%s", aopGet (left, 1, FALSE, TRUE, NULL));
10582 if (options.model == MODEL_FLAT24)
10583 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10584 emitcode ("pop", "dph");
10585 emitcode ("pop", "dpl");
10588 _endLazyDPSEvaluation ();
10591 /* so dptr now contains the address */
10592 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10594 /* if bit then unpack */
10595 if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
10596 if (AOP_INDPTRn(left)) {
10597 genSetDPTR(AOP(left)->aopu.dptr);
10599 genUnpackBits (result, "dptr", FPOINTER);
10600 if (AOP_INDPTRn(left)) {
10605 size = AOP_SIZE (result);
10608 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10610 genSetDPTR(AOP(left)->aopu.dptr);
10611 emitcode ("movx", "a,@dptr");
10612 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10613 emitcode ("inc", "dptr");
10615 aopPut (result, "a", offset++);
10618 _startLazyDPSEvaluation ();
10620 if (AOP_INDPTRn(left)) {
10621 genSetDPTR(AOP(left)->aopu.dptr);
10627 emitcode ("movx", "a,@dptr");
10628 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10629 emitcode ("inc", "dptr");
10631 aopPut (result, "a", offset++);
10633 _endLazyDPSEvaluation ();
10636 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10637 if (!AOP_INDPTRn(left)) {
10638 _startLazyDPSEvaluation ();
10639 aopPut (left, "dpl", 0);
10640 aopPut (left, "dph", 1);
10641 if (options.model == MODEL_FLAT24)
10642 aopPut (left, "dpx", 2);
10643 _endLazyDPSEvaluation ();
10646 } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) &&
10647 AOP_SIZE(result) > 1 &&
10649 (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
10651 size = AOP_SIZE (result) - 1;
10652 if (AOP_INDPTRn(left)) {
10653 genSetDPTR(AOP(left)->aopu.dptr);
10655 while (size--) emitcode ("lcall","__decdptr");
10656 if (AOP_INDPTRn(left)) {
10661 freeAsmop (result, NULL, ic, TRUE);
10662 freeAsmop (left, NULL, ic, TRUE);
10665 /*-----------------------------------------------------------------*/
10666 /* genCodePointerGet - get value from code space */
10667 /*-----------------------------------------------------------------*/
10669 genCodePointerGet (operand * left,
10670 operand * result, iCode * ic, iCode *pi)
10672 int size, offset, dopi=1;
10673 sym_link *retype = getSpec (operandType (result));
10675 aopOp (left, ic, FALSE, FALSE);
10677 /* if the operand is already in dptr
10678 then we do nothing else we move the value to dptr */
10679 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
10681 /* if this is rematerializable */
10682 if (AOP_TYPE (left) == AOP_IMMD)
10684 emitcode ("mov", "dptr,%s", aopGet (left, 0, TRUE, FALSE, NULL));
10687 { /* we need to get it byte by byte */
10688 _startLazyDPSEvaluation ();
10689 if (AOP_TYPE (left) != AOP_DPTR)
10691 emitcode ("mov", "dpl,%s", aopGet (left, 0, FALSE, FALSE, NULL));
10692 emitcode ("mov", "dph,%s", aopGet (left, 1, FALSE, FALSE, NULL));
10693 if (options.model == MODEL_FLAT24)
10694 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10698 /* We need to generate a load to DPTR indirect through DPTR. */
10699 D (emitcode (";", "gencodePointerGet -- indirection special case."););
10700 emitcode ("push", "%s", aopGet (left, 0, FALSE, TRUE, NULL));
10701 emitcode ("push", "%s", aopGet (left, 1, FALSE, TRUE, NULL));
10702 if (options.model == MODEL_FLAT24)
10703 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10704 emitcode ("pop", "dph");
10705 emitcode ("pop", "dpl");
10708 _endLazyDPSEvaluation ();
10711 /* so dptr now contains the address */
10712 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10714 /* if bit then unpack */
10715 if (IS_BITFIELD (retype)) {
10716 if (AOP_INDPTRn(left)) {
10717 genSetDPTR(AOP(left)->aopu.dptr);
10719 genUnpackBits (result, "dptr", CPOINTER);
10720 if (AOP_INDPTRn(left)) {
10725 size = AOP_SIZE (result);
10727 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10729 genSetDPTR(AOP(left)->aopu.dptr);
10730 emitcode ("clr", "a");
10731 emitcode ("movc", "a,@a+dptr");
10732 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10733 emitcode ("inc", "dptr");
10735 aopPut (result, "a", offset++);
10738 _startLazyDPSEvaluation ();
10741 if (AOP_INDPTRn(left)) {
10742 genSetDPTR(AOP(left)->aopu.dptr);
10748 emitcode ("clr", "a");
10749 emitcode ("movc", "a,@a+dptr");
10750 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10751 emitcode ("inc", "dptr");
10752 aopPut (result, "a", offset++);
10754 _endLazyDPSEvaluation ();
10757 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10758 if (!AOP_INDPTRn(left)) {
10759 _startLazyDPSEvaluation ();
10761 aopPut (left, "dpl", 0);
10762 aopPut (left, "dph", 1);
10763 if (options.model == MODEL_FLAT24)
10764 aopPut (left, "dpx", 2);
10766 _endLazyDPSEvaluation ();
10769 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
10770 AOP_SIZE(result) > 1 &&
10771 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10773 size = AOP_SIZE (result) - 1;
10774 if (AOP_INDPTRn(left)) {
10775 genSetDPTR(AOP(left)->aopu.dptr);
10777 while (size--) emitcode ("lcall","__decdptr");
10778 if (AOP_INDPTRn(left)) {
10783 freeAsmop (result, NULL, ic, TRUE);
10784 freeAsmop (left, NULL, ic, TRUE);
10787 /*-----------------------------------------------------------------*/
10788 /* genGenPointerGet - get value from generic pointer space */
10789 /*-----------------------------------------------------------------*/
10791 genGenPointerGet (operand * left,
10792 operand * result, iCode * ic, iCode * pi)
10796 sym_link *retype = getSpec (operandType (result));
10797 sym_link *letype = getSpec (operandType (left));
10799 D (emitcode (";", "genGenPointerGet"));
10801 aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
10803 pushedB = pushB ();
10804 /* if the operand is already in dptr
10805 then we do nothing else we move the value to dptr */
10806 if (AOP_TYPE (left) != AOP_STR)
10808 /* if this is rematerializable */
10809 if (AOP_TYPE (left) == AOP_IMMD)
10811 emitcode ("mov", "dptr,%s", aopGet (left, 0, TRUE, FALSE, NULL));
10812 if (AOP(left)->aopu.aop_immd.from_cast_remat)
10814 MOVB (aopGet (left, AOP_SIZE(left)-1, FALSE, FALSE, NULL));
10818 emitcode ("mov", "b,#%d", pointerCode (retype));
10822 { /* we need to get it byte by byte */
10823 _startLazyDPSEvaluation ();
10824 emitcode ("mov", "dpl,%s", aopGet (left,0,FALSE,FALSE,NULL));
10825 emitcode ("mov", "dph,%s", aopGet (left,1,FALSE,FALSE,NULL));
10826 if (options.model == MODEL_FLAT24) {
10827 emitcode ("mov", "dpx,%s", aopGet (left,2,FALSE,FALSE,NULL));
10828 emitcode ("mov", "b,%s", aopGet (left,3,FALSE,FALSE,NULL));
10830 emitcode ("mov", "b,%s", aopGet (left,2,FALSE,FALSE,NULL));
10832 _endLazyDPSEvaluation ();
10836 /* so dptr-b now contains the address */
10837 aopOp (result, ic, FALSE, TRUE);
10839 /* if bit then unpack */
10840 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10842 genUnpackBits (result, "dptr", GPOINTER);
10846 size = AOP_SIZE (result);
10853 // Get two bytes at a time, results in _AP & A.
10854 // dptr will be incremented ONCE by __gptrgetWord.
10856 // Note: any change here must be coordinated
10857 // with the implementation of __gptrgetWord
10858 // in device/lib/_gptrget.c
10859 emitcode ("lcall", "__gptrgetWord");
10860 aopPut (result, DP2_RESULT_REG, offset++);
10861 aopPut (result, "a", offset++);
10866 // Only one byte to get.
10867 emitcode ("lcall", "__gptrget");
10868 aopPut (result, "a", offset++);
10871 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
10873 emitcode ("inc", "dptr");
10878 if (pi && AOP_TYPE (left) != AOP_IMMD) {
10879 _startLazyDPSEvaluation ();
10881 aopPut (left, "dpl", 0);
10882 aopPut (left, "dph", 1);
10883 if (options.model == MODEL_FLAT24) {
10884 aopPut (left, "dpx", 2);
10885 aopPut (left, "b", 3);
10886 } else aopPut (left, "b", 2);
10888 _endLazyDPSEvaluation ();
10891 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
10892 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10894 size = AOP_SIZE (result) - 1;
10895 while (size--) emitcode ("lcall","__decdptr");
10899 freeAsmop (result, NULL, ic, TRUE);
10900 freeAsmop (left, NULL, ic, TRUE);
10903 /*-----------------------------------------------------------------*/
10904 /* genPointerGet - generate code for pointer get */
10905 /*-----------------------------------------------------------------*/
10907 genPointerGet (iCode * ic, iCode *pi)
10909 operand *left, *result;
10910 sym_link *type, *etype;
10913 D (emitcode (";", "genPointerGet"));
10915 left = IC_LEFT (ic);
10916 result = IC_RESULT (ic);
10918 /* depending on the type of pointer we need to
10919 move it to the correct pointer register */
10920 type = operandType (left);
10921 etype = getSpec (type);
10922 /* if left is of type of pointer then it is simple */
10923 if (IS_PTR (type) && !IS_FUNC (type->next))
10924 p_type = DCL_TYPE (type);
10927 /* we have to go by the storage class */
10928 p_type = PTR_TYPE (SPEC_OCLS (etype));
10931 /* special case when cast remat */
10932 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10933 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10935 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10936 type = operandType (left);
10937 p_type = DCL_TYPE (type);
10939 /* now that we have the pointer type we assign
10940 the pointer values */
10946 genNearPointerGet (left, result, ic, pi);
10950 genPagedPointerGet (left, result, ic, pi);
10954 genFarPointerGet (left, result, ic, pi);
10958 genCodePointerGet (left, result, ic, pi);
10962 genGenPointerGet (left, result, ic, pi);
10968 /*-----------------------------------------------------------------*/
10969 /* genPackBits - generates code for packed bit storage */
10970 /*-----------------------------------------------------------------*/
10972 genPackBits (sym_link * etype,
10974 char *rname, int p_type)
10976 int offset = 0; /* source byte offset */
10977 int rlen = 0; /* remaining bitfield length */
10978 int blen; /* bitfield length */
10979 int bstr; /* bitfield starting bit within byte */
10980 int litval; /* source literal value (if AOP_LIT) */
10981 unsigned char mask; /* bitmask within current byte */
10983 D(emitcode ("; genPackBits",""));
10985 blen = SPEC_BLEN (etype);
10986 bstr = SPEC_BSTR (etype);
10988 /* If the bitfield length is less than a byte */
10991 mask = ((unsigned char) (0xFF << (blen + bstr)) |
10992 (unsigned char) (0xFF >> (8 - bstr)));
10994 if (AOP_TYPE (right) == AOP_LIT)
10996 /* Case with a bitfield length <8 and literal source
10998 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
11000 litval &= (~mask) & 0xff;
11001 emitPtrByteGet (rname, p_type, FALSE);
11002 if ((mask|litval)!=0xff)
11003 emitcode ("anl","a,#!constbyte", mask);
11005 emitcode ("orl","a,#!constbyte", litval);
11009 if ((blen==1) && (p_type!=GPOINTER))
11011 /* Case with a bitfield length == 1 and no generic pointer
11013 if (AOP_TYPE (right) == AOP_CRY)
11014 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
11017 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
11018 emitcode ("rrc","a");
11020 emitPtrByteGet (rname, p_type, FALSE);
11021 emitcode ("mov","acc.%d,c",bstr);
11026 /* Case with a bitfield length < 8 and arbitrary source
11028 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
11029 /* shift and mask source value */
11031 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
11033 pushedB = pushB ();
11034 /* transfer A to B and get next byte */
11035 emitPtrByteGet (rname, p_type, TRUE);
11037 emitcode ("anl", "a,#!constbyte", mask);
11038 emitcode ("orl", "a,b");
11039 if (p_type == GPOINTER)
11040 emitcode ("pop", "b");
11046 emitPtrByteSet (rname, p_type, "a");
11050 /* Bit length is greater than 7 bits. In this case, copy */
11051 /* all except the partial byte at the end */
11052 for (rlen=blen;rlen>=8;rlen-=8)
11054 emitPtrByteSet (rname, p_type,
11055 aopGet (right, offset++, FALSE, TRUE, NULL) );
11057 emitcode ("inc", "%s", rname);
11060 /* If there was a partial byte at the end */
11063 mask = (((unsigned char) -1 << rlen) & 0xff);
11065 if (AOP_TYPE (right) == AOP_LIT)
11067 /* Case with partial byte and literal source
11069 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
11070 litval >>= (blen-rlen);
11071 litval &= (~mask) & 0xff;
11072 emitPtrByteGet (rname, p_type, FALSE);
11073 if ((mask|litval)!=0xff)
11074 emitcode ("anl","a,#!constbyte", mask);
11076 emitcode ("orl","a,#!constbyte", litval);
11081 /* Case with partial byte and arbitrary source
11083 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11084 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
11086 pushedB = pushB ();
11087 /* transfer A to B and get next byte */
11088 emitPtrByteGet (rname, p_type, TRUE);
11090 emitcode ("anl", "a,#!constbyte", mask);
11091 emitcode ("orl", "a,b");
11092 if (p_type == GPOINTER)
11093 emitcode ("pop", "b");
11097 emitPtrByteSet (rname, p_type, "a");
11102 /*-----------------------------------------------------------------*/
11103 /* genDataPointerSet - remat pointer to data space */
11104 /*-----------------------------------------------------------------*/
11106 genDataPointerSet (operand * right,
11110 int size, offset = 0;
11111 char *l, buffer[256];
11113 D (emitcode (";", "genDataPointerSet"));
11115 aopOp (right, ic, FALSE, FALSE);
11117 l = aopGet (result, 0, FALSE, TRUE, NULL);
11118 size = AOP_SIZE (right);
11122 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l + 1, offset);
11124 SNPRINTF (buffer, sizeof(buffer), "%s", l + 1);
11125 emitcode ("mov", "%s,%s", buffer,
11126 aopGet (right, offset++, FALSE, FALSE, NULL));
11129 freeAsmop (result, NULL, ic, TRUE);
11130 freeAsmop (right, NULL, ic, TRUE);
11133 /*-----------------------------------------------------------------*/
11134 /* genNearPointerSet - emitcode for near pointer put */
11135 /*-----------------------------------------------------------------*/
11137 genNearPointerSet (operand * right,
11144 sym_link *retype, *letype;
11145 sym_link *ptype = operandType (result);
11147 D (emitcode (";", "genNearPointerSet"));
11149 retype = getSpec (operandType (right));
11150 letype = getSpec (ptype);
11152 aopOp (result, ic, FALSE, FALSE);
11154 /* if the result is rematerializable &
11155 in data space & not a bit variable */
11156 if (AOP_TYPE (result) == AOP_IMMD &&
11157 DCL_TYPE (ptype) == POINTER &&
11158 !IS_BITVAR (retype) &&
11159 !IS_BITVAR (letype))
11161 genDataPointerSet (right, result, ic);
11165 /* if the value is already in a pointer register
11166 then don't need anything more */
11167 if (!AOP_INPREG (AOP (result)))
11169 /* otherwise get a free pointer register */
11172 aop = newAsmop (0);
11173 preg = getFreePtr (ic, &aop, FALSE);
11174 emitcode ("mov", "%s,%s",
11176 aopGet (result, 0, FALSE, TRUE, NULL));
11177 rname = preg->name;
11181 rname = aopGet (result, 0, FALSE, FALSE, NULL);
11184 aopOp (right, ic, FALSE, FALSE);
11186 /* if bitfield then unpack the bits */
11187 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11188 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
11191 /* we can just get the values */
11192 int size = AOP_SIZE (right);
11197 l = aopGet (right, offset, FALSE, TRUE, NULL);
11198 if ((*l == '@') || (strcmp (l, "acc") == 0))
11201 emitcode ("mov", "@%s,a", rname);
11204 emitcode ("mov", "@%s,%s", rname, l);
11206 emitcode ("inc", "%s", rname);
11211 /* now some housekeeping stuff */
11212 if (aop) /* we had to allocate for this iCode */
11215 aopPut (result, rname, 0);
11216 freeAsmop (NULL, aop, ic, TRUE);
11220 /* we did not allocate which means left
11221 already in a pointer register, then
11222 if size > 0 && this could be used again
11223 we have to point it back to where it
11225 if (AOP_SIZE (right) > 1 &&
11226 !OP_SYMBOL (result)->remat &&
11227 (OP_SYMBOL (result)->liveTo > ic->seq ||
11231 int size = AOP_SIZE (right) - 1;
11233 emitcode ("dec", "%s", rname);
11238 if (pi) pi->generated = 1;
11239 freeAsmop (result, NULL, ic, TRUE);
11240 freeAsmop (right, NULL, ic, TRUE);
11243 /*-----------------------------------------------------------------*/
11244 /* genPagedPointerSet - emitcode for Paged pointer put */
11245 /*-----------------------------------------------------------------*/
11247 genPagedPointerSet (operand * right,
11254 sym_link *retype, *letype;
11256 D (emitcode (";", "genPagedPointerSet"));
11258 retype = getSpec (operandType (right));
11259 letype = getSpec (operandType (result));
11261 aopOp (result, ic, FALSE, FALSE);
11263 /* if the value is already in a pointer register
11264 then don't need anything more */
11265 if (!AOP_INPREG (AOP (result)))
11267 /* otherwise get a free pointer register */
11270 aop = newAsmop (0);
11271 preg = getFreePtr (ic, &aop, FALSE);
11272 emitcode ("mov", "%s,%s",
11274 aopGet (result, 0, FALSE, TRUE, NULL));
11275 rname = preg->name;
11278 rname = aopGet (result, 0, FALSE, FALSE, NULL);
11280 aopOp (right, ic, FALSE, FALSE);
11282 /* if bitfield then unpack the bits */
11283 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11284 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
11287 /* we have can just get the values */
11288 int size = AOP_SIZE (right);
11293 l = aopGet (right, offset, FALSE, TRUE, NULL);
11295 emitcode ("movx", "@%s,a", rname);
11298 emitcode ("inc", "%s", rname);
11304 /* now some housekeeping stuff */
11308 aopPut (result, rname, 0);
11309 /* we had to allocate for this iCode */
11310 freeAsmop (NULL, aop, ic, TRUE);
11314 /* we did not allocate which means left
11315 already in a pointer register, then
11316 if size > 0 && this could be used again
11317 we have to point it back to where it
11319 if (AOP_SIZE (right) > 1 &&
11320 !OP_SYMBOL (result)->remat &&
11321 (OP_SYMBOL (result)->liveTo > ic->seq ||
11325 int size = AOP_SIZE (right) - 1;
11327 emitcode ("dec", "%s", rname);
11332 if (pi) pi->generated = 1;
11333 freeAsmop (result, NULL, ic, TRUE);
11334 freeAsmop (right, NULL, ic, TRUE);
11337 /*-----------------------------------------------------------------*/
11338 /* genFarPointerSet - set value from far space */
11339 /*-----------------------------------------------------------------*/
11341 genFarPointerSet (operand * right,
11342 operand * result, iCode * ic, iCode *pi)
11344 int size, offset, dopi=1;
11345 sym_link *retype = getSpec (operandType (right));
11346 sym_link *letype = getSpec (operandType (result));
11348 aopOp (result, ic, FALSE, FALSE);
11350 /* if the operand is already in dptr
11351 then we do nothing else we move the value to dptr */
11352 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
11354 /* if this is remateriazable */
11355 if (AOP_TYPE (result) == AOP_IMMD)
11356 emitcode ("mov", "dptr,%s",
11357 aopGet (result, 0, TRUE, FALSE, NULL));
11360 /* we need to get it byte by byte */
11361 _startLazyDPSEvaluation ();
11362 if (AOP_TYPE (result) != AOP_DPTR)
11364 emitcode ("mov", "dpl,%s", aopGet (result, 0, FALSE, FALSE, NULL));
11365 emitcode ("mov", "dph,%s", aopGet (result, 1, FALSE, FALSE, NULL));
11366 if (options.model == MODEL_FLAT24)
11367 emitcode ("mov", "dpx,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11371 /* We need to generate a load to DPTR indirect through DPTR. */
11372 D (emitcode (";", "genFarPointerSet -- indirection special case."););
11374 emitcode ("push", "%s", aopGet (result, 0, FALSE, TRUE, NULL));
11375 emitcode ("push", "%s", aopGet (result, 1, FALSE, TRUE, NULL));
11376 if (options.model == MODEL_FLAT24)
11377 emitcode ("mov", "dpx,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11378 emitcode ("pop", "dph");
11379 emitcode ("pop", "dpl");
11382 _endLazyDPSEvaluation ();
11385 /* so dptr now contains the address */
11386 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
11388 /* if bit then unpack */
11389 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11391 if (AOP_INDPTRn(result)) {
11392 genSetDPTR(AOP(result)->aopu.dptr);
11394 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
11395 if (AOP_INDPTRn(result)) {
11399 size = AOP_SIZE (right);
11401 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
11403 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11405 genSetDPTR(AOP(result)->aopu.dptr);
11406 emitcode ("movx", "@dptr,a");
11407 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
11408 emitcode ("inc", "dptr");
11412 _startLazyDPSEvaluation ();
11414 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11416 if (AOP_INDPTRn(result)) {
11417 genSetDPTR(AOP(result)->aopu.dptr);
11423 emitcode ("movx", "@dptr,a");
11424 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
11425 emitcode ("inc", "dptr");
11427 _endLazyDPSEvaluation ();
11431 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
11432 if (!AOP_INDPTRn(result)) {
11433 _startLazyDPSEvaluation ();
11435 aopPut (result,"dpl",0);
11436 aopPut (result,"dph",1);
11437 if (options.model == MODEL_FLAT24)
11438 aopPut (result,"dpx",2);
11440 _endLazyDPSEvaluation ();
11443 } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
11444 AOP_SIZE(right) > 1 &&
11445 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
11447 size = AOP_SIZE (right) - 1;
11448 if (AOP_INDPTRn(result)) {
11449 genSetDPTR(AOP(result)->aopu.dptr);
11451 while (size--) emitcode ("lcall","__decdptr");
11452 if (AOP_INDPTRn(result)) {
11456 freeAsmop (result, NULL, ic, TRUE);
11457 freeAsmop (right, NULL, ic, TRUE);
11460 /*-----------------------------------------------------------------*/
11461 /* genGenPointerSet - set value from generic pointer space */
11462 /*-----------------------------------------------------------------*/
11464 genGenPointerSet (operand * right,
11465 operand * result, iCode * ic, iCode *pi)
11469 sym_link *retype = getSpec (operandType (right));
11470 sym_link *letype = getSpec (operandType (result));
11472 aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
11474 pushedB = pushB ();
11475 /* if the operand is already in dptr
11476 then we do nothing else we move the value to dptr */
11477 if (AOP_TYPE (result) != AOP_STR)
11479 _startLazyDPSEvaluation ();
11480 /* if this is remateriazable */
11481 if (AOP_TYPE (result) == AOP_IMMD)
11483 emitcode ("mov", "dptr,%s", aopGet (result, 0, TRUE, FALSE, NULL));
11484 if (AOP(result)->aopu.aop_immd.from_cast_remat)
11486 MOVB (aopGet (result, AOP_SIZE(result)-1, FALSE, FALSE, NULL));
11491 "b,%s + 1", aopGet (result, 0, TRUE, FALSE, NULL));
11495 { /* we need to get it byte by byte */
11496 emitcode ("mov", "dpl,%s", aopGet (result, 0, FALSE, FALSE, NULL));
11497 emitcode ("mov", "dph,%s", aopGet (result, 1, FALSE, FALSE, NULL));
11498 if (options.model == MODEL_FLAT24) {
11499 emitcode ("mov", "dpx,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11500 emitcode ("mov", "b,%s", aopGet (result, 3, FALSE, FALSE, NULL));
11502 emitcode ("mov", "b,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11505 _endLazyDPSEvaluation ();
11507 /* so dptr + b now contains the address */
11508 aopOp (right, ic, FALSE, TRUE);
11510 /* if bit then unpack */
11511 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11513 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
11517 size = AOP_SIZE (right);
11520 _startLazyDPSEvaluation ();
11525 // Set two bytes at a time, passed in _AP & A.
11526 // dptr will be incremented ONCE by __gptrputWord.
11528 // Note: any change here must be coordinated
11529 // with the implementation of __gptrputWord
11530 // in device/lib/_gptrput.c
11531 emitcode("mov", "_ap, %s",
11532 aopGet (right, offset++, FALSE, FALSE, NULL));
11533 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11537 emitcode ("lcall", "__gptrputWord");
11542 // Only one byte to put.
11543 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11547 emitcode ("lcall", "__gptrput");
11550 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
11552 emitcode ("inc", "dptr");
11555 _endLazyDPSEvaluation ();
11558 if (pi && AOP_TYPE (result) != AOP_IMMD) {
11559 _startLazyDPSEvaluation ();
11561 aopPut (result, "dpl",0);
11562 aopPut (result, "dph",1);
11563 if (options.model == MODEL_FLAT24) {
11564 aopPut (result, "dpx",2);
11565 aopPut (result, "b",3);
11567 aopPut (result, "b",2);
11569 _endLazyDPSEvaluation ();
11572 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
11573 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
11575 size = AOP_SIZE (right) - 1;
11576 while (size--) emitcode ("lcall","__decdptr");
11580 freeAsmop (result, NULL, ic, TRUE);
11581 freeAsmop (right, NULL, ic, TRUE);
11584 /*-----------------------------------------------------------------*/
11585 /* genPointerSet - stores the value into a pointer location */
11586 /*-----------------------------------------------------------------*/
11588 genPointerSet (iCode * ic, iCode *pi)
11590 operand *right, *result;
11591 sym_link *type, *etype;
11594 D (emitcode (";", "genPointerSet"));
11596 right = IC_RIGHT (ic);
11597 result = IC_RESULT (ic);
11599 /* depending on the type of pointer we need to
11600 move it to the correct pointer register */
11601 type = operandType (result);
11602 etype = getSpec (type);
11603 /* if left is of type of pointer then it is simple */
11604 if (IS_PTR (type) && !IS_FUNC (type->next))
11606 p_type = DCL_TYPE (type);
11610 /* we have to go by the storage class */
11611 p_type = PTR_TYPE (SPEC_OCLS (etype));
11614 /* special case when cast remat */
11615 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
11616 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
11617 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
11618 type = operandType (result);
11619 p_type = DCL_TYPE (type);
11622 /* now that we have the pointer type we assign
11623 the pointer values */
11629 genNearPointerSet (right, result, ic, pi);
11633 genPagedPointerSet (right, result, ic, pi);
11637 genFarPointerSet (right, result, ic, pi);
11641 genGenPointerSet (right, result, ic, pi);
11645 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11646 "genPointerSet: illegal pointer type");
11650 /*-----------------------------------------------------------------*/
11651 /* genIfx - generate code for Ifx statement */
11652 /*-----------------------------------------------------------------*/
11654 genIfx (iCode * ic, iCode * popIc)
11656 operand *cond = IC_COND (ic);
11660 D (emitcode (";", "genIfx"));
11662 aopOp (cond, ic, FALSE, FALSE);
11664 /* get the value into acc */
11665 if (AOP_TYPE (cond) != AOP_CRY)
11672 if (AOP(cond)->aopu.aop_dir)
11673 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
11676 /* the result is now in the accumulator or a directly addressable bit */
11677 freeAsmop (cond, NULL, ic, TRUE);
11679 /* if there was something to be popped then do it */
11683 /* if the condition is a bit variable */
11685 genIfxJump (ic, dup);
11686 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
11687 genIfxJump (ic, SPIL_LOC (cond)->rname);
11688 else if (isbit && !IS_ITEMP (cond))
11689 genIfxJump (ic, OP_SYMBOL (cond)->rname);
11691 genIfxJump (ic, "a");
11696 /*-----------------------------------------------------------------*/
11697 /* genAddrOf - generates code for address of */
11698 /*-----------------------------------------------------------------*/
11700 genAddrOf (iCode * ic)
11702 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
11705 D (emitcode (";", "genAddrOf"));
11707 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11709 /* if the operand is on the stack then we
11710 need to get the stack offset of this
11715 /* if 10 bit stack */
11716 if (options.stack10bit) {
11720 tsprintf(buff, sizeof(buff),
11721 "#!constbyte",(options.stack_loc >> 16) & 0xff);
11722 /* if it has an offset then we need to compute it */
11723 /* emitcode ("subb", "a,#!constbyte", */
11724 /* -((sym->stack < 0) ? */
11725 /* ((short) (sym->stack - _G.nRegsSaved)) : */
11726 /* ((short) sym->stack)) & 0xff); */
11727 /* emitcode ("mov","b,a"); */
11728 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
11729 /* ((short) (sym->stack - _G.nRegsSaved)) : */
11730 /* ((short) sym->stack)) >> 8) & 0xff); */
11732 emitcode ("mov", "a,_bpx");
11733 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
11734 ((char) (sym->stack - _G.nRegsSaved)) :
11735 ((char) sym->stack )) & 0xff);
11736 emitcode ("mov", "b,a");
11737 emitcode ("mov", "a,_bpx+1");
11739 offset = (((sym->stack < 0) ?
11740 ((short) (sym->stack - _G.nRegsSaved)) :
11741 ((short) sym->stack )) >> 8) & 0xff;
11743 emitcode ("addc","a,#!constbyte", offset);
11745 aopPut (IC_RESULT (ic), "b", 0);
11746 aopPut (IC_RESULT (ic), "a", 1);
11747 aopPut (IC_RESULT (ic), buff, 2);
11749 /* we can just move _bp */
11750 aopPut (IC_RESULT (ic), "_bpx", 0);
11751 aopPut (IC_RESULT (ic), "_bpx+1", 1);
11752 aopPut (IC_RESULT (ic), buff, 2);
11755 /* if it has an offset then we need to compute it */
11758 emitcode ("mov", "a,_bp");
11759 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
11760 aopPut (IC_RESULT (ic), "a", 0);
11764 /* we can just move _bp */
11765 aopPut (IC_RESULT (ic), "_bp", 0);
11767 /* fill the result with zero */
11768 size = AOP_SIZE (IC_RESULT (ic)) - 1;
11771 if (options.stack10bit && size < (FPTRSIZE - 1)) {
11773 "*** warning: pointer to stack var truncated.\n");
11779 aopPut (IC_RESULT (ic), zero, offset++);
11785 /* object not on stack then we need the name */
11786 size = AOP_SIZE (IC_RESULT (ic));
11791 char s[SDCC_NAME_MAX];
11795 tsprintf(s, sizeof(s), "#!his",sym->rname);
11798 tsprintf(s, sizeof(s), "#!hihis",sym->rname);
11801 tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
11803 default: /* should not need this (just in case) */
11804 SNPRINTF (s, sizeof(s), "#(%s >> %d)",
11811 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11814 aopPut (IC_RESULT (ic), s, offset++);
11818 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11822 #if 0 // obsolete, and buggy for != xdata
11823 /*-----------------------------------------------------------------*/
11824 /* genArrayInit - generates code for address of */
11825 /*-----------------------------------------------------------------*/
11827 genArrayInit (iCode * ic)
11829 literalList *iLoop;
11831 int elementSize = 0, eIndex;
11832 unsigned val, lastVal;
11834 operand *left=IC_LEFT(ic);
11836 D (emitcode (";", "genArrayInit"));
11838 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
11840 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
11842 // Load immediate value into DPTR.
11843 emitcode("mov", "dptr, %s",
11844 aopGet (IC_LEFT(ic), 0, TRUE, FALSE, NULL));
11846 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
11849 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11850 "Unexpected operand to genArrayInit.\n");
11853 // a regression because of SDCCcse.c:1.52
11854 emitcode ("mov", "dpl,%s", aopGet (left, 0, FALSE, FALSE, NULL));
11855 emitcode ("mov", "dph,%s", aopGet (left, 1, FALSE, FALSE, NULL));
11856 if (options.model == MODEL_FLAT24)
11857 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
11861 type = operandType(IC_LEFT(ic));
11863 if (type && type->next)
11865 elementSize = getSize(type->next);
11869 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11870 "can't determine element size in genArrayInit.\n");
11874 iLoop = IC_ARRAYILIST(ic);
11879 bool firstpass = TRUE;
11881 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
11882 iLoop->count, (int)iLoop->literalValue, elementSize);
11888 symbol *tlbl = NULL;
11890 count = ix > 256 ? 256 : ix;
11894 tlbl = newiTempLabel (NULL);
11895 if (firstpass || (count & 0xff))
11897 emitcode("mov", "b, #!constbyte", count & 0xff);
11905 for (eIndex = 0; eIndex < elementSize; eIndex++)
11907 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
11908 if (val != lastVal)
11910 emitcode("mov", "a, #!constbyte", val);
11914 emitcode("movx", "@dptr, a");
11915 emitcode("inc", "dptr");
11920 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
11926 iLoop = iLoop->next;
11929 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
11933 /*-----------------------------------------------------------------*/
11934 /* genFarFarAssign - assignment when both are in far space */
11935 /*-----------------------------------------------------------------*/
11937 genFarFarAssign (operand * result, operand * right, iCode * ic)
11939 int size = AOP_SIZE (right);
11941 symbol *rSym = NULL;
11945 /* quick & easy case. */
11946 D (emitcode(";","genFarFarAssign (1 byte case)"));
11947 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
11948 freeAsmop (right, NULL, ic, FALSE);
11949 /* now assign DPTR to result */
11951 aopOp(result, ic, FALSE, FALSE);
11953 aopPut (result, "a", 0);
11954 freeAsmop(result, NULL, ic, FALSE);
11958 /* See if we've got an underlying symbol to abuse. */
11959 if (IS_SYMOP(result) && OP_SYMBOL(result))
11961 if (IS_TRUE_SYMOP(result))
11963 rSym = OP_SYMBOL(result);
11965 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
11967 rSym = OP_SYMBOL(result)->usl.spillLoc;
11971 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
11973 /* We can use the '390 auto-toggle feature to good effect here. */
11975 D (emitcode(";", "genFarFarAssign (390 auto-toggle fun)"));
11976 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11977 emitcode ("mov", "dptr,#%s", rSym->rname);
11978 /* DP2 = result, DP1 = right, DP1 is current. */
11981 emitcode("movx", "a,@dptr");
11982 emitcode("movx", "@dptr,a");
11985 emitcode("inc", "dptr");
11986 emitcode("inc", "dptr");
11989 emitcode("mov", "dps,#0");
11990 freeAsmop (right, NULL, ic, FALSE);
11992 some alternative code for processors without auto-toggle
11993 no time to test now, so later well put in...kpb
11994 D (emitcode(";", "genFarFarAssign (dual-dptr fun)"));
11995 emitcode("mov", "dps,#1"); /* Select DPTR2. */
11996 emitcode ("mov", "dptr,#%s", rSym->rname);
11997 /* DP2 = result, DP1 = right, DP1 is current. */
12001 emitcode("movx", "a,@dptr");
12003 emitcode("inc", "dptr");
12004 emitcode("inc", "dps");
12005 emitcode("movx", "@dptr,a");
12007 emitcode("inc", "dptr");
12008 emitcode("inc", "dps");
12010 emitcode("mov", "dps,#0");
12011 freeAsmop (right, NULL, ic, FALSE);
12016 D (emitcode (";", "genFarFarAssign"));
12017 aopOp (result, ic, TRUE, TRUE);
12019 _startLazyDPSEvaluation ();
12024 aopGet (right, offset, FALSE, FALSE, NULL), offset);
12027 _endLazyDPSEvaluation ();
12028 freeAsmop (result, NULL, ic, FALSE);
12029 freeAsmop (right, NULL, ic, FALSE);
12033 /*-----------------------------------------------------------------*/
12034 /* genAssign - generate code for assignment */
12035 /*-----------------------------------------------------------------*/
12037 genAssign (iCode * ic)
12039 operand *result, *right;
12041 unsigned long lit = 0L;
12043 D (emitcode (";", "genAssign"));
12045 result = IC_RESULT (ic);
12046 right = IC_RIGHT (ic);
12048 /* if they are the same */
12049 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
12052 aopOp (right, ic, FALSE, FALSE);
12054 emitcode (";", "genAssign: resultIsFar = %s",
12055 isOperandInFarSpace (result) ?
12058 /* special case both in far space */
12059 if ((AOP_TYPE (right) == AOP_DPTR ||
12060 AOP_TYPE (right) == AOP_DPTR2) &&
12061 /* IS_TRUE_SYMOP(result) && */
12062 isOperandInFarSpace (result))
12064 genFarFarAssign (result, right, ic);
12068 aopOp (result, ic, TRUE, FALSE);
12070 /* if they are the same registers */
12071 if (sameRegs (AOP (right), AOP (result)))
12074 /* if the result is a bit */
12075 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
12077 /* if the right size is a literal then
12078 we know what the value is */
12079 if (AOP_TYPE (right) == AOP_LIT)
12081 if (((int) operandLitValue (right)))
12082 aopPut (result, one, 0);
12084 aopPut (result, zero, 0);
12088 /* the right is also a bit variable */
12089 if (AOP_TYPE (right) == AOP_CRY)
12091 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
12092 aopPut (result, "c", 0);
12096 /* we need to or */
12098 aopPut (result, "a", 0);
12102 /* bit variables done */
12104 size = AOP_SIZE (result);
12106 if (AOP_TYPE (right) == AOP_LIT)
12107 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
12110 (AOP_TYPE (result) != AOP_REG) &&
12111 (AOP_TYPE (right) == AOP_LIT) &&
12112 !IS_FLOAT (operandType (right)))
12114 _startLazyDPSEvaluation ();
12115 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
12118 aopGet (right, offset, FALSE, FALSE, NULL),
12123 /* And now fill the rest with zeros. */
12126 emitcode ("clr", "a");
12130 aopPut (result, "a", offset++);
12132 _endLazyDPSEvaluation ();
12136 _startLazyDPSEvaluation ();
12140 aopGet (right, offset, FALSE, FALSE, NULL),
12144 _endLazyDPSEvaluation ();
12148 freeAsmop (result, NULL, ic, TRUE);
12149 freeAsmop (right, NULL, ic, TRUE);
12152 /*-----------------------------------------------------------------*/
12153 /* genJumpTab - generates code for jump table */
12154 /*-----------------------------------------------------------------*/
12156 genJumpTab (iCode * ic)
12161 D (emitcode (";", "genJumpTab"));
12163 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
12164 /* get the condition into accumulator */
12165 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE, NULL);
12167 /* multiply by four! */
12168 emitcode ("add", "a,acc");
12169 emitcode ("add", "a,acc");
12170 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
12172 jtab = newiTempLabel (NULL);
12173 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
12174 emitcode ("jmp", "@a+dptr");
12176 /* now generate the jump labels */
12177 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
12178 jtab = setNextItem (IC_JTLABELS (ic)))
12179 emitcode ("ljmp", "!tlabel", jtab->key + 100);
12183 /*-----------------------------------------------------------------*/
12184 /* genCast - gen code for casting */
12185 /*-----------------------------------------------------------------*/
12187 genCast (iCode * ic)
12189 operand *result = IC_RESULT (ic);
12190 sym_link *ctype = operandType (IC_LEFT (ic));
12191 sym_link *rtype = operandType (IC_RIGHT (ic));
12192 operand *right = IC_RIGHT (ic);
12195 D (emitcode (";", "genCast"));
12197 /* if they are equivalent then do nothing */
12198 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
12201 aopOp (right, ic, FALSE, AOP_IS_STR (result));
12202 aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR));
12204 /* if the result is a bit (and not a bitfield) */
12205 if (IS_BIT (OP_SYMBOL (result)->type))
12207 /* if the right size is a literal then
12208 we know what the value is */
12209 if (AOP_TYPE (right) == AOP_LIT)
12211 if (((int) operandLitValue (right)))
12212 aopPut (result, one, 0);
12214 aopPut (result, zero, 0);
12219 /* the right is also a bit variable */
12220 if (AOP_TYPE (right) == AOP_CRY)
12222 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
12223 aopPut (result, "c", 0);
12227 /* we need to or */
12229 aopPut (result, "a", 0);
12233 /* if they are the same size : or less */
12234 if (AOP_SIZE (result) <= AOP_SIZE (right))
12237 /* if they are in the same place */
12238 if (sameRegs (AOP (right), AOP (result)))
12241 /* if they in different places then copy */
12242 size = AOP_SIZE (result);
12244 _startLazyDPSEvaluation ();
12248 aopGet (right, offset, FALSE, FALSE, NULL),
12252 _endLazyDPSEvaluation ();
12256 /* if the result is of type pointer */
12257 if (IS_PTR (ctype))
12261 sym_link *type = operandType (right);
12263 /* pointer to generic pointer */
12264 if (IS_GENPTR (ctype))
12268 p_type = DCL_TYPE (type);
12272 #if OLD_CAST_BEHAVIOR
12273 /* KV: we are converting a non-pointer type to
12274 * a generic pointer. This (ifdef'd out) code
12275 * says that the resulting generic pointer
12276 * should have the same class as the storage
12277 * location of the non-pointer variable.
12279 * For example, converting an int (which happens
12280 * to be stored in DATA space) to a pointer results
12281 * in a DATA generic pointer; if the original int
12282 * in XDATA space, so will be the resulting pointer.
12284 * I don't like that behavior, and thus this change:
12285 * all such conversions will be forced to XDATA and
12286 * throw a warning. If you want some non-XDATA
12287 * type, or you want to suppress the warning, you
12288 * must go through an intermediate cast, like so:
12290 * char _generic *gp = (char _xdata *)(intVar);
12292 sym_link *etype = getSpec (type);
12294 /* we have to go by the storage class */
12295 if (SPEC_OCLS (etype) != generic)
12297 p_type = PTR_TYPE (SPEC_OCLS (etype));
12302 /* Converting unknown class (i.e. register variable)
12303 * to generic pointer. This is not good, but
12304 * we'll make a guess (and throw a warning).
12307 werror (W_INT_TO_GEN_PTR_CAST);
12311 /* the first two bytes are known */
12312 size = GPTRSIZE - 1;
12314 _startLazyDPSEvaluation ();
12318 aopGet (right, offset, FALSE, FALSE, NULL),
12322 _endLazyDPSEvaluation ();
12324 /* the last byte depending on type */
12326 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
12331 // pointerTypeToGPByte will have bitched.
12335 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%x", gpVal);
12336 aopPut (result, gpValStr, GPTRSIZE - 1);
12341 /* just copy the pointers */
12342 size = AOP_SIZE (result);
12344 _startLazyDPSEvaluation ();
12348 aopGet (right, offset, FALSE, FALSE, NULL),
12352 _endLazyDPSEvaluation ();
12356 /* so we now know that the size of destination is greater
12357 than the size of the source */
12358 /* we move to result for the size of source */
12359 size = AOP_SIZE (right);
12361 _startLazyDPSEvaluation ();
12365 aopGet (right, offset, FALSE, FALSE, NULL),
12369 _endLazyDPSEvaluation ();
12371 /* now depending on the sign of the source && destination */
12372 size = AOP_SIZE (result) - AOP_SIZE (right);
12373 /* if unsigned or not an integral type */
12374 /* also, if the source is a bit, we don't need to sign extend, because
12375 * it can't possibly have set the sign bit.
12377 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
12381 aopPut (result, zero, offset++);
12386 /* we need to extend the sign :{ */
12387 MOVA (aopGet (right, AOP_SIZE (right) - 1,
12388 FALSE, FALSE, NULL));
12389 emitcode ("rlc", "a");
12390 emitcode ("subb", "a,acc");
12392 aopPut (result, "a", offset++);
12395 /* we are done hurray !!!! */
12398 freeAsmop (right, NULL, ic, TRUE);
12399 freeAsmop (result, NULL, ic, TRUE);
12403 /*-----------------------------------------------------------------*/
12404 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
12405 /*-----------------------------------------------------------------*/
12406 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
12408 operand *from , *to , *count;
12413 /* we know it has to be 3 parameters */
12414 assert (nparms == 3);
12416 rsave = newBitVect(16);
12417 /* save DPTR if it needs to be saved */
12418 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12419 if (bitVectBitValue(ic->rMask,i))
12420 rsave = bitVectSetBit(rsave,i);
12422 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12423 ds390_rUmaskForOp (IC_RESULT(ic))));
12430 aopOp (from, ic->next, FALSE, FALSE);
12432 /* get from into DPTR1 */
12433 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12434 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12435 if (options.model == MODEL_FLAT24) {
12436 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12439 freeAsmop (from, NULL, ic, FALSE);
12440 aopOp (to, ic, FALSE, FALSE);
12441 /* get "to" into DPTR */
12442 /* if the operand is already in dptr
12443 then we do nothing else we move the value to dptr */
12444 if (AOP_TYPE (to) != AOP_STR) {
12445 /* if already in DPTR then we need to push */
12446 if (AOP_TYPE(to) == AOP_DPTR) {
12447 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12448 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12449 if (options.model == MODEL_FLAT24)
12450 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12451 emitcode ("pop", "dph");
12452 emitcode ("pop", "dpl");
12454 _startLazyDPSEvaluation ();
12455 /* if this is remateriazable */
12456 if (AOP_TYPE (to) == AOP_IMMD) {
12457 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12458 } else { /* we need to get it byte by byte */
12459 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12460 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12461 if (options.model == MODEL_FLAT24) {
12462 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12465 _endLazyDPSEvaluation ();
12468 freeAsmop (to, NULL, ic, FALSE);
12469 _G.dptrInUse = _G.dptr1InUse = 1;
12470 aopOp (count, ic->next->next, FALSE,FALSE);
12471 lbl =newiTempLabel(NULL);
12473 /* now for the actual copy */
12474 if (AOP_TYPE(count) == AOP_LIT &&
12475 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12476 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12478 emitcode ("lcall","__bi_memcpyc2x_s");
12480 emitcode ("lcall","__bi_memcpyx2x_s");
12482 freeAsmop (count, NULL, ic, FALSE);
12484 symbol *lbl1 = newiTempLabel(NULL);
12486 emitcode (";"," Auto increment but no djnz");
12487 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
12488 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
12489 freeAsmop (count, NULL, ic, FALSE);
12490 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12491 emitcode ("","!tlabeldef",lbl->key+100);
12493 emitcode ("clr","a");
12494 emitcode ("movc", "a,@a+dptr");
12496 emitcode ("movx", "a,@dptr");
12497 emitcode ("movx", "@dptr,a");
12498 emitcode ("inc", "dptr");
12499 emitcode ("inc", "dptr");
12500 emitcode ("mov","a,b");
12501 emitcode ("orl","a,_ap");
12502 emitcode ("jz","!tlabel",lbl1->key+100);
12503 emitcode ("mov","a,_ap");
12504 emitcode ("add","a,#!constbyte",0xFF);
12505 emitcode ("mov","_ap,a");
12506 emitcode ("mov","a,b");
12507 emitcode ("addc","a,#!constbyte",0xFF);
12508 emitcode ("mov","b,a");
12509 emitcode ("sjmp","!tlabel",lbl->key+100);
12510 emitcode ("","!tlabeldef",lbl1->key+100);
12512 emitcode ("mov", "dps,#0");
12513 _G.dptrInUse = _G.dptr1InUse = 0;
12514 unsavermask(rsave);
12518 /*-----------------------------------------------------------------*/
12519 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
12520 /*-----------------------------------------------------------------*/
12521 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
12523 operand *from , *to , *count;
12528 /* we know it has to be 3 parameters */
12529 assert (nparms == 3);
12531 rsave = newBitVect(16);
12532 /* save DPTR if it needs to be saved */
12533 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12534 if (bitVectBitValue(ic->rMask,i))
12535 rsave = bitVectSetBit(rsave,i);
12537 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12538 ds390_rUmaskForOp (IC_RESULT(ic))));
12545 aopOp (from, ic->next, FALSE, FALSE);
12547 /* get from into DPTR1 */
12548 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12549 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12550 if (options.model == MODEL_FLAT24) {
12551 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12554 freeAsmop (from, NULL, ic, FALSE);
12555 aopOp (to, ic, FALSE, FALSE);
12556 /* get "to" into DPTR */
12557 /* if the operand is already in dptr
12558 then we do nothing else we move the value to dptr */
12559 if (AOP_TYPE (to) != AOP_STR) {
12560 /* if already in DPTR then we need to push */
12561 if (AOP_TYPE(to) == AOP_DPTR) {
12562 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12563 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12564 if (options.model == MODEL_FLAT24)
12565 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12566 emitcode ("pop", "dph");
12567 emitcode ("pop", "dpl");
12569 _startLazyDPSEvaluation ();
12570 /* if this is remateriazable */
12571 if (AOP_TYPE (to) == AOP_IMMD) {
12572 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12573 } else { /* we need to get it byte by byte */
12574 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12575 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12576 if (options.model == MODEL_FLAT24) {
12577 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12580 _endLazyDPSEvaluation ();
12583 freeAsmop (to, NULL, ic, FALSE);
12584 _G.dptrInUse = _G.dptr1InUse = 1;
12585 aopOp (count, ic->next->next, FALSE,FALSE);
12586 lbl =newiTempLabel(NULL);
12587 lbl2 =newiTempLabel(NULL);
12589 /* now for the actual compare */
12590 if (AOP_TYPE(count) == AOP_LIT &&
12591 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12592 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12594 emitcode("lcall","__bi_memcmpc2x_s");
12596 emitcode("lcall","__bi_memcmpx2x_s");
12597 freeAsmop (count, NULL, ic, FALSE);
12598 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12599 aopPut(IC_RESULT(ic),"a",0);
12600 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12602 symbol *lbl1 = newiTempLabel(NULL);
12604 emitcode("push","ar0");
12605 emitcode (";"," Auto increment but no djnz");
12606 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
12607 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
12608 freeAsmop (count, NULL, ic, FALSE);
12609 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12610 emitcode ("","!tlabeldef",lbl->key+100);
12612 emitcode ("clr","a");
12613 emitcode ("movc", "a,@a+dptr");
12615 emitcode ("movx", "a,@dptr");
12616 emitcode ("mov","r0,a");
12617 emitcode ("movx", "a,@dptr");
12618 emitcode ("clr","c");
12619 emitcode ("subb","a,r0");
12620 emitcode ("jnz","!tlabel",lbl2->key+100);
12621 emitcode ("inc", "dptr");
12622 emitcode ("inc", "dptr");
12623 emitcode ("mov","a,b");
12624 emitcode ("orl","a,_ap");
12625 emitcode ("jz","!tlabel",lbl1->key+100);
12626 emitcode ("mov","a,_ap");
12627 emitcode ("add","a,#!constbyte",0xFF);
12628 emitcode ("mov","_ap,a");
12629 emitcode ("mov","a,b");
12630 emitcode ("addc","a,#!constbyte",0xFF);
12631 emitcode ("mov","b,a");
12632 emitcode ("sjmp","!tlabel",lbl->key+100);
12633 emitcode ("","!tlabeldef",lbl1->key+100);
12634 emitcode ("clr","a");
12635 emitcode ("","!tlabeldef",lbl2->key+100);
12636 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12637 aopPut(IC_RESULT(ic),"a",0);
12638 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12639 emitcode("pop","ar0");
12640 emitcode ("mov", "dps,#0");
12642 _G.dptrInUse = _G.dptr1InUse = 0;
12643 unsavermask(rsave);
12647 /*-----------------------------------------------------------------*/
12648 /* genInp - gen code for __builtin_inp read data from a mem mapped */
12649 /* port, first parameter output area second parameter pointer to */
12650 /* port third parameter count */
12651 /*-----------------------------------------------------------------*/
12652 static void genInp( iCode *ic, int nparms, operand **parms)
12654 operand *from , *to , *count;
12659 /* we know it has to be 3 parameters */
12660 assert (nparms == 3);
12662 rsave = newBitVect(16);
12663 /* save DPTR if it needs to be saved */
12664 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12665 if (bitVectBitValue(ic->rMask,i))
12666 rsave = bitVectSetBit(rsave,i);
12668 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12669 ds390_rUmaskForOp (IC_RESULT(ic))));
12676 aopOp (from, ic->next, FALSE, FALSE);
12678 /* get from into DPTR1 */
12679 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12680 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12681 if (options.model == MODEL_FLAT24) {
12682 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12685 freeAsmop (from, NULL, ic, FALSE);
12686 aopOp (to, ic, FALSE, FALSE);
12687 /* get "to" into DPTR */
12688 /* if the operand is already in dptr
12689 then we do nothing else we move the value to dptr */
12690 if (AOP_TYPE (to) != AOP_STR) {
12691 /* if already in DPTR then we need to push */
12692 if (AOP_TYPE(to) == AOP_DPTR) {
12693 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12694 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12695 if (options.model == MODEL_FLAT24)
12696 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12697 emitcode ("pop", "dph");
12698 emitcode ("pop", "dpl");
12700 _startLazyDPSEvaluation ();
12701 /* if this is remateriazable */
12702 if (AOP_TYPE (to) == AOP_IMMD) {
12703 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12704 } else { /* we need to get it byte by byte */
12705 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12706 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12707 if (options.model == MODEL_FLAT24) {
12708 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12711 _endLazyDPSEvaluation ();
12714 freeAsmop (to, NULL, ic, FALSE);
12716 _G.dptrInUse = _G.dptr1InUse = 1;
12717 aopOp (count, ic->next->next, FALSE,FALSE);
12718 lbl =newiTempLabel(NULL);
12720 /* now for the actual copy */
12721 if (AOP_TYPE(count) == AOP_LIT &&
12722 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12723 emitcode (";","OH JOY auto increment with djnz (very fast)");
12724 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
12725 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12726 freeAsmop (count, NULL, ic, FALSE);
12727 emitcode ("","!tlabeldef",lbl->key+100);
12728 emitcode ("movx", "a,@dptr"); /* read data from port */
12729 emitcode ("dec","dps"); /* switch to DPTR */
12730 emitcode ("movx", "@dptr,a"); /* save into location */
12731 emitcode ("inc", "dptr"); /* point to next area */
12732 emitcode ("inc","dps"); /* switch to DPTR2 */
12733 emitcode ("djnz","b,!tlabel",lbl->key+100);
12735 symbol *lbl1 = newiTempLabel(NULL);
12737 emitcode (";"," Auto increment but no djnz");
12738 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
12739 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
12740 freeAsmop (count, NULL, ic, FALSE);
12741 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
12742 emitcode ("","!tlabeldef",lbl->key+100);
12743 emitcode ("movx", "a,@dptr");
12744 emitcode ("dec","dps"); /* switch to DPTR */
12745 emitcode ("movx", "@dptr,a");
12746 emitcode ("inc", "dptr");
12747 emitcode ("inc","dps"); /* switch to DPTR2 */
12748 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
12749 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
12750 emitcode ("mov","a,b");
12751 emitcode ("orl","a,_ap");
12752 emitcode ("jz","!tlabel",lbl1->key+100);
12753 emitcode ("mov","a,_ap");
12754 emitcode ("add","a,#!constbyte",0xFF);
12755 emitcode ("mov","_ap,a");
12756 emitcode ("mov","a,b");
12757 emitcode ("addc","a,#!constbyte",0xFF);
12758 emitcode ("mov","b,a");
12759 emitcode ("sjmp","!tlabel",lbl->key+100);
12760 emitcode ("","!tlabeldef",lbl1->key+100);
12762 emitcode ("mov", "dps,#0");
12763 _G.dptrInUse = _G.dptr1InUse = 0;
12764 unsavermask(rsave);
12768 /*-----------------------------------------------------------------*/
12769 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
12770 /* port, first parameter output area second parameter pointer to */
12771 /* port third parameter count */
12772 /*-----------------------------------------------------------------*/
12773 static void genOutp( iCode *ic, int nparms, operand **parms)
12775 operand *from , *to , *count;
12780 /* we know it has to be 3 parameters */
12781 assert (nparms == 3);
12783 rsave = newBitVect(16);
12784 /* save DPTR if it needs to be saved */
12785 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12786 if (bitVectBitValue(ic->rMask,i))
12787 rsave = bitVectSetBit(rsave,i);
12789 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12790 ds390_rUmaskForOp (IC_RESULT(ic))));
12797 aopOp (from, ic->next, FALSE, FALSE);
12799 /* get from into DPTR1 */
12800 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12801 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12802 if (options.model == MODEL_FLAT24) {
12803 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12806 freeAsmop (from, NULL, ic, FALSE);
12807 aopOp (to, ic, FALSE, FALSE);
12808 /* get "to" into DPTR */
12809 /* if the operand is already in dptr
12810 then we do nothing else we move the value to dptr */
12811 if (AOP_TYPE (to) != AOP_STR) {
12812 /* if already in DPTR then we need to push */
12813 if (AOP_TYPE(to) == AOP_DPTR) {
12814 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12815 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12816 if (options.model == MODEL_FLAT24)
12817 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12818 emitcode ("pop", "dph");
12819 emitcode ("pop", "dpl");
12821 _startLazyDPSEvaluation ();
12822 /* if this is remateriazable */
12823 if (AOP_TYPE (to) == AOP_IMMD) {
12824 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12825 } else { /* we need to get it byte by byte */
12826 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12827 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12828 if (options.model == MODEL_FLAT24) {
12829 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12832 _endLazyDPSEvaluation ();
12835 freeAsmop (to, NULL, ic, FALSE);
12837 _G.dptrInUse = _G.dptr1InUse = 1;
12838 aopOp (count, ic->next->next, FALSE,FALSE);
12839 lbl =newiTempLabel(NULL);
12841 /* now for the actual copy */
12842 if (AOP_TYPE(count) == AOP_LIT &&
12843 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12844 emitcode (";","OH JOY auto increment with djnz (very fast)");
12845 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
12846 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12847 emitcode ("","!tlabeldef",lbl->key+100);
12848 emitcode ("movx", "a,@dptr"); /* read data from port */
12849 emitcode ("inc","dps"); /* switch to DPTR2 */
12850 emitcode ("movx", "@dptr,a"); /* save into location */
12851 emitcode ("inc", "dptr"); /* point to next area */
12852 emitcode ("dec","dps"); /* switch to DPTR */
12853 emitcode ("djnz","b,!tlabel",lbl->key+100);
12854 freeAsmop (count, NULL, ic, FALSE);
12856 symbol *lbl1 = newiTempLabel(NULL);
12858 emitcode (";"," Auto increment but no djnz");
12859 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
12860 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
12861 freeAsmop (count, NULL, ic, FALSE);
12862 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
12863 emitcode ("","!tlabeldef",lbl->key+100);
12864 emitcode ("movx", "a,@dptr");
12865 emitcode ("inc", "dptr");
12866 emitcode ("inc","dps"); /* switch to DPTR2 */
12867 emitcode ("movx", "@dptr,a");
12868 emitcode ("dec","dps"); /* switch to DPTR */
12869 emitcode ("mov","a,b");
12870 emitcode ("orl","a,_ap");
12871 emitcode ("jz","!tlabel",lbl1->key+100);
12872 emitcode ("mov","a,_ap");
12873 emitcode ("add","a,#!constbyte",0xFF);
12874 emitcode ("mov","_ap,a");
12875 emitcode ("mov","a,b");
12876 emitcode ("addc","a,#!constbyte",0xFF);
12877 emitcode ("mov","b,a");
12878 emitcode ("sjmp","!tlabel",lbl->key+100);
12879 emitcode ("","!tlabeldef",lbl1->key+100);
12881 emitcode ("mov", "dps,#0");
12882 _G.dptrInUse = _G.dptr1InUse = 0;
12883 unsavermask(rsave);
12887 /*-----------------------------------------------------------------*/
12888 /* genSwapW - swap lower & high order bytes */
12889 /*-----------------------------------------------------------------*/
12890 static void genSwapW(iCode *ic, int nparms, operand **parms)
12894 assert (nparms==1);
12897 dest=IC_RESULT(ic);
12899 assert(getSize(operandType(src))==2);
12901 aopOp (src, ic, FALSE, FALSE);
12902 emitcode ("mov","a,%s",aopGet(src,0,FALSE,FALSE,NULL));
12904 MOVB(aopGet(src,1,FALSE,FALSE,"b"));
12906 freeAsmop (src, NULL, ic, FALSE);
12908 aopOp (dest,ic, FALSE, FALSE);
12909 aopPut(dest,"b",0);
12910 aopPut(dest,"a",1);
12911 freeAsmop (dest, NULL, ic, FALSE);
12914 /*-----------------------------------------------------------------*/
12915 /* genMemsetX - gencode for memSetX data */
12916 /*-----------------------------------------------------------------*/
12917 static void genMemsetX(iCode *ic, int nparms, operand **parms)
12919 operand *to , *val , *count;
12925 /* we know it has to be 3 parameters */
12926 assert (nparms == 3);
12932 /* save DPTR if it needs to be saved */
12933 rsave = newBitVect(16);
12934 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12935 if (bitVectBitValue(ic->rMask,i))
12936 rsave = bitVectSetBit(rsave,i);
12938 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12939 ds390_rUmaskForOp (IC_RESULT(ic))));
12942 aopOp (to, ic, FALSE, FALSE);
12943 /* get "to" into DPTR */
12944 /* if the operand is already in dptr
12945 then we do nothing else we move the value to dptr */
12946 if (AOP_TYPE (to) != AOP_STR) {
12947 /* if already in DPTR then we need to push */
12948 if (AOP_TYPE(to) == AOP_DPTR) {
12949 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12950 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12951 if (options.model == MODEL_FLAT24)
12952 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12953 emitcode ("pop", "dph");
12954 emitcode ("pop", "dpl");
12956 _startLazyDPSEvaluation ();
12957 /* if this is remateriazable */
12958 if (AOP_TYPE (to) == AOP_IMMD) {
12959 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12960 } else { /* we need to get it byte by byte */
12961 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12962 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12963 if (options.model == MODEL_FLAT24) {
12964 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12967 _endLazyDPSEvaluation ();
12970 freeAsmop (to, NULL, ic, FALSE);
12972 aopOp (val, ic->next->next, FALSE,FALSE);
12973 aopOp (count, ic->next->next, FALSE,FALSE);
12974 lbl =newiTempLabel(NULL);
12975 /* now for the actual copy */
12976 if (AOP_TYPE(count) == AOP_LIT &&
12977 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12978 l = aopGet(val, 0, FALSE, FALSE, NULL);
12979 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12981 emitcode ("","!tlabeldef",lbl->key+100);
12982 emitcode ("movx", "@dptr,a");
12983 emitcode ("inc", "dptr");
12984 emitcode ("djnz","b,!tlabel",lbl->key+100);
12986 symbol *lbl1 = newiTempLabel(NULL);
12988 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
12989 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
12990 emitcode ("","!tlabeldef",lbl->key+100);
12991 MOVA (aopGet(val, 0, FALSE, FALSE, NULL));
12992 emitcode ("movx", "@dptr,a");
12993 emitcode ("inc", "dptr");
12994 emitcode ("mov","a,b");
12995 emitcode ("orl","a,_ap");
12996 emitcode ("jz","!tlabel",lbl1->key+100);
12997 emitcode ("mov","a,_ap");
12998 emitcode ("add","a,#!constbyte",0xFF);
12999 emitcode ("mov","_ap,a");
13000 emitcode ("mov","a,b");
13001 emitcode ("addc","a,#!constbyte",0xFF);
13002 emitcode ("mov","b,a");
13003 emitcode ("sjmp","!tlabel",lbl->key+100);
13004 emitcode ("","!tlabeldef",lbl1->key+100);
13006 freeAsmop (count, NULL, ic, FALSE);
13007 unsavermask(rsave);
13010 /*-----------------------------------------------------------------*/
13011 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
13012 /*-----------------------------------------------------------------*/
13013 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
13016 operand *pnum, *result;
13019 assert (nparms==1);
13020 /* save registers that need to be saved */
13021 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13022 ds390_rUmaskForOp (IC_RESULT(ic))));
13025 aopOp (pnum, ic, FALSE, FALSE);
13026 emitcode ("mov","a,%s",aopGet(pnum,0,FALSE,FALSE,DP2_RESULT_REG));
13027 freeAsmop (pnum, NULL, ic, FALSE);
13028 emitcode ("lcall","NatLib_LoadPrimitive");
13029 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
13030 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
13031 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
13032 for (i = (size-1) ; i >= 0 ; i-- ) {
13033 emitcode ("push","a%s",javaRet[i]);
13035 for (i=0; i < size ; i++ ) {
13036 emitcode ("pop","a%s",
13037 aopGet(result,i,FALSE,FALSE,DP2_RESULT_REG));
13040 for (i = 0 ; i < size ; i++ ) {
13041 aopPut(result,javaRet[i],i);
13044 freeAsmop (result, NULL, ic, FALSE);
13045 unsavermask(rsave);
13048 /*-----------------------------------------------------------------*/
13049 /* genNatLibLoadPointer - calls TINI api function to load pointer */
13050 /*-----------------------------------------------------------------*/
13051 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
13054 operand *pnum, *result;
13058 assert (nparms==1);
13059 /* save registers that need to be saved */
13060 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13061 ds390_rUmaskForOp (IC_RESULT(ic))));
13064 aopOp (pnum, ic, FALSE, FALSE);
13065 emitcode ("mov","a,%s",aopGet(pnum,0,FALSE,FALSE,DP2_RESULT_REG));
13066 freeAsmop (pnum, NULL, ic, FALSE);
13067 emitcode ("lcall","NatLib_LoadPointer");
13068 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
13069 if (AOP_TYPE(result)!=AOP_STR) {
13070 for (i = 0 ; i < size ; i++ ) {
13071 aopPut(result,fReturn[i],i);
13074 freeAsmop (result, NULL, ic, FALSE);
13075 unsavermask(rsave);
13078 /*-----------------------------------------------------------------*/
13079 /* genNatLibInstallStateBlock - */
13080 /*-----------------------------------------------------------------*/
13081 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
13082 operand **parms, const char *name)
13085 operand *psb, *handle;
13086 assert (nparms==2);
13088 /* save registers that need to be saved */
13089 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13090 ds390_rUmaskForOp (IC_RESULT(ic))));
13094 /* put pointer to state block into DPTR1 */
13095 aopOp (psb, ic, FALSE, FALSE);
13096 if (AOP_TYPE (psb) == AOP_IMMD) {
13097 emitcode ("mov","dps,#1");
13098 emitcode ("mov", "dptr,%s",
13099 aopGet (psb, 0, TRUE, FALSE, DP2_RESULT_REG));
13100 emitcode ("mov","dps,#0");
13102 emitcode ("mov","dpl1,%s",aopGet(psb,0,FALSE,FALSE,DP2_RESULT_REG));
13103 emitcode ("mov","dph1,%s",aopGet(psb,1,FALSE,FALSE,DP2_RESULT_REG));
13104 emitcode ("mov","dpx1,%s",aopGet(psb,2,FALSE,FALSE,DP2_RESULT_REG));
13106 freeAsmop (psb, NULL, ic, FALSE);
13108 /* put libraryID into DPTR */
13109 emitcode ("mov","dptr,#LibraryID");
13111 /* put handle into r3:r2 */
13112 aopOp (handle, ic, FALSE, FALSE);
13113 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13114 emitcode ("push","%s",aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13115 emitcode ("push","%s",aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13116 emitcode ("pop","ar3");
13117 emitcode ("pop","ar2");
13119 emitcode ("mov","r2,%s",aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13120 emitcode ("mov","r3,%s",aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13122 freeAsmop (psb, NULL, ic, FALSE);
13124 /* make the call */
13125 emitcode ("lcall","NatLib_Install%sStateBlock",name);
13127 /* put return value into place*/
13129 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
13131 aopPut(IC_RESULT(ic),"a",0);
13132 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13133 unsavermask(rsave);
13136 /*-----------------------------------------------------------------*/
13137 /* genNatLibRemoveStateBlock - */
13138 /*-----------------------------------------------------------------*/
13139 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
13145 /* save registers that need to be saved */
13146 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13147 ds390_rUmaskForOp (IC_RESULT(ic))));
13149 /* put libraryID into DPTR */
13150 emitcode ("mov","dptr,#LibraryID");
13151 /* make the call */
13152 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
13153 unsavermask(rsave);
13156 /*-----------------------------------------------------------------*/
13157 /* genNatLibGetStateBlock - */
13158 /*-----------------------------------------------------------------*/
13159 static void genNatLibGetStateBlock(iCode *ic,int nparms,
13160 operand **parms,const char *name)
13163 symbol *lbl = newiTempLabel(NULL);
13166 /* save registers that need to be saved */
13167 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13168 ds390_rUmaskForOp (IC_RESULT(ic))));
13170 /* put libraryID into DPTR */
13171 emitcode ("mov","dptr,#LibraryID");
13172 /* make the call */
13173 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
13174 emitcode ("jnz","!tlabel",lbl->key+100);
13176 /* put return value into place */
13177 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
13178 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
13179 emitcode ("push","ar3");
13180 emitcode ("push","ar2");
13181 emitcode ("pop","%s",
13182 aopGet(IC_RESULT(ic),0,FALSE,TRUE,DP2_RESULT_REG));
13183 emitcode ("pop","%s",
13184 aopGet(IC_RESULT(ic),1,FALSE,TRUE,DP2_RESULT_REG));
13186 aopPut(IC_RESULT(ic),"r2",0);
13187 aopPut(IC_RESULT(ic),"r3",1);
13189 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13190 emitcode ("","!tlabeldef",lbl->key+100);
13191 unsavermask(rsave);
13194 /*-----------------------------------------------------------------*/
13195 /* genMMMalloc - */
13196 /*-----------------------------------------------------------------*/
13197 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
13198 int size, const char *name)
13203 symbol *lbl = newiTempLabel(NULL);
13205 assert (nparms == 1);
13206 /* save registers that need to be saved */
13207 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13208 ds390_rUmaskForOp (IC_RESULT(ic))));
13211 aopOp (bsize,ic,FALSE,FALSE);
13213 /* put the size in R4-R2 */
13214 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
13215 emitcode("push","%s",aopGet(bsize,0,FALSE,TRUE,DP2_RESULT_REG));
13216 emitcode("push","%s",aopGet(bsize,1,FALSE,TRUE,DP2_RESULT_REG));
13218 emitcode("push","%s",aopGet(bsize,2,FALSE,TRUE,DP2_RESULT_REG));
13219 emitcode("pop","ar4");
13221 emitcode("pop","ar3");
13222 emitcode("pop","ar2");
13224 emitcode ("mov","r2,%s",aopGet(bsize,0,FALSE,TRUE,DP2_RESULT_REG));
13225 emitcode ("mov","r3,%s",aopGet(bsize,1,FALSE,TRUE,DP2_RESULT_REG));
13227 emitcode("mov","r4,%s",aopGet(bsize,2,FALSE,TRUE,DP2_RESULT_REG));
13230 freeAsmop (bsize, NULL, ic, FALSE);
13232 /* make the call */
13233 emitcode ("lcall","MM_%s",name);
13234 emitcode ("jz","!tlabel",lbl->key+100);
13235 emitcode ("mov","r2,#!constbyte",0xff);
13236 emitcode ("mov","r3,#!constbyte",0xff);
13237 emitcode ("","!tlabeldef",lbl->key+100);
13238 /* we don't care about the pointer : we just save the handle */
13239 rsym = OP_SYMBOL(IC_RESULT(ic));
13240 if (rsym->liveFrom != rsym->liveTo) {
13241 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
13242 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
13243 emitcode ("push","ar3");
13244 emitcode ("push","ar2");
13245 emitcode ("pop","%s",
13246 aopGet(IC_RESULT(ic),0,FALSE,TRUE,DP2_RESULT_REG));
13247 emitcode ("pop","%s",
13248 aopGet(IC_RESULT(ic),1,FALSE,TRUE,DP2_RESULT_REG));
13250 aopPut(IC_RESULT(ic),"r2",0);
13251 aopPut(IC_RESULT(ic),"r3",1);
13253 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13255 unsavermask(rsave);
13258 /*-----------------------------------------------------------------*/
13260 /*-----------------------------------------------------------------*/
13261 static void genMMDeref (iCode *ic,int nparms, operand **parms)
13266 assert (nparms == 1);
13267 /* save registers that need to be saved */
13268 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13269 ds390_rUmaskForOp (IC_RESULT(ic))));
13272 aopOp (handle,ic,FALSE,FALSE);
13274 /* put the size in R4-R2 */
13275 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13276 emitcode("push","%s",
13277 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13278 emitcode("push","%s",
13279 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13280 emitcode("pop","ar3");
13281 emitcode("pop","ar2");
13283 emitcode ("mov","r2,%s",
13284 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13285 emitcode ("mov","r3,%s",
13286 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13288 freeAsmop (handle, NULL, ic, FALSE);
13290 /* make the call */
13291 emitcode ("lcall","MM_Deref");
13294 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13295 if (rsym->liveFrom != rsym->liveTo) {
13296 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13297 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
13298 _startLazyDPSEvaluation ();
13300 aopPut(IC_RESULT(ic),"dpl",0);
13301 aopPut(IC_RESULT(ic),"dph",1);
13302 aopPut(IC_RESULT(ic),"dpx",2);
13304 _endLazyDPSEvaluation ();
13309 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13310 unsavermask(rsave);
13313 /*-----------------------------------------------------------------*/
13314 /* genMMUnrestrictedPersist - */
13315 /*-----------------------------------------------------------------*/
13316 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
13321 assert (nparms == 1);
13322 /* save registers that need to be saved */
13323 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13324 ds390_rUmaskForOp (IC_RESULT(ic))));
13327 aopOp (handle,ic,FALSE,FALSE);
13329 /* put the size in R3-R2 */
13330 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13331 emitcode("push","%s",
13332 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13333 emitcode("push","%s",
13334 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13335 emitcode("pop","ar3");
13336 emitcode("pop","ar2");
13338 emitcode ("mov","r2,%s",
13339 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13340 emitcode ("mov","r3,%s",
13341 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13343 freeAsmop (handle, NULL, ic, FALSE);
13345 /* make the call */
13346 emitcode ("lcall","MM_UnrestrictedPersist");
13349 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13350 if (rsym->liveFrom != rsym->liveTo) {
13351 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13352 aopPut(IC_RESULT(ic),"a",0);
13353 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13356 unsavermask(rsave);
13359 /*-----------------------------------------------------------------*/
13360 /* genSystemExecJavaProcess - */
13361 /*-----------------------------------------------------------------*/
13362 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
13365 operand *handle, *pp;
13367 assert (nparms==2);
13368 /* save registers that need to be saved */
13369 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13370 ds390_rUmaskForOp (IC_RESULT(ic))));
13375 /* put the handle in R3-R2 */
13376 aopOp (handle,ic,FALSE,FALSE);
13377 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13378 emitcode("push","%s",
13379 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13380 emitcode("push","%s",
13381 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13382 emitcode("pop","ar3");
13383 emitcode("pop","ar2");
13385 emitcode ("mov","r2,%s",
13386 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13387 emitcode ("mov","r3,%s",
13388 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13390 freeAsmop (handle, NULL, ic, FALSE);
13392 /* put pointer in DPTR */
13393 aopOp (pp,ic,FALSE,FALSE);
13394 if (AOP_TYPE(pp) == AOP_IMMD) {
13395 emitcode ("mov", "dptr,%s",
13396 aopGet (pp, 0, TRUE, FALSE, NULL));
13397 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
13398 emitcode ("mov","dpl,%s",aopGet(pp,0,FALSE,FALSE,NULL));
13399 emitcode ("mov","dph,%s",aopGet(pp,1,FALSE,FALSE,NULL));
13400 emitcode ("mov","dpx,%s",aopGet(pp,2,FALSE,FALSE,NULL));
13402 freeAsmop (handle, NULL, ic, FALSE);
13404 /* make the call */
13405 emitcode ("lcall","System_ExecJavaProcess");
13407 /* put result in place */
13409 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13410 if (rsym->liveFrom != rsym->liveTo) {
13411 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13412 aopPut(IC_RESULT(ic),"a",0);
13413 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13417 unsavermask(rsave);
13420 /*-----------------------------------------------------------------*/
13421 /* genSystemRTCRegisters - */
13422 /*-----------------------------------------------------------------*/
13423 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
13429 assert (nparms==1);
13430 /* save registers that need to be saved */
13431 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13432 ds390_rUmaskForOp (IC_RESULT(ic))));
13435 /* put pointer in DPTR */
13436 aopOp (pp,ic,FALSE,FALSE);
13437 if (AOP_TYPE (pp) == AOP_IMMD) {
13438 emitcode ("mov","dps,#1");
13439 emitcode ("mov", "dptr,%s",
13440 aopGet (pp, 0, TRUE, FALSE, NULL));
13441 emitcode ("mov","dps,#0");
13443 emitcode ("mov","dpl1,%s",
13444 aopGet(pp,0,FALSE,FALSE,DP2_RESULT_REG));
13445 emitcode ("mov","dph1,%s",
13446 aopGet(pp,1,FALSE,FALSE,DP2_RESULT_REG));
13447 emitcode ("mov","dpx1,%s",
13448 aopGet(pp,2,FALSE,FALSE,DP2_RESULT_REG));
13450 freeAsmop (pp, NULL, ic, FALSE);
13452 /* make the call */
13453 emitcode ("lcall","System_%sRTCRegisters",name);
13455 unsavermask(rsave);
13458 /*-----------------------------------------------------------------*/
13459 /* genSystemThreadSleep - */
13460 /*-----------------------------------------------------------------*/
13461 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
13466 assert (nparms==1);
13467 /* save registers that need to be saved */
13468 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13469 ds390_rUmaskForOp (IC_RESULT(ic))));
13472 aopOp(to,ic,FALSE,FALSE);
13473 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
13474 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
13475 emitcode ("push","%s",
13476 aopGet(to,0,FALSE,TRUE,DP2_RESULT_REG));
13477 emitcode ("push","%s",
13478 aopGet(to,1,FALSE,TRUE,DP2_RESULT_REG));
13479 emitcode ("push","%s",
13480 aopGet(to,2,FALSE,TRUE,DP2_RESULT_REG));
13481 emitcode ("push","%s",
13482 aopGet(to,3,FALSE,TRUE,DP2_RESULT_REG));
13483 emitcode ("pop","ar3");
13484 emitcode ("pop","ar2");
13485 emitcode ("pop","ar1");
13486 emitcode ("pop","ar0");
13488 emitcode ("mov","r0,%s",
13489 aopGet(to,0,FALSE,TRUE,DP2_RESULT_REG));
13490 emitcode ("mov","r1,%s",
13491 aopGet(to,1,FALSE,TRUE,DP2_RESULT_REG));
13492 emitcode ("mov","r2,%s",
13493 aopGet(to,2,FALSE,TRUE,DP2_RESULT_REG));
13494 emitcode ("mov","r3,%s",
13495 aopGet(to,3,FALSE,TRUE,DP2_RESULT_REG));
13497 freeAsmop (to, NULL, ic, FALSE);
13499 /* suspend in acc */
13501 aopOp(s,ic,FALSE,FALSE);
13502 emitcode ("mov","a,%s",
13503 aopGet(s,0,FALSE,TRUE,NULL));
13504 freeAsmop (s, NULL, ic, FALSE);
13506 /* make the call */
13507 emitcode ("lcall","System_%s",name);
13509 unsavermask(rsave);
13512 /*-----------------------------------------------------------------*/
13513 /* genSystemThreadResume - */
13514 /*-----------------------------------------------------------------*/
13515 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
13520 assert (nparms==2);
13521 /* save registers that need to be saved */
13522 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13523 ds390_rUmaskForOp (IC_RESULT(ic))));
13529 aopOp(pid,ic,FALSE,FALSE);
13530 emitcode ("mov","r0,%s",
13531 aopGet(pid,0,FALSE,TRUE,DP2_RESULT_REG));
13532 freeAsmop (pid, NULL, ic, FALSE);
13535 aopOp(tid,ic,FALSE,FALSE);
13536 emitcode ("mov","a,%s",
13537 aopGet(tid,0,FALSE,TRUE,DP2_RESULT_REG));
13538 freeAsmop (tid, NULL, ic, FALSE);
13540 emitcode ("lcall","System_ThreadResume");
13542 /* put result into place */
13544 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13545 if (rsym->liveFrom != rsym->liveTo) {
13546 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13547 aopPut(IC_RESULT(ic),"a",0);
13548 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13551 unsavermask(rsave);
13554 /*-----------------------------------------------------------------*/
13555 /* genSystemProcessResume - */
13556 /*-----------------------------------------------------------------*/
13557 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
13562 assert (nparms==1);
13563 /* save registers that need to be saved */
13564 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13565 ds390_rUmaskForOp (IC_RESULT(ic))));
13570 aopOp(pid,ic,FALSE,FALSE);
13571 emitcode ("mov","a,%s",
13572 aopGet(pid,0,FALSE,TRUE,DP2_RESULT_REG));
13573 freeAsmop (pid, NULL, ic, FALSE);
13575 emitcode ("lcall","System_ProcessResume");
13577 unsavermask(rsave);
13580 /*-----------------------------------------------------------------*/
13582 /*-----------------------------------------------------------------*/
13583 static void genSystem (iCode *ic,int nparms,char *name)
13585 assert(nparms == 0);
13587 emitcode ("lcall","System_%s",name);
13590 /*-----------------------------------------------------------------*/
13591 /* genSystemPoll - */
13592 /*-----------------------------------------------------------------*/
13593 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
13598 assert (nparms==1);
13599 /* save registers that need to be saved */
13600 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13601 ds390_rUmaskForOp (IC_RESULT(ic))));
13604 aopOp (fp,ic,FALSE,FALSE);
13605 if (AOP_TYPE (fp) == AOP_IMMD) {
13606 emitcode ("mov", "dptr,%s",
13607 aopGet (fp, 0, TRUE, FALSE, DP2_RESULT_REG));
13608 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
13609 emitcode ("mov","dpl,%s",
13610 aopGet(fp,0,FALSE,FALSE,DP2_RESULT_REG));
13611 emitcode ("mov","dph,%s",
13612 aopGet(fp,1,FALSE,FALSE,DP2_RESULT_REG));
13613 emitcode ("mov","dpx,%s",
13614 aopGet(fp,2,FALSE,FALSE,DP2_RESULT_REG));
13616 freeAsmop (fp, NULL, ic, FALSE);
13618 emitcode ("lcall","System_%sPoll",name);
13620 /* put result into place */
13622 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13623 if (rsym->liveFrom != rsym->liveTo) {
13624 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13625 aopPut(IC_RESULT(ic),"a",0);
13626 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13629 unsavermask(rsave);
13632 /*-----------------------------------------------------------------*/
13633 /* genSystemGetCurrentID - */
13634 /*-----------------------------------------------------------------*/
13635 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
13637 assert (nparms==0);
13639 emitcode ("lcall","System_GetCurrent%sId",name);
13640 /* put result into place */
13642 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13643 if (rsym->liveFrom != rsym->liveTo) {
13644 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13645 aopPut(IC_RESULT(ic),"a",0);
13646 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13651 /*-----------------------------------------------------------------*/
13652 /* genDjnz - generate decrement & jump if not zero instrucion */
13653 /*-----------------------------------------------------------------*/
13655 genDjnz (iCode * ic, iCode * ifx)
13657 symbol *lbl, *lbl1;
13661 /* if the if condition has a false label
13662 then we cannot save */
13663 if (IC_FALSE (ifx))
13666 /* if the minus is not of the form a = a - 1 */
13667 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
13668 !IS_OP_LITERAL (IC_RIGHT (ic)))
13671 if (operandLitValue (IC_RIGHT (ic)) != 1)
13674 /* if the size of this greater than one then no
13676 if (getSize (operandType (IC_RESULT (ic))) > 1)
13679 /* otherwise we can save BIG */
13681 D (emitcode (";", "genDjnz"));
13683 lbl = newiTempLabel (NULL);
13684 lbl1 = newiTempLabel (NULL);
13686 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
13688 if (AOP_NEEDSACC(IC_RESULT(ic)))
13690 /* If the result is accessed indirectly via
13691 * the accumulator, we must explicitly write
13692 * it back after the decrement.
13694 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE, NULL);
13696 if (strcmp(rByte, "a"))
13698 /* Something is hopelessly wrong */
13699 fprintf(stderr, "*** warning: internal error at %s:%d\n",
13700 __FILE__, __LINE__);
13701 /* We can just give up; the generated code will be inefficient,
13702 * but what the hey.
13704 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13707 emitcode ("dec", "%s", rByte);
13708 aopPut (IC_RESULT (ic), rByte, 0);
13709 emitcode ("jnz", "!tlabel", lbl->key + 100);
13711 else if (IS_AOP_PREG (IC_RESULT (ic)))
13713 emitcode ("dec", "%s",
13714 aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL));
13715 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL));
13716 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13717 ifx->generated = 1;
13718 emitcode ("jnz", "!tlabel", lbl->key + 100);
13722 emitcode ("djnz", "%s,!tlabel", aopGet (IC_RESULT (ic), 0, FALSE, TRUE, NULL),
13725 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
13727 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
13730 if (!ifx->generated)
13731 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13732 ifx->generated = 1;
13736 /*-----------------------------------------------------------------*/
13737 /* genReceive - generate code for a receive iCode */
13738 /*-----------------------------------------------------------------*/
13740 genReceive (iCode * ic)
13742 int size = getSize (operandType (IC_RESULT (ic)));
13746 D (emitcode (";", "genReceive"));
13748 if (ic->argreg == 1)
13750 /* first parameter */
13751 if (AOP_IS_STR(IC_RESULT(ic)))
13753 /* Nothing to do: it's already in the proper place. */
13760 useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
13761 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
13762 IS_TRUE_SYMOP (IC_RESULT (ic)));
13765 aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
13768 /* Sanity checking... */
13769 if (AOP_USESDPTR(IC_RESULT(ic)))
13771 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
13772 "genReceive got unexpected DPTR.");
13774 assignResultValue (IC_RESULT (ic), NULL);
13777 else if (ic->argreg > 12)
13778 { /* bit parameters */
13779 if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
13781 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
13782 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
13783 outBitC(IC_RESULT (ic));
13788 /* second receive onwards */
13789 /* this gets a little tricky since unused receives will be
13790 eliminated, we have saved the reg in the type field . and
13791 we use that to figure out which register to use */
13792 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
13793 rb1off = ic->argreg;
13796 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
13799 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13802 /*-----------------------------------------------------------------*/
13803 /* genDummyRead - generate code for dummy read of volatiles */
13804 /*-----------------------------------------------------------------*/
13806 genDummyRead (iCode * ic)
13811 D (emitcode(";", "genDummyRead"));
13813 op = IC_RIGHT (ic);
13814 if (op && IS_SYMOP (op))
13816 aopOp (op, ic, FALSE, FALSE);
13818 /* if the result is a bit */
13819 if (AOP_TYPE (op) == AOP_CRY)
13820 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13823 /* bit variables done */
13825 size = AOP_SIZE (op);
13829 MOVA (aopGet (op, offset, FALSE, FALSE, FALSE));
13834 freeAsmop (op, NULL, ic, TRUE);
13838 if (op && IS_SYMOP (op))
13840 aopOp (op, ic, FALSE, FALSE);
13842 /* if the result is a bit */
13843 if (AOP_TYPE (op) == AOP_CRY)
13844 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13847 /* bit variables done */
13849 size = AOP_SIZE (op);
13853 MOVA (aopGet (op, offset, FALSE, FALSE, FALSE));
13858 freeAsmop (op, NULL, ic, TRUE);
13862 /*-----------------------------------------------------------------*/
13863 /* genCritical - generate code for start of a critical sequence */
13864 /*-----------------------------------------------------------------*/
13866 genCritical (iCode *ic)
13868 symbol *tlbl = newiTempLabel (NULL);
13870 D (emitcode(";", "genCritical"));
13872 if (IC_RESULT (ic))
13874 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
13875 aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
13876 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
13877 aopPut (IC_RESULT (ic), zero, 0);
13879 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13883 emitcode ("setb", "c");
13884 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
13885 emitcode ("clr", "c");
13887 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
13891 /*-----------------------------------------------------------------*/
13892 /* genEndCritical - generate code for end of a critical sequence */
13893 /*-----------------------------------------------------------------*/
13895 genEndCritical (iCode *ic)
13897 D(emitcode("; genEndCritical",""));
13901 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
13902 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
13904 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
13905 emitcode ("mov", "ea,c");
13909 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE, FALSE));
13910 emitcode ("rrc", "a");
13911 emitcode ("mov", "ea,c");
13913 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
13917 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
13918 emitcode ("mov", "ea,c");
13924 /*-----------------------------------------------------------------*/
13925 /* genBuiltIn - calls the appropriate function to generating code */
13926 /* for a built in function */
13927 /*-----------------------------------------------------------------*/
13928 static void genBuiltIn (iCode *ic)
13930 operand *bi_parms[MAX_BUILTIN_ARGS];
13935 /* get all the arguments for a built in function */
13936 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
13938 /* which function is it */
13939 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
13940 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
13941 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
13942 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
13943 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
13944 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
13945 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
13946 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
13947 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
13948 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
13949 genMemsetX(bi_iCode,nbi_parms,bi_parms);
13950 } else if (strcmp(bif->name,"__builtin_inp")==0) {
13951 genInp(bi_iCode,nbi_parms,bi_parms);
13952 } else if (strcmp(bif->name,"__builtin_outp")==0) {
13953 genOutp(bi_iCode,nbi_parms,bi_parms);
13954 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
13955 genSwapW(bi_iCode,nbi_parms,bi_parms);
13956 /* JavaNative builtIns */
13957 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
13958 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
13959 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
13960 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
13961 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
13962 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
13963 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
13964 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
13965 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
13966 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
13967 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
13968 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
13969 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
13970 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
13971 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
13972 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
13973 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
13974 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
13975 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
13976 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
13977 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
13978 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
13979 } else if (strcmp(bif->name,"MM_Malloc")==0) {
13980 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
13981 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
13982 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
13983 } else if (strcmp(bif->name,"MM_Free")==0) {
13984 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
13985 } else if (strcmp(bif->name,"MM_Deref")==0) {
13986 genMMDeref(bi_iCode,nbi_parms,bi_parms);
13987 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
13988 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
13989 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
13990 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
13991 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
13992 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
13993 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
13994 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
13995 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
13996 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
13997 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
13998 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
13999 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
14000 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
14001 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
14002 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
14003 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
14004 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
14005 } else if (strcmp(bif->name,"System_SaveThread")==0) {
14006 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
14007 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
14008 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
14009 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
14010 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
14011 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
14012 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
14013 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
14014 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
14015 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
14016 genSystem(bi_iCode,nbi_parms,"ProcessYield");
14017 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
14018 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
14019 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
14020 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
14021 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
14022 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
14023 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
14024 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
14025 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
14026 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
14028 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
14034 /*-----------------------------------------------------------------*/
14035 /* gen390Code - generate code for Dallas 390 based controllers */
14036 /*-----------------------------------------------------------------*/
14038 gen390Code (iCode * lic)
14043 _G.currentFunc = NULL;
14044 lineHead = lineCurr = NULL;
14045 dptrn[1][0] = "dpl1";
14046 dptrn[1][1] = "dph1";
14047 dptrn[1][2] = "dpx1";
14049 if (options.model == MODEL_FLAT24) {
14050 fReturnSizeDS390 = 5;
14051 fReturn = fReturn24;
14053 fReturnSizeDS390 = 4;
14054 fReturn = fReturn16;
14055 options.stack10bit=0;
14058 /* print the allocation information */
14059 if (allocInfo && currFunc)
14060 printAllocInfo (currFunc, codeOutFile);
14062 /* if debug information required */
14063 if (options.debug && currFunc)
14065 debugFile->writeFunction (currFunc, lic);
14067 /* stack pointer name */
14068 if (options.useXstack)
14074 for (ic = lic; ic; ic = ic->next)
14076 _G.current_iCode = ic;
14078 if (ic->lineno && cln != ic->lineno)
14082 debugFile->writeCLine (ic);
14084 if (!options.noCcodeInAsm) {
14085 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
14086 printCLine(ic->filename, ic->lineno));
14090 if (options.iCodeInAsm) {
14091 emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
14093 /* if the result is marked as
14094 spilt and rematerializable or code for
14095 this has already been generated then
14097 if (resultRemat (ic) || ic->generated)
14100 /* depending on the operation */
14120 /* IPOP happens only when trying to restore a
14121 spilt live range, if there is an ifx statement
14122 following this pop then the if statement might
14123 be using some of the registers being popped which
14124 would destory the contents of the register so
14125 we need to check for this condition and handle it */
14127 ic->next->op == IFX &&
14128 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
14129 genIfx (ic->next, ic);
14147 genEndFunction (ic);
14167 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
14184 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
14188 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
14195 /* note these two are xlated by algebraic equivalence
14196 during parsing SDCC.y */
14197 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
14198 "got '>=' or '<=' shouldn't have come here");
14202 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
14214 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
14218 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
14222 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
14246 genRightShift (ic);
14249 case GET_VALUE_AT_ADDRESS:
14251 hasInc (IC_LEFT (ic), ic,
14252 getSize (operandType (IC_RESULT (ic)))));
14256 if (POINTER_SET (ic))
14258 hasInc (IC_RESULT (ic), ic,
14259 getSize (operandType (IC_RIGHT (ic)))));
14285 if (ic->builtinSEND)
14288 addSet (&_G.sendSet, ic);
14291 case DUMMY_READ_VOLATILE:
14300 genEndCritical (ic);
14307 #if 0 // obsolete, and buggy for != xdata
14319 /* now we are ready to call the
14320 peep hole optimizer */
14321 if (!options.nopeep)
14322 peepHole (&lineHead);
14324 /* now do the actual printing */
14325 printLine (lineHead, codeOutFile);