1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for DS80C390
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7 DS390 adaptation by Kevin Vigor <kevin@vigor.nu>
9 This program is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 2, or (at your option) any
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 In other words, you are welcome to use, share and improve this program.
24 You are forbidden to forbid anyone else to use, share and improve
25 what you give them. Help stamp out software-hoarding!
26 -------------------------------------------------------------------------*/
35 #include "SDCCglobl.h"
43 #define BETTER_LITERAL_SHIFT
45 char *aopLiteral (value * val, int offset);
48 /* this is the down and dirty file with all kinds of
49 kludgy & hacky stuff. This is what it is all about
50 CODE GENERATION for a specific MCU . some of the
51 routines may be reusable, will have to see */
53 static char *zero = "#0";
54 static char *one = "#1";
57 #define TR_DPTR(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_DPTR1 %s ", s); }
58 #define TR_AP(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_AP %s ", s); }
60 unsigned fReturnSizeDS390 = 5;
61 static char *fReturn24[] =
62 {"dpl", "dph", "dpx", "b", "a"};
63 static char *fReturn16[] =
64 {"dpl", "dph", "b", "a"};
65 static char **fReturn = fReturn24;
66 static char *accUse[] =
68 static char *dptrn[2][3];
69 static char *javaRet[] = { "r0","r1","r2","r3"};
70 static short rbank = -1;
72 #define REG_WITH_INDEX ds390_regWithIdx
74 #define AOP(op) op->aop
75 #define AOP_TYPE(op) AOP(op)->type
76 #define AOP_SIZE(op) AOP(op)->size
77 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
78 AOP_TYPE(x) == AOP_R0))
80 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
81 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
84 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
85 (x->aopu.aop_reg[0] == REG_WITH_INDEX(R0_IDX) || \
86 x->aopu.aop_reg[0] == REG_WITH_INDEX(R1_IDX) )))
87 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
88 #define AOP_USESDPTR(x) ((AOP_TYPE(x) == AOP_DPTR) || (AOP_TYPE(x) == AOP_STR))
89 #define AOP_USESDPTR2(x) ((AOP_TYPE(x) == AOP_DPTR2) || (AOP_TYPE(x) == AOP_DPTRn))
91 // The following two macros can be used even if the aop has not yet been aopOp'd.
92 #define AOP_IS_STR(x) (IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
93 #define AOP_IS_DPTRn(x) (IS_SYMOP(x) && OP_SYMBOL(x)->dptr)
95 /* Workaround for DS80C390 bug: div ab may return bogus results
96 * if A is accessed in instruction immediately before the div.
98 * Will be fixed in B4 rev of processor, Dallas claims.
101 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
102 if (!AOP_NEEDSACC(RIGHT)) \
104 /* We can load A first, then B, since \
105 * B (the RIGHT operand) won't clobber A, \
106 * thus avoiding touching A right before the div. \
108 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
109 L = aopGet(LEFT,0,FALSE,FALSE,NULL); \
111 L = aopGet(RIGHT,0,FALSE,FALSE,"b"); \
116 /* Just stuff in a nop after loading A. */ \
117 emitcode("mov","b,%s",aopGet(RIGHT,0,FALSE,FALSE,NULL));\
118 L = aopGet(LEFT,0,FALSE,FALSE,NULL); \
120 emitcode("nop", "; workaround for DS80C390 div bug."); \
123 #define R0INB _G.bu.bs.r0InB
124 #define R1INB _G.bu.bs.r1InB
125 #define OPINB _G.bu.bs.OpInB
126 #define BINUSE _G.bu.BInUse
136 short r0InB : 2;//2 so we can see it overflow
137 short r1InB : 2;//2 so we can see it overflow
138 short OpInB : 2;//2 so we can see it overflow
149 iCode *current_iCode;
154 static char *rb1regs[] = {
155 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7",
156 "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7"
159 static void saveRBank (int, iCode *, bool);
161 #define RESULTONSTACK(x) \
162 (IC_RESULT(x) && IC_RESULT(x)->aop && \
163 IC_RESULT(x)->aop->type == AOP_STK )
165 #define MOVA(x) mova(x) /* use function to avoid multiple eval */
166 #define MOVB(x) movb(x)
168 #define CLRC emitcode("clr","c")
169 #define SETC emitcode("setb","c")
171 // A scratch register which will be used to hold
172 // result bytes from operands in far space via DPTR2.
173 #define DP2_RESULT_REG "_ap"
175 static lineNode *lineHead = NULL;
176 static lineNode *lineCurr = NULL;
178 static unsigned char SLMask[] =
179 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
180 0xE0, 0xC0, 0x80, 0x00};
181 static unsigned char SRMask[] =
182 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
183 0x07, 0x03, 0x01, 0x00};
189 #define PROTECT_SP {if (options.protect_sp_update) { \
190 symbol *lbl = newiTempLabel(NULL); \
191 emitcode ("setb","F1"); \
192 emitcode ("jbc","EA,!tlabel",lbl->key+100); \
193 emitcode ("clr","F1"); \
194 emitcode ("","!tlabeldef",lbl->key+100); \
196 #define UNPROTECT_SP { if (options.protect_sp_update) { \
197 emitcode ("mov","EA,F1"); \
200 static int _currentDPS; /* Current processor DPS. */
201 static int _desiredDPS; /* DPS value compiler thinks we should be using. */
202 static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */
204 /*-----------------------------------------------------------------*/
205 /* emitcode - writes the code into a file : for now it is simple */
206 /*-----------------------------------------------------------------*/
208 emitcode (char *inst, const char *fmt,...)
211 char lb[INITIAL_INLINEASM];
220 SNPRINTF (lb, sizeof(lb), "%s\t", inst);
224 SNPRINTF (lb, sizeof(lb), "%s", inst);
227 tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb), fmt, ap);
231 tvsprintf (lb, sizeof(lb), fmt, ap);
234 while (isspace ((unsigned char)*lbp))
241 lineCurr = (lineCurr ?
242 connectLine (lineCurr, newLineNode (lb)) :
243 (lineHead = newLineNode (lb)));
246 lineCurr->isInline = _G.inLine;
247 lineCurr->isDebug = _G.debugLine;
248 lineCurr->ic = _G.current_iCode;
249 lineCurr->aln = ds390newAsmLineNode(_currentDPS);
254 emitLabel (symbol *tlbl)
256 emitcode ("", "!tlabeldef", tlbl->key + 100);
259 /*-----------------------------------------------------------------*/
260 /* ds390_emitDebuggerSymbol - associate the current code location */
261 /* with a debugger symbol */
262 /*-----------------------------------------------------------------*/
264 ds390_emitDebuggerSymbol (char * debugSym)
267 emitcode ("", "%s ==.", debugSym);
271 /*-----------------------------------------------------------------*/
272 /* mova - moves specified value into accumulator */
273 /*-----------------------------------------------------------------*/
277 /* do some early peephole optimization */
278 if (!strncmp(x, "a", 2) || !strncmp(x, "acc", 4))
281 emitcode("mov", "a,%s", x);
284 /*-----------------------------------------------------------------*/
285 /* movb - moves specified value into register b */
286 /*-----------------------------------------------------------------*/
290 /* do some early peephole optimization */
291 if (!strncmp(x, "b", 2))
294 emitcode("mov","b,%s", x);
297 /*-----------------------------------------------------------------*/
298 /* movc - moves specified value into the carry */
299 /*-----------------------------------------------------------------*/
307 else if (strcmp (s, "c"))
308 {/* it's not in carry already */
310 /* set C, if a >= 1 */
311 emitcode ("add", "a,#0xff");
315 /*-----------------------------------------------------------------*/
316 /* pushB - saves register B if necessary */
317 /*-----------------------------------------------------------------*/
321 bool pushedB = FALSE;
325 emitcode ("push", "b");
326 // printf("B was in use !\n");
336 /*-----------------------------------------------------------------*/
337 /* popB - restores value of register B if necessary */
338 /*-----------------------------------------------------------------*/
344 emitcode ("pop", "b");
352 /*-----------------------------------------------------------------*/
353 /* pushReg - saves register */
354 /*-----------------------------------------------------------------*/
356 pushReg (int index, bool bits_pushed)
358 regs * reg = REG_WITH_INDEX (index);
359 if (reg->type == REG_BIT)
362 emitcode ("push", "%s", reg->base);
366 emitcode ("push", "%s", reg->dname);
370 /*-----------------------------------------------------------------*/
371 /* popReg - restores register */
372 /*-----------------------------------------------------------------*/
374 popReg (int index, bool bits_popped)
376 regs * reg = REG_WITH_INDEX (index);
377 if (reg->type == REG_BIT)
380 emitcode ("pop", "%s", reg->base);
384 emitcode ("pop", "%s", reg->dname);
388 /*-----------------------------------------------------------------*/
389 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
390 /*-----------------------------------------------------------------*/
392 getFreePtr (iCode * ic, asmop ** aopp, bool result)
397 /* the logic: if r0 & r1 used in the instruction
398 then we are in trouble otherwise */
400 /* first check if r0 & r1 are used by this
401 instruction, in which case we are in trouble */
402 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
403 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
408 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
409 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
411 /* if no usage of r0 then return it */
414 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
415 (*aopp)->type = AOP_R0;
417 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
420 /* if no usage of r1 then return it */
423 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
424 (*aopp)->type = AOP_R1;
426 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R1_IDX);
429 /* now we know they both have usage */
430 /* if r0 not used in this instruction */
433 /* push it if not already pushed */
436 emitcode ("push", "%s",
437 REG_WITH_INDEX (R0_IDX)->dname);
441 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
442 (*aopp)->type = AOP_R0;
444 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
447 /* if r1 not used then */
451 /* push it if not already pushed */
454 emitcode ("push", "%s",
455 REG_WITH_INDEX (R1_IDX)->dname);
459 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
460 (*aopp)->type = AOP_R1;
461 return REG_WITH_INDEX (R1_IDX);
465 /* I said end of world, but not quite end of world yet */
466 /* if this is a result then we can push it on the stack */
469 (*aopp)->type = AOP_STK;
473 /* now this is REALLY the end of the world */
474 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
475 "getFreePtr should never reach here");
478 return NULL; // notreached, but makes compiler happy.
482 /*-----------------------------------------------------------------*/
483 /* genSetDPTR: generate code to select which DPTR is in use (zero */
484 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */
485 /* alternate DPTR (DPL1/DPH1/DPX1). */
486 /*-----------------------------------------------------------------*/
491 /* If we are doing lazy evaluation, simply note the desired
492 * change, but don't emit any code yet.
502 emitcode ("mov", "dps,#0");
507 emitcode ("mov", "dps,#1");
511 /*------------------------------------------------------------------*/
512 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
514 /* Any code that operates on DPTR (NB: not on the individual */
515 /* components, like DPH) *must* call _flushLazyDPS() before using */
516 /* DPTR within a lazy DPS evaluation block. */
518 /* Note that aopPut and aopGet already contain the proper calls to */
519 /* _flushLazyDPS, so it is safe to use these calls within a lazy */
520 /* DPS evaluation block. */
522 /* Also, _flushLazyDPS must be called before any flow control */
523 /* operations that could potentially branch out of the block. */
525 /* Lazy DPS evaluation is simply an optimization (though an */
526 /* important one), so if in doubt, leave it out. */
527 /*------------------------------------------------------------------*/
529 _startLazyDPSEvaluation (void)
533 #ifdef BETTER_LITERAL_SHIFT
540 /*------------------------------------------------------------------*/
541 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
542 /* desired one. Call before using DPTR within a lazy DPS evaluation */
544 /*------------------------------------------------------------------*/
554 if (_desiredDPS != _currentDPS)
558 emitcode ("inc", "dps");
562 emitcode ("dec", "dps");
564 _currentDPS = _desiredDPS;
568 /*-----------------------------------------------------------------*/
569 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
571 /* Forces us back to the safe state (standard DPTR selected). */
572 /*-----------------------------------------------------------------*/
574 _endLazyDPSEvaluation (void)
576 #ifdef BETTER_LITERAL_SHIFT
594 /*-----------------------------------------------------------------*/
595 /* newAsmop - creates a new asmOp */
596 /*-----------------------------------------------------------------*/
598 newAsmop (short type)
602 aop = Safe_calloc (1, sizeof (asmop));
608 /*-----------------------------------------------------------------*/
609 /* pointerCode - returns the code for a pointer type */
610 /*-----------------------------------------------------------------*/
612 pointerCode (sym_link * etype)
615 return PTR_TYPE (SPEC_OCLS (etype));
619 /*-----------------------------------------------------------------*/
620 /* leftRightUseAcc - returns size of accumulator use by operands */
621 /*-----------------------------------------------------------------*/
623 leftRightUseAcc(iCode *ic)
632 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
633 "null iCode pointer");
640 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
643 size = getSize (OP_SYMBOL (op)->type);
648 else if (ic->op == JUMPTABLE)
651 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
654 size = getSize (OP_SYMBOL (op)->type);
662 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
665 size = getSize (OP_SYMBOL (op)->type);
670 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
673 size = getSize (OP_SYMBOL (op)->type);
685 /*-----------------------------------------------------------------*/
686 /* aopForSym - for a true symbol */
687 /*-----------------------------------------------------------------*/
689 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
693 bool accuse = leftRightUseAcc (ic) || _G.accInUse;
694 char *dpl = useDP2 ? "dpl1" : "dpl";
695 char *dph = useDP2 ? "dph1" : "dph";
696 char *dpx = useDP2 ? "dpx1" : "dpx";
698 wassertl (ic != NULL, "Got a null iCode");
699 wassertl (sym != NULL, "Got a null symbol");
701 space = SPEC_OCLS (sym->etype);
703 /* if already has one */
706 if ((sym->aop->type == AOP_DPTR && useDP2)
707 || (sym->aop->type == AOP_DPTR2 && !useDP2))
711 sym->aop->allocated++;
716 /* assign depending on the storage class */
717 /* if it is on the stack or indirectly addressable */
718 /* space we need to assign either r0 or r1 to it */
719 if ((sym->onStack && !options.stack10bit) || sym->iaccess)
721 sym->aop = aop = newAsmop (0);
722 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
723 aop->size = getSize (sym->type);
725 /* now assign the address of the variable to
726 the pointer register */
727 if (aop->type != AOP_STK)
731 signed char offset = ((sym->stack < 0) ?
732 ((signed char) (sym->stack - _G.nRegsSaved)) :
733 ((signed char) sym->stack)) & 0xff;
735 if ((abs(offset) <= 3) ||
736 (accuse && (abs(offset) <= 7)))
738 emitcode ("mov", "%s,_bp",
739 aop->aopu.aop_ptr->name);
742 emitcode ("dec", aop->aopu.aop_ptr->name);
747 emitcode ("inc", aop->aopu.aop_ptr->name);
754 emitcode ("push", "acc");
755 emitcode ("mov", "a,_bp");
756 emitcode ("add", "a,#!constbyte", offset);
757 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
759 emitcode ("pop", "acc");
764 emitcode ("mov", "%s,#%s",
765 aop->aopu.aop_ptr->name,
768 aop->paged = space->paged;
771 aop->aopu.aop_stk = sym->stack;
775 if (sym->onStack && options.stack10bit)
777 short stack_val = -((sym->stack < 0) ?
778 ((short) (sym->stack - _G.nRegsSaved)) :
779 ((short) sym->stack)) ;
781 emitcode ("push",dpl);
782 emitcode ("push",dph);
783 emitcode ("push",dpx);
785 /* It's on the 10 bit stack, which is located in
788 if (stack_val < 0 && stack_val > -5)
789 { /* between -5 & -1 */
790 if (options.model == MODEL_FLAT24)
792 emitcode ("mov", "%s,#!constbyte", dpx,
793 (options.stack_loc >> 16) & 0xff);
795 emitcode ("mov", "%s,_bpx+1", dph);
796 emitcode ("mov", "%s,_bpx", dpl);
798 emitcode ("mov","dps,#1");
800 stack_val = -stack_val;
801 while (stack_val--) {
802 emitcode ("inc","dptr");
805 emitcode("mov","dps,#0");
811 emitcode ("push", "acc");
813 emitcode ("mov", "a,_bpx");
814 emitcode ("clr","c");
815 emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
816 emitcode ("mov","%s,a", dpl);
817 emitcode ("mov","a,_bpx+1");
818 emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
819 emitcode ("mov", "%s,a", dph);
820 if (options.model == MODEL_FLAT24)
822 emitcode ("mov", "%s,#!constbyte", dpx,
823 (options.stack_loc >> 16) & 0xff);
827 emitcode ("pop", "acc");
829 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
830 aop->size = getSize (sym->type);
834 /* if in bit space */
835 if (IN_BITSPACE (space))
837 sym->aop = aop = newAsmop (AOP_CRY);
838 aop->aopu.aop_dir = sym->rname;
839 aop->size = getSize (sym->type);
842 /* if it is in direct space */
843 if (IN_DIRSPACE (space))
845 sym->aop = aop = newAsmop (AOP_DIR);
846 aop->aopu.aop_dir = sym->rname;
847 aop->size = getSize (sym->type);
851 /* special case for a function */
852 if (IS_FUNC (sym->type) && !(sym->isitmp))
854 sym->aop = aop = newAsmop (AOP_IMMD);
855 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
856 aop->size = FPTRSIZE;
860 /* only remaining is far space */
861 /* in which case DPTR gets the address */
862 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
867 emitcode ("mov", "dptr,#%s", sym->rname);
872 emitcode ("mov", "dptr,#%s", sym->rname);
874 aop->size = getSize (sym->type);
876 /* if it is in code space */
877 if (IN_CODESPACE (space))
883 /*-----------------------------------------------------------------*/
884 /* aopForRemat - rematerialzes an object */
885 /*-----------------------------------------------------------------*/
887 aopForRemat (symbol * sym)
889 iCode *ic = sym->rematiCode;
890 asmop *aop = newAsmop (AOP_IMMD);
897 val += (int) operandLitValue (IC_RIGHT (ic));
898 else if (ic->op == '-')
899 val -= (int) operandLitValue (IC_RIGHT (ic));
900 else if (IS_CAST_ICODE(ic)) {
901 sym_link *from_type = operandType(IC_RIGHT(ic));
902 aop->aopu.aop_immd.from_cast_remat = 1;
903 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
904 ptr_type = pointerTypeToGPByte (DCL_TYPE(from_type), NULL, NULL);
908 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
913 SNPRINTF (buffer, sizeof(buffer),
915 OP_SYMBOL (IC_LEFT (ic))->rname,
916 val >= 0 ? '+' : '-',
917 abs (val) & 0xffffff);
921 if (IS_ASSIGN_ICODE(ic) && isOperandLiteral(IC_RIGHT(ic)))
923 SNPRINTF(buffer, sizeof(buffer),
924 "0x%x",(int) operandLitValue (IC_RIGHT (ic)));
928 strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
932 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
933 /* set immd2 field if required */
934 if (aop->aopu.aop_immd.from_cast_remat)
936 tsprintf(buffer, sizeof(buffer), "#!constbyte",ptr_type);
937 aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
943 /*-----------------------------------------------------------------*/
944 /* aopHasRegs - returns true if aop has regs between from-to */
945 /*-----------------------------------------------------------------*/
946 static int aopHasRegs(asmop *aop, int from, int to)
950 if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
952 for (; size < aop->size ; size++) {
954 for (reg = from ; reg <= to ; reg++)
955 if (aop->aopu.aop_reg[size] == REG_WITH_INDEX(reg)) return 1;
960 /*-----------------------------------------------------------------*/
961 /* regsInCommon - two operands have some registers in common */
962 /*-----------------------------------------------------------------*/
964 regsInCommon (operand * op1, operand * op2)
969 /* if they have registers in common */
970 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
973 sym1 = OP_SYMBOL (op1);
974 sym2 = OP_SYMBOL (op2);
976 if (sym1->nRegs == 0 || sym2->nRegs == 0)
979 for (i = 0; i < sym1->nRegs; i++)
985 for (j = 0; j < sym2->nRegs; j++)
990 if (sym2->regs[j] == sym1->regs[i])
998 /*-----------------------------------------------------------------*/
999 /* operandsEqu - equivalent */
1000 /*-----------------------------------------------------------------*/
1002 operandsEqu (operand * op1, operand * op2)
1004 symbol *sym1, *sym2;
1006 /* if they're not symbols */
1007 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
1010 sym1 = OP_SYMBOL (op1);
1011 sym2 = OP_SYMBOL (op2);
1013 /* if both are itemps & one is spilt
1014 and the other is not then false */
1015 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
1016 sym1->isspilt != sym2->isspilt)
1019 /* if they are the same */
1023 /* if they have the same rname */
1024 if (sym1->rname[0] && sym2->rname[0] &&
1025 strcmp (sym1->rname, sym2->rname) == 0 &&
1026 !(IS_PARM (op2) && IS_ITEMP (op1)))
1029 /* if left is a tmp & right is not */
1030 if (IS_ITEMP (op1) &&
1033 (sym1->usl.spillLoc == sym2))
1036 if (IS_ITEMP (op2) &&
1040 (sym2->usl.spillLoc == sym1))
1043 /* are they spilt to the same location */
1044 if (IS_ITEMP (op2) &&
1048 (sym1->usl.spillLoc == sym2->usl.spillLoc))
1054 /*-----------------------------------------------------------------*/
1055 /* sameRegs - two asmops have the same registers */
1056 /*-----------------------------------------------------------------*/
1058 sameRegs (asmop * aop1, asmop * aop2)
1064 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
1071 if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
1074 if (aop1->type != aop2->type)
1077 if (aop1->size != aop2->size)
1080 for (i = 0; i < aop1->size; i++)
1081 if (aop1->aopu.aop_reg[i] != aop2->aopu.aop_reg[i])
1087 /*-----------------------------------------------------------------*/
1088 /* aopOp - allocates an asmop for an operand : */
1089 /*-----------------------------------------------------------------*/
1091 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
1100 /* if this a literal */
1101 if (IS_OP_LITERAL (op))
1103 op->aop = aop = newAsmop (AOP_LIT);
1104 aop->aopu.aop_lit = op->operand.valOperand;
1105 aop->size = getSize (operandType (op));
1109 /* if already has a asmop then continue */
1112 if ((op->aop->type == AOP_DPTR && useDP2)
1113 || (op->aop->type == AOP_DPTR2 && !useDP2))
1117 op->aop->allocated++;
1122 /* if the underlying symbol has a aop */
1123 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
1125 op->aop = OP_SYMBOL (op)->aop;
1126 if ((op->aop->type == AOP_DPTR && useDP2)
1127 || (op->aop->type == AOP_DPTR2 && !useDP2))
1131 op->aop->allocated++;
1136 /* if this is a true symbol */
1137 if (IS_TRUE_SYMOP (op))
1139 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
1143 /* this is a temporary : this has
1149 e) can be a return use only */
1151 sym = OP_SYMBOL (op);
1153 /* if the type is a conditional */
1154 if (sym->regType == REG_CND)
1156 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
1161 /* if it is spilt then two situations
1163 b) has a spill location */
1164 if (sym->isspilt || sym->nRegs == 0)
1167 /* rematerialize it NOW */
1170 sym->aop = op->aop = aop =
1172 aop->size = getSize (sym->type);
1179 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
1180 aop->size = getSize (sym->type);
1181 for (i = 0; i < 2; i++)
1182 aop->aopu.aop_str[i] = accUse[i];
1192 /* a AOP_STR uses DPTR, but DPTR is already in use;
1195 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
1198 aop = op->aop = sym->aop = newAsmop (AOP_STR);
1199 aop->size = getSize (sym->type);
1200 for (i = 0; i < fReturnSizeDS390; i++)
1201 aop->aopu.aop_str[i] = fReturn[i];
1205 if (sym->dptr) { /* has been allocated to a DPTRn */
1206 aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
1207 aop->size = getSize (sym->type);
1208 aop->aopu.dptr = sym->dptr;
1212 if (sym->usl.spillLoc)
1214 asmop *oldAsmOp = NULL;
1216 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1218 /* force a new aop if sizes differ */
1219 oldAsmOp = sym->usl.spillLoc->aop;
1220 sym->usl.spillLoc->aop = NULL;
1222 sym->aop = op->aop = aop =
1223 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
1224 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1226 /* Don't reuse the new aop, go with the last one */
1227 sym->usl.spillLoc->aop = oldAsmOp;
1229 aop->size = getSize (sym->type);
1233 /* else must be a dummy iTemp */
1234 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1235 aop->size = getSize (sym->type);
1239 /* if the type is a bit register */
1240 if (sym->regType == REG_BIT)
1242 sym->aop = op->aop = aop = newAsmop (AOP_CRY);
1243 aop->size = sym->nRegs;//1???
1244 aop->aopu.aop_reg[0] = sym->regs[0];
1245 aop->aopu.aop_dir = sym->regs[0]->name;
1249 /* must be in a register */
1250 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1251 aop->size = sym->nRegs;
1252 for (i = 0; i < sym->nRegs; i++)
1253 aop->aopu.aop_reg[i] = sym->regs[i];
1256 /*-----------------------------------------------------------------*/
1257 /* freeAsmop - free up the asmop given to an operand */
1258 /*----------------------------------------------------------------*/
1260 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1277 /* depending on the asmop type only three cases need work
1278 AOP_R0, AOP_R1 & AOP_STK */
1286 emitcode ("pop", "ar0");
1290 bitVectUnSetBit (ic->rUsed, R0_IDX);
1298 emitcode ("pop", "ar1");
1302 bitVectUnSetBit (ic->rUsed, R1_IDX);
1308 int stk = aop->aopu.aop_stk + aop->size;
1309 bitVectUnSetBit (ic->rUsed, R0_IDX);
1310 bitVectUnSetBit (ic->rUsed, R1_IDX);
1312 getFreePtr (ic, &aop, FALSE);
1314 if (options.stack10bit)
1316 /* I'm not sure what to do here yet... */
1319 "*** Warning: probably generating bad code for "
1320 "10 bit stack mode.\n");
1325 emitcode ("mov", "a,_bp");
1326 emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
1327 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1331 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1336 emitcode ("pop", "acc");
1337 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1340 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1343 freeAsmop (op, NULL, ic, TRUE);
1346 emitcode ("pop", "ar1");
1351 emitcode ("pop", "ar0");
1356 if (_G.dptr1InUse) {
1357 emitcode ("pop","dpx1");
1358 emitcode ("pop","dph1");
1359 emitcode ("pop","dpl1");
1364 emitcode ("pop","dpx");
1365 emitcode ("pop","dph");
1366 emitcode ("pop","dpl");
1372 /* all other cases just dealloc */
1378 OP_SYMBOL (op)->aop = NULL;
1379 /* if the symbol has a spill */
1381 SPIL_LOC (op)->aop = NULL;
1386 #define DEFAULT_ACC_WARNING 0
1387 static int saveAccWarn = DEFAULT_ACC_WARNING;
1390 /*-----------------------------------------------------------------*/
1391 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
1392 /* clobber the accumulator */
1393 /*-----------------------------------------------------------------*/
1395 aopGetUsesAcc (operand * oper, int offset)
1397 asmop * aop = AOP (oper);
1399 if (offset > (aop->size - 1))
1417 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1428 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1434 /* Error case --- will have been caught already */
1440 /*-------------------------------------------------------------------*/
1441 /* aopGet - for fetching value of the aop */
1443 /* Set saveAcc to NULL if you are sure it is OK to clobber the value */
1444 /* in the accumulator. Set it to the name of a free register */
1445 /* if acc must be preserved; the register will be used to preserve */
1446 /* acc temporarily and to return the result byte. */
1447 /*-------------------------------------------------------------------*/
1449 aopGet (operand * oper,
1455 asmop * aop = AOP (oper);
1457 /* offset is greater than
1459 if (offset > (aop->size - 1) &&
1460 aop->type != AOP_LIT)
1463 /* depending on type */
1471 /* if we need to increment it */
1472 while (offset > aop->coff)
1474 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1478 while (offset < aop->coff)
1480 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1487 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1488 return (dname ? "acc" : "a");
1490 SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1491 return Safe_strdup(buffer);
1494 assert(offset <= 3);
1495 return dptrn[aop->aopu.dptr][offset];
1500 if (aop->type == AOP_DPTR2)
1508 // if (aop->type != AOP_DPTR2)
1510 // if (saveAccWarn) { fprintf(stderr, "saveAcc for DPTR...\n"); }
1511 // emitcode(";", "spanky: saveAcc for DPTR");
1514 emitcode ("xch", "a, %s", saveAcc);
1519 while (offset > aop->coff)
1521 emitcode ("inc", "dptr");
1525 while (offset < aop->coff)
1527 emitcode ("lcall", "__decdptr");
1534 emitcode ("clr", "a");
1535 emitcode ("movc", "a,@a+dptr");
1539 emitcode ("movx", "a,@dptr");
1542 if (aop->type == AOP_DPTR2)
1550 emitcode ("xch", "a, %s", saveAcc);
1551 // if (strcmp(saveAcc, "_ap"))
1553 // emitcode(";", "spiffy: non _ap return from aopGet.");
1558 return (dname ? "acc" : "a");
1561 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1563 SNPRINTF(buffer, sizeof(buffer),
1564 "%s",aop->aopu.aop_immd.aop_immd2);
1568 SNPRINTF(buffer, sizeof(buffer),
1569 "#%s", aop->aopu.aop_immd.aop_immd1);
1575 tsprintf(buffer, sizeof(buffer),
1576 "#!his",aop->aopu.aop_immd.aop_immd1);
1579 tsprintf(buffer, sizeof(buffer),
1580 "#!hihis",aop->aopu.aop_immd.aop_immd1);
1583 tsprintf(buffer, sizeof(buffer),
1584 "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1586 default: /* should not need this (just in case) */
1587 SNPRINTF (buffer, sizeof(buffer),
1589 aop->aopu.aop_immd.aop_immd1,
1595 SNPRINTF (buffer, sizeof(buffer),
1597 aop->aopu.aop_immd.aop_immd1);
1599 return Safe_strdup(buffer);
1602 if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
1604 SNPRINTF (buffer, sizeof(buffer),
1606 aop->aopu.aop_dir, offset * 8);
1610 SNPRINTF (buffer, sizeof(buffer),
1617 SNPRINTF (buffer, sizeof(buffer),
1622 return Safe_strdup(buffer);
1626 return aop->aopu.aop_reg[offset]->dname;
1628 return aop->aopu.aop_reg[offset]->name;
1631 emitcode ("clr", "a");
1632 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1633 emitcode ("rlc", "a");
1634 return (dname ? "acc" : "a");
1637 if (!offset && dname)
1639 return aop->aopu.aop_str[offset];
1642 return aopLiteral (aop->aopu.aop_lit, offset);
1646 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1650 return aop->aopu.aop_str[offset];
1654 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1655 "aopget got unsupported aop->type");
1658 return NULL; // not reached, but makes compiler happy.
1661 /*-----------------------------------------------------------------*/
1662 /* 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 bool overlapping = regsInCommon (left, result) || operandsEqu(left, result);
9631 if (overlapping && offl>1)
9633 // we are in big trouble, but this shouldn't happen
9634 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9637 MOVA (aopGet (left, MSB32, FALSE, FALSE, NULL));
9644 emitcode ("rlc", "a");
9645 emitcode ("subb", "a,acc");
9646 emitcode ("xch", "a,%s",
9647 aopGet(left, MSB32, FALSE, FALSE, DP2_RESULT_REG));
9651 aopPut (result, zero, MSB32);
9657 emitcode ("clr", "c");
9661 emitcode ("mov", "c,acc.7");
9664 emitcode ("rrc", "a");
9666 if (overlapping && offl==MSB16)
9668 emitcode ("xch", "a,%s", aopGet (left, MSB24, FALSE, FALSE, DP2_RESULT_REG));
9672 aopPut (result, "a", MSB32 - offl);
9673 MOVA (aopGet (left, MSB24, FALSE, FALSE, NULL));
9676 emitcode ("rrc", "a");
9678 if (overlapping && offl==MSB16)
9680 emitcode ("xch", "a,%s", aopGet (left, MSB16, FALSE, FALSE, DP2_RESULT_REG));
9684 aopPut (result, "a", MSB24 - offl);
9685 MOVA (aopGet (left, MSB16, FALSE, FALSE, NULL));
9688 emitcode ("rrc", "a");
9691 aopPut (result, "a", MSB16 - offl);
9695 if (overlapping && offl==MSB16)
9697 emitcode ("xch", "a,%s", aopGet (left, LSB, FALSE, FALSE, DP2_RESULT_REG));
9701 aopPut (result, "a", MSB16 - offl);
9702 MOVA (aopGet (left, LSB, FALSE, FALSE, NULL));
9704 emitcode ("rrc", "a");
9705 aopPut (result, "a", LSB);
9709 /*-----------------------------------------------------------------*/
9710 /* genrshFour - shift four byte by a known amount != 0 */
9711 /*-----------------------------------------------------------------*/
9713 genrshFour (operand * result, operand * left,
9714 int shCount, int sign)
9716 D (emitcode (";", "genrshFour"));
9718 /* if shifting more that 3 bytes */
9722 _startLazyDPSEvaluation();
9724 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9726 movLeft2Result (left, MSB32, result, LSB, sign);
9727 addSign (result, MSB16, sign);
9728 _endLazyDPSEvaluation();
9730 else if (shCount >= 16)
9733 _startLazyDPSEvaluation();
9735 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9738 movLeft2Result (left, MSB24, result, LSB, 0);
9739 movLeft2Result (left, MSB32, result, MSB16, sign);
9741 addSign (result, MSB24, sign);
9742 _endLazyDPSEvaluation();
9744 else if (shCount >= 8)
9747 _startLazyDPSEvaluation();
9750 shiftRLong (left, MSB16, result, sign);
9752 else if (shCount == 0)
9754 movLeft2Result (left, MSB16, result, LSB, 0);
9755 movLeft2Result (left, MSB24, result, MSB16, 0);
9756 movLeft2Result (left, MSB32, result, MSB24, sign);
9757 addSign (result, MSB32, sign);
9761 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9762 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9763 /* the last shift is signed */
9764 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9765 addSign (result, MSB32, sign);
9767 _endLazyDPSEvaluation();
9771 /* 1 <= shCount <= 7 */
9774 shiftRLong (left, LSB, result, sign);
9776 shiftRLong (result, LSB, result, sign);
9780 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9781 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9782 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9787 #ifdef BETTER_LITERAL_SHIFT
9788 /*-----------------------------------------------------------------*/
9789 /* genRightShiftLiteral - right shifting by known count */
9790 /*-----------------------------------------------------------------*/
9792 genRightShiftLiteral (operand * left,
9798 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9801 size = getSize (operandType (result));
9803 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
9805 /* We only handle certain easy cases so far. */
9807 && (shCount < (size * 8))
9812 D(emitcode (";", "genRightShiftLiteral wimping out"););
9816 freeAsmop (right, NULL, ic, TRUE);
9818 aopOp (left, ic, FALSE, FALSE);
9819 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9822 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9826 /* test the LEFT size !!! */
9828 /* I suppose that the left size >= result size */
9831 size = getDataSize (result);
9832 _startLazyDPSEvaluation();
9834 movLeft2Result (left, size, result, size, 0);
9835 _endLazyDPSEvaluation();
9837 else if (shCount >= (size * 8))
9841 /* get sign in acc.7 */
9842 MOVA (aopGet (left, size - 1, FALSE, FALSE, NULL));
9844 addSign (result, LSB, sign);
9851 genrshOne (result, left, shCount, sign);
9855 genrshTwo (result, left, shCount, sign);
9859 genrshFour (result, left, shCount, sign);
9866 freeAsmop (result, NULL, ic, TRUE);
9867 freeAsmop (left, NULL, ic, TRUE);
9873 /*-----------------------------------------------------------------*/
9874 /* genSignedRightShift - right shift of signed number */
9875 /*-----------------------------------------------------------------*/
9877 genSignedRightShift (iCode * ic)
9879 operand *right, *left, *result;
9882 symbol *tlbl, *tlbl1;
9885 D (emitcode (";", "genSignedRightShift"));
9887 /* we do it the hard way put the shift count in b
9888 and loop thru preserving the sign */
9890 right = IC_RIGHT (ic);
9891 left = IC_LEFT (ic);
9892 result = IC_RESULT (ic);
9894 aopOp (right, ic, FALSE, FALSE);
9896 #ifdef BETTER_LITERAL_SHIFT
9897 if (AOP_TYPE (right) == AOP_LIT)
9899 if (genRightShiftLiteral (left, right, result, ic, 1))
9905 /* shift count is unknown then we have to form
9906 a loop get the loop count in B : Note: we take
9907 only the lower order byte since shifting
9908 more that 32 bits make no sense anyway, ( the
9909 largest size of an object can be only 32 bits ) */
9912 if (AOP_TYPE (right) == AOP_LIT)
9914 /* Really should be handled by genRightShiftLiteral,
9915 * but since I'm too lazy to fix that today, at least we can make
9916 * some small improvement.
9918 emitcode("mov", "b,#!constbyte",
9919 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9923 MOVB (aopGet (right, 0, FALSE, FALSE, "b"));
9924 emitcode ("inc", "b");
9926 freeAsmop (right, NULL, ic, TRUE);
9927 aopOp (left, ic, FALSE, FALSE);
9928 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9930 /* now move the left to the result if they are not the
9932 if (!sameRegs (AOP (left), AOP (result)) &&
9933 AOP_SIZE (result) > 1)
9936 size = AOP_SIZE (result);
9938 _startLazyDPSEvaluation ();
9941 l = aopGet (left, offset, FALSE, TRUE, NULL);
9942 if (*l == '@' && IS_AOP_PREG (result))
9945 emitcode ("mov", "a,%s", l);
9946 aopPut (result, "a", offset);
9949 aopPut (result, l, offset);
9952 _endLazyDPSEvaluation ();
9955 /* mov the highest order bit to OVR */
9956 tlbl = newiTempLabel (NULL);
9957 tlbl1 = newiTempLabel (NULL);
9959 size = AOP_SIZE (result);
9961 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
9962 emitcode ("rlc", "a");
9963 emitcode ("mov", "ov,c");
9964 /* if it is only one byte then */
9967 l = aopGet (left, 0, FALSE, FALSE, NULL);
9969 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9971 emitcode ("mov", "c,ov");
9972 emitcode ("rrc", "a");
9974 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9976 aopPut (result, "a", 0);
9980 reAdjustPreg (AOP (result));
9981 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9983 emitcode ("mov", "c,ov");
9984 _startLazyDPSEvaluation ();
9987 l = aopGet (result, offset, FALSE, FALSE, NULL);
9989 emitcode ("rrc", "a");
9990 aopPut (result, "a", offset--);
9992 _endLazyDPSEvaluation ();
9993 reAdjustPreg (AOP (result));
9995 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9999 freeAsmop (result, NULL, ic, TRUE);
10000 freeAsmop (left, NULL, ic, TRUE);
10003 /*-----------------------------------------------------------------*/
10004 /* genRightShift - generate code for right shifting */
10005 /*-----------------------------------------------------------------*/
10007 genRightShift (iCode * ic)
10009 operand *right, *left, *result;
10013 symbol *tlbl, *tlbl1;
10016 D (emitcode (";", "genRightShift"));
10018 /* if signed then we do it the hard way preserve the
10019 sign bit moving it inwards */
10020 letype = getSpec (operandType (IC_LEFT (ic)));
10022 if (!SPEC_USIGN (letype))
10024 genSignedRightShift (ic);
10028 /* signed & unsigned types are treated the same : i.e. the
10029 signed is NOT propagated inwards : quoting from the
10030 ANSI - standard : "for E1 >> E2, is equivalent to division
10031 by 2**E2 if unsigned or if it has a non-negative value,
10032 otherwise the result is implementation defined ", MY definition
10033 is that the sign does not get propagated */
10035 right = IC_RIGHT (ic);
10036 left = IC_LEFT (ic);
10037 result = IC_RESULT (ic);
10039 aopOp (right, ic, FALSE, FALSE);
10041 #ifdef BETTER_LITERAL_SHIFT
10042 /* if the shift count is known then do it
10043 as efficiently as possible */
10044 if (AOP_TYPE (right) == AOP_LIT)
10046 if (genRightShiftLiteral (left, right, result, ic, 0))
10053 /* shift count is unknown then we have to form
10054 a loop get the loop count in B : Note: we take
10055 only the lower order byte since shifting
10056 more that 32 bits make no sense anyway, ( the
10057 largest size of an object can be only 32 bits ) */
10059 pushedB = pushB ();
10060 if (AOP_TYPE (right) == AOP_LIT)
10062 /* Really should be handled by genRightShiftLiteral,
10063 * but since I'm too lazy to fix that today, at least we can make
10064 * some small improvement.
10066 emitcode("mov", "b,#!constbyte",
10067 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
10071 MOVB (aopGet (right, 0, FALSE, FALSE, "b"));
10072 emitcode ("inc", "b");
10074 freeAsmop (right, NULL, ic, TRUE);
10075 aopOp (left, ic, FALSE, FALSE);
10076 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
10078 /* now move the left to the result if they are not the
10080 if (!sameRegs (AOP (left), AOP (result)) &&
10081 AOP_SIZE (result) > 1)
10083 size = AOP_SIZE (result);
10085 _startLazyDPSEvaluation ();
10088 l = aopGet (left, offset, FALSE, TRUE, NULL);
10089 if (*l == '@' && IS_AOP_PREG (result))
10092 emitcode ("mov", "a,%s", l);
10093 aopPut (result, "a", offset);
10096 aopPut (result, l, offset);
10099 _endLazyDPSEvaluation ();
10102 tlbl = newiTempLabel (NULL);
10103 tlbl1 = newiTempLabel (NULL);
10104 size = AOP_SIZE (result);
10107 /* if it is only one byte then */
10110 l = aopGet (left, 0, FALSE, FALSE, NULL);
10112 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
10115 emitcode ("rrc", "a");
10117 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
10119 aopPut (result, "a", 0);
10123 reAdjustPreg (AOP (result));
10124 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
10127 _startLazyDPSEvaluation ();
10130 l = aopGet (result, offset, FALSE, FALSE, NULL);
10132 emitcode ("rrc", "a");
10133 aopPut (result, "a", offset--);
10135 _endLazyDPSEvaluation ();
10136 reAdjustPreg (AOP (result));
10139 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
10143 freeAsmop (result, NULL, ic, TRUE);
10144 freeAsmop (left, NULL, ic, TRUE);
10147 /*-----------------------------------------------------------------*/
10148 /* emitPtrByteGet - emits code to get a byte into A through a */
10149 /* pointer register (R0, R1, or DPTR). The */
10150 /* original value of A can be preserved in B. */
10151 /*-----------------------------------------------------------------*/
10153 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
10160 emitcode ("mov", "b,a");
10161 emitcode ("mov", "a,@%s", rname);
10166 emitcode ("mov", "b,a");
10167 emitcode ("movx", "a,@%s", rname);
10172 emitcode ("mov", "b,a");
10173 emitcode ("movx", "a,@dptr");
10178 emitcode ("mov", "b,a");
10179 emitcode ("clr", "a");
10180 emitcode ("movc", "a,@a+dptr");
10186 emitcode ("push", "b");
10187 emitcode ("push", "acc");
10189 emitcode ("lcall", "__gptrget");
10191 emitcode ("pop", "b");
10196 /*-----------------------------------------------------------------*/
10197 /* emitPtrByteSet - emits code to set a byte from src through a */
10198 /* pointer register (R0, R1, or DPTR). */
10199 /*-----------------------------------------------------------------*/
10201 emitPtrByteSet (char *rname, int p_type, char *src)
10210 emitcode ("mov", "@%s,a", rname);
10213 emitcode ("mov", "@%s,%s", rname, src);
10218 emitcode ("movx", "@%s,a", rname);
10223 emitcode ("movx", "@dptr,a");
10228 emitcode ("lcall", "__gptrput");
10233 /*-----------------------------------------------------------------*/
10234 /* genUnpackBits - generates code for unpacking bits */
10235 /*-----------------------------------------------------------------*/
10237 genUnpackBits (operand * result, char *rname, int ptype)
10239 int offset = 0; /* result byte offset */
10240 int rsize; /* result size */
10241 int rlen = 0; /* remaining bitfield length */
10242 sym_link *etype; /* bitfield type information */
10243 int blen; /* bitfield length */
10244 int bstr; /* bitfield starting bit within byte */
10246 D(emitcode ("; genUnpackBits",""));
10248 etype = getSpec (operandType (result));
10249 rsize = getSize (operandType (result));
10250 blen = SPEC_BLEN (etype);
10251 bstr = SPEC_BSTR (etype);
10253 /* If the bitfield length is less than a byte */
10256 emitPtrByteGet (rname, ptype, FALSE);
10258 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
10259 if (!SPEC_USIGN (etype))
10261 /* signed bitfield */
10262 symbol *tlbl = newiTempLabel (NULL);
10264 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
10265 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
10268 aopPut (result, "a", offset++);
10272 /* Bit field did not fit in a byte. Copy all
10273 but the partial byte at the end. */
10274 for (rlen=blen;rlen>=8;rlen-=8)
10276 emitPtrByteGet (rname, ptype, FALSE);
10277 aopPut (result, "a", offset++);
10279 emitcode ("inc", "%s", rname);
10282 /* Handle the partial byte at the end */
10285 emitPtrByteGet (rname, ptype, FALSE);
10286 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
10287 if (!SPEC_USIGN (etype))
10289 /* signed bitfield */
10290 symbol *tlbl = newiTempLabel (NULL);
10292 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
10293 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
10296 aopPut (result, "a", offset++);
10300 if (offset < rsize)
10304 if (SPEC_USIGN (etype))
10308 /* signed bitfield: sign extension with 0x00 or 0xff */
10309 emitcode ("rlc", "a");
10310 emitcode ("subb", "a,acc");
10316 aopPut (result, source, offset++);
10321 /*-----------------------------------------------------------------*/
10322 /* genDataPointerGet - generates code when ptr offset is known */
10323 /*-----------------------------------------------------------------*/
10325 genDataPointerGet (operand * left,
10331 int size, offset = 0;
10332 aopOp (result, ic, TRUE, FALSE);
10334 /* get the string representation of the name */
10335 l = aopGet (left, 0, FALSE, TRUE, NULL);
10336 size = AOP_SIZE (result);
10337 _startLazyDPSEvaluation ();
10342 SNPRINTF (buffer, sizeof(buffer),
10343 "(%s + %d)", l + 1, offset);
10347 SNPRINTF (buffer, sizeof(buffer),
10350 aopPut (result, buffer, offset++);
10352 _endLazyDPSEvaluation ();
10354 freeAsmop (result, NULL, ic, TRUE);
10355 freeAsmop (left, NULL, ic, TRUE);
10358 /*-----------------------------------------------------------------*/
10359 /* genNearPointerGet - emitcode for near pointer fetch */
10360 /*-----------------------------------------------------------------*/
10362 genNearPointerGet (operand * left,
10370 sym_link *rtype, *retype, *letype;
10371 sym_link *ltype = operandType (left);
10374 rtype = operandType (result);
10375 retype = getSpec (rtype);
10376 letype = getSpec (ltype);
10378 aopOp (left, ic, FALSE, FALSE);
10380 /* if left is rematerialisable and
10381 result is not bitfield variable type and
10382 the left is pointer to data space i.e
10383 lower 128 bytes of space */
10384 if (AOP_TYPE (left) == AOP_IMMD &&
10385 !IS_BITFIELD (retype) &&
10386 !IS_BITFIELD (letype) &&
10387 DCL_TYPE (ltype) == POINTER)
10389 genDataPointerGet (left, result, ic);
10393 /* if the value is already in a pointer register
10394 then don't need anything more */
10395 if (!AOP_INPREG (AOP (left)))
10397 /* otherwise get a free pointer register */
10398 aop = newAsmop (0);
10399 preg = getFreePtr (ic, &aop, FALSE);
10400 emitcode ("mov", "%s,%s",
10402 aopGet (left, 0, FALSE, TRUE, DP2_RESULT_REG));
10403 rname = preg->name;
10406 rname = aopGet (left, 0, FALSE, FALSE, DP2_RESULT_REG);
10408 freeAsmop (left, NULL, ic, TRUE);
10409 aopOp (result, ic, FALSE, FALSE);
10411 /* if bitfield then unpack the bits */
10412 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10413 genUnpackBits (result, rname, POINTER);
10416 /* we have can just get the values */
10417 int size = AOP_SIZE (result);
10422 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
10425 emitcode ("mov", "a,@%s", rname);
10426 aopPut (result, "a", offset);
10430 SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
10431 aopPut (result, buffer, offset);
10435 emitcode ("inc", "%s", rname);
10439 /* now some housekeeping stuff */
10440 if (aop) /* we had to allocate for this iCode */
10442 if (pi) { /* post increment present */
10443 aopPut (left, rname, 0);
10445 freeAsmop (NULL, aop, ic, TRUE);
10449 /* we did not allocate which means left
10450 already in a pointer register, then
10451 if size > 0 && this could be used again
10452 we have to point it back to where it
10454 if (AOP_SIZE (result) > 1 &&
10455 !OP_SYMBOL (left)->remat &&
10456 (OP_SYMBOL (left)->liveTo > ic->seq ||
10460 int size = AOP_SIZE (result) - 1;
10462 emitcode ("dec", "%s", rname);
10467 freeAsmop (result, NULL, ic, TRUE);
10468 if (pi) pi->generated = 1;
10471 /*-----------------------------------------------------------------*/
10472 /* genPagedPointerGet - emitcode for paged pointer fetch */
10473 /*-----------------------------------------------------------------*/
10475 genPagedPointerGet (operand * left,
10483 sym_link *rtype, *retype, *letype;
10485 rtype = operandType (result);
10486 retype = getSpec (rtype);
10487 letype = getSpec (operandType (left));
10488 aopOp (left, ic, FALSE, FALSE);
10490 /* if the value is already in a pointer register
10491 then don't need anything more */
10492 if (!AOP_INPREG (AOP (left)))
10494 /* otherwise get a free pointer register */
10495 aop = newAsmop (0);
10496 preg = getFreePtr (ic, &aop, FALSE);
10497 emitcode ("mov", "%s,%s",
10499 aopGet (left, 0, FALSE, TRUE, NULL));
10500 rname = preg->name;
10503 rname = aopGet (left, 0, FALSE, FALSE, NULL);
10505 freeAsmop (left, NULL, ic, TRUE);
10506 aopOp (result, ic, FALSE, FALSE);
10508 /* if bitfield then unpack the bits */
10509 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10510 genUnpackBits (result, rname, PPOINTER);
10513 /* we have can just get the values */
10514 int size = AOP_SIZE (result);
10520 emitcode ("movx", "a,@%s", rname);
10521 aopPut (result, "a", offset);
10526 emitcode ("inc", "%s", rname);
10530 /* now some housekeeping stuff */
10531 if (aop) /* we had to allocate for this iCode */
10534 aopPut (left, rname, 0);
10535 freeAsmop (NULL, aop, ic, TRUE);
10539 /* we did not allocate which means left
10540 already in a pointer register, then
10541 if size > 0 && this could be used again
10542 we have to point it back to where it
10544 if (AOP_SIZE (result) > 1 &&
10545 !OP_SYMBOL (left)->remat &&
10546 (OP_SYMBOL (left)->liveTo > ic->seq ||
10550 int size = AOP_SIZE (result) - 1;
10552 emitcode ("dec", "%s", rname);
10557 freeAsmop (result, NULL, ic, TRUE);
10558 if (pi) pi->generated = 1;
10561 /*-----------------------------------------------------------------*/
10562 /* genFarPointerGet - get value from far space */
10563 /*-----------------------------------------------------------------*/
10565 genFarPointerGet (operand * left,
10566 operand * result, iCode * ic, iCode *pi)
10568 int size, offset, dopi=1;
10569 sym_link *retype = getSpec (operandType (result));
10570 sym_link *letype = getSpec (operandType (left));
10571 D (emitcode (";", "genFarPointerGet"););
10573 aopOp (left, ic, FALSE, FALSE);
10575 /* if the operand is already in dptr
10576 then we do nothing else we move the value to dptr */
10577 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
10579 /* if this is rematerializable */
10580 if (AOP_TYPE (left) == AOP_IMMD)
10582 emitcode ("mov", "dptr,%s", aopGet (left, 0, TRUE, FALSE, NULL));
10586 /* we need to get it byte by byte */
10587 _startLazyDPSEvaluation ();
10588 if (AOP_TYPE (left) != AOP_DPTR)
10590 emitcode ("mov", "dpl,%s", aopGet (left, 0, FALSE, FALSE, NULL));
10591 emitcode ("mov", "dph,%s", aopGet (left, 1, FALSE, FALSE, NULL));
10592 if (options.model == MODEL_FLAT24)
10593 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10597 /* We need to generate a load to DPTR indirect through DPTR. */
10598 D (emitcode (";", "genFarPointerGet -- indirection special case."););
10599 emitcode ("push", "%s", aopGet (left, 0, FALSE, TRUE, NULL));
10600 emitcode ("push", "%s", aopGet (left, 1, FALSE, TRUE, NULL));
10601 if (options.model == MODEL_FLAT24)
10602 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10603 emitcode ("pop", "dph");
10604 emitcode ("pop", "dpl");
10607 _endLazyDPSEvaluation ();
10610 /* so dptr now contains the address */
10611 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10613 /* if bit then unpack */
10614 if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
10615 if (AOP_INDPTRn(left)) {
10616 genSetDPTR(AOP(left)->aopu.dptr);
10618 genUnpackBits (result, "dptr", FPOINTER);
10619 if (AOP_INDPTRn(left)) {
10624 size = AOP_SIZE (result);
10627 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10629 genSetDPTR(AOP(left)->aopu.dptr);
10630 emitcode ("movx", "a,@dptr");
10631 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10632 emitcode ("inc", "dptr");
10634 aopPut (result, "a", offset++);
10637 _startLazyDPSEvaluation ();
10639 if (AOP_INDPTRn(left)) {
10640 genSetDPTR(AOP(left)->aopu.dptr);
10646 emitcode ("movx", "a,@dptr");
10647 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10648 emitcode ("inc", "dptr");
10650 aopPut (result, "a", offset++);
10652 _endLazyDPSEvaluation ();
10655 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10656 if (!AOP_INDPTRn(left)) {
10657 _startLazyDPSEvaluation ();
10658 aopPut (left, "dpl", 0);
10659 aopPut (left, "dph", 1);
10660 if (options.model == MODEL_FLAT24)
10661 aopPut (left, "dpx", 2);
10662 _endLazyDPSEvaluation ();
10665 } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) &&
10666 AOP_SIZE(result) > 1 &&
10668 (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
10670 size = AOP_SIZE (result) - 1;
10671 if (AOP_INDPTRn(left)) {
10672 genSetDPTR(AOP(left)->aopu.dptr);
10674 while (size--) emitcode ("lcall","__decdptr");
10675 if (AOP_INDPTRn(left)) {
10680 freeAsmop (result, NULL, ic, TRUE);
10681 freeAsmop (left, NULL, ic, TRUE);
10684 /*-----------------------------------------------------------------*/
10685 /* genCodePointerGet - get value from code space */
10686 /*-----------------------------------------------------------------*/
10688 genCodePointerGet (operand * left,
10689 operand * result, iCode * ic, iCode *pi)
10691 int size, offset, dopi=1;
10692 sym_link *retype = getSpec (operandType (result));
10694 aopOp (left, ic, FALSE, FALSE);
10696 /* if the operand is already in dptr
10697 then we do nothing else we move the value to dptr */
10698 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
10700 /* if this is rematerializable */
10701 if (AOP_TYPE (left) == AOP_IMMD)
10703 emitcode ("mov", "dptr,%s", aopGet (left, 0, TRUE, FALSE, NULL));
10706 { /* we need to get it byte by byte */
10707 _startLazyDPSEvaluation ();
10708 if (AOP_TYPE (left) != AOP_DPTR)
10710 emitcode ("mov", "dpl,%s", aopGet (left, 0, FALSE, FALSE, NULL));
10711 emitcode ("mov", "dph,%s", aopGet (left, 1, FALSE, FALSE, NULL));
10712 if (options.model == MODEL_FLAT24)
10713 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10717 /* We need to generate a load to DPTR indirect through DPTR. */
10718 D (emitcode (";", "gencodePointerGet -- indirection special case."););
10719 emitcode ("push", "%s", aopGet (left, 0, FALSE, TRUE, NULL));
10720 emitcode ("push", "%s", aopGet (left, 1, FALSE, TRUE, NULL));
10721 if (options.model == MODEL_FLAT24)
10722 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10723 emitcode ("pop", "dph");
10724 emitcode ("pop", "dpl");
10727 _endLazyDPSEvaluation ();
10730 /* so dptr now contains the address */
10731 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10733 /* if bit then unpack */
10734 if (IS_BITFIELD (retype)) {
10735 if (AOP_INDPTRn(left)) {
10736 genSetDPTR(AOP(left)->aopu.dptr);
10738 genUnpackBits (result, "dptr", CPOINTER);
10739 if (AOP_INDPTRn(left)) {
10744 size = AOP_SIZE (result);
10746 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10748 genSetDPTR(AOP(left)->aopu.dptr);
10749 emitcode ("clr", "a");
10750 emitcode ("movc", "a,@a+dptr");
10751 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10752 emitcode ("inc", "dptr");
10754 aopPut (result, "a", offset++);
10757 _startLazyDPSEvaluation ();
10760 if (AOP_INDPTRn(left)) {
10761 genSetDPTR(AOP(left)->aopu.dptr);
10767 emitcode ("clr", "a");
10768 emitcode ("movc", "a,@a+dptr");
10769 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10770 emitcode ("inc", "dptr");
10771 aopPut (result, "a", offset++);
10773 _endLazyDPSEvaluation ();
10776 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10777 if (!AOP_INDPTRn(left)) {
10778 _startLazyDPSEvaluation ();
10780 aopPut (left, "dpl", 0);
10781 aopPut (left, "dph", 1);
10782 if (options.model == MODEL_FLAT24)
10783 aopPut (left, "dpx", 2);
10785 _endLazyDPSEvaluation ();
10788 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
10789 AOP_SIZE(result) > 1 &&
10790 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10792 size = AOP_SIZE (result) - 1;
10793 if (AOP_INDPTRn(left)) {
10794 genSetDPTR(AOP(left)->aopu.dptr);
10796 while (size--) emitcode ("lcall","__decdptr");
10797 if (AOP_INDPTRn(left)) {
10802 freeAsmop (result, NULL, ic, TRUE);
10803 freeAsmop (left, NULL, ic, TRUE);
10806 /*-----------------------------------------------------------------*/
10807 /* genGenPointerGet - get value from generic pointer space */
10808 /*-----------------------------------------------------------------*/
10810 genGenPointerGet (operand * left,
10811 operand * result, iCode * ic, iCode * pi)
10815 sym_link *retype = getSpec (operandType (result));
10816 sym_link *letype = getSpec (operandType (left));
10818 D (emitcode (";", "genGenPointerGet"));
10820 aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
10822 pushedB = pushB ();
10823 /* if the operand is already in dptr
10824 then we do nothing else we move the value to dptr */
10825 if (AOP_TYPE (left) != AOP_STR)
10827 /* if this is rematerializable */
10828 if (AOP_TYPE (left) == AOP_IMMD)
10830 emitcode ("mov", "dptr,%s", aopGet (left, 0, TRUE, FALSE, NULL));
10831 if (AOP(left)->aopu.aop_immd.from_cast_remat)
10833 MOVB (aopGet (left, AOP_SIZE(left)-1, FALSE, FALSE, NULL));
10837 emitcode ("mov", "b,#%d", pointerCode (retype));
10841 { /* we need to get it byte by byte */
10842 _startLazyDPSEvaluation ();
10843 emitcode ("mov", "dpl,%s", aopGet (left,0,FALSE,FALSE,NULL));
10844 emitcode ("mov", "dph,%s", aopGet (left,1,FALSE,FALSE,NULL));
10845 if (options.model == MODEL_FLAT24) {
10846 emitcode ("mov", "dpx,%s", aopGet (left,2,FALSE,FALSE,NULL));
10847 emitcode ("mov", "b,%s", aopGet (left,3,FALSE,FALSE,NULL));
10849 emitcode ("mov", "b,%s", aopGet (left,2,FALSE,FALSE,NULL));
10851 _endLazyDPSEvaluation ();
10855 /* so dptr-b now contains the address */
10856 aopOp (result, ic, FALSE, TRUE);
10858 /* if bit then unpack */
10859 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10861 genUnpackBits (result, "dptr", GPOINTER);
10865 size = AOP_SIZE (result);
10872 // Get two bytes at a time, results in _AP & A.
10873 // dptr will be incremented ONCE by __gptrgetWord.
10875 // Note: any change here must be coordinated
10876 // with the implementation of __gptrgetWord
10877 // in device/lib/_gptrget.c
10878 emitcode ("lcall", "__gptrgetWord");
10879 aopPut (result, DP2_RESULT_REG, offset++);
10880 aopPut (result, "a", offset++);
10885 // Only one byte to get.
10886 emitcode ("lcall", "__gptrget");
10887 aopPut (result, "a", offset++);
10890 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
10892 emitcode ("inc", "dptr");
10897 if (pi && AOP_TYPE (left) != AOP_IMMD) {
10898 _startLazyDPSEvaluation ();
10900 aopPut (left, "dpl", 0);
10901 aopPut (left, "dph", 1);
10902 if (options.model == MODEL_FLAT24) {
10903 aopPut (left, "dpx", 2);
10904 aopPut (left, "b", 3);
10905 } else aopPut (left, "b", 2);
10907 _endLazyDPSEvaluation ();
10910 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
10911 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10913 size = AOP_SIZE (result) - 1;
10914 while (size--) emitcode ("lcall","__decdptr");
10918 freeAsmop (result, NULL, ic, TRUE);
10919 freeAsmop (left, NULL, ic, TRUE);
10922 /*-----------------------------------------------------------------*/
10923 /* genPointerGet - generate code for pointer get */
10924 /*-----------------------------------------------------------------*/
10926 genPointerGet (iCode * ic, iCode *pi)
10928 operand *left, *result;
10929 sym_link *type, *etype;
10932 D (emitcode (";", "genPointerGet"));
10934 left = IC_LEFT (ic);
10935 result = IC_RESULT (ic);
10937 /* depending on the type of pointer we need to
10938 move it to the correct pointer register */
10939 type = operandType (left);
10940 etype = getSpec (type);
10941 /* if left is of type of pointer then it is simple */
10942 if (IS_PTR (type) && !IS_FUNC (type->next))
10943 p_type = DCL_TYPE (type);
10946 /* we have to go by the storage class */
10947 p_type = PTR_TYPE (SPEC_OCLS (etype));
10950 /* special case when cast remat */
10951 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10952 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10954 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10955 type = operandType (left);
10956 p_type = DCL_TYPE (type);
10958 /* now that we have the pointer type we assign
10959 the pointer values */
10965 genNearPointerGet (left, result, ic, pi);
10969 genPagedPointerGet (left, result, ic, pi);
10973 genFarPointerGet (left, result, ic, pi);
10977 genCodePointerGet (left, result, ic, pi);
10981 genGenPointerGet (left, result, ic, pi);
10987 /*-----------------------------------------------------------------*/
10988 /* genPackBits - generates code for packed bit storage */
10989 /*-----------------------------------------------------------------*/
10991 genPackBits (sym_link * etype,
10993 char *rname, int p_type)
10995 int offset = 0; /* source byte offset */
10996 int rlen = 0; /* remaining bitfield length */
10997 int blen; /* bitfield length */
10998 int bstr; /* bitfield starting bit within byte */
10999 int litval; /* source literal value (if AOP_LIT) */
11000 unsigned char mask; /* bitmask within current byte */
11002 D(emitcode ("; genPackBits",""));
11004 blen = SPEC_BLEN (etype);
11005 bstr = SPEC_BSTR (etype);
11007 /* If the bitfield length is less than a byte */
11010 mask = ((unsigned char) (0xFF << (blen + bstr)) |
11011 (unsigned char) (0xFF >> (8 - bstr)));
11013 if (AOP_TYPE (right) == AOP_LIT)
11015 /* Case with a bitfield length <8 and literal source
11017 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
11019 litval &= (~mask) & 0xff;
11020 emitPtrByteGet (rname, p_type, FALSE);
11021 if ((mask|litval)!=0xff)
11022 emitcode ("anl","a,#!constbyte", mask);
11024 emitcode ("orl","a,#!constbyte", litval);
11028 if ((blen==1) && (p_type!=GPOINTER))
11030 /* Case with a bitfield length == 1 and no generic pointer
11032 if (AOP_TYPE (right) == AOP_CRY)
11033 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
11036 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
11037 emitcode ("rrc","a");
11039 emitPtrByteGet (rname, p_type, FALSE);
11040 emitcode ("mov","acc.%d,c",bstr);
11045 /* Case with a bitfield length < 8 and arbitrary source
11047 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
11048 /* shift and mask source value */
11050 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
11052 pushedB = pushB ();
11053 /* transfer A to B and get next byte */
11054 emitPtrByteGet (rname, p_type, TRUE);
11056 emitcode ("anl", "a,#!constbyte", mask);
11057 emitcode ("orl", "a,b");
11058 if (p_type == GPOINTER)
11059 emitcode ("pop", "b");
11065 emitPtrByteSet (rname, p_type, "a");
11069 /* Bit length is greater than 7 bits. In this case, copy */
11070 /* all except the partial byte at the end */
11071 for (rlen=blen;rlen>=8;rlen-=8)
11073 emitPtrByteSet (rname, p_type,
11074 aopGet (right, offset++, FALSE, TRUE, NULL) );
11076 emitcode ("inc", "%s", rname);
11079 /* If there was a partial byte at the end */
11082 mask = (((unsigned char) -1 << rlen) & 0xff);
11084 if (AOP_TYPE (right) == AOP_LIT)
11086 /* Case with partial byte and literal source
11088 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
11089 litval >>= (blen-rlen);
11090 litval &= (~mask) & 0xff;
11091 emitPtrByteGet (rname, p_type, FALSE);
11092 if ((mask|litval)!=0xff)
11093 emitcode ("anl","a,#!constbyte", mask);
11095 emitcode ("orl","a,#!constbyte", litval);
11100 /* Case with partial byte and arbitrary source
11102 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11103 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
11105 pushedB = pushB ();
11106 /* transfer A to B and get next byte */
11107 emitPtrByteGet (rname, p_type, TRUE);
11109 emitcode ("anl", "a,#!constbyte", mask);
11110 emitcode ("orl", "a,b");
11111 if (p_type == GPOINTER)
11112 emitcode ("pop", "b");
11116 emitPtrByteSet (rname, p_type, "a");
11121 /*-----------------------------------------------------------------*/
11122 /* genDataPointerSet - remat pointer to data space */
11123 /*-----------------------------------------------------------------*/
11125 genDataPointerSet (operand * right,
11129 int size, offset = 0;
11130 char *l, buffer[256];
11132 D (emitcode (";", "genDataPointerSet"));
11134 aopOp (right, ic, FALSE, FALSE);
11136 l = aopGet (result, 0, FALSE, TRUE, NULL);
11137 size = AOP_SIZE (right);
11141 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l + 1, offset);
11143 SNPRINTF (buffer, sizeof(buffer), "%s", l + 1);
11144 emitcode ("mov", "%s,%s", buffer,
11145 aopGet (right, offset++, FALSE, FALSE, NULL));
11148 freeAsmop (result, NULL, ic, TRUE);
11149 freeAsmop (right, NULL, ic, TRUE);
11152 /*-----------------------------------------------------------------*/
11153 /* genNearPointerSet - emitcode for near pointer put */
11154 /*-----------------------------------------------------------------*/
11156 genNearPointerSet (operand * right,
11163 sym_link *retype, *letype;
11164 sym_link *ptype = operandType (result);
11166 D (emitcode (";", "genNearPointerSet"));
11168 retype = getSpec (operandType (right));
11169 letype = getSpec (ptype);
11171 aopOp (result, ic, FALSE, FALSE);
11173 /* if the result is rematerializable &
11174 in data space & not a bit variable */
11175 if (AOP_TYPE (result) == AOP_IMMD &&
11176 DCL_TYPE (ptype) == POINTER &&
11177 !IS_BITVAR (retype) &&
11178 !IS_BITVAR (letype))
11180 genDataPointerSet (right, result, ic);
11184 /* if the value is already in a pointer register
11185 then don't need anything more */
11186 if (!AOP_INPREG (AOP (result)))
11188 /* otherwise get a free pointer register */
11191 aop = newAsmop (0);
11192 preg = getFreePtr (ic, &aop, FALSE);
11193 emitcode ("mov", "%s,%s",
11195 aopGet (result, 0, FALSE, TRUE, NULL));
11196 rname = preg->name;
11200 rname = aopGet (result, 0, FALSE, FALSE, NULL);
11203 aopOp (right, ic, FALSE, FALSE);
11205 /* if bitfield then unpack the bits */
11206 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11207 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
11210 /* we can just get the values */
11211 int size = AOP_SIZE (right);
11216 l = aopGet (right, offset, FALSE, TRUE, NULL);
11217 if ((*l == '@') || (strcmp (l, "acc") == 0))
11220 emitcode ("mov", "@%s,a", rname);
11223 emitcode ("mov", "@%s,%s", rname, l);
11225 emitcode ("inc", "%s", rname);
11230 /* now some housekeeping stuff */
11231 if (aop) /* we had to allocate for this iCode */
11234 aopPut (result, rname, 0);
11235 freeAsmop (NULL, aop, ic, TRUE);
11239 /* we did not allocate which means left
11240 already in a pointer register, then
11241 if size > 0 && this could be used again
11242 we have to point it back to where it
11244 if (AOP_SIZE (right) > 1 &&
11245 !OP_SYMBOL (result)->remat &&
11246 (OP_SYMBOL (result)->liveTo > ic->seq ||
11250 int size = AOP_SIZE (right) - 1;
11252 emitcode ("dec", "%s", rname);
11257 if (pi) pi->generated = 1;
11258 freeAsmop (result, NULL, ic, TRUE);
11259 freeAsmop (right, NULL, ic, TRUE);
11262 /*-----------------------------------------------------------------*/
11263 /* genPagedPointerSet - emitcode for Paged pointer put */
11264 /*-----------------------------------------------------------------*/
11266 genPagedPointerSet (operand * right,
11273 sym_link *retype, *letype;
11275 D (emitcode (";", "genPagedPointerSet"));
11277 retype = getSpec (operandType (right));
11278 letype = getSpec (operandType (result));
11280 aopOp (result, ic, FALSE, FALSE);
11282 /* if the value is already in a pointer register
11283 then don't need anything more */
11284 if (!AOP_INPREG (AOP (result)))
11286 /* otherwise get a free pointer register */
11289 aop = newAsmop (0);
11290 preg = getFreePtr (ic, &aop, FALSE);
11291 emitcode ("mov", "%s,%s",
11293 aopGet (result, 0, FALSE, TRUE, NULL));
11294 rname = preg->name;
11297 rname = aopGet (result, 0, FALSE, FALSE, NULL);
11299 aopOp (right, ic, FALSE, FALSE);
11301 /* if bitfield then unpack the bits */
11302 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11303 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
11306 /* we have can just get the values */
11307 int size = AOP_SIZE (right);
11312 l = aopGet (right, offset, FALSE, TRUE, NULL);
11314 emitcode ("movx", "@%s,a", rname);
11317 emitcode ("inc", "%s", rname);
11323 /* now some housekeeping stuff */
11327 aopPut (result, rname, 0);
11328 /* we had to allocate for this iCode */
11329 freeAsmop (NULL, aop, ic, TRUE);
11333 /* we did not allocate which means left
11334 already in a pointer register, then
11335 if size > 0 && this could be used again
11336 we have to point it back to where it
11338 if (AOP_SIZE (right) > 1 &&
11339 !OP_SYMBOL (result)->remat &&
11340 (OP_SYMBOL (result)->liveTo > ic->seq ||
11344 int size = AOP_SIZE (right) - 1;
11346 emitcode ("dec", "%s", rname);
11351 if (pi) pi->generated = 1;
11352 freeAsmop (result, NULL, ic, TRUE);
11353 freeAsmop (right, NULL, ic, TRUE);
11356 /*-----------------------------------------------------------------*/
11357 /* genFarPointerSet - set value from far space */
11358 /*-----------------------------------------------------------------*/
11360 genFarPointerSet (operand * right,
11361 operand * result, iCode * ic, iCode *pi)
11363 int size, offset, dopi=1;
11364 sym_link *retype = getSpec (operandType (right));
11365 sym_link *letype = getSpec (operandType (result));
11367 aopOp (result, ic, FALSE, FALSE);
11369 /* if the operand is already in dptr
11370 then we do nothing else we move the value to dptr */
11371 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
11373 /* if this is remateriazable */
11374 if (AOP_TYPE (result) == AOP_IMMD)
11375 emitcode ("mov", "dptr,%s",
11376 aopGet (result, 0, TRUE, FALSE, NULL));
11379 /* we need to get it byte by byte */
11380 _startLazyDPSEvaluation ();
11381 if (AOP_TYPE (result) != AOP_DPTR)
11383 emitcode ("mov", "dpl,%s", aopGet (result, 0, FALSE, FALSE, NULL));
11384 emitcode ("mov", "dph,%s", aopGet (result, 1, FALSE, FALSE, NULL));
11385 if (options.model == MODEL_FLAT24)
11386 emitcode ("mov", "dpx,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11390 /* We need to generate a load to DPTR indirect through DPTR. */
11391 D (emitcode (";", "genFarPointerSet -- indirection special case."););
11393 emitcode ("push", "%s", aopGet (result, 0, FALSE, TRUE, NULL));
11394 emitcode ("push", "%s", aopGet (result, 1, FALSE, TRUE, NULL));
11395 if (options.model == MODEL_FLAT24)
11396 emitcode ("mov", "dpx,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11397 emitcode ("pop", "dph");
11398 emitcode ("pop", "dpl");
11401 _endLazyDPSEvaluation ();
11404 /* so dptr now contains the address */
11405 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
11407 /* if bit then unpack */
11408 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11410 if (AOP_INDPTRn(result)) {
11411 genSetDPTR(AOP(result)->aopu.dptr);
11413 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
11414 if (AOP_INDPTRn(result)) {
11418 size = AOP_SIZE (right);
11420 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
11422 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11424 genSetDPTR(AOP(result)->aopu.dptr);
11425 emitcode ("movx", "@dptr,a");
11426 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
11427 emitcode ("inc", "dptr");
11431 _startLazyDPSEvaluation ();
11433 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11435 if (AOP_INDPTRn(result)) {
11436 genSetDPTR(AOP(result)->aopu.dptr);
11442 emitcode ("movx", "@dptr,a");
11443 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
11444 emitcode ("inc", "dptr");
11446 _endLazyDPSEvaluation ();
11450 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
11451 if (!AOP_INDPTRn(result)) {
11452 _startLazyDPSEvaluation ();
11454 aopPut (result,"dpl",0);
11455 aopPut (result,"dph",1);
11456 if (options.model == MODEL_FLAT24)
11457 aopPut (result,"dpx",2);
11459 _endLazyDPSEvaluation ();
11462 } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
11463 AOP_SIZE(right) > 1 &&
11464 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
11466 size = AOP_SIZE (right) - 1;
11467 if (AOP_INDPTRn(result)) {
11468 genSetDPTR(AOP(result)->aopu.dptr);
11470 while (size--) emitcode ("lcall","__decdptr");
11471 if (AOP_INDPTRn(result)) {
11475 freeAsmop (result, NULL, ic, TRUE);
11476 freeAsmop (right, NULL, ic, TRUE);
11479 /*-----------------------------------------------------------------*/
11480 /* genGenPointerSet - set value from generic pointer space */
11481 /*-----------------------------------------------------------------*/
11483 genGenPointerSet (operand * right,
11484 operand * result, iCode * ic, iCode *pi)
11488 sym_link *retype = getSpec (operandType (right));
11489 sym_link *letype = getSpec (operandType (result));
11491 aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
11493 pushedB = pushB ();
11494 /* if the operand is already in dptr
11495 then we do nothing else we move the value to dptr */
11496 if (AOP_TYPE (result) != AOP_STR)
11498 _startLazyDPSEvaluation ();
11499 /* if this is remateriazable */
11500 if (AOP_TYPE (result) == AOP_IMMD)
11502 emitcode ("mov", "dptr,%s", aopGet (result, 0, TRUE, FALSE, NULL));
11503 if (AOP(result)->aopu.aop_immd.from_cast_remat)
11505 MOVB (aopGet (result, AOP_SIZE(result)-1, FALSE, FALSE, NULL));
11510 "b,%s + 1", aopGet (result, 0, TRUE, FALSE, NULL));
11514 { /* we need to get it byte by byte */
11515 emitcode ("mov", "dpl,%s", aopGet (result, 0, FALSE, FALSE, NULL));
11516 emitcode ("mov", "dph,%s", aopGet (result, 1, FALSE, FALSE, NULL));
11517 if (options.model == MODEL_FLAT24) {
11518 emitcode ("mov", "dpx,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11519 emitcode ("mov", "b,%s", aopGet (result, 3, FALSE, FALSE, NULL));
11521 emitcode ("mov", "b,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11524 _endLazyDPSEvaluation ();
11526 /* so dptr + b now contains the address */
11527 aopOp (right, ic, FALSE, TRUE);
11529 /* if bit then unpack */
11530 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11532 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
11536 size = AOP_SIZE (right);
11539 _startLazyDPSEvaluation ();
11544 // Set two bytes at a time, passed in _AP & A.
11545 // dptr will be incremented ONCE by __gptrputWord.
11547 // Note: any change here must be coordinated
11548 // with the implementation of __gptrputWord
11549 // in device/lib/_gptrput.c
11550 emitcode("mov", "_ap, %s",
11551 aopGet (right, offset++, FALSE, FALSE, NULL));
11552 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11556 emitcode ("lcall", "__gptrputWord");
11561 // Only one byte to put.
11562 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11566 emitcode ("lcall", "__gptrput");
11569 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
11571 emitcode ("inc", "dptr");
11574 _endLazyDPSEvaluation ();
11577 if (pi && AOP_TYPE (result) != AOP_IMMD) {
11578 _startLazyDPSEvaluation ();
11580 aopPut (result, "dpl",0);
11581 aopPut (result, "dph",1);
11582 if (options.model == MODEL_FLAT24) {
11583 aopPut (result, "dpx",2);
11584 aopPut (result, "b",3);
11586 aopPut (result, "b",2);
11588 _endLazyDPSEvaluation ();
11591 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
11592 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
11594 size = AOP_SIZE (right) - 1;
11595 while (size--) emitcode ("lcall","__decdptr");
11599 freeAsmop (result, NULL, ic, TRUE);
11600 freeAsmop (right, NULL, ic, TRUE);
11603 /*-----------------------------------------------------------------*/
11604 /* genPointerSet - stores the value into a pointer location */
11605 /*-----------------------------------------------------------------*/
11607 genPointerSet (iCode * ic, iCode *pi)
11609 operand *right, *result;
11610 sym_link *type, *etype;
11613 D (emitcode (";", "genPointerSet"));
11615 right = IC_RIGHT (ic);
11616 result = IC_RESULT (ic);
11618 /* depending on the type of pointer we need to
11619 move it to the correct pointer register */
11620 type = operandType (result);
11621 etype = getSpec (type);
11622 /* if left is of type of pointer then it is simple */
11623 if (IS_PTR (type) && !IS_FUNC (type->next))
11625 p_type = DCL_TYPE (type);
11629 /* we have to go by the storage class */
11630 p_type = PTR_TYPE (SPEC_OCLS (etype));
11633 /* special case when cast remat */
11634 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
11635 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
11636 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
11637 type = operandType (result);
11638 p_type = DCL_TYPE (type);
11641 /* now that we have the pointer type we assign
11642 the pointer values */
11648 genNearPointerSet (right, result, ic, pi);
11652 genPagedPointerSet (right, result, ic, pi);
11656 genFarPointerSet (right, result, ic, pi);
11660 genGenPointerSet (right, result, ic, pi);
11664 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11665 "genPointerSet: illegal pointer type");
11669 /*-----------------------------------------------------------------*/
11670 /* genIfx - generate code for Ifx statement */
11671 /*-----------------------------------------------------------------*/
11673 genIfx (iCode * ic, iCode * popIc)
11675 operand *cond = IC_COND (ic);
11679 D (emitcode (";", "genIfx"));
11681 aopOp (cond, ic, FALSE, FALSE);
11683 /* get the value into acc */
11684 if (AOP_TYPE (cond) != AOP_CRY)
11691 if (AOP(cond)->aopu.aop_dir)
11692 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
11695 /* the result is now in the accumulator or a directly addressable bit */
11696 freeAsmop (cond, NULL, ic, TRUE);
11698 /* if there was something to be popped then do it */
11702 /* if the condition is a bit variable */
11704 genIfxJump (ic, dup);
11705 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
11706 genIfxJump (ic, SPIL_LOC (cond)->rname);
11707 else if (isbit && !IS_ITEMP (cond))
11708 genIfxJump (ic, OP_SYMBOL (cond)->rname);
11710 genIfxJump (ic, "a");
11715 /*-----------------------------------------------------------------*/
11716 /* genAddrOf - generates code for address of */
11717 /*-----------------------------------------------------------------*/
11719 genAddrOf (iCode * ic)
11721 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
11724 D (emitcode (";", "genAddrOf"));
11726 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11728 /* if the operand is on the stack then we
11729 need to get the stack offset of this
11734 /* if 10 bit stack */
11735 if (options.stack10bit) {
11739 tsprintf(buff, sizeof(buff),
11740 "#!constbyte",(options.stack_loc >> 16) & 0xff);
11741 /* if it has an offset then we need to compute it */
11742 /* emitcode ("subb", "a,#!constbyte", */
11743 /* -((sym->stack < 0) ? */
11744 /* ((short) (sym->stack - _G.nRegsSaved)) : */
11745 /* ((short) sym->stack)) & 0xff); */
11746 /* emitcode ("mov","b,a"); */
11747 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
11748 /* ((short) (sym->stack - _G.nRegsSaved)) : */
11749 /* ((short) sym->stack)) >> 8) & 0xff); */
11751 emitcode ("mov", "a,_bpx");
11752 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
11753 ((char) (sym->stack - _G.nRegsSaved)) :
11754 ((char) sym->stack )) & 0xff);
11755 emitcode ("mov", "b,a");
11756 emitcode ("mov", "a,_bpx+1");
11758 offset = (((sym->stack < 0) ?
11759 ((short) (sym->stack - _G.nRegsSaved)) :
11760 ((short) sym->stack )) >> 8) & 0xff;
11762 emitcode ("addc","a,#!constbyte", offset);
11764 aopPut (IC_RESULT (ic), "b", 0);
11765 aopPut (IC_RESULT (ic), "a", 1);
11766 aopPut (IC_RESULT (ic), buff, 2);
11768 /* we can just move _bp */
11769 aopPut (IC_RESULT (ic), "_bpx", 0);
11770 aopPut (IC_RESULT (ic), "_bpx+1", 1);
11771 aopPut (IC_RESULT (ic), buff, 2);
11774 /* if it has an offset then we need to compute it */
11777 emitcode ("mov", "a,_bp");
11778 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
11779 aopPut (IC_RESULT (ic), "a", 0);
11783 /* we can just move _bp */
11784 aopPut (IC_RESULT (ic), "_bp", 0);
11786 /* fill the result with zero */
11787 size = AOP_SIZE (IC_RESULT (ic)) - 1;
11790 if (options.stack10bit && size < (FPTRSIZE - 1)) {
11792 "*** warning: pointer to stack var truncated.\n");
11798 aopPut (IC_RESULT (ic), zero, offset++);
11804 /* object not on stack then we need the name */
11805 size = AOP_SIZE (IC_RESULT (ic));
11810 char s[SDCC_NAME_MAX];
11814 tsprintf(s, sizeof(s), "#!his",sym->rname);
11817 tsprintf(s, sizeof(s), "#!hihis",sym->rname);
11820 tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
11822 default: /* should not need this (just in case) */
11823 SNPRINTF (s, sizeof(s), "#(%s >> %d)",
11830 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11833 aopPut (IC_RESULT (ic), s, offset++);
11837 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11841 #if 0 // obsolete, and buggy for != xdata
11842 /*-----------------------------------------------------------------*/
11843 /* genArrayInit - generates code for address of */
11844 /*-----------------------------------------------------------------*/
11846 genArrayInit (iCode * ic)
11848 literalList *iLoop;
11850 int elementSize = 0, eIndex;
11851 unsigned val, lastVal;
11853 operand *left=IC_LEFT(ic);
11855 D (emitcode (";", "genArrayInit"));
11857 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
11859 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
11861 // Load immediate value into DPTR.
11862 emitcode("mov", "dptr, %s",
11863 aopGet (IC_LEFT(ic), 0, TRUE, FALSE, NULL));
11865 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
11868 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11869 "Unexpected operand to genArrayInit.\n");
11872 // a regression because of SDCCcse.c:1.52
11873 emitcode ("mov", "dpl,%s", aopGet (left, 0, FALSE, FALSE, NULL));
11874 emitcode ("mov", "dph,%s", aopGet (left, 1, FALSE, FALSE, NULL));
11875 if (options.model == MODEL_FLAT24)
11876 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
11880 type = operandType(IC_LEFT(ic));
11882 if (type && type->next)
11884 elementSize = getSize(type->next);
11888 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11889 "can't determine element size in genArrayInit.\n");
11893 iLoop = IC_ARRAYILIST(ic);
11898 bool firstpass = TRUE;
11900 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
11901 iLoop->count, (int)iLoop->literalValue, elementSize);
11907 symbol *tlbl = NULL;
11909 count = ix > 256 ? 256 : ix;
11913 tlbl = newiTempLabel (NULL);
11914 if (firstpass || (count & 0xff))
11916 emitcode("mov", "b, #!constbyte", count & 0xff);
11924 for (eIndex = 0; eIndex < elementSize; eIndex++)
11926 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
11927 if (val != lastVal)
11929 emitcode("mov", "a, #!constbyte", val);
11933 emitcode("movx", "@dptr, a");
11934 emitcode("inc", "dptr");
11939 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
11945 iLoop = iLoop->next;
11948 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
11952 /*-----------------------------------------------------------------*/
11953 /* genFarFarAssign - assignment when both are in far space */
11954 /*-----------------------------------------------------------------*/
11956 genFarFarAssign (operand * result, operand * right, iCode * ic)
11958 int size = AOP_SIZE (right);
11960 symbol *rSym = NULL;
11964 /* quick & easy case. */
11965 D (emitcode(";","genFarFarAssign (1 byte case)"));
11966 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
11967 freeAsmop (right, NULL, ic, FALSE);
11968 /* now assign DPTR to result */
11970 aopOp(result, ic, FALSE, FALSE);
11972 aopPut (result, "a", 0);
11973 freeAsmop(result, NULL, ic, FALSE);
11977 /* See if we've got an underlying symbol to abuse. */
11978 if (IS_SYMOP(result) && OP_SYMBOL(result))
11980 if (IS_TRUE_SYMOP(result))
11982 rSym = OP_SYMBOL(result);
11984 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
11986 rSym = OP_SYMBOL(result)->usl.spillLoc;
11990 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
11992 /* We can use the '390 auto-toggle feature to good effect here. */
11994 D (emitcode(";", "genFarFarAssign (390 auto-toggle fun)"));
11995 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11996 emitcode ("mov", "dptr,#%s", rSym->rname);
11997 /* DP2 = result, DP1 = right, DP1 is current. */
12000 emitcode("movx", "a,@dptr");
12001 emitcode("movx", "@dptr,a");
12004 emitcode("inc", "dptr");
12005 emitcode("inc", "dptr");
12008 emitcode("mov", "dps,#0");
12009 freeAsmop (right, NULL, ic, FALSE);
12011 some alternative code for processors without auto-toggle
12012 no time to test now, so later well put in...kpb
12013 D (emitcode(";", "genFarFarAssign (dual-dptr fun)"));
12014 emitcode("mov", "dps,#1"); /* Select DPTR2. */
12015 emitcode ("mov", "dptr,#%s", rSym->rname);
12016 /* DP2 = result, DP1 = right, DP1 is current. */
12020 emitcode("movx", "a,@dptr");
12022 emitcode("inc", "dptr");
12023 emitcode("inc", "dps");
12024 emitcode("movx", "@dptr,a");
12026 emitcode("inc", "dptr");
12027 emitcode("inc", "dps");
12029 emitcode("mov", "dps,#0");
12030 freeAsmop (right, NULL, ic, FALSE);
12035 D (emitcode (";", "genFarFarAssign"));
12036 aopOp (result, ic, TRUE, TRUE);
12038 _startLazyDPSEvaluation ();
12043 aopGet (right, offset, FALSE, FALSE, NULL), offset);
12046 _endLazyDPSEvaluation ();
12047 freeAsmop (result, NULL, ic, FALSE);
12048 freeAsmop (right, NULL, ic, FALSE);
12052 /*-----------------------------------------------------------------*/
12053 /* genAssign - generate code for assignment */
12054 /*-----------------------------------------------------------------*/
12056 genAssign (iCode * ic)
12058 operand *result, *right;
12060 unsigned long lit = 0L;
12062 D (emitcode (";", "genAssign"));
12064 result = IC_RESULT (ic);
12065 right = IC_RIGHT (ic);
12067 /* if they are the same */
12068 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
12071 aopOp (right, ic, FALSE, FALSE);
12073 emitcode (";", "genAssign: resultIsFar = %s",
12074 isOperandInFarSpace (result) ?
12077 /* special case both in far space */
12078 if ((AOP_TYPE (right) == AOP_DPTR ||
12079 AOP_TYPE (right) == AOP_DPTR2) &&
12080 /* IS_TRUE_SYMOP(result) && */
12081 isOperandInFarSpace (result))
12083 genFarFarAssign (result, right, ic);
12087 aopOp (result, ic, TRUE, FALSE);
12089 /* if they are the same registers */
12090 if (sameRegs (AOP (right), AOP (result)))
12093 /* if the result is a bit */
12094 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
12096 /* if the right size is a literal then
12097 we know what the value is */
12098 if (AOP_TYPE (right) == AOP_LIT)
12100 if (((int) operandLitValue (right)))
12101 aopPut (result, one, 0);
12103 aopPut (result, zero, 0);
12107 /* the right is also a bit variable */
12108 if (AOP_TYPE (right) == AOP_CRY)
12110 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
12111 aopPut (result, "c", 0);
12115 /* we need to or */
12117 aopPut (result, "a", 0);
12121 /* bit variables done */
12123 size = AOP_SIZE (result);
12125 if (AOP_TYPE (right) == AOP_LIT)
12126 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
12129 (AOP_TYPE (result) != AOP_REG) &&
12130 (AOP_TYPE (right) == AOP_LIT) &&
12131 !IS_FLOAT (operandType (right)))
12133 _startLazyDPSEvaluation ();
12134 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
12137 aopGet (right, offset, FALSE, FALSE, NULL),
12142 /* And now fill the rest with zeros. */
12145 emitcode ("clr", "a");
12149 aopPut (result, "a", offset++);
12151 _endLazyDPSEvaluation ();
12155 _startLazyDPSEvaluation ();
12159 aopGet (right, offset, FALSE, FALSE, NULL),
12163 _endLazyDPSEvaluation ();
12167 freeAsmop (result, NULL, ic, TRUE);
12168 freeAsmop (right, NULL, ic, TRUE);
12171 /*-----------------------------------------------------------------*/
12172 /* genJumpTab - generates code for jump table */
12173 /*-----------------------------------------------------------------*/
12175 genJumpTab (iCode * ic)
12180 D (emitcode (";", "genJumpTab"));
12182 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
12183 /* get the condition into accumulator */
12184 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE, NULL);
12186 /* multiply by four! */
12187 emitcode ("add", "a,acc");
12188 emitcode ("add", "a,acc");
12189 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
12191 jtab = newiTempLabel (NULL);
12192 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
12193 emitcode ("jmp", "@a+dptr");
12195 /* now generate the jump labels */
12196 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
12197 jtab = setNextItem (IC_JTLABELS (ic)))
12198 emitcode ("ljmp", "!tlabel", jtab->key + 100);
12202 /*-----------------------------------------------------------------*/
12203 /* genCast - gen code for casting */
12204 /*-----------------------------------------------------------------*/
12206 genCast (iCode * ic)
12208 operand *result = IC_RESULT (ic);
12209 sym_link *ctype = operandType (IC_LEFT (ic));
12210 sym_link *rtype = operandType (IC_RIGHT (ic));
12211 operand *right = IC_RIGHT (ic);
12214 D (emitcode (";", "genCast"));
12216 /* if they are equivalent then do nothing */
12217 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
12220 aopOp (right, ic, FALSE, AOP_IS_STR (result));
12221 aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR));
12223 /* if the result is a bit (and not a bitfield) */
12224 if (IS_BIT (OP_SYMBOL (result)->type))
12226 /* if the right size is a literal then
12227 we know what the value is */
12228 if (AOP_TYPE (right) == AOP_LIT)
12230 if (((int) operandLitValue (right)))
12231 aopPut (result, one, 0);
12233 aopPut (result, zero, 0);
12238 /* the right is also a bit variable */
12239 if (AOP_TYPE (right) == AOP_CRY)
12241 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
12242 aopPut (result, "c", 0);
12246 /* we need to or */
12248 aopPut (result, "a", 0);
12252 /* if they are the same size : or less */
12253 if (AOP_SIZE (result) <= AOP_SIZE (right))
12256 /* if they are in the same place */
12257 if (sameRegs (AOP (right), AOP (result)))
12260 /* if they in different places then copy */
12261 size = AOP_SIZE (result);
12263 _startLazyDPSEvaluation ();
12267 aopGet (right, offset, FALSE, FALSE, NULL),
12271 _endLazyDPSEvaluation ();
12275 /* if the result is of type pointer */
12276 if (IS_PTR (ctype))
12280 sym_link *type = operandType (right);
12282 /* pointer to generic pointer */
12283 if (IS_GENPTR (ctype))
12287 p_type = DCL_TYPE (type);
12291 #if OLD_CAST_BEHAVIOR
12292 /* KV: we are converting a non-pointer type to
12293 * a generic pointer. This (ifdef'd out) code
12294 * says that the resulting generic pointer
12295 * should have the same class as the storage
12296 * location of the non-pointer variable.
12298 * For example, converting an int (which happens
12299 * to be stored in DATA space) to a pointer results
12300 * in a DATA generic pointer; if the original int
12301 * in XDATA space, so will be the resulting pointer.
12303 * I don't like that behavior, and thus this change:
12304 * all such conversions will be forced to XDATA and
12305 * throw a warning. If you want some non-XDATA
12306 * type, or you want to suppress the warning, you
12307 * must go through an intermediate cast, like so:
12309 * char _generic *gp = (char _xdata *)(intVar);
12311 sym_link *etype = getSpec (type);
12313 /* we have to go by the storage class */
12314 if (SPEC_OCLS (etype) != generic)
12316 p_type = PTR_TYPE (SPEC_OCLS (etype));
12321 /* Converting unknown class (i.e. register variable)
12322 * to generic pointer. This is not good, but
12323 * we'll make a guess (and throw a warning).
12326 werror (W_INT_TO_GEN_PTR_CAST);
12330 /* the first two bytes are known */
12331 size = GPTRSIZE - 1;
12333 _startLazyDPSEvaluation ();
12337 aopGet (right, offset, FALSE, FALSE, NULL),
12341 _endLazyDPSEvaluation ();
12343 /* the last byte depending on type */
12345 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
12350 // pointerTypeToGPByte will have bitched.
12354 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%x", gpVal);
12355 aopPut (result, gpValStr, GPTRSIZE - 1);
12360 /* just copy the pointers */
12361 size = AOP_SIZE (result);
12363 _startLazyDPSEvaluation ();
12367 aopGet (right, offset, FALSE, FALSE, NULL),
12371 _endLazyDPSEvaluation ();
12375 /* so we now know that the size of destination is greater
12376 than the size of the source */
12377 /* we move to result for the size of source */
12378 size = AOP_SIZE (right);
12380 _startLazyDPSEvaluation ();
12384 aopGet (right, offset, FALSE, FALSE, NULL),
12388 _endLazyDPSEvaluation ();
12390 /* now depending on the sign of the source && destination */
12391 size = AOP_SIZE (result) - AOP_SIZE (right);
12392 /* if unsigned or not an integral type */
12393 /* also, if the source is a bit, we don't need to sign extend, because
12394 * it can't possibly have set the sign bit.
12396 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
12400 aopPut (result, zero, offset++);
12405 /* we need to extend the sign :{ */
12406 MOVA (aopGet (right, AOP_SIZE (right) - 1,
12407 FALSE, FALSE, NULL));
12408 emitcode ("rlc", "a");
12409 emitcode ("subb", "a,acc");
12411 aopPut (result, "a", offset++);
12414 /* we are done hurray !!!! */
12417 freeAsmop (right, NULL, ic, TRUE);
12418 freeAsmop (result, NULL, ic, TRUE);
12422 /*-----------------------------------------------------------------*/
12423 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
12424 /*-----------------------------------------------------------------*/
12425 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
12427 operand *from , *to , *count;
12432 /* we know it has to be 3 parameters */
12433 assert (nparms == 3);
12435 rsave = newBitVect(16);
12436 /* save DPTR if it needs to be saved */
12437 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12438 if (bitVectBitValue(ic->rMask,i))
12439 rsave = bitVectSetBit(rsave,i);
12441 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12442 ds390_rUmaskForOp (IC_RESULT(ic))));
12449 aopOp (from, ic->next, FALSE, FALSE);
12451 /* get from into DPTR1 */
12452 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12453 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12454 if (options.model == MODEL_FLAT24) {
12455 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12458 freeAsmop (from, NULL, ic, FALSE);
12459 aopOp (to, ic, FALSE, FALSE);
12460 /* get "to" into DPTR */
12461 /* if the operand is already in dptr
12462 then we do nothing else we move the value to dptr */
12463 if (AOP_TYPE (to) != AOP_STR) {
12464 /* if already in DPTR then we need to push */
12465 if (AOP_TYPE(to) == AOP_DPTR) {
12466 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12467 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12468 if (options.model == MODEL_FLAT24)
12469 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12470 emitcode ("pop", "dph");
12471 emitcode ("pop", "dpl");
12473 _startLazyDPSEvaluation ();
12474 /* if this is remateriazable */
12475 if (AOP_TYPE (to) == AOP_IMMD) {
12476 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12477 } else { /* we need to get it byte by byte */
12478 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12479 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12480 if (options.model == MODEL_FLAT24) {
12481 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12484 _endLazyDPSEvaluation ();
12487 freeAsmop (to, NULL, ic, FALSE);
12488 _G.dptrInUse = _G.dptr1InUse = 1;
12489 aopOp (count, ic->next->next, FALSE,FALSE);
12490 lbl =newiTempLabel(NULL);
12492 /* now for the actual copy */
12493 if (AOP_TYPE(count) == AOP_LIT &&
12494 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12495 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12497 emitcode ("lcall","__bi_memcpyc2x_s");
12499 emitcode ("lcall","__bi_memcpyx2x_s");
12501 freeAsmop (count, NULL, ic, FALSE);
12503 symbol *lbl1 = newiTempLabel(NULL);
12505 emitcode (";"," Auto increment but no djnz");
12506 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
12507 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
12508 freeAsmop (count, NULL, ic, FALSE);
12509 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12510 emitcode ("","!tlabeldef",lbl->key+100);
12512 emitcode ("clr","a");
12513 emitcode ("movc", "a,@a+dptr");
12515 emitcode ("movx", "a,@dptr");
12516 emitcode ("movx", "@dptr,a");
12517 emitcode ("inc", "dptr");
12518 emitcode ("inc", "dptr");
12519 emitcode ("mov","a,b");
12520 emitcode ("orl","a,_ap");
12521 emitcode ("jz","!tlabel",lbl1->key+100);
12522 emitcode ("mov","a,_ap");
12523 emitcode ("add","a,#!constbyte",0xFF);
12524 emitcode ("mov","_ap,a");
12525 emitcode ("mov","a,b");
12526 emitcode ("addc","a,#!constbyte",0xFF);
12527 emitcode ("mov","b,a");
12528 emitcode ("sjmp","!tlabel",lbl->key+100);
12529 emitcode ("","!tlabeldef",lbl1->key+100);
12531 emitcode ("mov", "dps,#0");
12532 _G.dptrInUse = _G.dptr1InUse = 0;
12533 unsavermask(rsave);
12537 /*-----------------------------------------------------------------*/
12538 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
12539 /*-----------------------------------------------------------------*/
12540 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
12542 operand *from , *to , *count;
12547 /* we know it has to be 3 parameters */
12548 assert (nparms == 3);
12550 rsave = newBitVect(16);
12551 /* save DPTR if it needs to be saved */
12552 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12553 if (bitVectBitValue(ic->rMask,i))
12554 rsave = bitVectSetBit(rsave,i);
12556 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12557 ds390_rUmaskForOp (IC_RESULT(ic))));
12564 aopOp (from, ic->next, FALSE, FALSE);
12566 /* get from into DPTR1 */
12567 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12568 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12569 if (options.model == MODEL_FLAT24) {
12570 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12573 freeAsmop (from, NULL, ic, FALSE);
12574 aopOp (to, ic, FALSE, FALSE);
12575 /* get "to" into DPTR */
12576 /* if the operand is already in dptr
12577 then we do nothing else we move the value to dptr */
12578 if (AOP_TYPE (to) != AOP_STR) {
12579 /* if already in DPTR then we need to push */
12580 if (AOP_TYPE(to) == AOP_DPTR) {
12581 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12582 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12583 if (options.model == MODEL_FLAT24)
12584 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12585 emitcode ("pop", "dph");
12586 emitcode ("pop", "dpl");
12588 _startLazyDPSEvaluation ();
12589 /* if this is remateriazable */
12590 if (AOP_TYPE (to) == AOP_IMMD) {
12591 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12592 } else { /* we need to get it byte by byte */
12593 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12594 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12595 if (options.model == MODEL_FLAT24) {
12596 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12599 _endLazyDPSEvaluation ();
12602 freeAsmop (to, NULL, ic, FALSE);
12603 _G.dptrInUse = _G.dptr1InUse = 1;
12604 aopOp (count, ic->next->next, FALSE,FALSE);
12605 lbl =newiTempLabel(NULL);
12606 lbl2 =newiTempLabel(NULL);
12608 /* now for the actual compare */
12609 if (AOP_TYPE(count) == AOP_LIT &&
12610 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12611 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12613 emitcode("lcall","__bi_memcmpc2x_s");
12615 emitcode("lcall","__bi_memcmpx2x_s");
12616 freeAsmop (count, NULL, ic, FALSE);
12617 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12618 aopPut(IC_RESULT(ic),"a",0);
12619 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12621 symbol *lbl1 = newiTempLabel(NULL);
12623 emitcode("push","ar0");
12624 emitcode (";"," Auto increment but no djnz");
12625 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
12626 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
12627 freeAsmop (count, NULL, ic, FALSE);
12628 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12629 emitcode ("","!tlabeldef",lbl->key+100);
12631 emitcode ("clr","a");
12632 emitcode ("movc", "a,@a+dptr");
12634 emitcode ("movx", "a,@dptr");
12635 emitcode ("mov","r0,a");
12636 emitcode ("movx", "a,@dptr");
12637 emitcode ("clr","c");
12638 emitcode ("subb","a,r0");
12639 emitcode ("jnz","!tlabel",lbl2->key+100);
12640 emitcode ("inc", "dptr");
12641 emitcode ("inc", "dptr");
12642 emitcode ("mov","a,b");
12643 emitcode ("orl","a,_ap");
12644 emitcode ("jz","!tlabel",lbl1->key+100);
12645 emitcode ("mov","a,_ap");
12646 emitcode ("add","a,#!constbyte",0xFF);
12647 emitcode ("mov","_ap,a");
12648 emitcode ("mov","a,b");
12649 emitcode ("addc","a,#!constbyte",0xFF);
12650 emitcode ("mov","b,a");
12651 emitcode ("sjmp","!tlabel",lbl->key+100);
12652 emitcode ("","!tlabeldef",lbl1->key+100);
12653 emitcode ("clr","a");
12654 emitcode ("","!tlabeldef",lbl2->key+100);
12655 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12656 aopPut(IC_RESULT(ic),"a",0);
12657 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12658 emitcode("pop","ar0");
12659 emitcode ("mov", "dps,#0");
12661 _G.dptrInUse = _G.dptr1InUse = 0;
12662 unsavermask(rsave);
12666 /*-----------------------------------------------------------------*/
12667 /* genInp - gen code for __builtin_inp read data from a mem mapped */
12668 /* port, first parameter output area second parameter pointer to */
12669 /* port third parameter count */
12670 /*-----------------------------------------------------------------*/
12671 static void genInp( iCode *ic, int nparms, operand **parms)
12673 operand *from , *to , *count;
12678 /* we know it has to be 3 parameters */
12679 assert (nparms == 3);
12681 rsave = newBitVect(16);
12682 /* save DPTR if it needs to be saved */
12683 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12684 if (bitVectBitValue(ic->rMask,i))
12685 rsave = bitVectSetBit(rsave,i);
12687 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12688 ds390_rUmaskForOp (IC_RESULT(ic))));
12695 aopOp (from, ic->next, FALSE, FALSE);
12697 /* get from into DPTR1 */
12698 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12699 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12700 if (options.model == MODEL_FLAT24) {
12701 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12704 freeAsmop (from, NULL, ic, FALSE);
12705 aopOp (to, ic, FALSE, FALSE);
12706 /* get "to" into DPTR */
12707 /* if the operand is already in dptr
12708 then we do nothing else we move the value to dptr */
12709 if (AOP_TYPE (to) != AOP_STR) {
12710 /* if already in DPTR then we need to push */
12711 if (AOP_TYPE(to) == AOP_DPTR) {
12712 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12713 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12714 if (options.model == MODEL_FLAT24)
12715 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12716 emitcode ("pop", "dph");
12717 emitcode ("pop", "dpl");
12719 _startLazyDPSEvaluation ();
12720 /* if this is remateriazable */
12721 if (AOP_TYPE (to) == AOP_IMMD) {
12722 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12723 } else { /* we need to get it byte by byte */
12724 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12725 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12726 if (options.model == MODEL_FLAT24) {
12727 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12730 _endLazyDPSEvaluation ();
12733 freeAsmop (to, NULL, ic, FALSE);
12735 _G.dptrInUse = _G.dptr1InUse = 1;
12736 aopOp (count, ic->next->next, FALSE,FALSE);
12737 lbl =newiTempLabel(NULL);
12739 /* now for the actual copy */
12740 if (AOP_TYPE(count) == AOP_LIT &&
12741 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12742 emitcode (";","OH JOY auto increment with djnz (very fast)");
12743 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
12744 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12745 freeAsmop (count, NULL, ic, FALSE);
12746 emitcode ("","!tlabeldef",lbl->key+100);
12747 emitcode ("movx", "a,@dptr"); /* read data from port */
12748 emitcode ("dec","dps"); /* switch to DPTR */
12749 emitcode ("movx", "@dptr,a"); /* save into location */
12750 emitcode ("inc", "dptr"); /* point to next area */
12751 emitcode ("inc","dps"); /* switch to DPTR2 */
12752 emitcode ("djnz","b,!tlabel",lbl->key+100);
12754 symbol *lbl1 = newiTempLabel(NULL);
12756 emitcode (";"," Auto increment but no djnz");
12757 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
12758 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
12759 freeAsmop (count, NULL, ic, FALSE);
12760 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
12761 emitcode ("","!tlabeldef",lbl->key+100);
12762 emitcode ("movx", "a,@dptr");
12763 emitcode ("dec","dps"); /* switch to DPTR */
12764 emitcode ("movx", "@dptr,a");
12765 emitcode ("inc", "dptr");
12766 emitcode ("inc","dps"); /* switch to DPTR2 */
12767 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
12768 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
12769 emitcode ("mov","a,b");
12770 emitcode ("orl","a,_ap");
12771 emitcode ("jz","!tlabel",lbl1->key+100);
12772 emitcode ("mov","a,_ap");
12773 emitcode ("add","a,#!constbyte",0xFF);
12774 emitcode ("mov","_ap,a");
12775 emitcode ("mov","a,b");
12776 emitcode ("addc","a,#!constbyte",0xFF);
12777 emitcode ("mov","b,a");
12778 emitcode ("sjmp","!tlabel",lbl->key+100);
12779 emitcode ("","!tlabeldef",lbl1->key+100);
12781 emitcode ("mov", "dps,#0");
12782 _G.dptrInUse = _G.dptr1InUse = 0;
12783 unsavermask(rsave);
12787 /*-----------------------------------------------------------------*/
12788 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
12789 /* port, first parameter output area second parameter pointer to */
12790 /* port third parameter count */
12791 /*-----------------------------------------------------------------*/
12792 static void genOutp( iCode *ic, int nparms, operand **parms)
12794 operand *from , *to , *count;
12799 /* we know it has to be 3 parameters */
12800 assert (nparms == 3);
12802 rsave = newBitVect(16);
12803 /* save DPTR if it needs to be saved */
12804 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12805 if (bitVectBitValue(ic->rMask,i))
12806 rsave = bitVectSetBit(rsave,i);
12808 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12809 ds390_rUmaskForOp (IC_RESULT(ic))));
12816 aopOp (from, ic->next, FALSE, FALSE);
12818 /* get from into DPTR1 */
12819 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12820 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12821 if (options.model == MODEL_FLAT24) {
12822 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12825 freeAsmop (from, NULL, ic, FALSE);
12826 aopOp (to, ic, FALSE, FALSE);
12827 /* get "to" into DPTR */
12828 /* if the operand is already in dptr
12829 then we do nothing else we move the value to dptr */
12830 if (AOP_TYPE (to) != AOP_STR) {
12831 /* if already in DPTR then we need to push */
12832 if (AOP_TYPE(to) == AOP_DPTR) {
12833 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12834 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12835 if (options.model == MODEL_FLAT24)
12836 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12837 emitcode ("pop", "dph");
12838 emitcode ("pop", "dpl");
12840 _startLazyDPSEvaluation ();
12841 /* if this is remateriazable */
12842 if (AOP_TYPE (to) == AOP_IMMD) {
12843 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12844 } else { /* we need to get it byte by byte */
12845 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12846 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12847 if (options.model == MODEL_FLAT24) {
12848 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12851 _endLazyDPSEvaluation ();
12854 freeAsmop (to, NULL, ic, FALSE);
12856 _G.dptrInUse = _G.dptr1InUse = 1;
12857 aopOp (count, ic->next->next, FALSE,FALSE);
12858 lbl =newiTempLabel(NULL);
12860 /* now for the actual copy */
12861 if (AOP_TYPE(count) == AOP_LIT &&
12862 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12863 emitcode (";","OH JOY auto increment with djnz (very fast)");
12864 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
12865 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12866 emitcode ("","!tlabeldef",lbl->key+100);
12867 emitcode ("movx", "a,@dptr"); /* read data from port */
12868 emitcode ("inc","dps"); /* switch to DPTR2 */
12869 emitcode ("movx", "@dptr,a"); /* save into location */
12870 emitcode ("inc", "dptr"); /* point to next area */
12871 emitcode ("dec","dps"); /* switch to DPTR */
12872 emitcode ("djnz","b,!tlabel",lbl->key+100);
12873 freeAsmop (count, NULL, ic, FALSE);
12875 symbol *lbl1 = newiTempLabel(NULL);
12877 emitcode (";"," Auto increment but no djnz");
12878 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
12879 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
12880 freeAsmop (count, NULL, ic, FALSE);
12881 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
12882 emitcode ("","!tlabeldef",lbl->key+100);
12883 emitcode ("movx", "a,@dptr");
12884 emitcode ("inc", "dptr");
12885 emitcode ("inc","dps"); /* switch to DPTR2 */
12886 emitcode ("movx", "@dptr,a");
12887 emitcode ("dec","dps"); /* switch to DPTR */
12888 emitcode ("mov","a,b");
12889 emitcode ("orl","a,_ap");
12890 emitcode ("jz","!tlabel",lbl1->key+100);
12891 emitcode ("mov","a,_ap");
12892 emitcode ("add","a,#!constbyte",0xFF);
12893 emitcode ("mov","_ap,a");
12894 emitcode ("mov","a,b");
12895 emitcode ("addc","a,#!constbyte",0xFF);
12896 emitcode ("mov","b,a");
12897 emitcode ("sjmp","!tlabel",lbl->key+100);
12898 emitcode ("","!tlabeldef",lbl1->key+100);
12900 emitcode ("mov", "dps,#0");
12901 _G.dptrInUse = _G.dptr1InUse = 0;
12902 unsavermask(rsave);
12906 /*-----------------------------------------------------------------*/
12907 /* genSwapW - swap lower & high order bytes */
12908 /*-----------------------------------------------------------------*/
12909 static void genSwapW(iCode *ic, int nparms, operand **parms)
12913 assert (nparms==1);
12916 dest=IC_RESULT(ic);
12918 assert(getSize(operandType(src))==2);
12920 aopOp (src, ic, FALSE, FALSE);
12921 emitcode ("mov","a,%s",aopGet(src,0,FALSE,FALSE,NULL));
12923 MOVB(aopGet(src,1,FALSE,FALSE,"b"));
12925 freeAsmop (src, NULL, ic, FALSE);
12927 aopOp (dest,ic, FALSE, FALSE);
12928 aopPut(dest,"b",0);
12929 aopPut(dest,"a",1);
12930 freeAsmop (dest, NULL, ic, FALSE);
12933 /*-----------------------------------------------------------------*/
12934 /* genMemsetX - gencode for memSetX data */
12935 /*-----------------------------------------------------------------*/
12936 static void genMemsetX(iCode *ic, int nparms, operand **parms)
12938 operand *to , *val , *count;
12944 /* we know it has to be 3 parameters */
12945 assert (nparms == 3);
12951 /* save DPTR if it needs to be saved */
12952 rsave = newBitVect(16);
12953 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12954 if (bitVectBitValue(ic->rMask,i))
12955 rsave = bitVectSetBit(rsave,i);
12957 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12958 ds390_rUmaskForOp (IC_RESULT(ic))));
12961 aopOp (to, ic, FALSE, FALSE);
12962 /* get "to" into DPTR */
12963 /* if the operand is already in dptr
12964 then we do nothing else we move the value to dptr */
12965 if (AOP_TYPE (to) != AOP_STR) {
12966 /* if already in DPTR then we need to push */
12967 if (AOP_TYPE(to) == AOP_DPTR) {
12968 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12969 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12970 if (options.model == MODEL_FLAT24)
12971 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12972 emitcode ("pop", "dph");
12973 emitcode ("pop", "dpl");
12975 _startLazyDPSEvaluation ();
12976 /* if this is remateriazable */
12977 if (AOP_TYPE (to) == AOP_IMMD) {
12978 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12979 } else { /* we need to get it byte by byte */
12980 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12981 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12982 if (options.model == MODEL_FLAT24) {
12983 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12986 _endLazyDPSEvaluation ();
12989 freeAsmop (to, NULL, ic, FALSE);
12991 aopOp (val, ic->next->next, FALSE,FALSE);
12992 aopOp (count, ic->next->next, FALSE,FALSE);
12993 lbl =newiTempLabel(NULL);
12994 /* now for the actual copy */
12995 if (AOP_TYPE(count) == AOP_LIT &&
12996 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12997 l = aopGet(val, 0, FALSE, FALSE, NULL);
12998 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
13000 emitcode ("","!tlabeldef",lbl->key+100);
13001 emitcode ("movx", "@dptr,a");
13002 emitcode ("inc", "dptr");
13003 emitcode ("djnz","b,!tlabel",lbl->key+100);
13005 symbol *lbl1 = newiTempLabel(NULL);
13007 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
13008 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
13009 emitcode ("","!tlabeldef",lbl->key+100);
13010 MOVA (aopGet(val, 0, FALSE, FALSE, NULL));
13011 emitcode ("movx", "@dptr,a");
13012 emitcode ("inc", "dptr");
13013 emitcode ("mov","a,b");
13014 emitcode ("orl","a,_ap");
13015 emitcode ("jz","!tlabel",lbl1->key+100);
13016 emitcode ("mov","a,_ap");
13017 emitcode ("add","a,#!constbyte",0xFF);
13018 emitcode ("mov","_ap,a");
13019 emitcode ("mov","a,b");
13020 emitcode ("addc","a,#!constbyte",0xFF);
13021 emitcode ("mov","b,a");
13022 emitcode ("sjmp","!tlabel",lbl->key+100);
13023 emitcode ("","!tlabeldef",lbl1->key+100);
13025 freeAsmop (count, NULL, ic, FALSE);
13026 unsavermask(rsave);
13029 /*-----------------------------------------------------------------*/
13030 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
13031 /*-----------------------------------------------------------------*/
13032 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
13035 operand *pnum, *result;
13038 assert (nparms==1);
13039 /* save registers that need to be saved */
13040 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13041 ds390_rUmaskForOp (IC_RESULT(ic))));
13044 aopOp (pnum, ic, FALSE, FALSE);
13045 emitcode ("mov","a,%s",aopGet(pnum,0,FALSE,FALSE,DP2_RESULT_REG));
13046 freeAsmop (pnum, NULL, ic, FALSE);
13047 emitcode ("lcall","NatLib_LoadPrimitive");
13048 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
13049 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
13050 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
13051 for (i = (size-1) ; i >= 0 ; i-- ) {
13052 emitcode ("push","a%s",javaRet[i]);
13054 for (i=0; i < size ; i++ ) {
13055 emitcode ("pop","a%s",
13056 aopGet(result,i,FALSE,FALSE,DP2_RESULT_REG));
13059 for (i = 0 ; i < size ; i++ ) {
13060 aopPut(result,javaRet[i],i);
13063 freeAsmop (result, NULL, ic, FALSE);
13064 unsavermask(rsave);
13067 /*-----------------------------------------------------------------*/
13068 /* genNatLibLoadPointer - calls TINI api function to load pointer */
13069 /*-----------------------------------------------------------------*/
13070 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
13073 operand *pnum, *result;
13077 assert (nparms==1);
13078 /* save registers that need to be saved */
13079 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13080 ds390_rUmaskForOp (IC_RESULT(ic))));
13083 aopOp (pnum, ic, FALSE, FALSE);
13084 emitcode ("mov","a,%s",aopGet(pnum,0,FALSE,FALSE,DP2_RESULT_REG));
13085 freeAsmop (pnum, NULL, ic, FALSE);
13086 emitcode ("lcall","NatLib_LoadPointer");
13087 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
13088 if (AOP_TYPE(result)!=AOP_STR) {
13089 for (i = 0 ; i < size ; i++ ) {
13090 aopPut(result,fReturn[i],i);
13093 freeAsmop (result, NULL, ic, FALSE);
13094 unsavermask(rsave);
13097 /*-----------------------------------------------------------------*/
13098 /* genNatLibInstallStateBlock - */
13099 /*-----------------------------------------------------------------*/
13100 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
13101 operand **parms, const char *name)
13104 operand *psb, *handle;
13105 assert (nparms==2);
13107 /* save registers that need to be saved */
13108 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13109 ds390_rUmaskForOp (IC_RESULT(ic))));
13113 /* put pointer to state block into DPTR1 */
13114 aopOp (psb, ic, FALSE, FALSE);
13115 if (AOP_TYPE (psb) == AOP_IMMD) {
13116 emitcode ("mov","dps,#1");
13117 emitcode ("mov", "dptr,%s",
13118 aopGet (psb, 0, TRUE, FALSE, DP2_RESULT_REG));
13119 emitcode ("mov","dps,#0");
13121 emitcode ("mov","dpl1,%s",aopGet(psb,0,FALSE,FALSE,DP2_RESULT_REG));
13122 emitcode ("mov","dph1,%s",aopGet(psb,1,FALSE,FALSE,DP2_RESULT_REG));
13123 emitcode ("mov","dpx1,%s",aopGet(psb,2,FALSE,FALSE,DP2_RESULT_REG));
13125 freeAsmop (psb, NULL, ic, FALSE);
13127 /* put libraryID into DPTR */
13128 emitcode ("mov","dptr,#LibraryID");
13130 /* put handle into r3:r2 */
13131 aopOp (handle, ic, FALSE, FALSE);
13132 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13133 emitcode ("push","%s",aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13134 emitcode ("push","%s",aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13135 emitcode ("pop","ar3");
13136 emitcode ("pop","ar2");
13138 emitcode ("mov","r2,%s",aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13139 emitcode ("mov","r3,%s",aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13141 freeAsmop (psb, NULL, ic, FALSE);
13143 /* make the call */
13144 emitcode ("lcall","NatLib_Install%sStateBlock",name);
13146 /* put return value into place*/
13148 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
13150 aopPut(IC_RESULT(ic),"a",0);
13151 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13152 unsavermask(rsave);
13155 /*-----------------------------------------------------------------*/
13156 /* genNatLibRemoveStateBlock - */
13157 /*-----------------------------------------------------------------*/
13158 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
13164 /* save registers that need to be saved */
13165 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13166 ds390_rUmaskForOp (IC_RESULT(ic))));
13168 /* put libraryID into DPTR */
13169 emitcode ("mov","dptr,#LibraryID");
13170 /* make the call */
13171 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
13172 unsavermask(rsave);
13175 /*-----------------------------------------------------------------*/
13176 /* genNatLibGetStateBlock - */
13177 /*-----------------------------------------------------------------*/
13178 static void genNatLibGetStateBlock(iCode *ic,int nparms,
13179 operand **parms,const char *name)
13182 symbol *lbl = newiTempLabel(NULL);
13185 /* save registers that need to be saved */
13186 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13187 ds390_rUmaskForOp (IC_RESULT(ic))));
13189 /* put libraryID into DPTR */
13190 emitcode ("mov","dptr,#LibraryID");
13191 /* make the call */
13192 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
13193 emitcode ("jnz","!tlabel",lbl->key+100);
13195 /* put return value into place */
13196 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
13197 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
13198 emitcode ("push","ar3");
13199 emitcode ("push","ar2");
13200 emitcode ("pop","%s",
13201 aopGet(IC_RESULT(ic),0,FALSE,TRUE,DP2_RESULT_REG));
13202 emitcode ("pop","%s",
13203 aopGet(IC_RESULT(ic),1,FALSE,TRUE,DP2_RESULT_REG));
13205 aopPut(IC_RESULT(ic),"r2",0);
13206 aopPut(IC_RESULT(ic),"r3",1);
13208 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13209 emitcode ("","!tlabeldef",lbl->key+100);
13210 unsavermask(rsave);
13213 /*-----------------------------------------------------------------*/
13214 /* genMMMalloc - */
13215 /*-----------------------------------------------------------------*/
13216 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
13217 int size, const char *name)
13222 symbol *lbl = newiTempLabel(NULL);
13224 assert (nparms == 1);
13225 /* save registers that need to be saved */
13226 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13227 ds390_rUmaskForOp (IC_RESULT(ic))));
13230 aopOp (bsize,ic,FALSE,FALSE);
13232 /* put the size in R4-R2 */
13233 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
13234 emitcode("push","%s",aopGet(bsize,0,FALSE,TRUE,DP2_RESULT_REG));
13235 emitcode("push","%s",aopGet(bsize,1,FALSE,TRUE,DP2_RESULT_REG));
13237 emitcode("push","%s",aopGet(bsize,2,FALSE,TRUE,DP2_RESULT_REG));
13238 emitcode("pop","ar4");
13240 emitcode("pop","ar3");
13241 emitcode("pop","ar2");
13243 emitcode ("mov","r2,%s",aopGet(bsize,0,FALSE,TRUE,DP2_RESULT_REG));
13244 emitcode ("mov","r3,%s",aopGet(bsize,1,FALSE,TRUE,DP2_RESULT_REG));
13246 emitcode("mov","r4,%s",aopGet(bsize,2,FALSE,TRUE,DP2_RESULT_REG));
13249 freeAsmop (bsize, NULL, ic, FALSE);
13251 /* make the call */
13252 emitcode ("lcall","MM_%s",name);
13253 emitcode ("jz","!tlabel",lbl->key+100);
13254 emitcode ("mov","r2,#!constbyte",0xff);
13255 emitcode ("mov","r3,#!constbyte",0xff);
13256 emitcode ("","!tlabeldef",lbl->key+100);
13257 /* we don't care about the pointer : we just save the handle */
13258 rsym = OP_SYMBOL(IC_RESULT(ic));
13259 if (rsym->liveFrom != rsym->liveTo) {
13260 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
13261 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
13262 emitcode ("push","ar3");
13263 emitcode ("push","ar2");
13264 emitcode ("pop","%s",
13265 aopGet(IC_RESULT(ic),0,FALSE,TRUE,DP2_RESULT_REG));
13266 emitcode ("pop","%s",
13267 aopGet(IC_RESULT(ic),1,FALSE,TRUE,DP2_RESULT_REG));
13269 aopPut(IC_RESULT(ic),"r2",0);
13270 aopPut(IC_RESULT(ic),"r3",1);
13272 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13274 unsavermask(rsave);
13277 /*-----------------------------------------------------------------*/
13279 /*-----------------------------------------------------------------*/
13280 static void genMMDeref (iCode *ic,int nparms, operand **parms)
13285 assert (nparms == 1);
13286 /* save registers that need to be saved */
13287 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13288 ds390_rUmaskForOp (IC_RESULT(ic))));
13291 aopOp (handle,ic,FALSE,FALSE);
13293 /* put the size in R4-R2 */
13294 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13295 emitcode("push","%s",
13296 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13297 emitcode("push","%s",
13298 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13299 emitcode("pop","ar3");
13300 emitcode("pop","ar2");
13302 emitcode ("mov","r2,%s",
13303 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13304 emitcode ("mov","r3,%s",
13305 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13307 freeAsmop (handle, NULL, ic, FALSE);
13309 /* make the call */
13310 emitcode ("lcall","MM_Deref");
13313 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13314 if (rsym->liveFrom != rsym->liveTo) {
13315 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13316 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
13317 _startLazyDPSEvaluation ();
13319 aopPut(IC_RESULT(ic),"dpl",0);
13320 aopPut(IC_RESULT(ic),"dph",1);
13321 aopPut(IC_RESULT(ic),"dpx",2);
13323 _endLazyDPSEvaluation ();
13328 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13329 unsavermask(rsave);
13332 /*-----------------------------------------------------------------*/
13333 /* genMMUnrestrictedPersist - */
13334 /*-----------------------------------------------------------------*/
13335 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
13340 assert (nparms == 1);
13341 /* save registers that need to be saved */
13342 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13343 ds390_rUmaskForOp (IC_RESULT(ic))));
13346 aopOp (handle,ic,FALSE,FALSE);
13348 /* put the size in R3-R2 */
13349 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13350 emitcode("push","%s",
13351 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13352 emitcode("push","%s",
13353 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13354 emitcode("pop","ar3");
13355 emitcode("pop","ar2");
13357 emitcode ("mov","r2,%s",
13358 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13359 emitcode ("mov","r3,%s",
13360 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13362 freeAsmop (handle, NULL, ic, FALSE);
13364 /* make the call */
13365 emitcode ("lcall","MM_UnrestrictedPersist");
13368 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13369 if (rsym->liveFrom != rsym->liveTo) {
13370 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13371 aopPut(IC_RESULT(ic),"a",0);
13372 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13375 unsavermask(rsave);
13378 /*-----------------------------------------------------------------*/
13379 /* genSystemExecJavaProcess - */
13380 /*-----------------------------------------------------------------*/
13381 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
13384 operand *handle, *pp;
13386 assert (nparms==2);
13387 /* save registers that need to be saved */
13388 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13389 ds390_rUmaskForOp (IC_RESULT(ic))));
13394 /* put the handle in R3-R2 */
13395 aopOp (handle,ic,FALSE,FALSE);
13396 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13397 emitcode("push","%s",
13398 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13399 emitcode("push","%s",
13400 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13401 emitcode("pop","ar3");
13402 emitcode("pop","ar2");
13404 emitcode ("mov","r2,%s",
13405 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13406 emitcode ("mov","r3,%s",
13407 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13409 freeAsmop (handle, NULL, ic, FALSE);
13411 /* put pointer in DPTR */
13412 aopOp (pp,ic,FALSE,FALSE);
13413 if (AOP_TYPE(pp) == AOP_IMMD) {
13414 emitcode ("mov", "dptr,%s",
13415 aopGet (pp, 0, TRUE, FALSE, NULL));
13416 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
13417 emitcode ("mov","dpl,%s",aopGet(pp,0,FALSE,FALSE,NULL));
13418 emitcode ("mov","dph,%s",aopGet(pp,1,FALSE,FALSE,NULL));
13419 emitcode ("mov","dpx,%s",aopGet(pp,2,FALSE,FALSE,NULL));
13421 freeAsmop (handle, NULL, ic, FALSE);
13423 /* make the call */
13424 emitcode ("lcall","System_ExecJavaProcess");
13426 /* put result in place */
13428 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13429 if (rsym->liveFrom != rsym->liveTo) {
13430 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13431 aopPut(IC_RESULT(ic),"a",0);
13432 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13436 unsavermask(rsave);
13439 /*-----------------------------------------------------------------*/
13440 /* genSystemRTCRegisters - */
13441 /*-----------------------------------------------------------------*/
13442 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
13448 assert (nparms==1);
13449 /* save registers that need to be saved */
13450 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13451 ds390_rUmaskForOp (IC_RESULT(ic))));
13454 /* put pointer in DPTR */
13455 aopOp (pp,ic,FALSE,FALSE);
13456 if (AOP_TYPE (pp) == AOP_IMMD) {
13457 emitcode ("mov","dps,#1");
13458 emitcode ("mov", "dptr,%s",
13459 aopGet (pp, 0, TRUE, FALSE, NULL));
13460 emitcode ("mov","dps,#0");
13462 emitcode ("mov","dpl1,%s",
13463 aopGet(pp,0,FALSE,FALSE,DP2_RESULT_REG));
13464 emitcode ("mov","dph1,%s",
13465 aopGet(pp,1,FALSE,FALSE,DP2_RESULT_REG));
13466 emitcode ("mov","dpx1,%s",
13467 aopGet(pp,2,FALSE,FALSE,DP2_RESULT_REG));
13469 freeAsmop (pp, NULL, ic, FALSE);
13471 /* make the call */
13472 emitcode ("lcall","System_%sRTCRegisters",name);
13474 unsavermask(rsave);
13477 /*-----------------------------------------------------------------*/
13478 /* genSystemThreadSleep - */
13479 /*-----------------------------------------------------------------*/
13480 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
13485 assert (nparms==1);
13486 /* save registers that need to be saved */
13487 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13488 ds390_rUmaskForOp (IC_RESULT(ic))));
13491 aopOp(to,ic,FALSE,FALSE);
13492 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
13493 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
13494 emitcode ("push","%s",
13495 aopGet(to,0,FALSE,TRUE,DP2_RESULT_REG));
13496 emitcode ("push","%s",
13497 aopGet(to,1,FALSE,TRUE,DP2_RESULT_REG));
13498 emitcode ("push","%s",
13499 aopGet(to,2,FALSE,TRUE,DP2_RESULT_REG));
13500 emitcode ("push","%s",
13501 aopGet(to,3,FALSE,TRUE,DP2_RESULT_REG));
13502 emitcode ("pop","ar3");
13503 emitcode ("pop","ar2");
13504 emitcode ("pop","ar1");
13505 emitcode ("pop","ar0");
13507 emitcode ("mov","r0,%s",
13508 aopGet(to,0,FALSE,TRUE,DP2_RESULT_REG));
13509 emitcode ("mov","r1,%s",
13510 aopGet(to,1,FALSE,TRUE,DP2_RESULT_REG));
13511 emitcode ("mov","r2,%s",
13512 aopGet(to,2,FALSE,TRUE,DP2_RESULT_REG));
13513 emitcode ("mov","r3,%s",
13514 aopGet(to,3,FALSE,TRUE,DP2_RESULT_REG));
13516 freeAsmop (to, NULL, ic, FALSE);
13518 /* suspend in acc */
13520 aopOp(s,ic,FALSE,FALSE);
13521 emitcode ("mov","a,%s",
13522 aopGet(s,0,FALSE,TRUE,NULL));
13523 freeAsmop (s, NULL, ic, FALSE);
13525 /* make the call */
13526 emitcode ("lcall","System_%s",name);
13528 unsavermask(rsave);
13531 /*-----------------------------------------------------------------*/
13532 /* genSystemThreadResume - */
13533 /*-----------------------------------------------------------------*/
13534 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
13539 assert (nparms==2);
13540 /* save registers that need to be saved */
13541 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13542 ds390_rUmaskForOp (IC_RESULT(ic))));
13548 aopOp(pid,ic,FALSE,FALSE);
13549 emitcode ("mov","r0,%s",
13550 aopGet(pid,0,FALSE,TRUE,DP2_RESULT_REG));
13551 freeAsmop (pid, NULL, ic, FALSE);
13554 aopOp(tid,ic,FALSE,FALSE);
13555 emitcode ("mov","a,%s",
13556 aopGet(tid,0,FALSE,TRUE,DP2_RESULT_REG));
13557 freeAsmop (tid, NULL, ic, FALSE);
13559 emitcode ("lcall","System_ThreadResume");
13561 /* put result into place */
13563 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13564 if (rsym->liveFrom != rsym->liveTo) {
13565 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13566 aopPut(IC_RESULT(ic),"a",0);
13567 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13570 unsavermask(rsave);
13573 /*-----------------------------------------------------------------*/
13574 /* genSystemProcessResume - */
13575 /*-----------------------------------------------------------------*/
13576 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
13581 assert (nparms==1);
13582 /* save registers that need to be saved */
13583 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13584 ds390_rUmaskForOp (IC_RESULT(ic))));
13589 aopOp(pid,ic,FALSE,FALSE);
13590 emitcode ("mov","a,%s",
13591 aopGet(pid,0,FALSE,TRUE,DP2_RESULT_REG));
13592 freeAsmop (pid, NULL, ic, FALSE);
13594 emitcode ("lcall","System_ProcessResume");
13596 unsavermask(rsave);
13599 /*-----------------------------------------------------------------*/
13601 /*-----------------------------------------------------------------*/
13602 static void genSystem (iCode *ic,int nparms,char *name)
13604 assert(nparms == 0);
13606 emitcode ("lcall","System_%s",name);
13609 /*-----------------------------------------------------------------*/
13610 /* genSystemPoll - */
13611 /*-----------------------------------------------------------------*/
13612 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
13617 assert (nparms==1);
13618 /* save registers that need to be saved */
13619 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13620 ds390_rUmaskForOp (IC_RESULT(ic))));
13623 aopOp (fp,ic,FALSE,FALSE);
13624 if (AOP_TYPE (fp) == AOP_IMMD) {
13625 emitcode ("mov", "dptr,%s",
13626 aopGet (fp, 0, TRUE, FALSE, DP2_RESULT_REG));
13627 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
13628 emitcode ("mov","dpl,%s",
13629 aopGet(fp,0,FALSE,FALSE,DP2_RESULT_REG));
13630 emitcode ("mov","dph,%s",
13631 aopGet(fp,1,FALSE,FALSE,DP2_RESULT_REG));
13632 emitcode ("mov","dpx,%s",
13633 aopGet(fp,2,FALSE,FALSE,DP2_RESULT_REG));
13635 freeAsmop (fp, NULL, ic, FALSE);
13637 emitcode ("lcall","System_%sPoll",name);
13639 /* put result into place */
13641 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13642 if (rsym->liveFrom != rsym->liveTo) {
13643 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13644 aopPut(IC_RESULT(ic),"a",0);
13645 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13648 unsavermask(rsave);
13651 /*-----------------------------------------------------------------*/
13652 /* genSystemGetCurrentID - */
13653 /*-----------------------------------------------------------------*/
13654 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
13656 assert (nparms==0);
13658 emitcode ("lcall","System_GetCurrent%sId",name);
13659 /* put result into place */
13661 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13662 if (rsym->liveFrom != rsym->liveTo) {
13663 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13664 aopPut(IC_RESULT(ic),"a",0);
13665 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13670 /*-----------------------------------------------------------------*/
13671 /* genDjnz - generate decrement & jump if not zero instrucion */
13672 /*-----------------------------------------------------------------*/
13674 genDjnz (iCode * ic, iCode * ifx)
13676 symbol *lbl, *lbl1;
13680 /* if the if condition has a false label
13681 then we cannot save */
13682 if (IC_FALSE (ifx))
13685 /* if the minus is not of the form a = a - 1 */
13686 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
13687 !IS_OP_LITERAL (IC_RIGHT (ic)))
13690 if (operandLitValue (IC_RIGHT (ic)) != 1)
13693 /* if the size of this greater than one then no
13695 if (getSize (operandType (IC_RESULT (ic))) > 1)
13698 /* otherwise we can save BIG */
13700 D (emitcode (";", "genDjnz"));
13702 lbl = newiTempLabel (NULL);
13703 lbl1 = newiTempLabel (NULL);
13705 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
13707 if (AOP_NEEDSACC(IC_RESULT(ic)))
13709 /* If the result is accessed indirectly via
13710 * the accumulator, we must explicitly write
13711 * it back after the decrement.
13713 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE, NULL);
13715 if (strcmp(rByte, "a"))
13717 /* Something is hopelessly wrong */
13718 fprintf(stderr, "*** warning: internal error at %s:%d\n",
13719 __FILE__, __LINE__);
13720 /* We can just give up; the generated code will be inefficient,
13721 * but what the hey.
13723 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13726 emitcode ("dec", "%s", rByte);
13727 aopPut (IC_RESULT (ic), rByte, 0);
13728 emitcode ("jnz", "!tlabel", lbl->key + 100);
13730 else if (IS_AOP_PREG (IC_RESULT (ic)))
13732 emitcode ("dec", "%s",
13733 aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL));
13734 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL));
13735 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13736 ifx->generated = 1;
13737 emitcode ("jnz", "!tlabel", lbl->key + 100);
13741 emitcode ("djnz", "%s,!tlabel", aopGet (IC_RESULT (ic), 0, FALSE, TRUE, NULL),
13744 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
13746 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
13749 if (!ifx->generated)
13750 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13751 ifx->generated = 1;
13755 /*-----------------------------------------------------------------*/
13756 /* genReceive - generate code for a receive iCode */
13757 /*-----------------------------------------------------------------*/
13759 genReceive (iCode * ic)
13761 int size = getSize (operandType (IC_RESULT (ic)));
13765 D (emitcode (";", "genReceive"));
13767 if (ic->argreg == 1)
13769 /* first parameter */
13770 if (AOP_IS_STR(IC_RESULT(ic)))
13772 /* Nothing to do: it's already in the proper place. */
13779 useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
13780 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
13781 IS_TRUE_SYMOP (IC_RESULT (ic)));
13784 aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
13787 /* Sanity checking... */
13788 if (AOP_USESDPTR(IC_RESULT(ic)))
13790 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
13791 "genReceive got unexpected DPTR.");
13793 assignResultValue (IC_RESULT (ic), NULL);
13796 else if (ic->argreg > 12)
13797 { /* bit parameters */
13798 if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
13800 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
13801 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
13802 outBitC(IC_RESULT (ic));
13807 /* second receive onwards */
13808 /* this gets a little tricky since unused receives will be
13809 eliminated, we have saved the reg in the type field . and
13810 we use that to figure out which register to use */
13811 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
13812 rb1off = ic->argreg;
13815 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
13818 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13821 /*-----------------------------------------------------------------*/
13822 /* genDummyRead - generate code for dummy read of volatiles */
13823 /*-----------------------------------------------------------------*/
13825 genDummyRead (iCode * ic)
13830 D (emitcode(";", "genDummyRead"));
13832 op = IC_RIGHT (ic);
13833 if (op && IS_SYMOP (op))
13835 aopOp (op, ic, FALSE, FALSE);
13837 /* if the result is a bit */
13838 if (AOP_TYPE (op) == AOP_CRY)
13839 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13842 /* bit variables done */
13844 size = AOP_SIZE (op);
13848 MOVA (aopGet (op, offset, FALSE, FALSE, FALSE));
13853 freeAsmop (op, NULL, ic, TRUE);
13857 if (op && IS_SYMOP (op))
13859 aopOp (op, ic, FALSE, FALSE);
13861 /* if the result is a bit */
13862 if (AOP_TYPE (op) == AOP_CRY)
13863 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13866 /* bit variables done */
13868 size = AOP_SIZE (op);
13872 MOVA (aopGet (op, offset, FALSE, FALSE, FALSE));
13877 freeAsmop (op, NULL, ic, TRUE);
13881 /*-----------------------------------------------------------------*/
13882 /* genCritical - generate code for start of a critical sequence */
13883 /*-----------------------------------------------------------------*/
13885 genCritical (iCode *ic)
13887 symbol *tlbl = newiTempLabel (NULL);
13889 D (emitcode(";", "genCritical"));
13891 if (IC_RESULT (ic))
13893 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
13894 aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
13895 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
13896 aopPut (IC_RESULT (ic), zero, 0);
13898 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13902 emitcode ("setb", "c");
13903 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
13904 emitcode ("clr", "c");
13906 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
13910 /*-----------------------------------------------------------------*/
13911 /* genEndCritical - generate code for end of a critical sequence */
13912 /*-----------------------------------------------------------------*/
13914 genEndCritical (iCode *ic)
13916 D(emitcode("; genEndCritical",""));
13920 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
13921 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
13923 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
13924 emitcode ("mov", "ea,c");
13928 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE, FALSE));
13929 emitcode ("rrc", "a");
13930 emitcode ("mov", "ea,c");
13932 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
13936 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
13937 emitcode ("mov", "ea,c");
13943 /*-----------------------------------------------------------------*/
13944 /* genBuiltIn - calls the appropriate function to generating code */
13945 /* for a built in function */
13946 /*-----------------------------------------------------------------*/
13947 static void genBuiltIn (iCode *ic)
13949 operand *bi_parms[MAX_BUILTIN_ARGS];
13954 /* get all the arguments for a built in function */
13955 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
13957 /* which function is it */
13958 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
13959 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
13960 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
13961 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
13962 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
13963 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
13964 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
13965 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
13966 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
13967 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
13968 genMemsetX(bi_iCode,nbi_parms,bi_parms);
13969 } else if (strcmp(bif->name,"__builtin_inp")==0) {
13970 genInp(bi_iCode,nbi_parms,bi_parms);
13971 } else if (strcmp(bif->name,"__builtin_outp")==0) {
13972 genOutp(bi_iCode,nbi_parms,bi_parms);
13973 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
13974 genSwapW(bi_iCode,nbi_parms,bi_parms);
13975 /* JavaNative builtIns */
13976 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
13977 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
13978 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
13979 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
13980 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
13981 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
13982 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
13983 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
13984 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
13985 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
13986 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
13987 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
13988 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
13989 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
13990 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
13991 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
13992 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
13993 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
13994 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
13995 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
13996 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
13997 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
13998 } else if (strcmp(bif->name,"MM_Malloc")==0) {
13999 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
14000 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
14001 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
14002 } else if (strcmp(bif->name,"MM_Free")==0) {
14003 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
14004 } else if (strcmp(bif->name,"MM_Deref")==0) {
14005 genMMDeref(bi_iCode,nbi_parms,bi_parms);
14006 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
14007 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
14008 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
14009 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
14010 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
14011 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
14012 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
14013 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
14014 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
14015 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
14016 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
14017 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
14018 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
14019 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
14020 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
14021 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
14022 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
14023 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
14024 } else if (strcmp(bif->name,"System_SaveThread")==0) {
14025 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
14026 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
14027 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
14028 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
14029 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
14030 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
14031 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
14032 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
14033 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
14034 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
14035 genSystem(bi_iCode,nbi_parms,"ProcessYield");
14036 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
14037 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
14038 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
14039 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
14040 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
14041 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
14042 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
14043 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
14044 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
14045 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
14047 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
14053 /*-----------------------------------------------------------------*/
14054 /* gen390Code - generate code for Dallas 390 based controllers */
14055 /*-----------------------------------------------------------------*/
14057 gen390Code (iCode * lic)
14062 _G.currentFunc = NULL;
14063 lineHead = lineCurr = NULL;
14064 dptrn[1][0] = "dpl1";
14065 dptrn[1][1] = "dph1";
14066 dptrn[1][2] = "dpx1";
14068 if (options.model == MODEL_FLAT24) {
14069 fReturnSizeDS390 = 5;
14070 fReturn = fReturn24;
14072 fReturnSizeDS390 = 4;
14073 fReturn = fReturn16;
14074 options.stack10bit=0;
14077 /* print the allocation information */
14078 if (allocInfo && currFunc)
14079 printAllocInfo (currFunc, codeOutFile);
14081 /* if debug information required */
14082 if (options.debug && currFunc)
14084 debugFile->writeFunction (currFunc, lic);
14086 /* stack pointer name */
14087 if (options.useXstack)
14093 for (ic = lic; ic; ic = ic->next)
14095 _G.current_iCode = ic;
14097 if (ic->lineno && cln != ic->lineno)
14101 debugFile->writeCLine (ic);
14103 if (!options.noCcodeInAsm) {
14104 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
14105 printCLine(ic->filename, ic->lineno));
14109 if (options.iCodeInAsm) {
14110 emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
14112 /* if the result is marked as
14113 spilt and rematerializable or code for
14114 this has already been generated then
14116 if (resultRemat (ic) || ic->generated)
14119 /* depending on the operation */
14139 /* IPOP happens only when trying to restore a
14140 spilt live range, if there is an ifx statement
14141 following this pop then the if statement might
14142 be using some of the registers being popped which
14143 would destory the contents of the register so
14144 we need to check for this condition and handle it */
14146 ic->next->op == IFX &&
14147 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
14148 genIfx (ic->next, ic);
14166 genEndFunction (ic);
14186 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
14203 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
14207 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
14214 /* note these two are xlated by algebraic equivalence
14215 during parsing SDCC.y */
14216 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
14217 "got '>=' or '<=' shouldn't have come here");
14221 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
14233 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
14237 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
14241 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
14265 genRightShift (ic);
14268 case GET_VALUE_AT_ADDRESS:
14270 hasInc (IC_LEFT (ic), ic,
14271 getSize (operandType (IC_RESULT (ic)))));
14275 if (POINTER_SET (ic))
14277 hasInc (IC_RESULT (ic), ic,
14278 getSize (operandType (IC_RIGHT (ic)))));
14304 if (ic->builtinSEND)
14307 addSet (&_G.sendSet, ic);
14310 case DUMMY_READ_VOLATILE:
14319 genEndCritical (ic);
14326 #if 0 // obsolete, and buggy for != xdata
14338 /* now we are ready to call the
14339 peep hole optimizer */
14340 if (!options.nopeep)
14341 peepHole (&lineHead);
14343 /* now do the actual printing */
14344 printLine (lineHead, codeOutFile);