1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for DS80C390
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7 DS390 adaptation by Kevin Vigor <kevin@vigor.nu>
9 This program is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 2, or (at your option) any
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 In other words, you are welcome to use, share and improve this program.
24 You are forbidden to forbid anyone else to use, share and improve
25 what you give them. Help stamp out software-hoarding!
26 -------------------------------------------------------------------------*/
35 #include "SDCCglobl.h"
43 #define BETTER_LITERAL_SHIFT
45 char *aopLiteral (value * val, int offset);
48 /* this is the down and dirty file with all kinds of
49 kludgy & hacky stuff. This is what it is all about
50 CODE GENERATION for a specific MCU . some of the
51 routines may be reusable, will have to see */
53 static char *zero = "#0";
54 static char *one = "#1";
57 #define TR_DPTR(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_DPTR1 %s ", s); }
58 #define TR_AP(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_AP %s ", s); }
60 unsigned fReturnSizeDS390 = 5;
61 static char *fReturn24[] =
62 {"dpl", "dph", "dpx", "b", "a"};
63 static char *fReturn16[] =
64 {"dpl", "dph", "b", "a"};
65 static char **fReturn = fReturn24;
66 static char *accUse[] =
68 static char *dptrn[2][3];
69 static char *javaRet[] = { "r0","r1","r2","r3"};
70 static short rbank = -1;
72 #define REG_WITH_INDEX ds390_regWithIdx
74 #define AOP(op) op->aop
75 #define AOP_TYPE(op) AOP(op)->type
76 #define AOP_SIZE(op) AOP(op)->size
77 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
78 AOP_TYPE(x) == AOP_R0))
80 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
81 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
84 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
85 (x->aopu.aop_reg[0] == REG_WITH_INDEX(R0_IDX) || \
86 x->aopu.aop_reg[0] == REG_WITH_INDEX(R1_IDX) )))
87 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
88 #define AOP_USESDPTR(x) ((AOP_TYPE(x) == AOP_DPTR) || (AOP_TYPE(x) == AOP_STR))
89 #define AOP_USESDPTR2(x) ((AOP_TYPE(x) == AOP_DPTR2) || (AOP_TYPE(x) == AOP_DPTRn))
91 // The following two macros can be used even if the aop has not yet been aopOp'd.
92 #define AOP_IS_STR(x) (IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
93 #define AOP_IS_DPTRn(x) (IS_SYMOP(x) && OP_SYMBOL(x)->dptr)
95 /* Workaround for DS80C390 bug: div ab may return bogus results
96 * if A is accessed in instruction immediately before the div.
98 * Will be fixed in B4 rev of processor, Dallas claims.
101 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
102 if (!AOP_NEEDSACC(RIGHT)) \
104 /* We can load A first, then B, since \
105 * B (the RIGHT operand) won't clobber A, \
106 * thus avoiding touching A right before the div. \
108 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
109 L = aopGet(LEFT,0,FALSE,FALSE,NULL); \
111 L = aopGet(RIGHT,0,FALSE,FALSE,"b"); \
116 /* Just stuff in a nop after loading A. */ \
117 emitcode("mov","b,%s",aopGet(RIGHT,0,FALSE,FALSE,NULL));\
118 L = aopGet(LEFT,0,FALSE,FALSE,NULL); \
120 emitcode("nop", "; workaround for DS80C390 div bug."); \
123 #define R0INB _G.bu.bs.r0InB
124 #define R1INB _G.bu.bs.r1InB
125 #define OPINB _G.bu.bs.OpInB
126 #define BINUSE _G.bu.BInUse
136 short r0InB : 2;//2 so we can see it overflow
137 short r1InB : 2;//2 so we can see it overflow
138 short OpInB : 2;//2 so we can see it overflow
149 iCode *current_iCode;
154 static char *rb1regs[] = {
155 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7",
156 "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7"
159 static void saveRBank (int, iCode *, bool);
161 #define RESULTONSTACK(x) \
162 (IC_RESULT(x) && IC_RESULT(x)->aop && \
163 IC_RESULT(x)->aop->type == AOP_STK )
165 #define MOVA(x) mova(x) /* use function to avoid multiple eval */
166 #define MOVB(x) movb(x)
168 #define CLRC emitcode("clr","c")
169 #define SETC emitcode("setb","c")
171 // A scratch register which will be used to hold
172 // result bytes from operands in far space via DPTR2.
173 #define DP2_RESULT_REG "_ap"
175 static lineNode *lineHead = NULL;
176 static lineNode *lineCurr = NULL;
178 static unsigned char SLMask[] =
179 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
180 0xE0, 0xC0, 0x80, 0x00};
181 static unsigned char SRMask[] =
182 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
183 0x07, 0x03, 0x01, 0x00};
189 #define PROTECT_SP {if (options.protect_sp_update) { \
190 symbol *lbl = newiTempLabel(NULL); \
191 emitcode ("setb","F1"); \
192 emitcode ("jbc","EA,!tlabel",lbl->key+100); \
193 emitcode ("clr","F1"); \
194 emitcode ("","!tlabeldef",lbl->key+100); \
196 #define UNPROTECT_SP { if (options.protect_sp_update) { \
197 emitcode ("mov","EA,F1"); \
200 static int _currentDPS; /* Current processor DPS. */
201 static int _desiredDPS; /* DPS value compiler thinks we should be using. */
202 static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */
204 /*-----------------------------------------------------------------*/
205 /* emitcode - writes the code into a file : for now it is simple */
206 /*-----------------------------------------------------------------*/
208 emitcode (char *inst, const char *fmt,...)
211 char lb[INITIAL_INLINEASM];
220 SNPRINTF (lb, sizeof(lb), "%s\t", inst);
224 SNPRINTF (lb, sizeof(lb), "%s", inst);
227 tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb), fmt, ap);
231 tvsprintf (lb, sizeof(lb), fmt, ap);
234 while (isspace ((unsigned char)*lbp))
241 lineCurr = (lineCurr ?
242 connectLine (lineCurr, newLineNode (lb)) :
243 (lineHead = newLineNode (lb)));
246 lineCurr->isInline = _G.inLine;
247 lineCurr->isDebug = _G.debugLine;
248 lineCurr->ic = _G.current_iCode;
249 lineCurr->aln = ds390newAsmLineNode(_currentDPS);
254 emitLabel (symbol *tlbl)
256 emitcode ("", "!tlabeldef", tlbl->key + 100);
259 /*-----------------------------------------------------------------*/
260 /* ds390_emitDebuggerSymbol - associate the current code location */
261 /* with a debugger symbol */
262 /*-----------------------------------------------------------------*/
264 ds390_emitDebuggerSymbol (char * debugSym)
267 emitcode ("", "%s ==.", debugSym);
271 /*-----------------------------------------------------------------*/
272 /* mova - moves specified value into accumulator */
273 /*-----------------------------------------------------------------*/
277 /* do some early peephole optimization */
278 if (!strncmp(x, "a", 2) || !strncmp(x, "acc", 4))
281 emitcode("mov", "a,%s", x);
284 /*-----------------------------------------------------------------*/
285 /* movb - moves specified value into register b */
286 /*-----------------------------------------------------------------*/
290 /* do some early peephole optimization */
291 if (!strncmp(x, "b", 2))
294 emitcode("mov","b,%s", x);
297 /*-----------------------------------------------------------------*/
298 /* movc - moves specified value into the carry */
299 /*-----------------------------------------------------------------*/
307 else if (strcmp (s, "c"))
308 {/* it's not in carry already */
310 /* set C, if a >= 1 */
311 emitcode ("add", "a,#0xff");
315 /*-----------------------------------------------------------------*/
316 /* pushB - saves register B if necessary */
317 /*-----------------------------------------------------------------*/
321 bool pushedB = FALSE;
325 emitcode ("push", "b");
326 // printf("B was in use !\n");
336 /*-----------------------------------------------------------------*/
337 /* popB - restores value of register B if necessary */
338 /*-----------------------------------------------------------------*/
344 emitcode ("pop", "b");
352 /*-----------------------------------------------------------------*/
353 /* pushReg - saves register */
354 /*-----------------------------------------------------------------*/
356 pushReg (int index, bool bits_pushed)
358 regs * reg = REG_WITH_INDEX (index);
359 if (reg->type == REG_BIT)
362 emitcode ("push", "%s", reg->base);
366 emitcode ("push", "%s", reg->dname);
370 /*-----------------------------------------------------------------*/
371 /* popReg - restores register */
372 /*-----------------------------------------------------------------*/
374 popReg (int index, bool bits_popped)
376 regs * reg = REG_WITH_INDEX (index);
377 if (reg->type == REG_BIT)
380 emitcode ("pop", "%s", reg->base);
384 emitcode ("pop", "%s", reg->dname);
388 /*-----------------------------------------------------------------*/
389 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
390 /*-----------------------------------------------------------------*/
392 getFreePtr (iCode * ic, asmop ** aopp, bool result)
397 /* the logic: if r0 & r1 used in the instruction
398 then we are in trouble otherwise */
400 /* first check if r0 & r1 are used by this
401 instruction, in which case we are in trouble */
402 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
403 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
408 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
409 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
411 /* if no usage of r0 then return it */
414 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
415 (*aopp)->type = AOP_R0;
417 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
420 /* if no usage of r1 then return it */
423 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
424 (*aopp)->type = AOP_R1;
426 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R1_IDX);
429 /* now we know they both have usage */
430 /* if r0 not used in this instruction */
433 /* push it if not already pushed */
436 emitcode ("push", "%s",
437 REG_WITH_INDEX (R0_IDX)->dname);
441 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
442 (*aopp)->type = AOP_R0;
444 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
447 /* if r1 not used then */
451 /* push it if not already pushed */
454 emitcode ("push", "%s",
455 REG_WITH_INDEX (R1_IDX)->dname);
459 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
460 (*aopp)->type = AOP_R1;
461 return REG_WITH_INDEX (R1_IDX);
465 /* I said end of world, but not quite end of world yet */
466 /* if this is a result then we can push it on the stack */
469 (*aopp)->type = AOP_STK;
473 /* now this is REALLY the end of the world */
474 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
475 "getFreePtr should never reach here");
478 return NULL; // notreached, but makes compiler happy.
482 /*-----------------------------------------------------------------*/
483 /* genSetDPTR: generate code to select which DPTR is in use (zero */
484 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */
485 /* alternate DPTR (DPL1/DPH1/DPX1). */
486 /*-----------------------------------------------------------------*/
491 /* If we are doing lazy evaluation, simply note the desired
492 * change, but don't emit any code yet.
502 emitcode ("mov", "dps,#0");
507 emitcode ("mov", "dps,#1");
511 /*------------------------------------------------------------------*/
512 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
514 /* Any code that operates on DPTR (NB: not on the individual */
515 /* components, like DPH) *must* call _flushLazyDPS() before using */
516 /* DPTR within a lazy DPS evaluation block. */
518 /* Note that aopPut and aopGet already contain the proper calls to */
519 /* _flushLazyDPS, so it is safe to use these calls within a lazy */
520 /* DPS evaluation block. */
522 /* Also, _flushLazyDPS must be called before any flow control */
523 /* operations that could potentially branch out of the block. */
525 /* Lazy DPS evaluation is simply an optimization (though an */
526 /* important one), so if in doubt, leave it out. */
527 /*------------------------------------------------------------------*/
529 _startLazyDPSEvaluation (void)
533 #ifdef BETTER_LITERAL_SHIFT
540 /*------------------------------------------------------------------*/
541 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
542 /* desired one. Call before using DPTR within a lazy DPS evaluation */
544 /*------------------------------------------------------------------*/
554 if (_desiredDPS != _currentDPS)
558 emitcode ("inc", "dps");
562 emitcode ("dec", "dps");
564 _currentDPS = _desiredDPS;
568 /*-----------------------------------------------------------------*/
569 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
571 /* Forces us back to the safe state (standard DPTR selected). */
572 /*-----------------------------------------------------------------*/
574 _endLazyDPSEvaluation (void)
576 #ifdef BETTER_LITERAL_SHIFT
594 /*-----------------------------------------------------------------*/
595 /* newAsmop - creates a new asmOp */
596 /*-----------------------------------------------------------------*/
598 newAsmop (short type)
602 aop = Safe_calloc (1, sizeof (asmop));
608 /*-----------------------------------------------------------------*/
609 /* pointerCode - returns the code for a pointer type */
610 /*-----------------------------------------------------------------*/
612 pointerCode (sym_link * etype)
615 return PTR_TYPE (SPEC_OCLS (etype));
619 /*-----------------------------------------------------------------*/
620 /* leftRightUseAcc - returns size of accumulator use by operands */
621 /*-----------------------------------------------------------------*/
623 leftRightUseAcc(iCode *ic)
632 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
633 "null iCode pointer");
640 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
643 size = getSize (OP_SYMBOL (op)->type);
648 else if (ic->op == JUMPTABLE)
651 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
654 size = getSize (OP_SYMBOL (op)->type);
662 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
665 size = getSize (OP_SYMBOL (op)->type);
670 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
673 size = getSize (OP_SYMBOL (op)->type);
685 /*-----------------------------------------------------------------*/
686 /* aopForSym - for a true symbol */
687 /*-----------------------------------------------------------------*/
689 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
693 bool accuse = leftRightUseAcc (ic) || _G.accInUse;
694 char *dpl = useDP2 ? "dpl1" : "dpl";
695 char *dph = useDP2 ? "dph1" : "dph";
696 char *dpx = useDP2 ? "dpx1" : "dpx";
698 wassertl (ic != NULL, "Got a null iCode");
699 wassertl (sym != NULL, "Got a null symbol");
701 space = SPEC_OCLS (sym->etype);
703 /* if already has one */
706 if ((sym->aop->type == AOP_DPTR && useDP2)
707 || (sym->aop->type == AOP_DPTR2 && !useDP2))
711 sym->aop->allocated++;
716 /* assign depending on the storage class */
717 /* if it is on the stack or indirectly addressable */
718 /* space we need to assign either r0 or r1 to it */
719 if ((sym->onStack && !options.stack10bit) || sym->iaccess)
721 sym->aop = aop = newAsmop (0);
722 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
723 aop->size = getSize (sym->type);
725 /* now assign the address of the variable to
726 the pointer register */
727 if (aop->type != AOP_STK)
731 signed char offset = ((sym->stack < 0) ?
732 ((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 /*-----------------------------------------------------------------*/
1667 aopPutUsesAcc (operand * oper, const char *s, int offset)
1669 asmop * aop = AOP (oper);
1671 if (offset > (aop->size - 1))
1681 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1687 return ((aop->paged) || (*s == '@'));
1691 return (!aop->aopu.aop_dir || strcmp(s, aop->aopu.aop_dir));
1699 /* Error case --- will have been caught already */
1706 /*-----------------------------------------------------------------*/
1707 /* aopPut - puts a string for a aop and indicates if acc is in use */
1708 /*-----------------------------------------------------------------*/
1710 aopPut (operand * result, const char *s, int offset)
1712 bool bvolatile = isOperandVolatile (result, FALSE);
1713 bool accuse = FALSE;
1714 asmop * aop = AOP (result);
1716 if (aop->size && offset > (aop->size - 1))
1718 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1719 "aopPut got offset > aop->size");
1723 /* will assign value to value */
1724 /* depending on where it is ofcourse */
1728 MOVA (s); /* read s in case it was volatile */
1733 if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1735 SNPRINTF (buffer, sizeof(buffer),
1737 aop->aopu.aop_dir, offset * 8);
1741 SNPRINTF (buffer, sizeof(buffer),
1743 aop->aopu.aop_dir, offset);
1747 SNPRINTF (buffer, sizeof(buffer),
1752 if (strcmp (buffer, s) || bvolatile)
1754 emitcode ("mov", "%s,%s", buffer, s);
1756 if (!strcmp (buffer, "acc"))
1763 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1764 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1767 strcmp (s, "r0") == 0 ||
1768 strcmp (s, "r1") == 0 ||
1769 strcmp (s, "r2") == 0 ||
1770 strcmp (s, "r3") == 0 ||
1771 strcmp (s, "r4") == 0 ||
1772 strcmp (s, "r5") == 0 ||
1773 strcmp (s, "r6") == 0 ||
1774 strcmp (s, "r7") == 0)
1776 emitcode ("mov", "%s,%s",
1777 aop->aopu.aop_reg[offset]->dname, s);
1781 emitcode ("mov", "%s,%s",
1782 aop->aopu.aop_reg[offset]->name, s);
1788 emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1794 if (aop->type == AOP_DPTR2)
1802 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1803 "aopPut writing to code space");
1807 while (offset > aop->coff)
1810 emitcode ("inc", "dptr");
1813 while (offset < aop->coff)
1816 emitcode ("lcall", "__decdptr");
1821 /* if not in accumulator */
1824 emitcode ("movx", "@dptr,a");
1826 if (aop->type == AOP_DPTR2)
1834 while (offset > aop->coff)
1837 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1839 while (offset < aop->coff)
1842 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1849 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1854 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1856 else if (strcmp (s, "r0") == 0 ||
1857 strcmp (s, "r1") == 0 ||
1858 strcmp (s, "r2") == 0 ||
1859 strcmp (s, "r3") == 0 ||
1860 strcmp (s, "r4") == 0 ||
1861 strcmp (s, "r5") == 0 ||
1862 strcmp (s, "r6") == 0 ||
1863 strcmp (s, "r7") == 0)
1866 SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1867 emitcode ("mov", "@%s,%s",
1868 aop->aopu.aop_ptr->name, buffer);
1872 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1877 if (strcmp (s, "a") == 0)
1878 emitcode ("push", "acc");
1882 emitcode ("push", "acc");
1884 emitcode ("push", s);
1890 /* if not bit variable */
1891 if (!aop->aopu.aop_dir)
1893 /* inefficient: move carry into A and use jz/jnz */
1894 emitcode ("clr", "a");
1895 emitcode ("rlc", "a");
1901 emitcode ("clr", "%s", aop->aopu.aop_dir);
1903 emitcode ("setb", "%s", aop->aopu.aop_dir);
1904 else if (!strcmp (s, "c"))
1905 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1906 else if (strcmp (s, aop->aopu.aop_dir))
1909 /* set C, if a >= 1 */
1910 emitcode ("add", "a,#!constbyte",0xff);
1911 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1918 if (strcmp (aop->aopu.aop_str[offset], s) || bvolatile)
1919 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1925 if (!offset && (strcmp (s, "acc") == 0) && !bvolatile)
1928 if (strcmp (aop->aopu.aop_str[offset], s) && !bvolatile)
1929 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1933 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1934 "aopPut got unsupported aop->type");
1942 /*--------------------------------------------------------------------*/
1943 /* reAdjustPreg - points a register back to where it should (coff==0) */
1944 /*--------------------------------------------------------------------*/
1946 reAdjustPreg (asmop * aop)
1948 if ((aop->coff==0) || (aop->size <= 1))
1956 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1960 if (aop->type == AOP_DPTR2)
1967 emitcode ("lcall", "__decdptr");
1970 if (aop->type == AOP_DPTR2)
1979 /*-----------------------------------------------------------------*/
1980 /* opIsGptr: returns non-zero if the passed operand is */
1981 /* a generic pointer type. */
1982 /*-----------------------------------------------------------------*/
1984 opIsGptr (operand * op)
1986 sym_link *type = operandType (op);
1988 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1995 /*-----------------------------------------------------------------*/
1996 /* getDataSize - get the operand data size */
1997 /*-----------------------------------------------------------------*/
1999 getDataSize (operand * op)
2002 size = AOP_SIZE (op);
2003 if (size == GPTRSIZE)
2005 sym_link *type = operandType (op);
2006 if (IS_GENPTR (type))
2008 /* generic pointer; arithmetic operations
2009 * should ignore the high byte (pointer type).
2017 /*-----------------------------------------------------------------*/
2018 /* outAcc - output Acc */
2019 /*-----------------------------------------------------------------*/
2021 outAcc (operand * result)
2024 size = getDataSize (result);
2027 aopPut (result, "a", 0);
2030 /* unsigned or positive */
2033 aopPut (result, zero, offset++);
2038 /*-----------------------------------------------------------------*/
2039 /* outBitC - output a bit C */
2040 /*-----------------------------------------------------------------*/
2042 outBitC (operand * result)
2044 /* if the result is bit */
2045 if (AOP_TYPE (result) == AOP_CRY)
2047 aopPut (result, "c", 0);
2051 emitcode ("clr", "a");
2052 emitcode ("rlc", "a");
2057 /*-----------------------------------------------------------------*/
2058 /* toBoolean - emit code for orl a,operator(sizeop) */
2059 /*-----------------------------------------------------------------*/
2061 toBoolean (operand * oper)
2063 int size = AOP_SIZE (oper) - 1;
2067 /* The generic part of a generic pointer should
2068 * not participate in it's truth value.
2070 * i.e. 0x10000000 is zero.
2072 if (opIsGptr (oper))
2074 D (emitcode (";", "toBoolean: generic ptr special case."));
2078 _startLazyDPSEvaluation ();
2079 MOVA (aopGet (oper, 0, FALSE, FALSE, NULL));
2080 if (AOP_NEEDSACC (oper) && size && (AOP (oper)->type != AOP_ACC))
2083 emitcode("mov", "b,a");
2086 MOVA (aopGet (oper, offset++, FALSE, FALSE, NULL));
2087 emitcode ("orl", "b,a");
2089 MOVA (aopGet (oper, offset++, FALSE, FALSE, NULL));
2090 emitcode ("orl", "a,b");
2097 emitcode ("orl", "a,%s",
2098 aopGet (oper, offset++, FALSE, FALSE, NULL));
2101 _endLazyDPSEvaluation ();
2105 /*-----------------------------------------------------------------*/
2106 /* genNot - generate code for ! operation */
2107 /*-----------------------------------------------------------------*/
2113 D (emitcode (";", "genNot"));
2115 /* assign asmOps to operand & result */
2116 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2117 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
2119 /* if in bit space then a special case */
2120 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2122 /* if left==result then cpl bit */
2123 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2125 emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2129 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2130 emitcode ("cpl", "c");
2131 outBitC (IC_RESULT (ic));
2136 toBoolean (IC_LEFT (ic));
2138 /* set C, if a == 0 */
2139 tlbl = newiTempLabel (NULL);
2140 emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
2142 outBitC (IC_RESULT (ic));
2145 /* release the aops */
2146 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2147 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2151 /*-----------------------------------------------------------------*/
2152 /* genCpl - generate code for complement */
2153 /*-----------------------------------------------------------------*/
2160 sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
2162 D(emitcode (";", "genCpl"));
2164 /* assign asmOps to operand & result */
2165 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2166 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
2168 /* special case if in bit space */
2169 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2173 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
2174 (SPEC_USIGN (letype) && IS_CHAR (letype)))
2176 /* promotion rules are responsible for this strange result:
2177 bit -> int -> ~int -> bit
2178 uchar -> int -> ~int -> bit
2180 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
2184 tlbl=newiTempLabel(NULL);
2185 l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE, NULL);
2186 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
2187 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
2188 IS_AOP_PREG (IC_LEFT (ic)))
2190 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
2195 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
2198 outBitC (IC_RESULT(ic));
2202 size = AOP_SIZE (IC_RESULT (ic));
2203 _startLazyDPSEvaluation ();
2206 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL);
2208 emitcode ("cpl", "a");
2209 aopPut (IC_RESULT (ic), "a", offset++);
2211 _endLazyDPSEvaluation ();
2215 /* release the aops */
2216 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2217 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2220 /*-----------------------------------------------------------------*/
2221 /* genUminusFloat - unary minus for floating points */
2222 /*-----------------------------------------------------------------*/
2224 genUminusFloat (operand * op, operand * result)
2226 int size, offset = 0;
2229 D (emitcode (";", "genUminusFloat"));
2231 /* for this we just copy and then flip the bit */
2233 _startLazyDPSEvaluation ();
2234 size = AOP_SIZE (op) - 1;
2239 aopGet (op, offset, FALSE, FALSE, NULL),
2244 l = aopGet (op, offset, FALSE, FALSE, NULL);
2247 emitcode ("cpl", "acc.7");
2248 aopPut (result, "a", offset);
2249 _endLazyDPSEvaluation ();
2252 /*-----------------------------------------------------------------*/
2253 /* genUminus - unary minus code generation */
2254 /*-----------------------------------------------------------------*/
2256 genUminus (iCode * ic)
2261 D (emitcode (";", "genUminus"));
2264 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2265 aopOp (IC_RESULT (ic), ic, TRUE, (AOP_TYPE(IC_LEFT (ic)) == AOP_DPTR));
2267 /* if both in bit space then special
2269 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2270 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2273 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2274 emitcode ("cpl", "c");
2275 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2279 optype = operandType (IC_LEFT (ic));
2281 /* if float then do float stuff */
2282 if (IS_FLOAT (optype))
2284 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2288 /* otherwise subtract from zero */
2289 size = AOP_SIZE (IC_LEFT (ic));
2291 _startLazyDPSEvaluation ();
2294 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL);
2295 if (!strcmp (l, "a"))
2299 emitcode ("cpl", "a");
2300 emitcode ("addc", "a,#0");
2306 emitcode ("clr", "a");
2307 emitcode ("subb", "a,%s", l);
2309 aopPut (IC_RESULT (ic), "a", offset++);
2311 _endLazyDPSEvaluation ();
2313 /* if any remaining bytes in the result */
2314 /* we just need to propagate the sign */
2315 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2317 emitcode ("rlc", "a");
2318 emitcode ("subb", "a,acc");
2320 aopPut (IC_RESULT (ic), "a", offset++);
2324 /* release the aops */
2325 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2326 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2329 /*-----------------------------------------------------------------*/
2330 /* savermask - saves registers in the mask */
2331 /*-----------------------------------------------------------------*/
2332 static void savermask(bitVect *rs_mask)
2335 if (options.useXstack)
2337 if (bitVectBitValue (rs_mask, R0_IDX))
2338 emitcode ("mov", "b,r0");
2339 emitcode ("mov", "r0,%s", spname);
2340 for (i = 0; i < ds390_nRegs; i++)
2342 if (bitVectBitValue (rs_mask, i))
2345 emitcode ("mov", "a,b");
2347 emitcode ("mov", "a,%s", REG_WITH_INDEX (i)->name);
2348 emitcode ("movx", "@r0,a");
2349 emitcode ("inc", "r0");
2352 emitcode ("mov", "%s,r0", spname);
2353 if (bitVectBitValue (rs_mask, R0_IDX))
2354 emitcode ("mov", "r0,b");
2358 bool bits_pushed = FALSE;
2359 for (i = 0; i < ds390_nRegs; i++)
2361 if (bitVectBitValue (rs_mask, i))
2363 bits_pushed = pushReg (i, bits_pushed);
2369 /*-----------------------------------------------------------------*/
2370 /* saveRegisters - will look for a call and save the registers */
2371 /*-----------------------------------------------------------------*/
2373 saveRegisters (iCode * lic)
2379 for (ic = lic; ic; ic = ic->next)
2380 if (ic->op == CALL || ic->op == PCALL)
2385 fprintf (stderr, "found parameter push with no function call\n");
2389 /* if the registers have been saved already or don't need to be then
2392 || (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))) && !TARGET_IS_DS400) )
2395 /* special case if DPTR alive across a function call then must save it
2396 even though callee saves */
2397 if (IS_SYMOP(IC_LEFT(ic)) &&
2398 IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type))
2401 rsave = newBitVect(ic->rMask->size);
2402 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2403 if (bitVectBitValue(ic->rMask,i))
2404 rsave = bitVectSetBit(rsave,i);
2406 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2410 /* save the registers in use at this time but skip the
2411 ones for the result */
2412 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2413 ds390_rUmaskForOp (IC_RESULT(ic)));
2419 /*-----------------------------------------------------------------*/
2420 /* usavermask - restore registers with mask */
2421 /*-----------------------------------------------------------------*/
2422 static void unsavermask(bitVect *rs_mask)
2425 if (options.useXstack) {
2426 emitcode ("mov", "r0,%s", spname);
2427 for (i = ds390_nRegs; i >= 0; i--)
2429 if (bitVectBitValue (rs_mask, i))
2431 regs * reg = REG_WITH_INDEX (i);
2432 emitcode ("dec", "r0");
2433 emitcode ("movx", "a,@r0");
2436 emitcode ("push", "acc");
2440 emitcode ("mov", "%s,a", reg->name);
2444 emitcode ("mov", "%s,r0", spname);
2445 if (bitVectBitValue (rs_mask, R0_IDX))
2447 emitcode ("pop", "ar0");
2452 bool bits_popped = FALSE;
2453 for (i = ds390_nRegs; i >= 0; i--)
2455 if (bitVectBitValue (rs_mask, i))
2457 bits_popped = popReg (i, bits_popped);
2463 /*-----------------------------------------------------------------*/
2464 /* unsaveRegisters - pop the pushed registers */
2465 /*-----------------------------------------------------------------*/
2467 unsaveRegisters (iCode * ic)
2471 if (IS_SYMOP(IC_LEFT (ic)) &&
2472 IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2474 rsave = newBitVect(ic->rMask->size);
2475 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2476 if (bitVectBitValue(ic->rMask,i))
2477 rsave = bitVectSetBit(rsave,i);
2479 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2481 /* restore the registers in use at this time but skip the
2482 ones for the result */
2483 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2484 ds390_rUmaskForOp (IC_RESULT(ic)));
2490 /*-----------------------------------------------------------------*/
2492 /*-----------------------------------------------------------------*/
2494 pushSide (operand * oper, int size)
2497 _startLazyDPSEvaluation ();
2500 char *l = aopGet (oper, offset++, FALSE, TRUE, NULL);
2501 if (AOP_TYPE (oper) != AOP_REG &&
2502 AOP_TYPE (oper) != AOP_DIR &&
2506 emitcode ("push", "acc");
2510 emitcode ("push", "%s", l);
2513 _endLazyDPSEvaluation ();
2516 /*-----------------------------------------------------------------*/
2517 /* assignResultValue - also indicates if acc is in use afterwards */
2518 /*-----------------------------------------------------------------*/
2520 assignResultValue (operand * oper, operand * func)
2523 unsigned size = AOP_SIZE (oper);
2524 bool accuse = FALSE;
2525 bool pushedA = FALSE;
2527 if (func && IS_BIT (OP_SYM_ETYPE (func)))
2533 if (size == fReturnSizeDS390)
2535 /* I don't think this case can ever happen... */
2536 /* ACC is the last part of this. If writing the result
2537 * uses ACC, we must preserve it.
2539 if (AOP_NEEDSACC(oper))
2541 emitcode(";", "assignResultValue special case for ACC.");
2542 emitcode("push", "acc");
2548 _startLazyDPSEvaluation ();
2551 accuse |= aopPut (oper, fReturn[offset], offset);
2554 _endLazyDPSEvaluation ();
2558 emitcode ("pop", "acc");
2559 accuse |= aopPut (oper, "a", offset);
2565 /*-----------------------------------------------------------------*/
2566 /* genXpush - pushes onto the external stack */
2567 /*-----------------------------------------------------------------*/
2569 genXpush (iCode * ic)
2571 asmop *aop = newAsmop (0);
2573 int size, offset = 0;
2575 D (emitcode (";", "genXpush"));
2577 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2578 r = getFreePtr (ic, &aop, FALSE);
2580 size = AOP_SIZE (IC_LEFT (ic));
2584 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
2585 emitcode ("mov", "%s,_spx", r->name);
2586 emitcode ("inc", "_spx"); // allocate space first
2587 emitcode ("movx", "@%s,a", r->name);
2591 // allocate space first
2592 emitcode ("mov", "%s,_spx", r->name);
2594 emitcode ("add", "a,#%d", size);
2595 emitcode ("mov", "_spx,a");
2597 _startLazyDPSEvaluation ();
2600 MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE, NULL));
2601 emitcode ("movx", "@%s,a", r->name);
2602 emitcode ("inc", "%s", r->name);
2604 _endLazyDPSEvaluation ();
2607 freeAsmop (NULL, aop, ic, TRUE);
2608 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2611 /*-----------------------------------------------------------------*/
2612 /* genIpush - generate code for pushing this gets a little complex */
2613 /*-----------------------------------------------------------------*/
2615 genIpush (iCode * ic)
2617 int size, offset = 0;
2621 D (emitcode (";", "genIpush"));
2623 /* if this is not a parm push : ie. it is spill push
2624 and spill push is always done on the local stack */
2628 /* and the item is spilt then do nothing */
2629 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2632 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2633 size = AOP_SIZE (IC_LEFT (ic));
2634 /* push it on the stack */
2635 _startLazyDPSEvaluation ();
2638 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE, NULL);
2644 emitcode ("push", "%s", l);
2646 _endLazyDPSEvaluation ();
2650 /* this is a parameter push: in this case we call
2651 the routine to find the call and save those
2652 registers that need to be saved */
2655 /* if use external stack then call the external
2656 stack pushing routine */
2657 if (options.useXstack)
2663 /* then do the push */
2664 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2666 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2667 size = AOP_SIZE (IC_LEFT (ic));
2669 _startLazyDPSEvaluation ();
2672 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE, NULL);
2673 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2674 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2677 if (strcmp (l, prev) || *l == '@')
2679 emitcode ("push", "acc");
2683 emitcode ("push", "%s", l);
2687 _endLazyDPSEvaluation ();
2689 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2692 /*-----------------------------------------------------------------*/
2693 /* genIpop - recover the registers: can happen only for spilling */
2694 /*-----------------------------------------------------------------*/
2696 genIpop (iCode * ic)
2700 D (emitcode (";", "genIpop"));
2702 /* if the temp was not pushed then */
2703 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2706 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2707 size = AOP_SIZE (IC_LEFT (ic));
2708 offset = (size - 1);
2709 _startLazyDPSEvaluation ();
2712 emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2713 FALSE, TRUE, NULL));
2715 _endLazyDPSEvaluation ();
2717 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2720 /*-----------------------------------------------------------------*/
2721 /* saveRBank - saves an entire register bank on the stack */
2722 /*-----------------------------------------------------------------*/
2724 saveRBank (int bank, iCode * ic, bool pushPsw)
2727 int count = 8 + (ds390_nBitRegs/8) + (pushPsw ? 1 : 0);
2731 if (options.useXstack)
2735 /* Assume r0 is available for use. */
2736 r = REG_WITH_INDEX (R0_IDX);;
2741 r = getFreePtr (ic, &aop, FALSE);
2743 // allocate space first
2744 emitcode ("mov", "%s,_spx", r->name);
2746 emitcode ("add", "a,#%d", count);
2747 emitcode ("mov", "_spx,a");
2750 for (i = 0; i < 8; i++) /* only R0-R7 needs saving */
2752 if (options.useXstack)
2754 emitcode ("mov", "a,(%s+%d)",
2755 regs390[i].base, 8 * bank + regs390[i].offset);
2756 emitcode ("movx", "@%s,a", r->name);
2758 emitcode ("inc", "%s", r->name);
2761 emitcode ("push", "(%s+%d)",
2762 regs390[i].base, 8 * bank + regs390[i].offset);
2765 if (ds390_nBitRegs > 0)
2767 if (options.useXstack)
2769 emitcode ("mov", "a,bits");
2770 emitcode ("movx", "@%s,a", r->name);
2772 emitcode ("inc", "%s", r->name);
2776 emitcode ("push", "bits");
2783 if (options.useXstack)
2785 emitcode ("mov", "a,psw");
2786 emitcode ("movx", "@%s,a", r->name);
2790 emitcode ("push", "psw");
2793 emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2798 freeAsmop (NULL, aop, ic, TRUE);
2807 /*-----------------------------------------------------------------*/
2808 /* unsaveRBank - restores the register bank from stack */
2809 /*-----------------------------------------------------------------*/
2811 unsaveRBank (int bank, iCode * ic, bool popPsw)
2817 if (options.useXstack)
2821 /* Assume r0 is available for use. */
2822 r = REG_WITH_INDEX (R0_IDX);;
2827 r = getFreePtr (ic, &aop, FALSE);
2829 emitcode ("mov", "%s,_spx", r->name);
2834 if (options.useXstack)
2836 emitcode ("dec", "%s", r->name);
2837 emitcode ("movx", "a,@%s", r->name);
2838 emitcode ("mov", "psw,a");
2842 emitcode ("pop", "psw");
2846 if (ds390_nBitRegs > 0)
2848 if (options.useXstack)
2850 emitcode ("dec", "%s", r->name);
2851 emitcode ("movx", "a,@%s", r->name);
2852 emitcode ("mov", "bits,a");
2856 emitcode ("pop", "bits");
2860 for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2862 if (options.useXstack)
2864 emitcode ("dec", "%s", r->name);
2865 emitcode ("movx", "a,@%s", r->name);
2866 emitcode ("mov", "(%s+%d),a",
2867 regs390[i].base, 8 * bank + regs390[i].offset);
2871 emitcode ("pop", "(%s+%d)",
2872 regs390[i].base, 8 * bank + regs390[i].offset);
2876 if (options.useXstack)
2878 emitcode ("mov", "_spx,%s", r->name);
2883 freeAsmop (NULL, aop, ic, TRUE);
2887 /*-----------------------------------------------------------------*/
2888 /* genSend - gen code for SEND */
2889 /*-----------------------------------------------------------------*/
2890 static void genSend(set *sendSet)
2895 static int rb1_count = 0;
2897 /* first we do all bit parameters */
2898 for (sic = setFirstItem (sendSet); sic;
2899 sic = setNextItem (sendSet))
2901 if (sic->argreg > 12)
2903 int bit = sic->argreg-13;
2905 aopOp (IC_LEFT (sic), sic, FALSE,
2906 (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2908 /* if left is a literal then
2909 we know what the value is */
2910 if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2912 if (((int) operandLitValue (IC_LEFT (sic))))
2913 emitcode ("setb", "b[%d]", bit);
2915 emitcode ("clr", "b[%d]", bit);
2917 else if (AOP_TYPE (IC_LEFT (sic)) == AOP_CRY)
2919 char *l = AOP (IC_LEFT (sic))->aopu.aop_dir;
2920 if (strcmp (l, "c"))
2921 emitcode ("mov", "c,%s", l);
2922 emitcode ("mov", "b[%d],c", bit);
2927 toBoolean (IC_LEFT (sic));
2928 /* set C, if a >= 1 */
2929 emitcode ("add", "a,#0xff");
2930 emitcode ("mov", "b[%d],c", bit);
2935 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2941 saveRegisters (setFirstItem (sendSet));
2942 emitcode ("mov", "bits,b");
2945 /* then we do all other parameters */
2946 for (sic = setFirstItem (sendSet); sic;
2947 sic = setNextItem (sendSet))
2949 if (sic->argreg <= 12)
2951 int size, offset = 0;
2953 size = getSize (operandType (IC_LEFT (sic)));
2954 D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2955 if (sendCount == 0) { /* first parameter */
2956 // we know that dpl(hxb) is the result, so
2958 _startLazyDPSEvaluation ();
2960 aopOp (IC_LEFT (sic), sic, FALSE,
2961 (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2963 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2967 char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE, NULL);
2968 if (strcmp (l, fReturn[offset]))
2970 emitcode ("mov", "%s,%s", fReturn[offset], l);
2974 _endLazyDPSEvaluation ();
2975 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2977 } else { /* if more parameter in registers */
2978 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2980 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (IC_LEFT (sic), offset++,
2981 FALSE, FALSE, NULL));
2983 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2991 adjustEsp(const char *reg)
2993 emitcode ("anl","%s,#3", reg);
2994 if (TARGET_IS_DS400)
2996 emitcode ("orl","%s,#!constbyte",
2998 (options.stack_loc >> 8) & 0xff);
3002 /*-----------------------------------------------------------------*/
3003 /* selectRegBank - emit code to select the register bank */
3004 /*-----------------------------------------------------------------*/
3006 selectRegBank (short bank, bool keepFlags)
3008 /* if f.e. result is in carry */
3011 emitcode ("anl", "psw,#0xE7");
3013 emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
3017 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
3021 /*-----------------------------------------------------------------*/
3022 /* genCall - generates a call statement */
3023 /*-----------------------------------------------------------------*/
3025 genCall (iCode * ic)
3029 bool restoreBank = FALSE;
3030 bool swapBanks = FALSE;
3031 bool accuse = FALSE;
3032 bool accPushed = FALSE;
3033 bool resultInF0 = FALSE;
3034 bool assignResultGenerated = FALSE;
3036 D (emitcode (";", "genCall"));
3038 /* if we are calling a not _naked function that is not using
3039 the same register bank then we need to save the
3040 destination registers on the stack */
3041 dtype = operandType (IC_LEFT (ic));
3042 etype = getSpec(dtype);
3043 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
3044 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
3045 IFFUNC_ISISR (currFunc->type))
3049 /* This is unexpected; the bank should have been saved in
3052 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
3058 /* if caller saves & we have not saved then */
3062 /* if send set is not empty then assign */
3063 /* We've saved all the registers we care about;
3064 * therefore, we may clobber any register not used
3065 * in the calling convention (i.e. anything not in
3070 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
3071 genSend(reverseSet(_G.sendSet));
3073 genSend(_G.sendSet);
3080 emitcode ("mov", "psw,#!constbyte",
3081 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3085 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
3086 OP_SYMBOL (IC_LEFT (ic))->rname :
3087 OP_SYMBOL (IC_LEFT (ic))->name));
3091 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
3094 /* if we need assign a result value */
3095 if ((IS_ITEMP (IC_RESULT (ic)) &&
3096 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3097 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3098 OP_SYMBOL (IC_RESULT (ic))->accuse ||
3099 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3100 IS_TRUE_SYMOP (IC_RESULT (ic)))
3102 if (isOperandInFarSpace (IC_RESULT (ic))
3103 && getSize (operandType (IC_RESULT (ic))) <= 2)
3105 int size = getSize (operandType (IC_RESULT (ic)));
3106 bool pushedB = FALSE;
3108 /* Special case for 1 or 2 byte return in far space. */
3113 emitcode ("mov", "b,%s", fReturn[1]);
3117 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
3122 aopPut (IC_RESULT (ic), "a", 0);
3126 aopPut (IC_RESULT (ic), "b", 1);
3128 assignResultGenerated = TRUE;
3129 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3133 bool pushedB = pushB ();
3134 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
3137 accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3138 assignResultGenerated = TRUE;
3139 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3143 /* adjust the stack for parameters if required */
3147 if (options.stack10bit) {
3148 if (ic->parmBytes <= 10) {
3149 emitcode(";","stack adjustment for parms");
3150 for (i=0; i < ic->parmBytes ; i++) {
3151 emitcode("pop","acc");
3155 emitcode ("clr","c");
3156 emitcode ("mov","a,sp");
3157 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
3158 emitcode ("mov","sp,a");
3159 emitcode ("mov","a,esp");
3161 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
3162 emitcode ("mov","esp,a");
3166 if (ic->parmBytes > 3)
3170 emitcode ("push", "acc");
3173 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3174 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3175 !assignResultGenerated)
3177 emitcode ("mov", "F0,c");
3181 emitcode ("mov", "a,%s", spname);
3182 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
3183 emitcode ("mov", "%s,a", spname);
3185 /* unsaveRegisters from xstack needs acc, but */
3186 /* unsaveRegisters from stack needs this popped */
3187 if (accPushed && !options.useXstack)
3189 emitcode ("pop", "acc");
3194 for (i = 0; i < ic->parmBytes; i++)
3195 emitcode ("dec", "%s", spname);
3199 /* if we had saved some registers then unsave them */
3200 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3202 if (accuse && !accPushed && options.useXstack)
3204 /* xstack needs acc, but doesn't touch normal stack */
3205 emitcode ("push", "acc");
3208 unsaveRegisters (ic);
3211 /* if register bank was saved then pop them */
3213 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
3215 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
3218 emitcode ("mov", "c,F0");
3220 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
3221 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3222 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3226 emitcode ("pop", "acc");
3229 /*-----------------------------------------------------------------*/
3230 /* genPcall - generates a call by pointer statement */
3231 /*-----------------------------------------------------------------*/
3233 genPcall (iCode * ic)
3237 symbol *rlbl = newiTempLabel (NULL);
3238 bool restoreBank=FALSE;
3239 bool resultInF0 = FALSE;
3241 D (emitcode (";", "genPcall"));
3243 dtype = operandType (IC_LEFT (ic))->next;
3244 etype = getSpec(dtype);
3245 /* if caller saves & we have not saved then */
3249 /* if we are calling a not _naked function that is not using
3250 the same register bank then we need to save the
3251 destination registers on the stack */
3252 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
3253 IFFUNC_ISISR (currFunc->type) &&
3254 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
3255 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3259 /* push the return address on to the stack */
3260 emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
3261 emitcode ("push", "acc");
3262 emitcode ("mov", "a,#!hil", (rlbl->key + 100));
3263 emitcode ("push", "acc");
3265 if (options.model == MODEL_FLAT24)
3267 emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
3268 emitcode ("push", "acc");
3271 /* now push the calling address */
3272 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3274 pushSide (IC_LEFT (ic), FPTRSIZE);
3276 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3278 /* if send set is not empty the assign */
3281 genSend(reverseSet(_G.sendSet));
3286 emitcode ("ret", "");
3290 /* if we need assign a result value */
3291 if ((IS_ITEMP (IC_RESULT (ic)) &&
3292 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3293 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3294 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3295 IS_TRUE_SYMOP (IC_RESULT (ic)))
3299 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
3302 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3304 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3307 /* adjust the stack for parameters if required */
3311 if (options.stack10bit) {
3312 if (ic->parmBytes <= 10) {
3313 emitcode(";","stack adjustment for parms");
3314 for (i=0; i < ic->parmBytes ; i++) {
3315 emitcode("pop","acc");
3318 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3319 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3321 emitcode ("mov", "F0,c");
3326 emitcode ("clr","c");
3327 emitcode ("mov","a,sp");
3328 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
3329 emitcode ("mov","sp,a");
3330 emitcode ("mov","a,esp");
3332 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
3333 emitcode ("mov","esp,a");
3337 if (ic->parmBytes > 3) {
3338 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3339 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3341 emitcode ("mov", "F0,c");
3345 emitcode ("mov", "a,%s", spname);
3346 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
3347 emitcode ("mov", "%s,a", spname);
3350 for (i = 0; i < ic->parmBytes; i++)
3351 emitcode ("dec", "%s", spname);
3354 /* if register bank was saved then unsave them */
3356 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3358 /* if we had saved some registers then unsave them */
3360 unsaveRegisters (ic);
3362 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3365 emitcode ("mov", "c,F0");
3367 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
3368 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3369 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3373 /*-----------------------------------------------------------------*/
3374 /* resultRemat - result is rematerializable */
3375 /*-----------------------------------------------------------------*/
3377 resultRemat (iCode * ic)
3379 if (SKIP_IC (ic) || ic->op == IFX)
3382 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3384 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3385 if (sym->remat && !POINTER_SET (ic))
3392 #if defined(__BORLANDC__) || defined(_MSC_VER)
3393 #define STRCASECMP stricmp
3395 #define STRCASECMP strcasecmp
3398 /*-----------------------------------------------------------------*/
3399 /* inExcludeList - return 1 if the string is in exclude Reg list */
3400 /*-----------------------------------------------------------------*/
3402 regsCmp(void *p1, void *p2)
3404 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3408 inExcludeList (char *s)
3410 const char *p = setFirstItem(options.excludeRegsSet);
3412 if (p == NULL || STRCASECMP(p, "none") == 0)
3416 return isinSetWith(options.excludeRegsSet, s, regsCmp);
3419 /*-----------------------------------------------------------------*/
3420 /* genFunction - generated code for function entry */
3421 /*-----------------------------------------------------------------*/
3423 genFunction (iCode * ic)
3425 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3427 bool switchedPSW = FALSE;
3428 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3430 D (emitcode (";", "genFunction"));
3433 /* create the function header */
3434 emitcode (";", "-----------------------------------------");
3435 emitcode (";", " function %s", sym->name);
3436 emitcode (";", "-----------------------------------------");
3438 emitcode ("", "%s:", sym->rname);
3439 ftype = operandType (IC_LEFT (ic));
3440 _G.currentFunc = sym;
3442 if (IFFUNC_ISNAKED(ftype))
3444 emitcode(";", "naked function: no prologue.");
3448 if (options.stack_probe)
3449 emitcode ("lcall","__stack_probe");
3451 /* here we need to generate the equates for the
3452 register bank if required */
3453 if (FUNC_REGBANK (ftype) != rbank)
3457 rbank = FUNC_REGBANK (ftype);
3458 for (i = 0; i < ds390_nRegs; i++)
3460 if (regs390[i].print) {
3461 if (strcmp (regs390[i].base, "0") == 0)
3462 emitcode ("", "%s !equ !constbyte",
3464 8 * rbank + regs390[i].offset);
3466 emitcode ("", "%s !equ %s + !constbyte",
3469 8 * rbank + regs390[i].offset);
3474 /* if this is an interrupt service routine then
3475 save acc, b, dpl, dph */
3476 if (IFFUNC_ISISR (sym->type))
3478 if (!inExcludeList ("acc"))
3479 emitcode ("push", "acc");
3480 if (!inExcludeList ("b"))
3481 emitcode ("push", "b");
3482 if (!inExcludeList ("dpl"))
3483 emitcode ("push", "dpl");
3484 if (!inExcludeList ("dph"))
3485 emitcode ("push", "dph");
3486 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3488 emitcode ("push", "dpx");
3489 /* Make sure we're using standard DPTR */
3490 emitcode ("push", "dps");
3491 emitcode ("mov", "dps,#0");
3492 if (options.stack10bit)
3494 /* This ISR could conceivably use DPTR2. Better save it. */
3495 emitcode ("push", "dpl1");
3496 emitcode ("push", "dph1");
3497 emitcode ("push", "dpx1");
3498 emitcode ("push", DP2_RESULT_REG);
3501 /* if this isr has no bank i.e. is going to
3502 run with bank 0 , then we need to save more
3504 if (!FUNC_REGBANK (sym->type))
3508 /* if this function does not call any other
3509 function then we can be economical and
3510 save only those registers that are used */
3511 if (!IFFUNC_HASFCALL(sym->type))
3513 /* if any registers used */
3516 bool bits_pushed = FALSE;
3517 /* save the registers used */
3518 for (i = 0; i < sym->regsUsed->size; i++)
3520 if (bitVectBitValue (sym->regsUsed, i))
3521 bits_pushed = pushReg (i, bits_pushed);
3527 /* this function has a function call. We cannot
3528 determine register usage so we will have to push the
3530 saveRBank (0, ic, FALSE);
3531 if (options.parms_in_bank1) {
3532 for (i=0; i < 8 ; i++ ) {
3533 emitcode ("push","%s",rb1regs[i]);
3540 /* This ISR uses a non-zero bank.
3542 * We assume that the bank is available for our
3545 * However, if this ISR calls a function which uses some
3546 * other bank, we must save that bank entirely.
3548 unsigned long banksToSave = 0;
3550 if (IFFUNC_HASFCALL(sym->type))
3553 #define MAX_REGISTER_BANKS 4
3558 for (i = ic; i; i = i->next)
3560 if (i->op == ENDFUNCTION)
3562 /* we got to the end OK. */
3570 dtype = operandType (IC_LEFT(i));
3572 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3574 /* Mark this bank for saving. */
3575 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3577 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3581 banksToSave |= (1 << FUNC_REGBANK(dtype));
3584 /* And note that we don't need to do it in
3592 /* This is a mess; we have no idea what
3593 * register bank the called function might
3596 * The only thing I can think of to do is
3597 * throw a warning and hope.
3599 werror(W_FUNCPTR_IN_USING_ISR);
3603 if (banksToSave && options.useXstack)
3605 /* Since we aren't passing it an ic,
3606 * saveRBank will assume r0 is available to abuse.
3608 * So switch to our (trashable) bank now, so
3609 * the caller's R0 isn't trashed.
3611 emitcode ("push", "psw");
3612 emitcode ("mov", "psw,#!constbyte",
3613 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3617 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3619 if (banksToSave & (1 << ix))
3621 saveRBank(ix, NULL, FALSE);
3625 // TODO: this needs a closer look
3626 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3631 /* if callee-save to be used for this function
3632 then save the registers being used in this function */
3633 if (IFFUNC_CALLEESAVES(sym->type))
3637 /* if any registers used */
3640 bool bits_pushed = FALSE;
3641 /* save the registers used */
3642 for (i = 0; i < sym->regsUsed->size; i++)
3644 if (bitVectBitValue (sym->regsUsed, i))
3646 bits_pushed = pushReg (i, bits_pushed);
3654 /* set the register bank to the desired value */
3655 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3658 emitcode ("push", "psw");
3659 emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3663 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3664 if (options.stack10bit) {
3665 emitcode ("push","_bpx");
3666 emitcode ("push","_bpx+1");
3667 emitcode ("mov","_bpx,%s",spname);
3668 emitcode ("mov","_bpx+1,esp");
3669 adjustEsp("_bpx+1");
3671 if (options.useXstack)
3673 emitcode ("mov", "r0,%s", spname);
3674 emitcode ("mov", "a,_bp");
3675 emitcode ("movx", "@r0,a");
3676 emitcode ("inc", "%s", spname);
3678 /* set up the stack */
3679 emitcode ("push", "_bp"); /* save the callers stack */
3681 emitcode ("mov", "_bp,%s", spname);
3685 /* adjust the stack for the function */
3688 if (options.stack10bit) {
3689 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
3690 assert (sym->recvSize <= 4);
3691 if (sym->stack <= 8) {
3692 while (i--) emitcode ("push","acc");
3695 emitcode ("mov","a,sp");
3696 emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3697 emitcode ("mov","sp,a");
3698 emitcode ("mov","a,esp");
3700 emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3701 emitcode ("mov","esp,a");
3706 werror (W_STACK_OVERFLOW, sym->name);
3708 if (i > 3 && sym->recvSize < 4) {
3710 emitcode ("mov", "a,sp");
3711 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3712 emitcode ("mov", "sp,a");
3716 emitcode ("inc", "sp");
3723 emitcode ("mov", "a,_spx");
3724 emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3725 emitcode ("mov", "_spx,a");
3728 /* if critical function then turn interrupts off */
3729 if (IFFUNC_ISCRITICAL (ftype))
3731 symbol *tlbl = newiTempLabel (NULL);
3732 emitcode ("setb", "c");
3733 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3734 emitcode ("clr", "c");
3736 emitcode ("push", "psw"); /* save old ea via c in psw */
3740 /*-----------------------------------------------------------------*/
3741 /* genEndFunction - generates epilogue for functions */
3742 /*-----------------------------------------------------------------*/
3744 genEndFunction (iCode * ic)
3746 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3747 lineNode *lnp = lineCurr;
3749 bitVect *regsUsedPrologue;
3750 bitVect *regsUnneeded;
3753 D (emitcode (";", "genEndFunction"));
3755 _G.currentFunc = NULL;
3756 if (IFFUNC_ISNAKED(sym->type))
3758 emitcode(";", "naked function: no epilogue.");
3759 if (options.debug && currFunc)
3760 debugFile->writeEndFunction (currFunc, ic, 0);
3764 if (IFFUNC_ISCRITICAL (sym->type))
3766 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3768 emitcode ("rlc", "a"); /* save c in a */
3769 emitcode ("pop", "psw"); /* restore ea via c in psw */
3770 emitcode ("mov", "ea,c");
3771 emitcode ("rrc", "a"); /* restore c from a */
3775 emitcode ("pop", "psw"); /* restore ea via c in psw */
3776 emitcode ("mov", "ea,c");
3780 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3781 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3783 if (options.stack10bit) {
3785 emitcode ("mov", "sp,_bpx", spname);
3786 emitcode ("mov", "esp,_bpx+1", spname);
3789 emitcode ("mov", "%s,_bp", spname);
3793 /* if use external stack but some variables were
3794 added to the local stack then decrement the
3796 if (options.useXstack && sym->stack) {
3797 emitcode ("mov", "a,sp");
3798 emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3799 emitcode ("mov", "sp,a");
3803 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3804 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3806 if (options.useXstack) {
3807 emitcode ("mov", "r0,%s", spname);
3808 emitcode ("movx", "a,@r0");
3809 emitcode ("mov", "_bp,a");
3810 emitcode ("dec", "%s", spname);
3812 if (options.stack10bit) {
3813 emitcode ("pop", "_bpx+1");
3814 emitcode ("pop", "_bpx");
3816 emitcode ("pop", "_bp");
3821 /* restore the register bank */
3822 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3824 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3825 || !options.useXstack)
3827 /* Special case of ISR using non-zero bank with useXstack
3830 emitcode ("pop", "psw");
3834 if (IFFUNC_ISISR (sym->type))
3837 /* now we need to restore the registers */
3838 /* if this isr has no bank i.e. is going to
3839 run with bank 0 , then we need to save more
3841 if (!FUNC_REGBANK (sym->type))
3844 /* if this function does not call any other
3845 function then we can be economical and
3846 save only those registers that are used */
3847 if (!IFFUNC_HASFCALL(sym->type))
3849 /* if any registers used */
3852 bool bits_popped = FALSE;
3853 /* save the registers used */
3854 for (i = sym->regsUsed->size; i >= 0; i--)
3856 if (bitVectBitValue (sym->regsUsed, i))
3857 bits_popped = popReg (i, bits_popped);
3863 /* this function has a function call. We cannot
3864 determine register usage so we will have to pop the
3866 if (options.parms_in_bank1) {
3867 for (i = 7 ; i >= 0 ; i-- ) {
3868 emitcode ("pop","%s",rb1regs[i]);
3871 unsaveRBank (0, ic, FALSE);
3876 /* This ISR uses a non-zero bank.
3878 * Restore any register banks saved by genFunction
3881 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3884 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3886 if (savedBanks & (1 << ix))
3888 unsaveRBank(ix, NULL, FALSE);
3892 if (options.useXstack)
3894 /* Restore bank AFTER calling unsaveRBank,
3895 * since it can trash r0.
3897 emitcode ("pop", "psw");
3901 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3903 if (options.stack10bit)
3905 emitcode ("pop", DP2_RESULT_REG);
3906 emitcode ("pop", "dpx1");
3907 emitcode ("pop", "dph1");
3908 emitcode ("pop", "dpl1");
3910 emitcode ("pop", "dps");
3911 emitcode ("pop", "dpx");
3913 if (!inExcludeList ("dph"))
3914 emitcode ("pop", "dph");
3915 if (!inExcludeList ("dpl"))
3916 emitcode ("pop", "dpl");
3917 if (!inExcludeList ("b"))
3918 emitcode ("pop", "b");
3919 if (!inExcludeList ("acc"))
3920 emitcode ("pop", "acc");
3922 /* if debug then send end of function */
3923 if (options.debug && currFunc)
3925 debugFile->writeEndFunction (currFunc, ic, 1);
3928 emitcode ("reti", "");
3932 if (IFFUNC_CALLEESAVES(sym->type))
3936 /* if any registers used */
3939 /* save the registers used */
3940 for (i = sym->regsUsed->size; i >= 0; i--)
3942 if (bitVectBitValue (sym->regsUsed, i))
3943 emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
3948 /* if debug then send end of function */
3949 if (options.debug && currFunc)
3951 debugFile->writeEndFunction (currFunc, ic, 1);
3954 emitcode ("ret", "");
3957 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3960 /* If this was an interrupt handler using bank 0 that called another */
3961 /* function, then all registers must be saved; nothing to optimized. */
3962 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3963 && !FUNC_REGBANK(sym->type))
3966 /* There are no push/pops to optimize if not callee-saves or ISR */
3967 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3970 /* If there were stack parameters, we cannot optimize without also */
3971 /* fixing all of the stack offsets; this is too dificult to consider. */
3972 if (FUNC_HASSTACKPARM(sym->type))
3975 /* Compute the registers actually used */
3976 regsUsed = newBitVect (ds390_nRegs);
3977 regsUsedPrologue = newBitVect (ds390_nRegs);
3980 if (lnp->ic && lnp->ic->op == FUNCTION)
3981 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3983 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3985 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3986 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3993 if (bitVectBitValue (regsUsedPrologue, DPS_IDX)
3994 && !bitVectBitValue (regsUsed, DPS_IDX))
3996 bitVectUnSetBit (regsUsedPrologue, DPS_IDX);
3999 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
4000 && !bitVectBitValue (regsUsed, CND_IDX))
4002 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
4003 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
4004 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
4005 bitVectUnSetBit (regsUsed, CND_IDX);
4008 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
4010 /* If this was an interrupt handler that called another function */
4011 /* function, then assume working registers may be modified by it. */
4012 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
4014 regsUsed = bitVectSetBit (regsUsed, AP_IDX);
4015 regsUsed = bitVectSetBit (regsUsed, DPX1_IDX);
4016 regsUsed = bitVectSetBit (regsUsed, DPL1_IDX);
4017 regsUsed = bitVectSetBit (regsUsed, DPH1_IDX);
4018 regsUsed = bitVectSetBit (regsUsed, DPX_IDX);
4019 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
4020 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
4021 regsUsed = bitVectSetBit (regsUsed, DPS_IDX);
4022 regsUsed = bitVectSetBit (regsUsed, B_IDX);
4023 regsUsed = bitVectSetBit (regsUsed, A_IDX);
4024 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
4027 /* Remove the unneeded push/pops */
4028 regsUnneeded = newBitVect (ds390_nRegs);
4031 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
4033 if (!strncmp(lnp->line, "push", 4))
4035 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
4036 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4038 connectLine (lnp->prev, lnp->next);
4039 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4042 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
4044 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
4045 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4047 connectLine (lnp->prev, lnp->next);
4048 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4055 for (idx = 0; idx < regsUnneeded->size; idx++)
4056 if (bitVectBitValue (regsUnneeded, idx))
4057 emitcode (";", "eliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
4059 freeBitVect (regsUnneeded);
4060 freeBitVect (regsUsed);
4061 freeBitVect (regsUsedPrologue);
4064 /*-----------------------------------------------------------------*/
4065 /* genJavaNativeRet - generate code for return JavaNative */
4066 /*-----------------------------------------------------------------*/
4067 static void genJavaNativeRet(iCode *ic)
4071 aopOp (IC_LEFT (ic), ic, FALSE,
4072 AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
4073 size = AOP_SIZE (IC_LEFT (ic));
4077 /* it is assigned to GPR0-R3 then push them */
4078 if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
4079 aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
4080 for (i = 0 ; i < size ; i++ ) {
4081 emitcode ("push","%s",
4082 aopGet(IC_LEFT(ic),i,FALSE,TRUE,DP2_RESULT_REG));
4084 for (i = (size-1) ; i >= 0 ; i--) {
4085 emitcode ("pop","a%s",javaRet[i]);
4088 for (i = 0 ; i < size ; i++)
4089 emitcode ("mov","%s,%s",javaRet[i],
4090 aopGet(IC_LEFT(ic),i,FALSE,TRUE,DP2_RESULT_REG));
4092 for (i = size ; i < 4 ; i++ )
4093 emitcode ("mov","%s,#0",javaRet[i]);
4097 /*-----------------------------------------------------------------*/
4098 /* genRet - generate code for return statement */
4099 /*-----------------------------------------------------------------*/
4103 int size, offset = 0, pushed = 0;
4105 D (emitcode (";", "genRet"));
4107 /* if we have no return value then
4108 just generate the "ret" */
4112 /* if this is a JavaNative function then return
4113 value in different register */
4114 if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
4115 genJavaNativeRet(ic);
4118 /* we have something to return then
4119 move the return value into place */
4120 aopOp (IC_LEFT (ic), ic, FALSE,
4121 (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
4122 size = AOP_SIZE (IC_LEFT (ic));
4124 _startLazyDPSEvaluation ();
4126 if (IS_BIT(_G.currentFunc->etype))
4128 movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4135 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
4137 l = aopGet (IC_LEFT (ic), offset++,
4139 emitcode ("push", "%s", l);
4144 /* Since A is the last element of fReturn,
4145 * it is OK to clobber it in the aopGet.
4147 l = aopGet (IC_LEFT (ic), offset,
4148 FALSE, FALSE, NULL);
4149 if (strcmp (fReturn[offset], l))
4150 emitcode ("mov", "%s,%s", fReturn[offset++], l);
4153 _endLazyDPSEvaluation ();
4158 if (strcmp (fReturn[pushed], "a"))
4159 emitcode ("pop", fReturn[pushed]);
4161 emitcode ("pop", "acc");
4163 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
4166 /* generate a jump to the return label
4167 if the next is not the return statement */
4168 if (!(ic->next && ic->next->op == LABEL &&
4169 IC_LABEL (ic->next) == returnLabel))
4171 emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
4175 /*-----------------------------------------------------------------*/
4176 /* genLabel - generates a label */
4177 /*-----------------------------------------------------------------*/
4179 genLabel (iCode * ic)
4181 /* special case never generate */
4182 if (IC_LABEL (ic) == entryLabel)
4185 D (emitcode (";", "genLabel"));
4187 emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
4190 /*-----------------------------------------------------------------*/
4191 /* genGoto - generates a ljmp */
4192 /*-----------------------------------------------------------------*/
4194 genGoto (iCode * ic)
4196 D (emitcode (";", "genGoto"));
4198 emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
4201 /*-----------------------------------------------------------------*/
4202 /* findLabelBackwards: walks back through the iCode chain looking */
4203 /* for the given label. Returns number of iCode instructions */
4204 /* between that label and given ic. */
4205 /* Returns zero if label not found. */
4206 /*-----------------------------------------------------------------*/
4208 findLabelBackwards (iCode * ic, int key)
4217 /* If we have any pushes or pops, we cannot predict the distance.
4218 I don't like this at all, this should be dealt with in the
4220 if (ic->op == IPUSH || ic->op == IPOP) {
4224 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4226 /* printf("findLabelBackwards = %d\n", count); */
4234 /*-----------------------------------------------------------------*/
4235 /* genPlusIncr :- does addition with increment if possible */
4236 /*-----------------------------------------------------------------*/
4238 genPlusIncr (iCode * ic)
4240 unsigned int icount;
4241 unsigned int size = getDataSize (IC_RESULT (ic));
4243 /* will try to generate an increment */
4244 /* if the right side is not a literal
4246 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4249 /* if the literal value of the right hand side
4250 is greater than 4 then it is not worth it */
4251 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4254 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4255 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4257 emitcode("inc","%s",aopGet(IC_RESULT(ic),0,FALSE,FALSE,NULL));
4261 /* if increment 16 bits in register */
4263 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4264 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4265 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4274 /* If the next instruction is a goto and the goto target
4275 * is <= 5 instructions previous to this, we can generate
4276 * jumps straight to that target.
4278 if (ic->next && ic->next->op == GOTO
4279 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4282 D (emitcode (";", "tail increment optimized (range %d)", labelRange));
4283 tlbl = IC_LABEL (ic->next);
4288 tlbl = newiTempLabel (NULL);
4291 l = aopGet (IC_RESULT (ic), LSB, FALSE, FALSE, NULL);
4292 emitcode ("inc", "%s", l);
4294 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4295 IS_AOP_PREG (IC_RESULT (ic)))
4297 emitcode ("cjne", "%s,%s,!tlabel", l, zero, tlbl->key + 100);
4301 emitcode ("clr", "a");
4302 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4305 l = aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE, NULL);
4306 emitcode ("inc", "%s", l);
4309 if (!strcmp(l, "acc"))
4311 emitcode("jnz", "!tlabel", tlbl->key + 100);
4313 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4314 IS_AOP_PREG (IC_RESULT (ic)))
4316 emitcode ("cjne", "%s,%s,!tlabel", l, zero, tlbl->key + 100);
4320 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4323 l = aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE, NULL);
4324 emitcode ("inc", "%s", l);
4328 if (!strcmp(l, "acc"))
4330 emitcode("jnz", "!tlabel", tlbl->key + 100);
4332 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4333 IS_AOP_PREG (IC_RESULT (ic)))
4335 emitcode ("cjne", "%s,%s,!tlabel", l, zero, tlbl->key + 100);
4339 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4342 l = aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE, NULL);
4343 emitcode ("inc", "%s", l);
4353 if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
4354 !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 &&
4355 options.model == MODEL_FLAT24 )
4357 if (IC_RESULT(ic)->isGptr)
4359 emitcode ("mov", "b,%s", aopGet(IC_LEFT (ic), 3, FALSE, FALSE, NULL));
4363 emitcode ("mov", "dpx,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE, NULL));
4365 emitcode ("mov", "dph,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE, NULL));
4367 emitcode ("mov", "dpl,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4371 emitcode ("inc", "dptr");
4375 if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
4376 AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
4378 emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
4380 emitcode ("inc", "dptr");
4381 emitcode ("mov", "dps,#0");
4385 /* if the sizes are greater than 1 then we cannot */
4386 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4387 AOP_SIZE (IC_LEFT (ic)) > 1)
4390 /* we can if the aops of the left & result match or
4391 if they are in registers and the registers are the
4394 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4395 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4396 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4400 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4401 emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
4402 aopPut (IC_RESULT (ic), "a", 0);
4406 _startLazyDPSEvaluation ();
4409 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4411 _endLazyDPSEvaluation ();
4420 /*-----------------------------------------------------------------*/
4421 /* outBitAcc - output a bit in acc */
4422 /*-----------------------------------------------------------------*/
4424 outBitAcc (operand * result)
4426 symbol *tlbl = newiTempLabel (NULL);
4427 /* if the result is a bit */
4428 if (AOP_TYPE (result) == AOP_CRY)
4430 aopPut (result, "a", 0);
4434 emitcode ("jz", "!tlabel", tlbl->key + 100);
4435 emitcode ("mov", "a,%s", one);
4441 /*-----------------------------------------------------------------*/
4442 /* genPlusBits - generates code for addition of two bits */
4443 /*-----------------------------------------------------------------*/
4445 genPlusBits (iCode * ic)
4447 D (emitcode (";", "genPlusBits"));
4449 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4451 symbol *lbl = newiTempLabel (NULL);
4452 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4453 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4454 emitcode ("cpl", "c");
4456 outBitC (IC_RESULT (ic));
4460 emitcode ("clr", "a");
4461 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4462 emitcode ("rlc", "a");
4463 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4464 emitcode ("addc", "a,%s", zero);
4465 outAcc (IC_RESULT (ic));
4470 adjustArithmeticResult (iCode * ic)
4472 if (opIsGptr (IC_RESULT (ic)) &&
4473 opIsGptr (IC_LEFT (ic)) &&
4474 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4476 aopPut (IC_RESULT (ic),
4477 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE, NULL),
4481 if (opIsGptr (IC_RESULT (ic)) &&
4482 opIsGptr (IC_RIGHT (ic)) &&
4483 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4485 aopPut (IC_RESULT (ic),
4486 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE, NULL),
4490 if (opIsGptr (IC_RESULT (ic)) &&
4491 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4492 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4493 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4494 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4497 SNPRINTF (buffer, sizeof(buffer),
4498 "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4499 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4503 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
4504 // generates the result if possible. If result is generated, returns TRUE; otherwise
4505 // returns false and caller must deal with fact that result isn't aopOp'd.
4506 bool aopOp3(iCode * ic)
4508 bool dp1InUse, dp2InUse;
4511 // First, generate the right opcode. DPTR may be used if neither left nor result are
4514 // D (emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
4515 // AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
4516 // AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
4517 // AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
4519 // D (emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
4520 // AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
4521 // AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
4522 // AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
4525 // Right uses DPTR unless left or result is an AOP_STR; however,
4526 // if right is an AOP_STR, it must use DPTR regardless.
4527 if ((AOP_IS_STR (IC_LEFT (ic)) || AOP_IS_STR (IC_RESULT (ic)))
4528 && !AOP_IS_STR (IC_RIGHT (ic)))
4537 aopOp (IC_RIGHT(ic), ic, FALSE, useDp2);
4539 // if the right used DPTR, left MUST use DPTR2.
4540 // if the right used DPTR2, left MUST use DPTR.
4541 // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
4542 // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
4543 // enabling us to assign DPTR to result.
4545 if (AOP_USESDPTR (IC_RIGHT (ic)))
4549 else if (AOP_USESDPTR2 (IC_RIGHT (ic)))
4555 if (AOP_IS_STR (IC_RESULT (ic)) && !AOP_IS_STR (IC_LEFT (ic)))
4565 aopOp (IC_LEFT (ic), ic, FALSE, useDp2);
4568 // We've op'd the left & right. So, if left or right are the same operand as result,
4569 // we know aopOp will succeed, and we can just do it & bail.
4570 if (isOperandEqual (IC_LEFT (ic), IC_RESULT (ic)))
4572 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4575 if (isOperandEqual (IC_RIGHT (ic), IC_RESULT (ic)))
4577 // D (emitcode(";", "aopOp3: (left | right) & result equal"));
4578 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4582 // Operands may be equivalent (but not equal) if they share a spill location. If
4583 // so, use the same DPTR or DPTR2.
4584 if (operandsEqu (IC_LEFT (ic), IC_RESULT (ic)))
4586 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4589 if (operandsEqu (IC_RIGHT (ic), IC_RESULT (ic)))
4591 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4595 // Note which dptrs are currently in use.
4596 dp1InUse = AOP_USESDPTR (IC_LEFT (ic)) || AOP_USESDPTR (IC_RIGHT (ic));
4597 dp2InUse = AOP_USESDPTR2 (IC_LEFT (ic)) || AOP_USESDPTR2 (IC_RIGHT (ic));
4599 // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot
4601 if (dp1InUse && AOP_IS_STR (IC_RESULT (ic)))
4606 // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
4607 if (dp2InUse && AOP_IS_DPTRn (IC_RESULT (ic)))
4612 // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck
4613 if (dp1InUse && dp2InUse && isOperandInFarSpace (IC_RESULT (ic)))
4618 aopOp (IC_RESULT (ic), ic, TRUE, dp1InUse);
4620 // Some sanity checking...
4621 if (dp1InUse && AOP_USESDPTR (IC_RESULT (ic)))
4624 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
4625 __FILE__, __LINE__, ic->filename, ic->lineno);
4626 emitcode(";", ">>> unexpected DPTR here.");
4629 if (dp2InUse && AOP_USESDPTR2 (IC_RESULT (ic)))
4632 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
4633 __FILE__, __LINE__, ic->filename, ic->lineno);
4634 emitcode(";", ">>> unexpected DPTR2 here.");
4640 // Macro to aopOp all three operands of an ic. If this cannot be done,
4641 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
4642 // will be set TRUE. The caller must then handle the case specially, noting
4643 // that the IC_RESULT operand is not aopOp'd.
4645 #define AOP_OP_3_NOFATAL(ic, rc) \
4646 do { rc = !aopOp3(ic); } while (0)
4648 // aopOp the left & right operands of an ic.
4649 #define AOP_OP_2(ic) \
4650 aopOp (IC_RIGHT (ic), ic, FALSE, AOP_IS_STR (IC_LEFT (ic))); \
4651 aopOp (IC_LEFT (ic), ic, FALSE, AOP_USESDPTR (IC_RIGHT (ic)));
4653 // convienience macro.
4654 #define AOP_SET_LOCALS(ic) \
4655 left = IC_LEFT(ic); \
4656 right = IC_RIGHT(ic); \
4657 result = IC_RESULT(ic);
4660 // Given an integer value of pushedSize bytes on the stack,
4661 // adjust it to be resultSize bytes, either by discarding
4662 // the most significant bytes or by zero-padding.
4664 // On exit from this macro, pushedSize will have been adjusted to
4665 // equal resultSize, and ACC may be trashed.
4666 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
4667 /* If the pushed data is bigger than the result, \
4668 * simply discard unused bytes. Icky, but works. \
4670 while (pushedSize > resultSize) \
4672 D (emitcode (";", "discarding unused result byte.")); \
4673 emitcode ("pop", "acc"); \
4676 if (pushedSize < resultSize) \
4678 emitcode ("clr", "a"); \
4679 /* Conversly, we haven't pushed enough here. \
4680 * just zero-pad, and all is well. \
4682 while (pushedSize < resultSize) \
4684 emitcode("push", "acc"); \
4688 assert(pushedSize == resultSize);
4690 /*-----------------------------------------------------------------*/
4691 /* genPlus - generates code for addition */
4692 /*-----------------------------------------------------------------*/
4694 genPlus (iCode * ic)
4696 int size, offset = 0;
4699 bool swappedLR = FALSE;
4701 D (emitcode (";", "genPlus"));
4703 /* special cases :- */
4704 if ( AOP_IS_STR (IC_LEFT (ic)) &&
4705 isOperandLiteral (IC_RIGHT (ic)) && OP_SYMBOL (IC_RESULT (ic))->ruonly) {
4706 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
4707 size = (int)floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4709 while (size--) emitcode ("inc","dptr");
4711 emitcode ("mov", "a,dpl");
4712 emitcode ("add", "a,#!constbyte", size & 0xff);
4713 emitcode ("mov", "dpl,a");
4714 emitcode ("mov", "a,dph");
4715 emitcode ("addc", "a,#!constbyte", (size >> 8) & 0xff);
4716 emitcode ("mov", "dph,a");
4717 emitcode ("mov", "a,dpx");
4718 emitcode ("addc", "a,#!constbyte", (size >> 16) & 0xff);
4719 emitcode ("mov", "dpx,a");
4721 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4724 if ( IS_SYMOP (IC_LEFT (ic)) &&
4725 OP_SYMBOL (IC_LEFT (ic))->remat &&
4726 isOperandInFarSpace (IC_RIGHT (ic))) {
4727 operand *op = IC_RIGHT(ic);
4728 IC_RIGHT(ic) = IC_LEFT(ic);
4732 AOP_OP_3_NOFATAL (ic, pushResult);
4736 D (emitcode (";", "genPlus: must push result: 3 ops in far space"));
4741 /* if literal, literal on the right or
4742 if left requires ACC or right is already
4744 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4745 ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic)))) ||
4746 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4748 operand *t = IC_RIGHT (ic);
4749 IC_RIGHT (ic) = IC_LEFT (ic);
4752 D (emitcode (";", "Swapped plus args."));
4755 /* if both left & right are in bit
4757 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4758 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4764 /* if left in bit space & right literal */
4765 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4766 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4768 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4769 /* if result in bit space */
4770 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4772 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4773 emitcode ("cpl", "c");
4774 outBitC (IC_RESULT (ic));
4778 size = getDataSize (IC_RESULT (ic));
4779 _startLazyDPSEvaluation ();
4782 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4783 emitcode ("addc", "a,%s", zero);
4784 aopPut (IC_RESULT (ic), "a", offset++);
4786 _endLazyDPSEvaluation ();
4791 /* if I can do an increment instead
4792 of add then GOOD for ME */
4793 if (genPlusIncr (ic) == TRUE)
4795 D (emitcode (";", "did genPlusIncr"));
4800 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4802 _startLazyDPSEvaluation ();
4805 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4807 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
4809 emitcode ("add", "a,%s",
4810 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4812 emitcode ("addc", "a,%s",
4813 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4817 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4819 /* right is going to use ACC or we would have taken the
4822 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4824 D(emitcode(";", "+ AOP_ACC special case."););
4825 emitcode("xch", "a, %s", DP2_RESULT_REG);
4827 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4830 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4833 emitcode("add", "a, %s", DP2_RESULT_REG);
4837 emitcode ("add", "a,%s",
4838 aopGet (IC_LEFT(ic), offset, FALSE, FALSE,
4844 emitcode ("addc", "a,%s",
4845 aopGet (IC_LEFT (ic), offset, FALSE, FALSE,
4851 aopPut (IC_RESULT (ic), "a", offset);
4855 emitcode ("push", "acc");
4859 _endLazyDPSEvaluation ();
4863 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4865 size = getDataSize (IC_LEFT (ic));
4866 rSize = getDataSize (IC_RESULT (ic));
4868 ADJUST_PUSHED_RESULT(size, rSize);
4870 _startLazyDPSEvaluation ();
4873 emitcode ("pop", "acc");
4874 aopPut (IC_RESULT (ic), "a", size);
4876 _endLazyDPSEvaluation ();
4879 adjustArithmeticResult (ic);
4882 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4885 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4886 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4890 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4891 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4895 /*-----------------------------------------------------------------*/
4896 /* genMinusDec :- does subtraction with decrement if possible */
4897 /*-----------------------------------------------------------------*/
4899 genMinusDec (iCode * ic)
4901 unsigned int icount;
4902 unsigned int size = getDataSize (IC_RESULT (ic));
4904 /* will try to generate an increment */
4905 /* if the right side is not a literal
4907 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4910 /* if the literal value of the right hand side
4911 is greater than 4 then it is not worth it */
4912 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4915 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4916 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4918 emitcode("dec","%s",aopGet(IC_RESULT(ic),0,FALSE,FALSE,NULL));
4922 /* if decrement 16 bits in register */
4923 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4924 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4925 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4934 /* If the next instruction is a goto and the goto target
4935 * is <= 5 instructions previous to this, we can generate
4936 * jumps straight to that target.
4938 if (ic->next && ic->next->op == GOTO
4939 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4942 D (emitcode (";", "tail decrement optimized (range %d)", labelRange));
4943 tlbl = IC_LABEL (ic->next);
4948 tlbl = newiTempLabel (NULL);
4952 l = aopGet (IC_RESULT (ic), LSB, FALSE, FALSE, NULL);
4953 emitcode ("dec", "%s", l);
4955 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4956 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4957 IS_AOP_PREG (IC_RESULT (ic)))
4959 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4963 emitcode ("mov", "a,#!constbyte",0xff);
4964 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4966 l = aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE, NULL);
4967 emitcode ("dec", "%s", l);
4970 if (!strcmp(l, "acc"))
4972 emitcode("jnz", "!tlabel", tlbl->key + 100);
4974 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4975 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4976 IS_AOP_PREG (IC_RESULT (ic)))
4978 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4982 emitcode ("mov", "a,#!constbyte",0xff);
4983 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4985 l = aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE, NULL);
4986 emitcode ("dec", "%s", l);
4990 if (!strcmp(l, "acc"))
4992 emitcode("jnz", "!tlabel", tlbl->key + 100);
4994 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4995 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4996 IS_AOP_PREG (IC_RESULT (ic)))
4998 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
5002 emitcode ("mov", "a,#!constbyte",0xff);
5003 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
5005 l = aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE, NULL);
5006 emitcode ("dec", "%s", l);
5015 /* if the sizes are greater than 1 then we cannot */
5016 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
5017 AOP_SIZE (IC_LEFT (ic)) > 1)
5020 /* we can if the aops of the left & result match or
5021 if they are in registers and the registers are the
5024 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
5025 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
5026 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
5030 if (aopGetUsesAcc (IC_LEFT (ic), 0))
5032 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL));
5037 l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL);
5040 _startLazyDPSEvaluation ();
5043 emitcode ("dec", "%s", l);
5045 _endLazyDPSEvaluation ();
5047 if (AOP_NEEDSACC (IC_RESULT (ic)))
5048 aopPut (IC_RESULT (ic), "a", 0);
5056 /*-----------------------------------------------------------------*/
5057 /* addSign - complete with sign */
5058 /*-----------------------------------------------------------------*/
5060 addSign (operand * result, int offset, int sign)
5062 int size = (getDataSize (result) - offset);
5065 _startLazyDPSEvaluation();
5068 emitcode ("rlc", "a");
5069 emitcode ("subb", "a,acc");
5072 aopPut (result, "a", offset++);
5079 aopPut (result, zero, offset++);
5082 _endLazyDPSEvaluation();
5086 /*-----------------------------------------------------------------*/
5087 /* genMinusBits - generates code for subtraction of two bits */
5088 /*-----------------------------------------------------------------*/
5090 genMinusBits (iCode * ic)
5092 symbol *lbl = newiTempLabel (NULL);
5094 D (emitcode (";", "genMinusBits"));
5096 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
5098 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
5099 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
5100 emitcode ("cpl", "c");
5102 outBitC (IC_RESULT (ic));
5106 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
5107 emitcode ("subb", "a,acc");
5108 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
5109 emitcode ("inc", "a");
5111 aopPut (IC_RESULT (ic), "a", 0);
5112 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
5116 /*-----------------------------------------------------------------*/
5117 /* genMinus - generates code for subtraction */
5118 /*-----------------------------------------------------------------*/
5120 genMinus (iCode * ic)
5122 int size, offset = 0;
5127 D (emitcode (";", "genMinus"));
5129 AOP_OP_3_NOFATAL(ic, pushResult);
5133 /* special cases :- */
5134 /* if both left & right are in bit space */
5135 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
5136 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
5142 /* if I can do an decrement instead
5143 of subtract then GOOD for ME */
5144 if (genMinusDec (ic) == TRUE)
5149 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
5151 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
5157 lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5162 /* if literal, add a,#-lit, else normal subb */
5163 _startLazyDPSEvaluation ();
5165 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
5166 if (AOP_USESDPTR(IC_RIGHT(ic))) {
5167 emitcode ("mov","b,%s",
5168 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
5169 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
5170 emitcode ("subb","a,b");
5172 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
5173 emitcode ("subb", "a,%s",
5174 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE,
5178 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
5179 /* first add without previous c */
5181 if (!size && lit==-1) {
5182 emitcode ("dec", "a");
5184 emitcode ("add", "a,#!constbyte",
5185 (unsigned int) (lit & 0x0FFL));
5188 emitcode ("addc", "a,#!constbyte",
5189 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5194 emitcode ("push", "acc");
5196 aopPut (IC_RESULT (ic), "a", offset);
5200 _endLazyDPSEvaluation ();
5204 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
5206 size = getDataSize (IC_LEFT (ic));
5207 rSize = getDataSize (IC_RESULT (ic));
5209 ADJUST_PUSHED_RESULT(size, rSize);
5211 _startLazyDPSEvaluation ();
5214 emitcode ("pop", "acc");
5215 aopPut (IC_RESULT (ic), "a", size);
5217 _endLazyDPSEvaluation ();
5220 adjustArithmeticResult (ic);
5223 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5224 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5225 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5229 /*-----------------------------------------------------------------*/
5230 /* genMultbits :- multiplication of bits */
5231 /*-----------------------------------------------------------------*/
5233 genMultbits (operand * left,
5238 D (emitcode (";", "genMultbits"));
5240 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5241 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5242 aopOp(result, ic, TRUE, FALSE);
5246 /*-----------------------------------------------------------------*/
5247 /* genMultOneByte : 8*8=8/16 bit multiplication */
5248 /*-----------------------------------------------------------------*/
5250 genMultOneByte (operand * left,
5257 bool runtimeSign, compiletimeSign;
5258 bool lUnsigned, rUnsigned, pushedB;
5260 /* (if two literals: the value is computed before) */
5261 /* if one literal, literal on the right */
5262 if (AOP_TYPE (left) == AOP_LIT)
5267 /* emitcode (";", "swapped left and right"); */
5269 /* if no literal, unsigned on the right: shorter code */
5270 if ( AOP_TYPE (right) != AOP_LIT
5271 && SPEC_USIGN (getSpec (operandType (left))))
5278 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5279 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5283 if ((lUnsigned && rUnsigned)
5284 /* sorry, I don't know how to get size
5285 without calling aopOp (result,...);
5286 see Feature Request */
5287 /* || size == 1 */ ) /* no, this is not a bug; with a 1 byte result there's
5288 no need to take care about the signedness! */
5290 /* just an unsigned 8 * 8 = 8 multiply
5292 /* emitcode (";","unsigned"); */
5293 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
5294 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
5295 emitcode ("mul", "ab");
5298 aopOp (result, ic, TRUE, FALSE);
5299 size = AOP_SIZE (result);
5301 if (size < 1 || size > 2)
5303 /* this should never happen */
5304 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
5305 size, __FILE__, lineno);
5309 aopPut (result, "a", 0);
5312 aopPut (result, "b", 1);
5318 /* we have to do a signed multiply */
5319 /* emitcode (";", "signed"); */
5321 /* now sign adjust for both left & right */
5323 /* let's see what's needed: */
5324 /* apply negative sign during runtime */
5325 runtimeSign = FALSE;
5326 /* negative sign from literals */
5327 compiletimeSign = FALSE;
5331 if (AOP_TYPE(left) == AOP_LIT)
5333 /* signed literal */
5334 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5336 compiletimeSign = TRUE;
5339 /* signed but not literal */
5345 if (AOP_TYPE(right) == AOP_LIT)
5347 /* signed literal */
5348 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5350 compiletimeSign ^= TRUE;
5353 /* signed but not literal */
5357 /* initialize F0, which stores the runtime sign */
5360 if (compiletimeSign)
5361 emitcode ("setb", "F0"); /* set sign flag */
5363 emitcode ("clr", "F0"); /* reset sign flag */
5366 /* save the signs of the operands */
5367 if (AOP_TYPE(right) == AOP_LIT)
5369 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5371 if (!rUnsigned && val < 0)
5372 emitcode ("mov", "b,#!constbyte", -val);
5374 emitcode ("mov", "b,#!constbyte", (unsigned char) val);
5376 else /* ! literal */
5378 if (rUnsigned) /* emitcode (";", "signed"); */
5379 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
5382 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
5383 lbl = newiTempLabel (NULL);
5384 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5385 emitcode ("cpl", "F0"); /* complement sign flag */
5386 emitcode ("cpl", "a"); /* 2's complement */
5387 emitcode ("inc", "a");
5389 emitcode ("mov", "b,a");
5393 if (AOP_TYPE(left) == AOP_LIT)
5395 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5397 if (!lUnsigned && val < 0)
5398 emitcode ("mov", "a,#!constbyte", -val);
5400 emitcode ("mov", "a,#!constbyte", (unsigned char) val);
5402 else /* ! literal */
5404 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
5406 if (!lUnsigned) /* emitcode (";", "signed"); */
5408 lbl = newiTempLabel (NULL);
5409 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5410 emitcode ("cpl", "F0"); /* complement sign flag */
5411 emitcode ("cpl", "a"); /* 2's complement */
5412 emitcode ("inc", "a");
5417 /* now the multiplication */
5418 emitcode ("mul", "ab");
5420 aopOp(result, ic, TRUE, FALSE);
5421 size = AOP_SIZE (result);
5423 if (size < 1 || size > 2)
5425 /* this should never happen */
5426 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
5427 size, __FILE__, lineno);
5431 if (runtimeSign || compiletimeSign)
5433 lbl = newiTempLabel (NULL);
5435 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5436 emitcode ("cpl", "a"); /* lsb 2's complement */
5438 emitcode ("inc", "a"); /* inc doesn't set carry flag */
5441 emitcode ("add", "a,#1"); /* this sets carry flag */
5442 emitcode ("xch", "a,b");
5443 emitcode ("cpl", "a"); /* msb 2's complement */
5444 emitcode ("addc", "a,#0");
5445 emitcode ("xch", "a,b");
5449 aopPut (result, "a", 0);
5452 aopPut (result, "b", 1);
5457 /*-----------------------------------------------------------------*/
5458 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
5459 /*-----------------------------------------------------------------*/
5460 static void genMultTwoByte (operand *left, operand *right,
5461 operand *result, iCode *ic)
5463 sym_link *retype = getSpec(operandType(right));
5464 sym_link *letype = getSpec(operandType(left));
5465 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5468 if (AOP_TYPE (left) == AOP_LIT) {
5473 /* save EA bit in F1 */
5474 lbl = newiTempLabel(NULL);
5475 emitcode ("setb","F1");
5476 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5477 emitcode ("clr","F1");
5480 /* load up MB with right */
5482 emitcode("clr","F0");
5483 if (AOP_TYPE(right) == AOP_LIT) {
5484 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5486 emitcode("setb","F0");
5489 emitcode ("mov","mb,#!constbyte",val & 0xff);
5490 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5492 lbl = newiTempLabel(NULL);
5493 emitcode ("mov","b,%s",aopGet(right,0,FALSE,FALSE,NULL));
5494 emitcode ("mov","a,%s",aopGet(right,1,FALSE,FALSE,NULL));
5495 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5496 emitcode ("xch", "a,b");
5497 emitcode ("cpl","a");
5498 emitcode ("add", "a,#1");
5499 emitcode ("xch", "a,b");
5500 emitcode ("cpl", "a"); // msb
5501 emitcode ("addc", "a,#0");
5502 emitcode ("setb","F0");
5504 emitcode ("mov","mb,b");
5505 emitcode ("mov","mb,a");
5508 emitcode ("mov","mb,%s",aopGet(right,0,FALSE,FALSE,NULL));
5509 emitcode ("mov","mb,%s",aopGet(right,1,FALSE,FALSE,NULL));
5511 /* load up MA with left */
5513 lbl = newiTempLabel(NULL);
5514 emitcode ("mov","b,%s",aopGet(left,0,FALSE,FALSE,NULL));
5515 emitcode ("mov","a,%s",aopGet(left,1,FALSE,FALSE,NULL));
5516 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5517 emitcode ("xch", "a,b");
5518 emitcode ("cpl","a");
5519 emitcode ("add", "a,#1");
5520 emitcode ("xch", "a,b");
5521 emitcode ("cpl", "a"); // msb
5522 emitcode ("addc","a,#0");
5523 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5524 emitcode ("setb","F0");
5526 emitcode ("mov","ma,b");
5527 emitcode ("mov","ma,a");
5529 emitcode ("mov","ma,%s",aopGet(left,0,FALSE,FALSE,NULL));
5530 emitcode ("mov","ma,%s",aopGet(left,1,FALSE,FALSE,NULL));
5532 /* wait for multiplication to finish */
5533 lbl = newiTempLabel(NULL);
5535 emitcode("mov","a,mcnt1");
5536 emitcode("anl","a,#!constbyte",0x80);
5537 emitcode("jnz","!tlabel",lbl->key+100);
5539 freeAsmop (left, NULL, ic, TRUE);
5540 freeAsmop (right, NULL, ic,TRUE);
5541 aopOp(result, ic, TRUE, FALSE);
5543 /* if unsigned then simple */
5545 emitcode ("mov","a,ma");
5546 if (AOP_SIZE(result) >= 4) aopPut(result,"a",3);
5547 emitcode ("mov","a,ma");
5548 if (AOP_SIZE(result) >= 3) aopPut(result,"a",2);
5549 aopPut(result,"ma",1);
5550 aopPut(result,"ma",0);
5552 emitcode("push","ma");
5553 emitcode("push","ma");
5554 emitcode("push","ma");
5556 /* negate result if needed */
5557 lbl = newiTempLabel(NULL);
5558 emitcode("jnb","F0,!tlabel",lbl->key+100);
5559 emitcode("cpl","a");
5560 emitcode("add","a,#1");
5562 if (AOP_TYPE(result) == AOP_ACC)
5564 D (emitcode(";", "ACC special case."));
5565 /* We know result is the only live aop, and
5566 * it's obviously not a DPTR2, so AP is available.
5568 emitcode("mov", "%s,acc", DP2_RESULT_REG);
5572 aopPut(result,"a",0);
5575 emitcode("pop","acc");
5576 lbl = newiTempLabel(NULL);
5577 emitcode("jnb","F0,!tlabel",lbl->key+100);
5578 emitcode("cpl","a");
5579 emitcode("addc","a,#0");
5581 aopPut(result,"a",1);
5582 emitcode("pop","acc");
5583 if (AOP_SIZE(result) >= 3) {
5584 lbl = newiTempLabel(NULL);
5585 emitcode("jnb","F0,!tlabel",lbl->key+100);
5586 emitcode("cpl","a");
5587 emitcode("addc","a,#0");
5589 aopPut(result,"a",2);
5591 emitcode("pop","acc");
5592 if (AOP_SIZE(result) >= 4) {
5593 lbl = newiTempLabel(NULL);
5594 emitcode("jnb","F0,!tlabel",lbl->key+100);
5595 emitcode("cpl","a");
5596 emitcode("addc","a,#0");
5598 aopPut(result,"a",3);
5600 if (AOP_TYPE(result) == AOP_ACC)
5602 /* We stashed the result away above. */
5603 emitcode("mov", "acc,%s", DP2_RESULT_REG);
5607 freeAsmop (result, NULL, ic, TRUE);
5609 /* restore EA bit in F1 */
5610 lbl = newiTempLabel(NULL);
5611 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5612 emitcode ("setb","EA");
5617 /*-----------------------------------------------------------------*/
5618 /* genMult - generates code for multiplication */
5619 /*-----------------------------------------------------------------*/
5621 genMult (iCode * ic)
5623 operand *left = IC_LEFT (ic);
5624 operand *right = IC_RIGHT (ic);
5625 operand *result = IC_RESULT (ic);
5627 D (emitcode (";", "genMult"));
5629 /* assign the asmops */
5632 /* special cases first */
5634 if (AOP_TYPE (left) == AOP_CRY &&
5635 AOP_TYPE (right) == AOP_CRY)
5637 genMultbits (left, right, result, ic);
5641 /* if both are of size == 1 */
5642 if (AOP_SIZE (left) == 1 &&
5643 AOP_SIZE (right) == 1)
5645 genMultOneByte (left, right, result, ic);
5649 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5650 /* use the ds390 ARITHMETIC accel UNIT */
5651 genMultTwoByte (left, right, result, ic);
5654 /* should have been converted to function call */
5658 freeAsmop (result, NULL, ic, TRUE);
5659 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5660 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5663 /*-----------------------------------------------------------------*/
5664 /* genDivbits :- division of bits */
5665 /*-----------------------------------------------------------------*/
5667 genDivbits (operand * left,
5675 D(emitcode ("; genDivbits",""));
5679 /* the result must be bit */
5680 LOAD_AB_FOR_DIV (left, right, l);
5681 emitcode ("div", "ab");
5682 emitcode ("rrc", "a");
5683 aopOp(result, ic, TRUE, FALSE);
5687 aopPut (result, "c", 0);
5690 /*-----------------------------------------------------------------*/
5691 /* genDivOneByte : 8 bit division */
5692 /*-----------------------------------------------------------------*/
5694 genDivOneByte (operand * left,
5699 bool lUnsigned, rUnsigned, pushedB;
5700 bool runtimeSign, compiletimeSign;
5705 D(emitcode ("; genDivOneByte",""));
5708 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5709 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5713 /* signed or unsigned */
5714 if (lUnsigned && rUnsigned)
5716 /* unsigned is easy */
5717 LOAD_AB_FOR_DIV (left, right, l);
5718 emitcode ("div", "ab");
5721 aopOp (result, ic, TRUE, FALSE);
5722 aopPut (result, "a", 0);
5725 size = AOP_SIZE (result) - 1;
5728 aopPut (result, zero, offset++);
5734 /* signed is a little bit more difficult */
5736 /* now sign adjust for both left & right */
5738 /* let's see what's needed: */
5739 /* apply negative sign during runtime */
5740 runtimeSign = FALSE;
5741 /* negative sign from literals */
5742 compiletimeSign = FALSE;
5746 if (AOP_TYPE(left) == AOP_LIT)
5748 /* signed literal */
5749 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5751 compiletimeSign = TRUE;
5754 /* signed but not literal */
5760 if (AOP_TYPE(right) == AOP_LIT)
5762 /* signed literal */
5763 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5765 compiletimeSign ^= TRUE;
5768 /* signed but not literal */
5772 /* initialize F0, which stores the runtime sign */
5775 if (compiletimeSign)
5776 emitcode ("setb", "F0"); /* set sign flag */
5778 emitcode ("clr", "F0"); /* reset sign flag */
5781 /* save the signs of the operands */
5782 if (AOP_TYPE(right) == AOP_LIT)
5784 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5786 if (!rUnsigned && val < 0)
5787 emitcode ("mov", "b,#0x%02x", -val);
5789 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5791 else /* ! literal */
5794 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
5797 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
5798 lbl = newiTempLabel (NULL);
5799 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5800 emitcode ("cpl", "F0"); /* complement sign flag */
5801 emitcode ("cpl", "a"); /* 2's complement */
5802 emitcode ("inc", "a");
5804 emitcode ("mov", "b,a");
5808 if (AOP_TYPE(left) == AOP_LIT)
5810 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5812 if (!lUnsigned && val < 0)
5813 emitcode ("mov", "a,#0x%02x", -val);
5815 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5817 else /* ! literal */
5819 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
5823 lbl = newiTempLabel (NULL);
5824 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5825 emitcode ("cpl", "F0"); /* complement sign flag */
5826 emitcode ("cpl", "a"); /* 2's complement */
5827 emitcode ("inc", "a");
5832 /* now the division */
5833 emitcode ("nop", "; workaround for DS80C390 div bug.");
5834 emitcode ("div", "ab");
5836 if (runtimeSign || compiletimeSign)
5838 lbl = newiTempLabel (NULL);
5840 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5841 emitcode ("cpl", "a"); /* lsb 2's complement */
5842 emitcode ("inc", "a");
5846 aopOp (result, ic, TRUE, FALSE);
5847 size = AOP_SIZE (result) - 1;
5851 /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
5852 then the result will be in b, a */
5853 emitcode ("mov", "b,a"); /* 1 */
5854 /* msb is 0x00 or 0xff depending on the sign */
5857 emitcode ("mov", "c,F0");
5858 emitcode ("subb", "a,acc");
5859 emitcode ("xch", "a,b"); /* 2 */
5861 aopPut (result, "b", offset++); /* write msb's */
5863 else /* compiletimeSign */
5865 aopPut (result, "#0xff", offset++); /* write msb's */
5867 aopPut (result, "a", 0); /* 3: write lsb */
5872 aopOp(result, ic, TRUE, FALSE);
5873 size = AOP_SIZE (result) - 1;
5875 aopPut (result, "a", 0);
5877 aopPut (result, zero, offset++);
5883 /*-----------------------------------------------------------------*/
5884 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
5885 /*-----------------------------------------------------------------*/
5886 static void genDivTwoByte (operand *left, operand *right,
5887 operand *result, iCode *ic)
5889 sym_link *retype = getSpec(operandType(right));
5890 sym_link *letype = getSpec(operandType(left));
5891 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5894 /* save EA bit in F1 */
5895 lbl = newiTempLabel(NULL);
5896 emitcode ("setb","F1");
5897 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5898 emitcode ("clr","F1");
5901 /* load up MA with left */
5903 emitcode("clr","F0");
5904 lbl = newiTempLabel(NULL);
5905 emitcode ("mov","b,%s",aopGet(left,0,FALSE,FALSE,NULL));
5906 emitcode ("mov","a,%s",aopGet(left,1,FALSE,FALSE,NULL));
5907 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5908 emitcode ("xch", "a,b");
5909 emitcode ("cpl","a");
5910 emitcode ("add", "a,#1");
5911 emitcode ("xch", "a,b");
5912 emitcode ("cpl", "a"); // msb
5913 emitcode ("addc","a,#0");
5914 emitcode ("setb","F0");
5916 emitcode ("mov","ma,b");
5917 emitcode ("mov","ma,a");
5919 emitcode ("mov","ma,%s",aopGet(left,0,FALSE,FALSE,NULL));
5920 emitcode ("mov","ma,%s",aopGet(left,1,FALSE,FALSE,NULL));
5923 /* load up MB with right */
5925 if (AOP_TYPE(right) == AOP_LIT) {
5926 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5928 lbl = newiTempLabel(NULL);
5929 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5930 emitcode("setb","F0");
5934 emitcode ("mov","mb,#!constbyte",val & 0xff);
5935 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5937 lbl = newiTempLabel(NULL);
5938 emitcode ("mov","b,%s",aopGet(right,0,FALSE,FALSE,NULL));
5939 emitcode ("mov","a,%s",aopGet(right,1,FALSE,FALSE,NULL));
5940 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5941 emitcode ("xch", "a,b");
5942 emitcode ("cpl","a");
5943 emitcode ("add", "a,#1");
5944 emitcode ("xch", "a,b");
5945 emitcode ("cpl", "a"); // msb
5946 emitcode ("addc", "a,#0");
5947 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5948 emitcode ("setb","F0");
5950 emitcode ("mov","mb,b");
5951 emitcode ("mov","mb,a");
5954 emitcode ("mov","mb,%s",aopGet(right,0,FALSE,FALSE,NULL));
5955 emitcode ("mov","mb,%s",aopGet(right,1,FALSE,FALSE,NULL));
5958 /* wait for multiplication to finish */
5959 lbl = newiTempLabel(NULL);
5961 emitcode("mov","a,mcnt1");
5962 emitcode("anl","a,#!constbyte",0x80);
5963 emitcode("jnz","!tlabel",lbl->key+100);
5965 freeAsmop (left, NULL, ic, TRUE);
5966 freeAsmop (right, NULL, ic,TRUE);
5967 aopOp(result, ic, TRUE, FALSE);
5969 /* if unsigned then simple */
5971 aopPut(result,"ma",1);
5972 aopPut(result,"ma",0);
5974 emitcode("push","ma");
5976 /* negate result if needed */
5977 lbl = newiTempLabel(NULL);
5978 emitcode("jnb","F0,!tlabel",lbl->key+100);
5979 emitcode("cpl","a");
5980 emitcode("add","a,#1");
5982 aopPut(result,"a",0);
5983 emitcode("pop","acc");
5984 lbl = newiTempLabel(NULL);
5985 emitcode("jnb","F0,!tlabel",lbl->key+100);
5986 emitcode("cpl","a");
5987 emitcode("addc","a,#0");
5989 aopPut(result,"a",1);
5991 freeAsmop (result, NULL, ic, TRUE);
5992 /* restore EA bit in F1 */
5993 lbl = newiTempLabel(NULL);
5994 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5995 emitcode ("setb","EA");
6000 /*-----------------------------------------------------------------*/
6001 /* genDiv - generates code for division */
6002 /*-----------------------------------------------------------------*/
6006 operand *left = IC_LEFT (ic);
6007 operand *right = IC_RIGHT (ic);
6008 operand *result = IC_RESULT (ic);
6010 D (emitcode (";", "genDiv"));
6012 /* assign the amsops */
6015 /* special cases first */
6017 if (AOP_TYPE (left) == AOP_CRY &&
6018 AOP_TYPE (right) == AOP_CRY)
6020 genDivbits (left, right, result, ic);
6024 /* if both are of size == 1 */
6025 if (AOP_SIZE (left) == 1 &&
6026 AOP_SIZE (right) == 1)
6028 genDivOneByte (left, right, result, ic);
6032 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
6033 /* use the ds390 ARITHMETIC accel UNIT */
6034 genDivTwoByte (left, right, result, ic);
6037 /* should have been converted to function call */
6040 freeAsmop (result, NULL, ic, TRUE);
6041 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6042 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6045 /*-----------------------------------------------------------------*/
6046 /* genModbits :- modulus of bits */
6047 /*-----------------------------------------------------------------*/
6049 genModbits (operand * left,
6057 D (emitcode (";", "genModbits"));
6061 /* the result must be bit */
6062 LOAD_AB_FOR_DIV (left, right, l);
6063 emitcode ("div", "ab");
6064 emitcode ("mov", "a,b");
6065 emitcode ("rrc", "a");
6066 aopOp(result, ic, TRUE, FALSE);
6070 aopPut (result, "c", 0);
6073 /*-----------------------------------------------------------------*/
6074 /* genModOneByte : 8 bit modulus */
6075 /*-----------------------------------------------------------------*/
6077 genModOneByte (operand * left,
6082 bool lUnsigned, rUnsigned, pushedB;
6083 bool runtimeSign, compiletimeSign;
6088 D (emitcode (";", "genModOneByte"));
6091 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
6092 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
6096 /* signed or unsigned */
6097 if (lUnsigned && rUnsigned)
6099 /* unsigned is easy */
6100 LOAD_AB_FOR_DIV (left, right, l);
6101 emitcode ("div", "ab");
6102 aopOp (result, ic, TRUE, FALSE);
6103 aopPut (result, "b", 0);
6105 for (size = AOP_SIZE (result) - 1; size--;)
6106 aopPut (result, zero, offset++);
6112 /* signed is a little bit more difficult */
6114 /* now sign adjust for both left & right */
6116 /* modulus: sign of the right operand has no influence on the result! */
6117 if (AOP_TYPE(right) == AOP_LIT)
6119 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
6121 if (!rUnsigned && val < 0)
6122 emitcode ("mov", "b,#0x%02x", -val);
6124 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
6126 else /* not literal */
6129 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
6132 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
6133 lbl = newiTempLabel (NULL);
6134 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
6135 emitcode ("cpl", "a"); /* 2's complement */
6136 emitcode ("inc", "a");
6138 emitcode ("mov", "b,a");
6142 /* let's see what's needed: */
6143 /* apply negative sign during runtime */
6144 runtimeSign = FALSE;
6145 /* negative sign from literals */
6146 compiletimeSign = FALSE;
6148 /* sign adjust left side */
6149 if (AOP_TYPE(left) == AOP_LIT)
6151 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
6153 if (!lUnsigned && val < 0)
6155 compiletimeSign = TRUE; /* set sign flag */
6156 emitcode ("mov", "a,#0x%02x", -val);
6159 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
6161 else /* ! literal */
6163 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
6168 emitcode ("clr", "F0"); /* clear sign flag */
6170 lbl = newiTempLabel (NULL);
6171 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
6172 emitcode ("setb", "F0"); /* set sign flag */
6173 emitcode ("cpl", "a"); /* 2's complement */
6174 emitcode ("inc", "a");
6179 /* now the modulus */
6180 emitcode ("nop", "; workaround for DS80C390 div bug.");
6181 emitcode ("div", "ab");
6183 if (runtimeSign || compiletimeSign)
6185 emitcode ("mov", "a,b");
6186 lbl = newiTempLabel (NULL);
6188 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
6189 emitcode ("cpl", "a"); /* lsb 2's complement */
6190 emitcode ("inc", "a");
6194 aopOp (result, ic, TRUE, FALSE);
6195 size = AOP_SIZE (result) - 1;
6199 /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
6200 then the result will be in b, a */
6201 emitcode ("mov", "b,a"); /* 1 */
6202 /* msb is 0x00 or 0xff depending on the sign */
6205 emitcode ("mov", "c,F0");
6206 emitcode ("subb", "a,acc");
6207 emitcode ("xch", "a,b"); /* 2 */
6209 aopPut (result, "b", offset++); /* write msb's */
6211 else /* compiletimeSign */
6213 aopPut (result, "#0xff", offset++); /* write msb's */
6215 aopPut (result, "a", 0); /* 3: write lsb */
6220 aopOp(result, ic, TRUE, FALSE);
6221 size = AOP_SIZE (result) - 1;
6223 aopPut (result, "b", 0);
6225 aopPut (result, zero, offset++);
6231 /*-----------------------------------------------------------------*/
6232 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
6233 /*-----------------------------------------------------------------*/
6234 static void genModTwoByte (operand *left, operand *right,
6235 operand *result, iCode *ic)
6237 sym_link *retype = getSpec(operandType(right));
6238 sym_link *letype = getSpec(operandType(left));
6239 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
6242 /* load up MA with left */
6243 /* save EA bit in F1 */
6244 lbl = newiTempLabel(NULL);
6245 emitcode ("setb","F1");
6246 emitcode ("jbc","EA,!tlabel",lbl->key+100);
6247 emitcode ("clr","F1");
6251 lbl = newiTempLabel(NULL);
6252 emitcode ("mov","b,%s",aopGet(left,0,FALSE,FALSE,NULL));
6253 emitcode ("mov","a,%s",aopGet(left,1,FALSE,FALSE,NULL));
6254 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
6255 emitcode ("xch", "a,b");
6256 emitcode ("cpl","a");
6257 emitcode ("add", "a,#1");
6258 emitcode ("xch", "a,b");
6259 emitcode ("cpl", "a"); // msb
6260 emitcode ("addc","a,#0");
6262 emitcode ("mov","ma,b");
6263 emitcode ("mov","ma,a");
6265 emitcode ("mov","ma,%s",aopGet(left,0,FALSE,FALSE,NULL));
6266 emitcode ("mov","ma,%s",aopGet(left,1,FALSE,FALSE,NULL));
6269 /* load up MB with right */
6271 if (AOP_TYPE(right) == AOP_LIT) {
6272 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
6276 emitcode ("mov","mb,#!constbyte",val & 0xff);
6277 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
6279 lbl = newiTempLabel(NULL);
6280 emitcode ("mov","b,%s",aopGet(right,0,FALSE,FALSE,NULL));
6281 emitcode ("mov","a,%s",aopGet(right,1,FALSE,FALSE,NULL));
6282 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
6283 emitcode ("xch", "a,b");
6284 emitcode ("cpl","a");
6285 emitcode ("add", "a,#1");
6286 emitcode ("xch", "a,b");
6287 emitcode ("cpl", "a"); // msb
6288 emitcode ("addc", "a,#0");
6290 emitcode ("mov","mb,b");
6291 emitcode ("mov","mb,a");
6294 emitcode ("mov","mb,%s",aopGet(right,0,FALSE,FALSE,NULL));
6295 emitcode ("mov","mb,%s",aopGet(right,1,FALSE,FALSE,NULL));
6298 /* wait for multiplication to finish */
6299 lbl = newiTempLabel(NULL);
6301 emitcode("mov","a,mcnt1");
6302 emitcode("anl","a,#!constbyte",0x80);
6303 emitcode("jnz","!tlabel",lbl->key+100);
6305 freeAsmop (left, NULL, ic, TRUE);
6306 freeAsmop (right, NULL, ic,TRUE);
6307 aopOp(result, ic, TRUE, FALSE);
6309 aopPut(result,"mb",1);
6310 aopPut(result,"mb",0);
6311 freeAsmop (result, NULL, ic, TRUE);
6313 /* restore EA bit in F1 */
6314 lbl = newiTempLabel(NULL);
6315 emitcode ("jnb","F1,!tlabel",lbl->key+100);
6316 emitcode ("setb","EA");
6320 /*-----------------------------------------------------------------*/
6321 /* genMod - generates code for division */
6322 /*-----------------------------------------------------------------*/
6326 operand *left = IC_LEFT (ic);
6327 operand *right = IC_RIGHT (ic);
6328 operand *result = IC_RESULT (ic);
6330 D (emitcode (";", "genMod"));
6332 /* assign the asmops */
6335 /* special cases first */
6337 if (AOP_TYPE (left) == AOP_CRY &&
6338 AOP_TYPE (right) == AOP_CRY)
6340 genModbits (left, right, result, ic);
6344 /* if both are of size == 1 */
6345 if (AOP_SIZE (left) == 1 &&
6346 AOP_SIZE (right) == 1)
6348 genModOneByte (left, right, result, ic);
6352 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
6353 /* use the ds390 ARITHMETIC accel UNIT */
6354 genModTwoByte (left, right, result, ic);
6358 /* should have been converted to function call */
6362 freeAsmop (result, NULL, ic, TRUE);
6363 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6364 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6367 /*-----------------------------------------------------------------*/
6368 /* genIfxJump :- will create a jump depending on the ifx */
6369 /*-----------------------------------------------------------------*/
6371 genIfxJump (iCode * ic, char *jval)
6374 symbol *tlbl = newiTempLabel (NULL);
6377 D (emitcode (";", "genIfxJump"));
6379 /* if true label then we jump if condition
6383 jlbl = IC_TRUE (ic);
6384 inst = ((strcmp (jval, "a") == 0 ? "jz" :
6385 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
6389 /* false label is present */
6390 jlbl = IC_FALSE (ic);
6391 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
6392 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
6394 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
6395 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
6397 emitcode (inst, "!tlabel", tlbl->key + 100);
6398 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
6401 /* mark the icode as generated */
6405 /*-----------------------------------------------------------------*/
6406 /* genCmp :- greater or less than comparison */
6407 /*-----------------------------------------------------------------*/
6409 genCmp (operand * left, operand * right,
6410 iCode * ic, iCode * ifx, int sign)
6412 int size, offset = 0;
6413 unsigned long lit = 0L;
6416 D (emitcode (";", "genCmp"));
6418 result = IC_RESULT (ic);
6420 /* if left & right are bit variables */
6421 if (AOP_TYPE (left) == AOP_CRY &&
6422 AOP_TYPE (right) == AOP_CRY)
6424 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6425 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6429 /* subtract right from left if at the
6430 end the carry flag is set then we know that
6431 left is greater than right */
6432 size = max (AOP_SIZE (left), AOP_SIZE (right));
6434 /* if unsigned char cmp with lit, do cjne left,#right,zz */
6435 if ((size == 1) && !sign &&
6436 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
6438 symbol *lbl = newiTempLabel (NULL);
6439 emitcode ("cjne", "%s,%s,!tlabel",
6440 aopGet (left, offset, FALSE, FALSE, NULL),
6441 aopGet (right, offset, FALSE, FALSE, NULL),
6447 if (AOP_TYPE (right) == AOP_LIT)
6449 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6450 /* optimize if(x < 0) or if(x >= 0) */
6459 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
6461 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6462 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6464 aopOp (result, ic, FALSE, FALSE);
6466 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
6468 freeAsmop (result, NULL, ic, TRUE);
6469 genIfxJump (ifx, "acc.7");
6474 emitcode ("rlc", "a");
6476 goto release_freedLR;
6484 // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
6485 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
6486 // emitcode (";", "genCmp #2");
6487 if (sign && (size == 0))
6489 // emitcode (";", "genCmp #3");
6490 emitcode ("xrl", "a,#!constbyte",0x80);
6491 if (AOP_TYPE (right) == AOP_LIT)
6493 unsigned long lit = (unsigned long)
6494 floatFromVal (AOP (right)->aopu.aop_lit);
6495 // emitcode (";", "genCmp #3.1");
6496 emitcode ("subb", "a,#!constbyte",
6497 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
6501 // emitcode (";", "genCmp #3.2");
6503 MOVB (aopGet (right, offset++, FALSE, FALSE, "b"));
6504 saveAccWarn = DEFAULT_ACC_WARNING;
6505 emitcode ("xrl", "b,#!constbyte",0x80);
6506 emitcode ("subb", "a,b");
6513 // emitcode (";", "genCmp #4");
6515 s = aopGet (right, offset++, FALSE, FALSE, "b");
6516 saveAccWarn = DEFAULT_ACC_WARNING;
6518 emitcode ("subb", "a,%s", s);
6525 /* Don't need the left & right operands any more; do need the result. */
6526 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6527 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6529 aopOp (result, ic, FALSE, FALSE);
6533 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6539 /* if the result is used in the next
6540 ifx conditional branch then generate
6541 code a little differently */
6544 genIfxJump (ifx, "c");
6550 /* leave the result in acc */
6552 freeAsmop (result, NULL, ic, TRUE);
6555 /*-----------------------------------------------------------------*/
6556 /* genCmpGt :- greater than comparison */
6557 /*-----------------------------------------------------------------*/
6559 genCmpGt (iCode * ic, iCode * ifx)
6561 operand *left, *right;
6562 sym_link *letype, *retype;
6565 D (emitcode (";", "genCmpGt"));
6567 left = IC_LEFT (ic);
6568 right = IC_RIGHT (ic);
6570 letype = getSpec (operandType (left));
6571 retype = getSpec (operandType (right));
6572 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6574 /* assign the left & right amsops */
6577 genCmp (right, left, ic, ifx, sign);
6580 /*-----------------------------------------------------------------*/
6581 /* genCmpLt - less than comparisons */
6582 /*-----------------------------------------------------------------*/
6584 genCmpLt (iCode * ic, iCode * ifx)
6586 operand *left, *right;
6587 sym_link *letype, *retype;
6590 D (emitcode (";", "genCmpLt"));
6592 left = IC_LEFT (ic);
6593 right = IC_RIGHT (ic);
6595 letype = getSpec (operandType (left));
6596 retype = getSpec (operandType (right));
6597 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6599 /* assign the left & right amsops */
6602 genCmp (left, right, ic, ifx, sign);
6605 /*-----------------------------------------------------------------*/
6606 /* gencjneshort - compare and jump if not equal */
6607 /*-----------------------------------------------------------------*/
6609 gencjneshort (operand * left, operand * right, symbol * lbl)
6611 int size = max (AOP_SIZE (left), AOP_SIZE (right));
6613 unsigned long lit = 0L;
6615 D (emitcode (";", "gencjneshort"));
6617 /* if the left side is a literal or
6618 if the right is in a pointer register and left
6620 if ((AOP_TYPE (left) == AOP_LIT) ||
6621 (AOP_TYPE (left) == AOP_IMMD) ||
6622 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6629 if (AOP_TYPE (right) == AOP_LIT)
6630 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6632 if (opIsGptr (left) || opIsGptr (right))
6634 /* We are comparing a generic pointer to something.
6635 * Exclude the generic type byte from the comparison.
6638 D (emitcode (";", "cjneshort: generic ptr special case."););
6642 /* if the right side is a literal then anything goes */
6643 if (AOP_TYPE (right) == AOP_LIT &&
6644 AOP_TYPE (left) != AOP_DIR)
6648 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
6649 emitcode ("cjne", "a,%s,!tlabel",
6650 aopGet (right, offset, FALSE, FALSE, NULL),
6656 /* if the right side is in a register or in direct space or
6657 if the left is a pointer register & right is not */
6658 else if (AOP_TYPE (right) == AOP_REG ||
6659 AOP_TYPE (right) == AOP_DIR ||
6660 AOP_TYPE (right) == AOP_LIT ||
6661 AOP_TYPE (right) == AOP_IMMD ||
6662 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6663 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6667 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
6668 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6669 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6670 emitcode ("jnz", "!tlabel", lbl->key + 100);
6672 emitcode ("cjne", "a,%s,!tlabel",
6673 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG),
6680 /* right is a pointer reg need both a & b */
6683 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
6684 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
6685 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
6691 /*-----------------------------------------------------------------*/
6692 /* gencjne - compare and jump if not equal */
6693 /*-----------------------------------------------------------------*/
6695 gencjne (operand * left, operand * right, symbol * lbl)
6697 symbol *tlbl = newiTempLabel (NULL);
6699 D (emitcode (";", "gencjne"));
6701 gencjneshort (left, right, lbl);
6703 emitcode ("mov", "a,%s", one);
6704 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
6706 emitcode ("clr", "a");
6710 /*-----------------------------------------------------------------*/
6711 /* genCmpEq - generates code for equal to */
6712 /*-----------------------------------------------------------------*/
6714 genCmpEq (iCode * ic, iCode * ifx)
6716 operand *left, *right, *result;
6718 D (emitcode (";", "genCmpEq"));
6721 AOP_SET_LOCALS (ic);
6723 /* if literal, literal on the right or
6724 if the right is in a pointer register and left
6726 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6727 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6729 operand *t = IC_RIGHT (ic);
6730 IC_RIGHT (ic) = IC_LEFT (ic);
6734 if (ifx && /* !AOP_SIZE(result) */
6735 OP_SYMBOL (result) &&
6736 OP_SYMBOL (result)->regType == REG_CND)
6739 /* if they are both bit variables */
6740 if (AOP_TYPE (left) == AOP_CRY &&
6741 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6743 if (AOP_TYPE (right) == AOP_LIT)
6745 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6748 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6749 emitcode ("cpl", "c");
6753 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6757 emitcode ("clr", "c");
6759 /* AOP_TYPE(right) == AOP_CRY */
6763 symbol *lbl = newiTempLabel (NULL);
6764 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6765 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6766 emitcode ("cpl", "c");
6769 /* if true label then we jump if condition
6771 tlbl = newiTempLabel (NULL);
6774 emitcode ("jnc", "!tlabel", tlbl->key + 100);
6775 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6779 emitcode ("jc", "!tlabel", tlbl->key + 100);
6780 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6786 tlbl = newiTempLabel (NULL);
6787 gencjneshort (left, right, tlbl);
6790 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6795 symbol *lbl = newiTempLabel (NULL);
6796 emitcode ("sjmp", "!tlabel", lbl->key + 100);
6798 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6802 /* mark the icode as generated */
6805 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6806 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6810 /* if they are both bit variables */
6811 if (AOP_TYPE (left) == AOP_CRY &&
6812 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6814 if (AOP_TYPE (right) == AOP_LIT)
6816 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6819 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6820 emitcode ("cpl", "c");
6824 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6828 emitcode ("clr", "c");
6830 /* AOP_TYPE(right) == AOP_CRY */
6834 symbol *lbl = newiTempLabel (NULL);
6835 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6836 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6837 emitcode ("cpl", "c");
6841 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6842 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6844 aopOp (result, ic, TRUE, FALSE);
6847 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6854 genIfxJump (ifx, "c");
6857 /* if the result is used in an arithmetic operation
6858 then put the result in place */
6863 gencjne (left, right, newiTempLabel (NULL));
6865 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6866 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6868 aopOp (result, ic, TRUE, FALSE);
6870 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6872 aopPut (result, "a", 0);
6877 genIfxJump (ifx, "a");
6880 /* if the result is used in an arithmetic operation
6881 then put the result in place */
6882 if (AOP_TYPE (result) != AOP_CRY)
6884 /* leave the result in acc */
6888 freeAsmop (result, NULL, ic, TRUE);
6891 /*-----------------------------------------------------------------*/
6892 /* ifxForOp - returns the icode containing the ifx for operand */
6893 /*-----------------------------------------------------------------*/
6895 ifxForOp (operand * op, iCode * ic)
6897 /* if true symbol then needs to be assigned */
6898 if (IS_TRUE_SYMOP (op))
6901 /* if this has register type condition and
6902 the next instruction is ifx with the same operand
6903 and live to of the operand is upto the ifx only then */
6905 ic->next->op == IFX &&
6906 IC_COND (ic->next)->key == op->key &&
6907 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6913 /*-----------------------------------------------------------------*/
6914 /* hasInc - operand is incremented before any other use */
6915 /*-----------------------------------------------------------------*/
6917 hasInc (operand *op, iCode *ic, int osize)
6919 sym_link *type = operandType(op);
6920 sym_link *retype = getSpec (type);
6921 iCode *lic = ic->next;
6924 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6925 if (!IS_SYMOP(op)) return NULL;
6927 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6928 if (IS_AGGREGATE(type->next)) return NULL;
6929 if (osize != (isize = getSize(type->next))) return NULL;
6932 /* if operand of the form op = op + <sizeof *op> */
6933 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6934 isOperandEqual(IC_RESULT(lic),op) &&
6935 isOperandLiteral(IC_RIGHT(lic)) &&
6936 operandLitValue(IC_RIGHT(lic)) == isize) {
6939 /* if the operand used or deffed */
6940 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6943 /* if GOTO or IFX */
6944 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6950 /*-----------------------------------------------------------------*/
6951 /* genAndOp - for && operation */
6952 /*-----------------------------------------------------------------*/
6954 genAndOp (iCode * ic)
6956 operand *left, *right, *result;
6959 D (emitcode (";", "genAndOp"));
6961 /* note here that && operations that are in an
6962 if statement are taken away by backPatchLabels
6963 only those used in arthmetic operations remain */
6965 AOP_SET_LOCALS (ic);
6967 /* if both are bit variables */
6968 if (AOP_TYPE (left) == AOP_CRY &&
6969 AOP_TYPE (right) == AOP_CRY)
6971 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6972 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6973 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6974 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6976 aopOp (result,ic,FALSE, FALSE);
6981 tlbl = newiTempLabel (NULL);
6983 emitcode ("jz", "!tlabel", tlbl->key + 100);
6986 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6987 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6989 aopOp (result,ic,FALSE, FALSE);
6993 freeAsmop (result, NULL, ic, TRUE);
6997 /*-----------------------------------------------------------------*/
6998 /* genOrOp - for || operation */
6999 /*-----------------------------------------------------------------*/
7001 genOrOp (iCode * ic)
7003 operand *left, *right, *result;
7006 D (emitcode (";", "genOrOp"));
7008 /* note here that || operations that are in an
7009 if statement are taken away by backPatchLabels
7010 only those used in arthmetic operations remain */
7012 AOP_SET_LOCALS (ic);
7014 /* if both are bit variables */
7015 if (AOP_TYPE (left) == AOP_CRY &&
7016 AOP_TYPE (right) == AOP_CRY)
7018 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7019 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
7020 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7021 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7023 aopOp (result,ic,FALSE, FALSE);
7029 tlbl = newiTempLabel (NULL);
7031 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7034 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7035 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7037 aopOp (result,ic,FALSE, FALSE);
7042 freeAsmop (result, NULL, ic, TRUE);
7045 /*-----------------------------------------------------------------*/
7046 /* isLiteralBit - test if lit == 2^n */
7047 /*-----------------------------------------------------------------*/
7049 isLiteralBit (unsigned long lit)
7051 unsigned long pw[32] =
7052 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
7053 0x100L, 0x200L, 0x400L, 0x800L,
7054 0x1000L, 0x2000L, 0x4000L, 0x8000L,
7055 0x10000L, 0x20000L, 0x40000L, 0x80000L,
7056 0x100000L, 0x200000L, 0x400000L, 0x800000L,
7057 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
7058 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
7061 for (idx = 0; idx < 32; idx++)
7067 /*-----------------------------------------------------------------*/
7068 /* continueIfTrue - */
7069 /*-----------------------------------------------------------------*/
7071 continueIfTrue (iCode * ic)
7074 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
7078 /*-----------------------------------------------------------------*/
7080 /*-----------------------------------------------------------------*/
7082 jumpIfTrue (iCode * ic)
7085 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
7089 /*-----------------------------------------------------------------*/
7090 /* jmpTrueOrFalse - */
7091 /*-----------------------------------------------------------------*/
7093 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
7095 // ugly but optimized by peephole
7098 symbol *nlbl = newiTempLabel (NULL);
7099 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
7101 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
7106 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
7112 // Generate code to perform a bit-wise logic operation
7113 // on two operands in far space (assumed to already have been
7114 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
7115 // in far space. This requires pushing the result on the stack
7116 // then popping it into the result.
7118 genFarFarLogicOp(iCode *ic, char *logicOp)
7120 int size, resultSize, compSize;
7124 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
7125 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
7126 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
7128 _startLazyDPSEvaluation();
7129 for (size = compSize; (size--); offset++)
7131 MOVA (aopGet (IC_LEFT(ic), offset, FALSE, FALSE, NULL));
7132 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
7133 MOVA (aopGet (IC_RIGHT(ic), offset, FALSE, FALSE, NULL));
7135 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
7136 emitcode ("push", "acc");
7138 _endLazyDPSEvaluation();
7140 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7141 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7142 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
7144 resultSize = AOP_SIZE(IC_RESULT(ic));
7146 ADJUST_PUSHED_RESULT(compSize, resultSize);
7148 _startLazyDPSEvaluation();
7151 emitcode ("pop", "acc");
7152 aopPut (IC_RESULT (ic), "a", compSize);
7154 _endLazyDPSEvaluation();
7155 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
7159 /*-----------------------------------------------------------------*/
7160 /* genAnd - code for and */
7161 /*-----------------------------------------------------------------*/
7163 genAnd (iCode * ic, iCode * ifx)
7165 operand *left, *right, *result;
7166 int size, offset = 0;
7167 unsigned long lit = 0L;
7172 D (emitcode (";", "genAnd"));
7174 AOP_OP_3_NOFATAL (ic, pushResult);
7175 AOP_SET_LOCALS (ic);
7179 genFarFarLogicOp(ic, "anl");
7184 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7186 AOP_TYPE (left), AOP_TYPE (right));
7187 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7189 AOP_SIZE (left), AOP_SIZE (right));
7192 /* if left is a literal & right is not then exchange them */
7193 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7194 #ifdef LOGIC_OPS_BROKEN
7195 || AOP_NEEDSACC (left)
7199 operand *tmp = right;
7204 /* if result = right then exchange left and right */
7205 if (sameRegs (AOP (result), AOP (right)))
7207 operand *tmp = right;
7212 /* if right is bit then exchange them */
7213 if (AOP_TYPE (right) == AOP_CRY &&
7214 AOP_TYPE (left) != AOP_CRY)
7216 operand *tmp = right;
7220 if (AOP_TYPE (right) == AOP_LIT)
7221 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7223 size = AOP_SIZE (result);
7226 // result = bit & yy;
7227 if (AOP_TYPE (left) == AOP_CRY)
7229 // c = bit & literal;
7230 if (AOP_TYPE (right) == AOP_LIT)
7234 if (size && sameRegs (AOP (result), AOP (left)))
7237 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7242 if (size && (AOP_TYPE (result) == AOP_CRY))
7244 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
7247 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7252 emitcode ("clr", "c");
7257 if (AOP_TYPE (right) == AOP_CRY)
7260 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7261 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
7266 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
7268 emitcode ("rrc", "a");
7269 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
7277 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7278 genIfxJump (ifx, "c");
7282 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7283 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7284 if ((AOP_TYPE (right) == AOP_LIT) &&
7285 (AOP_TYPE (result) == AOP_CRY) &&
7286 (AOP_TYPE (left) != AOP_CRY))
7288 int posbit = isLiteralBit (lit);
7293 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE, NULL));
7297 switch (posbit & 0x07)
7299 case 0: emitcode ("rrc", "a");
7301 case 7: emitcode ("rlc", "a");
7303 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
7312 SNPRINTF (buffer, sizeof(buffer),
7313 "acc.%d", posbit & 0x07);
7314 genIfxJump (ifx, buffer);
7318 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
7325 symbol *tlbl = newiTempLabel (NULL);
7326 int sizel = AOP_SIZE (left);
7328 emitcode ("setb", "c");
7331 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
7333 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7335 if ((posbit = isLiteralBit (bytelit)) != 0)
7336 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
7339 if (bytelit != 0x0FFL)
7340 emitcode ("anl", "a,%s",
7341 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG));
7342 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7347 // bit = left & literal
7350 emitcode ("clr", "c");
7353 // if(left & literal)
7357 jmpTrueOrFalse (ifx, tlbl);
7367 /* if left is same as result */
7368 if (sameRegs (AOP (result), AOP (left)))
7370 for (; size--; offset++)
7372 if (AOP_TYPE (right) == AOP_LIT)
7374 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7375 if (bytelit == 0x0FF)
7377 /* dummy read of volatile operand */
7378 if (isOperandVolatile (left, FALSE))
7379 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7383 else if (bytelit == 0)
7385 aopPut (result, zero, offset);
7387 else if (IS_AOP_PREG (result))
7389 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7390 emitcode ("anl", "a,%s",
7391 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG));
7392 aopPut (result, "a", offset);
7395 emitcode ("anl", "%s,%s",
7396 aopGet (left, offset, FALSE, TRUE, NULL),
7397 aopGet (right, offset, FALSE, FALSE, NULL));
7401 if (AOP_TYPE (left) == AOP_ACC)
7402 emitcode ("anl", "a,%s",
7403 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7406 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7407 if (IS_AOP_PREG (result))
7409 emitcode ("anl", "a,%s",
7410 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7411 aopPut (result, "a", offset);
7414 emitcode ("anl", "%s,a",
7415 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7422 // left & result in different registers
7423 if (AOP_TYPE (result) == AOP_CRY)
7426 // if(size), result in bit
7427 // if(!size && ifx), conditional oper: if(left & right)
7428 symbol *tlbl = newiTempLabel (NULL);
7429 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
7431 emitcode ("setb", "c");
7434 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7435 emitcode ("anl", "a,%s",
7436 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7438 if (AOP_TYPE(left)==AOP_ACC)
7440 bool pushedB = pushB ();
7441 emitcode("mov", "b,a");
7442 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7443 emitcode("anl", "a,b");
7448 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7449 emitcode ("anl", "a,%s",
7450 aopGet (left, offset, FALSE, FALSE, DP2_RESULT_REG));
7453 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7463 jmpTrueOrFalse (ifx, tlbl);
7469 for (; (size--); offset++)
7472 // result = left & right
7473 if (AOP_TYPE (right) == AOP_LIT)
7475 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7476 if (bytelit == 0x0FF)
7479 aopGet (left, offset, FALSE, FALSE, NULL),
7483 else if (bytelit == 0)
7485 /* dummy read of volatile operand */
7486 if (isOperandVolatile (left, FALSE))
7487 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7488 aopPut (result, zero, offset);
7491 D (emitcode (";", "better literal AND."));
7492 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7493 emitcode ("anl", "a, %s", aopGet (right, offset,
7494 FALSE, FALSE, DP2_RESULT_REG));
7499 // faster than result <- left, anl result,right
7500 // and better if result is SFR
7501 if (AOP_TYPE (left) == AOP_ACC)
7503 emitcode ("anl", "a,%s",
7504 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7508 char *rOp = aopGet (right, offset, FALSE, FALSE, NULL);
7509 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7511 emitcode("mov", "b,a");
7515 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7516 emitcode ("anl", "a,%s", rOp);
7519 aopPut (result, "a", offset);
7525 freeAsmop (result, NULL, ic, TRUE);
7526 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7527 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7530 /*-----------------------------------------------------------------*/
7531 /* genOr - code for or */
7532 /*-----------------------------------------------------------------*/
7534 genOr (iCode * ic, iCode * ifx)
7536 operand *left, *right, *result;
7537 int size, offset = 0;
7538 unsigned long lit = 0L;
7542 D (emitcode (";", "genOr"));
7544 AOP_OP_3_NOFATAL (ic, pushResult);
7545 AOP_SET_LOCALS (ic);
7549 genFarFarLogicOp(ic, "orl");
7555 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7557 AOP_TYPE (left), AOP_TYPE (right));
7558 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7560 AOP_SIZE (left), AOP_SIZE (right));
7563 /* if left is a literal & right is not then exchange them */
7564 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7565 #ifdef LOGIC_OPS_BROKEN
7566 || AOP_NEEDSACC (left) // I think this is a net loss now.
7570 operand *tmp = right;
7575 /* if result = right then exchange them */
7576 if (sameRegs (AOP (result), AOP (right)))
7578 operand *tmp = right;
7583 /* if right is bit then exchange them */
7584 if (AOP_TYPE (right) == AOP_CRY &&
7585 AOP_TYPE (left) != AOP_CRY)
7587 operand *tmp = right;
7591 if (AOP_TYPE (right) == AOP_LIT)
7592 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7594 size = AOP_SIZE (result);
7598 if (AOP_TYPE (left) == AOP_CRY)
7600 if (AOP_TYPE (right) == AOP_LIT)
7602 // c = bit | literal;
7605 // lit != 0 => result = 1
7606 if (AOP_TYPE (result) == AOP_CRY)
7609 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7611 continueIfTrue (ifx);
7614 emitcode ("setb", "c");
7618 // lit == 0 => result = left
7619 if (size && sameRegs (AOP (result), AOP (left)))
7621 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7626 if (AOP_TYPE (right) == AOP_CRY)
7629 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7630 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7635 symbol *tlbl = newiTempLabel (NULL);
7636 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
7637 emitcode ("setb", "c");
7638 emitcode ("jb", "%s,!tlabel",
7639 AOP (left)->aopu.aop_dir, tlbl->key + 100);
7641 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7642 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7644 jmpTrueOrFalse (ifx, tlbl);
7659 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7660 genIfxJump (ifx, "c");
7664 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7665 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7666 if ((AOP_TYPE (right) == AOP_LIT) &&
7667 (AOP_TYPE (result) == AOP_CRY) &&
7668 (AOP_TYPE (left) != AOP_CRY))
7674 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7676 continueIfTrue (ifx);
7681 // lit = 0, result = boolean(left)
7683 emitcode ("setb", "c");
7687 symbol *tlbl = newiTempLabel (NULL);
7688 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7694 genIfxJump (ifx, "a");
7702 /* if left is same as result */
7703 if (sameRegs (AOP (result), AOP (left)))
7705 for (; size--; offset++)
7707 if (AOP_TYPE (right) == AOP_LIT)
7709 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7712 /* dummy read of volatile operand */
7713 if (isOperandVolatile (left, FALSE))
7714 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7718 else if (bytelit == 0x0FF)
7720 aopPut (result, "#0xFF", offset);
7722 else if (IS_AOP_PREG (left))
7724 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7725 emitcode ("orl", "a,%s",
7726 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7727 aopPut (result, "a", offset);
7731 emitcode ("orl", "%s,%s",
7732 aopGet (left, offset, FALSE, TRUE, NULL),
7733 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7738 if (AOP_TYPE (left) == AOP_ACC)
7740 emitcode ("orl", "a,%s",
7741 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7745 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7746 if (IS_AOP_PREG (left))
7748 emitcode ("orl", "a,%s",
7749 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7750 aopPut (result, "a", offset);
7754 emitcode ("orl", "%s,a",
7755 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7763 // left & result in different registers
7764 if (AOP_TYPE (result) == AOP_CRY)
7767 // if(size), result in bit
7768 // if(!size && ifx), conditional oper: if(left | right)
7769 symbol *tlbl = newiTempLabel (NULL);
7770 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7772 emitcode ("setb", "c");
7775 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7776 emitcode ("orl", "a,%s",
7777 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7779 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7780 emitcode ("orl", "a,%s",
7781 aopGet (left, offset, FALSE, FALSE, DP2_RESULT_REG));
7783 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7793 jmpTrueOrFalse (ifx, tlbl);
7799 _startLazyDPSEvaluation();
7800 for (; (size--); offset++)
7803 // result = left | right
7804 if (AOP_TYPE (right) == AOP_LIT)
7806 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7810 aopGet (left, offset, FALSE, FALSE, NULL),
7814 else if (bytelit == 0x0FF)
7816 /* dummy read of volatile operand */
7817 if (isOperandVolatile (left, FALSE))
7818 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7819 aopPut (result, "#0xFF", offset);
7822 D (emitcode (";", "better literal OR."));
7823 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7824 emitcode ("orl", "a, %s",
7825 aopGet (right, offset,
7826 FALSE, FALSE, DP2_RESULT_REG));
7831 // faster than result <- left, anl result,right
7832 // and better if result is SFR
7833 if (AOP_TYPE (left) == AOP_ACC)
7835 emitcode ("orl", "a,%s",
7836 aopGet (right, offset,
7837 FALSE, FALSE, DP2_RESULT_REG));
7841 char *rOp = aopGet (right, offset, FALSE, FALSE, NULL);
7843 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7845 emitcode("mov", "b,a");
7849 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7850 emitcode ("orl", "a,%s", rOp);
7853 aopPut (result, "a", offset);
7855 _endLazyDPSEvaluation();
7860 freeAsmop (result, NULL, ic, TRUE);
7861 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7862 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7865 /*-----------------------------------------------------------------*/
7866 /* genXor - code for xclusive or */
7867 /*-----------------------------------------------------------------*/
7869 genXor (iCode * ic, iCode * ifx)
7871 operand *left, *right, *result;
7872 int size, offset = 0;
7873 unsigned long lit = 0L;
7877 D (emitcode (";", "genXor"));
7879 AOP_OP_3_NOFATAL (ic, pushResult);
7880 AOP_SET_LOCALS (ic);
7884 genFarFarLogicOp(ic, "xrl");
7889 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7891 AOP_TYPE (left), AOP_TYPE (right));
7892 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7894 AOP_SIZE (left), AOP_SIZE (right));
7897 /* if left is a literal & right is not ||
7898 if left needs acc & right does not */
7899 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7900 #ifdef LOGIC_OPS_BROKEN
7901 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
7905 operand *tmp = right;
7910 /* if result = right then exchange them */
7911 if (sameRegs (AOP (result), AOP (right)))
7913 operand *tmp = right;
7918 /* if right is bit then exchange them */
7919 if (AOP_TYPE (right) == AOP_CRY &&
7920 AOP_TYPE (left) != AOP_CRY)
7922 operand *tmp = right;
7926 if (AOP_TYPE (right) == AOP_LIT)
7927 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7929 size = AOP_SIZE (result);
7933 if (AOP_TYPE (left) == AOP_CRY)
7935 if (AOP_TYPE (right) == AOP_LIT)
7937 // c = bit & literal;
7940 // lit>>1 != 0 => result = 1
7941 if (AOP_TYPE (result) == AOP_CRY)
7944 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7946 continueIfTrue (ifx);
7949 emitcode ("setb", "c");
7956 // lit == 0, result = left
7957 if (size && sameRegs (AOP (result), AOP (left)))
7959 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7963 // lit == 1, result = not(left)
7964 if (size && sameRegs (AOP (result), AOP (left)))
7966 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7971 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7972 emitcode ("cpl", "c");
7981 symbol *tlbl = newiTempLabel (NULL);
7982 if (AOP_TYPE (right) == AOP_CRY)
7985 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7989 int sizer = AOP_SIZE (right);
7991 // if val>>1 != 0, result = 1
7992 emitcode ("setb", "c");
7995 MOVA (aopGet (right, sizer - 1, FALSE, FALSE, NULL));
7997 // test the msb of the lsb
7998 emitcode ("anl", "a,#!constbyte",0xfe);
7999 emitcode ("jnz", "!tlabel", tlbl->key + 100);
8003 emitcode ("rrc", "a");
8005 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
8006 emitcode ("cpl", "c");
8014 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
8015 genIfxJump (ifx, "c");
8019 /* if left is same as result */
8020 if (sameRegs (AOP (result), AOP (left)))
8022 for (; size--; offset++)
8024 if (AOP_TYPE (right) == AOP_LIT)
8026 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
8029 /* dummy read of volatile operand */
8030 if (isOperandVolatile (left, FALSE))
8031 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8035 else if (IS_AOP_PREG (left))
8037 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8038 emitcode ("xrl", "a,%s",
8039 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG));
8040 aopPut (result, "a", offset);
8044 emitcode ("xrl", "%s,%s",
8045 aopGet (left, offset, FALSE, TRUE, NULL),
8046 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8051 if (AOP_TYPE (left) == AOP_ACC)
8052 emitcode ("xrl", "a,%s",
8053 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8056 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
8057 if (IS_AOP_PREG (left))
8059 emitcode ("xrl", "a,%s",
8060 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
8061 aopPut (result, "a", offset);
8064 emitcode ("xrl", "%s,a",
8065 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
8072 // left & result in different registers
8073 if (AOP_TYPE (result) == AOP_CRY)
8076 // if(size), result in bit
8077 // if(!size && ifx), conditional oper: if(left ^ right)
8078 symbol *tlbl = newiTempLabel (NULL);
8079 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
8082 emitcode ("setb", "c");
8085 if ((AOP_TYPE (right) == AOP_LIT) &&
8086 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
8088 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8092 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
8093 emitcode ("xrl", "a,%s",
8094 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8096 char *rOp = aopGet (right, offset, FALSE, FALSE, NULL);
8097 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
8099 emitcode("mov", "b,a");
8103 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8104 emitcode ("xrl", "a,%s", rOp);
8107 emitcode ("jnz", "!tlabel", tlbl->key + 100);
8117 jmpTrueOrFalse (ifx, tlbl);
8121 for (; (size--); offset++)
8124 // result = left ^ right
8125 if (AOP_TYPE (right) == AOP_LIT)
8127 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
8131 aopGet (left, offset, FALSE, FALSE, NULL),
8135 D (emitcode (";", "better literal XOR."));
8136 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8137 emitcode ("xrl", "a, %s",
8138 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8142 // faster than result <- left, anl result,right
8143 // and better if result is SFR
8144 if (AOP_TYPE (left) == AOP_ACC)
8146 emitcode ("xrl", "a,%s",
8147 aopGet (right, offset,
8148 FALSE, FALSE, DP2_RESULT_REG));
8152 char *rOp = aopGet (right, offset, FALSE, FALSE, NULL);
8153 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
8155 emitcode("mov", "b,a");
8159 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8160 emitcode ("xrl", "a,%s", rOp);
8163 aopPut (result, "a", offset);
8169 freeAsmop (result, NULL, ic, TRUE);
8170 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
8171 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
8174 /*-----------------------------------------------------------------*/
8175 /* genInline - write the inline code out */
8176 /*-----------------------------------------------------------------*/
8178 genInline (iCode * ic)
8180 char *buffer, *bp, *bp1;
8182 D (emitcode (";", "genInline"));
8184 _G.inLine += (!options.asmpeep);
8186 buffer = bp = bp1 = Safe_strdup(IC_INLINE(ic));
8188 /* emit each line as a code */
8199 /* Add \n for labels, not dirs such as c:\mydir */
8200 if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
8214 /* emitcode("",buffer); */
8215 _G.inLine -= (!options.asmpeep);
8218 /*-----------------------------------------------------------------*/
8219 /* genRRC - rotate right with carry */
8220 /*-----------------------------------------------------------------*/
8224 operand *left, *result;
8228 D (emitcode (";", "genRRC"));
8230 /* rotate right with carry */
8231 left = IC_LEFT (ic);
8232 result = IC_RESULT (ic);
8233 aopOp (left, ic, FALSE, FALSE);
8234 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8236 /* move it to the result */
8237 size = AOP_SIZE (result);
8241 _startLazyDPSEvaluation ();
8244 l = aopGet (left, offset, FALSE, FALSE, NULL);
8246 emitcode ("rrc", "a");
8247 if (AOP_SIZE (result) > 1)
8248 aopPut (result, "a", offset--);
8250 _endLazyDPSEvaluation ();
8252 /* now we need to put the carry into the
8253 highest order byte of the result */
8254 if (AOP_SIZE (result) > 1)
8256 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE, NULL);
8259 emitcode ("mov", "acc.7,c");
8260 aopPut (result, "a", AOP_SIZE (result) - 1);
8261 freeAsmop (result, NULL, ic, TRUE);
8262 freeAsmop (left, NULL, ic, TRUE);
8265 /*-----------------------------------------------------------------*/
8266 /* genRLC - generate code for rotate left with carry */
8267 /*-----------------------------------------------------------------*/
8271 operand *left, *result;
8275 D (emitcode (";", "genRLC"));
8277 /* rotate right with carry */
8278 left = IC_LEFT (ic);
8279 result = IC_RESULT (ic);
8280 aopOp (left, ic, FALSE, FALSE);
8281 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8283 /* move it to the result */
8284 size = AOP_SIZE (result);
8288 l = aopGet (left, offset, FALSE, FALSE, NULL);
8290 emitcode ("add", "a,acc");
8291 if (AOP_SIZE (result) > 1)
8293 aopPut (result, "a", offset++);
8296 _startLazyDPSEvaluation ();
8299 l = aopGet (left, offset, FALSE, FALSE, NULL);
8301 emitcode ("rlc", "a");
8302 if (AOP_SIZE (result) > 1)
8303 aopPut (result, "a", offset++);
8305 _endLazyDPSEvaluation ();
8307 /* now we need to put the carry into the
8308 highest order byte of the result */
8309 if (AOP_SIZE (result) > 1)
8311 l = aopGet (result, 0, FALSE, FALSE, NULL);
8314 emitcode ("mov", "acc.0,c");
8315 aopPut (result, "a", 0);
8316 freeAsmop (result, NULL, ic, TRUE);
8317 freeAsmop (left, NULL, ic, TRUE);
8320 /*-----------------------------------------------------------------*/
8321 /* genGetHbit - generates code get highest order bit */
8322 /*-----------------------------------------------------------------*/
8324 genGetHbit (iCode * ic)
8326 operand *left, *result;
8328 D (emitcode (";", "genGetHbit"));
8330 left = IC_LEFT (ic);
8331 result = IC_RESULT (ic);
8332 aopOp (left, ic, FALSE, FALSE);
8333 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8335 /* get the highest order byte into a */
8336 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
8337 if (AOP_TYPE (result) == AOP_CRY)
8339 emitcode ("rlc", "a");
8344 emitcode ("rl", "a");
8345 emitcode ("anl", "a,#1");
8350 freeAsmop (result, NULL, ic, TRUE);
8351 freeAsmop (left, NULL, ic, TRUE);
8354 /*-----------------------------------------------------------------*/
8355 /* genSwap - generates code to swap nibbles or bytes */
8356 /*-----------------------------------------------------------------*/
8358 genSwap (iCode * ic)
8360 operand *left, *result;
8362 D(emitcode ("; genSwap",""));
8364 left = IC_LEFT (ic);
8365 result = IC_RESULT (ic);
8366 aopOp (left, ic, FALSE, FALSE);
8367 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8369 _startLazyDPSEvaluation ();
8370 switch (AOP_SIZE (left))
8372 case 1: /* swap nibbles in byte */
8373 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
8374 emitcode ("swap", "a");
8375 aopPut (result, "a", 0);
8377 case 2: /* swap bytes in word */
8378 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
8380 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
8381 aopPut (result, aopGet (left, 1, FALSE, FALSE, NULL), 0);
8382 aopPut (result, "a", 1);
8384 else if (operandsEqu (left, result))
8387 bool pushedB = FALSE, leftInB = FALSE;
8389 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
8390 if (AOP_NEEDSACC (left) || AOP_NEEDSACC (result))
8393 emitcode ("mov", "b,a");
8397 aopPut (result, aopGet (left, 1, FALSE, FALSE, NULL), 0);
8398 aopPut (result, reg, 1);
8405 aopPut (result, aopGet (left, 1, FALSE, FALSE, NULL), 0);
8406 aopPut (result, aopGet (left, 0, FALSE, FALSE, NULL), 1);
8410 wassertl(FALSE, "unsupported SWAP operand size");
8412 _endLazyDPSEvaluation ();
8414 freeAsmop (result, NULL, ic, TRUE);
8415 freeAsmop (left, NULL, ic, TRUE);
8418 /*-----------------------------------------------------------------*/
8419 /* AccRol - rotate left accumulator by known count */
8420 /*-----------------------------------------------------------------*/
8422 AccRol (int shCount)
8424 shCount &= 0x0007; // shCount : 0..7
8431 emitcode ("rl", "a");
8434 emitcode ("rl", "a");
8435 emitcode ("rl", "a");
8438 emitcode ("swap", "a");
8439 emitcode ("rr", "a");
8442 emitcode ("swap", "a");
8445 emitcode ("swap", "a");
8446 emitcode ("rl", "a");
8449 emitcode ("rr", "a");
8450 emitcode ("rr", "a");
8453 emitcode ("rr", "a");
8458 /*-----------------------------------------------------------------*/
8459 /* AccLsh - left shift accumulator by known count */
8460 /*-----------------------------------------------------------------*/
8462 AccLsh (int shCount)
8467 emitcode ("add", "a,acc");
8468 else if (shCount == 2)
8470 emitcode ("add", "a,acc");
8471 emitcode ("add", "a,acc");
8475 /* rotate left accumulator */
8477 /* and kill the lower order bits */
8478 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
8483 /*-----------------------------------------------------------------*/
8484 /* AccRsh - right shift accumulator by known count */
8485 /*-----------------------------------------------------------------*/
8487 AccRsh (int shCount)
8494 emitcode ("rrc", "a");
8498 /* rotate right accumulator */
8499 AccRol (8 - shCount);
8500 /* and kill the higher order bits */
8501 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
8506 #ifdef BETTER_LITERAL_SHIFT
8507 /*-----------------------------------------------------------------*/
8508 /* AccSRsh - signed right shift accumulator by known count */
8509 /*-----------------------------------------------------------------*/
8511 AccSRsh (int shCount)
8518 emitcode ("mov", "c,acc.7");
8519 emitcode ("rrc", "a");
8521 else if (shCount == 2)
8523 emitcode ("mov", "c,acc.7");
8524 emitcode ("rrc", "a");
8525 emitcode ("mov", "c,acc.7");
8526 emitcode ("rrc", "a");
8530 tlbl = newiTempLabel (NULL);
8531 /* rotate right accumulator */
8532 AccRol (8 - shCount);
8533 /* and kill the higher order bits */
8534 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
8535 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8536 emitcode ("orl", "a,#!constbyte",
8537 (unsigned char) ~SRMask[shCount]);
8544 #ifdef BETTER_LITERAL_SHIFT
8545 /*-----------------------------------------------------------------*/
8546 /* shiftR1Left2Result - shift right one byte from left to result */
8547 /*-----------------------------------------------------------------*/
8549 shiftR1Left2Result (operand * left, int offl,
8550 operand * result, int offr,
8551 int shCount, int sign)
8553 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
8554 /* shift right accumulator */
8559 aopPut (result, "a", offr);
8563 #ifdef BETTER_LITERAL_SHIFT
8564 /*-----------------------------------------------------------------*/
8565 /* shiftL1Left2Result - shift left one byte from left to result */
8566 /*-----------------------------------------------------------------*/
8568 shiftL1Left2Result (operand * left, int offl,
8569 operand * result, int offr, int shCount)
8572 l = aopGet (left, offl, FALSE, FALSE, NULL);
8574 /* shift left accumulator */
8576 aopPut (result, "a", offr);
8580 #ifdef BETTER_LITERAL_SHIFT
8581 /*-----------------------------------------------------------------*/
8582 /* movLeft2Result - move byte from left to result */
8583 /*-----------------------------------------------------------------*/
8585 movLeft2Result (operand * left, int offl,
8586 operand * result, int offr, int sign)
8589 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8591 l = aopGet (left, offl, FALSE, FALSE, NULL);
8593 if (*l == '@' && (IS_AOP_PREG (result)))
8595 emitcode ("mov", "a,%s", l);
8596 aopPut (result, "a", offr);
8602 aopPut (result, l, offr);
8606 /* MSB sign in acc.7 ! */
8607 if (getDataSize (left) == offl + 1)
8610 aopPut (result, "a", offr);
8618 #ifdef BETTER_LITERAL_SHIFT
8619 /*-----------------------------------------------------------------*/
8620 /* AccAXRrl1 - right rotate a:x by 1 */
8621 /*-----------------------------------------------------------------*/
8625 emitcode ("mov", "c,acc.0");
8626 emitcode ("xch", "a,%s", x);
8627 emitcode ("rrc", "a");
8628 emitcode ("xch", "a,%s", x);
8629 emitcode ("rrc", "a");
8633 #ifdef BETTER_LITERAL_SHIFT
8635 /*-----------------------------------------------------------------*/
8636 /* AccAXLrl1 - left rotate a:x by 1 */
8637 /*-----------------------------------------------------------------*/
8641 emitcode ("mov", "c,acc.7");
8642 emitcode ("xch", "a,%s", x);
8643 emitcode ("rlc", "a");
8644 emitcode ("xch", "a,%s", x);
8645 emitcode ("rlc", "a");
8649 #ifdef BETTER_LITERAL_SHIFT
8650 /*-----------------------------------------------------------------*/
8651 /* AccAXRsh1 - right shift c->a:x->c by 1 */
8652 /*-----------------------------------------------------------------*/
8656 emitcode ("rrc", "a");
8657 emitcode ("xch", "a,%s", x);
8658 emitcode ("rrc", "a");
8659 emitcode ("xch", "a,%s", x);
8663 #ifdef BETTER_LITERAL_SHIFT
8664 /*-----------------------------------------------------------------*/
8665 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8666 /*-----------------------------------------------------------------*/
8670 emitcode ("xch", "a,%s", x);
8671 emitcode ("add", "a,acc");
8672 emitcode ("xch", "a,%s", x);
8673 emitcode ("rlc", "a");
8677 #ifdef BETTER_LITERAL_SHIFT
8678 /*-----------------------------------------------------------------*/
8679 /* AccAXLsh - left shift a:x by known count (0..7) */
8680 /*-----------------------------------------------------------------*/
8682 AccAXLsh (char *x, int shCount)
8697 case 5: // AAAAABBB:CCCCCDDD
8699 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8701 emitcode ("anl", "a,#!constbyte",
8702 SLMask[shCount]); // BBB00000:CCCCCDDD
8704 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8706 AccRol (shCount); // DDDCCCCC:BBB00000
8708 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8710 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8712 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8714 emitcode ("anl", "a,#!constbyte",
8715 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8717 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8719 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8722 case 6: // AAAAAABB:CCCCCCDD
8723 emitcode ("anl", "a,#!constbyte",
8724 SRMask[shCount]); // 000000BB:CCCCCCDD
8726 AccAXRrl1 (x); // D000000B:BCCCCCCD
8727 AccAXRrl1 (x); // DD000000:BBCCCCCC
8728 emitcode ("xch", "a,%s", x); // BBCCCCCC:DD000000
8730 emitcode ("mov", "c,acc.0"); // c = B
8731 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8732 emitcode("rrc","a");
8733 emitcode("xch","a,%s", x);
8734 emitcode("rrc","a");
8735 emitcode("mov","c,acc.0"); //<< get correct bit
8736 emitcode("xch","a,%s", x);
8738 emitcode("rrc","a");
8739 emitcode("xch","a,%s", x);
8740 emitcode("rrc","a");
8741 emitcode("xch","a,%s", x);
8744 case 7: // a:x <<= 7
8746 emitcode ("anl", "a,#!constbyte",
8747 SRMask[shCount]); // 0000000B:CCCCCCCD
8749 AccAXRrl1 (x); // D0000000:BCCCCCCC
8751 emitcode ("xch", "a,%s", x); // BCCCCCCC:D0000000
8760 #ifdef BETTER_LITERAL_SHIFT
8762 /*-----------------------------------------------------------------*/
8763 /* AccAXRsh - right shift a:x known count (0..7) */
8764 /*-----------------------------------------------------------------*/
8766 AccAXRsh (char *x, int shCount)
8774 AccAXRsh1 (x); // 0->a:x
8779 AccAXRsh1 (x); // 0->a:x
8782 AccAXRsh1 (x); // 0->a:x
8787 case 5: // AAAAABBB:CCCCCDDD = a:x
8789 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8791 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8793 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8795 emitcode ("anl", "a,#!constbyte",
8796 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8798 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8800 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8802 emitcode ("anl", "a,#!constbyte",
8803 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8805 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8807 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8809 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8812 case 6: // AABBBBBB:CCDDDDDD
8814 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDE
8815 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8817 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8819 emitcode ("anl", "a,#!constbyte",
8820 SRMask[shCount]); // 000000AA:BBBBBBCC
8823 case 7: // ABBBBBBB:CDDDDDDD
8825 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8827 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8829 emitcode ("anl", "a,#!constbyte",
8830 SRMask[shCount]); // 0000000A:BBBBBBBC
8839 #ifdef BETTER_LITERAL_SHIFT
8840 /*-----------------------------------------------------------------*/
8841 /* AccAXRshS - right shift signed a:x known count (0..7) */
8842 /*-----------------------------------------------------------------*/
8844 AccAXRshS (char *x, int shCount)
8852 emitcode ("mov", "c,acc.7");
8853 AccAXRsh1 (x); // s->a:x
8857 emitcode ("mov", "c,acc.7");
8858 AccAXRsh1 (x); // s->a:x
8860 emitcode ("mov", "c,acc.7");
8861 AccAXRsh1 (x); // s->a:x
8866 case 5: // AAAAABBB:CCCCCDDD = a:x
8868 tlbl = newiTempLabel (NULL);
8869 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8871 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8873 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8875 emitcode ("anl", "a,#!constbyte",
8876 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8878 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8880 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8882 emitcode ("anl", "a,#!constbyte",
8883 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8885 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8887 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8889 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8891 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8892 emitcode ("orl", "a,#!constbyte",
8893 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8896 break; // SSSSAAAA:BBBCCCCC
8898 case 6: // AABBBBBB:CCDDDDDD
8900 tlbl = newiTempLabel (NULL);
8902 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8903 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8905 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8907 emitcode ("anl", "a,#!constbyte",
8908 SRMask[shCount]); // 000000AA:BBBBBBCC
8910 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8911 emitcode ("orl", "a,#!constbyte",
8912 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8916 case 7: // ABBBBBBB:CDDDDDDD
8918 tlbl = newiTempLabel (NULL);
8920 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8922 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8924 emitcode ("anl", "a,#!constbyte",
8925 SRMask[shCount]); // 0000000A:BBBBBBBC
8927 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8928 emitcode ("orl", "a,#!constbyte",
8929 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8939 #ifdef BETTER_LITERAL_SHIFT
8941 _loadLeftIntoAx(char **lsb,
8947 // Get the initial value from left into a pair of registers.
8948 // MSB must be in A, LSB can be any register.
8950 // If the result is held in registers, it is an optimization
8951 // if the LSB can be held in the register which will hold the,
8952 // result LSB since this saves us from having to copy it into
8953 // the result following AccAXLsh.
8955 // If the result is addressed indirectly, this is not a gain.
8956 if (AOP_NEEDSACC(result))
8960 _startLazyDPSEvaluation();
8961 if (AOP_TYPE(left) == AOP_DPTR2)
8964 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE, NULL));
8965 // get LSB in DP2_RESULT_REG.
8966 leftByte = aopGet (left, offl, FALSE, FALSE, DP2_RESULT_REG);
8967 assert(!strcmp(leftByte, DP2_RESULT_REG));
8971 // get LSB into DP2_RESULT_REG
8972 leftByte = aopGet (left, offl, FALSE, FALSE, NULL);
8973 if (strcmp(leftByte, DP2_RESULT_REG))
8976 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
8979 leftByte = aopGet (left, offl + MSB16, FALSE, FALSE, NULL);
8980 assert(strcmp(leftByte, DP2_RESULT_REG));
8983 _endLazyDPSEvaluation();
8984 *lsb = DP2_RESULT_REG;
8988 if (sameRegs (AOP (result), AOP (left)) &&
8989 ((offl + MSB16) == offr))
8991 /* don't crash result[offr] */
8992 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
8993 emitcode ("xch", "a,%s",
8994 aopGet (left, offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
8998 movLeft2Result (left, offl, result, offr, 0);
8999 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE, NULL));
9001 *lsb = aopGet (result, offr, FALSE, FALSE, DP2_RESULT_REG);
9002 assert(strcmp(*lsb,"a"));
9007 _storeAxResults(char *lsb,
9011 _startLazyDPSEvaluation();
9012 if (AOP_NEEDSACC(result))
9014 /* We have to explicitly update the result LSB.
9016 emitcode ("xch","a,%s", lsb);
9017 aopPut (result, "a", offr);
9018 emitcode ("mov","a,%s", lsb);
9020 if (getDataSize (result) > 1)
9022 aopPut (result, "a", offr + MSB16);
9024 _endLazyDPSEvaluation();
9027 /*-----------------------------------------------------------------*/
9028 /* shiftL2Left2Result - shift left two bytes from left to result */
9029 /*-----------------------------------------------------------------*/
9031 shiftL2Left2Result (operand * left, int offl,
9032 operand * result, int offr, int shCount)
9036 _loadLeftIntoAx(&lsb, left, result, offl, offr);
9038 AccAXLsh (lsb, shCount);
9040 _storeAxResults(lsb, result, offr);
9044 #ifdef BETTER_LITERAL_SHIFT
9045 /*-----------------------------------------------------------------*/
9046 /* shiftR2Left2Result - shift right two bytes from left to result */
9047 /*-----------------------------------------------------------------*/
9049 shiftR2Left2Result (operand * left, int offl,
9050 operand * result, int offr,
9051 int shCount, int sign)
9055 _loadLeftIntoAx(&lsb, left, result, offl, offr);
9057 /* a:x >> shCount (x = lsb(result)) */
9060 AccAXRshS(lsb, shCount);
9064 AccAXRsh(lsb, shCount);
9067 _storeAxResults(lsb, result, offr);
9071 /*-----------------------------------------------------------------*/
9072 /* shiftLLeftOrResult - shift left one byte from left, or to result */
9073 /*-----------------------------------------------------------------*/
9075 shiftLLeftOrResult (operand * left, int offl,
9076 operand * result, int offr, int shCount)
9078 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
9079 /* shift left accumulator */
9081 /* or with result */
9082 emitcode ("orl", "a,%s",
9083 aopGet (result, offr, FALSE, FALSE, DP2_RESULT_REG));
9084 /* back to result */
9085 aopPut (result, "a", offr);
9090 /*-----------------------------------------------------------------*/
9091 /* shiftRLeftOrResult - shift right one byte from left,or to result */
9092 /*-----------------------------------------------------------------*/
9094 shiftRLeftOrResult (operand * left, int offl,
9095 operand * result, int offr, int shCount)
9097 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
9098 /* shift right accumulator */
9100 /* or with result */
9101 emitcode ("orl", "a,%s",
9102 aopGet (result, offr, FALSE, FALSE, DP2_RESULT_REG));
9103 /* back to result */
9104 aopPut (result, "a", offr);
9108 #ifdef BETTER_LITERAL_SHIFT
9109 /*-----------------------------------------------------------------*/
9110 /* genlshOne - left shift a one byte quantity by known count */
9111 /*-----------------------------------------------------------------*/
9113 genlshOne (operand * result, operand * left, int shCount)
9115 D (emitcode (";", "genlshOne"));
9117 shiftL1Left2Result (left, LSB, result, LSB, shCount);
9121 #ifdef BETTER_LITERAL_SHIFT
9122 /*-----------------------------------------------------------------*/
9123 /* genlshTwo - left shift two bytes by known amount != 0 */
9124 /*-----------------------------------------------------------------*/
9126 genlshTwo (operand * result, operand * left, int shCount)
9130 D (emitcode (";", "genlshTwo"));
9132 size = getDataSize (result);
9134 /* if shCount >= 8 */
9139 _startLazyDPSEvaluation();
9145 _endLazyDPSEvaluation();
9146 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
9147 aopPut (result, zero, LSB);
9151 movLeft2Result (left, LSB, result, MSB16, 0);
9152 aopPut (result, zero, LSB);
9153 _endLazyDPSEvaluation();
9158 aopPut (result, zero, LSB);
9159 _endLazyDPSEvaluation();
9163 /* 1 <= shCount <= 7 */
9167 shiftL1Left2Result (left, LSB, result, LSB, shCount);
9169 shiftL2Left2Result (left, LSB, result, LSB, shCount);
9176 /*-----------------------------------------------------------------*/
9177 /* shiftLLong - shift left one long from left to result */
9178 /* offl = LSB or MSB16 */
9179 /*-----------------------------------------------------------------*/
9181 shiftLLong (operand * left, operand * result, int offr)
9184 int size = AOP_SIZE (result);
9186 if (size >= LSB + offr)
9188 l = aopGet (left, LSB, FALSE, FALSE, NULL);
9190 emitcode ("add", "a,acc");
9191 if (sameRegs (AOP (left), AOP (result)) &&
9192 size >= MSB16 + offr && offr != LSB)
9193 emitcode ("xch", "a,%s",
9194 aopGet (left, LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
9196 aopPut (result, "a", LSB + offr);
9199 if (size >= MSB16 + offr)
9201 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
9203 l = aopGet (left, MSB16, FALSE, FALSE, TRUE);
9206 emitcode ("rlc", "a");
9207 if (sameRegs (AOP (left), AOP (result)) &&
9208 size >= MSB24 + offr && offr != LSB)
9209 emitcode ("xch", "a,%s",
9210 aopGet (left, MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
9212 aopPut (result, "a", MSB16 + offr);
9215 if (size >= MSB24 + offr)
9217 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
9219 l = aopGet (left, MSB24, FALSE, FALSE, NULL);
9222 emitcode ("rlc", "a");
9223 if (sameRegs (AOP (left), AOP (result)) &&
9224 size >= MSB32 + offr && offr != LSB)
9225 emitcode ("xch", "a,%s",
9226 aopGet (left, MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
9228 aopPut (result, "a", MSB24 + offr);
9231 if (size > MSB32 + offr)
9233 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
9235 l = aopGet (left, MSB32, FALSE, FALSE, NULL);
9238 emitcode ("rlc", "a");
9239 aopPut (result, "a", MSB32 + offr);
9242 aopPut (result, zero, LSB);
9248 /*-----------------------------------------------------------------*/
9249 /* genlshFour - shift four byte by a known amount != 0 */
9250 /*-----------------------------------------------------------------*/
9252 genlshFour (operand * result, operand * left, int shCount)
9256 D (emitcode (";", "genlshFour"));
9258 size = AOP_SIZE (result);
9260 /* if shifting more that 3 bytes */
9265 /* lowest order of left goes to the highest
9266 order of the destination */
9267 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
9269 movLeft2Result (left, LSB, result, MSB32, 0);
9270 aopPut (result, zero, LSB);
9271 aopPut (result, zero, MSB16);
9272 aopPut (result, zero, MSB24);
9276 /* more than two bytes */
9277 else if (shCount >= 16)
9279 /* lower order two bytes goes to higher order two bytes */
9281 /* if some more remaining */
9283 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
9286 movLeft2Result (left, MSB16, result, MSB32, 0);
9287 movLeft2Result (left, LSB, result, MSB24, 0);
9289 aopPut (result, zero, MSB16);
9290 aopPut (result, zero, LSB);
9294 /* if more than 1 byte */
9295 else if (shCount >= 8)
9297 /* lower order three bytes goes to higher order three bytes */
9302 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
9304 movLeft2Result (left, LSB, result, MSB16, 0);
9310 movLeft2Result (left, MSB24, result, MSB32, 0);
9311 movLeft2Result (left, MSB16, result, MSB24, 0);
9312 movLeft2Result (left, LSB, result, MSB16, 0);
9313 aopPut (result, zero, LSB);
9315 else if (shCount == 1)
9316 shiftLLong (left, result, MSB16);
9319 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
9320 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
9321 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
9322 aopPut (result, zero, LSB);
9327 /* 1 <= shCount <= 7 */
9328 else if (shCount <= 2)
9330 shiftLLong (left, result, LSB);
9332 shiftLLong (result, result, LSB);
9334 /* 3 <= shCount <= 7, optimize */
9337 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
9338 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
9339 shiftL2Left2Result (left, LSB, result, LSB, shCount);
9344 #ifdef BETTER_LITERAL_SHIFT
9345 /*-----------------------------------------------------------------*/
9346 /* genLeftShiftLiteral - left shifting by known count */
9347 /*-----------------------------------------------------------------*/
9349 genLeftShiftLiteral (operand * left,
9354 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9357 size = getSize (operandType (result));
9359 D (emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
9361 /* We only handle certain easy cases so far. */
9363 && (shCount < (size * 8))
9367 D(emitcode (";", "genLeftShiftLiteral wimping out"););
9371 freeAsmop (right, NULL, ic, TRUE);
9373 aopOp(left, ic, FALSE, FALSE);
9374 aopOp(result, ic, FALSE, AOP_USESDPTR(left));
9377 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
9379 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
9380 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
9382 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
9385 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
9387 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
9388 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
9390 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
9396 emitcode ("; shift left ", "result %d, left %d", size,
9400 /* I suppose that the left size >= result size */
9403 _startLazyDPSEvaluation();
9406 movLeft2Result (left, size, result, size, 0);
9408 _endLazyDPSEvaluation();
9410 else if (shCount >= (size * 8))
9412 _startLazyDPSEvaluation();
9415 aopPut (result, zero, size);
9417 _endLazyDPSEvaluation();
9424 genlshOne (result, left, shCount);
9428 genlshTwo (result, left, shCount);
9432 genlshFour (result, left, shCount);
9436 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9437 "*** ack! mystery literal shift!\n");
9441 freeAsmop (result, NULL, ic, TRUE);
9442 freeAsmop (left, NULL, ic, TRUE);
9447 /*-----------------------------------------------------------------*/
9448 /* genLeftShift - generates code for left shifting */
9449 /*-----------------------------------------------------------------*/
9451 genLeftShift (iCode * ic)
9453 operand *left, *right, *result;
9456 symbol *tlbl, *tlbl1;
9459 D (emitcode (";", "genLeftShift"));
9461 right = IC_RIGHT (ic);
9462 left = IC_LEFT (ic);
9463 result = IC_RESULT (ic);
9465 aopOp (right, ic, FALSE, FALSE);
9468 #ifdef BETTER_LITERAL_SHIFT
9469 /* if the shift count is known then do it
9470 as efficiently as possible */
9471 if (AOP_TYPE (right) == AOP_LIT)
9473 if (genLeftShiftLiteral (left, right, result, ic))
9480 /* shift count is unknown then we have to form
9481 a loop get the loop count in B : Note: we take
9482 only the lower order byte since shifting
9483 more that 32 bits make no sense anyway, ( the
9484 largest size of an object can be only 32 bits ) */
9487 if (AOP_TYPE (right) == AOP_LIT)
9489 /* Really should be handled by genLeftShiftLiteral,
9490 * but since I'm too lazy to fix that today, at least we can make
9491 * some small improvement.
9493 emitcode("mov", "b,#!constbyte",
9494 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9498 MOVB (aopGet (right, 0, FALSE, FALSE, "b"));
9499 emitcode ("inc", "b");
9501 freeAsmop (right, NULL, ic, TRUE);
9502 aopOp (left, ic, FALSE, FALSE);
9503 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9505 /* now move the left to the result if they are not the same */
9506 if (!sameRegs (AOP (left), AOP (result)) &&
9507 AOP_SIZE (result) > 1)
9510 size = AOP_SIZE (result);
9512 _startLazyDPSEvaluation ();
9515 l = aopGet (left, offset, FALSE, TRUE, NULL);
9516 if (*l == '@' && (IS_AOP_PREG (result)))
9519 emitcode ("mov", "a,%s", l);
9520 aopPut (result, "a", offset);
9523 aopPut (result, l, offset);
9526 _endLazyDPSEvaluation ();
9529 tlbl = newiTempLabel (NULL);
9530 size = AOP_SIZE (result);
9532 tlbl1 = newiTempLabel (NULL);
9534 /* if it is only one byte then */
9537 symbol *tlbl1 = newiTempLabel (NULL);
9539 l = aopGet (left, 0, FALSE, FALSE, NULL);
9541 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9543 emitcode ("add", "a,acc");
9545 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9547 aopPut (result, "a", 0);
9551 reAdjustPreg (AOP (result));
9553 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9555 l = aopGet (result, offset, FALSE, FALSE, NULL);
9557 emitcode ("add", "a,acc");
9558 aopPut (result, "a", offset++);
9559 _startLazyDPSEvaluation ();
9562 l = aopGet (result, offset, FALSE, FALSE, NULL);
9564 emitcode ("rlc", "a");
9565 aopPut (result, "a", offset++);
9567 _endLazyDPSEvaluation ();
9568 reAdjustPreg (AOP (result));
9571 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9574 freeAsmop (result, NULL, ic, TRUE);
9575 freeAsmop (left, NULL, ic, TRUE);
9578 #ifdef BETTER_LITERAL_SHIFT
9579 /*-----------------------------------------------------------------*/
9580 /* genrshOne - right shift a one byte quantity by known count */
9581 /*-----------------------------------------------------------------*/
9583 genrshOne (operand * result, operand * left,
9584 int shCount, int sign)
9586 D (emitcode (";", "genrshOne"));
9588 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9592 #ifdef BETTER_LITERAL_SHIFT
9593 /*-----------------------------------------------------------------*/
9594 /* genrshTwo - right shift two bytes by known amount != 0 */
9595 /*-----------------------------------------------------------------*/
9597 genrshTwo (operand * result, operand * left,
9598 int shCount, int sign)
9600 D (emitcode (";", "genrshTwo"));
9602 /* if shCount >= 8 */
9606 _startLazyDPSEvaluation();
9608 shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
9610 movLeft2Result (left, MSB16, result, LSB, sign);
9611 addSign (result, MSB16, sign);
9612 _endLazyDPSEvaluation();
9615 /* 1 <= shCount <= 7 */
9617 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9621 /*-----------------------------------------------------------------*/
9622 /* shiftRLong - shift right one long from left to result */
9623 /* offl = LSB or MSB16 */
9624 /*-----------------------------------------------------------------*/
9626 shiftRLong (operand * left, int offl,
9627 operand * result, int sign)
9629 int isSameRegs=sameRegs(AOP(left),AOP(result));
9631 if (isSameRegs && offl>1) {
9632 // we are in big trouble, but this shouldn't happen
9633 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9636 MOVA (aopGet (left, MSB32, FALSE, FALSE, NULL));
9643 emitcode ("rlc", "a");
9644 emitcode ("subb", "a,acc");
9645 emitcode ("xch", "a,%s",
9646 aopGet(left, MSB32, FALSE, FALSE, DP2_RESULT_REG));
9650 aopPut (result, zero, MSB32);
9656 emitcode ("clr", "c");
9660 emitcode ("mov", "c,acc.7");
9663 emitcode ("rrc", "a");
9665 if (isSameRegs && offl==MSB16) {
9667 "a,%s",aopGet (left, MSB24, FALSE, FALSE, DP2_RESULT_REG));
9669 aopPut (result, "a", MSB32);
9670 MOVA (aopGet (left, MSB24, FALSE, FALSE, NULL));
9673 emitcode ("rrc", "a");
9674 if (isSameRegs && offl==1) {
9675 emitcode ("xch", "a,%s",
9676 aopGet (left, MSB16, FALSE, FALSE, DP2_RESULT_REG));
9678 aopPut (result, "a", MSB24);
9679 MOVA (aopGet (left, MSB16, FALSE, FALSE, NULL));
9681 emitcode ("rrc", "a");
9682 aopPut (result, "a", MSB16 - offl);
9686 MOVA (aopGet (left, LSB, FALSE, FALSE, NULL));
9687 emitcode ("rrc", "a");
9688 aopPut (result, "a", LSB);
9692 /*-----------------------------------------------------------------*/
9693 /* genrshFour - shift four byte by a known amount != 0 */
9694 /*-----------------------------------------------------------------*/
9696 genrshFour (operand * result, operand * left,
9697 int shCount, int sign)
9699 D (emitcode (";", "genrshFour"));
9701 /* if shifting more that 3 bytes */
9705 _startLazyDPSEvaluation();
9707 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9709 movLeft2Result (left, MSB32, result, LSB, sign);
9710 addSign (result, MSB16, sign);
9711 _endLazyDPSEvaluation();
9713 else if (shCount >= 16)
9716 _startLazyDPSEvaluation();
9718 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9721 movLeft2Result (left, MSB24, result, LSB, 0);
9722 movLeft2Result (left, MSB32, result, MSB16, sign);
9724 addSign (result, MSB24, sign);
9725 _endLazyDPSEvaluation();
9727 else if (shCount >= 8)
9730 _startLazyDPSEvaluation();
9733 shiftRLong (left, MSB16, result, sign);
9735 else if (shCount == 0)
9737 movLeft2Result (left, MSB16, result, LSB, 0);
9738 movLeft2Result (left, MSB24, result, MSB16, 0);
9739 movLeft2Result (left, MSB32, result, MSB24, sign);
9740 addSign (result, MSB32, sign);
9744 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9745 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9746 /* the last shift is signed */
9747 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9748 addSign (result, MSB32, sign);
9750 _endLazyDPSEvaluation();
9754 /* 1 <= shCount <= 7 */
9757 shiftRLong (left, LSB, result, sign);
9759 shiftRLong (result, LSB, result, sign);
9763 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9764 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9765 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9770 #ifdef BETTER_LITERAL_SHIFT
9771 /*-----------------------------------------------------------------*/
9772 /* genRightShiftLiteral - right shifting by known count */
9773 /*-----------------------------------------------------------------*/
9775 genRightShiftLiteral (operand * left,
9781 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9784 size = getSize (operandType (result));
9786 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
9788 /* We only handle certain easy cases so far. */
9790 && (shCount < (size * 8))
9795 D(emitcode (";", "genRightShiftLiteral wimping out"););
9799 freeAsmop (right, NULL, ic, TRUE);
9801 aopOp (left, ic, FALSE, FALSE);
9802 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9805 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9809 /* test the LEFT size !!! */
9811 /* I suppose that the left size >= result size */
9814 size = getDataSize (result);
9815 _startLazyDPSEvaluation();
9817 movLeft2Result (left, size, result, size, 0);
9818 _endLazyDPSEvaluation();
9820 else if (shCount >= (size * 8))
9824 /* get sign in acc.7 */
9825 MOVA (aopGet (left, size - 1, FALSE, FALSE, NULL));
9827 addSign (result, LSB, sign);
9834 genrshOne (result, left, shCount, sign);
9838 genrshTwo (result, left, shCount, sign);
9842 genrshFour (result, left, shCount, sign);
9849 freeAsmop (result, NULL, ic, TRUE);
9850 freeAsmop (left, NULL, ic, TRUE);
9856 /*-----------------------------------------------------------------*/
9857 /* genSignedRightShift - right shift of signed number */
9858 /*-----------------------------------------------------------------*/
9860 genSignedRightShift (iCode * ic)
9862 operand *right, *left, *result;
9865 symbol *tlbl, *tlbl1;
9868 D (emitcode (";", "genSignedRightShift"));
9870 /* we do it the hard way put the shift count in b
9871 and loop thru preserving the sign */
9873 right = IC_RIGHT (ic);
9874 left = IC_LEFT (ic);
9875 result = IC_RESULT (ic);
9877 aopOp (right, ic, FALSE, FALSE);
9879 #ifdef BETTER_LITERAL_SHIFT
9880 if (AOP_TYPE (right) == AOP_LIT)
9882 if (genRightShiftLiteral (left, right, result, ic, 1))
9888 /* shift count is unknown then we have to form
9889 a loop get the loop count in B : Note: we take
9890 only the lower order byte since shifting
9891 more that 32 bits make no sense anyway, ( the
9892 largest size of an object can be only 32 bits ) */
9895 if (AOP_TYPE (right) == AOP_LIT)
9897 /* Really should be handled by genRightShiftLiteral,
9898 * but since I'm too lazy to fix that today, at least we can make
9899 * some small improvement.
9901 emitcode("mov", "b,#!constbyte",
9902 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9906 MOVB (aopGet (right, 0, FALSE, FALSE, "b"));
9907 emitcode ("inc", "b");
9909 freeAsmop (right, NULL, ic, TRUE);
9910 aopOp (left, ic, FALSE, FALSE);
9911 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9913 /* now move the left to the result if they are not the
9915 if (!sameRegs (AOP (left), AOP (result)) &&
9916 AOP_SIZE (result) > 1)
9919 size = AOP_SIZE (result);
9921 _startLazyDPSEvaluation ();
9924 l = aopGet (left, offset, FALSE, TRUE, NULL);
9925 if (*l == '@' && IS_AOP_PREG (result))
9928 emitcode ("mov", "a,%s", l);
9929 aopPut (result, "a", offset);
9932 aopPut (result, l, offset);
9935 _endLazyDPSEvaluation ();
9938 /* mov the highest order bit to OVR */
9939 tlbl = newiTempLabel (NULL);
9940 tlbl1 = newiTempLabel (NULL);
9942 size = AOP_SIZE (result);
9944 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
9945 emitcode ("rlc", "a");
9946 emitcode ("mov", "ov,c");
9947 /* if it is only one byte then */
9950 l = aopGet (left, 0, FALSE, FALSE, NULL);
9952 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9954 emitcode ("mov", "c,ov");
9955 emitcode ("rrc", "a");
9957 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9959 aopPut (result, "a", 0);
9963 reAdjustPreg (AOP (result));
9964 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9966 emitcode ("mov", "c,ov");
9967 _startLazyDPSEvaluation ();
9970 l = aopGet (result, offset, FALSE, FALSE, NULL);
9972 emitcode ("rrc", "a");
9973 aopPut (result, "a", offset--);
9975 _endLazyDPSEvaluation ();
9976 reAdjustPreg (AOP (result));
9978 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9982 freeAsmop (result, NULL, ic, TRUE);
9983 freeAsmop (left, NULL, ic, TRUE);
9986 /*-----------------------------------------------------------------*/
9987 /* genRightShift - generate code for right shifting */
9988 /*-----------------------------------------------------------------*/
9990 genRightShift (iCode * ic)
9992 operand *right, *left, *result;
9996 symbol *tlbl, *tlbl1;
9999 D (emitcode (";", "genRightShift"));
10001 /* if signed then we do it the hard way preserve the
10002 sign bit moving it inwards */
10003 letype = getSpec (operandType (IC_LEFT (ic)));
10005 if (!SPEC_USIGN (letype))
10007 genSignedRightShift (ic);
10011 /* signed & unsigned types are treated the same : i.e. the
10012 signed is NOT propagated inwards : quoting from the
10013 ANSI - standard : "for E1 >> E2, is equivalent to division
10014 by 2**E2 if unsigned or if it has a non-negative value,
10015 otherwise the result is implementation defined ", MY definition
10016 is that the sign does not get propagated */
10018 right = IC_RIGHT (ic);
10019 left = IC_LEFT (ic);
10020 result = IC_RESULT (ic);
10022 aopOp (right, ic, FALSE, FALSE);
10024 #ifdef BETTER_LITERAL_SHIFT
10025 /* if the shift count is known then do it
10026 as efficiently as possible */
10027 if (AOP_TYPE (right) == AOP_LIT)
10029 if (genRightShiftLiteral (left, right, result, ic, 0))
10036 /* shift count is unknown then we have to form
10037 a loop get the loop count in B : Note: we take
10038 only the lower order byte since shifting
10039 more that 32 bits make no sense anyway, ( the
10040 largest size of an object can be only 32 bits ) */
10042 pushedB = pushB ();
10043 if (AOP_TYPE (right) == AOP_LIT)
10045 /* Really should be handled by genRightShiftLiteral,
10046 * but since I'm too lazy to fix that today, at least we can make
10047 * some small improvement.
10049 emitcode("mov", "b,#!constbyte",
10050 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
10054 MOVB (aopGet (right, 0, FALSE, FALSE, "b"));
10055 emitcode ("inc", "b");
10057 freeAsmop (right, NULL, ic, TRUE);
10058 aopOp (left, ic, FALSE, FALSE);
10059 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
10061 /* now move the left to the result if they are not the
10063 if (!sameRegs (AOP (left), AOP (result)) &&
10064 AOP_SIZE (result) > 1)
10066 size = AOP_SIZE (result);
10068 _startLazyDPSEvaluation ();
10071 l = aopGet (left, offset, FALSE, TRUE, NULL);
10072 if (*l == '@' && IS_AOP_PREG (result))
10075 emitcode ("mov", "a,%s", l);
10076 aopPut (result, "a", offset);
10079 aopPut (result, l, offset);
10082 _endLazyDPSEvaluation ();
10085 tlbl = newiTempLabel (NULL);
10086 tlbl1 = newiTempLabel (NULL);
10087 size = AOP_SIZE (result);
10090 /* if it is only one byte then */
10093 l = aopGet (left, 0, FALSE, FALSE, NULL);
10095 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
10098 emitcode ("rrc", "a");
10100 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
10102 aopPut (result, "a", 0);
10106 reAdjustPreg (AOP (result));
10107 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
10110 _startLazyDPSEvaluation ();
10113 l = aopGet (result, offset, FALSE, FALSE, NULL);
10115 emitcode ("rrc", "a");
10116 aopPut (result, "a", offset--);
10118 _endLazyDPSEvaluation ();
10119 reAdjustPreg (AOP (result));
10122 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
10126 freeAsmop (result, NULL, ic, TRUE);
10127 freeAsmop (left, NULL, ic, TRUE);
10130 /*-----------------------------------------------------------------*/
10131 /* emitPtrByteGet - emits code to get a byte into A through a */
10132 /* pointer register (R0, R1, or DPTR). The */
10133 /* original value of A can be preserved in B. */
10134 /*-----------------------------------------------------------------*/
10136 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
10143 emitcode ("mov", "b,a");
10144 emitcode ("mov", "a,@%s", rname);
10149 emitcode ("mov", "b,a");
10150 emitcode ("movx", "a,@%s", rname);
10155 emitcode ("mov", "b,a");
10156 emitcode ("movx", "a,@dptr");
10161 emitcode ("mov", "b,a");
10162 emitcode ("clr", "a");
10163 emitcode ("movc", "a,@a+dptr");
10169 emitcode ("push", "b");
10170 emitcode ("push", "acc");
10172 emitcode ("lcall", "__gptrget");
10174 emitcode ("pop", "b");
10179 /*-----------------------------------------------------------------*/
10180 /* emitPtrByteSet - emits code to set a byte from src through a */
10181 /* pointer register (R0, R1, or DPTR). */
10182 /*-----------------------------------------------------------------*/
10184 emitPtrByteSet (char *rname, int p_type, char *src)
10193 emitcode ("mov", "@%s,a", rname);
10196 emitcode ("mov", "@%s,%s", rname, src);
10201 emitcode ("movx", "@%s,a", rname);
10206 emitcode ("movx", "@dptr,a");
10211 emitcode ("lcall", "__gptrput");
10216 /*-----------------------------------------------------------------*/
10217 /* genUnpackBits - generates code for unpacking bits */
10218 /*-----------------------------------------------------------------*/
10220 genUnpackBits (operand * result, char *rname, int ptype)
10222 int offset = 0; /* result byte offset */
10223 int rsize; /* result size */
10224 int rlen = 0; /* remaining bitfield length */
10225 sym_link *etype; /* bitfield type information */
10226 int blen; /* bitfield length */
10227 int bstr; /* bitfield starting bit within byte */
10229 D(emitcode ("; genUnpackBits",""));
10231 etype = getSpec (operandType (result));
10232 rsize = getSize (operandType (result));
10233 blen = SPEC_BLEN (etype);
10234 bstr = SPEC_BSTR (etype);
10236 /* If the bitfield length is less than a byte */
10239 emitPtrByteGet (rname, ptype, FALSE);
10241 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
10242 if (!SPEC_USIGN (etype))
10244 /* signed bitfield */
10245 symbol *tlbl = newiTempLabel (NULL);
10247 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
10248 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
10251 aopPut (result, "a", offset++);
10255 /* Bit field did not fit in a byte. Copy all
10256 but the partial byte at the end. */
10257 for (rlen=blen;rlen>=8;rlen-=8)
10259 emitPtrByteGet (rname, ptype, FALSE);
10260 aopPut (result, "a", offset++);
10262 emitcode ("inc", "%s", rname);
10265 /* Handle the partial byte at the end */
10268 emitPtrByteGet (rname, ptype, FALSE);
10269 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
10270 if (!SPEC_USIGN (etype))
10272 /* signed bitfield */
10273 symbol *tlbl = newiTempLabel (NULL);
10275 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
10276 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
10279 aopPut (result, "a", offset++);
10283 if (offset < rsize)
10287 if (SPEC_USIGN (etype))
10291 /* signed bitfield: sign extension with 0x00 or 0xff */
10292 emitcode ("rlc", "a");
10293 emitcode ("subb", "a,acc");
10299 aopPut (result, source, offset++);
10304 /*-----------------------------------------------------------------*/
10305 /* genDataPointerGet - generates code when ptr offset is known */
10306 /*-----------------------------------------------------------------*/
10308 genDataPointerGet (operand * left,
10314 int size, offset = 0;
10315 aopOp (result, ic, TRUE, FALSE);
10317 /* get the string representation of the name */
10318 l = aopGet (left, 0, FALSE, TRUE, NULL);
10319 size = AOP_SIZE (result);
10320 _startLazyDPSEvaluation ();
10325 SNPRINTF (buffer, sizeof(buffer),
10326 "(%s + %d)", l + 1, offset);
10330 SNPRINTF (buffer, sizeof(buffer),
10333 aopPut (result, buffer, offset++);
10335 _endLazyDPSEvaluation ();
10337 freeAsmop (result, NULL, ic, TRUE);
10338 freeAsmop (left, NULL, ic, TRUE);
10341 /*-----------------------------------------------------------------*/
10342 /* genNearPointerGet - emitcode for near pointer fetch */
10343 /*-----------------------------------------------------------------*/
10345 genNearPointerGet (operand * left,
10353 sym_link *rtype, *retype, *letype;
10354 sym_link *ltype = operandType (left);
10357 rtype = operandType (result);
10358 retype = getSpec (rtype);
10359 letype = getSpec (ltype);
10361 aopOp (left, ic, FALSE, FALSE);
10363 /* if left is rematerialisable and
10364 result is not bitfield variable type and
10365 the left is pointer to data space i.e
10366 lower 128 bytes of space */
10367 if (AOP_TYPE (left) == AOP_IMMD &&
10368 !IS_BITFIELD (retype) &&
10369 !IS_BITFIELD (letype) &&
10370 DCL_TYPE (ltype) == POINTER)
10372 genDataPointerGet (left, result, ic);
10376 /* if the value is already in a pointer register
10377 then don't need anything more */
10378 if (!AOP_INPREG (AOP (left)))
10380 /* otherwise get a free pointer register */
10381 aop = newAsmop (0);
10382 preg = getFreePtr (ic, &aop, FALSE);
10383 emitcode ("mov", "%s,%s",
10385 aopGet (left, 0, FALSE, TRUE, DP2_RESULT_REG));
10386 rname = preg->name;
10389 rname = aopGet (left, 0, FALSE, FALSE, DP2_RESULT_REG);
10391 freeAsmop (left, NULL, ic, TRUE);
10392 aopOp (result, ic, FALSE, FALSE);
10394 /* if bitfield then unpack the bits */
10395 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10396 genUnpackBits (result, rname, POINTER);
10399 /* we have can just get the values */
10400 int size = AOP_SIZE (result);
10405 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
10408 emitcode ("mov", "a,@%s", rname);
10409 aopPut (result, "a", offset);
10413 SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
10414 aopPut (result, buffer, offset);
10418 emitcode ("inc", "%s", rname);
10422 /* now some housekeeping stuff */
10423 if (aop) /* we had to allocate for this iCode */
10425 if (pi) { /* post increment present */
10426 aopPut (left, rname, 0);
10428 freeAsmop (NULL, aop, ic, TRUE);
10432 /* we did not allocate which means left
10433 already in a pointer register, then
10434 if size > 0 && this could be used again
10435 we have to point it back to where it
10437 if (AOP_SIZE (result) > 1 &&
10438 !OP_SYMBOL (left)->remat &&
10439 (OP_SYMBOL (left)->liveTo > ic->seq ||
10443 int size = AOP_SIZE (result) - 1;
10445 emitcode ("dec", "%s", rname);
10450 freeAsmop (result, NULL, ic, TRUE);
10451 if (pi) pi->generated = 1;
10454 /*-----------------------------------------------------------------*/
10455 /* genPagedPointerGet - emitcode for paged pointer fetch */
10456 /*-----------------------------------------------------------------*/
10458 genPagedPointerGet (operand * left,
10466 sym_link *rtype, *retype, *letype;
10468 rtype = operandType (result);
10469 retype = getSpec (rtype);
10470 letype = getSpec (operandType (left));
10471 aopOp (left, ic, FALSE, FALSE);
10473 /* if the value is already in a pointer register
10474 then don't need anything more */
10475 if (!AOP_INPREG (AOP (left)))
10477 /* otherwise get a free pointer register */
10478 aop = newAsmop (0);
10479 preg = getFreePtr (ic, &aop, FALSE);
10480 emitcode ("mov", "%s,%s",
10482 aopGet (left, 0, FALSE, TRUE, NULL));
10483 rname = preg->name;
10486 rname = aopGet (left, 0, FALSE, FALSE, NULL);
10488 freeAsmop (left, NULL, ic, TRUE);
10489 aopOp (result, ic, FALSE, FALSE);
10491 /* if bitfield then unpack the bits */
10492 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10493 genUnpackBits (result, rname, PPOINTER);
10496 /* we have can just get the values */
10497 int size = AOP_SIZE (result);
10503 emitcode ("movx", "a,@%s", rname);
10504 aopPut (result, "a", offset);
10509 emitcode ("inc", "%s", rname);
10513 /* now some housekeeping stuff */
10514 if (aop) /* we had to allocate for this iCode */
10517 aopPut (left, rname, 0);
10518 freeAsmop (NULL, aop, ic, TRUE);
10522 /* we did not allocate which means left
10523 already in a pointer register, then
10524 if size > 0 && this could be used again
10525 we have to point it back to where it
10527 if (AOP_SIZE (result) > 1 &&
10528 !OP_SYMBOL (left)->remat &&
10529 (OP_SYMBOL (left)->liveTo > ic->seq ||
10533 int size = AOP_SIZE (result) - 1;
10535 emitcode ("dec", "%s", rname);
10540 freeAsmop (result, NULL, ic, TRUE);
10541 if (pi) pi->generated = 1;
10544 /*-----------------------------------------------------------------*/
10545 /* genFarPointerGet - get value from far space */
10546 /*-----------------------------------------------------------------*/
10548 genFarPointerGet (operand * left,
10549 operand * result, iCode * ic, iCode *pi)
10551 int size, offset, dopi=1;
10552 sym_link *retype = getSpec (operandType (result));
10553 sym_link *letype = getSpec (operandType (left));
10554 D (emitcode (";", "genFarPointerGet"););
10556 aopOp (left, ic, FALSE, FALSE);
10558 /* if the operand is already in dptr
10559 then we do nothing else we move the value to dptr */
10560 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
10562 /* if this is rematerializable */
10563 if (AOP_TYPE (left) == AOP_IMMD)
10565 emitcode ("mov", "dptr,%s", aopGet (left, 0, TRUE, FALSE, NULL));
10569 /* we need to get it byte by byte */
10570 _startLazyDPSEvaluation ();
10571 if (AOP_TYPE (left) != AOP_DPTR)
10573 emitcode ("mov", "dpl,%s", aopGet (left, 0, FALSE, FALSE, NULL));
10574 emitcode ("mov", "dph,%s", aopGet (left, 1, FALSE, FALSE, NULL));
10575 if (options.model == MODEL_FLAT24)
10576 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10580 /* We need to generate a load to DPTR indirect through DPTR. */
10581 D (emitcode (";", "genFarPointerGet -- indirection special case."););
10582 emitcode ("push", "%s", aopGet (left, 0, FALSE, TRUE, NULL));
10583 emitcode ("push", "%s", aopGet (left, 1, FALSE, TRUE, NULL));
10584 if (options.model == MODEL_FLAT24)
10585 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10586 emitcode ("pop", "dph");
10587 emitcode ("pop", "dpl");
10590 _endLazyDPSEvaluation ();
10593 /* so dptr now contains the address */
10594 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10596 /* if bit then unpack */
10597 if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
10598 if (AOP_INDPTRn(left)) {
10599 genSetDPTR(AOP(left)->aopu.dptr);
10601 genUnpackBits (result, "dptr", FPOINTER);
10602 if (AOP_INDPTRn(left)) {
10607 size = AOP_SIZE (result);
10610 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10612 genSetDPTR(AOP(left)->aopu.dptr);
10613 emitcode ("movx", "a,@dptr");
10614 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10615 emitcode ("inc", "dptr");
10617 aopPut (result, "a", offset++);
10620 _startLazyDPSEvaluation ();
10622 if (AOP_INDPTRn(left)) {
10623 genSetDPTR(AOP(left)->aopu.dptr);
10629 emitcode ("movx", "a,@dptr");
10630 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10631 emitcode ("inc", "dptr");
10633 aopPut (result, "a", offset++);
10635 _endLazyDPSEvaluation ();
10638 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10639 if (!AOP_INDPTRn(left)) {
10640 _startLazyDPSEvaluation ();
10641 aopPut (left, "dpl", 0);
10642 aopPut (left, "dph", 1);
10643 if (options.model == MODEL_FLAT24)
10644 aopPut (left, "dpx", 2);
10645 _endLazyDPSEvaluation ();
10648 } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) &&
10649 AOP_SIZE(result) > 1 &&
10651 (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
10653 size = AOP_SIZE (result) - 1;
10654 if (AOP_INDPTRn(left)) {
10655 genSetDPTR(AOP(left)->aopu.dptr);
10657 while (size--) emitcode ("lcall","__decdptr");
10658 if (AOP_INDPTRn(left)) {
10663 freeAsmop (result, NULL, ic, TRUE);
10664 freeAsmop (left, NULL, ic, TRUE);
10667 /*-----------------------------------------------------------------*/
10668 /* genCodePointerGet - get value from code space */
10669 /*-----------------------------------------------------------------*/
10671 genCodePointerGet (operand * left,
10672 operand * result, iCode * ic, iCode *pi)
10674 int size, offset, dopi=1;
10675 sym_link *retype = getSpec (operandType (result));
10677 aopOp (left, ic, FALSE, FALSE);
10679 /* if the operand is already in dptr
10680 then we do nothing else we move the value to dptr */
10681 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
10683 /* if this is rematerializable */
10684 if (AOP_TYPE (left) == AOP_IMMD)
10686 emitcode ("mov", "dptr,%s", aopGet (left, 0, TRUE, FALSE, NULL));
10689 { /* we need to get it byte by byte */
10690 _startLazyDPSEvaluation ();
10691 if (AOP_TYPE (left) != AOP_DPTR)
10693 emitcode ("mov", "dpl,%s", aopGet (left, 0, FALSE, FALSE, NULL));
10694 emitcode ("mov", "dph,%s", aopGet (left, 1, FALSE, FALSE, NULL));
10695 if (options.model == MODEL_FLAT24)
10696 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10700 /* We need to generate a load to DPTR indirect through DPTR. */
10701 D (emitcode (";", "gencodePointerGet -- indirection special case."););
10702 emitcode ("push", "%s", aopGet (left, 0, FALSE, TRUE, NULL));
10703 emitcode ("push", "%s", aopGet (left, 1, FALSE, TRUE, NULL));
10704 if (options.model == MODEL_FLAT24)
10705 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10706 emitcode ("pop", "dph");
10707 emitcode ("pop", "dpl");
10710 _endLazyDPSEvaluation ();
10713 /* so dptr now contains the address */
10714 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10716 /* if bit then unpack */
10717 if (IS_BITFIELD (retype)) {
10718 if (AOP_INDPTRn(left)) {
10719 genSetDPTR(AOP(left)->aopu.dptr);
10721 genUnpackBits (result, "dptr", CPOINTER);
10722 if (AOP_INDPTRn(left)) {
10727 size = AOP_SIZE (result);
10729 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10731 genSetDPTR(AOP(left)->aopu.dptr);
10732 emitcode ("clr", "a");
10733 emitcode ("movc", "a,@a+dptr");
10734 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10735 emitcode ("inc", "dptr");
10737 aopPut (result, "a", offset++);
10740 _startLazyDPSEvaluation ();
10743 if (AOP_INDPTRn(left)) {
10744 genSetDPTR(AOP(left)->aopu.dptr);
10750 emitcode ("clr", "a");
10751 emitcode ("movc", "a,@a+dptr");
10752 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10753 emitcode ("inc", "dptr");
10754 aopPut (result, "a", offset++);
10756 _endLazyDPSEvaluation ();
10759 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10760 if (!AOP_INDPTRn(left)) {
10761 _startLazyDPSEvaluation ();
10763 aopPut (left, "dpl", 0);
10764 aopPut (left, "dph", 1);
10765 if (options.model == MODEL_FLAT24)
10766 aopPut (left, "dpx", 2);
10768 _endLazyDPSEvaluation ();
10771 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
10772 AOP_SIZE(result) > 1 &&
10773 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10775 size = AOP_SIZE (result) - 1;
10776 if (AOP_INDPTRn(left)) {
10777 genSetDPTR(AOP(left)->aopu.dptr);
10779 while (size--) emitcode ("lcall","__decdptr");
10780 if (AOP_INDPTRn(left)) {
10785 freeAsmop (result, NULL, ic, TRUE);
10786 freeAsmop (left, NULL, ic, TRUE);
10789 /*-----------------------------------------------------------------*/
10790 /* genGenPointerGet - get value from generic pointer space */
10791 /*-----------------------------------------------------------------*/
10793 genGenPointerGet (operand * left,
10794 operand * result, iCode * ic, iCode * pi)
10798 sym_link *retype = getSpec (operandType (result));
10799 sym_link *letype = getSpec (operandType (left));
10801 D (emitcode (";", "genGenPointerGet"));
10803 aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
10805 pushedB = pushB ();
10806 /* if the operand is already in dptr
10807 then we do nothing else we move the value to dptr */
10808 if (AOP_TYPE (left) != AOP_STR)
10810 /* if this is rematerializable */
10811 if (AOP_TYPE (left) == AOP_IMMD)
10813 emitcode ("mov", "dptr,%s", aopGet (left, 0, TRUE, FALSE, NULL));
10814 if (AOP(left)->aopu.aop_immd.from_cast_remat)
10816 MOVB (aopGet (left, AOP_SIZE(left)-1, FALSE, FALSE, NULL));
10820 emitcode ("mov", "b,#%d", pointerCode (retype));
10824 { /* we need to get it byte by byte */
10825 _startLazyDPSEvaluation ();
10826 emitcode ("mov", "dpl,%s", aopGet (left,0,FALSE,FALSE,NULL));
10827 emitcode ("mov", "dph,%s", aopGet (left,1,FALSE,FALSE,NULL));
10828 if (options.model == MODEL_FLAT24) {
10829 emitcode ("mov", "dpx,%s", aopGet (left,2,FALSE,FALSE,NULL));
10830 emitcode ("mov", "b,%s", aopGet (left,3,FALSE,FALSE,NULL));
10832 emitcode ("mov", "b,%s", aopGet (left,2,FALSE,FALSE,NULL));
10834 _endLazyDPSEvaluation ();
10838 /* so dptr-b now contains the address */
10839 aopOp (result, ic, FALSE, TRUE);
10841 /* if bit then unpack */
10842 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10844 genUnpackBits (result, "dptr", GPOINTER);
10848 size = AOP_SIZE (result);
10855 // Get two bytes at a time, results in _AP & A.
10856 // dptr will be incremented ONCE by __gptrgetWord.
10858 // Note: any change here must be coordinated
10859 // with the implementation of __gptrgetWord
10860 // in device/lib/_gptrget.c
10861 emitcode ("lcall", "__gptrgetWord");
10862 aopPut (result, DP2_RESULT_REG, offset++);
10863 aopPut (result, "a", offset++);
10868 // Only one byte to get.
10869 emitcode ("lcall", "__gptrget");
10870 aopPut (result, "a", offset++);
10873 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
10875 emitcode ("inc", "dptr");
10880 if (pi && AOP_TYPE (left) != AOP_IMMD) {
10881 _startLazyDPSEvaluation ();
10883 aopPut (left, "dpl", 0);
10884 aopPut (left, "dph", 1);
10885 if (options.model == MODEL_FLAT24) {
10886 aopPut (left, "dpx", 2);
10887 aopPut (left, "b", 3);
10888 } else aopPut (left, "b", 2);
10890 _endLazyDPSEvaluation ();
10893 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
10894 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10896 size = AOP_SIZE (result) - 1;
10897 while (size--) emitcode ("lcall","__decdptr");
10901 freeAsmop (result, NULL, ic, TRUE);
10902 freeAsmop (left, NULL, ic, TRUE);
10905 /*-----------------------------------------------------------------*/
10906 /* genPointerGet - generate code for pointer get */
10907 /*-----------------------------------------------------------------*/
10909 genPointerGet (iCode * ic, iCode *pi)
10911 operand *left, *result;
10912 sym_link *type, *etype;
10915 D (emitcode (";", "genPointerGet"));
10917 left = IC_LEFT (ic);
10918 result = IC_RESULT (ic);
10920 /* depending on the type of pointer we need to
10921 move it to the correct pointer register */
10922 type = operandType (left);
10923 etype = getSpec (type);
10924 /* if left is of type of pointer then it is simple */
10925 if (IS_PTR (type) && !IS_FUNC (type->next))
10926 p_type = DCL_TYPE (type);
10929 /* we have to go by the storage class */
10930 p_type = PTR_TYPE (SPEC_OCLS (etype));
10933 /* special case when cast remat */
10934 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10935 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10937 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10938 type = operandType (left);
10939 p_type = DCL_TYPE (type);
10941 /* now that we have the pointer type we assign
10942 the pointer values */
10948 genNearPointerGet (left, result, ic, pi);
10952 genPagedPointerGet (left, result, ic, pi);
10956 genFarPointerGet (left, result, ic, pi);
10960 genCodePointerGet (left, result, ic, pi);
10964 genGenPointerGet (left, result, ic, pi);
10970 /*-----------------------------------------------------------------*/
10971 /* genPackBits - generates code for packed bit storage */
10972 /*-----------------------------------------------------------------*/
10974 genPackBits (sym_link * etype,
10976 char *rname, int p_type)
10978 int offset = 0; /* source byte offset */
10979 int rlen = 0; /* remaining bitfield length */
10980 int blen; /* bitfield length */
10981 int bstr; /* bitfield starting bit within byte */
10982 int litval; /* source literal value (if AOP_LIT) */
10983 unsigned char mask; /* bitmask within current byte */
10985 D(emitcode ("; genPackBits",""));
10987 blen = SPEC_BLEN (etype);
10988 bstr = SPEC_BSTR (etype);
10990 /* If the bitfield length is less than a byte */
10993 mask = ((unsigned char) (0xFF << (blen + bstr)) |
10994 (unsigned char) (0xFF >> (8 - bstr)));
10996 if (AOP_TYPE (right) == AOP_LIT)
10998 /* Case with a bitfield length <8 and literal source
11000 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
11002 litval &= (~mask) & 0xff;
11003 emitPtrByteGet (rname, p_type, FALSE);
11004 if ((mask|litval)!=0xff)
11005 emitcode ("anl","a,#!constbyte", mask);
11007 emitcode ("orl","a,#!constbyte", litval);
11011 if ((blen==1) && (p_type!=GPOINTER))
11013 /* Case with a bitfield length == 1 and no generic pointer
11015 if (AOP_TYPE (right) == AOP_CRY)
11016 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
11019 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
11020 emitcode ("rrc","a");
11022 emitPtrByteGet (rname, p_type, FALSE);
11023 emitcode ("mov","acc.%d,c",bstr);
11028 /* Case with a bitfield length < 8 and arbitrary source
11030 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
11031 /* shift and mask source value */
11033 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
11035 pushedB = pushB ();
11036 /* transfer A to B and get next byte */
11037 emitPtrByteGet (rname, p_type, TRUE);
11039 emitcode ("anl", "a,#!constbyte", mask);
11040 emitcode ("orl", "a,b");
11041 if (p_type == GPOINTER)
11042 emitcode ("pop", "b");
11048 emitPtrByteSet (rname, p_type, "a");
11052 /* Bit length is greater than 7 bits. In this case, copy */
11053 /* all except the partial byte at the end */
11054 for (rlen=blen;rlen>=8;rlen-=8)
11056 emitPtrByteSet (rname, p_type,
11057 aopGet (right, offset++, FALSE, TRUE, NULL) );
11059 emitcode ("inc", "%s", rname);
11062 /* If there was a partial byte at the end */
11065 mask = (((unsigned char) -1 << rlen) & 0xff);
11067 if (AOP_TYPE (right) == AOP_LIT)
11069 /* Case with partial byte and literal source
11071 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
11072 litval >>= (blen-rlen);
11073 litval &= (~mask) & 0xff;
11074 emitPtrByteGet (rname, p_type, FALSE);
11075 if ((mask|litval)!=0xff)
11076 emitcode ("anl","a,#!constbyte", mask);
11078 emitcode ("orl","a,#!constbyte", litval);
11083 /* Case with partial byte and arbitrary source
11085 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11086 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
11088 pushedB = pushB ();
11089 /* transfer A to B and get next byte */
11090 emitPtrByteGet (rname, p_type, TRUE);
11092 emitcode ("anl", "a,#!constbyte", mask);
11093 emitcode ("orl", "a,b");
11094 if (p_type == GPOINTER)
11095 emitcode ("pop", "b");
11099 emitPtrByteSet (rname, p_type, "a");
11104 /*-----------------------------------------------------------------*/
11105 /* genDataPointerSet - remat pointer to data space */
11106 /*-----------------------------------------------------------------*/
11108 genDataPointerSet (operand * right,
11112 int size, offset = 0;
11113 char *l, buffer[256];
11115 D (emitcode (";", "genDataPointerSet"));
11117 aopOp (right, ic, FALSE, FALSE);
11119 l = aopGet (result, 0, FALSE, TRUE, NULL);
11120 size = AOP_SIZE (right);
11124 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l + 1, offset);
11126 SNPRINTF (buffer, sizeof(buffer), "%s", l + 1);
11127 emitcode ("mov", "%s,%s", buffer,
11128 aopGet (right, offset++, FALSE, FALSE, NULL));
11131 freeAsmop (result, NULL, ic, TRUE);
11132 freeAsmop (right, NULL, ic, TRUE);
11135 /*-----------------------------------------------------------------*/
11136 /* genNearPointerSet - emitcode for near pointer put */
11137 /*-----------------------------------------------------------------*/
11139 genNearPointerSet (operand * right,
11146 sym_link *retype, *letype;
11147 sym_link *ptype = operandType (result);
11149 D (emitcode (";", "genNearPointerSet"));
11151 retype = getSpec (operandType (right));
11152 letype = getSpec (ptype);
11154 aopOp (result, ic, FALSE, FALSE);
11156 /* if the result is rematerializable &
11157 in data space & not a bit variable */
11158 if (AOP_TYPE (result) == AOP_IMMD &&
11159 DCL_TYPE (ptype) == POINTER &&
11160 !IS_BITVAR (retype) &&
11161 !IS_BITVAR (letype))
11163 genDataPointerSet (right, result, ic);
11167 /* if the value is already in a pointer register
11168 then don't need anything more */
11169 if (!AOP_INPREG (AOP (result)))
11171 /* otherwise get a free pointer register */
11174 aop = newAsmop (0);
11175 preg = getFreePtr (ic, &aop, FALSE);
11176 emitcode ("mov", "%s,%s",
11178 aopGet (result, 0, FALSE, TRUE, NULL));
11179 rname = preg->name;
11183 rname = aopGet (result, 0, FALSE, FALSE, NULL);
11186 aopOp (right, ic, FALSE, FALSE);
11188 /* if bitfield then unpack the bits */
11189 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11190 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
11193 /* we can just get the values */
11194 int size = AOP_SIZE (right);
11199 l = aopGet (right, offset, FALSE, TRUE, NULL);
11200 if ((*l == '@') || (strcmp (l, "acc") == 0))
11203 emitcode ("mov", "@%s,a", rname);
11206 emitcode ("mov", "@%s,%s", rname, l);
11208 emitcode ("inc", "%s", rname);
11213 /* now some housekeeping stuff */
11214 if (aop) /* we had to allocate for this iCode */
11217 aopPut (result, rname, 0);
11218 freeAsmop (NULL, aop, ic, TRUE);
11222 /* we did not allocate which means left
11223 already in a pointer register, then
11224 if size > 0 && this could be used again
11225 we have to point it back to where it
11227 if (AOP_SIZE (right) > 1 &&
11228 !OP_SYMBOL (result)->remat &&
11229 (OP_SYMBOL (result)->liveTo > ic->seq ||
11233 int size = AOP_SIZE (right) - 1;
11235 emitcode ("dec", "%s", rname);
11240 if (pi) pi->generated = 1;
11241 freeAsmop (result, NULL, ic, TRUE);
11242 freeAsmop (right, NULL, ic, TRUE);
11245 /*-----------------------------------------------------------------*/
11246 /* genPagedPointerSet - emitcode for Paged pointer put */
11247 /*-----------------------------------------------------------------*/
11249 genPagedPointerSet (operand * right,
11256 sym_link *retype, *letype;
11258 D (emitcode (";", "genPagedPointerSet"));
11260 retype = getSpec (operandType (right));
11261 letype = getSpec (operandType (result));
11263 aopOp (result, ic, FALSE, FALSE);
11265 /* if the value is already in a pointer register
11266 then don't need anything more */
11267 if (!AOP_INPREG (AOP (result)))
11269 /* otherwise get a free pointer register */
11272 aop = newAsmop (0);
11273 preg = getFreePtr (ic, &aop, FALSE);
11274 emitcode ("mov", "%s,%s",
11276 aopGet (result, 0, FALSE, TRUE, NULL));
11277 rname = preg->name;
11280 rname = aopGet (result, 0, FALSE, FALSE, NULL);
11282 aopOp (right, ic, FALSE, FALSE);
11284 /* if bitfield then unpack the bits */
11285 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11286 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
11289 /* we have can just get the values */
11290 int size = AOP_SIZE (right);
11295 l = aopGet (right, offset, FALSE, TRUE, NULL);
11297 emitcode ("movx", "@%s,a", rname);
11300 emitcode ("inc", "%s", rname);
11306 /* now some housekeeping stuff */
11310 aopPut (result, rname, 0);
11311 /* we had to allocate for this iCode */
11312 freeAsmop (NULL, aop, ic, TRUE);
11316 /* we did not allocate which means left
11317 already in a pointer register, then
11318 if size > 0 && this could be used again
11319 we have to point it back to where it
11321 if (AOP_SIZE (right) > 1 &&
11322 !OP_SYMBOL (result)->remat &&
11323 (OP_SYMBOL (result)->liveTo > ic->seq ||
11327 int size = AOP_SIZE (right) - 1;
11329 emitcode ("dec", "%s", rname);
11334 if (pi) pi->generated = 1;
11335 freeAsmop (result, NULL, ic, TRUE);
11336 freeAsmop (right, NULL, ic, TRUE);
11339 /*-----------------------------------------------------------------*/
11340 /* genFarPointerSet - set value from far space */
11341 /*-----------------------------------------------------------------*/
11343 genFarPointerSet (operand * right,
11344 operand * result, iCode * ic, iCode *pi)
11346 int size, offset, dopi=1;
11347 sym_link *retype = getSpec (operandType (right));
11348 sym_link *letype = getSpec (operandType (result));
11350 aopOp (result, ic, FALSE, FALSE);
11352 /* if the operand is already in dptr
11353 then we do nothing else we move the value to dptr */
11354 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
11356 /* if this is remateriazable */
11357 if (AOP_TYPE (result) == AOP_IMMD)
11358 emitcode ("mov", "dptr,%s",
11359 aopGet (result, 0, TRUE, FALSE, NULL));
11362 /* we need to get it byte by byte */
11363 _startLazyDPSEvaluation ();
11364 if (AOP_TYPE (result) != AOP_DPTR)
11366 emitcode ("mov", "dpl,%s", aopGet (result, 0, FALSE, FALSE, NULL));
11367 emitcode ("mov", "dph,%s", aopGet (result, 1, FALSE, FALSE, NULL));
11368 if (options.model == MODEL_FLAT24)
11369 emitcode ("mov", "dpx,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11373 /* We need to generate a load to DPTR indirect through DPTR. */
11374 D (emitcode (";", "genFarPointerSet -- indirection special case."););
11376 emitcode ("push", "%s", aopGet (result, 0, FALSE, TRUE, NULL));
11377 emitcode ("push", "%s", aopGet (result, 1, FALSE, TRUE, NULL));
11378 if (options.model == MODEL_FLAT24)
11379 emitcode ("mov", "dpx,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11380 emitcode ("pop", "dph");
11381 emitcode ("pop", "dpl");
11384 _endLazyDPSEvaluation ();
11387 /* so dptr now contains the address */
11388 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
11390 /* if bit then unpack */
11391 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11393 if (AOP_INDPTRn(result)) {
11394 genSetDPTR(AOP(result)->aopu.dptr);
11396 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
11397 if (AOP_INDPTRn(result)) {
11401 size = AOP_SIZE (right);
11403 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
11405 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11407 genSetDPTR(AOP(result)->aopu.dptr);
11408 emitcode ("movx", "@dptr,a");
11409 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
11410 emitcode ("inc", "dptr");
11414 _startLazyDPSEvaluation ();
11416 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11418 if (AOP_INDPTRn(result)) {
11419 genSetDPTR(AOP(result)->aopu.dptr);
11425 emitcode ("movx", "@dptr,a");
11426 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
11427 emitcode ("inc", "dptr");
11429 _endLazyDPSEvaluation ();
11433 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
11434 if (!AOP_INDPTRn(result)) {
11435 _startLazyDPSEvaluation ();
11437 aopPut (result,"dpl",0);
11438 aopPut (result,"dph",1);
11439 if (options.model == MODEL_FLAT24)
11440 aopPut (result,"dpx",2);
11442 _endLazyDPSEvaluation ();
11445 } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
11446 AOP_SIZE(right) > 1 &&
11447 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
11449 size = AOP_SIZE (right) - 1;
11450 if (AOP_INDPTRn(result)) {
11451 genSetDPTR(AOP(result)->aopu.dptr);
11453 while (size--) emitcode ("lcall","__decdptr");
11454 if (AOP_INDPTRn(result)) {
11458 freeAsmop (result, NULL, ic, TRUE);
11459 freeAsmop (right, NULL, ic, TRUE);
11462 /*-----------------------------------------------------------------*/
11463 /* genGenPointerSet - set value from generic pointer space */
11464 /*-----------------------------------------------------------------*/
11466 genGenPointerSet (operand * right,
11467 operand * result, iCode * ic, iCode *pi)
11471 sym_link *retype = getSpec (operandType (right));
11472 sym_link *letype = getSpec (operandType (result));
11474 aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
11476 pushedB = pushB ();
11477 /* if the operand is already in dptr
11478 then we do nothing else we move the value to dptr */
11479 if (AOP_TYPE (result) != AOP_STR)
11481 _startLazyDPSEvaluation ();
11482 /* if this is remateriazable */
11483 if (AOP_TYPE (result) == AOP_IMMD)
11485 emitcode ("mov", "dptr,%s", aopGet (result, 0, TRUE, FALSE, NULL));
11486 if (AOP(result)->aopu.aop_immd.from_cast_remat)
11488 MOVB (aopGet (result, AOP_SIZE(result)-1, FALSE, FALSE, NULL));
11493 "b,%s + 1", aopGet (result, 0, TRUE, FALSE, NULL));
11497 { /* we need to get it byte by byte */
11498 emitcode ("mov", "dpl,%s", aopGet (result, 0, FALSE, FALSE, NULL));
11499 emitcode ("mov", "dph,%s", aopGet (result, 1, FALSE, FALSE, NULL));
11500 if (options.model == MODEL_FLAT24) {
11501 emitcode ("mov", "dpx,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11502 emitcode ("mov", "b,%s", aopGet (result, 3, FALSE, FALSE, NULL));
11504 emitcode ("mov", "b,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11507 _endLazyDPSEvaluation ();
11509 /* so dptr + b now contains the address */
11510 aopOp (right, ic, FALSE, TRUE);
11512 /* if bit then unpack */
11513 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11515 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
11519 size = AOP_SIZE (right);
11522 _startLazyDPSEvaluation ();
11527 // Set two bytes at a time, passed in _AP & A.
11528 // dptr will be incremented ONCE by __gptrputWord.
11530 // Note: any change here must be coordinated
11531 // with the implementation of __gptrputWord
11532 // in device/lib/_gptrput.c
11533 emitcode("mov", "_ap, %s",
11534 aopGet (right, offset++, FALSE, FALSE, NULL));
11535 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11539 emitcode ("lcall", "__gptrputWord");
11544 // Only one byte to put.
11545 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11549 emitcode ("lcall", "__gptrput");
11552 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
11554 emitcode ("inc", "dptr");
11557 _endLazyDPSEvaluation ();
11560 if (pi && AOP_TYPE (result) != AOP_IMMD) {
11561 _startLazyDPSEvaluation ();
11563 aopPut (result, "dpl",0);
11564 aopPut (result, "dph",1);
11565 if (options.model == MODEL_FLAT24) {
11566 aopPut (result, "dpx",2);
11567 aopPut (result, "b",3);
11569 aopPut (result, "b",2);
11571 _endLazyDPSEvaluation ();
11574 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
11575 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
11577 size = AOP_SIZE (right) - 1;
11578 while (size--) emitcode ("lcall","__decdptr");
11582 freeAsmop (result, NULL, ic, TRUE);
11583 freeAsmop (right, NULL, ic, TRUE);
11586 /*-----------------------------------------------------------------*/
11587 /* genPointerSet - stores the value into a pointer location */
11588 /*-----------------------------------------------------------------*/
11590 genPointerSet (iCode * ic, iCode *pi)
11592 operand *right, *result;
11593 sym_link *type, *etype;
11596 D (emitcode (";", "genPointerSet"));
11598 right = IC_RIGHT (ic);
11599 result = IC_RESULT (ic);
11601 /* depending on the type of pointer we need to
11602 move it to the correct pointer register */
11603 type = operandType (result);
11604 etype = getSpec (type);
11605 /* if left is of type of pointer then it is simple */
11606 if (IS_PTR (type) && !IS_FUNC (type->next))
11608 p_type = DCL_TYPE (type);
11612 /* we have to go by the storage class */
11613 p_type = PTR_TYPE (SPEC_OCLS (etype));
11616 /* special case when cast remat */
11617 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
11618 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
11619 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
11620 type = operandType (result);
11621 p_type = DCL_TYPE (type);
11624 /* now that we have the pointer type we assign
11625 the pointer values */
11631 genNearPointerSet (right, result, ic, pi);
11635 genPagedPointerSet (right, result, ic, pi);
11639 genFarPointerSet (right, result, ic, pi);
11643 genGenPointerSet (right, result, ic, pi);
11647 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11648 "genPointerSet: illegal pointer type");
11652 /*-----------------------------------------------------------------*/
11653 /* genIfx - generate code for Ifx statement */
11654 /*-----------------------------------------------------------------*/
11656 genIfx (iCode * ic, iCode * popIc)
11658 operand *cond = IC_COND (ic);
11662 D (emitcode (";", "genIfx"));
11664 aopOp (cond, ic, FALSE, FALSE);
11666 /* get the value into acc */
11667 if (AOP_TYPE (cond) != AOP_CRY)
11674 if (AOP(cond)->aopu.aop_dir)
11675 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
11678 /* the result is now in the accumulator or a directly addressable bit */
11679 freeAsmop (cond, NULL, ic, TRUE);
11681 /* if there was something to be popped then do it */
11685 /* if the condition is a bit variable */
11687 genIfxJump (ic, dup);
11688 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
11689 genIfxJump (ic, SPIL_LOC (cond)->rname);
11690 else if (isbit && !IS_ITEMP (cond))
11691 genIfxJump (ic, OP_SYMBOL (cond)->rname);
11693 genIfxJump (ic, "a");
11698 /*-----------------------------------------------------------------*/
11699 /* genAddrOf - generates code for address of */
11700 /*-----------------------------------------------------------------*/
11702 genAddrOf (iCode * ic)
11704 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
11707 D (emitcode (";", "genAddrOf"));
11709 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11711 /* if the operand is on the stack then we
11712 need to get the stack offset of this
11717 /* if 10 bit stack */
11718 if (options.stack10bit) {
11722 tsprintf(buff, sizeof(buff),
11723 "#!constbyte",(options.stack_loc >> 16) & 0xff);
11724 /* if it has an offset then we need to compute it */
11725 /* emitcode ("subb", "a,#!constbyte", */
11726 /* -((sym->stack < 0) ? */
11727 /* ((short) (sym->stack - _G.nRegsSaved)) : */
11728 /* ((short) sym->stack)) & 0xff); */
11729 /* emitcode ("mov","b,a"); */
11730 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
11731 /* ((short) (sym->stack - _G.nRegsSaved)) : */
11732 /* ((short) sym->stack)) >> 8) & 0xff); */
11734 emitcode ("mov", "a,_bpx");
11735 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
11736 ((char) (sym->stack - _G.nRegsSaved)) :
11737 ((char) sym->stack )) & 0xff);
11738 emitcode ("mov", "b,a");
11739 emitcode ("mov", "a,_bpx+1");
11741 offset = (((sym->stack < 0) ?
11742 ((short) (sym->stack - _G.nRegsSaved)) :
11743 ((short) sym->stack )) >> 8) & 0xff;
11745 emitcode ("addc","a,#!constbyte", offset);
11747 aopPut (IC_RESULT (ic), "b", 0);
11748 aopPut (IC_RESULT (ic), "a", 1);
11749 aopPut (IC_RESULT (ic), buff, 2);
11751 /* we can just move _bp */
11752 aopPut (IC_RESULT (ic), "_bpx", 0);
11753 aopPut (IC_RESULT (ic), "_bpx+1", 1);
11754 aopPut (IC_RESULT (ic), buff, 2);
11757 /* if it has an offset then we need to compute it */
11760 emitcode ("mov", "a,_bp");
11761 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
11762 aopPut (IC_RESULT (ic), "a", 0);
11766 /* we can just move _bp */
11767 aopPut (IC_RESULT (ic), "_bp", 0);
11769 /* fill the result with zero */
11770 size = AOP_SIZE (IC_RESULT (ic)) - 1;
11773 if (options.stack10bit && size < (FPTRSIZE - 1)) {
11775 "*** warning: pointer to stack var truncated.\n");
11781 aopPut (IC_RESULT (ic), zero, offset++);
11787 /* object not on stack then we need the name */
11788 size = AOP_SIZE (IC_RESULT (ic));
11793 char s[SDCC_NAME_MAX];
11797 tsprintf(s, sizeof(s), "#!his",sym->rname);
11800 tsprintf(s, sizeof(s), "#!hihis",sym->rname);
11803 tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
11805 default: /* should not need this (just in case) */
11806 SNPRINTF (s, sizeof(s), "#(%s >> %d)",
11813 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11816 aopPut (IC_RESULT (ic), s, offset++);
11820 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11824 #if 0 // obsolete, and buggy for != xdata
11825 /*-----------------------------------------------------------------*/
11826 /* genArrayInit - generates code for address of */
11827 /*-----------------------------------------------------------------*/
11829 genArrayInit (iCode * ic)
11831 literalList *iLoop;
11833 int elementSize = 0, eIndex;
11834 unsigned val, lastVal;
11836 operand *left=IC_LEFT(ic);
11838 D (emitcode (";", "genArrayInit"));
11840 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
11842 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
11844 // Load immediate value into DPTR.
11845 emitcode("mov", "dptr, %s",
11846 aopGet (IC_LEFT(ic), 0, TRUE, FALSE, NULL));
11848 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
11851 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11852 "Unexpected operand to genArrayInit.\n");
11855 // a regression because of SDCCcse.c:1.52
11856 emitcode ("mov", "dpl,%s", aopGet (left, 0, FALSE, FALSE, NULL));
11857 emitcode ("mov", "dph,%s", aopGet (left, 1, FALSE, FALSE, NULL));
11858 if (options.model == MODEL_FLAT24)
11859 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
11863 type = operandType(IC_LEFT(ic));
11865 if (type && type->next)
11867 elementSize = getSize(type->next);
11871 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11872 "can't determine element size in genArrayInit.\n");
11876 iLoop = IC_ARRAYILIST(ic);
11881 bool firstpass = TRUE;
11883 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
11884 iLoop->count, (int)iLoop->literalValue, elementSize);
11890 symbol *tlbl = NULL;
11892 count = ix > 256 ? 256 : ix;
11896 tlbl = newiTempLabel (NULL);
11897 if (firstpass || (count & 0xff))
11899 emitcode("mov", "b, #!constbyte", count & 0xff);
11907 for (eIndex = 0; eIndex < elementSize; eIndex++)
11909 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
11910 if (val != lastVal)
11912 emitcode("mov", "a, #!constbyte", val);
11916 emitcode("movx", "@dptr, a");
11917 emitcode("inc", "dptr");
11922 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
11928 iLoop = iLoop->next;
11931 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
11935 /*-----------------------------------------------------------------*/
11936 /* genFarFarAssign - assignment when both are in far space */
11937 /*-----------------------------------------------------------------*/
11939 genFarFarAssign (operand * result, operand * right, iCode * ic)
11941 int size = AOP_SIZE (right);
11943 symbol *rSym = NULL;
11947 /* quick & easy case. */
11948 D (emitcode(";","genFarFarAssign (1 byte case)"));
11949 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
11950 freeAsmop (right, NULL, ic, FALSE);
11951 /* now assign DPTR to result */
11953 aopOp(result, ic, FALSE, FALSE);
11955 aopPut (result, "a", 0);
11956 freeAsmop(result, NULL, ic, FALSE);
11960 /* See if we've got an underlying symbol to abuse. */
11961 if (IS_SYMOP(result) && OP_SYMBOL(result))
11963 if (IS_TRUE_SYMOP(result))
11965 rSym = OP_SYMBOL(result);
11967 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
11969 rSym = OP_SYMBOL(result)->usl.spillLoc;
11973 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
11975 /* We can use the '390 auto-toggle feature to good effect here. */
11977 D (emitcode(";", "genFarFarAssign (390 auto-toggle fun)"));
11978 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11979 emitcode ("mov", "dptr,#%s", rSym->rname);
11980 /* DP2 = result, DP1 = right, DP1 is current. */
11983 emitcode("movx", "a,@dptr");
11984 emitcode("movx", "@dptr,a");
11987 emitcode("inc", "dptr");
11988 emitcode("inc", "dptr");
11991 emitcode("mov", "dps,#0");
11992 freeAsmop (right, NULL, ic, FALSE);
11994 some alternative code for processors without auto-toggle
11995 no time to test now, so later well put in...kpb
11996 D (emitcode(";", "genFarFarAssign (dual-dptr fun)"));
11997 emitcode("mov", "dps,#1"); /* Select DPTR2. */
11998 emitcode ("mov", "dptr,#%s", rSym->rname);
11999 /* DP2 = result, DP1 = right, DP1 is current. */
12003 emitcode("movx", "a,@dptr");
12005 emitcode("inc", "dptr");
12006 emitcode("inc", "dps");
12007 emitcode("movx", "@dptr,a");
12009 emitcode("inc", "dptr");
12010 emitcode("inc", "dps");
12012 emitcode("mov", "dps,#0");
12013 freeAsmop (right, NULL, ic, FALSE);
12018 D (emitcode (";", "genFarFarAssign"));
12019 aopOp (result, ic, TRUE, TRUE);
12021 _startLazyDPSEvaluation ();
12026 aopGet (right, offset, FALSE, FALSE, NULL), offset);
12029 _endLazyDPSEvaluation ();
12030 freeAsmop (result, NULL, ic, FALSE);
12031 freeAsmop (right, NULL, ic, FALSE);
12035 /*-----------------------------------------------------------------*/
12036 /* genAssign - generate code for assignment */
12037 /*-----------------------------------------------------------------*/
12039 genAssign (iCode * ic)
12041 operand *result, *right;
12043 unsigned long lit = 0L;
12045 D (emitcode (";", "genAssign"));
12047 result = IC_RESULT (ic);
12048 right = IC_RIGHT (ic);
12050 /* if they are the same */
12051 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
12054 aopOp (right, ic, FALSE, FALSE);
12056 emitcode (";", "genAssign: resultIsFar = %s",
12057 isOperandInFarSpace (result) ?
12060 /* special case both in far space */
12061 if ((AOP_TYPE (right) == AOP_DPTR ||
12062 AOP_TYPE (right) == AOP_DPTR2) &&
12063 /* IS_TRUE_SYMOP(result) && */
12064 isOperandInFarSpace (result))
12066 genFarFarAssign (result, right, ic);
12070 aopOp (result, ic, TRUE, FALSE);
12072 /* if they are the same registers */
12073 if (sameRegs (AOP (right), AOP (result)))
12076 /* if the result is a bit */
12077 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
12079 /* if the right size is a literal then
12080 we know what the value is */
12081 if (AOP_TYPE (right) == AOP_LIT)
12083 if (((int) operandLitValue (right)))
12084 aopPut (result, one, 0);
12086 aopPut (result, zero, 0);
12090 /* the right is also a bit variable */
12091 if (AOP_TYPE (right) == AOP_CRY)
12093 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
12094 aopPut (result, "c", 0);
12098 /* we need to or */
12100 aopPut (result, "a", 0);
12104 /* bit variables done */
12106 size = AOP_SIZE (result);
12108 if (AOP_TYPE (right) == AOP_LIT)
12109 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
12112 (AOP_TYPE (result) != AOP_REG) &&
12113 (AOP_TYPE (right) == AOP_LIT) &&
12114 !IS_FLOAT (operandType (right)))
12116 _startLazyDPSEvaluation ();
12117 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
12120 aopGet (right, offset, FALSE, FALSE, NULL),
12125 /* And now fill the rest with zeros. */
12128 emitcode ("clr", "a");
12132 aopPut (result, "a", offset++);
12134 _endLazyDPSEvaluation ();
12138 _startLazyDPSEvaluation ();
12142 aopGet (right, offset, FALSE, FALSE, NULL),
12146 _endLazyDPSEvaluation ();
12150 freeAsmop (result, NULL, ic, TRUE);
12151 freeAsmop (right, NULL, ic, TRUE);
12154 /*-----------------------------------------------------------------*/
12155 /* genJumpTab - generates code for jump table */
12156 /*-----------------------------------------------------------------*/
12158 genJumpTab (iCode * ic)
12163 D (emitcode (";", "genJumpTab"));
12165 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
12166 /* get the condition into accumulator */
12167 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE, NULL);
12169 /* multiply by four! */
12170 emitcode ("add", "a,acc");
12171 emitcode ("add", "a,acc");
12172 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
12174 jtab = newiTempLabel (NULL);
12175 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
12176 emitcode ("jmp", "@a+dptr");
12178 /* now generate the jump labels */
12179 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
12180 jtab = setNextItem (IC_JTLABELS (ic)))
12181 emitcode ("ljmp", "!tlabel", jtab->key + 100);
12185 /*-----------------------------------------------------------------*/
12186 /* genCast - gen code for casting */
12187 /*-----------------------------------------------------------------*/
12189 genCast (iCode * ic)
12191 operand *result = IC_RESULT (ic);
12192 sym_link *ctype = operandType (IC_LEFT (ic));
12193 sym_link *rtype = operandType (IC_RIGHT (ic));
12194 operand *right = IC_RIGHT (ic);
12197 D (emitcode (";", "genCast"));
12199 /* if they are equivalent then do nothing */
12200 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
12203 aopOp (right, ic, FALSE, AOP_IS_STR (result));
12204 aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR));
12206 /* if the result is a bit (and not a bitfield) */
12207 if (IS_BIT (OP_SYMBOL (result)->type))
12209 /* if the right size is a literal then
12210 we know what the value is */
12211 if (AOP_TYPE (right) == AOP_LIT)
12213 if (((int) operandLitValue (right)))
12214 aopPut (result, one, 0);
12216 aopPut (result, zero, 0);
12221 /* the right is also a bit variable */
12222 if (AOP_TYPE (right) == AOP_CRY)
12224 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
12225 aopPut (result, "c", 0);
12229 /* we need to or */
12231 aopPut (result, "a", 0);
12235 /* if they are the same size : or less */
12236 if (AOP_SIZE (result) <= AOP_SIZE (right))
12239 /* if they are in the same place */
12240 if (sameRegs (AOP (right), AOP (result)))
12243 /* if they in different places then copy */
12244 size = AOP_SIZE (result);
12246 _startLazyDPSEvaluation ();
12250 aopGet (right, offset, FALSE, FALSE, NULL),
12254 _endLazyDPSEvaluation ();
12258 /* if the result is of type pointer */
12259 if (IS_PTR (ctype))
12263 sym_link *type = operandType (right);
12265 /* pointer to generic pointer */
12266 if (IS_GENPTR (ctype))
12270 p_type = DCL_TYPE (type);
12274 #if OLD_CAST_BEHAVIOR
12275 /* KV: we are converting a non-pointer type to
12276 * a generic pointer. This (ifdef'd out) code
12277 * says that the resulting generic pointer
12278 * should have the same class as the storage
12279 * location of the non-pointer variable.
12281 * For example, converting an int (which happens
12282 * to be stored in DATA space) to a pointer results
12283 * in a DATA generic pointer; if the original int
12284 * in XDATA space, so will be the resulting pointer.
12286 * I don't like that behavior, and thus this change:
12287 * all such conversions will be forced to XDATA and
12288 * throw a warning. If you want some non-XDATA
12289 * type, or you want to suppress the warning, you
12290 * must go through an intermediate cast, like so:
12292 * char _generic *gp = (char _xdata *)(intVar);
12294 sym_link *etype = getSpec (type);
12296 /* we have to go by the storage class */
12297 if (SPEC_OCLS (etype) != generic)
12299 p_type = PTR_TYPE (SPEC_OCLS (etype));
12304 /* Converting unknown class (i.e. register variable)
12305 * to generic pointer. This is not good, but
12306 * we'll make a guess (and throw a warning).
12309 werror (W_INT_TO_GEN_PTR_CAST);
12313 /* the first two bytes are known */
12314 size = GPTRSIZE - 1;
12316 _startLazyDPSEvaluation ();
12320 aopGet (right, offset, FALSE, FALSE, NULL),
12324 _endLazyDPSEvaluation ();
12326 /* the last byte depending on type */
12328 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
12333 // pointerTypeToGPByte will have bitched.
12337 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%x", gpVal);
12338 aopPut (result, gpValStr, GPTRSIZE - 1);
12343 /* just copy the pointers */
12344 size = AOP_SIZE (result);
12346 _startLazyDPSEvaluation ();
12350 aopGet (right, offset, FALSE, FALSE, NULL),
12354 _endLazyDPSEvaluation ();
12358 /* so we now know that the size of destination is greater
12359 than the size of the source */
12360 /* we move to result for the size of source */
12361 size = AOP_SIZE (right);
12363 _startLazyDPSEvaluation ();
12367 aopGet (right, offset, FALSE, FALSE, NULL),
12371 _endLazyDPSEvaluation ();
12373 /* now depending on the sign of the source && destination */
12374 size = AOP_SIZE (result) - AOP_SIZE (right);
12375 /* if unsigned or not an integral type */
12376 /* also, if the source is a bit, we don't need to sign extend, because
12377 * it can't possibly have set the sign bit.
12379 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
12383 aopPut (result, zero, offset++);
12388 /* we need to extend the sign :{ */
12389 MOVA (aopGet (right, AOP_SIZE (right) - 1,
12390 FALSE, FALSE, NULL));
12391 emitcode ("rlc", "a");
12392 emitcode ("subb", "a,acc");
12394 aopPut (result, "a", offset++);
12397 /* we are done hurray !!!! */
12400 freeAsmop (right, NULL, ic, TRUE);
12401 freeAsmop (result, NULL, ic, TRUE);
12405 /*-----------------------------------------------------------------*/
12406 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
12407 /*-----------------------------------------------------------------*/
12408 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
12410 operand *from , *to , *count;
12415 /* we know it has to be 3 parameters */
12416 assert (nparms == 3);
12418 rsave = newBitVect(16);
12419 /* save DPTR if it needs to be saved */
12420 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12421 if (bitVectBitValue(ic->rMask,i))
12422 rsave = bitVectSetBit(rsave,i);
12424 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12425 ds390_rUmaskForOp (IC_RESULT(ic))));
12432 aopOp (from, ic->next, FALSE, FALSE);
12434 /* get from into DPTR1 */
12435 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12436 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12437 if (options.model == MODEL_FLAT24) {
12438 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12441 freeAsmop (from, NULL, ic, FALSE);
12442 aopOp (to, ic, FALSE, FALSE);
12443 /* get "to" into DPTR */
12444 /* if the operand is already in dptr
12445 then we do nothing else we move the value to dptr */
12446 if (AOP_TYPE (to) != AOP_STR) {
12447 /* if already in DPTR then we need to push */
12448 if (AOP_TYPE(to) == AOP_DPTR) {
12449 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12450 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12451 if (options.model == MODEL_FLAT24)
12452 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12453 emitcode ("pop", "dph");
12454 emitcode ("pop", "dpl");
12456 _startLazyDPSEvaluation ();
12457 /* if this is remateriazable */
12458 if (AOP_TYPE (to) == AOP_IMMD) {
12459 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12460 } else { /* we need to get it byte by byte */
12461 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12462 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12463 if (options.model == MODEL_FLAT24) {
12464 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12467 _endLazyDPSEvaluation ();
12470 freeAsmop (to, NULL, ic, FALSE);
12471 _G.dptrInUse = _G.dptr1InUse = 1;
12472 aopOp (count, ic->next->next, FALSE,FALSE);
12473 lbl =newiTempLabel(NULL);
12475 /* now for the actual copy */
12476 if (AOP_TYPE(count) == AOP_LIT &&
12477 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12478 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12480 emitcode ("lcall","__bi_memcpyc2x_s");
12482 emitcode ("lcall","__bi_memcpyx2x_s");
12484 freeAsmop (count, NULL, ic, FALSE);
12486 symbol *lbl1 = newiTempLabel(NULL);
12488 emitcode (";"," Auto increment but no djnz");
12489 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
12490 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
12491 freeAsmop (count, NULL, ic, FALSE);
12492 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12493 emitcode ("","!tlabeldef",lbl->key+100);
12495 emitcode ("clr","a");
12496 emitcode ("movc", "a,@a+dptr");
12498 emitcode ("movx", "a,@dptr");
12499 emitcode ("movx", "@dptr,a");
12500 emitcode ("inc", "dptr");
12501 emitcode ("inc", "dptr");
12502 emitcode ("mov","a,b");
12503 emitcode ("orl","a,_ap");
12504 emitcode ("jz","!tlabel",lbl1->key+100);
12505 emitcode ("mov","a,_ap");
12506 emitcode ("add","a,#!constbyte",0xFF);
12507 emitcode ("mov","_ap,a");
12508 emitcode ("mov","a,b");
12509 emitcode ("addc","a,#!constbyte",0xFF);
12510 emitcode ("mov","b,a");
12511 emitcode ("sjmp","!tlabel",lbl->key+100);
12512 emitcode ("","!tlabeldef",lbl1->key+100);
12514 emitcode ("mov", "dps,#0");
12515 _G.dptrInUse = _G.dptr1InUse = 0;
12516 unsavermask(rsave);
12520 /*-----------------------------------------------------------------*/
12521 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
12522 /*-----------------------------------------------------------------*/
12523 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
12525 operand *from , *to , *count;
12530 /* we know it has to be 3 parameters */
12531 assert (nparms == 3);
12533 rsave = newBitVect(16);
12534 /* save DPTR if it needs to be saved */
12535 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12536 if (bitVectBitValue(ic->rMask,i))
12537 rsave = bitVectSetBit(rsave,i);
12539 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12540 ds390_rUmaskForOp (IC_RESULT(ic))));
12547 aopOp (from, ic->next, FALSE, FALSE);
12549 /* get from into DPTR1 */
12550 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12551 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12552 if (options.model == MODEL_FLAT24) {
12553 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12556 freeAsmop (from, NULL, ic, FALSE);
12557 aopOp (to, ic, FALSE, FALSE);
12558 /* get "to" into DPTR */
12559 /* if the operand is already in dptr
12560 then we do nothing else we move the value to dptr */
12561 if (AOP_TYPE (to) != AOP_STR) {
12562 /* if already in DPTR then we need to push */
12563 if (AOP_TYPE(to) == AOP_DPTR) {
12564 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12565 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12566 if (options.model == MODEL_FLAT24)
12567 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12568 emitcode ("pop", "dph");
12569 emitcode ("pop", "dpl");
12571 _startLazyDPSEvaluation ();
12572 /* if this is remateriazable */
12573 if (AOP_TYPE (to) == AOP_IMMD) {
12574 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12575 } else { /* we need to get it byte by byte */
12576 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12577 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12578 if (options.model == MODEL_FLAT24) {
12579 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12582 _endLazyDPSEvaluation ();
12585 freeAsmop (to, NULL, ic, FALSE);
12586 _G.dptrInUse = _G.dptr1InUse = 1;
12587 aopOp (count, ic->next->next, FALSE,FALSE);
12588 lbl =newiTempLabel(NULL);
12589 lbl2 =newiTempLabel(NULL);
12591 /* now for the actual compare */
12592 if (AOP_TYPE(count) == AOP_LIT &&
12593 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12594 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12596 emitcode("lcall","__bi_memcmpc2x_s");
12598 emitcode("lcall","__bi_memcmpx2x_s");
12599 freeAsmop (count, NULL, ic, FALSE);
12600 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12601 aopPut(IC_RESULT(ic),"a",0);
12602 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12604 symbol *lbl1 = newiTempLabel(NULL);
12606 emitcode("push","ar0");
12607 emitcode (";"," Auto increment but no djnz");
12608 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
12609 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
12610 freeAsmop (count, NULL, ic, FALSE);
12611 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12612 emitcode ("","!tlabeldef",lbl->key+100);
12614 emitcode ("clr","a");
12615 emitcode ("movc", "a,@a+dptr");
12617 emitcode ("movx", "a,@dptr");
12618 emitcode ("mov","r0,a");
12619 emitcode ("movx", "a,@dptr");
12620 emitcode ("clr","c");
12621 emitcode ("subb","a,r0");
12622 emitcode ("jnz","!tlabel",lbl2->key+100);
12623 emitcode ("inc", "dptr");
12624 emitcode ("inc", "dptr");
12625 emitcode ("mov","a,b");
12626 emitcode ("orl","a,_ap");
12627 emitcode ("jz","!tlabel",lbl1->key+100);
12628 emitcode ("mov","a,_ap");
12629 emitcode ("add","a,#!constbyte",0xFF);
12630 emitcode ("mov","_ap,a");
12631 emitcode ("mov","a,b");
12632 emitcode ("addc","a,#!constbyte",0xFF);
12633 emitcode ("mov","b,a");
12634 emitcode ("sjmp","!tlabel",lbl->key+100);
12635 emitcode ("","!tlabeldef",lbl1->key+100);
12636 emitcode ("clr","a");
12637 emitcode ("","!tlabeldef",lbl2->key+100);
12638 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12639 aopPut(IC_RESULT(ic),"a",0);
12640 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12641 emitcode("pop","ar0");
12642 emitcode ("mov", "dps,#0");
12644 _G.dptrInUse = _G.dptr1InUse = 0;
12645 unsavermask(rsave);
12649 /*-----------------------------------------------------------------*/
12650 /* genInp - gen code for __builtin_inp read data from a mem mapped */
12651 /* port, first parameter output area second parameter pointer to */
12652 /* port third parameter count */
12653 /*-----------------------------------------------------------------*/
12654 static void genInp( iCode *ic, int nparms, operand **parms)
12656 operand *from , *to , *count;
12661 /* we know it has to be 3 parameters */
12662 assert (nparms == 3);
12664 rsave = newBitVect(16);
12665 /* save DPTR if it needs to be saved */
12666 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12667 if (bitVectBitValue(ic->rMask,i))
12668 rsave = bitVectSetBit(rsave,i);
12670 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12671 ds390_rUmaskForOp (IC_RESULT(ic))));
12678 aopOp (from, ic->next, FALSE, FALSE);
12680 /* get from into DPTR1 */
12681 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12682 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12683 if (options.model == MODEL_FLAT24) {
12684 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12687 freeAsmop (from, NULL, ic, FALSE);
12688 aopOp (to, ic, FALSE, FALSE);
12689 /* get "to" into DPTR */
12690 /* if the operand is already in dptr
12691 then we do nothing else we move the value to dptr */
12692 if (AOP_TYPE (to) != AOP_STR) {
12693 /* if already in DPTR then we need to push */
12694 if (AOP_TYPE(to) == AOP_DPTR) {
12695 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12696 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12697 if (options.model == MODEL_FLAT24)
12698 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12699 emitcode ("pop", "dph");
12700 emitcode ("pop", "dpl");
12702 _startLazyDPSEvaluation ();
12703 /* if this is remateriazable */
12704 if (AOP_TYPE (to) == AOP_IMMD) {
12705 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12706 } else { /* we need to get it byte by byte */
12707 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12708 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12709 if (options.model == MODEL_FLAT24) {
12710 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12713 _endLazyDPSEvaluation ();
12716 freeAsmop (to, NULL, ic, FALSE);
12718 _G.dptrInUse = _G.dptr1InUse = 1;
12719 aopOp (count, ic->next->next, FALSE,FALSE);
12720 lbl =newiTempLabel(NULL);
12722 /* now for the actual copy */
12723 if (AOP_TYPE(count) == AOP_LIT &&
12724 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12725 emitcode (";","OH JOY auto increment with djnz (very fast)");
12726 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
12727 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12728 freeAsmop (count, NULL, ic, FALSE);
12729 emitcode ("","!tlabeldef",lbl->key+100);
12730 emitcode ("movx", "a,@dptr"); /* read data from port */
12731 emitcode ("dec","dps"); /* switch to DPTR */
12732 emitcode ("movx", "@dptr,a"); /* save into location */
12733 emitcode ("inc", "dptr"); /* point to next area */
12734 emitcode ("inc","dps"); /* switch to DPTR2 */
12735 emitcode ("djnz","b,!tlabel",lbl->key+100);
12737 symbol *lbl1 = newiTempLabel(NULL);
12739 emitcode (";"," Auto increment but no djnz");
12740 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
12741 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
12742 freeAsmop (count, NULL, ic, FALSE);
12743 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
12744 emitcode ("","!tlabeldef",lbl->key+100);
12745 emitcode ("movx", "a,@dptr");
12746 emitcode ("dec","dps"); /* switch to DPTR */
12747 emitcode ("movx", "@dptr,a");
12748 emitcode ("inc", "dptr");
12749 emitcode ("inc","dps"); /* switch to DPTR2 */
12750 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
12751 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
12752 emitcode ("mov","a,b");
12753 emitcode ("orl","a,_ap");
12754 emitcode ("jz","!tlabel",lbl1->key+100);
12755 emitcode ("mov","a,_ap");
12756 emitcode ("add","a,#!constbyte",0xFF);
12757 emitcode ("mov","_ap,a");
12758 emitcode ("mov","a,b");
12759 emitcode ("addc","a,#!constbyte",0xFF);
12760 emitcode ("mov","b,a");
12761 emitcode ("sjmp","!tlabel",lbl->key+100);
12762 emitcode ("","!tlabeldef",lbl1->key+100);
12764 emitcode ("mov", "dps,#0");
12765 _G.dptrInUse = _G.dptr1InUse = 0;
12766 unsavermask(rsave);
12770 /*-----------------------------------------------------------------*/
12771 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
12772 /* port, first parameter output area second parameter pointer to */
12773 /* port third parameter count */
12774 /*-----------------------------------------------------------------*/
12775 static void genOutp( iCode *ic, int nparms, operand **parms)
12777 operand *from , *to , *count;
12782 /* we know it has to be 3 parameters */
12783 assert (nparms == 3);
12785 rsave = newBitVect(16);
12786 /* save DPTR if it needs to be saved */
12787 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12788 if (bitVectBitValue(ic->rMask,i))
12789 rsave = bitVectSetBit(rsave,i);
12791 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12792 ds390_rUmaskForOp (IC_RESULT(ic))));
12799 aopOp (from, ic->next, FALSE, FALSE);
12801 /* get from into DPTR1 */
12802 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12803 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12804 if (options.model == MODEL_FLAT24) {
12805 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12808 freeAsmop (from, NULL, ic, FALSE);
12809 aopOp (to, ic, FALSE, FALSE);
12810 /* get "to" into DPTR */
12811 /* if the operand is already in dptr
12812 then we do nothing else we move the value to dptr */
12813 if (AOP_TYPE (to) != AOP_STR) {
12814 /* if already in DPTR then we need to push */
12815 if (AOP_TYPE(to) == AOP_DPTR) {
12816 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12817 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12818 if (options.model == MODEL_FLAT24)
12819 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12820 emitcode ("pop", "dph");
12821 emitcode ("pop", "dpl");
12823 _startLazyDPSEvaluation ();
12824 /* if this is remateriazable */
12825 if (AOP_TYPE (to) == AOP_IMMD) {
12826 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12827 } else { /* we need to get it byte by byte */
12828 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12829 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12830 if (options.model == MODEL_FLAT24) {
12831 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12834 _endLazyDPSEvaluation ();
12837 freeAsmop (to, NULL, ic, FALSE);
12839 _G.dptrInUse = _G.dptr1InUse = 1;
12840 aopOp (count, ic->next->next, FALSE,FALSE);
12841 lbl =newiTempLabel(NULL);
12843 /* now for the actual copy */
12844 if (AOP_TYPE(count) == AOP_LIT &&
12845 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12846 emitcode (";","OH JOY auto increment with djnz (very fast)");
12847 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
12848 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12849 emitcode ("","!tlabeldef",lbl->key+100);
12850 emitcode ("movx", "a,@dptr"); /* read data from port */
12851 emitcode ("inc","dps"); /* switch to DPTR2 */
12852 emitcode ("movx", "@dptr,a"); /* save into location */
12853 emitcode ("inc", "dptr"); /* point to next area */
12854 emitcode ("dec","dps"); /* switch to DPTR */
12855 emitcode ("djnz","b,!tlabel",lbl->key+100);
12856 freeAsmop (count, NULL, ic, FALSE);
12858 symbol *lbl1 = newiTempLabel(NULL);
12860 emitcode (";"," Auto increment but no djnz");
12861 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
12862 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
12863 freeAsmop (count, NULL, ic, FALSE);
12864 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
12865 emitcode ("","!tlabeldef",lbl->key+100);
12866 emitcode ("movx", "a,@dptr");
12867 emitcode ("inc", "dptr");
12868 emitcode ("inc","dps"); /* switch to DPTR2 */
12869 emitcode ("movx", "@dptr,a");
12870 emitcode ("dec","dps"); /* switch to DPTR */
12871 emitcode ("mov","a,b");
12872 emitcode ("orl","a,_ap");
12873 emitcode ("jz","!tlabel",lbl1->key+100);
12874 emitcode ("mov","a,_ap");
12875 emitcode ("add","a,#!constbyte",0xFF);
12876 emitcode ("mov","_ap,a");
12877 emitcode ("mov","a,b");
12878 emitcode ("addc","a,#!constbyte",0xFF);
12879 emitcode ("mov","b,a");
12880 emitcode ("sjmp","!tlabel",lbl->key+100);
12881 emitcode ("","!tlabeldef",lbl1->key+100);
12883 emitcode ("mov", "dps,#0");
12884 _G.dptrInUse = _G.dptr1InUse = 0;
12885 unsavermask(rsave);
12889 /*-----------------------------------------------------------------*/
12890 /* genSwapW - swap lower & high order bytes */
12891 /*-----------------------------------------------------------------*/
12892 static void genSwapW(iCode *ic, int nparms, operand **parms)
12896 assert (nparms==1);
12899 dest=IC_RESULT(ic);
12901 assert(getSize(operandType(src))==2);
12903 aopOp (src, ic, FALSE, FALSE);
12904 emitcode ("mov","a,%s",aopGet(src,0,FALSE,FALSE,NULL));
12906 MOVB(aopGet(src,1,FALSE,FALSE,"b"));
12908 freeAsmop (src, NULL, ic, FALSE);
12910 aopOp (dest,ic, FALSE, FALSE);
12911 aopPut(dest,"b",0);
12912 aopPut(dest,"a",1);
12913 freeAsmop (dest, NULL, ic, FALSE);
12916 /*-----------------------------------------------------------------*/
12917 /* genMemsetX - gencode for memSetX data */
12918 /*-----------------------------------------------------------------*/
12919 static void genMemsetX(iCode *ic, int nparms, operand **parms)
12921 operand *to , *val , *count;
12927 /* we know it has to be 3 parameters */
12928 assert (nparms == 3);
12934 /* save DPTR if it needs to be saved */
12935 rsave = newBitVect(16);
12936 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12937 if (bitVectBitValue(ic->rMask,i))
12938 rsave = bitVectSetBit(rsave,i);
12940 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12941 ds390_rUmaskForOp (IC_RESULT(ic))));
12944 aopOp (to, ic, FALSE, FALSE);
12945 /* get "to" into DPTR */
12946 /* if the operand is already in dptr
12947 then we do nothing else we move the value to dptr */
12948 if (AOP_TYPE (to) != AOP_STR) {
12949 /* if already in DPTR then we need to push */
12950 if (AOP_TYPE(to) == AOP_DPTR) {
12951 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12952 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12953 if (options.model == MODEL_FLAT24)
12954 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12955 emitcode ("pop", "dph");
12956 emitcode ("pop", "dpl");
12958 _startLazyDPSEvaluation ();
12959 /* if this is remateriazable */
12960 if (AOP_TYPE (to) == AOP_IMMD) {
12961 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12962 } else { /* we need to get it byte by byte */
12963 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12964 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12965 if (options.model == MODEL_FLAT24) {
12966 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12969 _endLazyDPSEvaluation ();
12972 freeAsmop (to, NULL, ic, FALSE);
12974 aopOp (val, ic->next->next, FALSE,FALSE);
12975 aopOp (count, ic->next->next, FALSE,FALSE);
12976 lbl =newiTempLabel(NULL);
12977 /* now for the actual copy */
12978 if (AOP_TYPE(count) == AOP_LIT &&
12979 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12980 l = aopGet(val, 0, FALSE, FALSE, NULL);
12981 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12983 emitcode ("","!tlabeldef",lbl->key+100);
12984 emitcode ("movx", "@dptr,a");
12985 emitcode ("inc", "dptr");
12986 emitcode ("djnz","b,!tlabel",lbl->key+100);
12988 symbol *lbl1 = newiTempLabel(NULL);
12990 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
12991 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
12992 emitcode ("","!tlabeldef",lbl->key+100);
12993 MOVA (aopGet(val, 0, FALSE, FALSE, NULL));
12994 emitcode ("movx", "@dptr,a");
12995 emitcode ("inc", "dptr");
12996 emitcode ("mov","a,b");
12997 emitcode ("orl","a,_ap");
12998 emitcode ("jz","!tlabel",lbl1->key+100);
12999 emitcode ("mov","a,_ap");
13000 emitcode ("add","a,#!constbyte",0xFF);
13001 emitcode ("mov","_ap,a");
13002 emitcode ("mov","a,b");
13003 emitcode ("addc","a,#!constbyte",0xFF);
13004 emitcode ("mov","b,a");
13005 emitcode ("sjmp","!tlabel",lbl->key+100);
13006 emitcode ("","!tlabeldef",lbl1->key+100);
13008 freeAsmop (count, NULL, ic, FALSE);
13009 unsavermask(rsave);
13012 /*-----------------------------------------------------------------*/
13013 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
13014 /*-----------------------------------------------------------------*/
13015 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
13018 operand *pnum, *result;
13021 assert (nparms==1);
13022 /* save registers that need to be saved */
13023 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13024 ds390_rUmaskForOp (IC_RESULT(ic))));
13027 aopOp (pnum, ic, FALSE, FALSE);
13028 emitcode ("mov","a,%s",aopGet(pnum,0,FALSE,FALSE,DP2_RESULT_REG));
13029 freeAsmop (pnum, NULL, ic, FALSE);
13030 emitcode ("lcall","NatLib_LoadPrimitive");
13031 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
13032 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
13033 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
13034 for (i = (size-1) ; i >= 0 ; i-- ) {
13035 emitcode ("push","a%s",javaRet[i]);
13037 for (i=0; i < size ; i++ ) {
13038 emitcode ("pop","a%s",
13039 aopGet(result,i,FALSE,FALSE,DP2_RESULT_REG));
13042 for (i = 0 ; i < size ; i++ ) {
13043 aopPut(result,javaRet[i],i);
13046 freeAsmop (result, NULL, ic, FALSE);
13047 unsavermask(rsave);
13050 /*-----------------------------------------------------------------*/
13051 /* genNatLibLoadPointer - calls TINI api function to load pointer */
13052 /*-----------------------------------------------------------------*/
13053 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
13056 operand *pnum, *result;
13060 assert (nparms==1);
13061 /* save registers that need to be saved */
13062 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13063 ds390_rUmaskForOp (IC_RESULT(ic))));
13066 aopOp (pnum, ic, FALSE, FALSE);
13067 emitcode ("mov","a,%s",aopGet(pnum,0,FALSE,FALSE,DP2_RESULT_REG));
13068 freeAsmop (pnum, NULL, ic, FALSE);
13069 emitcode ("lcall","NatLib_LoadPointer");
13070 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
13071 if (AOP_TYPE(result)!=AOP_STR) {
13072 for (i = 0 ; i < size ; i++ ) {
13073 aopPut(result,fReturn[i],i);
13076 freeAsmop (result, NULL, ic, FALSE);
13077 unsavermask(rsave);
13080 /*-----------------------------------------------------------------*/
13081 /* genNatLibInstallStateBlock - */
13082 /*-----------------------------------------------------------------*/
13083 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
13084 operand **parms, const char *name)
13087 operand *psb, *handle;
13088 assert (nparms==2);
13090 /* save registers that need to be saved */
13091 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13092 ds390_rUmaskForOp (IC_RESULT(ic))));
13096 /* put pointer to state block into DPTR1 */
13097 aopOp (psb, ic, FALSE, FALSE);
13098 if (AOP_TYPE (psb) == AOP_IMMD) {
13099 emitcode ("mov","dps,#1");
13100 emitcode ("mov", "dptr,%s",
13101 aopGet (psb, 0, TRUE, FALSE, DP2_RESULT_REG));
13102 emitcode ("mov","dps,#0");
13104 emitcode ("mov","dpl1,%s",aopGet(psb,0,FALSE,FALSE,DP2_RESULT_REG));
13105 emitcode ("mov","dph1,%s",aopGet(psb,1,FALSE,FALSE,DP2_RESULT_REG));
13106 emitcode ("mov","dpx1,%s",aopGet(psb,2,FALSE,FALSE,DP2_RESULT_REG));
13108 freeAsmop (psb, NULL, ic, FALSE);
13110 /* put libraryID into DPTR */
13111 emitcode ("mov","dptr,#LibraryID");
13113 /* put handle into r3:r2 */
13114 aopOp (handle, ic, FALSE, FALSE);
13115 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13116 emitcode ("push","%s",aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13117 emitcode ("push","%s",aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13118 emitcode ("pop","ar3");
13119 emitcode ("pop","ar2");
13121 emitcode ("mov","r2,%s",aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13122 emitcode ("mov","r3,%s",aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13124 freeAsmop (psb, NULL, ic, FALSE);
13126 /* make the call */
13127 emitcode ("lcall","NatLib_Install%sStateBlock",name);
13129 /* put return value into place*/
13131 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
13133 aopPut(IC_RESULT(ic),"a",0);
13134 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13135 unsavermask(rsave);
13138 /*-----------------------------------------------------------------*/
13139 /* genNatLibRemoveStateBlock - */
13140 /*-----------------------------------------------------------------*/
13141 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
13147 /* save registers that need to be saved */
13148 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13149 ds390_rUmaskForOp (IC_RESULT(ic))));
13151 /* put libraryID into DPTR */
13152 emitcode ("mov","dptr,#LibraryID");
13153 /* make the call */
13154 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
13155 unsavermask(rsave);
13158 /*-----------------------------------------------------------------*/
13159 /* genNatLibGetStateBlock - */
13160 /*-----------------------------------------------------------------*/
13161 static void genNatLibGetStateBlock(iCode *ic,int nparms,
13162 operand **parms,const char *name)
13165 symbol *lbl = newiTempLabel(NULL);
13168 /* save registers that need to be saved */
13169 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13170 ds390_rUmaskForOp (IC_RESULT(ic))));
13172 /* put libraryID into DPTR */
13173 emitcode ("mov","dptr,#LibraryID");
13174 /* make the call */
13175 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
13176 emitcode ("jnz","!tlabel",lbl->key+100);
13178 /* put return value into place */
13179 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
13180 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
13181 emitcode ("push","ar3");
13182 emitcode ("push","ar2");
13183 emitcode ("pop","%s",
13184 aopGet(IC_RESULT(ic),0,FALSE,TRUE,DP2_RESULT_REG));
13185 emitcode ("pop","%s",
13186 aopGet(IC_RESULT(ic),1,FALSE,TRUE,DP2_RESULT_REG));
13188 aopPut(IC_RESULT(ic),"r2",0);
13189 aopPut(IC_RESULT(ic),"r3",1);
13191 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13192 emitcode ("","!tlabeldef",lbl->key+100);
13193 unsavermask(rsave);
13196 /*-----------------------------------------------------------------*/
13197 /* genMMMalloc - */
13198 /*-----------------------------------------------------------------*/
13199 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
13200 int size, const char *name)
13205 symbol *lbl = newiTempLabel(NULL);
13207 assert (nparms == 1);
13208 /* save registers that need to be saved */
13209 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13210 ds390_rUmaskForOp (IC_RESULT(ic))));
13213 aopOp (bsize,ic,FALSE,FALSE);
13215 /* put the size in R4-R2 */
13216 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
13217 emitcode("push","%s",aopGet(bsize,0,FALSE,TRUE,DP2_RESULT_REG));
13218 emitcode("push","%s",aopGet(bsize,1,FALSE,TRUE,DP2_RESULT_REG));
13220 emitcode("push","%s",aopGet(bsize,2,FALSE,TRUE,DP2_RESULT_REG));
13221 emitcode("pop","ar4");
13223 emitcode("pop","ar3");
13224 emitcode("pop","ar2");
13226 emitcode ("mov","r2,%s",aopGet(bsize,0,FALSE,TRUE,DP2_RESULT_REG));
13227 emitcode ("mov","r3,%s",aopGet(bsize,1,FALSE,TRUE,DP2_RESULT_REG));
13229 emitcode("mov","r4,%s",aopGet(bsize,2,FALSE,TRUE,DP2_RESULT_REG));
13232 freeAsmop (bsize, NULL, ic, FALSE);
13234 /* make the call */
13235 emitcode ("lcall","MM_%s",name);
13236 emitcode ("jz","!tlabel",lbl->key+100);
13237 emitcode ("mov","r2,#!constbyte",0xff);
13238 emitcode ("mov","r3,#!constbyte",0xff);
13239 emitcode ("","!tlabeldef",lbl->key+100);
13240 /* we don't care about the pointer : we just save the handle */
13241 rsym = OP_SYMBOL(IC_RESULT(ic));
13242 if (rsym->liveFrom != rsym->liveTo) {
13243 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
13244 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
13245 emitcode ("push","ar3");
13246 emitcode ("push","ar2");
13247 emitcode ("pop","%s",
13248 aopGet(IC_RESULT(ic),0,FALSE,TRUE,DP2_RESULT_REG));
13249 emitcode ("pop","%s",
13250 aopGet(IC_RESULT(ic),1,FALSE,TRUE,DP2_RESULT_REG));
13252 aopPut(IC_RESULT(ic),"r2",0);
13253 aopPut(IC_RESULT(ic),"r3",1);
13255 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13257 unsavermask(rsave);
13260 /*-----------------------------------------------------------------*/
13262 /*-----------------------------------------------------------------*/
13263 static void genMMDeref (iCode *ic,int nparms, operand **parms)
13268 assert (nparms == 1);
13269 /* save registers that need to be saved */
13270 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13271 ds390_rUmaskForOp (IC_RESULT(ic))));
13274 aopOp (handle,ic,FALSE,FALSE);
13276 /* put the size in R4-R2 */
13277 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13278 emitcode("push","%s",
13279 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13280 emitcode("push","%s",
13281 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13282 emitcode("pop","ar3");
13283 emitcode("pop","ar2");
13285 emitcode ("mov","r2,%s",
13286 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13287 emitcode ("mov","r3,%s",
13288 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13290 freeAsmop (handle, NULL, ic, FALSE);
13292 /* make the call */
13293 emitcode ("lcall","MM_Deref");
13296 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13297 if (rsym->liveFrom != rsym->liveTo) {
13298 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13299 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
13300 _startLazyDPSEvaluation ();
13302 aopPut(IC_RESULT(ic),"dpl",0);
13303 aopPut(IC_RESULT(ic),"dph",1);
13304 aopPut(IC_RESULT(ic),"dpx",2);
13306 _endLazyDPSEvaluation ();
13311 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13312 unsavermask(rsave);
13315 /*-----------------------------------------------------------------*/
13316 /* genMMUnrestrictedPersist - */
13317 /*-----------------------------------------------------------------*/
13318 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
13323 assert (nparms == 1);
13324 /* save registers that need to be saved */
13325 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13326 ds390_rUmaskForOp (IC_RESULT(ic))));
13329 aopOp (handle,ic,FALSE,FALSE);
13331 /* put the size in R3-R2 */
13332 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13333 emitcode("push","%s",
13334 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13335 emitcode("push","%s",
13336 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13337 emitcode("pop","ar3");
13338 emitcode("pop","ar2");
13340 emitcode ("mov","r2,%s",
13341 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13342 emitcode ("mov","r3,%s",
13343 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13345 freeAsmop (handle, NULL, ic, FALSE);
13347 /* make the call */
13348 emitcode ("lcall","MM_UnrestrictedPersist");
13351 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13352 if (rsym->liveFrom != rsym->liveTo) {
13353 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13354 aopPut(IC_RESULT(ic),"a",0);
13355 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13358 unsavermask(rsave);
13361 /*-----------------------------------------------------------------*/
13362 /* genSystemExecJavaProcess - */
13363 /*-----------------------------------------------------------------*/
13364 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
13367 operand *handle, *pp;
13369 assert (nparms==2);
13370 /* save registers that need to be saved */
13371 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13372 ds390_rUmaskForOp (IC_RESULT(ic))));
13377 /* put the handle in R3-R2 */
13378 aopOp (handle,ic,FALSE,FALSE);
13379 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13380 emitcode("push","%s",
13381 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13382 emitcode("push","%s",
13383 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13384 emitcode("pop","ar3");
13385 emitcode("pop","ar2");
13387 emitcode ("mov","r2,%s",
13388 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13389 emitcode ("mov","r3,%s",
13390 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13392 freeAsmop (handle, NULL, ic, FALSE);
13394 /* put pointer in DPTR */
13395 aopOp (pp,ic,FALSE,FALSE);
13396 if (AOP_TYPE(pp) == AOP_IMMD) {
13397 emitcode ("mov", "dptr,%s",
13398 aopGet (pp, 0, TRUE, FALSE, NULL));
13399 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
13400 emitcode ("mov","dpl,%s",aopGet(pp,0,FALSE,FALSE,NULL));
13401 emitcode ("mov","dph,%s",aopGet(pp,1,FALSE,FALSE,NULL));
13402 emitcode ("mov","dpx,%s",aopGet(pp,2,FALSE,FALSE,NULL));
13404 freeAsmop (handle, NULL, ic, FALSE);
13406 /* make the call */
13407 emitcode ("lcall","System_ExecJavaProcess");
13409 /* put result in place */
13411 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13412 if (rsym->liveFrom != rsym->liveTo) {
13413 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13414 aopPut(IC_RESULT(ic),"a",0);
13415 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13419 unsavermask(rsave);
13422 /*-----------------------------------------------------------------*/
13423 /* genSystemRTCRegisters - */
13424 /*-----------------------------------------------------------------*/
13425 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
13431 assert (nparms==1);
13432 /* save registers that need to be saved */
13433 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13434 ds390_rUmaskForOp (IC_RESULT(ic))));
13437 /* put pointer in DPTR */
13438 aopOp (pp,ic,FALSE,FALSE);
13439 if (AOP_TYPE (pp) == AOP_IMMD) {
13440 emitcode ("mov","dps,#1");
13441 emitcode ("mov", "dptr,%s",
13442 aopGet (pp, 0, TRUE, FALSE, NULL));
13443 emitcode ("mov","dps,#0");
13445 emitcode ("mov","dpl1,%s",
13446 aopGet(pp,0,FALSE,FALSE,DP2_RESULT_REG));
13447 emitcode ("mov","dph1,%s",
13448 aopGet(pp,1,FALSE,FALSE,DP2_RESULT_REG));
13449 emitcode ("mov","dpx1,%s",
13450 aopGet(pp,2,FALSE,FALSE,DP2_RESULT_REG));
13452 freeAsmop (pp, NULL, ic, FALSE);
13454 /* make the call */
13455 emitcode ("lcall","System_%sRTCRegisters",name);
13457 unsavermask(rsave);
13460 /*-----------------------------------------------------------------*/
13461 /* genSystemThreadSleep - */
13462 /*-----------------------------------------------------------------*/
13463 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
13468 assert (nparms==1);
13469 /* save registers that need to be saved */
13470 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13471 ds390_rUmaskForOp (IC_RESULT(ic))));
13474 aopOp(to,ic,FALSE,FALSE);
13475 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
13476 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
13477 emitcode ("push","%s",
13478 aopGet(to,0,FALSE,TRUE,DP2_RESULT_REG));
13479 emitcode ("push","%s",
13480 aopGet(to,1,FALSE,TRUE,DP2_RESULT_REG));
13481 emitcode ("push","%s",
13482 aopGet(to,2,FALSE,TRUE,DP2_RESULT_REG));
13483 emitcode ("push","%s",
13484 aopGet(to,3,FALSE,TRUE,DP2_RESULT_REG));
13485 emitcode ("pop","ar3");
13486 emitcode ("pop","ar2");
13487 emitcode ("pop","ar1");
13488 emitcode ("pop","ar0");
13490 emitcode ("mov","r0,%s",
13491 aopGet(to,0,FALSE,TRUE,DP2_RESULT_REG));
13492 emitcode ("mov","r1,%s",
13493 aopGet(to,1,FALSE,TRUE,DP2_RESULT_REG));
13494 emitcode ("mov","r2,%s",
13495 aopGet(to,2,FALSE,TRUE,DP2_RESULT_REG));
13496 emitcode ("mov","r3,%s",
13497 aopGet(to,3,FALSE,TRUE,DP2_RESULT_REG));
13499 freeAsmop (to, NULL, ic, FALSE);
13501 /* suspend in acc */
13503 aopOp(s,ic,FALSE,FALSE);
13504 emitcode ("mov","a,%s",
13505 aopGet(s,0,FALSE,TRUE,NULL));
13506 freeAsmop (s, NULL, ic, FALSE);
13508 /* make the call */
13509 emitcode ("lcall","System_%s",name);
13511 unsavermask(rsave);
13514 /*-----------------------------------------------------------------*/
13515 /* genSystemThreadResume - */
13516 /*-----------------------------------------------------------------*/
13517 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
13522 assert (nparms==2);
13523 /* save registers that need to be saved */
13524 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13525 ds390_rUmaskForOp (IC_RESULT(ic))));
13531 aopOp(pid,ic,FALSE,FALSE);
13532 emitcode ("mov","r0,%s",
13533 aopGet(pid,0,FALSE,TRUE,DP2_RESULT_REG));
13534 freeAsmop (pid, NULL, ic, FALSE);
13537 aopOp(tid,ic,FALSE,FALSE);
13538 emitcode ("mov","a,%s",
13539 aopGet(tid,0,FALSE,TRUE,DP2_RESULT_REG));
13540 freeAsmop (tid, NULL, ic, FALSE);
13542 emitcode ("lcall","System_ThreadResume");
13544 /* put result into place */
13546 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13547 if (rsym->liveFrom != rsym->liveTo) {
13548 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13549 aopPut(IC_RESULT(ic),"a",0);
13550 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13553 unsavermask(rsave);
13556 /*-----------------------------------------------------------------*/
13557 /* genSystemProcessResume - */
13558 /*-----------------------------------------------------------------*/
13559 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
13564 assert (nparms==1);
13565 /* save registers that need to be saved */
13566 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13567 ds390_rUmaskForOp (IC_RESULT(ic))));
13572 aopOp(pid,ic,FALSE,FALSE);
13573 emitcode ("mov","a,%s",
13574 aopGet(pid,0,FALSE,TRUE,DP2_RESULT_REG));
13575 freeAsmop (pid, NULL, ic, FALSE);
13577 emitcode ("lcall","System_ProcessResume");
13579 unsavermask(rsave);
13582 /*-----------------------------------------------------------------*/
13584 /*-----------------------------------------------------------------*/
13585 static void genSystem (iCode *ic,int nparms,char *name)
13587 assert(nparms == 0);
13589 emitcode ("lcall","System_%s",name);
13592 /*-----------------------------------------------------------------*/
13593 /* genSystemPoll - */
13594 /*-----------------------------------------------------------------*/
13595 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
13600 assert (nparms==1);
13601 /* save registers that need to be saved */
13602 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13603 ds390_rUmaskForOp (IC_RESULT(ic))));
13606 aopOp (fp,ic,FALSE,FALSE);
13607 if (AOP_TYPE (fp) == AOP_IMMD) {
13608 emitcode ("mov", "dptr,%s",
13609 aopGet (fp, 0, TRUE, FALSE, DP2_RESULT_REG));
13610 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
13611 emitcode ("mov","dpl,%s",
13612 aopGet(fp,0,FALSE,FALSE,DP2_RESULT_REG));
13613 emitcode ("mov","dph,%s",
13614 aopGet(fp,1,FALSE,FALSE,DP2_RESULT_REG));
13615 emitcode ("mov","dpx,%s",
13616 aopGet(fp,2,FALSE,FALSE,DP2_RESULT_REG));
13618 freeAsmop (fp, NULL, ic, FALSE);
13620 emitcode ("lcall","System_%sPoll",name);
13622 /* put result into place */
13624 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13625 if (rsym->liveFrom != rsym->liveTo) {
13626 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13627 aopPut(IC_RESULT(ic),"a",0);
13628 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13631 unsavermask(rsave);
13634 /*-----------------------------------------------------------------*/
13635 /* genSystemGetCurrentID - */
13636 /*-----------------------------------------------------------------*/
13637 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
13639 assert (nparms==0);
13641 emitcode ("lcall","System_GetCurrent%sId",name);
13642 /* put result into place */
13644 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13645 if (rsym->liveFrom != rsym->liveTo) {
13646 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13647 aopPut(IC_RESULT(ic),"a",0);
13648 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13653 /*-----------------------------------------------------------------*/
13654 /* genDjnz - generate decrement & jump if not zero instrucion */
13655 /*-----------------------------------------------------------------*/
13657 genDjnz (iCode * ic, iCode * ifx)
13659 symbol *lbl, *lbl1;
13663 /* if the if condition has a false label
13664 then we cannot save */
13665 if (IC_FALSE (ifx))
13668 /* if the minus is not of the form a = a - 1 */
13669 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
13670 !IS_OP_LITERAL (IC_RIGHT (ic)))
13673 if (operandLitValue (IC_RIGHT (ic)) != 1)
13676 /* if the size of this greater than one then no
13678 if (getSize (operandType (IC_RESULT (ic))) > 1)
13681 /* otherwise we can save BIG */
13683 D (emitcode (";", "genDjnz"));
13685 lbl = newiTempLabel (NULL);
13686 lbl1 = newiTempLabel (NULL);
13688 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
13690 if (AOP_NEEDSACC(IC_RESULT(ic)))
13692 /* If the result is accessed indirectly via
13693 * the accumulator, we must explicitly write
13694 * it back after the decrement.
13696 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE, NULL);
13698 if (strcmp(rByte, "a"))
13700 /* Something is hopelessly wrong */
13701 fprintf(stderr, "*** warning: internal error at %s:%d\n",
13702 __FILE__, __LINE__);
13703 /* We can just give up; the generated code will be inefficient,
13704 * but what the hey.
13706 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13709 emitcode ("dec", "%s", rByte);
13710 aopPut (IC_RESULT (ic), rByte, 0);
13711 emitcode ("jnz", "!tlabel", lbl->key + 100);
13713 else if (IS_AOP_PREG (IC_RESULT (ic)))
13715 emitcode ("dec", "%s",
13716 aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL));
13717 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL));
13718 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13719 ifx->generated = 1;
13720 emitcode ("jnz", "!tlabel", lbl->key + 100);
13724 emitcode ("djnz", "%s,!tlabel", aopGet (IC_RESULT (ic), 0, FALSE, TRUE, NULL),
13727 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
13729 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
13732 if (!ifx->generated)
13733 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13734 ifx->generated = 1;
13738 /*-----------------------------------------------------------------*/
13739 /* genReceive - generate code for a receive iCode */
13740 /*-----------------------------------------------------------------*/
13742 genReceive (iCode * ic)
13744 int size = getSize (operandType (IC_RESULT (ic)));
13748 D (emitcode (";", "genReceive"));
13750 if (ic->argreg == 1)
13752 /* first parameter */
13753 if (AOP_IS_STR(IC_RESULT(ic)))
13755 /* Nothing to do: it's already in the proper place. */
13762 useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
13763 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
13764 IS_TRUE_SYMOP (IC_RESULT (ic)));
13767 aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
13770 /* Sanity checking... */
13771 if (AOP_USESDPTR(IC_RESULT(ic)))
13773 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
13774 "genReceive got unexpected DPTR.");
13776 assignResultValue (IC_RESULT (ic), NULL);
13779 else if (ic->argreg > 12)
13780 { /* bit parameters */
13781 if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
13783 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
13784 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
13785 outBitC(IC_RESULT (ic));
13790 /* second receive onwards */
13791 /* this gets a little tricky since unused receives will be
13792 eliminated, we have saved the reg in the type field . and
13793 we use that to figure out which register to use */
13794 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
13795 rb1off = ic->argreg;
13798 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
13801 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13804 /*-----------------------------------------------------------------*/
13805 /* genDummyRead - generate code for dummy read of volatiles */
13806 /*-----------------------------------------------------------------*/
13808 genDummyRead (iCode * ic)
13813 D (emitcode(";", "genDummyRead"));
13815 op = IC_RIGHT (ic);
13816 if (op && IS_SYMOP (op))
13818 aopOp (op, ic, FALSE, FALSE);
13820 /* if the result is a bit */
13821 if (AOP_TYPE (op) == AOP_CRY)
13822 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13825 /* bit variables done */
13827 size = AOP_SIZE (op);
13831 MOVA (aopGet (op, offset, FALSE, FALSE, FALSE));
13836 freeAsmop (op, NULL, ic, TRUE);
13840 if (op && IS_SYMOP (op))
13842 aopOp (op, ic, FALSE, FALSE);
13844 /* if the result is a bit */
13845 if (AOP_TYPE (op) == AOP_CRY)
13846 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13849 /* bit variables done */
13851 size = AOP_SIZE (op);
13855 MOVA (aopGet (op, offset, FALSE, FALSE, FALSE));
13860 freeAsmop (op, NULL, ic, TRUE);
13864 /*-----------------------------------------------------------------*/
13865 /* genCritical - generate code for start of a critical sequence */
13866 /*-----------------------------------------------------------------*/
13868 genCritical (iCode *ic)
13870 symbol *tlbl = newiTempLabel (NULL);
13872 D (emitcode(";", "genCritical"));
13874 if (IC_RESULT (ic))
13876 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
13877 aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
13878 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
13879 aopPut (IC_RESULT (ic), zero, 0);
13881 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13885 emitcode ("setb", "c");
13886 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
13887 emitcode ("clr", "c");
13889 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
13893 /*-----------------------------------------------------------------*/
13894 /* genEndCritical - generate code for end of a critical sequence */
13895 /*-----------------------------------------------------------------*/
13897 genEndCritical (iCode *ic)
13899 D(emitcode("; genEndCritical",""));
13903 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
13904 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
13906 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
13907 emitcode ("mov", "ea,c");
13911 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE, FALSE));
13912 emitcode ("rrc", "a");
13913 emitcode ("mov", "ea,c");
13915 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
13919 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
13920 emitcode ("mov", "ea,c");
13926 /*-----------------------------------------------------------------*/
13927 /* genBuiltIn - calls the appropriate function to generating code */
13928 /* for a built in function */
13929 /*-----------------------------------------------------------------*/
13930 static void genBuiltIn (iCode *ic)
13932 operand *bi_parms[MAX_BUILTIN_ARGS];
13937 /* get all the arguments for a built in function */
13938 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
13940 /* which function is it */
13941 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
13942 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
13943 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
13944 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
13945 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
13946 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
13947 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
13948 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
13949 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
13950 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
13951 genMemsetX(bi_iCode,nbi_parms,bi_parms);
13952 } else if (strcmp(bif->name,"__builtin_inp")==0) {
13953 genInp(bi_iCode,nbi_parms,bi_parms);
13954 } else if (strcmp(bif->name,"__builtin_outp")==0) {
13955 genOutp(bi_iCode,nbi_parms,bi_parms);
13956 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
13957 genSwapW(bi_iCode,nbi_parms,bi_parms);
13958 /* JavaNative builtIns */
13959 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
13960 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
13961 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
13962 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
13963 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
13964 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
13965 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
13966 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
13967 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
13968 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
13969 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
13970 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
13971 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
13972 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
13973 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
13974 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
13975 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
13976 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
13977 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
13978 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
13979 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
13980 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
13981 } else if (strcmp(bif->name,"MM_Malloc")==0) {
13982 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
13983 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
13984 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
13985 } else if (strcmp(bif->name,"MM_Free")==0) {
13986 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
13987 } else if (strcmp(bif->name,"MM_Deref")==0) {
13988 genMMDeref(bi_iCode,nbi_parms,bi_parms);
13989 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
13990 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
13991 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
13992 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
13993 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
13994 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
13995 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
13996 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
13997 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
13998 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
13999 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
14000 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
14001 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
14002 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
14003 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
14004 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
14005 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
14006 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
14007 } else if (strcmp(bif->name,"System_SaveThread")==0) {
14008 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
14009 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
14010 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
14011 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
14012 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
14013 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
14014 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
14015 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
14016 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
14017 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
14018 genSystem(bi_iCode,nbi_parms,"ProcessYield");
14019 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
14020 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
14021 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
14022 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
14023 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
14024 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
14025 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
14026 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
14027 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
14028 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
14030 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
14036 /*-----------------------------------------------------------------*/
14037 /* gen390Code - generate code for Dallas 390 based controllers */
14038 /*-----------------------------------------------------------------*/
14040 gen390Code (iCode * lic)
14045 _G.currentFunc = NULL;
14046 lineHead = lineCurr = NULL;
14047 dptrn[1][0] = "dpl1";
14048 dptrn[1][1] = "dph1";
14049 dptrn[1][2] = "dpx1";
14051 if (options.model == MODEL_FLAT24) {
14052 fReturnSizeDS390 = 5;
14053 fReturn = fReturn24;
14055 fReturnSizeDS390 = 4;
14056 fReturn = fReturn16;
14057 options.stack10bit=0;
14060 /* print the allocation information */
14061 if (allocInfo && currFunc)
14062 printAllocInfo (currFunc, codeOutFile);
14064 /* if debug information required */
14065 if (options.debug && currFunc)
14067 debugFile->writeFunction (currFunc, lic);
14069 /* stack pointer name */
14070 if (options.useXstack)
14076 for (ic = lic; ic; ic = ic->next)
14078 _G.current_iCode = ic;
14080 if (ic->lineno && cln != ic->lineno)
14084 debugFile->writeCLine (ic);
14086 if (!options.noCcodeInAsm) {
14087 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
14088 printCLine(ic->filename, ic->lineno));
14092 if (options.iCodeInAsm) {
14093 emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
14095 /* if the result is marked as
14096 spilt and rematerializable or code for
14097 this has already been generated then
14099 if (resultRemat (ic) || ic->generated)
14102 /* depending on the operation */
14122 /* IPOP happens only when trying to restore a
14123 spilt live range, if there is an ifx statement
14124 following this pop then the if statement might
14125 be using some of the registers being popped which
14126 would destory the contents of the register so
14127 we need to check for this condition and handle it */
14129 ic->next->op == IFX &&
14130 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
14131 genIfx (ic->next, ic);
14149 genEndFunction (ic);
14169 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
14186 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
14190 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
14197 /* note these two are xlated by algebraic equivalence
14198 during parsing SDCC.y */
14199 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
14200 "got '>=' or '<=' shouldn't have come here");
14204 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
14216 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
14220 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
14224 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
14248 genRightShift (ic);
14251 case GET_VALUE_AT_ADDRESS:
14253 hasInc (IC_LEFT (ic), ic,
14254 getSize (operandType (IC_RESULT (ic)))));
14258 if (POINTER_SET (ic))
14260 hasInc (IC_RESULT (ic), ic,
14261 getSize (operandType (IC_RIGHT (ic)))));
14287 if (ic->builtinSEND)
14290 addSet (&_G.sendSet, ic);
14293 case DUMMY_READ_VOLATILE:
14302 genEndCritical (ic);
14309 #if 0 // obsolete, and buggy for != xdata
14321 /* now we are ready to call the
14322 peep hole optimizer */
14323 if (!options.nopeep)
14324 peepHole (&lineHead);
14326 /* now do the actual printing */
14327 printLine (lineHead, codeOutFile);