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);
253 /*-----------------------------------------------------------------*/
254 /* ds390_emitDebuggerSymbol - associate the current code location */
255 /* with a debugger symbol */
256 /*-----------------------------------------------------------------*/
258 ds390_emitDebuggerSymbol (char * debugSym)
261 emitcode ("", "%s ==.", debugSym);
265 /*-----------------------------------------------------------------*/
266 /* mova - moves specified value into accumulator */
267 /*-----------------------------------------------------------------*/
271 /* do some early peephole optimization */
272 if (!strncmp(x, "a", 2) || !strncmp(x, "acc", 4))
275 emitcode("mov", "a,%s", x);
278 /*-----------------------------------------------------------------*/
279 /* movb - moves specified value into register b */
280 /*-----------------------------------------------------------------*/
284 /* do some early peephole optimization */
285 if (!strncmp(x, "b", 2))
288 emitcode("mov","b,%s", x);
291 /*-----------------------------------------------------------------*/
292 /* movc - moves specified value into the carry */
293 /*-----------------------------------------------------------------*/
301 else if (strcmp (s, "c"))
302 {/* it's not in carry already */
304 /* set C, if a >= 1 */
305 emitcode ("add", "a,#0xff");
309 /*-----------------------------------------------------------------*/
310 /* pushB - saves register B if necessary */
311 /*-----------------------------------------------------------------*/
315 bool pushedB = FALSE;
319 emitcode ("push", "b");
320 // printf("B was in use !\n");
330 /*-----------------------------------------------------------------*/
331 /* popB - restores value of register B if necessary */
332 /*-----------------------------------------------------------------*/
338 emitcode ("pop", "b");
346 /*-----------------------------------------------------------------*/
347 /* pushReg - saves register */
348 /*-----------------------------------------------------------------*/
350 pushReg (int index, bool bits_pushed)
352 regs * reg = REG_WITH_INDEX (index);
353 if (reg->type == REG_BIT)
356 emitcode ("push", "%s", reg->base);
360 emitcode ("push", "%s", reg->dname);
364 /*-----------------------------------------------------------------*/
365 /* popReg - restores register */
366 /*-----------------------------------------------------------------*/
368 popReg (int index, bool bits_popped)
370 regs * reg = REG_WITH_INDEX (index);
371 if (reg->type == REG_BIT)
374 emitcode ("pop", "%s", reg->base);
378 emitcode ("pop", "%s", reg->dname);
382 /*-----------------------------------------------------------------*/
383 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
384 /*-----------------------------------------------------------------*/
386 getFreePtr (iCode * ic, asmop ** aopp, bool result)
391 /* the logic: if r0 & r1 used in the instruction
392 then we are in trouble otherwise */
394 /* first check if r0 & r1 are used by this
395 instruction, in which case we are in trouble */
396 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
397 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
402 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
403 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
405 /* if no usage of r0 then return it */
408 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
409 (*aopp)->type = AOP_R0;
411 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
414 /* if no usage of r1 then return it */
417 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
418 (*aopp)->type = AOP_R1;
420 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R1_IDX);
423 /* now we know they both have usage */
424 /* if r0 not used in this instruction */
427 /* push it if not already pushed */
430 emitcode ("push", "%s",
431 REG_WITH_INDEX (R0_IDX)->dname);
435 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
436 (*aopp)->type = AOP_R0;
438 return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
441 /* if r1 not used then */
445 /* push it if not already pushed */
448 emitcode ("push", "%s",
449 REG_WITH_INDEX (R1_IDX)->dname);
453 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
454 (*aopp)->type = AOP_R1;
455 return REG_WITH_INDEX (R1_IDX);
459 /* I said end of world, but not quite end of world yet */
460 /* if this is a result then we can push it on the stack */
463 (*aopp)->type = AOP_STK;
467 /* now this is REALLY the end of the world */
468 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
469 "getFreePtr should never reach here");
472 return NULL; // notreached, but makes compiler happy.
476 /*-----------------------------------------------------------------*/
477 /* genSetDPTR: generate code to select which DPTR is in use (zero */
478 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */
479 /* alternate DPTR (DPL1/DPH1/DPX1). */
480 /*-----------------------------------------------------------------*/
485 /* If we are doing lazy evaluation, simply note the desired
486 * change, but don't emit any code yet.
496 emitcode ("mov", "dps,#0");
501 emitcode ("mov", "dps,#1");
505 /*------------------------------------------------------------------*/
506 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
508 /* Any code that operates on DPTR (NB: not on the individual */
509 /* components, like DPH) *must* call _flushLazyDPS() before using */
510 /* DPTR within a lazy DPS evaluation block. */
512 /* Note that aopPut and aopGet already contain the proper calls to */
513 /* _flushLazyDPS, so it is safe to use these calls within a lazy */
514 /* DPS evaluation block. */
516 /* Also, _flushLazyDPS must be called before any flow control */
517 /* operations that could potentially branch out of the block. */
519 /* Lazy DPS evaluation is simply an optimization (though an */
520 /* important one), so if in doubt, leave it out. */
521 /*------------------------------------------------------------------*/
523 _startLazyDPSEvaluation (void)
527 #ifdef BETTER_LITERAL_SHIFT
534 /*------------------------------------------------------------------*/
535 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
536 /* desired one. Call before using DPTR within a lazy DPS evaluation */
538 /*------------------------------------------------------------------*/
548 if (_desiredDPS != _currentDPS)
552 emitcode ("inc", "dps");
556 emitcode ("dec", "dps");
558 _currentDPS = _desiredDPS;
562 /*-----------------------------------------------------------------*/
563 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
565 /* Forces us back to the safe state (standard DPTR selected). */
566 /*-----------------------------------------------------------------*/
568 _endLazyDPSEvaluation (void)
570 #ifdef BETTER_LITERAL_SHIFT
588 /*-----------------------------------------------------------------*/
589 /* newAsmop - creates a new asmOp */
590 /*-----------------------------------------------------------------*/
592 newAsmop (short type)
596 aop = Safe_calloc (1, sizeof (asmop));
602 /*-----------------------------------------------------------------*/
603 /* pointerCode - returns the code for a pointer type */
604 /*-----------------------------------------------------------------*/
606 pointerCode (sym_link * etype)
609 return PTR_TYPE (SPEC_OCLS (etype));
613 /*-----------------------------------------------------------------*/
614 /* leftRightUseAcc - returns size of accumulator use by operands */
615 /*-----------------------------------------------------------------*/
617 leftRightUseAcc(iCode *ic)
626 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
627 "null iCode pointer");
634 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
637 size = getSize (OP_SYMBOL (op)->type);
642 else if (ic->op == JUMPTABLE)
645 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
648 size = getSize (OP_SYMBOL (op)->type);
656 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
659 size = getSize (OP_SYMBOL (op)->type);
664 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
667 size = getSize (OP_SYMBOL (op)->type);
679 /*-----------------------------------------------------------------*/
680 /* aopForSym - for a true symbol */
681 /*-----------------------------------------------------------------*/
683 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
687 bool accuse = leftRightUseAcc (ic) || _G.accInUse;
688 char *dpl = useDP2 ? "dpl1" : "dpl";
689 char *dph = useDP2 ? "dph1" : "dph";
690 char *dpx = useDP2 ? "dpx1" : "dpx";
692 wassertl (ic != NULL, "Got a null iCode");
693 wassertl (sym != NULL, "Got a null symbol");
695 space = SPEC_OCLS (sym->etype);
697 /* if already has one */
700 if ((sym->aop->type == AOP_DPTR && useDP2)
701 || (sym->aop->type == AOP_DPTR2 && !useDP2))
705 sym->aop->allocated++;
710 /* assign depending on the storage class */
711 /* if it is on the stack or indirectly addressable */
712 /* space we need to assign either r0 or r1 to it */
713 if ((sym->onStack && !options.stack10bit) || sym->iaccess)
715 sym->aop = aop = newAsmop (0);
716 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
717 aop->size = getSize (sym->type);
719 /* now assign the address of the variable to
720 the pointer register */
721 if (aop->type != AOP_STK)
725 char offset = ((sym->stack < 0) ?
726 ((char) (sym->stack - _G.nRegsSaved)) :
727 ((char) sym->stack)) & 0xff;
729 if ((abs(offset) <= 3) ||
730 (accuse && (abs(offset) <= 7)))
732 emitcode ("mov", "%s,_bp",
733 aop->aopu.aop_ptr->name);
736 emitcode ("dec", aop->aopu.aop_ptr->name);
741 emitcode ("inc", aop->aopu.aop_ptr->name);
748 emitcode ("push", "acc");
749 emitcode ("mov", "a,_bp");
750 emitcode ("add", "a,#!constbyte", offset);
751 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
753 emitcode ("pop", "acc");
758 emitcode ("mov", "%s,#%s",
759 aop->aopu.aop_ptr->name,
762 aop->paged = space->paged;
765 aop->aopu.aop_stk = sym->stack;
769 if (sym->onStack && options.stack10bit)
771 short stack_val = -((sym->stack < 0) ?
772 ((short) (sym->stack - _G.nRegsSaved)) :
773 ((short) sym->stack)) ;
775 emitcode ("push",dpl);
776 emitcode ("push",dph);
777 emitcode ("push",dpx);
779 /* It's on the 10 bit stack, which is located in
782 if (stack_val < 0 && stack_val > -5)
783 { /* between -5 & -1 */
784 if (options.model == MODEL_FLAT24)
786 emitcode ("mov", "%s,#!constbyte", dpx,
787 (options.stack_loc >> 16) & 0xff);
789 emitcode ("mov", "%s,_bpx+1", dph);
790 emitcode ("mov", "%s,_bpx", dpl);
792 emitcode ("mov","dps,#1");
794 stack_val = -stack_val;
795 while (stack_val--) {
796 emitcode ("inc","dptr");
799 emitcode("mov","dps,#0");
805 emitcode ("push", "acc");
807 emitcode ("mov", "a,_bpx");
808 emitcode ("clr","c");
809 emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
810 emitcode ("mov","%s,a", dpl);
811 emitcode ("mov","a,_bpx+1");
812 emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
813 emitcode ("mov", "%s,a", dph);
814 if (options.model == MODEL_FLAT24)
816 emitcode ("mov", "%s,#!constbyte", dpx,
817 (options.stack_loc >> 16) & 0xff);
821 emitcode ("pop", "acc");
823 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
824 aop->size = getSize (sym->type);
828 /* if in bit space */
829 if (IN_BITSPACE (space))
831 sym->aop = aop = newAsmop (AOP_CRY);
832 aop->aopu.aop_dir = sym->rname;
833 aop->size = getSize (sym->type);
836 /* if it is in direct space */
837 if (IN_DIRSPACE (space))
839 sym->aop = aop = newAsmop (AOP_DIR);
840 aop->aopu.aop_dir = sym->rname;
841 aop->size = getSize (sym->type);
845 /* special case for a function */
846 if (IS_FUNC (sym->type) && !(sym->isitmp))
848 sym->aop = aop = newAsmop (AOP_IMMD);
849 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
850 aop->size = FPTRSIZE;
854 /* only remaining is far space */
855 /* in which case DPTR gets the address */
856 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
861 emitcode ("mov", "dptr,#%s", sym->rname);
866 emitcode ("mov", "dptr,#%s", sym->rname);
868 aop->size = getSize (sym->type);
870 /* if it is in code space */
871 if (IN_CODESPACE (space))
877 /*-----------------------------------------------------------------*/
878 /* aopForRemat - rematerialzes an object */
879 /*-----------------------------------------------------------------*/
881 aopForRemat (symbol * sym)
883 iCode *ic = sym->rematiCode;
884 asmop *aop = newAsmop (AOP_IMMD);
891 val += (int) operandLitValue (IC_RIGHT (ic));
892 else if (ic->op == '-')
893 val -= (int) operandLitValue (IC_RIGHT (ic));
894 else if (IS_CAST_ICODE(ic)) {
895 sym_link *from_type = operandType(IC_RIGHT(ic));
896 aop->aopu.aop_immd.from_cast_remat = 1;
897 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
898 ptr_type = pointerTypeToGPByte (DCL_TYPE(from_type), NULL, NULL);
902 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
907 SNPRINTF (buffer, sizeof(buffer),
909 OP_SYMBOL (IC_LEFT (ic))->rname,
910 val >= 0 ? '+' : '-',
911 abs (val) & 0xffffff);
915 if (IS_ASSIGN_ICODE(ic) && isOperandLiteral(IC_RIGHT(ic)))
917 SNPRINTF(buffer, sizeof(buffer),
918 "0x%x",(int) operandLitValue (IC_RIGHT (ic)));
922 strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
926 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
927 /* set immd2 field if required */
928 if (aop->aopu.aop_immd.from_cast_remat)
930 tsprintf(buffer, sizeof(buffer), "#!constbyte",ptr_type);
931 aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
937 /*-----------------------------------------------------------------*/
938 /* aopHasRegs - returns true if aop has regs between from-to */
939 /*-----------------------------------------------------------------*/
940 static int aopHasRegs(asmop *aop, int from, int to)
944 if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
946 for (; size < aop->size ; size++) {
948 for (reg = from ; reg <= to ; reg++)
949 if (aop->aopu.aop_reg[size] == REG_WITH_INDEX(reg)) return 1;
954 /*-----------------------------------------------------------------*/
955 /* regsInCommon - two operands have some registers in common */
956 /*-----------------------------------------------------------------*/
958 regsInCommon (operand * op1, operand * op2)
963 /* if they have registers in common */
964 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
967 sym1 = OP_SYMBOL (op1);
968 sym2 = OP_SYMBOL (op2);
970 if (sym1->nRegs == 0 || sym2->nRegs == 0)
973 for (i = 0; i < sym1->nRegs; i++)
979 for (j = 0; j < sym2->nRegs; j++)
984 if (sym2->regs[j] == sym1->regs[i])
992 /*-----------------------------------------------------------------*/
993 /* operandsEqu - equivalent */
994 /*-----------------------------------------------------------------*/
996 operandsEqu (operand * op1, operand * op2)
1000 /* if they're not symbols */
1001 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
1004 sym1 = OP_SYMBOL (op1);
1005 sym2 = OP_SYMBOL (op2);
1007 /* if both are itemps & one is spilt
1008 and the other is not then false */
1009 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
1010 sym1->isspilt != sym2->isspilt)
1013 /* if they are the same */
1017 /* if they have the same rname */
1018 if (sym1->rname[0] && sym2->rname[0] &&
1019 strcmp (sym1->rname, sym2->rname) == 0 &&
1020 !(IS_PARM (op2) && IS_ITEMP (op1)))
1023 /* if left is a tmp & right is not */
1024 if (IS_ITEMP (op1) &&
1027 (sym1->usl.spillLoc == sym2))
1030 if (IS_ITEMP (op2) &&
1034 (sym2->usl.spillLoc == sym1))
1037 /* are they spilt to the same location */
1038 if (IS_ITEMP (op2) &&
1042 (sym1->usl.spillLoc == sym2->usl.spillLoc))
1048 /*-----------------------------------------------------------------*/
1049 /* sameRegs - two asmops have the same registers */
1050 /*-----------------------------------------------------------------*/
1052 sameRegs (asmop * aop1, asmop * aop2)
1058 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
1065 if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
1068 if (aop1->type != aop2->type)
1071 if (aop1->size != aop2->size)
1074 for (i = 0; i < aop1->size; i++)
1075 if (aop1->aopu.aop_reg[i] != aop2->aopu.aop_reg[i])
1081 /*-----------------------------------------------------------------*/
1082 /* aopOp - allocates an asmop for an operand : */
1083 /*-----------------------------------------------------------------*/
1085 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
1094 /* if this a literal */
1095 if (IS_OP_LITERAL (op))
1097 op->aop = aop = newAsmop (AOP_LIT);
1098 aop->aopu.aop_lit = op->operand.valOperand;
1099 aop->size = getSize (operandType (op));
1103 /* if already has a asmop then continue */
1106 if ((op->aop->type == AOP_DPTR && useDP2)
1107 || (op->aop->type == AOP_DPTR2 && !useDP2))
1111 op->aop->allocated++;
1116 /* if the underlying symbol has a aop */
1117 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
1119 op->aop = OP_SYMBOL (op)->aop;
1120 if ((op->aop->type == AOP_DPTR && useDP2)
1121 || (op->aop->type == AOP_DPTR2 && !useDP2))
1125 op->aop->allocated++;
1130 /* if this is a true symbol */
1131 if (IS_TRUE_SYMOP (op))
1133 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
1137 /* this is a temporary : this has
1143 e) can be a return use only */
1145 sym = OP_SYMBOL (op);
1147 /* if the type is a conditional */
1148 if (sym->regType == REG_CND)
1150 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
1155 /* if it is spilt then two situations
1157 b) has a spill location */
1158 if (sym->isspilt || sym->nRegs == 0)
1161 /* rematerialize it NOW */
1164 sym->aop = op->aop = aop =
1166 aop->size = getSize (sym->type);
1173 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
1174 aop->size = getSize (sym->type);
1175 for (i = 0; i < 2; i++)
1176 aop->aopu.aop_str[i] = accUse[i];
1186 /* a AOP_STR uses DPTR, but DPTR is already in use;
1189 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
1192 aop = op->aop = sym->aop = newAsmop (AOP_STR);
1193 aop->size = getSize (sym->type);
1194 for (i = 0; i < fReturnSizeDS390; i++)
1195 aop->aopu.aop_str[i] = fReturn[i];
1199 if (sym->dptr) { /* has been allocated to a DPTRn */
1200 aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
1201 aop->size = getSize (sym->type);
1202 aop->aopu.dptr = sym->dptr;
1206 if (sym->usl.spillLoc)
1208 asmop *oldAsmOp = NULL;
1210 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1212 /* force a new aop if sizes differ */
1213 oldAsmOp = sym->usl.spillLoc->aop;
1214 sym->usl.spillLoc->aop = NULL;
1216 sym->aop = op->aop = aop =
1217 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
1218 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1220 /* Don't reuse the new aop, go with the last one */
1221 sym->usl.spillLoc->aop = oldAsmOp;
1223 aop->size = getSize (sym->type);
1227 /* else must be a dummy iTemp */
1228 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1229 aop->size = getSize (sym->type);
1233 /* if the type is a bit register */
1234 if (sym->regType == REG_BIT)
1236 sym->aop = op->aop = aop = newAsmop (AOP_CRY);
1237 aop->size = sym->nRegs;//1???
1238 aop->aopu.aop_reg[0] = sym->regs[0];
1239 aop->aopu.aop_dir = sym->regs[0]->name;
1243 /* must be in a register */
1244 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1245 aop->size = sym->nRegs;
1246 for (i = 0; i < sym->nRegs; i++)
1247 aop->aopu.aop_reg[i] = sym->regs[i];
1250 /*-----------------------------------------------------------------*/
1251 /* freeAsmop - free up the asmop given to an operand */
1252 /*----------------------------------------------------------------*/
1254 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1271 /* depending on the asmop type only three cases need work
1272 AOP_R0, AOP_R1 & AOP_STK */
1280 emitcode ("pop", "ar0");
1284 bitVectUnSetBit (ic->rUsed, R0_IDX);
1292 emitcode ("pop", "ar1");
1296 bitVectUnSetBit (ic->rUsed, R1_IDX);
1302 int stk = aop->aopu.aop_stk + aop->size;
1303 bitVectUnSetBit (ic->rUsed, R0_IDX);
1304 bitVectUnSetBit (ic->rUsed, R1_IDX);
1306 getFreePtr (ic, &aop, FALSE);
1308 if (options.stack10bit)
1310 /* I'm not sure what to do here yet... */
1313 "*** Warning: probably generating bad code for "
1314 "10 bit stack mode.\n");
1319 emitcode ("mov", "a,_bp");
1320 emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
1321 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1325 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1330 emitcode ("pop", "acc");
1331 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1334 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1337 freeAsmop (op, NULL, ic, TRUE);
1340 emitcode ("pop", "ar1");
1345 emitcode ("pop", "ar0");
1350 if (_G.dptr1InUse) {
1351 emitcode ("pop","dpx1");
1352 emitcode ("pop","dph1");
1353 emitcode ("pop","dpl1");
1358 emitcode ("pop","dpx");
1359 emitcode ("pop","dph");
1360 emitcode ("pop","dpl");
1366 /* all other cases just dealloc */
1372 OP_SYMBOL (op)->aop = NULL;
1373 /* if the symbol has a spill */
1375 SPIL_LOC (op)->aop = NULL;
1380 #define DEFAULT_ACC_WARNING 0
1381 static int saveAccWarn = DEFAULT_ACC_WARNING;
1384 /*-----------------------------------------------------------------*/
1385 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
1386 /* clobber the accumulator */
1387 /*-----------------------------------------------------------------*/
1389 aopGetUsesAcc (operand * oper, int offset)
1391 asmop * aop = AOP (oper);
1393 if (offset > (aop->size - 1))
1411 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1422 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1428 /* Error case --- will have been caught already */
1434 /*-------------------------------------------------------------------*/
1435 /* aopGet - for fetching value of the aop */
1437 /* Set saveAcc to NULL if you are sure it is OK to clobber the value */
1438 /* in the accumulator. Set it to the name of a free register */
1439 /* if acc must be preserved; the register will be used to preserve */
1440 /* acc temporarily and to return the result byte. */
1441 /*-------------------------------------------------------------------*/
1443 aopGet (operand * oper,
1449 asmop * aop = AOP (oper);
1451 /* offset is greater than
1453 if (offset > (aop->size - 1) &&
1454 aop->type != AOP_LIT)
1457 /* depending on type */
1465 /* if we need to increment it */
1466 while (offset > aop->coff)
1468 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1472 while (offset < aop->coff)
1474 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1481 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1482 return (dname ? "acc" : "a");
1484 SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1485 return Safe_strdup(buffer);
1488 assert(offset <= 3);
1489 return dptrn[aop->aopu.dptr][offset];
1494 if (aop->type == AOP_DPTR2)
1502 // if (aop->type != AOP_DPTR2)
1504 // if (saveAccWarn) { fprintf(stderr, "saveAcc for DPTR...\n"); }
1505 // emitcode(";", "spanky: saveAcc for DPTR");
1508 emitcode ("xch", "a, %s", saveAcc);
1513 while (offset > aop->coff)
1515 emitcode ("inc", "dptr");
1519 while (offset < aop->coff)
1521 emitcode ("lcall", "__decdptr");
1528 emitcode ("clr", "a");
1529 emitcode ("movc", "a,@a+dptr");
1533 emitcode ("movx", "a,@dptr");
1536 if (aop->type == AOP_DPTR2)
1544 emitcode ("xch", "a, %s", saveAcc);
1545 // if (strcmp(saveAcc, "_ap"))
1547 // emitcode(";", "spiffy: non _ap return from aopGet.");
1552 return (dname ? "acc" : "a");
1555 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1557 SNPRINTF(buffer, sizeof(buffer),
1558 "%s",aop->aopu.aop_immd.aop_immd2);
1562 SNPRINTF(buffer, sizeof(buffer),
1563 "#%s", aop->aopu.aop_immd.aop_immd1);
1569 tsprintf(buffer, sizeof(buffer),
1570 "#!his",aop->aopu.aop_immd.aop_immd1);
1573 tsprintf(buffer, sizeof(buffer),
1574 "#!hihis",aop->aopu.aop_immd.aop_immd1);
1577 tsprintf(buffer, sizeof(buffer),
1578 "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1580 default: /* should not need this (just in case) */
1581 SNPRINTF (buffer, sizeof(buffer),
1583 aop->aopu.aop_immd.aop_immd1,
1589 SNPRINTF (buffer, sizeof(buffer),
1590 "#%s", aop->aopu.aop_immd.aop_immd1);
1592 return Safe_strdup(buffer);
1595 if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
1597 SNPRINTF (buffer, sizeof(buffer),
1599 aop->aopu.aop_dir, offset * 8);
1603 SNPRINTF (buffer, sizeof(buffer),
1610 SNPRINTF (buffer, sizeof(buffer),
1611 "%s", aop->aopu.aop_dir);
1614 return Safe_strdup(buffer);
1618 return aop->aopu.aop_reg[offset]->dname;
1620 return aop->aopu.aop_reg[offset]->name;
1623 emitcode ("clr", "a");
1624 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1625 emitcode ("rlc", "a");
1626 return (dname ? "acc" : "a");
1629 if (!offset && dname)
1631 return aop->aopu.aop_str[offset];
1634 return aopLiteral (aop->aopu.aop_lit, offset);
1638 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1642 return aop->aopu.aop_str[offset];
1646 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1647 "aopget got unsupported aop->type");
1650 return NULL; // not reached, but makes compiler happy.
1653 /*-----------------------------------------------------------------*/
1654 /* aopPutUsesAcc - indicates ahead of time whether aopPut() will */
1655 /* clobber the accumulator */
1656 /*-----------------------------------------------------------------*/
1658 aopPutUsesAcc (operand * oper, const char *s, int offset)
1660 asmop * aop = AOP (oper);
1662 if (offset > (aop->size - 1))
1672 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1678 return ((aop->paged) || (*s == '@'));
1682 return (!aop->aopu.aop_dir || strcmp(s, aop->aopu.aop_dir));
1690 /* Error case --- will have been caught already */
1696 /*-----------------------------------------------------------------*/
1697 /* aopPut - puts a string for a aop and indicates if acc is in use */
1698 /*-----------------------------------------------------------------*/
1700 aopPut (operand * result, const char *s, int offset)
1702 bool bvolatile = isOperandVolatile (result, FALSE);
1703 bool accuse = FALSE;
1704 asmop * aop = AOP (result);
1706 if (aop->size && offset > (aop->size - 1))
1708 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1709 "aopPut got offset > aop->size");
1713 /* will assign value to value */
1714 /* depending on where it is ofcourse */
1718 MOVA (s); /* read s in case it was volatile */
1723 if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1725 SNPRINTF (buffer, sizeof(buffer),
1727 aop->aopu.aop_dir, offset * 8);
1731 SNPRINTF (buffer, sizeof(buffer),
1733 aop->aopu.aop_dir, offset);
1737 SNPRINTF (buffer, sizeof(buffer),
1738 "%s", aop->aopu.aop_dir);
1741 if (strcmp (buffer, s) || bvolatile)
1743 emitcode ("mov", "%s,%s", buffer, s);
1745 if (!strcmp (buffer, "acc"))
1752 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1753 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1756 strcmp (s, "r0") == 0 ||
1757 strcmp (s, "r1") == 0 ||
1758 strcmp (s, "r2") == 0 ||
1759 strcmp (s, "r3") == 0 ||
1760 strcmp (s, "r4") == 0 ||
1761 strcmp (s, "r5") == 0 ||
1762 strcmp (s, "r6") == 0 ||
1763 strcmp (s, "r7") == 0)
1765 emitcode ("mov", "%s,%s",
1766 aop->aopu.aop_reg[offset]->dname, s);
1770 emitcode ("mov", "%s,%s",
1771 aop->aopu.aop_reg[offset]->name, s);
1777 emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1783 if (aop->type == AOP_DPTR2)
1791 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1792 "aopPut writing to code space");
1796 while (offset > aop->coff)
1799 emitcode ("inc", "dptr");
1802 while (offset < aop->coff)
1805 emitcode ("lcall", "__decdptr");
1810 /* if not in accumulator */
1813 emitcode ("movx", "@dptr,a");
1815 if (aop->type == AOP_DPTR2)
1823 while (offset > aop->coff)
1826 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1828 while (offset < aop->coff)
1831 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1838 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1843 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1845 else if (strcmp (s, "r0") == 0 ||
1846 strcmp (s, "r1") == 0 ||
1847 strcmp (s, "r2") == 0 ||
1848 strcmp (s, "r3") == 0 ||
1849 strcmp (s, "r4") == 0 ||
1850 strcmp (s, "r5") == 0 ||
1851 strcmp (s, "r6") == 0 ||
1852 strcmp (s, "r7") == 0)
1855 SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1856 emitcode ("mov", "@%s,%s",
1857 aop->aopu.aop_ptr->name, buffer);
1861 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1866 if (strcmp (s, "a") == 0)
1867 emitcode ("push", "acc");
1871 emitcode ("push", "acc");
1873 emitcode ("push", s);
1879 /* if not bit variable */
1880 if (!aop->aopu.aop_dir)
1882 /* inefficient: move carry into A and use jz/jnz */
1883 emitcode ("clr", "a");
1884 emitcode ("rlc", "a");
1890 emitcode ("clr", "%s", aop->aopu.aop_dir);
1892 emitcode ("setb", "%s", aop->aopu.aop_dir);
1893 else if (!strcmp (s, "c"))
1894 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1895 else if (strcmp (s, aop->aopu.aop_dir))
1898 /* set C, if a >= 1 */
1899 emitcode ("add", "a,#!constbyte",0xff);
1900 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1907 if (strcmp (aop->aopu.aop_str[offset], s) || bvolatile)
1908 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1914 if (!offset && (strcmp (s, "acc") == 0) && !bvolatile)
1917 if (strcmp (aop->aopu.aop_str[offset], s) && !bvolatile)
1918 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1922 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1923 "aopPut got unsupported aop->type");
1931 /*--------------------------------------------------------------------*/
1932 /* reAdjustPreg - points a register back to where it should (coff==0) */
1933 /*--------------------------------------------------------------------*/
1935 reAdjustPreg (asmop * aop)
1937 if ((aop->coff==0) || (aop->size <= 1))
1945 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1949 if (aop->type == AOP_DPTR2)
1956 emitcode ("lcall", "__decdptr");
1959 if (aop->type == AOP_DPTR2)
1968 /*-----------------------------------------------------------------*/
1969 /* opIsGptr: returns non-zero if the passed operand is */
1970 /* a generic pointer type. */
1971 /*-----------------------------------------------------------------*/
1973 opIsGptr (operand * op)
1975 sym_link *type = operandType (op);
1977 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1984 /*-----------------------------------------------------------------*/
1985 /* getDataSize - get the operand data size */
1986 /*-----------------------------------------------------------------*/
1988 getDataSize (operand * op)
1991 size = AOP_SIZE (op);
1992 if (size == GPTRSIZE)
1994 sym_link *type = operandType (op);
1995 if (IS_GENPTR (type))
1997 /* generic pointer; arithmetic operations
1998 * should ignore the high byte (pointer type).
2006 /*-----------------------------------------------------------------*/
2007 /* outAcc - output Acc */
2008 /*-----------------------------------------------------------------*/
2010 outAcc (operand * result)
2013 size = getDataSize (result);
2016 aopPut (result, "a", 0);
2019 /* unsigned or positive */
2022 aopPut (result, zero, offset++);
2027 /*-----------------------------------------------------------------*/
2028 /* outBitC - output a bit C */
2029 /*-----------------------------------------------------------------*/
2031 outBitC (operand * result)
2033 /* if the result is bit */
2034 if (AOP_TYPE (result) == AOP_CRY)
2036 aopPut (result, "c", 0);
2040 emitcode ("clr", "a");
2041 emitcode ("rlc", "a");
2046 /*-----------------------------------------------------------------*/
2047 /* toBoolean - emit code for orl a,operator(sizeop) */
2048 /*-----------------------------------------------------------------*/
2050 toBoolean (operand * oper)
2052 int size = AOP_SIZE (oper) - 1;
2056 /* The generic part of a generic pointer should
2057 * not participate in it's truth value.
2059 * i.e. 0x10000000 is zero.
2061 if (opIsGptr (oper))
2063 D (emitcode (";", "toBoolean: generic ptr special case."));
2067 _startLazyDPSEvaluation ();
2068 MOVA (aopGet (oper, 0, FALSE, FALSE, NULL));
2069 if (AOP_NEEDSACC (oper) && size && (AOP (oper)->type != AOP_ACC))
2072 emitcode("mov", "b,a");
2075 MOVA (aopGet (oper, offset++, FALSE, FALSE, NULL));
2076 emitcode ("orl", "b,a");
2078 MOVA (aopGet (oper, offset++, FALSE, FALSE, NULL));
2079 emitcode ("orl", "a,b");
2086 emitcode ("orl", "a,%s",
2087 aopGet (oper, offset++, FALSE, FALSE, NULL));
2090 _endLazyDPSEvaluation ();
2094 /*-----------------------------------------------------------------*/
2095 /* genNot - generate code for ! operation */
2096 /*-----------------------------------------------------------------*/
2102 D (emitcode (";", "genNot "));
2104 /* assign asmOps to operand & result */
2105 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2106 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
2108 /* if in bit space then a special case */
2109 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2111 /* if left==result then cpl bit */
2112 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2114 emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2118 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2119 emitcode ("cpl", "c");
2120 outBitC (IC_RESULT (ic));
2125 toBoolean (IC_LEFT (ic));
2127 /* set C, if a == 0 */
2128 tlbl = newiTempLabel (NULL);
2129 emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
2130 emitcode ("", "!tlabeldef", tlbl->key + 100);
2131 outBitC (IC_RESULT (ic));
2134 /* release the aops */
2135 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2136 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2140 /*-----------------------------------------------------------------*/
2141 /* genCpl - generate code for complement */
2142 /*-----------------------------------------------------------------*/
2149 sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
2151 D(emitcode (";", "genCpl"));
2153 /* assign asmOps to operand & result */
2154 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2155 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
2157 /* special case if in bit space */
2158 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2162 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
2163 (SPEC_USIGN (letype) && IS_CHAR (letype)))
2165 /* promotion rules are responsible for this strange result:
2166 bit -> int -> ~int -> bit
2167 uchar -> int -> ~int -> bit
2169 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
2173 tlbl=newiTempLabel(NULL);
2174 l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE, NULL);
2175 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
2176 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
2177 IS_AOP_PREG (IC_LEFT (ic)))
2179 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
2184 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
2186 emitcode ("", "%05d$:", tlbl->key + 100);
2187 outBitC (IC_RESULT(ic));
2191 size = AOP_SIZE (IC_RESULT (ic));
2192 _startLazyDPSEvaluation ();
2195 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL);
2197 emitcode ("cpl", "a");
2198 aopPut (IC_RESULT (ic), "a", offset++);
2200 _endLazyDPSEvaluation ();
2204 /* release the aops */
2205 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2206 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2209 /*-----------------------------------------------------------------*/
2210 /* genUminusFloat - unary minus for floating points */
2211 /*-----------------------------------------------------------------*/
2213 genUminusFloat (operand * op, operand * result)
2215 int size, offset = 0;
2218 D(emitcode (";", "genUminusFloat"));
2220 /* for this we just copy and then flip the bit */
2222 _startLazyDPSEvaluation ();
2223 size = AOP_SIZE (op) - 1;
2228 aopGet (op, offset, FALSE, FALSE, NULL),
2233 l = aopGet (op, offset, FALSE, FALSE, NULL);
2236 emitcode ("cpl", "acc.7");
2237 aopPut (result, "a", offset);
2238 _endLazyDPSEvaluation ();
2241 /*-----------------------------------------------------------------*/
2242 /* genUminus - unary minus code generation */
2243 /*-----------------------------------------------------------------*/
2245 genUminus (iCode * ic)
2250 D (emitcode (";", "genUminus "));
2253 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2254 aopOp (IC_RESULT (ic), ic, TRUE, (AOP_TYPE(IC_LEFT (ic)) == AOP_DPTR));
2256 /* if both in bit space then special
2258 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2259 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2262 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2263 emitcode ("cpl", "c");
2264 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2268 optype = operandType (IC_LEFT (ic));
2270 /* if float then do float stuff */
2271 if (IS_FLOAT (optype))
2273 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2277 /* otherwise subtract from zero */
2278 size = AOP_SIZE (IC_LEFT (ic));
2280 _startLazyDPSEvaluation ();
2283 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL);
2284 if (!strcmp (l, "a"))
2288 emitcode ("cpl", "a");
2289 emitcode ("addc", "a,#0");
2295 emitcode ("clr", "a");
2296 emitcode ("subb", "a,%s", l);
2298 aopPut (IC_RESULT (ic), "a", offset++);
2300 _endLazyDPSEvaluation ();
2302 /* if any remaining bytes in the result */
2303 /* we just need to propagate the sign */
2304 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))) != 0)
2306 emitcode ("rlc", "a");
2307 emitcode ("subb", "a,acc");
2309 aopPut (IC_RESULT (ic), "a", offset++);
2313 /* release the aops */
2314 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2315 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2318 /*-----------------------------------------------------------------*/
2319 /* savermask - saves registers in the mask */
2320 /*-----------------------------------------------------------------*/
2321 static void savermask(bitVect *rs_mask)
2324 if (options.useXstack)
2326 if (bitVectBitValue (rs_mask, R0_IDX))
2327 emitcode ("mov", "b,r0");
2328 emitcode ("mov", "r0,%s", spname);
2329 for (i = 0; i < ds390_nRegs; i++)
2331 if (bitVectBitValue (rs_mask, i))
2334 emitcode ("mov", "a,b");
2336 emitcode ("mov", "a,%s", REG_WITH_INDEX (i)->name);
2337 emitcode ("movx", "@r0,a");
2338 emitcode ("inc", "r0");
2341 emitcode ("mov", "%s,r0", spname);
2342 if (bitVectBitValue (rs_mask, R0_IDX))
2343 emitcode ("mov", "r0,b");
2347 bool bits_pushed = FALSE;
2348 for (i = 0; i < ds390_nRegs; i++)
2350 if (bitVectBitValue (rs_mask, i))
2352 bits_pushed = pushReg (i, bits_pushed);
2358 /*-----------------------------------------------------------------*/
2359 /* saveRegisters - will look for a call and save the registers */
2360 /*-----------------------------------------------------------------*/
2362 saveRegisters (iCode * lic)
2368 for (ic = lic; ic; ic = ic->next)
2369 if (ic->op == CALL || ic->op == PCALL)
2374 fprintf (stderr, "found parameter push with no function call\n");
2378 /* if the registers have been saved already or don't need to be then
2381 || (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))) && !TARGET_IS_DS400) )
2384 /* special case if DPTR alive across a function call then must save it
2385 even though callee saves */
2386 if (IS_SYMOP(IC_LEFT(ic)) &&
2387 IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type))
2390 rsave = newBitVect(ic->rMask->size);
2391 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2392 if (bitVectBitValue(ic->rMask,i))
2393 rsave = bitVectSetBit(rsave,i);
2395 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2399 /* save the registers in use at this time but skip the
2400 ones for the result */
2401 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2402 ds390_rUmaskForOp (IC_RESULT(ic)));
2408 /*-----------------------------------------------------------------*/
2409 /* usavermask - restore registers with mask */
2410 /*-----------------------------------------------------------------*/
2411 static void unsavermask(bitVect *rs_mask)
2414 if (options.useXstack) {
2415 emitcode ("mov", "r0,%s", spname);
2416 for (i = ds390_nRegs; i >= 0; i--)
2418 if (bitVectBitValue (rs_mask, i))
2420 regs * reg = REG_WITH_INDEX (i);
2421 emitcode ("dec", "r0");
2422 emitcode ("movx", "a,@r0");
2425 emitcode ("push", "acc");
2429 emitcode ("mov", "%s,a", reg->name);
2433 emitcode ("mov", "%s,r0", spname);
2434 if (bitVectBitValue (rs_mask, R0_IDX))
2436 emitcode ("pop", "ar0");
2441 bool bits_popped = FALSE;
2442 for (i = ds390_nRegs; i >= 0; i--)
2444 if (bitVectBitValue (rs_mask, i))
2446 bits_popped = popReg (i, bits_popped);
2452 /*-----------------------------------------------------------------*/
2453 /* unsaveRegisters - pop the pushed registers */
2454 /*-----------------------------------------------------------------*/
2456 unsaveRegisters (iCode * ic)
2460 if (IS_SYMOP(IC_LEFT (ic)) &&
2461 IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2463 rsave = newBitVect(ic->rMask->size);
2464 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2465 if (bitVectBitValue(ic->rMask,i))
2466 rsave = bitVectSetBit(rsave,i);
2468 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2470 /* restore the registers in use at this time but skip the
2471 ones for the result */
2472 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2473 ds390_rUmaskForOp (IC_RESULT(ic)));
2479 /*-----------------------------------------------------------------*/
2481 /*-----------------------------------------------------------------*/
2483 pushSide (operand * oper, int size)
2486 _startLazyDPSEvaluation ();
2489 char *l = aopGet (oper, offset++, FALSE, TRUE, NULL);
2490 if (AOP_TYPE (oper) != AOP_REG &&
2491 AOP_TYPE (oper) != AOP_DIR &&
2495 emitcode ("push", "acc");
2499 emitcode ("push", "%s", l);
2502 _endLazyDPSEvaluation ();
2505 /*-----------------------------------------------------------------*/
2506 /* assignResultValue - also indicates if acc is in use afterwards */
2507 /*-----------------------------------------------------------------*/
2509 assignResultValue (operand * oper, operand * func)
2512 unsigned size = AOP_SIZE (oper);
2513 bool accuse = FALSE;
2514 bool pushedA = FALSE;
2516 if (func && IS_BIT (OP_SYM_ETYPE (func)))
2522 if (size == fReturnSizeDS390)
2524 /* I don't think this case can ever happen... */
2525 /* ACC is the last part of this. If writing the result
2526 * uses ACC, we must preserve it.
2528 if (AOP_NEEDSACC(oper))
2530 emitcode(";", "assignResultValue special case for ACC.");
2531 emitcode("push", "acc");
2537 _startLazyDPSEvaluation ();
2540 accuse |= aopPut (oper, fReturn[offset], offset);
2543 _endLazyDPSEvaluation ();
2547 emitcode ("pop", "acc");
2548 accuse |= aopPut (oper, "a", offset);
2554 /*-----------------------------------------------------------------*/
2555 /* genXpush - pushes onto the external stack */
2556 /*-----------------------------------------------------------------*/
2558 genXpush (iCode * ic)
2560 asmop *aop = newAsmop (0);
2562 int size, offset = 0;
2564 D (emitcode (";", "genXpush "));
2566 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2567 r = getFreePtr (ic, &aop, FALSE);
2569 size = AOP_SIZE (IC_LEFT (ic));
2573 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
2574 emitcode ("mov", "%s,_spx", r->name);
2575 emitcode ("inc", "_spx"); // allocate space first
2576 emitcode ("movx", "@%s,a", r->name);
2580 // allocate space first
2581 emitcode ("mov", "%s,_spx", r->name);
2583 emitcode ("add", "a,#%d", size);
2584 emitcode ("mov", "_spx,a");
2586 _startLazyDPSEvaluation ();
2589 MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE, NULL));
2590 emitcode ("movx", "@%s,a", r->name);
2591 emitcode ("inc", "%s", r->name);
2593 _endLazyDPSEvaluation ();
2596 freeAsmop (NULL, aop, ic, TRUE);
2597 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2600 /*-----------------------------------------------------------------*/
2601 /* genIpush - generate code for pushing this gets a little complex */
2602 /*-----------------------------------------------------------------*/
2604 genIpush (iCode * ic)
2606 int size, offset = 0;
2610 D (emitcode (";", "genIpush "));
2612 /* if this is not a parm push : ie. it is spill push
2613 and spill push is always done on the local stack */
2617 /* and the item is spilt then do nothing */
2618 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2621 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2622 size = AOP_SIZE (IC_LEFT (ic));
2623 /* push it on the stack */
2624 _startLazyDPSEvaluation ();
2627 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE, NULL);
2633 emitcode ("push", "%s", l);
2635 _endLazyDPSEvaluation ();
2639 /* this is a parameter push: in this case we call
2640 the routine to find the call and save those
2641 registers that need to be saved */
2644 /* if use external stack then call the external
2645 stack pushing routine */
2646 if (options.useXstack)
2652 /* then do the push */
2653 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2655 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2656 size = AOP_SIZE (IC_LEFT (ic));
2658 _startLazyDPSEvaluation ();
2661 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE, NULL);
2662 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2663 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2666 if (strcmp (l, prev) || *l == '@')
2668 emitcode ("push", "acc");
2672 emitcode ("push", "%s", l);
2676 _endLazyDPSEvaluation ();
2678 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2681 /*-----------------------------------------------------------------*/
2682 /* genIpop - recover the registers: can happen only for spilling */
2683 /*-----------------------------------------------------------------*/
2685 genIpop (iCode * ic)
2689 D (emitcode (";", "genIpop "));
2691 /* if the temp was not pushed then */
2692 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2695 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2696 size = AOP_SIZE (IC_LEFT (ic));
2697 offset = (size - 1);
2698 _startLazyDPSEvaluation ();
2701 emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2702 FALSE, TRUE, NULL));
2704 _endLazyDPSEvaluation ();
2706 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2709 /*-----------------------------------------------------------------*/
2710 /* saveRBank - saves an entire register bank on the stack */
2711 /*-----------------------------------------------------------------*/
2713 saveRBank (int bank, iCode * ic, bool pushPsw)
2716 int count = 8 + (ds390_nBitRegs/8) + (pushPsw ? 1 : 0);
2720 if (options.useXstack)
2724 /* Assume r0 is available for use. */
2725 r = REG_WITH_INDEX (R0_IDX);;
2730 r = getFreePtr (ic, &aop, FALSE);
2732 // allocate space first
2733 emitcode ("mov", "%s,_spx", r->name);
2735 emitcode ("add", "a,#%d", count);
2736 emitcode ("mov", "_spx,a");
2739 for (i = 0; i < 8; i++) /* only R0-R7 needs saving */
2741 if (options.useXstack)
2743 emitcode ("mov", "a,(%s+%d)",
2744 regs390[i].base, 8 * bank + regs390[i].offset);
2745 emitcode ("movx", "@%s,a", r->name);
2747 emitcode ("inc", "%s", r->name);
2750 emitcode ("push", "(%s+%d)",
2751 regs390[i].base, 8 * bank + regs390[i].offset);
2754 if (ds390_nBitRegs > 0)
2756 if (options.useXstack)
2758 emitcode ("mov", "a,bits");
2759 emitcode ("movx", "@%s,a", r->name);
2761 emitcode ("inc", "%s", r->name);
2765 emitcode ("push", "bits");
2772 if (options.useXstack)
2774 emitcode ("mov", "a,psw");
2775 emitcode ("movx", "@%s,a", r->name);
2779 emitcode ("push", "psw");
2782 emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2787 freeAsmop (NULL, aop, ic, TRUE);
2796 /*-----------------------------------------------------------------*/
2797 /* unsaveRBank - restores the register bank from stack */
2798 /*-----------------------------------------------------------------*/
2800 unsaveRBank (int bank, iCode * ic, bool popPsw)
2806 if (options.useXstack)
2810 /* Assume r0 is available for use. */
2811 r = REG_WITH_INDEX (R0_IDX);;
2816 r = getFreePtr (ic, &aop, FALSE);
2818 emitcode ("mov", "%s,_spx", r->name);
2823 if (options.useXstack)
2825 emitcode ("dec", "%s", r->name);
2826 emitcode ("movx", "a,@%s", r->name);
2827 emitcode ("mov", "psw,a");
2831 emitcode ("pop", "psw");
2835 if (ds390_nBitRegs > 0)
2837 if (options.useXstack)
2839 emitcode ("dec", "%s", r->name);
2840 emitcode ("movx", "a,@%s", r->name);
2841 emitcode ("mov", "bits,a");
2845 emitcode ("pop", "bits");
2849 for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2851 if (options.useXstack)
2853 emitcode ("dec", "%s", r->name);
2854 emitcode ("movx", "a,@%s", r->name);
2855 emitcode ("mov", "(%s+%d),a",
2856 regs390[i].base, 8 * bank + regs390[i].offset);
2860 emitcode ("pop", "(%s+%d)",
2861 regs390[i].base, 8 * bank + regs390[i].offset);
2865 if (options.useXstack)
2867 emitcode ("mov", "_spx,%s", r->name);
2872 freeAsmop (NULL, aop, ic, TRUE);
2876 /*-----------------------------------------------------------------*/
2877 /* genSend - gen code for SEND */
2878 /*-----------------------------------------------------------------*/
2879 static void genSend(set *sendSet)
2884 static int rb1_count = 0;
2886 /* first we do all bit parameters */
2887 for (sic = setFirstItem (sendSet); sic;
2888 sic = setNextItem (sendSet))
2890 if (sic->argreg > 12)
2892 int bit = sic->argreg-13;
2894 aopOp (IC_LEFT (sic), sic, FALSE,
2895 (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2897 /* if left is a literal then
2898 we know what the value is */
2899 if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2901 if (((int) operandLitValue (IC_LEFT (sic))))
2902 emitcode ("setb", "b[%d]", bit);
2904 emitcode ("clr", "b[%d]", bit);
2906 else if (AOP_TYPE (IC_LEFT (sic)) == AOP_CRY)
2908 char *l = AOP (IC_LEFT (sic))->aopu.aop_dir;
2909 if (strcmp (l, "c"))
2910 emitcode ("mov", "c,%s", l);
2911 emitcode ("mov", "b[%d],c", bit);
2916 toBoolean (IC_LEFT (sic));
2917 /* set C, if a >= 1 */
2918 emitcode ("add", "a,#0xff");
2919 emitcode ("mov", "b[%d],c", bit);
2924 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2930 saveRegisters (setFirstItem (sendSet));
2931 emitcode ("mov", "bits,b");
2934 /* then we do all other parameters */
2935 for (sic = setFirstItem (sendSet); sic;
2936 sic = setNextItem (sendSet))
2938 if (sic->argreg <= 12)
2940 int size, offset = 0;
2942 size=getSize(operandType(IC_LEFT(sic)));
2943 D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2944 if (sendCount == 0) { /* first parameter */
2945 // we know that dpl(hxb) is the result, so
2947 _startLazyDPSEvaluation ();
2949 aopOp (IC_LEFT (sic), sic, FALSE,
2950 (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2952 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2956 char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE, NULL);
2957 if (strcmp (l, fReturn[offset]))
2959 emitcode ("mov", "%s,%s", fReturn[offset], l);
2963 _endLazyDPSEvaluation ();
2964 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2966 } else { /* if more parameter in registers */
2967 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2969 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (IC_LEFT (sic), offset++,
2970 FALSE, FALSE, NULL));
2972 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2980 adjustEsp(const char *reg)
2982 emitcode ("anl","%s,#3", reg);
2983 if (TARGET_IS_DS400)
2985 emitcode ("orl","%s,#!constbyte",
2987 (options.stack_loc >> 8) & 0xff);
2991 /*-----------------------------------------------------------------*/
2992 /* selectRegBank - emit code to select the register bank */
2993 /*-----------------------------------------------------------------*/
2995 selectRegBank (short bank, bool keepFlags)
2997 /* if f.e. result is in carry */
3000 emitcode ("anl", "psw,#0xE7");
3002 emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
3006 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
3010 /*-----------------------------------------------------------------*/
3011 /* genCall - generates a call statement */
3012 /*-----------------------------------------------------------------*/
3014 genCall (iCode * ic)
3018 bool restoreBank = FALSE;
3019 bool swapBanks = FALSE;
3020 bool accuse = FALSE;
3021 bool accPushed = FALSE;
3022 bool resultInF0 = FALSE;
3023 bool assignResultGenerated = FALSE;
3025 D (emitcode (";", "genCall "));
3027 /* if we are calling a not _naked function that is not using
3028 the same register bank then we need to save the
3029 destination registers on the stack */
3030 dtype = operandType (IC_LEFT (ic));
3031 etype = getSpec(dtype);
3032 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
3033 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
3034 IFFUNC_ISISR (currFunc->type))
3038 /* This is unexpected; the bank should have been saved in
3041 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
3047 /* if caller saves & we have not saved then */
3051 /* if send set is not empty then assign */
3052 /* We've saved all the registers we care about;
3053 * therefore, we may clobber any register not used
3054 * in the calling convention (i.e. anything not in
3059 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
3060 genSend(reverseSet(_G.sendSet));
3062 genSend(_G.sendSet);
3069 emitcode ("mov", "psw,#!constbyte",
3070 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3074 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
3075 OP_SYMBOL (IC_LEFT (ic))->rname :
3076 OP_SYMBOL (IC_LEFT (ic))->name));
3080 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
3083 /* if we need assign a result value */
3084 if ((IS_ITEMP (IC_RESULT (ic)) &&
3085 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3086 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3087 OP_SYMBOL (IC_RESULT (ic))->accuse ||
3088 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3089 IS_TRUE_SYMOP (IC_RESULT (ic)))
3091 if (isOperandInFarSpace (IC_RESULT (ic))
3092 && getSize (operandType (IC_RESULT (ic))) <= 2)
3094 int size = getSize (operandType (IC_RESULT (ic)));
3095 bool pushedB = FALSE;
3097 /* Special case for 1 or 2 byte return in far space. */
3102 emitcode ("mov", "b,%s", fReturn[1]);
3106 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
3111 aopPut (IC_RESULT (ic), "a", 0);
3115 aopPut (IC_RESULT (ic), "b", 1);
3117 assignResultGenerated = TRUE;
3118 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3122 bool pushedB = pushB ();
3123 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
3126 accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3127 assignResultGenerated = TRUE;
3128 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3132 /* adjust the stack for parameters if required */
3136 if (options.stack10bit) {
3137 if (ic->parmBytes <= 10) {
3138 emitcode(";","stack adjustment for parms");
3139 for (i=0; i < ic->parmBytes ; i++) {
3140 emitcode("pop","acc");
3144 emitcode ("clr","c");
3145 emitcode ("mov","a,sp");
3146 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
3147 emitcode ("mov","sp,a");
3148 emitcode ("mov","a,esp");
3150 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
3151 emitcode ("mov","esp,a");
3155 if (ic->parmBytes > 3)
3159 emitcode ("push", "acc");
3162 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3163 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3164 !assignResultGenerated)
3166 emitcode ("mov", "F0,c");
3169 emitcode ("mov", "a,%s", spname);
3170 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
3171 emitcode ("mov", "%s,a", spname);
3173 /* unsaveRegisters from xstack needs acc, but */
3174 /* unsaveRegisters from stack needs this popped */
3175 if (accPushed && !options.useXstack)
3177 emitcode ("pop", "acc");
3182 for (i = 0; i < ic->parmBytes; i++)
3183 emitcode ("dec", "%s", spname);
3187 /* if we had saved some registers then unsave them */
3188 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3190 if (accuse && !accPushed && options.useXstack)
3192 /* xstack needs acc, but doesn't touch normal stack */
3193 emitcode ("push", "acc");
3196 unsaveRegisters (ic);
3199 /* if register bank was saved then pop them */
3201 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
3203 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
3206 emitcode ("mov", "c,F0");
3208 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
3209 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3210 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3214 emitcode ("pop", "acc");
3217 /*-----------------------------------------------------------------*/
3218 /* genPcall - generates a call by pointer statement */
3219 /*-----------------------------------------------------------------*/
3221 genPcall (iCode * ic)
3225 symbol *rlbl = newiTempLabel (NULL);
3226 bool restoreBank=FALSE;
3227 bool resultInF0 = FALSE;
3229 D (emitcode (";", "genPcall "));
3231 dtype = operandType (IC_LEFT (ic))->next;
3232 etype = getSpec(dtype);
3233 /* if caller saves & we have not saved then */
3237 /* if we are calling a not _naked function that is not using
3238 the same register bank then we need to save the
3239 destination registers on the stack */
3240 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
3241 IFFUNC_ISISR (currFunc->type) &&
3242 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
3243 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3247 /* push the return address on to the stack */
3248 emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
3249 emitcode ("push", "acc");
3250 emitcode ("mov", "a,#!hil", (rlbl->key + 100));
3251 emitcode ("push", "acc");
3253 if (options.model == MODEL_FLAT24)
3255 emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
3256 emitcode ("push", "acc");
3259 /* now push the calling address */
3260 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3262 pushSide (IC_LEFT (ic), FPTRSIZE);
3264 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3266 /* if send set is not empty the assign */
3269 genSend(reverseSet(_G.sendSet));
3273 emitcode ("ret", "");
3274 emitcode ("", "!tlabeldef", (rlbl->key + 100));
3277 /* if we need assign a result value */
3278 if ((IS_ITEMP (IC_RESULT (ic)) &&
3279 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3280 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3281 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3282 IS_TRUE_SYMOP (IC_RESULT (ic)))
3286 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
3289 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3291 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3294 /* adjust the stack for parameters if required */
3298 if (options.stack10bit) {
3299 if (ic->parmBytes <= 10) {
3300 emitcode(";","stack adjustment for parms");
3301 for (i=0; i < ic->parmBytes ; i++) {
3302 emitcode("pop","acc");
3305 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3306 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3308 emitcode ("mov", "F0,c");
3313 emitcode ("clr","c");
3314 emitcode ("mov","a,sp");
3315 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
3316 emitcode ("mov","sp,a");
3317 emitcode ("mov","a,esp");
3319 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
3320 emitcode ("mov","esp,a");
3324 if (ic->parmBytes > 3) {
3325 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3326 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3328 emitcode ("mov", "F0,c");
3332 emitcode ("mov", "a,%s", spname);
3333 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
3334 emitcode ("mov", "%s,a", spname);
3337 for (i = 0; i < ic->parmBytes; i++)
3338 emitcode ("dec", "%s", spname);
3341 /* if register bank was saved then unsave them */
3343 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3345 /* if we had saved some registers then unsave them */
3347 unsaveRegisters (ic);
3349 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3352 emitcode ("mov", "c,F0");
3354 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
3355 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3356 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3360 /*-----------------------------------------------------------------*/
3361 /* resultRemat - result is rematerializable */
3362 /*-----------------------------------------------------------------*/
3364 resultRemat (iCode * ic)
3366 if (SKIP_IC (ic) || ic->op == IFX)
3369 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3371 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3372 if (sym->remat && !POINTER_SET (ic))
3379 #if defined(__BORLANDC__) || defined(_MSC_VER)
3380 #define STRCASECMP stricmp
3382 #define STRCASECMP strcasecmp
3385 /*-----------------------------------------------------------------*/
3386 /* inExcludeList - return 1 if the string is in exclude Reg list */
3387 /*-----------------------------------------------------------------*/
3389 regsCmp(void *p1, void *p2)
3391 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3395 inExcludeList (char *s)
3397 const char *p = setFirstItem(options.excludeRegsSet);
3399 if (p == NULL || STRCASECMP(p, "none") == 0)
3403 return isinSetWith(options.excludeRegsSet, s, regsCmp);
3406 /*-----------------------------------------------------------------*/
3407 /* genFunction - generated code for function entry */
3408 /*-----------------------------------------------------------------*/
3410 genFunction (iCode * ic)
3412 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3414 bool switchedPSW = FALSE;
3415 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3417 D (emitcode (";", "genFunction "));
3420 /* create the function header */
3421 emitcode (";", "-----------------------------------------");
3422 emitcode (";", " function %s", sym->name);
3423 emitcode (";", "-----------------------------------------");
3425 emitcode ("", "%s:", sym->rname);
3426 ftype = operandType (IC_LEFT (ic));
3427 _G.currentFunc = sym;
3429 if (IFFUNC_ISNAKED(ftype))
3431 emitcode(";", "naked function: no prologue.");
3435 if (options.stack_probe)
3436 emitcode ("lcall","__stack_probe");
3438 /* here we need to generate the equates for the
3439 register bank if required */
3440 if (FUNC_REGBANK (ftype) != rbank)
3444 rbank = FUNC_REGBANK (ftype);
3445 for (i = 0; i < ds390_nRegs; i++)
3447 if (regs390[i].print) {
3448 if (strcmp (regs390[i].base, "0") == 0)
3449 emitcode ("", "%s !equ !constbyte",
3451 8 * rbank + regs390[i].offset);
3453 emitcode ("", "%s !equ %s + !constbyte",
3456 8 * rbank + regs390[i].offset);
3461 /* if this is an interrupt service routine then
3462 save acc, b, dpl, dph */
3463 if (IFFUNC_ISISR (sym->type))
3465 if (!inExcludeList ("acc"))
3466 emitcode ("push", "acc");
3467 if (!inExcludeList ("b"))
3468 emitcode ("push", "b");
3469 if (!inExcludeList ("dpl"))
3470 emitcode ("push", "dpl");
3471 if (!inExcludeList ("dph"))
3472 emitcode ("push", "dph");
3473 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3475 emitcode ("push", "dpx");
3476 /* Make sure we're using standard DPTR */
3477 emitcode ("push", "dps");
3478 emitcode ("mov", "dps,#0");
3479 if (options.stack10bit)
3481 /* This ISR could conceivably use DPTR2. Better save it. */
3482 emitcode ("push", "dpl1");
3483 emitcode ("push", "dph1");
3484 emitcode ("push", "dpx1");
3485 emitcode ("push", DP2_RESULT_REG);
3488 /* if this isr has no bank i.e. is going to
3489 run with bank 0 , then we need to save more
3491 if (!FUNC_REGBANK (sym->type))
3495 /* if this function does not call any other
3496 function then we can be economical and
3497 save only those registers that are used */
3498 if (!IFFUNC_HASFCALL(sym->type))
3500 /* if any registers used */
3503 bool bits_pushed = FALSE;
3504 /* save the registers used */
3505 for (i = 0; i < sym->regsUsed->size; i++)
3507 if (bitVectBitValue (sym->regsUsed, i))
3508 bits_pushed = pushReg (i, bits_pushed);
3514 /* this function has a function call. We cannot
3515 determine register usage so we will have to push the
3517 saveRBank (0, ic, FALSE);
3518 if (options.parms_in_bank1) {
3519 for (i=0; i < 8 ; i++ ) {
3520 emitcode ("push","%s",rb1regs[i]);
3527 /* This ISR uses a non-zero bank.
3529 * We assume that the bank is available for our
3532 * However, if this ISR calls a function which uses some
3533 * other bank, we must save that bank entirely.
3535 unsigned long banksToSave = 0;
3537 if (IFFUNC_HASFCALL(sym->type))
3540 #define MAX_REGISTER_BANKS 4
3545 for (i = ic; i; i = i->next)
3547 if (i->op == ENDFUNCTION)
3549 /* we got to the end OK. */
3557 dtype = operandType (IC_LEFT(i));
3559 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3561 /* Mark this bank for saving. */
3562 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3564 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3568 banksToSave |= (1 << FUNC_REGBANK(dtype));
3571 /* And note that we don't need to do it in
3579 /* This is a mess; we have no idea what
3580 * register bank the called function might
3583 * The only thing I can think of to do is
3584 * throw a warning and hope.
3586 werror(W_FUNCPTR_IN_USING_ISR);
3590 if (banksToSave && options.useXstack)
3592 /* Since we aren't passing it an ic,
3593 * saveRBank will assume r0 is available to abuse.
3595 * So switch to our (trashable) bank now, so
3596 * the caller's R0 isn't trashed.
3598 emitcode ("push", "psw");
3599 emitcode ("mov", "psw,#!constbyte",
3600 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3604 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3606 if (banksToSave & (1 << ix))
3608 saveRBank(ix, NULL, FALSE);
3612 // TODO: this needs a closer look
3613 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3618 /* if callee-save to be used for this function
3619 then save the registers being used in this function */
3620 if (IFFUNC_CALLEESAVES(sym->type))
3624 /* if any registers used */
3627 bool bits_pushed = FALSE;
3628 /* save the registers used */
3629 for (i = 0; i < sym->regsUsed->size; i++)
3631 if (bitVectBitValue (sym->regsUsed, i))
3633 bits_pushed = pushReg (i, bits_pushed);
3641 /* set the register bank to the desired value */
3642 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3645 emitcode ("push", "psw");
3646 emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3650 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3651 if (options.stack10bit) {
3652 emitcode ("push","_bpx");
3653 emitcode ("push","_bpx+1");
3654 emitcode ("mov","_bpx,%s",spname);
3655 emitcode ("mov","_bpx+1,esp");
3656 adjustEsp("_bpx+1");
3658 if (options.useXstack)
3660 emitcode ("mov", "r0,%s", spname);
3661 emitcode ("mov", "a,_bp");
3662 emitcode ("movx", "@r0,a");
3663 emitcode ("inc", "%s", spname);
3665 /* set up the stack */
3666 emitcode ("push", "_bp"); /* save the callers stack */
3668 emitcode ("mov", "_bp,%s", spname);
3672 /* adjust the stack for the function */
3675 if (options.stack10bit) {
3676 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
3677 assert (sym->recvSize <= 4);
3678 if (sym->stack <= 8) {
3679 while (i--) emitcode ("push","acc");
3682 emitcode ("mov","a,sp");
3683 emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3684 emitcode ("mov","sp,a");
3685 emitcode ("mov","a,esp");
3687 emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3688 emitcode ("mov","esp,a");
3693 werror (W_STACK_OVERFLOW, sym->name);
3695 if (i > 3 && sym->recvSize < 4) {
3697 emitcode ("mov", "a,sp");
3698 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3699 emitcode ("mov", "sp,a");
3703 emitcode ("inc", "sp");
3710 emitcode ("mov", "a,_spx");
3711 emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3712 emitcode ("mov", "_spx,a");
3715 /* if critical function then turn interrupts off */
3716 if (IFFUNC_ISCRITICAL (ftype))
3718 symbol *tlbl = newiTempLabel (NULL);
3719 emitcode ("setb", "c");
3720 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3721 emitcode ("clr", "c");
3722 emitcode ("", "%05d$:", (tlbl->key + 100));
3723 emitcode ("push", "psw"); /* save old ea via c in psw */
3727 /*-----------------------------------------------------------------*/
3728 /* genEndFunction - generates epilogue for functions */
3729 /*-----------------------------------------------------------------*/
3731 genEndFunction (iCode * ic)
3733 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3734 lineNode *lnp = lineCurr;
3736 bitVect *regsUsedPrologue;
3737 bitVect *regsUnneeded;
3740 D (emitcode (";", "genEndFunction "););
3742 _G.currentFunc = NULL;
3743 if (IFFUNC_ISNAKED(sym->type))
3745 emitcode(";", "naked function: no epilogue.");
3746 if (options.debug && currFunc)
3747 debugFile->writeEndFunction (currFunc, ic, 0);
3751 if (IFFUNC_ISCRITICAL (sym->type))
3753 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3755 emitcode ("rlc", "a"); /* save c in a */
3756 emitcode ("pop", "psw"); /* restore ea via c in psw */
3757 emitcode ("mov", "ea,c");
3758 emitcode ("rrc", "a"); /* restore c from a */
3762 emitcode ("pop", "psw"); /* restore ea via c in psw */
3763 emitcode ("mov", "ea,c");
3767 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3768 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3770 if (options.stack10bit) {
3772 emitcode ("mov", "sp,_bpx", spname);
3773 emitcode ("mov", "esp,_bpx+1", spname);
3776 emitcode ("mov", "%s,_bp", spname);
3780 /* if use external stack but some variables were
3781 added to the local stack then decrement the
3783 if (options.useXstack && sym->stack) {
3784 emitcode ("mov", "a,sp");
3785 emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3786 emitcode ("mov", "sp,a");
3790 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3791 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3793 if (options.useXstack) {
3794 emitcode ("mov", "r0,%s", spname);
3795 emitcode ("movx", "a,@r0");
3796 emitcode ("mov", "_bp,a");
3797 emitcode ("dec", "%s", spname);
3799 if (options.stack10bit) {
3800 emitcode ("pop", "_bpx+1");
3801 emitcode ("pop", "_bpx");
3803 emitcode ("pop", "_bp");
3808 /* restore the register bank */
3809 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3811 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3812 || !options.useXstack)
3814 /* Special case of ISR using non-zero bank with useXstack
3817 emitcode ("pop", "psw");
3821 if (IFFUNC_ISISR (sym->type))
3824 /* now we need to restore the registers */
3825 /* if this isr has no bank i.e. is going to
3826 run with bank 0 , then we need to save more
3828 if (!FUNC_REGBANK (sym->type))
3831 /* if this function does not call any other
3832 function then we can be economical and
3833 save only those registers that are used */
3834 if (!IFFUNC_HASFCALL(sym->type))
3836 /* if any registers used */
3839 bool bits_popped = FALSE;
3840 /* save the registers used */
3841 for (i = sym->regsUsed->size; i >= 0; i--)
3843 if (bitVectBitValue (sym->regsUsed, i))
3844 bits_popped = popReg (i, bits_popped);
3850 /* this function has a function call. We cannot
3851 determine register usage so we will have to pop the
3853 if (options.parms_in_bank1) {
3854 for (i = 7 ; i >= 0 ; i-- ) {
3855 emitcode ("pop","%s",rb1regs[i]);
3858 unsaveRBank (0, ic, FALSE);
3863 /* This ISR uses a non-zero bank.
3865 * Restore any register banks saved by genFunction
3868 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3871 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3873 if (savedBanks & (1 << ix))
3875 unsaveRBank(ix, NULL, FALSE);
3879 if (options.useXstack)
3881 /* Restore bank AFTER calling unsaveRBank,
3882 * since it can trash r0.
3884 emitcode ("pop", "psw");
3888 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3890 if (options.stack10bit)
3892 emitcode ("pop", DP2_RESULT_REG);
3893 emitcode ("pop", "dpx1");
3894 emitcode ("pop", "dph1");
3895 emitcode ("pop", "dpl1");
3897 emitcode ("pop", "dps");
3898 emitcode ("pop", "dpx");
3900 if (!inExcludeList ("dph"))
3901 emitcode ("pop", "dph");
3902 if (!inExcludeList ("dpl"))
3903 emitcode ("pop", "dpl");
3904 if (!inExcludeList ("b"))
3905 emitcode ("pop", "b");
3906 if (!inExcludeList ("acc"))
3907 emitcode ("pop", "acc");
3909 /* if debug then send end of function */
3910 if (options.debug && currFunc)
3912 debugFile->writeEndFunction (currFunc, ic, 1);
3915 emitcode ("reti", "");
3919 if (IFFUNC_CALLEESAVES(sym->type))
3923 /* if any registers used */
3926 /* save the registers used */
3927 for (i = sym->regsUsed->size; i >= 0; i--)
3929 if (bitVectBitValue (sym->regsUsed, i))
3930 emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
3935 /* if debug then send end of function */
3936 if (options.debug && currFunc)
3938 debugFile->writeEndFunction (currFunc, ic, 1);
3941 emitcode ("ret", "");
3944 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3947 /* If this was an interrupt handler using bank 0 that called another */
3948 /* function, then all registers must be saved; nothing to optimized. */
3949 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3950 && !FUNC_REGBANK(sym->type))
3953 /* There are no push/pops to optimize if not callee-saves or ISR */
3954 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3957 /* If there were stack parameters, we cannot optimize without also */
3958 /* fixing all of the stack offsets; this is too dificult to consider. */
3959 if (FUNC_HASSTACKPARM(sym->type))
3962 /* Compute the registers actually used */
3963 regsUsed = newBitVect (ds390_nRegs);
3964 regsUsedPrologue = newBitVect (ds390_nRegs);
3967 if (lnp->ic && lnp->ic->op == FUNCTION)
3968 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3970 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3972 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3973 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3980 if (bitVectBitValue (regsUsedPrologue, DPS_IDX)
3981 && !bitVectBitValue (regsUsed, DPS_IDX))
3983 bitVectUnSetBit (regsUsedPrologue, DPS_IDX);
3986 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3987 && !bitVectBitValue (regsUsed, CND_IDX))
3989 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3990 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3991 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3992 bitVectUnSetBit (regsUsed, CND_IDX);
3995 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3997 /* If this was an interrupt handler that called another function */
3998 /* function, then assume working registers may be modified by it. */
3999 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
4001 regsUsed = bitVectSetBit (regsUsed, AP_IDX);
4002 regsUsed = bitVectSetBit (regsUsed, DPX1_IDX);
4003 regsUsed = bitVectSetBit (regsUsed, DPL1_IDX);
4004 regsUsed = bitVectSetBit (regsUsed, DPH1_IDX);
4005 regsUsed = bitVectSetBit (regsUsed, DPX_IDX);
4006 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
4007 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
4008 regsUsed = bitVectSetBit (regsUsed, DPS_IDX);
4009 regsUsed = bitVectSetBit (regsUsed, B_IDX);
4010 regsUsed = bitVectSetBit (regsUsed, A_IDX);
4011 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
4014 /* Remove the unneeded push/pops */
4015 regsUnneeded = newBitVect (ds390_nRegs);
4018 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
4020 if (!strncmp(lnp->line, "push", 4))
4022 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
4023 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4025 connectLine (lnp->prev, lnp->next);
4026 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4029 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
4031 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
4032 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4034 connectLine (lnp->prev, lnp->next);
4035 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4042 for (idx = 0; idx < regsUnneeded->size; idx++)
4043 if (bitVectBitValue (regsUnneeded, idx))
4044 emitcode ("", ";\teliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
4046 freeBitVect (regsUnneeded);
4047 freeBitVect (regsUsed);
4048 freeBitVect (regsUsedPrologue);
4051 /*-----------------------------------------------------------------*/
4052 /* genJavaNativeRet - generate code for return JavaNative */
4053 /*-----------------------------------------------------------------*/
4054 static void genJavaNativeRet(iCode *ic)
4058 aopOp (IC_LEFT (ic), ic, FALSE,
4059 AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
4060 size = AOP_SIZE (IC_LEFT (ic));
4064 /* it is assigned to GPR0-R3 then push them */
4065 if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
4066 aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
4067 for (i = 0 ; i < size ; i++ ) {
4068 emitcode ("push","%s",
4069 aopGet(IC_LEFT(ic),i,FALSE,TRUE,DP2_RESULT_REG));
4071 for (i = (size-1) ; i >= 0 ; i--) {
4072 emitcode ("pop","a%s",javaRet[i]);
4075 for (i = 0 ; i < size ; i++)
4076 emitcode ("mov","%s,%s",javaRet[i],
4077 aopGet(IC_LEFT(ic),i,FALSE,TRUE,DP2_RESULT_REG));
4079 for (i = size ; i < 4 ; i++ )
4080 emitcode ("mov","%s,#0",javaRet[i]);
4084 /*-----------------------------------------------------------------*/
4085 /* genRet - generate code for return statement */
4086 /*-----------------------------------------------------------------*/
4090 int size, offset = 0, pushed = 0;
4092 D (emitcode (";", "genRet"));
4094 /* if we have no return value then
4095 just generate the "ret" */
4099 /* if this is a JavaNative function then return
4100 value in different register */
4101 if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
4102 genJavaNativeRet(ic);
4105 /* we have something to return then
4106 move the return value into place */
4107 aopOp (IC_LEFT (ic), ic, FALSE,
4108 (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
4109 size = AOP_SIZE (IC_LEFT (ic));
4111 _startLazyDPSEvaluation ();
4113 if (IS_BIT(_G.currentFunc->etype))
4115 movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4122 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
4124 l = aopGet (IC_LEFT (ic), offset++,
4126 emitcode ("push", "%s", l);
4131 /* Since A is the last element of fReturn,
4132 * it is OK to clobber it in the aopGet.
4134 l = aopGet (IC_LEFT (ic), offset,
4135 FALSE, FALSE, NULL);
4136 if (strcmp (fReturn[offset], l))
4137 emitcode ("mov", "%s,%s", fReturn[offset++], l);
4140 _endLazyDPSEvaluation ();
4145 if (strcmp (fReturn[pushed], "a"))
4146 emitcode ("pop", fReturn[pushed]);
4148 emitcode ("pop", "acc");
4150 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
4153 /* generate a jump to the return label
4154 if the next is not the return statement */
4155 if (!(ic->next && ic->next->op == LABEL &&
4156 IC_LABEL (ic->next) == returnLabel))
4158 emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
4162 /*-----------------------------------------------------------------*/
4163 /* genLabel - generates a label */
4164 /*-----------------------------------------------------------------*/
4166 genLabel (iCode * ic)
4168 /* special case never generate */
4169 if (IC_LABEL (ic) == entryLabel)
4172 D (emitcode (";", "genLabel "));
4174 emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
4177 /*-----------------------------------------------------------------*/
4178 /* genGoto - generates a ljmp */
4179 /*-----------------------------------------------------------------*/
4181 genGoto (iCode * ic)
4183 D (emitcode (";", "genGoto "));
4185 emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
4188 /*-----------------------------------------------------------------*/
4189 /* findLabelBackwards: walks back through the iCode chain looking */
4190 /* for the given label. Returns number of iCode instructions */
4191 /* between that label and given ic. */
4192 /* Returns zero if label not found. */
4193 /*-----------------------------------------------------------------*/
4195 findLabelBackwards (iCode * ic, int key)
4204 /* If we have any pushes or pops, we cannot predict the distance.
4205 I don't like this at all, this should be dealt with in the
4207 if (ic->op == IPUSH || ic->op == IPOP) {
4211 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4213 /* printf("findLabelBackwards = %d\n", count); */
4221 /*-----------------------------------------------------------------*/
4222 /* genPlusIncr :- does addition with increment if possible */
4223 /*-----------------------------------------------------------------*/
4225 genPlusIncr (iCode * ic)
4227 unsigned int icount;
4228 unsigned int size = getDataSize (IC_RESULT (ic));
4230 /* will try to generate an increment */
4231 /* if the right side is not a literal
4233 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4236 /* if the literal value of the right hand side
4237 is greater than 4 then it is not worth it */
4238 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4241 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4242 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4244 emitcode("inc","%s",aopGet(IC_RESULT(ic),0,FALSE,FALSE,NULL));
4248 /* if increment 16 bits in register */
4250 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4251 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4252 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4261 /* If the next instruction is a goto and the goto target
4262 * is <= 5 instructions previous to this, we can generate
4263 * jumps straight to that target.
4265 if (ic->next && ic->next->op == GOTO
4266 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4269 D(emitcode (";", "tail increment optimized (range %d)", labelRange););
4270 tlbl = IC_LABEL (ic->next);
4275 tlbl = newiTempLabel (NULL);
4278 l = aopGet (IC_RESULT (ic), LSB, FALSE, FALSE, NULL);
4279 emitcode ("inc", "%s", l);
4281 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4282 IS_AOP_PREG (IC_RESULT (ic)))
4284 emitcode ("cjne", "%s,%s,!tlabel", l, zero, tlbl->key + 100);
4288 emitcode ("clr", "a");
4289 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4292 l = aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE, NULL);
4293 emitcode ("inc", "%s", l);
4296 if (!strcmp(l, "acc"))
4298 emitcode("jnz", "!tlabel", tlbl->key + 100);
4300 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4301 IS_AOP_PREG (IC_RESULT (ic)))
4303 emitcode ("cjne", "%s,%s,!tlabel", l, zero, tlbl->key + 100);
4307 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4310 l = aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE, NULL);
4311 emitcode ("inc", "%s", l);
4315 if (!strcmp(l, "acc"))
4317 emitcode("jnz", "!tlabel", tlbl->key + 100);
4319 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4320 IS_AOP_PREG (IC_RESULT (ic)))
4322 emitcode ("cjne", "%s,%s,!tlabel", l, zero, tlbl->key + 100);
4326 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4329 l = aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE, NULL);
4330 emitcode ("inc", "%s", l);
4335 emitcode ("", "!tlabeldef", tlbl->key + 100);
4340 if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
4341 !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 &&
4342 options.model == MODEL_FLAT24 )
4344 if (IC_RESULT(ic)->isGptr)
4346 emitcode ("mov", "b,%s", aopGet(IC_LEFT (ic), 3, FALSE, FALSE, NULL));
4350 emitcode ("mov", "dpx,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE, NULL));
4352 emitcode ("mov", "dph,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE, NULL));
4354 emitcode ("mov", "dpl,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4358 emitcode ("inc", "dptr");
4362 if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
4363 AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
4365 emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
4367 emitcode ("inc", "dptr");
4368 emitcode ("mov", "dps,#0");
4372 /* if the sizes are greater than 1 then we cannot */
4373 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4374 AOP_SIZE (IC_LEFT (ic)) > 1)
4377 /* we can if the aops of the left & result match or
4378 if they are in registers and the registers are the
4381 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4382 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4383 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4387 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4388 emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
4389 aopPut (IC_RESULT (ic), "a", 0);
4393 _startLazyDPSEvaluation ();
4396 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE, NULL));
4398 _endLazyDPSEvaluation ();
4407 /*-----------------------------------------------------------------*/
4408 /* outBitAcc - output a bit in acc */
4409 /*-----------------------------------------------------------------*/
4411 outBitAcc (operand * result)
4413 symbol *tlbl = newiTempLabel (NULL);
4414 /* if the result is a bit */
4415 if (AOP_TYPE (result) == AOP_CRY)
4417 aopPut (result, "a", 0);
4421 emitcode ("jz", "!tlabel", tlbl->key + 100);
4422 emitcode ("mov", "a,%s", one);
4423 emitcode ("", "!tlabeldef", tlbl->key + 100);
4428 /*-----------------------------------------------------------------*/
4429 /* genPlusBits - generates code for addition of two bits */
4430 /*-----------------------------------------------------------------*/
4432 genPlusBits (iCode * ic)
4434 D (emitcode (";", "genPlusBits "));
4436 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4438 symbol *lbl = newiTempLabel (NULL);
4439 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4440 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4441 emitcode ("cpl", "c");
4442 emitcode ("", "!tlabeldef", (lbl->key + 100));
4443 outBitC (IC_RESULT (ic));
4447 emitcode ("clr", "a");
4448 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4449 emitcode ("rlc", "a");
4450 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4451 emitcode ("addc", "a,%s", zero);
4452 outAcc (IC_RESULT (ic));
4457 adjustArithmeticResult (iCode * ic)
4459 if (opIsGptr (IC_RESULT (ic)) &&
4460 opIsGptr (IC_LEFT (ic)) &&
4461 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4463 aopPut (IC_RESULT (ic),
4464 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE, NULL),
4468 if (opIsGptr (IC_RESULT (ic)) &&
4469 opIsGptr (IC_RIGHT (ic)) &&
4470 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4472 aopPut (IC_RESULT (ic),
4473 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE, NULL),
4477 if (opIsGptr (IC_RESULT (ic)) &&
4478 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4479 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4480 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4481 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4484 SNPRINTF (buffer, sizeof(buffer),
4485 "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4486 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4490 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
4491 // generates the result if possible. If result is generated, returns TRUE; otherwise
4492 // returns false and caller must deal with fact that result isn't aopOp'd.
4493 bool aopOp3(iCode * ic)
4495 bool dp1InUse, dp2InUse;
4498 // First, generate the right opcode. DPTR may be used if neither left nor result are
4501 // D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
4502 // AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
4503 // AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
4504 // AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
4506 // D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
4507 // AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
4508 // AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
4509 // AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
4512 // Right uses DPTR unless left or result is an AOP_STR; however,
4513 // if right is an AOP_STR, it must use DPTR regardless.
4514 if ((AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)))
4515 && !AOP_IS_STR(IC_RIGHT(ic)))
4524 aopOp (IC_RIGHT(ic),ic,FALSE, useDp2);
4526 // if the right used DPTR, left MUST use DPTR2.
4527 // if the right used DPTR2, left MUST use DPTR.
4528 // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
4529 // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
4530 // enabling us to assign DPTR to result.
4532 if (AOP_USESDPTR(IC_RIGHT(ic)))
4536 else if (AOP_USESDPTR2(IC_RIGHT(ic)))
4542 if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
4552 aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
4555 // We've op'd the left & right. So, if left or right are the same operand as result,
4556 // we know aopOp will succeed, and we can just do it & bail.
4557 if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)))
4559 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4562 if (isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
4564 // D(emitcode(";", "aopOp3: (left | right) & result equal"););
4565 aopOp(IC_RESULT(ic),ic,TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4569 // Operands may be equivalent (but not equal) if they share a spill location. If
4570 // so, use the same DPTR or DPTR2.
4571 if (operandsEqu (IC_LEFT(ic), IC_RESULT(ic)))
4573 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
4576 if (operandsEqu (IC_RIGHT(ic), IC_RESULT(ic)))
4578 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
4582 // Note which dptrs are currently in use.
4583 dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
4584 dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
4586 // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot
4588 if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
4593 // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
4594 if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
4599 // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck
4600 if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
4605 aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
4607 // Some sanity checking...
4608 if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
4611 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
4612 __FILE__, __LINE__, ic->filename, ic->lineno);
4613 emitcode(";", ">>> unexpected DPTR here.");
4616 if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
4619 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
4620 __FILE__, __LINE__, ic->filename, ic->lineno);
4621 emitcode(";", ">>> unexpected DPTR2 here.");
4627 // Macro to aopOp all three operands of an ic. If this cannot be done,
4628 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
4629 // will be set TRUE. The caller must then handle the case specially, noting
4630 // that the IC_RESULT operand is not aopOp'd.
4632 #define AOP_OP_3_NOFATAL(ic, rc) \
4633 do { rc = !aopOp3(ic); } while (0)
4635 // aopOp the left & right operands of an ic.
4636 #define AOP_OP_2(ic) \
4637 aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
4638 aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
4640 // convienience macro.
4641 #define AOP_SET_LOCALS(ic) \
4642 left = IC_LEFT(ic); \
4643 right = IC_RIGHT(ic); \
4644 result = IC_RESULT(ic);
4647 // Given an integer value of pushedSize bytes on the stack,
4648 // adjust it to be resultSize bytes, either by discarding
4649 // the most significant bytes or by zero-padding.
4651 // On exit from this macro, pushedSize will have been adjusted to
4652 // equal resultSize, and ACC may be trashed.
4653 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
4654 /* If the pushed data is bigger than the result, \
4655 * simply discard unused bytes. Icky, but works. \
4657 while (pushedSize > resultSize) \
4659 D (emitcode (";", "discarding unused result byte."););\
4660 emitcode ("pop", "acc"); \
4663 if (pushedSize < resultSize) \
4665 emitcode ("clr", "a"); \
4666 /* Conversly, we haven't pushed enough here. \
4667 * just zero-pad, and all is well. \
4669 while (pushedSize < resultSize) \
4671 emitcode("push", "acc"); \
4675 assert(pushedSize == resultSize);
4677 /*-----------------------------------------------------------------*/
4678 /* genPlus - generates code for addition */
4679 /*-----------------------------------------------------------------*/
4681 genPlus (iCode * ic)
4683 int size, offset = 0;
4686 bool swappedLR = FALSE;
4688 D (emitcode (";", "genPlus "));
4690 /* special cases :- */
4691 if ( AOP_IS_STR(IC_LEFT(ic)) &&
4692 isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
4693 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
4694 size = (int)floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
4696 while (size--) emitcode ("inc","dptr");
4698 emitcode ("mov","a,dpl");
4699 emitcode ("add","a,#!constbyte",size & 0xff);
4700 emitcode ("mov","dpl,a");
4701 emitcode ("mov","a,dph");
4702 emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
4703 emitcode ("mov","dph,a");
4704 emitcode ("mov","a,dpx");
4705 emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
4706 emitcode ("mov","dpx,a");
4708 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4711 if ( IS_SYMOP(IC_LEFT(ic)) &&
4712 OP_SYMBOL(IC_LEFT(ic))->remat &&
4713 isOperandInFarSpace(IC_RIGHT(ic))) {
4714 operand *op = IC_RIGHT(ic);
4715 IC_RIGHT(ic) = IC_LEFT(ic);
4719 AOP_OP_3_NOFATAL (ic, pushResult);
4723 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
4728 /* if literal, literal on the right or
4729 if left requires ACC or right is already
4731 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4732 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
4733 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4735 operand *t = IC_RIGHT (ic);
4736 IC_RIGHT (ic) = IC_LEFT (ic);
4739 emitcode (";", "Swapped plus args.");
4742 /* if both left & right are in bit
4744 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4745 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4751 /* if left in bit space & right literal */
4752 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4753 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4755 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4756 /* if result in bit space */
4757 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4759 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4760 emitcode ("cpl", "c");
4761 outBitC (IC_RESULT (ic));
4765 size = getDataSize (IC_RESULT (ic));
4766 _startLazyDPSEvaluation ();
4769 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4770 emitcode ("addc", "a,%s", zero);
4771 aopPut (IC_RESULT (ic), "a", offset++);
4773 _endLazyDPSEvaluation ();
4778 /* if I can do an increment instead
4779 of add then GOOD for ME */
4780 if (genPlusIncr (ic) == TRUE)
4782 emitcode (";", "did genPlusIncr");
4787 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4789 _startLazyDPSEvaluation ();
4792 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4794 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
4796 emitcode ("add", "a,%s",
4797 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4799 emitcode ("addc", "a,%s",
4800 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4804 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4806 /* right is going to use ACC or we would have taken the
4809 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4811 D(emitcode(";", "+ AOP_ACC special case."););
4812 emitcode("xch", "a, %s", DP2_RESULT_REG);
4814 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
4817 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4820 emitcode("add", "a, %s", DP2_RESULT_REG);
4824 emitcode ("add", "a,%s",
4825 aopGet (IC_LEFT(ic), offset, FALSE, FALSE,
4831 emitcode ("addc", "a,%s",
4832 aopGet (IC_LEFT (ic), offset, FALSE, FALSE,
4838 aopPut (IC_RESULT (ic), "a", offset);
4842 emitcode ("push", "acc");
4846 _endLazyDPSEvaluation ();
4850 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4852 size = getDataSize (IC_LEFT (ic));
4853 rSize = getDataSize (IC_RESULT (ic));
4855 ADJUST_PUSHED_RESULT(size, rSize);
4857 _startLazyDPSEvaluation ();
4860 emitcode ("pop", "acc");
4861 aopPut (IC_RESULT (ic), "a", size);
4863 _endLazyDPSEvaluation ();
4866 adjustArithmeticResult (ic);
4869 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4872 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4873 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4877 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4878 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4882 /*-----------------------------------------------------------------*/
4883 /* genMinusDec :- does subtraction with decrement if possible */
4884 /*-----------------------------------------------------------------*/
4886 genMinusDec (iCode * ic)
4888 unsigned int icount;
4889 unsigned int size = getDataSize (IC_RESULT (ic));
4891 /* will try to generate an increment */
4892 /* if the right side is not a literal
4894 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4897 /* if the literal value of the right hand side
4898 is greater than 4 then it is not worth it */
4899 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4902 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4903 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4905 emitcode("dec","%s",aopGet(IC_RESULT(ic),0,FALSE,FALSE,NULL));
4909 /* if decrement 16 bits in register */
4910 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4911 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4912 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4921 /* If the next instruction is a goto and the goto target
4922 * is <= 5 instructions previous to this, we can generate
4923 * jumps straight to that target.
4925 if (ic->next && ic->next->op == GOTO
4926 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4929 emitcode (";", "tail decrement optimized (range %d)", labelRange);
4930 tlbl = IC_LABEL (ic->next);
4935 tlbl = newiTempLabel (NULL);
4939 l = aopGet (IC_RESULT (ic), LSB, FALSE, FALSE, NULL);
4940 emitcode ("dec", "%s", l);
4942 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4943 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4944 IS_AOP_PREG (IC_RESULT (ic)))
4946 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4950 emitcode ("mov", "a,#!constbyte",0xff);
4951 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4953 l = aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE, NULL);
4954 emitcode ("dec", "%s", l);
4957 if (!strcmp(l, "acc"))
4959 emitcode("jnz", "!tlabel", tlbl->key + 100);
4961 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4962 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4963 IS_AOP_PREG (IC_RESULT (ic)))
4965 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4969 emitcode ("mov", "a,#!constbyte",0xff);
4970 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4972 l = aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE, NULL);
4973 emitcode ("dec", "%s", l);
4977 if (!strcmp(l, "acc"))
4979 emitcode("jnz", "!tlabel", tlbl->key + 100);
4981 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4982 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4983 IS_AOP_PREG (IC_RESULT (ic)))
4985 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4989 emitcode ("mov", "a,#!constbyte",0xff);
4990 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4992 l = aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE, NULL);
4993 emitcode ("dec", "%s", l);
4997 emitcode ("", "!tlabeldef", tlbl->key + 100);
5002 /* if the sizes are greater than 1 then we cannot */
5003 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
5004 AOP_SIZE (IC_LEFT (ic)) > 1)
5007 /* we can if the aops of the left & result match or
5008 if they are in registers and the registers are the
5011 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
5012 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
5013 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
5017 if (aopGetUsesAcc (IC_LEFT (ic), 0))
5019 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL));
5024 l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL);
5027 _startLazyDPSEvaluation ();
5030 emitcode ("dec", "%s", l);
5032 _endLazyDPSEvaluation ();
5034 if (AOP_NEEDSACC (IC_RESULT (ic)))
5035 aopPut (IC_RESULT (ic), "a", 0);
5043 /*-----------------------------------------------------------------*/
5044 /* addSign - complete with sign */
5045 /*-----------------------------------------------------------------*/
5047 addSign (operand * result, int offset, int sign)
5049 int size = (getDataSize (result) - offset);
5052 _startLazyDPSEvaluation();
5055 emitcode ("rlc", "a");
5056 emitcode ("subb", "a,acc");
5059 aopPut (result, "a", offset++);
5066 aopPut (result, zero, offset++);
5069 _endLazyDPSEvaluation();
5073 /*-----------------------------------------------------------------*/
5074 /* genMinusBits - generates code for subtraction of two bits */
5075 /*-----------------------------------------------------------------*/
5077 genMinusBits (iCode * ic)
5079 symbol *lbl = newiTempLabel (NULL);
5081 D (emitcode (";", "genMinusBits "));
5083 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
5085 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
5086 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
5087 emitcode ("cpl", "c");
5088 emitcode ("", "!tlabeldef", (lbl->key + 100));
5089 outBitC (IC_RESULT (ic));
5093 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
5094 emitcode ("subb", "a,acc");
5095 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
5096 emitcode ("inc", "a");
5097 emitcode ("", "!tlabeldef", (lbl->key + 100));
5098 aopPut (IC_RESULT (ic), "a", 0);
5099 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
5103 /*-----------------------------------------------------------------*/
5104 /* genMinus - generates code for subtraction */
5105 /*-----------------------------------------------------------------*/
5107 genMinus (iCode * ic)
5109 int size, offset = 0;
5114 D (emitcode (";", "genMinus "));
5116 AOP_OP_3_NOFATAL(ic, pushResult);
5120 /* special cases :- */
5121 /* if both left & right are in bit space */
5122 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
5123 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
5129 /* if I can do an decrement instead
5130 of subtract then GOOD for ME */
5131 if (genMinusDec (ic) == TRUE)
5136 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
5138 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
5144 lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5149 /* if literal, add a,#-lit, else normal subb */
5150 _startLazyDPSEvaluation ();
5152 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
5153 if (AOP_USESDPTR(IC_RIGHT(ic))) {
5154 emitcode ("mov","b,%s",
5155 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE, NULL));
5156 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
5157 emitcode ("subb","a,b");
5159 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
5160 emitcode ("subb", "a,%s",
5161 aopGet (IC_RIGHT (ic), offset, FALSE, FALSE,
5165 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE, NULL));
5166 /* first add without previous c */
5168 if (!size && lit==-1) {
5169 emitcode ("dec", "a");
5171 emitcode ("add", "a,#!constbyte",
5172 (unsigned int) (lit & 0x0FFL));
5175 emitcode ("addc", "a,#!constbyte",
5176 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5181 emitcode ("push", "acc");
5183 aopPut (IC_RESULT (ic), "a", offset);
5187 _endLazyDPSEvaluation ();
5191 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
5193 size = getDataSize (IC_LEFT (ic));
5194 rSize = getDataSize (IC_RESULT (ic));
5196 ADJUST_PUSHED_RESULT(size, rSize);
5198 _startLazyDPSEvaluation ();
5201 emitcode ("pop", "acc");
5202 aopPut (IC_RESULT (ic), "a", size);
5204 _endLazyDPSEvaluation ();
5207 adjustArithmeticResult (ic);
5210 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
5211 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5212 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5216 /*-----------------------------------------------------------------*/
5217 /* genMultbits :- multiplication of bits */
5218 /*-----------------------------------------------------------------*/
5220 genMultbits (operand * left,
5225 D(emitcode (";", "genMultbits"));
5227 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5228 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5229 aopOp(result, ic, TRUE, FALSE);
5233 /*-----------------------------------------------------------------*/
5234 /* genMultOneByte : 8*8=8/16 bit multiplication */
5235 /*-----------------------------------------------------------------*/
5237 genMultOneByte (operand * left,
5244 bool runtimeSign, compiletimeSign;
5245 bool lUnsigned, rUnsigned, pushedB;
5247 /* (if two literals: the value is computed before) */
5248 /* if one literal, literal on the right */
5249 if (AOP_TYPE (left) == AOP_LIT)
5254 /* emitcode (";", "swapped left and right"); */
5256 /* if no literal, unsigned on the right: shorter code */
5257 if ( AOP_TYPE (right) != AOP_LIT
5258 && SPEC_USIGN (getSpec (operandType (left))))
5265 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5266 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5270 if ((lUnsigned && rUnsigned)
5271 /* sorry, I don't know how to get size
5272 without calling aopOp (result,...);
5273 see Feature Request */
5274 /* || size == 1 */ ) /* no, this is not a bug; with a 1 byte result there's
5275 no need to take care about the signedness! */
5277 /* just an unsigned 8 * 8 = 8 multiply
5279 /* emitcode (";","unsigned"); */
5280 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
5281 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
5282 emitcode ("mul", "ab");
5285 aopOp (result, ic, TRUE, FALSE);
5286 size = AOP_SIZE (result);
5288 if (size < 1 || size > 2)
5290 /* this should never happen */
5291 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
5292 size, __FILE__, lineno);
5296 aopPut (result, "a", 0);
5299 aopPut (result, "b", 1);
5305 /* we have to do a signed multiply */
5306 /* emitcode (";", "signed"); */
5308 /* now sign adjust for both left & right */
5310 /* let's see what's needed: */
5311 /* apply negative sign during runtime */
5312 runtimeSign = FALSE;
5313 /* negative sign from literals */
5314 compiletimeSign = FALSE;
5318 if (AOP_TYPE(left) == AOP_LIT)
5320 /* signed literal */
5321 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5323 compiletimeSign = TRUE;
5326 /* signed but not literal */
5332 if (AOP_TYPE(right) == AOP_LIT)
5334 /* signed literal */
5335 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5337 compiletimeSign ^= TRUE;
5340 /* signed but not literal */
5344 /* initialize F0, which stores the runtime sign */
5347 if (compiletimeSign)
5348 emitcode ("setb", "F0"); /* set sign flag */
5350 emitcode ("clr", "F0"); /* reset sign flag */
5353 /* save the signs of the operands */
5354 if (AOP_TYPE(right) == AOP_LIT)
5356 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5358 if (!rUnsigned && val < 0)
5359 emitcode ("mov", "b,#!constbyte", -val);
5361 emitcode ("mov", "b,#!constbyte", (unsigned char) val);
5363 else /* ! literal */
5365 if (rUnsigned) /* emitcode (";", "signed"); */
5366 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
5369 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
5370 lbl = newiTempLabel (NULL);
5371 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5372 emitcode ("cpl", "F0"); /* complement sign flag */
5373 emitcode ("cpl", "a"); /* 2's complement */
5374 emitcode ("inc", "a");
5375 emitcode ("", "!tlabeldef", lbl->key + 100);
5376 emitcode ("mov", "b,a");
5380 if (AOP_TYPE(left) == AOP_LIT)
5382 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5384 if (!lUnsigned && val < 0)
5385 emitcode ("mov", "a,#!constbyte", -val);
5387 emitcode ("mov", "a,#!constbyte", (unsigned char) val);
5389 else /* ! literal */
5391 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
5393 if (!lUnsigned) /* emitcode (";", "signed"); */
5395 lbl = newiTempLabel (NULL);
5396 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5397 emitcode ("cpl", "F0"); /* complement sign flag */
5398 emitcode ("cpl", "a"); /* 2's complement */
5399 emitcode ("inc", "a");
5400 emitcode ("", "!tlabeldef", lbl->key + 100);
5404 /* now the multiplication */
5405 emitcode ("mul", "ab");
5407 aopOp(result, ic, TRUE, FALSE);
5408 size = AOP_SIZE (result);
5410 if (size < 1 || size > 2)
5412 /* this should never happen */
5413 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
5414 size, __FILE__, lineno);
5418 if (runtimeSign || compiletimeSign)
5420 lbl = newiTempLabel (NULL);
5422 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5423 emitcode ("cpl", "a"); /* lsb 2's complement */
5425 emitcode ("inc", "a"); /* inc doesn't set carry flag */
5428 emitcode ("add", "a,#1"); /* this sets carry flag */
5429 emitcode ("xch", "a,b");
5430 emitcode ("cpl", "a"); /* msb 2's complement */
5431 emitcode ("addc", "a,#0");
5432 emitcode ("xch", "a,b");
5434 emitcode ("", "!tlabeldef", lbl->key + 100);
5436 aopPut (result, "a", 0);
5439 aopPut (result, "b", 1);
5444 /*-----------------------------------------------------------------*/
5445 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
5446 /*-----------------------------------------------------------------*/
5447 static void genMultTwoByte (operand *left, operand *right,
5448 operand *result, iCode *ic)
5450 sym_link *retype = getSpec(operandType(right));
5451 sym_link *letype = getSpec(operandType(left));
5452 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5455 if (AOP_TYPE (left) == AOP_LIT) {
5460 /* save EA bit in F1 */
5461 lbl = newiTempLabel(NULL);
5462 emitcode ("setb","F1");
5463 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5464 emitcode ("clr","F1");
5465 emitcode("","!tlabeldef",lbl->key+100);
5467 /* load up MB with right */
5469 emitcode("clr","F0");
5470 if (AOP_TYPE(right) == AOP_LIT) {
5471 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5473 emitcode("setb","F0");
5476 emitcode ("mov","mb,#!constbyte",val & 0xff);
5477 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5479 lbl = newiTempLabel(NULL);
5480 emitcode ("mov","b,%s",aopGet(right,0,FALSE,FALSE,NULL));
5481 emitcode ("mov","a,%s",aopGet(right,1,FALSE,FALSE,NULL));
5482 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5483 emitcode ("xch", "a,b");
5484 emitcode ("cpl","a");
5485 emitcode ("add", "a,#1");
5486 emitcode ("xch", "a,b");
5487 emitcode ("cpl", "a"); // msb
5488 emitcode ("addc", "a,#0");
5489 emitcode ("setb","F0");
5490 emitcode ("","!tlabeldef",lbl->key+100);
5491 emitcode ("mov","mb,b");
5492 emitcode ("mov","mb,a");
5495 emitcode ("mov","mb,%s",aopGet(right,0,FALSE,FALSE,NULL));
5496 emitcode ("mov","mb,%s",aopGet(right,1,FALSE,FALSE,NULL));
5498 /* load up MA with left */
5500 lbl = newiTempLabel(NULL);
5501 emitcode ("mov","b,%s",aopGet(left,0,FALSE,FALSE,NULL));
5502 emitcode ("mov","a,%s",aopGet(left,1,FALSE,FALSE,NULL));
5503 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5504 emitcode ("xch", "a,b");
5505 emitcode ("cpl","a");
5506 emitcode ("add", "a,#1");
5507 emitcode ("xch", "a,b");
5508 emitcode ("cpl", "a"); // msb
5509 emitcode ("addc","a,#0");
5510 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5511 emitcode ("setb","F0");
5512 emitcode ("","!tlabeldef",lbl->key+100);
5513 emitcode ("mov","ma,b");
5514 emitcode ("mov","ma,a");
5516 emitcode ("mov","ma,%s",aopGet(left,0,FALSE,FALSE,NULL));
5517 emitcode ("mov","ma,%s",aopGet(left,1,FALSE,FALSE,NULL));
5519 /* wait for multiplication to finish */
5520 lbl = newiTempLabel(NULL);
5521 emitcode("","!tlabeldef", lbl->key+100);
5522 emitcode("mov","a,mcnt1");
5523 emitcode("anl","a,#!constbyte",0x80);
5524 emitcode("jnz","!tlabel",lbl->key+100);
5526 freeAsmop (left, NULL, ic, TRUE);
5527 freeAsmop (right, NULL, ic,TRUE);
5528 aopOp(result, ic, TRUE, FALSE);
5530 /* if unsigned then simple */
5532 emitcode ("mov","a,ma");
5533 if (AOP_SIZE(result) >= 4) aopPut(result,"a",3);
5534 emitcode ("mov","a,ma");
5535 if (AOP_SIZE(result) >= 3) aopPut(result,"a",2);
5536 aopPut(result,"ma",1);
5537 aopPut(result,"ma",0);
5539 emitcode("push","ma");
5540 emitcode("push","ma");
5541 emitcode("push","ma");
5543 /* negate result if needed */
5544 lbl = newiTempLabel(NULL);
5545 emitcode("jnb","F0,!tlabel",lbl->key+100);
5546 emitcode("cpl","a");
5547 emitcode("add","a,#1");
5548 emitcode("","!tlabeldef", lbl->key+100);
5549 if (AOP_TYPE(result) == AOP_ACC)
5551 D(emitcode(";", "ACC special case."););
5552 /* We know result is the only live aop, and
5553 * it's obviously not a DPTR2, so AP is available.
5555 emitcode("mov", "%s,acc", DP2_RESULT_REG);
5559 aopPut(result,"a",0);
5562 emitcode("pop","acc");
5563 lbl = newiTempLabel(NULL);
5564 emitcode("jnb","F0,!tlabel",lbl->key+100);
5565 emitcode("cpl","a");
5566 emitcode("addc","a,#0");
5567 emitcode("","!tlabeldef", lbl->key+100);
5568 aopPut(result,"a",1);
5569 emitcode("pop","acc");
5570 if (AOP_SIZE(result) >= 3) {
5571 lbl = newiTempLabel(NULL);
5572 emitcode("jnb","F0,!tlabel",lbl->key+100);
5573 emitcode("cpl","a");
5574 emitcode("addc","a,#0");
5575 emitcode("","!tlabeldef", lbl->key+100);
5576 aopPut(result,"a",2);
5578 emitcode("pop","acc");
5579 if (AOP_SIZE(result) >= 4) {
5580 lbl = newiTempLabel(NULL);
5581 emitcode("jnb","F0,!tlabel",lbl->key+100);
5582 emitcode("cpl","a");
5583 emitcode("addc","a,#0");
5584 emitcode("","!tlabeldef", lbl->key+100);
5585 aopPut(result,"a",3);
5587 if (AOP_TYPE(result) == AOP_ACC)
5589 /* We stashed the result away above. */
5590 emitcode("mov", "acc,%s", DP2_RESULT_REG);
5594 freeAsmop (result, NULL, ic, TRUE);
5596 /* restore EA bit in F1 */
5597 lbl = newiTempLabel(NULL);
5598 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5599 emitcode ("setb","EA");
5600 emitcode("","!tlabeldef",lbl->key+100);
5604 /*-----------------------------------------------------------------*/
5605 /* genMult - generates code for multiplication */
5606 /*-----------------------------------------------------------------*/
5608 genMult (iCode * ic)
5610 operand *left = IC_LEFT (ic);
5611 operand *right = IC_RIGHT (ic);
5612 operand *result = IC_RESULT (ic);
5614 D (emitcode (";", "genMult "));
5616 /* assign the asmops */
5619 /* special cases first */
5621 if (AOP_TYPE (left) == AOP_CRY &&
5622 AOP_TYPE (right) == AOP_CRY)
5624 genMultbits (left, right, result, ic);
5628 /* if both are of size == 1 */
5629 if (AOP_SIZE (left) == 1 &&
5630 AOP_SIZE (right) == 1)
5632 genMultOneByte (left, right, result, ic);
5636 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5637 /* use the ds390 ARITHMETIC accel UNIT */
5638 genMultTwoByte (left, right, result, ic);
5641 /* should have been converted to function call */
5645 freeAsmop (result, NULL, ic, TRUE);
5646 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5647 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5650 /*-----------------------------------------------------------------*/
5651 /* genDivbits :- division of bits */
5652 /*-----------------------------------------------------------------*/
5654 genDivbits (operand * left,
5662 D(emitcode ("; genDivbits",""));
5666 /* the result must be bit */
5667 LOAD_AB_FOR_DIV (left, right, l);
5668 emitcode ("div", "ab");
5669 emitcode ("rrc", "a");
5670 aopOp(result, ic, TRUE, FALSE);
5674 aopPut (result, "c", 0);
5677 /*-----------------------------------------------------------------*/
5678 /* genDivOneByte : 8 bit division */
5679 /*-----------------------------------------------------------------*/
5681 genDivOneByte (operand * left,
5686 bool lUnsigned, rUnsigned, pushedB;
5687 bool runtimeSign, compiletimeSign;
5692 D(emitcode ("; genDivOneByte",""));
5695 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5696 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5700 /* signed or unsigned */
5701 if (lUnsigned && rUnsigned)
5703 /* unsigned is easy */
5704 LOAD_AB_FOR_DIV (left, right, l);
5705 emitcode ("div", "ab");
5708 aopOp (result, ic, TRUE, FALSE);
5709 aopPut (result, "a", 0);
5712 size = AOP_SIZE (result) - 1;
5715 aopPut (result, zero, offset++);
5721 /* signed is a little bit more difficult */
5723 /* now sign adjust for both left & right */
5725 /* let's see what's needed: */
5726 /* apply negative sign during runtime */
5727 runtimeSign = FALSE;
5728 /* negative sign from literals */
5729 compiletimeSign = FALSE;
5733 if (AOP_TYPE(left) == AOP_LIT)
5735 /* signed literal */
5736 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5738 compiletimeSign = TRUE;
5741 /* signed but not literal */
5747 if (AOP_TYPE(right) == AOP_LIT)
5749 /* signed literal */
5750 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5752 compiletimeSign ^= TRUE;
5755 /* signed but not literal */
5759 /* initialize F0, which stores the runtime sign */
5762 if (compiletimeSign)
5763 emitcode ("setb", "F0"); /* set sign flag */
5765 emitcode ("clr", "F0"); /* reset sign flag */
5768 /* save the signs of the operands */
5769 if (AOP_TYPE(right) == AOP_LIT)
5771 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5773 if (!rUnsigned && val < 0)
5774 emitcode ("mov", "b,#0x%02x", -val);
5776 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5778 else /* ! literal */
5781 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
5784 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
5785 lbl = newiTempLabel (NULL);
5786 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5787 emitcode ("cpl", "F0"); /* complement sign flag */
5788 emitcode ("cpl", "a"); /* 2's complement */
5789 emitcode ("inc", "a");
5790 emitcode ("", "!tlabeldef", lbl->key + 100);
5791 emitcode ("mov", "b,a");
5795 if (AOP_TYPE(left) == AOP_LIT)
5797 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5799 if (!lUnsigned && val < 0)
5800 emitcode ("mov", "a,#0x%02x", -val);
5802 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5804 else /* ! literal */
5806 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
5810 lbl = newiTempLabel (NULL);
5811 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
5812 emitcode ("cpl", "F0"); /* complement sign flag */
5813 emitcode ("cpl", "a"); /* 2's complement */
5814 emitcode ("inc", "a");
5815 emitcode ("", "!tlabeldef", lbl->key + 100);
5819 /* now the division */
5820 emitcode ("nop", "; workaround for DS80C390 div bug.");
5821 emitcode ("div", "ab");
5823 if (runtimeSign || compiletimeSign)
5825 lbl = newiTempLabel (NULL);
5827 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
5828 emitcode ("cpl", "a"); /* lsb 2's complement */
5829 emitcode ("inc", "a");
5830 emitcode ("", "!tlabeldef", lbl->key + 100);
5833 aopOp (result, ic, TRUE, FALSE);
5834 size = AOP_SIZE (result) - 1;
5838 /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
5839 then the result will be in b, a */
5840 emitcode ("mov", "b,a"); /* 1 */
5841 /* msb is 0x00 or 0xff depending on the sign */
5844 emitcode ("mov", "c,F0");
5845 emitcode ("subb", "a,acc");
5846 emitcode ("xch", "a,b"); /* 2 */
5848 aopPut (result, "b", offset++); /* write msb's */
5850 else /* compiletimeSign */
5852 aopPut (result, "#0xff", offset++); /* write msb's */
5854 aopPut (result, "a", 0); /* 3: write lsb */
5859 aopOp(result, ic, TRUE, FALSE);
5860 size = AOP_SIZE (result) - 1;
5862 aopPut (result, "a", 0);
5864 aopPut (result, zero, offset++);
5870 /*-----------------------------------------------------------------*/
5871 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
5872 /*-----------------------------------------------------------------*/
5873 static void genDivTwoByte (operand *left, operand *right,
5874 operand *result, iCode *ic)
5876 sym_link *retype = getSpec(operandType(right));
5877 sym_link *letype = getSpec(operandType(left));
5878 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5881 /* save EA bit in F1 */
5882 lbl = newiTempLabel(NULL);
5883 emitcode ("setb","F1");
5884 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5885 emitcode ("clr","F1");
5886 emitcode("","!tlabeldef",lbl->key+100);
5888 /* load up MA with left */
5890 emitcode("clr","F0");
5891 lbl = newiTempLabel(NULL);
5892 emitcode ("mov","b,%s",aopGet(left,0,FALSE,FALSE,NULL));
5893 emitcode ("mov","a,%s",aopGet(left,1,FALSE,FALSE,NULL));
5894 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5895 emitcode ("xch", "a,b");
5896 emitcode ("cpl","a");
5897 emitcode ("add", "a,#1");
5898 emitcode ("xch", "a,b");
5899 emitcode ("cpl", "a"); // msb
5900 emitcode ("addc","a,#0");
5901 emitcode ("setb","F0");
5902 emitcode ("","!tlabeldef",lbl->key+100);
5903 emitcode ("mov","ma,b");
5904 emitcode ("mov","ma,a");
5906 emitcode ("mov","ma,%s",aopGet(left,0,FALSE,FALSE,NULL));
5907 emitcode ("mov","ma,%s",aopGet(left,1,FALSE,FALSE,NULL));
5910 /* load up MB with right */
5912 if (AOP_TYPE(right) == AOP_LIT) {
5913 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5915 lbl = newiTempLabel(NULL);
5916 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5917 emitcode("setb","F0");
5918 emitcode ("","!tlabeldef",lbl->key+100);
5921 emitcode ("mov","mb,#!constbyte",val & 0xff);
5922 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5924 lbl = newiTempLabel(NULL);
5925 emitcode ("mov","b,%s",aopGet(right,0,FALSE,FALSE,NULL));
5926 emitcode ("mov","a,%s",aopGet(right,1,FALSE,FALSE,NULL));
5927 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5928 emitcode ("xch", "a,b");
5929 emitcode ("cpl","a");
5930 emitcode ("add", "a,#1");
5931 emitcode ("xch", "a,b");
5932 emitcode ("cpl", "a"); // msb
5933 emitcode ("addc", "a,#0");
5934 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5935 emitcode ("setb","F0");
5936 emitcode ("","!tlabeldef",lbl->key+100);
5937 emitcode ("mov","mb,b");
5938 emitcode ("mov","mb,a");
5941 emitcode ("mov","mb,%s",aopGet(right,0,FALSE,FALSE,NULL));
5942 emitcode ("mov","mb,%s",aopGet(right,1,FALSE,FALSE,NULL));
5945 /* wait for multiplication to finish */
5946 lbl = newiTempLabel(NULL);
5947 emitcode("","!tlabeldef", lbl->key+100);
5948 emitcode("mov","a,mcnt1");
5949 emitcode("anl","a,#!constbyte",0x80);
5950 emitcode("jnz","!tlabel",lbl->key+100);
5952 freeAsmop (left, NULL, ic, TRUE);
5953 freeAsmop (right, NULL, ic,TRUE);
5954 aopOp(result, ic, TRUE, FALSE);
5956 /* if unsigned then simple */
5958 aopPut(result,"ma",1);
5959 aopPut(result,"ma",0);
5961 emitcode("push","ma");
5963 /* negate result if needed */
5964 lbl = newiTempLabel(NULL);
5965 emitcode("jnb","F0,!tlabel",lbl->key+100);
5966 emitcode("cpl","a");
5967 emitcode("add","a,#1");
5968 emitcode("","!tlabeldef", lbl->key+100);
5969 aopPut(result,"a",0);
5970 emitcode("pop","acc");
5971 lbl = newiTempLabel(NULL);
5972 emitcode("jnb","F0,!tlabel",lbl->key+100);
5973 emitcode("cpl","a");
5974 emitcode("addc","a,#0");
5975 emitcode("","!tlabeldef", lbl->key+100);
5976 aopPut(result,"a",1);
5978 freeAsmop (result, NULL, ic, TRUE);
5979 /* restore EA bit in F1 */
5980 lbl = newiTempLabel(NULL);
5981 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5982 emitcode ("setb","EA");
5983 emitcode("","!tlabeldef",lbl->key+100);
5987 /*-----------------------------------------------------------------*/
5988 /* genDiv - generates code for division */
5989 /*-----------------------------------------------------------------*/
5993 operand *left = IC_LEFT (ic);
5994 operand *right = IC_RIGHT (ic);
5995 operand *result = IC_RESULT (ic);
5997 D (emitcode (";", "genDiv "));
5999 /* assign the amsops */
6002 /* special cases first */
6004 if (AOP_TYPE (left) == AOP_CRY &&
6005 AOP_TYPE (right) == AOP_CRY)
6007 genDivbits (left, right, result, ic);
6011 /* if both are of size == 1 */
6012 if (AOP_SIZE (left) == 1 &&
6013 AOP_SIZE (right) == 1)
6015 genDivOneByte (left, right, result, ic);
6019 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
6020 /* use the ds390 ARITHMETIC accel UNIT */
6021 genDivTwoByte (left, right, result, ic);
6024 /* should have been converted to function call */
6027 freeAsmop (result, NULL, ic, TRUE);
6028 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6029 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6032 /*-----------------------------------------------------------------*/
6033 /* genModbits :- modulus of bits */
6034 /*-----------------------------------------------------------------*/
6036 genModbits (operand * left,
6044 D(emitcode ("; genModbits",""));
6048 /* the result must be bit */
6049 LOAD_AB_FOR_DIV (left, right, l);
6050 emitcode ("div", "ab");
6051 emitcode ("mov", "a,b");
6052 emitcode ("rrc", "a");
6053 aopOp(result, ic, TRUE, FALSE);
6057 aopPut (result, "c", 0);
6060 /*-----------------------------------------------------------------*/
6061 /* genModOneByte : 8 bit modulus */
6062 /*-----------------------------------------------------------------*/
6064 genModOneByte (operand * left,
6069 bool lUnsigned, rUnsigned, pushedB;
6070 bool runtimeSign, compiletimeSign;
6075 D(emitcode ("; genModOneByte",""));
6078 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
6079 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
6083 /* signed or unsigned */
6084 if (lUnsigned && rUnsigned)
6086 /* unsigned is easy */
6087 LOAD_AB_FOR_DIV (left, right, l);
6088 emitcode ("div", "ab");
6089 aopOp (result, ic, TRUE, FALSE);
6090 aopPut (result, "b", 0);
6092 for (size = AOP_SIZE (result) - 1; size--;)
6093 aopPut (result, zero, offset++);
6099 /* signed is a little bit more difficult */
6101 /* now sign adjust for both left & right */
6103 /* modulus: sign of the right operand has no influence on the result! */
6104 if (AOP_TYPE(right) == AOP_LIT)
6106 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
6108 if (!rUnsigned && val < 0)
6109 emitcode ("mov", "b,#0x%02x", -val);
6111 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
6113 else /* not literal */
6116 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE, NULL));
6119 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
6120 lbl = newiTempLabel (NULL);
6121 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
6122 emitcode ("cpl", "a"); /* 2's complement */
6123 emitcode ("inc", "a");
6124 emitcode ("", "!tlabeldef", lbl->key + 100);
6125 emitcode ("mov", "b,a");
6129 /* let's see what's needed: */
6130 /* apply negative sign during runtime */
6131 runtimeSign = FALSE;
6132 /* negative sign from literals */
6133 compiletimeSign = FALSE;
6135 /* sign adjust left side */
6136 if (AOP_TYPE(left) == AOP_LIT)
6138 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
6140 if (!lUnsigned && val < 0)
6142 compiletimeSign = TRUE; /* set sign flag */
6143 emitcode ("mov", "a,#0x%02x", -val);
6146 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
6148 else /* ! literal */
6150 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
6155 emitcode ("clr", "F0"); /* clear sign flag */
6157 lbl = newiTempLabel (NULL);
6158 emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
6159 emitcode ("setb", "F0"); /* set sign flag */
6160 emitcode ("cpl", "a"); /* 2's complement */
6161 emitcode ("inc", "a");
6162 emitcode ("", "!tlabeldef", lbl->key + 100);
6166 /* now the modulus */
6167 emitcode ("nop", "; workaround for DS80C390 div bug.");
6168 emitcode ("div", "ab");
6170 if (runtimeSign || compiletimeSign)
6172 emitcode ("mov", "a,b");
6173 lbl = newiTempLabel (NULL);
6175 emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
6176 emitcode ("cpl", "a"); /* lsb 2's complement */
6177 emitcode ("inc", "a");
6178 emitcode ("", "!tlabeldef", lbl->key + 100);
6181 aopOp (result, ic, TRUE, FALSE);
6182 size = AOP_SIZE (result) - 1;
6186 /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
6187 then the result will be in b, a */
6188 emitcode ("mov", "b,a"); /* 1 */
6189 /* msb is 0x00 or 0xff depending on the sign */
6192 emitcode ("mov", "c,F0");
6193 emitcode ("subb", "a,acc");
6194 emitcode ("xch", "a,b"); /* 2 */
6196 aopPut (result, "b", offset++); /* write msb's */
6198 else /* compiletimeSign */
6200 aopPut (result, "#0xff", offset++); /* write msb's */
6202 aopPut (result, "a", 0); /* 3: write lsb */
6207 aopOp(result, ic, TRUE, FALSE);
6208 size = AOP_SIZE (result) - 1;
6210 aopPut (result, "b", 0);
6212 aopPut (result, zero, offset++);
6218 /*-----------------------------------------------------------------*/
6219 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
6220 /*-----------------------------------------------------------------*/
6221 static void genModTwoByte (operand *left, operand *right,
6222 operand *result, iCode *ic)
6224 sym_link *retype = getSpec(operandType(right));
6225 sym_link *letype = getSpec(operandType(left));
6226 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
6229 /* load up MA with left */
6230 /* save EA bit in F1 */
6231 lbl = newiTempLabel(NULL);
6232 emitcode ("setb","F1");
6233 emitcode ("jbc","EA,!tlabel",lbl->key+100);
6234 emitcode ("clr","F1");
6235 emitcode("","!tlabeldef",lbl->key+100);
6238 lbl = newiTempLabel(NULL);
6239 emitcode ("mov","b,%s",aopGet(left,0,FALSE,FALSE,NULL));
6240 emitcode ("mov","a,%s",aopGet(left,1,FALSE,FALSE,NULL));
6241 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
6242 emitcode ("xch", "a,b");
6243 emitcode ("cpl","a");
6244 emitcode ("add", "a,#1");
6245 emitcode ("xch", "a,b");
6246 emitcode ("cpl", "a"); // msb
6247 emitcode ("addc","a,#0");
6248 emitcode ("","!tlabeldef",lbl->key+100);
6249 emitcode ("mov","ma,b");
6250 emitcode ("mov","ma,a");
6252 emitcode ("mov","ma,%s",aopGet(left,0,FALSE,FALSE,NULL));
6253 emitcode ("mov","ma,%s",aopGet(left,1,FALSE,FALSE,NULL));
6256 /* load up MB with right */
6258 if (AOP_TYPE(right) == AOP_LIT) {
6259 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
6263 emitcode ("mov","mb,#!constbyte",val & 0xff);
6264 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
6266 lbl = newiTempLabel(NULL);
6267 emitcode ("mov","b,%s",aopGet(right,0,FALSE,FALSE,NULL));
6268 emitcode ("mov","a,%s",aopGet(right,1,FALSE,FALSE,NULL));
6269 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
6270 emitcode ("xch", "a,b");
6271 emitcode ("cpl","a");
6272 emitcode ("add", "a,#1");
6273 emitcode ("xch", "a,b");
6274 emitcode ("cpl", "a"); // msb
6275 emitcode ("addc", "a,#0");
6276 emitcode ("","!tlabeldef",lbl->key+100);
6277 emitcode ("mov","mb,b");
6278 emitcode ("mov","mb,a");
6281 emitcode ("mov","mb,%s",aopGet(right,0,FALSE,FALSE,NULL));
6282 emitcode ("mov","mb,%s",aopGet(right,1,FALSE,FALSE,NULL));
6285 /* wait for multiplication to finish */
6286 lbl = newiTempLabel(NULL);
6287 emitcode("","!tlabeldef", lbl->key+100);
6288 emitcode("mov","a,mcnt1");
6289 emitcode("anl","a,#!constbyte",0x80);
6290 emitcode("jnz","!tlabel",lbl->key+100);
6292 freeAsmop (left, NULL, ic, TRUE);
6293 freeAsmop (right, NULL, ic,TRUE);
6294 aopOp(result, ic, TRUE, FALSE);
6296 aopPut(result,"mb",1);
6297 aopPut(result,"mb",0);
6298 freeAsmop (result, NULL, ic, TRUE);
6300 /* restore EA bit in F1 */
6301 lbl = newiTempLabel(NULL);
6302 emitcode ("jnb","F1,!tlabel",lbl->key+100);
6303 emitcode ("setb","EA");
6304 emitcode("","!tlabeldef",lbl->key+100);
6308 /*-----------------------------------------------------------------*/
6309 /* genMod - generates code for division */
6310 /*-----------------------------------------------------------------*/
6314 operand *left = IC_LEFT (ic);
6315 operand *right = IC_RIGHT (ic);
6316 operand *result = IC_RESULT (ic);
6318 D (emitcode (";", "genMod "));
6320 /* assign the asmops */
6323 /* special cases first */
6325 if (AOP_TYPE (left) == AOP_CRY &&
6326 AOP_TYPE (right) == AOP_CRY)
6328 genModbits (left, right, result, ic);
6332 /* if both are of size == 1 */
6333 if (AOP_SIZE (left) == 1 &&
6334 AOP_SIZE (right) == 1)
6336 genModOneByte (left, right, result, ic);
6340 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
6341 /* use the ds390 ARITHMETIC accel UNIT */
6342 genModTwoByte (left, right, result, ic);
6346 /* should have been converted to function call */
6350 freeAsmop (result, NULL, ic, TRUE);
6351 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6352 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6355 /*-----------------------------------------------------------------*/
6356 /* genIfxJump :- will create a jump depending on the ifx */
6357 /*-----------------------------------------------------------------*/
6359 genIfxJump (iCode * ic, char *jval)
6362 symbol *tlbl = newiTempLabel (NULL);
6365 D (emitcode (";", "genIfxJump"));
6367 /* if true label then we jump if condition
6371 jlbl = IC_TRUE (ic);
6372 inst = ((strcmp (jval, "a") == 0 ? "jz" :
6373 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
6377 /* false label is present */
6378 jlbl = IC_FALSE (ic);
6379 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
6380 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
6382 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
6383 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
6385 emitcode (inst, "!tlabel", tlbl->key + 100);
6386 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
6387 emitcode ("", "!tlabeldef", tlbl->key + 100);
6389 /* mark the icode as generated */
6393 /*-----------------------------------------------------------------*/
6394 /* genCmp :- greater or less than comparison */
6395 /*-----------------------------------------------------------------*/
6397 genCmp (operand * left, operand * right,
6398 iCode * ic, iCode * ifx, int sign)
6400 int size, offset = 0;
6401 unsigned long lit = 0L;
6404 D (emitcode (";", "genCmp"));
6406 result = IC_RESULT (ic);
6408 /* if left & right are bit variables */
6409 if (AOP_TYPE (left) == AOP_CRY &&
6410 AOP_TYPE (right) == AOP_CRY)
6412 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6413 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6417 /* subtract right from left if at the
6418 end the carry flag is set then we know that
6419 left is greater than right */
6420 size = max (AOP_SIZE (left), AOP_SIZE (right));
6422 /* if unsigned char cmp with lit, do cjne left,#right,zz */
6423 if ((size == 1) && !sign &&
6424 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
6426 symbol *lbl = newiTempLabel (NULL);
6427 emitcode ("cjne", "%s,%s,!tlabel",
6428 aopGet (left, offset, FALSE, FALSE, NULL),
6429 aopGet (right, offset, FALSE, FALSE, NULL),
6431 emitcode ("", "!tlabeldef", lbl->key + 100);
6435 if (AOP_TYPE (right) == AOP_LIT)
6437 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6438 /* optimize if(x < 0) or if(x >= 0) */
6447 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
6449 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6450 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6452 aopOp (result, ic, FALSE, FALSE);
6454 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
6456 freeAsmop (result, NULL, ic, TRUE);
6457 genIfxJump (ifx, "acc.7");
6462 emitcode ("rlc", "a");
6464 goto release_freedLR;
6472 // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
6473 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
6474 // emitcode (";", "genCmp #2");
6475 if (sign && (size == 0))
6477 // emitcode (";", "genCmp #3");
6478 emitcode ("xrl", "a,#!constbyte",0x80);
6479 if (AOP_TYPE (right) == AOP_LIT)
6481 unsigned long lit = (unsigned long)
6482 floatFromVal (AOP (right)->aopu.aop_lit);
6483 // emitcode (";", "genCmp #3.1");
6484 emitcode ("subb", "a,#!constbyte",
6485 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
6489 // emitcode (";", "genCmp #3.2");
6491 MOVB (aopGet (right, offset++, FALSE, FALSE, "b"));
6492 saveAccWarn = DEFAULT_ACC_WARNING;
6493 emitcode ("xrl", "b,#!constbyte",0x80);
6494 emitcode ("subb", "a,b");
6501 // emitcode (";", "genCmp #4");
6503 s = aopGet (right, offset++, FALSE, FALSE, "b");
6504 saveAccWarn = DEFAULT_ACC_WARNING;
6506 emitcode ("subb", "a,%s", s);
6513 /* Don't need the left & right operands any more; do need the result. */
6514 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6515 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6517 aopOp (result, ic, FALSE, FALSE);
6521 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6527 /* if the result is used in the next
6528 ifx conditional branch then generate
6529 code a little differently */
6532 genIfxJump (ifx, "c");
6538 /* leave the result in acc */
6540 freeAsmop (result, NULL, ic, TRUE);
6543 /*-----------------------------------------------------------------*/
6544 /* genCmpGt :- greater than comparison */
6545 /*-----------------------------------------------------------------*/
6547 genCmpGt (iCode * ic, iCode * ifx)
6549 operand *left, *right;
6550 sym_link *letype, *retype;
6553 D (emitcode (";", "genCmpGt"));
6555 left = IC_LEFT (ic);
6556 right = IC_RIGHT (ic);
6558 letype = getSpec (operandType (left));
6559 retype = getSpec (operandType (right));
6560 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6562 /* assign the left & right amsops */
6565 genCmp (right, left, ic, ifx, sign);
6568 /*-----------------------------------------------------------------*/
6569 /* genCmpLt - less than comparisons */
6570 /*-----------------------------------------------------------------*/
6572 genCmpLt (iCode * ic, iCode * ifx)
6574 operand *left, *right;
6575 sym_link *letype, *retype;
6578 D (emitcode (";", "genCmpLt "));
6580 left = IC_LEFT (ic);
6581 right = IC_RIGHT (ic);
6583 letype = getSpec (operandType (left));
6584 retype = getSpec (operandType (right));
6585 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
6587 /* assign the left & right amsops */
6590 genCmp (left, right, ic, ifx, sign);
6593 /*-----------------------------------------------------------------*/
6594 /* gencjneshort - compare and jump if not equal */
6595 /*-----------------------------------------------------------------*/
6597 gencjneshort (operand * left, operand * right, symbol * lbl)
6599 int size = max (AOP_SIZE (left), AOP_SIZE (right));
6601 unsigned long lit = 0L;
6603 D (emitcode (";", "gencjneshort"));
6605 /* if the left side is a literal or
6606 if the right is in a pointer register and left
6608 if ((AOP_TYPE (left) == AOP_LIT) ||
6609 (AOP_TYPE (left) == AOP_IMMD) ||
6610 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6617 if (AOP_TYPE (right) == AOP_LIT)
6618 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6620 if (opIsGptr (left) || opIsGptr (right))
6622 /* We are comparing a generic pointer to something.
6623 * Exclude the generic type byte from the comparison.
6626 D (emitcode (";", "cjneshort: generic ptr special case."););
6630 /* if the right side is a literal then anything goes */
6631 if (AOP_TYPE (right) == AOP_LIT &&
6632 AOP_TYPE (left) != AOP_DIR)
6636 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
6637 emitcode ("cjne", "a,%s,!tlabel",
6638 aopGet (right, offset, FALSE, FALSE, NULL),
6644 /* if the right side is in a register or in direct space or
6645 if the left is a pointer register & right is not */
6646 else if (AOP_TYPE (right) == AOP_REG ||
6647 AOP_TYPE (right) == AOP_DIR ||
6648 AOP_TYPE (right) == AOP_LIT ||
6649 AOP_TYPE (right) == AOP_IMMD ||
6650 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6651 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6655 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
6656 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6657 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6658 emitcode ("jnz", "!tlabel", lbl->key + 100);
6660 emitcode ("cjne", "a,%s,!tlabel",
6661 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG),
6668 /* right is a pointer reg need both a & b */
6671 MOVB (aopGet (left, offset, FALSE, FALSE, NULL));
6672 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
6673 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
6679 /*-----------------------------------------------------------------*/
6680 /* gencjne - compare and jump if not equal */
6681 /*-----------------------------------------------------------------*/
6683 gencjne (operand * left, operand * right, symbol * lbl)
6685 symbol *tlbl = newiTempLabel (NULL);
6687 D (emitcode (";", "gencjne"));
6689 gencjneshort (left, right, lbl);
6691 emitcode ("mov", "a,%s", one);
6692 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
6693 emitcode ("", "!tlabeldef", lbl->key + 100);
6694 emitcode ("clr", "a");
6695 emitcode ("", "!tlabeldef", tlbl->key + 100);
6698 /*-----------------------------------------------------------------*/
6699 /* genCmpEq - generates code for equal to */
6700 /*-----------------------------------------------------------------*/
6702 genCmpEq (iCode * ic, iCode * ifx)
6704 operand *left, *right, *result;
6706 D (emitcode (";", "genCmpEq"));
6709 AOP_SET_LOCALS (ic);
6711 /* if literal, literal on the right or
6712 if the right is in a pointer register and left
6714 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6715 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6717 operand *t = IC_RIGHT (ic);
6718 IC_RIGHT (ic) = IC_LEFT (ic);
6722 if (ifx && /* !AOP_SIZE(result) */
6723 OP_SYMBOL (result) &&
6724 OP_SYMBOL (result)->regType == REG_CND)
6727 /* if they are both bit variables */
6728 if (AOP_TYPE (left) == AOP_CRY &&
6729 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6731 if (AOP_TYPE (right) == AOP_LIT)
6733 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6736 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6737 emitcode ("cpl", "c");
6741 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6745 emitcode ("clr", "c");
6747 /* AOP_TYPE(right) == AOP_CRY */
6751 symbol *lbl = newiTempLabel (NULL);
6752 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6753 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6754 emitcode ("cpl", "c");
6755 emitcode ("", "!tlabeldef", (lbl->key + 100));
6757 /* if true label then we jump if condition
6759 tlbl = newiTempLabel (NULL);
6762 emitcode ("jnc", "!tlabel", tlbl->key + 100);
6763 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6767 emitcode ("jc", "!tlabel", tlbl->key + 100);
6768 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6770 emitcode ("", "!tlabeldef", tlbl->key + 100);
6774 tlbl = newiTempLabel (NULL);
6775 gencjneshort (left, right, tlbl);
6778 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
6779 emitcode ("", "!tlabeldef", tlbl->key + 100);
6783 symbol *lbl = newiTempLabel (NULL);
6784 emitcode ("sjmp", "!tlabel", lbl->key + 100);
6785 emitcode ("", "!tlabeldef", tlbl->key + 100);
6786 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
6787 emitcode ("", "!tlabeldef", lbl->key + 100);
6790 /* mark the icode as generated */
6793 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6794 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6798 /* if they are both bit variables */
6799 if (AOP_TYPE (left) == AOP_CRY &&
6800 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6802 if (AOP_TYPE (right) == AOP_LIT)
6804 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6807 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6808 emitcode ("cpl", "c");
6812 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6816 emitcode ("clr", "c");
6818 /* AOP_TYPE(right) == AOP_CRY */
6822 symbol *lbl = newiTempLabel (NULL);
6823 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6824 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6825 emitcode ("cpl", "c");
6826 emitcode ("", "!tlabeldef", (lbl->key + 100));
6829 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6830 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6832 aopOp (result, ic, TRUE, FALSE);
6835 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6842 genIfxJump (ifx, "c");
6845 /* if the result is used in an arithmetic operation
6846 then put the result in place */
6851 gencjne (left, right, newiTempLabel (NULL));
6853 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6854 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6856 aopOp (result, ic, TRUE, FALSE);
6858 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6860 aopPut (result, "a", 0);
6865 genIfxJump (ifx, "a");
6868 /* if the result is used in an arithmetic operation
6869 then put the result in place */
6870 if (AOP_TYPE (result) != AOP_CRY)
6872 /* leave the result in acc */
6876 freeAsmop (result, NULL, ic, TRUE);
6879 /*-----------------------------------------------------------------*/
6880 /* ifxForOp - returns the icode containing the ifx for operand */
6881 /*-----------------------------------------------------------------*/
6883 ifxForOp (operand * op, iCode * ic)
6885 /* if true symbol then needs to be assigned */
6886 if (IS_TRUE_SYMOP (op))
6889 /* if this has register type condition and
6890 the next instruction is ifx with the same operand
6891 and live to of the operand is upto the ifx only then */
6893 ic->next->op == IFX &&
6894 IC_COND (ic->next)->key == op->key &&
6895 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6901 /*-----------------------------------------------------------------*/
6902 /* hasInc - operand is incremented before any other use */
6903 /*-----------------------------------------------------------------*/
6905 hasInc (operand *op, iCode *ic, int osize)
6907 sym_link *type = operandType(op);
6908 sym_link *retype = getSpec (type);
6909 iCode *lic = ic->next;
6912 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6913 if (!IS_SYMOP(op)) return NULL;
6915 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6916 if (IS_AGGREGATE(type->next)) return NULL;
6917 if (osize != (isize = getSize(type->next))) return NULL;
6920 /* if operand of the form op = op + <sizeof *op> */
6921 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6922 isOperandEqual(IC_RESULT(lic),op) &&
6923 isOperandLiteral(IC_RIGHT(lic)) &&
6924 operandLitValue(IC_RIGHT(lic)) == isize) {
6927 /* if the operand used or deffed */
6928 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6931 /* if GOTO or IFX */
6932 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6938 /*-----------------------------------------------------------------*/
6939 /* genAndOp - for && operation */
6940 /*-----------------------------------------------------------------*/
6942 genAndOp (iCode * ic)
6944 operand *left, *right, *result;
6947 D (emitcode (";", "genAndOp "));
6949 /* note here that && operations that are in an
6950 if statement are taken away by backPatchLabels
6951 only those used in arthmetic operations remain */
6953 AOP_SET_LOCALS (ic);
6955 /* if both are bit variables */
6956 if (AOP_TYPE (left) == AOP_CRY &&
6957 AOP_TYPE (right) == AOP_CRY)
6959 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6960 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6961 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6962 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6964 aopOp (result,ic,FALSE, FALSE);
6969 tlbl = newiTempLabel (NULL);
6971 emitcode ("jz", "!tlabel", tlbl->key + 100);
6973 emitcode ("", "!tlabeldef", tlbl->key + 100);
6974 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6975 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6977 aopOp (result,ic,FALSE, FALSE);
6980 freeAsmop (result, NULL, ic, TRUE);
6984 /*-----------------------------------------------------------------*/
6985 /* genOrOp - for || operation */
6986 /*-----------------------------------------------------------------*/
6988 genOrOp (iCode * ic)
6990 operand *left, *right, *result;
6993 D (emitcode (";", "genOrOp "));
6995 /* note here that || operations that are in an
6996 if statement are taken away by backPatchLabels
6997 only those used in arthmetic operations remain */
6999 AOP_SET_LOCALS (ic);
7001 /* if both are bit variables */
7002 if (AOP_TYPE (left) == AOP_CRY &&
7003 AOP_TYPE (right) == AOP_CRY)
7005 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7006 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
7007 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7008 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7010 aopOp (result,ic,FALSE, FALSE);
7016 tlbl = newiTempLabel (NULL);
7018 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7020 emitcode ("", "!tlabeldef", tlbl->key + 100);
7021 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7022 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7024 aopOp (result,ic,FALSE, FALSE);
7029 freeAsmop (result, NULL, ic, TRUE);
7032 /*-----------------------------------------------------------------*/
7033 /* isLiteralBit - test if lit == 2^n */
7034 /*-----------------------------------------------------------------*/
7036 isLiteralBit (unsigned long lit)
7038 unsigned long pw[32] =
7039 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
7040 0x100L, 0x200L, 0x400L, 0x800L,
7041 0x1000L, 0x2000L, 0x4000L, 0x8000L,
7042 0x10000L, 0x20000L, 0x40000L, 0x80000L,
7043 0x100000L, 0x200000L, 0x400000L, 0x800000L,
7044 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
7045 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
7048 for (idx = 0; idx < 32; idx++)
7054 /*-----------------------------------------------------------------*/
7055 /* continueIfTrue - */
7056 /*-----------------------------------------------------------------*/
7058 continueIfTrue (iCode * ic)
7061 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
7065 /*-----------------------------------------------------------------*/
7067 /*-----------------------------------------------------------------*/
7069 jumpIfTrue (iCode * ic)
7072 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
7076 /*-----------------------------------------------------------------*/
7077 /* jmpTrueOrFalse - */
7078 /*-----------------------------------------------------------------*/
7080 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
7082 // ugly but optimized by peephole
7085 symbol *nlbl = newiTempLabel (NULL);
7086 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
7087 emitcode ("", "!tlabeldef", tlbl->key + 100);
7088 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
7089 emitcode ("", "!tlabeldef", nlbl->key + 100);
7093 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
7094 emitcode ("", "!tlabeldef", tlbl->key + 100);
7099 // Generate code to perform a bit-wise logic operation
7100 // on two operands in far space (assumed to already have been
7101 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
7102 // in far space. This requires pushing the result on the stack
7103 // then popping it into the result.
7105 genFarFarLogicOp(iCode *ic, char *logicOp)
7107 int size, resultSize, compSize;
7111 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
7112 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
7113 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
7115 _startLazyDPSEvaluation();
7116 for (size = compSize; (size--); offset++)
7118 MOVA (aopGet (IC_LEFT(ic), offset, FALSE, FALSE, NULL));
7119 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
7120 MOVA (aopGet (IC_RIGHT(ic), offset, FALSE, FALSE, NULL));
7122 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
7123 emitcode ("push", "acc");
7125 _endLazyDPSEvaluation();
7127 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7128 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7129 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
7131 resultSize = AOP_SIZE(IC_RESULT(ic));
7133 ADJUST_PUSHED_RESULT(compSize, resultSize);
7135 _startLazyDPSEvaluation();
7138 emitcode ("pop", "acc");
7139 aopPut (IC_RESULT (ic), "a", compSize);
7141 _endLazyDPSEvaluation();
7142 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
7146 /*-----------------------------------------------------------------*/
7147 /* genAnd - code for and */
7148 /*-----------------------------------------------------------------*/
7150 genAnd (iCode * ic, iCode * ifx)
7152 operand *left, *right, *result;
7153 int size, offset = 0;
7154 unsigned long lit = 0L;
7159 D (emitcode (";", "genAnd"));
7161 AOP_OP_3_NOFATAL (ic, pushResult);
7162 AOP_SET_LOCALS (ic);
7166 genFarFarLogicOp(ic, "anl");
7171 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7173 AOP_TYPE (left), AOP_TYPE (right));
7174 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7176 AOP_SIZE (left), AOP_SIZE (right));
7179 /* if left is a literal & right is not then exchange them */
7180 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7181 #ifdef LOGIC_OPS_BROKEN
7182 || AOP_NEEDSACC (left)
7186 operand *tmp = right;
7191 /* if result = right then exchange left and right */
7192 if (sameRegs (AOP (result), AOP (right)))
7194 operand *tmp = right;
7199 /* if right is bit then exchange them */
7200 if (AOP_TYPE (right) == AOP_CRY &&
7201 AOP_TYPE (left) != AOP_CRY)
7203 operand *tmp = right;
7207 if (AOP_TYPE (right) == AOP_LIT)
7208 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7210 size = AOP_SIZE (result);
7213 // result = bit & yy;
7214 if (AOP_TYPE (left) == AOP_CRY)
7216 // c = bit & literal;
7217 if (AOP_TYPE (right) == AOP_LIT)
7221 if (size && sameRegs (AOP (result), AOP (left)))
7224 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7229 if (size && (AOP_TYPE (result) == AOP_CRY))
7231 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
7234 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7239 emitcode ("clr", "c");
7244 if (AOP_TYPE (right) == AOP_CRY)
7247 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7248 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
7253 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
7255 emitcode ("rrc", "a");
7256 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
7264 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7265 genIfxJump (ifx, "c");
7269 // if(val & 0xZZ) - size = 0, ifx != FALSE -
7270 // bit = val & 0xZZ - size = 1, ifx = FALSE -
7271 if ((AOP_TYPE (right) == AOP_LIT) &&
7272 (AOP_TYPE (result) == AOP_CRY) &&
7273 (AOP_TYPE (left) != AOP_CRY))
7275 int posbit = isLiteralBit (lit);
7280 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE, NULL));
7284 switch (posbit & 0x07)
7286 case 0: emitcode ("rrc", "a");
7288 case 7: emitcode ("rlc", "a");
7290 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
7299 SNPRINTF (buffer, sizeof(buffer),
7300 "acc.%d", posbit & 0x07);
7301 genIfxJump (ifx, buffer);
7305 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
7312 symbol *tlbl = newiTempLabel (NULL);
7313 int sizel = AOP_SIZE (left);
7315 emitcode ("setb", "c");
7318 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
7320 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7322 if ((posbit = isLiteralBit (bytelit)) != 0)
7323 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
7326 if (bytelit != 0x0FFL)
7327 emitcode ("anl", "a,%s",
7328 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG));
7329 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7334 // bit = left & literal
7337 emitcode ("clr", "c");
7338 emitcode ("", "!tlabeldef", tlbl->key + 100);
7340 // if(left & literal)
7344 jmpTrueOrFalse (ifx, tlbl);
7346 emitcode ("", "!tlabeldef", tlbl->key + 100);
7354 /* if left is same as result */
7355 if (sameRegs (AOP (result), AOP (left)))
7357 for (; size--; offset++)
7359 if (AOP_TYPE (right) == AOP_LIT)
7361 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7362 if (bytelit == 0x0FF)
7364 /* dummy read of volatile operand */
7365 if (isOperandVolatile (left, FALSE))
7366 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7370 else if (bytelit == 0)
7372 aopPut (result, zero, offset);
7374 else if (IS_AOP_PREG (result))
7376 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7377 emitcode ("anl", "a,%s",
7378 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG));
7379 aopPut (result, "a", offset);
7382 emitcode ("anl", "%s,%s",
7383 aopGet (left, offset, FALSE, TRUE, NULL),
7384 aopGet (right, offset, FALSE, FALSE, NULL));
7388 if (AOP_TYPE (left) == AOP_ACC)
7389 emitcode ("anl", "a,%s",
7390 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7393 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7394 if (IS_AOP_PREG (result))
7396 emitcode ("anl", "a,%s",
7397 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7398 aopPut (result, "a", offset);
7401 emitcode ("anl", "%s,a",
7402 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7409 // left & result in different registers
7410 if (AOP_TYPE (result) == AOP_CRY)
7413 // if(size), result in bit
7414 // if(!size && ifx), conditional oper: if(left & right)
7415 symbol *tlbl = newiTempLabel (NULL);
7416 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
7418 emitcode ("setb", "c");
7421 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7422 emitcode ("anl", "a,%s",
7423 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7425 if (AOP_TYPE(left)==AOP_ACC)
7427 bool pushedB = pushB ();
7428 emitcode("mov", "b,a");
7429 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7430 emitcode("anl", "a,b");
7435 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7436 emitcode ("anl", "a,%s",
7437 aopGet (left, offset, FALSE, FALSE, DP2_RESULT_REG));
7440 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7446 emitcode ("", "!tlabeldef", tlbl->key + 100);
7450 jmpTrueOrFalse (ifx, tlbl);
7452 emitcode ("", "!tlabeldef", tlbl->key + 100);
7456 for (; (size--); offset++)
7459 // result = left & right
7460 if (AOP_TYPE (right) == AOP_LIT)
7462 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7463 if (bytelit == 0x0FF)
7466 aopGet (left, offset, FALSE, FALSE, NULL),
7470 else if (bytelit == 0)
7472 /* dummy read of volatile operand */
7473 if (isOperandVolatile (left, FALSE))
7474 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7475 aopPut (result, zero, offset);
7478 D (emitcode (";", "better literal AND."););
7479 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7480 emitcode ("anl", "a, %s", aopGet (right, offset,
7481 FALSE, FALSE, DP2_RESULT_REG));
7486 // faster than result <- left, anl result,right
7487 // and better if result is SFR
7488 if (AOP_TYPE (left) == AOP_ACC)
7490 emitcode ("anl", "a,%s",
7491 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7495 char *rOp = aopGet (right, offset, FALSE, FALSE, NULL);
7496 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7498 emitcode("mov", "b,a");
7502 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7503 emitcode ("anl", "a,%s", rOp);
7506 aopPut (result, "a", offset);
7512 freeAsmop (result, NULL, ic, TRUE);
7513 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7514 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7517 /*-----------------------------------------------------------------*/
7518 /* genOr - code for or */
7519 /*-----------------------------------------------------------------*/
7521 genOr (iCode * ic, iCode * ifx)
7523 operand *left, *right, *result;
7524 int size, offset = 0;
7525 unsigned long lit = 0L;
7529 D (emitcode (";", "genOr "));
7531 AOP_OP_3_NOFATAL (ic, pushResult);
7532 AOP_SET_LOCALS (ic);
7536 genFarFarLogicOp(ic, "orl");
7542 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7544 AOP_TYPE (left), AOP_TYPE (right));
7545 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7547 AOP_SIZE (left), AOP_SIZE (right));
7550 /* if left is a literal & right is not then exchange them */
7551 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7552 #ifdef LOGIC_OPS_BROKEN
7553 || AOP_NEEDSACC (left) // I think this is a net loss now.
7557 operand *tmp = right;
7562 /* if result = right then exchange them */
7563 if (sameRegs (AOP (result), AOP (right)))
7565 operand *tmp = right;
7570 /* if right is bit then exchange them */
7571 if (AOP_TYPE (right) == AOP_CRY &&
7572 AOP_TYPE (left) != AOP_CRY)
7574 operand *tmp = right;
7578 if (AOP_TYPE (right) == AOP_LIT)
7579 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7581 size = AOP_SIZE (result);
7585 if (AOP_TYPE (left) == AOP_CRY)
7587 if (AOP_TYPE (right) == AOP_LIT)
7589 // c = bit | literal;
7592 // lit != 0 => result = 1
7593 if (AOP_TYPE (result) == AOP_CRY)
7596 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7598 continueIfTrue (ifx);
7601 emitcode ("setb", "c");
7605 // lit == 0 => result = left
7606 if (size && sameRegs (AOP (result), AOP (left)))
7608 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7613 if (AOP_TYPE (right) == AOP_CRY)
7616 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7617 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7622 symbol *tlbl = newiTempLabel (NULL);
7623 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
7624 emitcode ("setb", "c");
7625 emitcode ("jb", "%s,!tlabel",
7626 AOP (left)->aopu.aop_dir, tlbl->key + 100);
7628 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7629 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7631 jmpTrueOrFalse (ifx, tlbl);
7637 emitcode ("", "!tlabeldef", tlbl->key + 100);
7646 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7647 genIfxJump (ifx, "c");
7651 // if(val | 0xZZ) - size = 0, ifx != FALSE -
7652 // bit = val | 0xZZ - size = 1, ifx = FALSE -
7653 if ((AOP_TYPE (right) == AOP_LIT) &&
7654 (AOP_TYPE (result) == AOP_CRY) &&
7655 (AOP_TYPE (left) != AOP_CRY))
7661 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7663 continueIfTrue (ifx);
7668 // lit = 0, result = boolean(left)
7670 emitcode ("setb", "c");
7674 symbol *tlbl = newiTempLabel (NULL);
7675 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7677 emitcode ("", "!tlabeldef", tlbl->key + 100);
7681 genIfxJump (ifx, "a");
7689 /* if left is same as result */
7690 if (sameRegs (AOP (result), AOP (left)))
7692 for (; size--; offset++)
7694 if (AOP_TYPE (right) == AOP_LIT)
7696 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7699 /* dummy read of volatile operand */
7700 if (isOperandVolatile (left, FALSE))
7701 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7705 else if (bytelit == 0x0FF)
7707 aopPut (result, "#0xFF", offset);
7709 else if (IS_AOP_PREG (left))
7711 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7712 emitcode ("orl", "a,%s",
7713 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7714 aopPut (result, "a", offset);
7718 emitcode ("orl", "%s,%s",
7719 aopGet (left, offset, FALSE, TRUE, NULL),
7720 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7725 if (AOP_TYPE (left) == AOP_ACC)
7727 emitcode ("orl", "a,%s",
7728 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7732 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7733 if (IS_AOP_PREG (left))
7735 emitcode ("orl", "a,%s",
7736 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7737 aopPut (result, "a", offset);
7741 emitcode ("orl", "%s,a",
7742 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
7750 // left & result in different registers
7751 if (AOP_TYPE (result) == AOP_CRY)
7754 // if(size), result in bit
7755 // if(!size && ifx), conditional oper: if(left | right)
7756 symbol *tlbl = newiTempLabel (NULL);
7757 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7759 emitcode ("setb", "c");
7762 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7763 emitcode ("orl", "a,%s",
7764 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
7766 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
7767 emitcode ("orl", "a,%s",
7768 aopGet (left, offset, FALSE, FALSE, DP2_RESULT_REG));
7770 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7776 emitcode ("", "!tlabeldef", tlbl->key + 100);
7780 jmpTrueOrFalse (ifx, tlbl);
7782 emitcode ("", "!tlabeldef", tlbl->key + 100);
7786 _startLazyDPSEvaluation();
7787 for (; (size--); offset++)
7790 // result = left | right
7791 if (AOP_TYPE (right) == AOP_LIT)
7793 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7797 aopGet (left, offset, FALSE, FALSE, NULL),
7801 else if (bytelit == 0x0FF)
7803 /* dummy read of volatile operand */
7804 if (isOperandVolatile (left, FALSE))
7805 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7806 aopPut (result, "#0xFF", offset);
7809 D (emitcode (";", "better literal OR."););
7810 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7811 emitcode ("orl", "a, %s",
7812 aopGet (right, offset,
7813 FALSE, FALSE, DP2_RESULT_REG));
7818 // faster than result <- left, anl result,right
7819 // and better if result is SFR
7820 if (AOP_TYPE (left) == AOP_ACC)
7822 emitcode ("orl", "a,%s",
7823 aopGet (right, offset,
7824 FALSE, FALSE, DP2_RESULT_REG));
7828 char *rOp = aopGet (right, offset, FALSE, FALSE, NULL);
7830 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7832 emitcode("mov", "b,a");
7836 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
7837 emitcode ("orl", "a,%s", rOp);
7840 aopPut (result, "a", offset);
7842 _endLazyDPSEvaluation();
7847 freeAsmop (result, NULL, ic, TRUE);
7848 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7849 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7852 /*-----------------------------------------------------------------*/
7853 /* genXor - code for xclusive or */
7854 /*-----------------------------------------------------------------*/
7856 genXor (iCode * ic, iCode * ifx)
7858 operand *left, *right, *result;
7859 int size, offset = 0;
7860 unsigned long lit = 0L;
7864 D (emitcode (";", "genXor "));
7866 AOP_OP_3_NOFATAL (ic, pushResult);
7867 AOP_SET_LOCALS (ic);
7871 genFarFarLogicOp(ic, "xrl");
7876 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7878 AOP_TYPE (left), AOP_TYPE (right));
7879 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7881 AOP_SIZE (left), AOP_SIZE (right));
7884 /* if left is a literal & right is not ||
7885 if left needs acc & right does not */
7886 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
7887 #ifdef LOGIC_OPS_BROKEN
7888 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
7892 operand *tmp = right;
7897 /* if result = right then exchange them */
7898 if (sameRegs (AOP (result), AOP (right)))
7900 operand *tmp = right;
7905 /* if right is bit then exchange them */
7906 if (AOP_TYPE (right) == AOP_CRY &&
7907 AOP_TYPE (left) != AOP_CRY)
7909 operand *tmp = right;
7913 if (AOP_TYPE (right) == AOP_LIT)
7914 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7916 size = AOP_SIZE (result);
7920 if (AOP_TYPE (left) == AOP_CRY)
7922 if (AOP_TYPE (right) == AOP_LIT)
7924 // c = bit & literal;
7927 // lit>>1 != 0 => result = 1
7928 if (AOP_TYPE (result) == AOP_CRY)
7931 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7933 continueIfTrue (ifx);
7936 emitcode ("setb", "c");
7943 // lit == 0, result = left
7944 if (size && sameRegs (AOP (result), AOP (left)))
7946 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7950 // lit == 1, result = not(left)
7951 if (size && sameRegs (AOP (result), AOP (left)))
7953 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7958 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7959 emitcode ("cpl", "c");
7968 symbol *tlbl = newiTempLabel (NULL);
7969 if (AOP_TYPE (right) == AOP_CRY)
7972 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7976 int sizer = AOP_SIZE (right);
7978 // if val>>1 != 0, result = 1
7979 emitcode ("setb", "c");
7982 MOVA (aopGet (right, sizer - 1, FALSE, FALSE, NULL));
7984 // test the msb of the lsb
7985 emitcode ("anl", "a,#!constbyte",0xfe);
7986 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7990 emitcode ("rrc", "a");
7992 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7993 emitcode ("cpl", "c");
7994 emitcode ("", "!tlabeldef", (tlbl->key + 100));
8001 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
8002 genIfxJump (ifx, "c");
8006 /* if left is same as result */
8007 if (sameRegs (AOP (result), AOP (left)))
8009 for (; size--; offset++)
8011 if (AOP_TYPE (right) == AOP_LIT)
8013 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
8016 /* dummy read of volatile operand */
8017 if (isOperandVolatile (left, FALSE))
8018 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8022 else if (IS_AOP_PREG (left))
8024 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8025 emitcode ("xrl", "a,%s",
8026 aopGet (right, offset, FALSE, TRUE, DP2_RESULT_REG));
8027 aopPut (result, "a", offset);
8031 emitcode ("xrl", "%s,%s",
8032 aopGet (left, offset, FALSE, TRUE, NULL),
8033 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8038 if (AOP_TYPE (left) == AOP_ACC)
8039 emitcode ("xrl", "a,%s",
8040 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8043 MOVA (aopGet (right, offset, FALSE, FALSE, NULL));
8044 if (IS_AOP_PREG (left))
8046 emitcode ("xrl", "a,%s",
8047 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
8048 aopPut (result, "a", offset);
8051 emitcode ("xrl", "%s,a",
8052 aopGet (left, offset, FALSE, TRUE, DP2_RESULT_REG));
8059 // left & result in different registers
8060 if (AOP_TYPE (result) == AOP_CRY)
8063 // if(size), result in bit
8064 // if(!size && ifx), conditional oper: if(left ^ right)
8065 symbol *tlbl = newiTempLabel (NULL);
8066 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
8069 emitcode ("setb", "c");
8072 if ((AOP_TYPE (right) == AOP_LIT) &&
8073 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
8075 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8079 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
8080 emitcode ("xrl", "a,%s",
8081 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8083 char *rOp = aopGet (right, offset, FALSE, FALSE, NULL);
8084 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
8086 emitcode("mov", "b,a");
8090 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8091 emitcode ("xrl", "a,%s", rOp);
8094 emitcode ("jnz", "!tlabel", tlbl->key + 100);
8100 emitcode ("", "!tlabeldef", tlbl->key + 100);
8104 jmpTrueOrFalse (ifx, tlbl);
8108 for (; (size--); offset++)
8111 // result = left ^ right
8112 if (AOP_TYPE (right) == AOP_LIT)
8114 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
8118 aopGet (left, offset, FALSE, FALSE, NULL),
8122 D (emitcode (";", "better literal XOR."););
8123 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8124 emitcode ("xrl", "a, %s",
8125 aopGet (right, offset, FALSE, FALSE, DP2_RESULT_REG));
8129 // faster than result <- left, anl result,right
8130 // and better if result is SFR
8131 if (AOP_TYPE (left) == AOP_ACC)
8133 emitcode ("xrl", "a,%s",
8134 aopGet (right, offset,
8135 FALSE, FALSE, DP2_RESULT_REG));
8139 char *rOp = aopGet (right, offset, FALSE, FALSE, NULL);
8140 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
8142 emitcode("mov", "b,a");
8146 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
8147 emitcode ("xrl", "a,%s", rOp);
8150 aopPut (result, "a", offset);
8156 freeAsmop (result, NULL, ic, TRUE);
8157 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
8158 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
8161 /*-----------------------------------------------------------------*/
8162 /* genInline - write the inline code out */
8163 /*-----------------------------------------------------------------*/
8165 genInline (iCode * ic)
8167 char *buffer, *bp, *bp1;
8169 D (emitcode (";", "genInline "));
8171 _G.inLine += (!options.asmpeep);
8173 buffer = bp = bp1 = Safe_strdup(IC_INLINE(ic));
8175 /* emit each line as a code */
8186 /* Add \n for labels, not dirs such as c:\mydir */
8187 if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
8201 /* emitcode("",buffer); */
8202 _G.inLine -= (!options.asmpeep);
8205 /*-----------------------------------------------------------------*/
8206 /* genRRC - rotate right with carry */
8207 /*-----------------------------------------------------------------*/
8211 operand *left, *result;
8215 D (emitcode (";", "genRRC"));
8217 /* rotate right with carry */
8218 left = IC_LEFT (ic);
8219 result = IC_RESULT (ic);
8220 aopOp (left, ic, FALSE, FALSE);
8221 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8223 /* move it to the result */
8224 size = AOP_SIZE (result);
8228 _startLazyDPSEvaluation ();
8231 l = aopGet (left, offset, FALSE, FALSE, NULL);
8233 emitcode ("rrc", "a");
8234 if (AOP_SIZE (result) > 1)
8235 aopPut (result, "a", offset--);
8237 _endLazyDPSEvaluation ();
8239 /* now we need to put the carry into the
8240 highest order byte of the result */
8241 if (AOP_SIZE (result) > 1)
8243 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE, NULL);
8246 emitcode ("mov", "acc.7,c");
8247 aopPut (result, "a", AOP_SIZE (result) - 1);
8248 freeAsmop (result, NULL, ic, TRUE);
8249 freeAsmop (left, NULL, ic, TRUE);
8252 /*-----------------------------------------------------------------*/
8253 /* genRLC - generate code for rotate left with carry */
8254 /*-----------------------------------------------------------------*/
8258 operand *left, *result;
8262 D (emitcode (";", "genRLC "));
8264 /* rotate right with carry */
8265 left = IC_LEFT (ic);
8266 result = IC_RESULT (ic);
8267 aopOp (left, ic, FALSE, FALSE);
8268 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8270 /* move it to the result */
8271 size = AOP_SIZE (result);
8275 l = aopGet (left, offset, FALSE, FALSE, NULL);
8277 emitcode ("add", "a,acc");
8278 if (AOP_SIZE (result) > 1)
8280 aopPut (result, "a", offset++);
8283 _startLazyDPSEvaluation ();
8286 l = aopGet (left, offset, FALSE, FALSE, NULL);
8288 emitcode ("rlc", "a");
8289 if (AOP_SIZE (result) > 1)
8290 aopPut (result, "a", offset++);
8292 _endLazyDPSEvaluation ();
8294 /* now we need to put the carry into the
8295 highest order byte of the result */
8296 if (AOP_SIZE (result) > 1)
8298 l = aopGet (result, 0, FALSE, FALSE, NULL);
8301 emitcode ("mov", "acc.0,c");
8302 aopPut (result, "a", 0);
8303 freeAsmop (result, NULL, ic, TRUE);
8304 freeAsmop (left, NULL, ic, TRUE);
8307 /*-----------------------------------------------------------------*/
8308 /* genGetHbit - generates code get highest order bit */
8309 /*-----------------------------------------------------------------*/
8311 genGetHbit (iCode * ic)
8313 operand *left, *result;
8315 D (emitcode (";", "genGetHbit"));
8317 left = IC_LEFT (ic);
8318 result = IC_RESULT (ic);
8319 aopOp (left, ic, FALSE, FALSE);
8320 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8322 /* get the highest order byte into a */
8323 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
8324 if (AOP_TYPE (result) == AOP_CRY)
8326 emitcode ("rlc", "a");
8331 emitcode ("rl", "a");
8332 emitcode ("anl", "a,#1");
8337 freeAsmop (result, NULL, ic, TRUE);
8338 freeAsmop (left, NULL, ic, TRUE);
8341 /*-----------------------------------------------------------------*/
8342 /* genSwap - generates code to swap nibbles or bytes */
8343 /*-----------------------------------------------------------------*/
8345 genSwap (iCode * ic)
8347 operand *left, *result;
8349 D(emitcode ("; genSwap",""));
8351 left = IC_LEFT (ic);
8352 result = IC_RESULT (ic);
8353 aopOp (left, ic, FALSE, FALSE);
8354 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8356 _startLazyDPSEvaluation ();
8357 switch (AOP_SIZE (left))
8359 case 1: /* swap nibbles in byte */
8360 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
8361 emitcode ("swap", "a");
8362 aopPut (result, "a", 0);
8364 case 2: /* swap bytes in word */
8365 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
8367 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
8368 aopPut (result, aopGet (left, 1, FALSE, FALSE, NULL), 0);
8369 aopPut (result, "a", 1);
8371 else if (operandsEqu (left, result))
8374 bool pushedB = FALSE, leftInB = FALSE;
8376 MOVA (aopGet (left, 0, FALSE, FALSE, NULL));
8377 if (AOP_NEEDSACC (left) || AOP_NEEDSACC (result))
8380 emitcode ("mov", "b,a");
8384 aopPut (result, aopGet (left, 1, FALSE, FALSE, NULL), 0);
8385 aopPut (result, reg, 1);
8392 aopPut (result, aopGet (left, 1, FALSE, FALSE, NULL), 0);
8393 aopPut (result, aopGet (left, 0, FALSE, FALSE, NULL), 1);
8397 wassertl(FALSE, "unsupported SWAP operand size");
8399 _endLazyDPSEvaluation ();
8401 freeAsmop (result, NULL, ic, TRUE);
8402 freeAsmop (left, NULL, ic, TRUE);
8405 /*-----------------------------------------------------------------*/
8406 /* AccRol - rotate left accumulator by known count */
8407 /*-----------------------------------------------------------------*/
8409 AccRol (int shCount)
8411 shCount &= 0x0007; // shCount : 0..7
8418 emitcode ("rl", "a");
8421 emitcode ("rl", "a");
8422 emitcode ("rl", "a");
8425 emitcode ("swap", "a");
8426 emitcode ("rr", "a");
8429 emitcode ("swap", "a");
8432 emitcode ("swap", "a");
8433 emitcode ("rl", "a");
8436 emitcode ("rr", "a");
8437 emitcode ("rr", "a");
8440 emitcode ("rr", "a");
8445 /*-----------------------------------------------------------------*/
8446 /* AccLsh - left shift accumulator by known count */
8447 /*-----------------------------------------------------------------*/
8449 AccLsh (int shCount)
8454 emitcode ("add", "a,acc");
8455 else if (shCount == 2)
8457 emitcode ("add", "a,acc");
8458 emitcode ("add", "a,acc");
8462 /* rotate left accumulator */
8464 /* and kill the lower order bits */
8465 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
8470 /*-----------------------------------------------------------------*/
8471 /* AccRsh - right shift accumulator by known count */
8472 /*-----------------------------------------------------------------*/
8474 AccRsh (int shCount)
8481 emitcode ("rrc", "a");
8485 /* rotate right accumulator */
8486 AccRol (8 - shCount);
8487 /* and kill the higher order bits */
8488 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
8493 #ifdef BETTER_LITERAL_SHIFT
8494 /*-----------------------------------------------------------------*/
8495 /* AccSRsh - signed right shift accumulator by known count */
8496 /*-----------------------------------------------------------------*/
8498 AccSRsh (int shCount)
8505 emitcode ("mov", "c,acc.7");
8506 emitcode ("rrc", "a");
8508 else if (shCount == 2)
8510 emitcode ("mov", "c,acc.7");
8511 emitcode ("rrc", "a");
8512 emitcode ("mov", "c,acc.7");
8513 emitcode ("rrc", "a");
8517 tlbl = newiTempLabel (NULL);
8518 /* rotate right accumulator */
8519 AccRol (8 - shCount);
8520 /* and kill the higher order bits */
8521 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
8522 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8523 emitcode ("orl", "a,#!constbyte",
8524 (unsigned char) ~SRMask[shCount]);
8525 emitcode ("", "!tlabeldef", tlbl->key + 100);
8531 #ifdef BETTER_LITERAL_SHIFT
8532 /*-----------------------------------------------------------------*/
8533 /* shiftR1Left2Result - shift right one byte from left to result */
8534 /*-----------------------------------------------------------------*/
8536 shiftR1Left2Result (operand * left, int offl,
8537 operand * result, int offr,
8538 int shCount, int sign)
8540 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
8541 /* shift right accumulator */
8546 aopPut (result, "a", offr);
8550 #ifdef BETTER_LITERAL_SHIFT
8551 /*-----------------------------------------------------------------*/
8552 /* shiftL1Left2Result - shift left one byte from left to result */
8553 /*-----------------------------------------------------------------*/
8555 shiftL1Left2Result (operand * left, int offl,
8556 operand * result, int offr, int shCount)
8559 l = aopGet (left, offl, FALSE, FALSE, NULL);
8561 /* shift left accumulator */
8563 aopPut (result, "a", offr);
8567 #ifdef BETTER_LITERAL_SHIFT
8568 /*-----------------------------------------------------------------*/
8569 /* movLeft2Result - move byte from left to result */
8570 /*-----------------------------------------------------------------*/
8572 movLeft2Result (operand * left, int offl,
8573 operand * result, int offr, int sign)
8576 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8578 l = aopGet (left, offl, FALSE, FALSE, NULL);
8580 if (*l == '@' && (IS_AOP_PREG (result)))
8582 emitcode ("mov", "a,%s", l);
8583 aopPut (result, "a", offr);
8589 aopPut (result, l, offr);
8593 /* MSB sign in acc.7 ! */
8594 if (getDataSize (left) == offl + 1)
8597 aopPut (result, "a", offr);
8605 #ifdef BETTER_LITERAL_SHIFT
8606 /*-----------------------------------------------------------------*/
8607 /* AccAXRrl1 - right rotate a:x by 1 */
8608 /*-----------------------------------------------------------------*/
8612 emitcode ("mov", "c,acc.0");
8613 emitcode ("xch", "a,%s", x);
8614 emitcode ("rrc", "a");
8615 emitcode ("xch", "a,%s", x);
8616 emitcode ("rrc", "a");
8620 #ifdef BETTER_LITERAL_SHIFT
8622 /*-----------------------------------------------------------------*/
8623 /* AccAXLrl1 - left rotate a:x by 1 */
8624 /*-----------------------------------------------------------------*/
8628 emitcode ("mov", "c,acc.7");
8629 emitcode ("xch", "a,%s", x);
8630 emitcode ("rlc", "a");
8631 emitcode ("xch", "a,%s", x);
8632 emitcode ("rlc", "a");
8636 #ifdef BETTER_LITERAL_SHIFT
8637 /*-----------------------------------------------------------------*/
8638 /* AccAXRsh1 - right shift c->a:x->c by 1 */
8639 /*-----------------------------------------------------------------*/
8643 emitcode ("rrc", "a");
8644 emitcode ("xch", "a,%s", x);
8645 emitcode ("rrc", "a");
8646 emitcode ("xch", "a,%s", x);
8650 #ifdef BETTER_LITERAL_SHIFT
8651 /*-----------------------------------------------------------------*/
8652 /* AccAXLsh1 - left shift a:x<-0 by 1 */
8653 /*-----------------------------------------------------------------*/
8657 emitcode ("xch", "a,%s", x);
8658 emitcode ("add", "a,acc");
8659 emitcode ("xch", "a,%s", x);
8660 emitcode ("rlc", "a");
8664 #ifdef BETTER_LITERAL_SHIFT
8665 /*-----------------------------------------------------------------*/
8666 /* AccAXLsh - left shift a:x by known count (0..7) */
8667 /*-----------------------------------------------------------------*/
8669 AccAXLsh (char *x, int shCount)
8684 case 5: // AAAAABBB:CCCCCDDD
8686 AccRol (shCount); // BBBAAAAA:CCCCCDDD
8688 emitcode ("anl", "a,#!constbyte",
8689 SLMask[shCount]); // BBB00000:CCCCCDDD
8691 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
8693 AccRol (shCount); // DDDCCCCC:BBB00000
8695 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8697 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8699 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8701 emitcode ("anl", "a,#!constbyte",
8702 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8704 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8706 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8709 case 6: // AAAAAABB:CCCCCCDD
8710 emitcode ("anl", "a,#!constbyte",
8711 SRMask[shCount]); // 000000BB:CCCCCCDD
8713 AccAXRrl1 (x); // D000000B:BCCCCCCD
8714 AccAXRrl1 (x); // DD000000:BBCCCCCC
8715 emitcode ("xch", "a,%s", x); // BBCCCCCC:DD000000
8717 emitcode ("mov", "c,acc.0"); // c = B
8718 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8719 emitcode("rrc","a");
8720 emitcode("xch","a,%s", x);
8721 emitcode("rrc","a");
8722 emitcode("mov","c,acc.0"); //<< get correct bit
8723 emitcode("xch","a,%s", x);
8725 emitcode("rrc","a");
8726 emitcode("xch","a,%s", x);
8727 emitcode("rrc","a");
8728 emitcode("xch","a,%s", x);
8731 case 7: // a:x <<= 7
8733 emitcode ("anl", "a,#!constbyte",
8734 SRMask[shCount]); // 0000000B:CCCCCCCD
8736 AccAXRrl1 (x); // D0000000:BCCCCCCC
8738 emitcode ("xch", "a,%s", x); // BCCCCCCC:D0000000
8747 #ifdef BETTER_LITERAL_SHIFT
8749 /*-----------------------------------------------------------------*/
8750 /* AccAXRsh - right shift a:x known count (0..7) */
8751 /*-----------------------------------------------------------------*/
8753 AccAXRsh (char *x, int shCount)
8761 AccAXRsh1 (x); // 0->a:x
8766 AccAXRsh1 (x); // 0->a:x
8769 AccAXRsh1 (x); // 0->a:x
8774 case 5: // AAAAABBB:CCCCCDDD = a:x
8776 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8778 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8780 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8782 emitcode ("anl", "a,#!constbyte",
8783 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8785 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8787 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8789 emitcode ("anl", "a,#!constbyte",
8790 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8792 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8794 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8796 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8799 case 6: // AABBBBBB:CCDDDDDD
8801 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDE
8802 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8804 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8806 emitcode ("anl", "a,#!constbyte",
8807 SRMask[shCount]); // 000000AA:BBBBBBCC
8810 case 7: // ABBBBBBB:CDDDDDDD
8812 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8814 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8816 emitcode ("anl", "a,#!constbyte",
8817 SRMask[shCount]); // 0000000A:BBBBBBBC
8826 #ifdef BETTER_LITERAL_SHIFT
8827 /*-----------------------------------------------------------------*/
8828 /* AccAXRshS - right shift signed a:x known count (0..7) */
8829 /*-----------------------------------------------------------------*/
8831 AccAXRshS (char *x, int shCount)
8839 emitcode ("mov", "c,acc.7");
8840 AccAXRsh1 (x); // s->a:x
8844 emitcode ("mov", "c,acc.7");
8845 AccAXRsh1 (x); // s->a:x
8847 emitcode ("mov", "c,acc.7");
8848 AccAXRsh1 (x); // s->a:x
8853 case 5: // AAAAABBB:CCCCCDDD = a:x
8855 tlbl = newiTempLabel (NULL);
8856 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8858 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8860 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8862 emitcode ("anl", "a,#!constbyte",
8863 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8865 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8867 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8869 emitcode ("anl", "a,#!constbyte",
8870 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8872 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8874 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8876 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8878 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8879 emitcode ("orl", "a,#!constbyte",
8880 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8882 emitcode ("", "!tlabeldef", tlbl->key + 100);
8883 break; // SSSSAAAA:BBBCCCCC
8885 case 6: // AABBBBBB:CCDDDDDD
8887 tlbl = newiTempLabel (NULL);
8889 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8890 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8892 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8894 emitcode ("anl", "a,#!constbyte",
8895 SRMask[shCount]); // 000000AA:BBBBBBCC
8897 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8898 emitcode ("orl", "a,#!constbyte",
8899 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8901 emitcode ("", "!tlabeldef", tlbl->key + 100);
8903 case 7: // ABBBBBBB:CDDDDDDD
8905 tlbl = newiTempLabel (NULL);
8907 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8909 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8911 emitcode ("anl", "a,#!constbyte",
8912 SRMask[shCount]); // 0000000A:BBBBBBBC
8914 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
8915 emitcode ("orl", "a,#!constbyte",
8916 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8918 emitcode ("", "!tlabeldef", tlbl->key + 100);
8926 #ifdef BETTER_LITERAL_SHIFT
8928 _loadLeftIntoAx(char **lsb,
8934 // Get the initial value from left into a pair of registers.
8935 // MSB must be in A, LSB can be any register.
8937 // If the result is held in registers, it is an optimization
8938 // if the LSB can be held in the register which will hold the,
8939 // result LSB since this saves us from having to copy it into
8940 // the result following AccAXLsh.
8942 // If the result is addressed indirectly, this is not a gain.
8943 if (AOP_NEEDSACC(result))
8947 _startLazyDPSEvaluation();
8948 if (AOP_TYPE(left) == AOP_DPTR2)
8951 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE, NULL));
8952 // get LSB in DP2_RESULT_REG.
8953 leftByte = aopGet (left, offl, FALSE, FALSE, DP2_RESULT_REG);
8954 assert(!strcmp(leftByte, DP2_RESULT_REG));
8958 // get LSB into DP2_RESULT_REG
8959 leftByte = aopGet (left, offl, FALSE, FALSE, NULL);
8960 if (strcmp(leftByte, DP2_RESULT_REG))
8963 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
8966 leftByte = aopGet (left, offl + MSB16, FALSE, FALSE, NULL);
8967 assert(strcmp(leftByte, DP2_RESULT_REG));
8970 _endLazyDPSEvaluation();
8971 *lsb = DP2_RESULT_REG;
8975 if (sameRegs (AOP (result), AOP (left)) &&
8976 ((offl + MSB16) == offr))
8978 /* don't crash result[offr] */
8979 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
8980 emitcode ("xch", "a,%s",
8981 aopGet (left, offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
8985 movLeft2Result (left, offl, result, offr, 0);
8986 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE, NULL));
8988 *lsb = aopGet (result, offr, FALSE, FALSE, DP2_RESULT_REG);
8989 assert(strcmp(*lsb,"a"));
8994 _storeAxResults(char *lsb,
8998 _startLazyDPSEvaluation();
8999 if (AOP_NEEDSACC(result))
9001 /* We have to explicitly update the result LSB.
9003 emitcode ("xch","a,%s", lsb);
9004 aopPut (result, "a", offr);
9005 emitcode ("mov","a,%s", lsb);
9007 if (getDataSize (result) > 1)
9009 aopPut (result, "a", offr + MSB16);
9011 _endLazyDPSEvaluation();
9014 /*-----------------------------------------------------------------*/
9015 /* shiftL2Left2Result - shift left two bytes from left to result */
9016 /*-----------------------------------------------------------------*/
9018 shiftL2Left2Result (operand * left, int offl,
9019 operand * result, int offr, int shCount)
9023 _loadLeftIntoAx(&lsb, left, result, offl, offr);
9025 AccAXLsh (lsb, shCount);
9027 _storeAxResults(lsb, result, offr);
9031 #ifdef BETTER_LITERAL_SHIFT
9032 /*-----------------------------------------------------------------*/
9033 /* shiftR2Left2Result - shift right two bytes from left to result */
9034 /*-----------------------------------------------------------------*/
9036 shiftR2Left2Result (operand * left, int offl,
9037 operand * result, int offr,
9038 int shCount, int sign)
9042 _loadLeftIntoAx(&lsb, left, result, offl, offr);
9044 /* a:x >> shCount (x = lsb(result)) */
9047 AccAXRshS(lsb, shCount);
9051 AccAXRsh(lsb, shCount);
9054 _storeAxResults(lsb, result, offr);
9058 /*-----------------------------------------------------------------*/
9059 /* shiftLLeftOrResult - shift left one byte from left, or to result */
9060 /*-----------------------------------------------------------------*/
9062 shiftLLeftOrResult (operand * left, int offl,
9063 operand * result, int offr, int shCount)
9065 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
9066 /* shift left accumulator */
9068 /* or with result */
9069 emitcode ("orl", "a,%s",
9070 aopGet (result, offr, FALSE, FALSE, DP2_RESULT_REG));
9071 /* back to result */
9072 aopPut (result, "a", offr);
9077 /*-----------------------------------------------------------------*/
9078 /* shiftRLeftOrResult - shift right one byte from left,or to result */
9079 /*-----------------------------------------------------------------*/
9081 shiftRLeftOrResult (operand * left, int offl,
9082 operand * result, int offr, int shCount)
9084 MOVA (aopGet (left, offl, FALSE, FALSE, NULL));
9085 /* shift right accumulator */
9087 /* or with result */
9088 emitcode ("orl", "a,%s",
9089 aopGet (result, offr, FALSE, FALSE, DP2_RESULT_REG));
9090 /* back to result */
9091 aopPut (result, "a", offr);
9095 #ifdef BETTER_LITERAL_SHIFT
9096 /*-----------------------------------------------------------------*/
9097 /* genlshOne - left shift a one byte quantity by known count */
9098 /*-----------------------------------------------------------------*/
9100 genlshOne (operand * result, operand * left, int shCount)
9102 D (emitcode (";", "genlshOne "));
9104 shiftL1Left2Result (left, LSB, result, LSB, shCount);
9108 #ifdef BETTER_LITERAL_SHIFT
9109 /*-----------------------------------------------------------------*/
9110 /* genlshTwo - left shift two bytes by known amount != 0 */
9111 /*-----------------------------------------------------------------*/
9113 genlshTwo (operand * result, operand * left, int shCount)
9117 D (emitcode (";", "genlshTwo"));
9119 size = getDataSize (result);
9121 /* if shCount >= 8 */
9126 _startLazyDPSEvaluation();
9132 _endLazyDPSEvaluation();
9133 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
9134 aopPut (result, zero, LSB);
9138 movLeft2Result (left, LSB, result, MSB16, 0);
9139 aopPut (result, zero, LSB);
9140 _endLazyDPSEvaluation();
9145 aopPut (result, zero, LSB);
9146 _endLazyDPSEvaluation();
9150 /* 1 <= shCount <= 7 */
9154 shiftL1Left2Result (left, LSB, result, LSB, shCount);
9156 shiftL2Left2Result (left, LSB, result, LSB, shCount);
9163 /*-----------------------------------------------------------------*/
9164 /* shiftLLong - shift left one long from left to result */
9165 /* offl = LSB or MSB16 */
9166 /*-----------------------------------------------------------------*/
9168 shiftLLong (operand * left, operand * result, int offr)
9171 int size = AOP_SIZE (result);
9173 if (size >= LSB + offr)
9175 l = aopGet (left, LSB, FALSE, FALSE, NULL);
9177 emitcode ("add", "a,acc");
9178 if (sameRegs (AOP (left), AOP (result)) &&
9179 size >= MSB16 + offr && offr != LSB)
9180 emitcode ("xch", "a,%s",
9181 aopGet (left, LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
9183 aopPut (result, "a", LSB + offr);
9186 if (size >= MSB16 + offr)
9188 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
9190 l = aopGet (left, MSB16, FALSE, FALSE, TRUE);
9193 emitcode ("rlc", "a");
9194 if (sameRegs (AOP (left), AOP (result)) &&
9195 size >= MSB24 + offr && offr != LSB)
9196 emitcode ("xch", "a,%s",
9197 aopGet (left, MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
9199 aopPut (result, "a", MSB16 + offr);
9202 if (size >= MSB24 + offr)
9204 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
9206 l = aopGet (left, MSB24, FALSE, FALSE, NULL);
9209 emitcode ("rlc", "a");
9210 if (sameRegs (AOP (left), AOP (result)) &&
9211 size >= MSB32 + offr && offr != LSB)
9212 emitcode ("xch", "a,%s",
9213 aopGet (left, MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
9215 aopPut (result, "a", MSB24 + offr);
9218 if (size > MSB32 + offr)
9220 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
9222 l = aopGet (left, MSB32, FALSE, FALSE, NULL);
9225 emitcode ("rlc", "a");
9226 aopPut (result, "a", MSB32 + offr);
9229 aopPut (result, zero, LSB);
9235 /*-----------------------------------------------------------------*/
9236 /* genlshFour - shift four byte by a known amount != 0 */
9237 /*-----------------------------------------------------------------*/
9239 genlshFour (operand * result, operand * left, int shCount)
9243 D (emitcode (";", "genlshFour "));
9245 size = AOP_SIZE (result);
9247 /* if shifting more that 3 bytes */
9252 /* lowest order of left goes to the highest
9253 order of the destination */
9254 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
9256 movLeft2Result (left, LSB, result, MSB32, 0);
9257 aopPut (result, zero, LSB);
9258 aopPut (result, zero, MSB16);
9259 aopPut (result, zero, MSB24);
9263 /* more than two bytes */
9264 else if (shCount >= 16)
9266 /* lower order two bytes goes to higher order two bytes */
9268 /* if some more remaining */
9270 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
9273 movLeft2Result (left, MSB16, result, MSB32, 0);
9274 movLeft2Result (left, LSB, result, MSB24, 0);
9276 aopPut (result, zero, MSB16);
9277 aopPut (result, zero, LSB);
9281 /* if more than 1 byte */
9282 else if (shCount >= 8)
9284 /* lower order three bytes goes to higher order three bytes */
9289 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
9291 movLeft2Result (left, LSB, result, MSB16, 0);
9297 movLeft2Result (left, MSB24, result, MSB32, 0);
9298 movLeft2Result (left, MSB16, result, MSB24, 0);
9299 movLeft2Result (left, LSB, result, MSB16, 0);
9300 aopPut (result, zero, LSB);
9302 else if (shCount == 1)
9303 shiftLLong (left, result, MSB16);
9306 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
9307 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
9308 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
9309 aopPut (result, zero, LSB);
9314 /* 1 <= shCount <= 7 */
9315 else if (shCount <= 2)
9317 shiftLLong (left, result, LSB);
9319 shiftLLong (result, result, LSB);
9321 /* 3 <= shCount <= 7, optimize */
9324 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
9325 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
9326 shiftL2Left2Result (left, LSB, result, LSB, shCount);
9331 #ifdef BETTER_LITERAL_SHIFT
9332 /*-----------------------------------------------------------------*/
9333 /* genLeftShiftLiteral - left shifting by known count */
9334 /*-----------------------------------------------------------------*/
9336 genLeftShiftLiteral (operand * left,
9341 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9344 size = getSize (operandType (result));
9346 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
9348 /* We only handle certain easy cases so far. */
9350 && (shCount < (size * 8))
9354 D(emitcode (";", "genLeftShiftLiteral wimping out"););
9358 freeAsmop (right, NULL, ic, TRUE);
9360 aopOp(left, ic, FALSE, FALSE);
9361 aopOp(result, ic, FALSE, AOP_USESDPTR(left));
9364 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
9366 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
9367 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
9369 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
9372 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
9374 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
9375 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
9377 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
9383 emitcode ("; shift left ", "result %d, left %d", size,
9387 /* I suppose that the left size >= result size */
9390 _startLazyDPSEvaluation();
9393 movLeft2Result (left, size, result, size, 0);
9395 _endLazyDPSEvaluation();
9397 else if (shCount >= (size * 8))
9399 _startLazyDPSEvaluation();
9402 aopPut (result, zero, size);
9404 _endLazyDPSEvaluation();
9411 genlshOne (result, left, shCount);
9415 genlshTwo (result, left, shCount);
9419 genlshFour (result, left, shCount);
9423 fprintf(stderr, "*** ack! mystery literal shift!\n");
9427 freeAsmop (result, NULL, ic, TRUE);
9428 freeAsmop (left, NULL, ic, TRUE);
9433 /*-----------------------------------------------------------------*/
9434 /* genLeftShift - generates code for left shifting */
9435 /*-----------------------------------------------------------------*/
9437 genLeftShift (iCode * ic)
9439 operand *left, *right, *result;
9442 symbol *tlbl, *tlbl1;
9445 D (emitcode (";", "genLeftShift "));
9447 right = IC_RIGHT (ic);
9448 left = IC_LEFT (ic);
9449 result = IC_RESULT (ic);
9451 aopOp (right, ic, FALSE, FALSE);
9454 #ifdef BETTER_LITERAL_SHIFT
9455 /* if the shift count is known then do it
9456 as efficiently as possible */
9457 if (AOP_TYPE (right) == AOP_LIT)
9459 if (genLeftShiftLiteral (left, right, result, ic))
9466 /* shift count is unknown then we have to form
9467 a loop get the loop count in B : Note: we take
9468 only the lower order byte since shifting
9469 more that 32 bits make no sense anyway, ( the
9470 largest size of an object can be only 32 bits ) */
9473 if (AOP_TYPE (right) == AOP_LIT)
9475 /* Really should be handled by genLeftShiftLiteral,
9476 * but since I'm too lazy to fix that today, at least we can make
9477 * some small improvement.
9479 emitcode("mov", "b,#!constbyte",
9480 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9484 MOVB (aopGet (right, 0, FALSE, FALSE, "b"));
9485 emitcode ("inc", "b");
9487 freeAsmop (right, NULL, ic, TRUE);
9488 aopOp (left, ic, FALSE, FALSE);
9489 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9491 /* now move the left to the result if they are not the same */
9492 if (!sameRegs (AOP (left), AOP (result)) &&
9493 AOP_SIZE (result) > 1)
9496 size = AOP_SIZE (result);
9498 _startLazyDPSEvaluation ();
9501 l = aopGet (left, offset, FALSE, TRUE, NULL);
9502 if (*l == '@' && (IS_AOP_PREG (result)))
9505 emitcode ("mov", "a,%s", l);
9506 aopPut (result, "a", offset);
9509 aopPut (result, l, offset);
9512 _endLazyDPSEvaluation ();
9515 tlbl = newiTempLabel (NULL);
9516 size = AOP_SIZE (result);
9518 tlbl1 = newiTempLabel (NULL);
9520 /* if it is only one byte then */
9523 symbol *tlbl1 = newiTempLabel (NULL);
9525 l = aopGet (left, 0, FALSE, FALSE, NULL);
9527 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9528 emitcode ("", "!tlabeldef", tlbl->key + 100);
9529 emitcode ("add", "a,acc");
9530 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9531 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9533 aopPut (result, "a", 0);
9537 reAdjustPreg (AOP (result));
9539 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9540 emitcode ("", "!tlabeldef", tlbl->key + 100);
9541 l = aopGet (result, offset, FALSE, FALSE, NULL);
9543 emitcode ("add", "a,acc");
9544 aopPut (result, "a", offset++);
9545 _startLazyDPSEvaluation ();
9548 l = aopGet (result, offset, FALSE, FALSE, NULL);
9550 emitcode ("rlc", "a");
9551 aopPut (result, "a", offset++);
9553 _endLazyDPSEvaluation ();
9554 reAdjustPreg (AOP (result));
9556 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9557 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9560 freeAsmop (result, NULL, ic, TRUE);
9561 freeAsmop (left, NULL, ic, TRUE);
9564 #ifdef BETTER_LITERAL_SHIFT
9565 /*-----------------------------------------------------------------*/
9566 /* genrshOne - right shift a one byte quantity by known count */
9567 /*-----------------------------------------------------------------*/
9569 genrshOne (operand * result, operand * left,
9570 int shCount, int sign)
9572 D (emitcode (";", "genrshOne"));
9573 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9577 #ifdef BETTER_LITERAL_SHIFT
9578 /*-----------------------------------------------------------------*/
9579 /* genrshTwo - right shift two bytes by known amount != 0 */
9580 /*-----------------------------------------------------------------*/
9582 genrshTwo (operand * result, operand * left,
9583 int shCount, int sign)
9585 D (emitcode (";", "genrshTwo"));
9587 /* if shCount >= 8 */
9591 _startLazyDPSEvaluation();
9593 shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
9595 movLeft2Result (left, MSB16, result, LSB, sign);
9596 addSign (result, MSB16, sign);
9597 _endLazyDPSEvaluation();
9600 /* 1 <= shCount <= 7 */
9602 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9606 /*-----------------------------------------------------------------*/
9607 /* shiftRLong - shift right one long from left to result */
9608 /* offl = LSB or MSB16 */
9609 /*-----------------------------------------------------------------*/
9611 shiftRLong (operand * left, int offl,
9612 operand * result, int sign)
9614 int isSameRegs=sameRegs(AOP(left),AOP(result));
9616 if (isSameRegs && offl>1) {
9617 // we are in big trouble, but this shouldn't happen
9618 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9621 MOVA (aopGet (left, MSB32, FALSE, FALSE, NULL));
9628 emitcode ("rlc", "a");
9629 emitcode ("subb", "a,acc");
9630 emitcode ("xch", "a,%s",
9631 aopGet(left, MSB32, FALSE, FALSE, DP2_RESULT_REG));
9635 aopPut (result, zero, MSB32);
9641 emitcode ("clr", "c");
9645 emitcode ("mov", "c,acc.7");
9648 emitcode ("rrc", "a");
9650 if (isSameRegs && offl==MSB16) {
9652 "a,%s",aopGet (left, MSB24, FALSE, FALSE, DP2_RESULT_REG));
9654 aopPut (result, "a", MSB32);
9655 MOVA (aopGet (left, MSB24, FALSE, FALSE, NULL));
9658 emitcode ("rrc", "a");
9659 if (isSameRegs && offl==1) {
9660 emitcode ("xch", "a,%s",
9661 aopGet (left, MSB16, FALSE, FALSE, DP2_RESULT_REG));
9663 aopPut (result, "a", MSB24);
9664 MOVA (aopGet (left, MSB16, FALSE, FALSE, NULL));
9666 emitcode ("rrc", "a");
9667 aopPut (result, "a", MSB16 - offl);
9671 MOVA (aopGet (left, LSB, FALSE, FALSE, NULL));
9672 emitcode ("rrc", "a");
9673 aopPut (result, "a", LSB);
9677 /*-----------------------------------------------------------------*/
9678 /* genrshFour - shift four byte by a known amount != 0 */
9679 /*-----------------------------------------------------------------*/
9681 genrshFour (operand * result, operand * left,
9682 int shCount, int sign)
9684 D (emitcode (";", "genrshFour"));
9686 /* if shifting more that 3 bytes */
9690 _startLazyDPSEvaluation();
9692 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9694 movLeft2Result (left, MSB32, result, LSB, sign);
9695 addSign (result, MSB16, sign);
9696 _endLazyDPSEvaluation();
9698 else if (shCount >= 16)
9701 _startLazyDPSEvaluation();
9703 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9706 movLeft2Result (left, MSB24, result, LSB, 0);
9707 movLeft2Result (left, MSB32, result, MSB16, sign);
9709 addSign (result, MSB24, sign);
9710 _endLazyDPSEvaluation();
9712 else if (shCount >= 8)
9715 _startLazyDPSEvaluation();
9718 shiftRLong (left, MSB16, result, sign);
9720 else if (shCount == 0)
9722 movLeft2Result (left, MSB16, result, LSB, 0);
9723 movLeft2Result (left, MSB24, result, MSB16, 0);
9724 movLeft2Result (left, MSB32, result, MSB24, sign);
9725 addSign (result, MSB32, sign);
9729 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9730 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9731 /* the last shift is signed */
9732 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9733 addSign (result, MSB32, sign);
9735 _endLazyDPSEvaluation();
9739 /* 1 <= shCount <= 7 */
9742 shiftRLong (left, LSB, result, sign);
9744 shiftRLong (result, LSB, result, sign);
9748 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9749 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9750 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9755 #ifdef BETTER_LITERAL_SHIFT
9756 /*-----------------------------------------------------------------*/
9757 /* genRightShiftLiteral - right shifting by known count */
9758 /*-----------------------------------------------------------------*/
9760 genRightShiftLiteral (operand * left,
9766 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9769 size = getSize (operandType (result));
9771 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
9773 /* We only handle certain easy cases so far. */
9775 && (shCount < (size * 8))
9780 D(emitcode (";", "genRightShiftLiteral wimping out"););
9784 freeAsmop (right, NULL, ic, TRUE);
9786 aopOp (left, ic, FALSE, FALSE);
9787 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9790 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9794 /* test the LEFT size !!! */
9796 /* I suppose that the left size >= result size */
9799 size = getDataSize (result);
9800 _startLazyDPSEvaluation();
9802 movLeft2Result (left, size, result, size, 0);
9803 _endLazyDPSEvaluation();
9805 else if (shCount >= (size * 8))
9809 /* get sign in acc.7 */
9810 MOVA (aopGet (left, size - 1, FALSE, FALSE, NULL));
9812 addSign (result, LSB, sign);
9819 genrshOne (result, left, shCount, sign);
9823 genrshTwo (result, left, shCount, sign);
9827 genrshFour (result, left, shCount, sign);
9834 freeAsmop (result, NULL, ic, TRUE);
9835 freeAsmop (left, NULL, ic, TRUE);
9841 /*-----------------------------------------------------------------*/
9842 /* genSignedRightShift - right shift of signed number */
9843 /*-----------------------------------------------------------------*/
9845 genSignedRightShift (iCode * ic)
9847 operand *right, *left, *result;
9850 symbol *tlbl, *tlbl1;
9853 D (emitcode (";", "genSignedRightShift"));
9855 /* we do it the hard way put the shift count in b
9856 and loop thru preserving the sign */
9858 right = IC_RIGHT (ic);
9859 left = IC_LEFT (ic);
9860 result = IC_RESULT (ic);
9862 aopOp (right, ic, FALSE, FALSE);
9864 #ifdef BETTER_LITERAL_SHIFT
9865 if (AOP_TYPE (right) == AOP_LIT)
9867 if (genRightShiftLiteral (left, right, result, ic, 1))
9873 /* shift count is unknown then we have to form
9874 a loop get the loop count in B : Note: we take
9875 only the lower order byte since shifting
9876 more that 32 bits make no sense anyway, ( the
9877 largest size of an object can be only 32 bits ) */
9880 if (AOP_TYPE (right) == AOP_LIT)
9882 /* Really should be handled by genRightShiftLiteral,
9883 * but since I'm too lazy to fix that today, at least we can make
9884 * some small improvement.
9886 emitcode("mov", "b,#!constbyte",
9887 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
9891 MOVB (aopGet (right, 0, FALSE, FALSE, "b"));
9892 emitcode ("inc", "b");
9894 freeAsmop (right, NULL, ic, TRUE);
9895 aopOp (left, ic, FALSE, FALSE);
9896 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
9898 /* now move the left to the result if they are not the
9900 if (!sameRegs (AOP (left), AOP (result)) &&
9901 AOP_SIZE (result) > 1)
9904 size = AOP_SIZE (result);
9906 _startLazyDPSEvaluation ();
9909 l = aopGet (left, offset, FALSE, TRUE, NULL);
9910 if (*l == '@' && IS_AOP_PREG (result))
9913 emitcode ("mov", "a,%s", l);
9914 aopPut (result, "a", offset);
9917 aopPut (result, l, offset);
9920 _endLazyDPSEvaluation ();
9923 /* mov the highest order bit to OVR */
9924 tlbl = newiTempLabel (NULL);
9925 tlbl1 = newiTempLabel (NULL);
9927 size = AOP_SIZE (result);
9929 MOVA (aopGet (left, offset, FALSE, FALSE, NULL));
9930 emitcode ("rlc", "a");
9931 emitcode ("mov", "ov,c");
9932 /* if it is only one byte then */
9935 l = aopGet (left, 0, FALSE, FALSE, NULL);
9937 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9938 emitcode ("", "!tlabeldef", tlbl->key + 100);
9939 emitcode ("mov", "c,ov");
9940 emitcode ("rrc", "a");
9941 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9942 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9944 aopPut (result, "a", 0);
9948 reAdjustPreg (AOP (result));
9949 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
9950 emitcode ("", "!tlabeldef", tlbl->key + 100);
9951 emitcode ("mov", "c,ov");
9952 _startLazyDPSEvaluation ();
9955 l = aopGet (result, offset, FALSE, FALSE, NULL);
9957 emitcode ("rrc", "a");
9958 aopPut (result, "a", offset--);
9960 _endLazyDPSEvaluation ();
9961 reAdjustPreg (AOP (result));
9962 emitcode ("", "!tlabeldef", tlbl1->key + 100);
9963 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
9967 freeAsmop (result, NULL, ic, TRUE);
9968 freeAsmop (left, NULL, ic, TRUE);
9971 /*-----------------------------------------------------------------*/
9972 /* genRightShift - generate code for right shifting */
9973 /*-----------------------------------------------------------------*/
9975 genRightShift (iCode * ic)
9977 operand *right, *left, *result;
9981 symbol *tlbl, *tlbl1;
9984 D (emitcode (";", "genRightShift"));
9986 /* if signed then we do it the hard way preserve the
9987 sign bit moving it inwards */
9988 letype = getSpec (operandType (IC_LEFT (ic)));
9990 if (!SPEC_USIGN (letype))
9992 genSignedRightShift (ic);
9996 /* signed & unsigned types are treated the same : i.e. the
9997 signed is NOT propagated inwards : quoting from the
9998 ANSI - standard : "for E1 >> E2, is equivalent to division
9999 by 2**E2 if unsigned or if it has a non-negative value,
10000 otherwise the result is implementation defined ", MY definition
10001 is that the sign does not get propagated */
10003 right = IC_RIGHT (ic);
10004 left = IC_LEFT (ic);
10005 result = IC_RESULT (ic);
10007 aopOp (right, ic, FALSE, FALSE);
10009 #ifdef BETTER_LITERAL_SHIFT
10010 /* if the shift count is known then do it
10011 as efficiently as possible */
10012 if (AOP_TYPE (right) == AOP_LIT)
10014 if (genRightShiftLiteral (left, right, result, ic, 0))
10021 /* shift count is unknown then we have to form
10022 a loop get the loop count in B : Note: we take
10023 only the lower order byte since shifting
10024 more that 32 bits make no sense anyway, ( the
10025 largest size of an object can be only 32 bits ) */
10027 pushedB = pushB ();
10028 if (AOP_TYPE (right) == AOP_LIT)
10030 /* Really should be handled by genRightShiftLiteral,
10031 * but since I'm too lazy to fix that today, at least we can make
10032 * some small improvement.
10034 emitcode("mov", "b,#!constbyte",
10035 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
10039 MOVB (aopGet (right, 0, FALSE, FALSE, "b"));
10040 emitcode ("inc", "b");
10042 freeAsmop (right, NULL, ic, TRUE);
10043 aopOp (left, ic, FALSE, FALSE);
10044 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
10046 /* now move the left to the result if they are not the
10048 if (!sameRegs (AOP (left), AOP (result)) &&
10049 AOP_SIZE (result) > 1)
10051 size = AOP_SIZE (result);
10053 _startLazyDPSEvaluation ();
10056 l = aopGet (left, offset, FALSE, TRUE, NULL);
10057 if (*l == '@' && IS_AOP_PREG (result))
10060 emitcode ("mov", "a,%s", l);
10061 aopPut (result, "a", offset);
10064 aopPut (result, l, offset);
10067 _endLazyDPSEvaluation ();
10070 tlbl = newiTempLabel (NULL);
10071 tlbl1 = newiTempLabel (NULL);
10072 size = AOP_SIZE (result);
10075 /* if it is only one byte then */
10078 l = aopGet (left, 0, FALSE, FALSE, NULL);
10080 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
10081 emitcode ("", "!tlabeldef", tlbl->key + 100);
10083 emitcode ("rrc", "a");
10084 emitcode ("", "!tlabeldef", tlbl1->key + 100);
10085 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
10087 aopPut (result, "a", 0);
10091 reAdjustPreg (AOP (result));
10092 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
10093 emitcode ("", "!tlabeldef", tlbl->key + 100);
10095 _startLazyDPSEvaluation ();
10098 l = aopGet (result, offset, FALSE, FALSE, NULL);
10100 emitcode ("rrc", "a");
10101 aopPut (result, "a", offset--);
10103 _endLazyDPSEvaluation ();
10104 reAdjustPreg (AOP (result));
10106 emitcode ("", "!tlabeldef", tlbl1->key + 100);
10107 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
10111 freeAsmop (result, NULL, ic, TRUE);
10112 freeAsmop (left, NULL, ic, TRUE);
10115 /*-----------------------------------------------------------------*/
10116 /* emitPtrByteGet - emits code to get a byte into A through a */
10117 /* pointer register (R0, R1, or DPTR). The */
10118 /* original value of A can be preserved in B. */
10119 /*-----------------------------------------------------------------*/
10121 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
10128 emitcode ("mov", "b,a");
10129 emitcode ("mov", "a,@%s", rname);
10134 emitcode ("mov", "b,a");
10135 emitcode ("movx", "a,@%s", rname);
10140 emitcode ("mov", "b,a");
10141 emitcode ("movx", "a,@dptr");
10146 emitcode ("mov", "b,a");
10147 emitcode ("clr", "a");
10148 emitcode ("movc", "a,@a+dptr");
10154 emitcode ("push", "b");
10155 emitcode ("push", "acc");
10157 emitcode ("lcall", "__gptrget");
10159 emitcode ("pop", "b");
10164 /*-----------------------------------------------------------------*/
10165 /* emitPtrByteSet - emits code to set a byte from src through a */
10166 /* pointer register (R0, R1, or DPTR). */
10167 /*-----------------------------------------------------------------*/
10169 emitPtrByteSet (char *rname, int p_type, char *src)
10178 emitcode ("mov", "@%s,a", rname);
10181 emitcode ("mov", "@%s,%s", rname, src);
10186 emitcode ("movx", "@%s,a", rname);
10191 emitcode ("movx", "@dptr,a");
10196 emitcode ("lcall", "__gptrput");
10201 /*-----------------------------------------------------------------*/
10202 /* genUnpackBits - generates code for unpacking bits */
10203 /*-----------------------------------------------------------------*/
10205 genUnpackBits (operand * result, char *rname, int ptype)
10207 int offset = 0; /* result byte offset */
10208 int rsize; /* result size */
10209 int rlen = 0; /* remaining bitfield length */
10210 sym_link *etype; /* bitfield type information */
10211 int blen; /* bitfield length */
10212 int bstr; /* bitfield starting bit within byte */
10214 D(emitcode ("; genUnpackBits",""));
10216 etype = getSpec (operandType (result));
10217 rsize = getSize (operandType (result));
10218 blen = SPEC_BLEN (etype);
10219 bstr = SPEC_BSTR (etype);
10221 /* If the bitfield length is less than a byte */
10224 emitPtrByteGet (rname, ptype, FALSE);
10226 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
10227 if (!SPEC_USIGN (etype))
10229 /* signed bitfield */
10230 symbol *tlbl = newiTempLabel (NULL);
10232 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
10233 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
10234 emitcode ("", "%05d$:", tlbl->key + 100);
10236 aopPut (result, "a", offset++);
10240 /* Bit field did not fit in a byte. Copy all
10241 but the partial byte at the end. */
10242 for (rlen=blen;rlen>=8;rlen-=8)
10244 emitPtrByteGet (rname, ptype, FALSE);
10245 aopPut (result, "a", offset++);
10247 emitcode ("inc", "%s", rname);
10250 /* Handle the partial byte at the end */
10253 emitPtrByteGet (rname, ptype, FALSE);
10254 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
10255 if (!SPEC_USIGN (etype))
10257 /* signed bitfield */
10258 symbol *tlbl = newiTempLabel (NULL);
10260 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
10261 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
10262 emitcode ("", "%05d$:", tlbl->key + 100);
10264 aopPut (result, "a", offset++);
10268 if (offset < rsize)
10272 if (SPEC_USIGN (etype))
10276 /* signed bitfield: sign extension with 0x00 or 0xff */
10277 emitcode ("rlc", "a");
10278 emitcode ("subb", "a,acc");
10284 aopPut (result, source, offset++);
10289 /*-----------------------------------------------------------------*/
10290 /* genDataPointerGet - generates code when ptr offset is known */
10291 /*-----------------------------------------------------------------*/
10293 genDataPointerGet (operand * left,
10299 int size, offset = 0;
10300 aopOp (result, ic, TRUE, FALSE);
10302 /* get the string representation of the name */
10303 l = aopGet (left, 0, FALSE, TRUE, NULL);
10304 size = AOP_SIZE (result);
10305 _startLazyDPSEvaluation ();
10310 SNPRINTF (buffer, sizeof(buffer),
10311 "(%s + %d)", l + 1, offset);
10315 SNPRINTF (buffer, sizeof(buffer),
10318 aopPut (result, buffer, offset++);
10320 _endLazyDPSEvaluation ();
10322 freeAsmop (result, NULL, ic, TRUE);
10323 freeAsmop (left, NULL, ic, TRUE);
10326 /*-----------------------------------------------------------------*/
10327 /* genNearPointerGet - emitcode for near pointer fetch */
10328 /*-----------------------------------------------------------------*/
10330 genNearPointerGet (operand * left,
10338 sym_link *rtype, *retype, *letype;
10339 sym_link *ltype = operandType (left);
10342 rtype = operandType (result);
10343 retype = getSpec (rtype);
10344 letype = getSpec (ltype);
10346 aopOp (left, ic, FALSE, FALSE);
10348 /* if left is rematerialisable and
10349 result is not bitfield variable type and
10350 the left is pointer to data space i.e
10351 lower 128 bytes of space */
10352 if (AOP_TYPE (left) == AOP_IMMD &&
10353 !IS_BITFIELD (retype) &&
10354 !IS_BITFIELD (letype) &&
10355 DCL_TYPE (ltype) == POINTER)
10357 genDataPointerGet (left, result, ic);
10361 /* if the value is already in a pointer register
10362 then don't need anything more */
10363 if (!AOP_INPREG (AOP (left)))
10365 /* otherwise get a free pointer register */
10366 aop = newAsmop (0);
10367 preg = getFreePtr (ic, &aop, FALSE);
10368 emitcode ("mov", "%s,%s",
10370 aopGet (left, 0, FALSE, TRUE, DP2_RESULT_REG));
10371 rname = preg->name;
10374 rname = aopGet (left, 0, FALSE, FALSE, DP2_RESULT_REG);
10376 freeAsmop (left, NULL, ic, TRUE);
10377 aopOp (result, ic, FALSE, FALSE);
10379 /* if bitfield then unpack the bits */
10380 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10381 genUnpackBits (result, rname, POINTER);
10384 /* we have can just get the values */
10385 int size = AOP_SIZE (result);
10390 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
10393 emitcode ("mov", "a,@%s", rname);
10394 aopPut (result, "a", offset);
10398 SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
10399 aopPut (result, buffer, offset);
10403 emitcode ("inc", "%s", rname);
10407 /* now some housekeeping stuff */
10408 if (aop) /* we had to allocate for this iCode */
10410 if (pi) { /* post increment present */
10411 aopPut (left, rname, 0);
10413 freeAsmop (NULL, aop, ic, TRUE);
10417 /* we did not allocate which means left
10418 already in a pointer register, then
10419 if size > 0 && this could be used again
10420 we have to point it back to where it
10422 if (AOP_SIZE (result) > 1 &&
10423 !OP_SYMBOL (left)->remat &&
10424 (OP_SYMBOL (left)->liveTo > ic->seq ||
10428 int size = AOP_SIZE (result) - 1;
10430 emitcode ("dec", "%s", rname);
10435 freeAsmop (result, NULL, ic, TRUE);
10436 if (pi) pi->generated = 1;
10439 /*-----------------------------------------------------------------*/
10440 /* genPagedPointerGet - emitcode for paged pointer fetch */
10441 /*-----------------------------------------------------------------*/
10443 genPagedPointerGet (operand * left,
10451 sym_link *rtype, *retype, *letype;
10453 rtype = operandType (result);
10454 retype = getSpec (rtype);
10455 letype = getSpec (operandType (left));
10456 aopOp (left, ic, FALSE, FALSE);
10458 /* if the value is already in a pointer register
10459 then don't need anything more */
10460 if (!AOP_INPREG (AOP (left)))
10462 /* otherwise get a free pointer register */
10463 aop = newAsmop (0);
10464 preg = getFreePtr (ic, &aop, FALSE);
10465 emitcode ("mov", "%s,%s",
10467 aopGet (left, 0, FALSE, TRUE, NULL));
10468 rname = preg->name;
10471 rname = aopGet (left, 0, FALSE, FALSE, NULL);
10473 freeAsmop (left, NULL, ic, TRUE);
10474 aopOp (result, ic, FALSE, FALSE);
10476 /* if bitfield then unpack the bits */
10477 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10478 genUnpackBits (result, rname, PPOINTER);
10481 /* we have can just get the values */
10482 int size = AOP_SIZE (result);
10488 emitcode ("movx", "a,@%s", rname);
10489 aopPut (result, "a", offset);
10494 emitcode ("inc", "%s", rname);
10498 /* now some housekeeping stuff */
10499 if (aop) /* we had to allocate for this iCode */
10501 if (pi) aopPut (left, rname, 0);
10502 freeAsmop (NULL, aop, ic, TRUE);
10506 /* we did not allocate which means left
10507 already in a pointer register, then
10508 if size > 0 && this could be used again
10509 we have to point it back to where it
10511 if (AOP_SIZE (result) > 1 &&
10512 !OP_SYMBOL (left)->remat &&
10513 (OP_SYMBOL (left)->liveTo > ic->seq ||
10517 int size = AOP_SIZE (result) - 1;
10519 emitcode ("dec", "%s", rname);
10524 freeAsmop (result, NULL, ic, TRUE);
10525 if (pi) pi->generated = 1;
10528 /*-----------------------------------------------------------------*/
10529 /* genFarPointerGet - get value from far space */
10530 /*-----------------------------------------------------------------*/
10532 genFarPointerGet (operand * left,
10533 operand * result, iCode * ic, iCode *pi)
10535 int size, offset, dopi=1;
10536 sym_link *retype = getSpec (operandType (result));
10537 sym_link *letype = getSpec (operandType (left));
10538 D (emitcode (";", "genFarPointerGet"););
10540 aopOp (left, ic, FALSE, FALSE);
10542 /* if the operand is already in dptr
10543 then we do nothing else we move the value to dptr */
10544 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
10546 /* if this is rematerializable */
10547 if (AOP_TYPE (left) == AOP_IMMD)
10549 emitcode ("mov", "dptr,%s", aopGet (left, 0, TRUE, FALSE, NULL));
10553 /* we need to get it byte by byte */
10554 _startLazyDPSEvaluation ();
10555 if (AOP_TYPE (left) != AOP_DPTR)
10557 emitcode ("mov", "dpl,%s", aopGet (left, 0, FALSE, FALSE, NULL));
10558 emitcode ("mov", "dph,%s", aopGet (left, 1, FALSE, FALSE, NULL));
10559 if (options.model == MODEL_FLAT24)
10560 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10564 /* We need to generate a load to DPTR indirect through DPTR. */
10565 D (emitcode (";", "genFarPointerGet -- indirection special case."););
10566 emitcode ("push", "%s", aopGet (left, 0, FALSE, TRUE, NULL));
10567 emitcode ("push", "%s", aopGet (left, 1, FALSE, TRUE, NULL));
10568 if (options.model == MODEL_FLAT24)
10569 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10570 emitcode ("pop", "dph");
10571 emitcode ("pop", "dpl");
10574 _endLazyDPSEvaluation ();
10577 /* so dptr know contains the address */
10578 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10580 /* if bit then unpack */
10581 if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
10582 if (AOP_INDPTRn(left)) {
10583 genSetDPTR(AOP(left)->aopu.dptr);
10585 genUnpackBits (result, "dptr", FPOINTER);
10586 if (AOP_INDPTRn(left)) {
10591 size = AOP_SIZE (result);
10594 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10596 genSetDPTR(AOP(left)->aopu.dptr);
10597 emitcode ("movx", "a,@dptr");
10598 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10599 emitcode ("inc", "dptr");
10601 aopPut (result, "a", offset++);
10604 _startLazyDPSEvaluation ();
10606 if (AOP_INDPTRn(left)) {
10607 genSetDPTR(AOP(left)->aopu.dptr);
10613 emitcode ("movx", "a,@dptr");
10614 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10615 emitcode ("inc", "dptr");
10617 aopPut (result, "a", offset++);
10619 _endLazyDPSEvaluation ();
10622 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10623 if (!AOP_INDPTRn(left)) {
10624 _startLazyDPSEvaluation ();
10625 aopPut (left, "dpl", 0);
10626 aopPut (left, "dph", 1);
10627 if (options.model == MODEL_FLAT24)
10628 aopPut (left, "dpx", 2);
10629 _endLazyDPSEvaluation ();
10632 } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) &&
10633 AOP_SIZE(result) > 1 &&
10635 (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
10637 size = AOP_SIZE (result) - 1;
10638 if (AOP_INDPTRn(left)) {
10639 genSetDPTR(AOP(left)->aopu.dptr);
10641 while (size--) emitcode ("lcall","__decdptr");
10642 if (AOP_INDPTRn(left)) {
10647 freeAsmop (left, NULL, ic, TRUE);
10648 freeAsmop (result, NULL, ic, TRUE);
10651 /*-----------------------------------------------------------------*/
10652 /* genCodePointerGet - get value from code space */
10653 /*-----------------------------------------------------------------*/
10655 genCodePointerGet (operand * left,
10656 operand * result, iCode * ic, iCode *pi)
10658 int size, offset, dopi=1;
10659 sym_link *retype = getSpec (operandType (result));
10661 aopOp (left, ic, FALSE, FALSE);
10663 /* if the operand is already in dptr
10664 then we do nothing else we move the value to dptr */
10665 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
10667 /* if this is rematerializable */
10668 if (AOP_TYPE (left) == AOP_IMMD)
10670 emitcode ("mov", "dptr,%s", aopGet (left, 0, TRUE, FALSE, NULL));
10673 { /* we need to get it byte by byte */
10674 _startLazyDPSEvaluation ();
10675 if (AOP_TYPE (left) != AOP_DPTR)
10677 emitcode ("mov", "dpl,%s", aopGet (left, 0, FALSE, FALSE, NULL));
10678 emitcode ("mov", "dph,%s", aopGet (left, 1, FALSE, FALSE, NULL));
10679 if (options.model == MODEL_FLAT24)
10680 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10684 /* We need to generate a load to DPTR indirect through DPTR. */
10685 D (emitcode (";", "gencodePointerGet -- indirection special case."););
10686 emitcode ("push", "%s", aopGet (left, 0, FALSE, TRUE, NULL));
10687 emitcode ("push", "%s", aopGet (left, 1, FALSE, TRUE, NULL));
10688 if (options.model == MODEL_FLAT24)
10689 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
10690 emitcode ("pop", "dph");
10691 emitcode ("pop", "dpl");
10694 _endLazyDPSEvaluation ();
10697 /* so dptr know contains the address */
10698 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
10700 /* if bit then unpack */
10701 if (IS_BITFIELD (retype)) {
10702 if (AOP_INDPTRn(left)) {
10703 genSetDPTR(AOP(left)->aopu.dptr);
10705 genUnpackBits (result, "dptr", CPOINTER);
10706 if (AOP_INDPTRn(left)) {
10711 size = AOP_SIZE (result);
10713 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
10715 genSetDPTR(AOP(left)->aopu.dptr);
10716 emitcode ("clr", "a");
10717 emitcode ("movc", "a,@a+dptr");
10718 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10719 emitcode ("inc", "dptr");
10721 aopPut (result, "a", offset++);
10724 _startLazyDPSEvaluation ();
10727 if (AOP_INDPTRn(left)) {
10728 genSetDPTR(AOP(left)->aopu.dptr);
10734 emitcode ("clr", "a");
10735 emitcode ("movc", "a,@a+dptr");
10736 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
10737 emitcode ("inc", "dptr");
10738 aopPut (result, "a", offset++);
10740 _endLazyDPSEvaluation ();
10743 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
10744 if (!AOP_INDPTRn(left)) {
10745 _startLazyDPSEvaluation ();
10747 aopPut (left, "dpl", 0);
10748 aopPut (left, "dph", 1);
10749 if (options.model == MODEL_FLAT24)
10750 aopPut (left, "dpx", 2);
10752 _endLazyDPSEvaluation ();
10755 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
10756 AOP_SIZE(result) > 1 &&
10757 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10759 size = AOP_SIZE (result) - 1;
10760 if (AOP_INDPTRn(left)) {
10761 genSetDPTR(AOP(left)->aopu.dptr);
10763 while (size--) emitcode ("lcall","__decdptr");
10764 if (AOP_INDPTRn(left)) {
10769 freeAsmop (result, NULL, ic, TRUE);
10770 freeAsmop (left, NULL, ic, TRUE);
10773 /*-----------------------------------------------------------------*/
10774 /* genGenPointerGet - gget value from generic pointer space */
10775 /*-----------------------------------------------------------------*/
10777 genGenPointerGet (operand * left,
10778 operand * result, iCode * ic, iCode * pi)
10782 sym_link *retype = getSpec (operandType (result));
10783 sym_link *letype = getSpec (operandType (left));
10785 D (emitcode (";", "genGenPointerGet"));
10787 aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
10789 pushedB = pushB ();
10790 /* if the operand is already in dptr
10791 then we do nothing else we move the value to dptr */
10792 if (AOP_TYPE (left) != AOP_STR)
10794 /* if this is rematerializable */
10795 if (AOP_TYPE (left) == AOP_IMMD)
10797 emitcode ("mov", "dptr,%s", aopGet (left, 0, TRUE, FALSE, NULL));
10798 if (AOP(left)->aopu.aop_immd.from_cast_remat)
10800 MOVB (aopGet (left, AOP_SIZE(left)-1, FALSE, FALSE, NULL));
10804 emitcode ("mov", "b,#%d", pointerCode (retype));
10808 { /* we need to get it byte by byte */
10809 _startLazyDPSEvaluation ();
10810 emitcode ("mov", "dpl,%s", aopGet (left,0,FALSE,FALSE,NULL));
10811 emitcode ("mov", "dph,%s", aopGet (left,1,FALSE,FALSE,NULL));
10812 if (options.model == MODEL_FLAT24) {
10813 emitcode ("mov", "dpx,%s", aopGet (left,2,FALSE,FALSE,NULL));
10814 emitcode ("mov", "b,%s", aopGet (left,3,FALSE,FALSE,NULL));
10816 emitcode ("mov", "b,%s", aopGet (left,2,FALSE,FALSE,NULL));
10818 _endLazyDPSEvaluation ();
10822 /* so dptr-b now contains the address */
10823 aopOp (result, ic, FALSE, TRUE);
10825 /* if bit then unpack */
10826 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10828 genUnpackBits (result, "dptr", GPOINTER);
10832 size = AOP_SIZE (result);
10839 // Get two bytes at a time, results in _AP & A.
10840 // dptr will be incremented ONCE by __gptrgetWord.
10842 // Note: any change here must be coordinated
10843 // with the implementation of __gptrgetWord
10844 // in device/lib/_gptrget.c
10845 emitcode ("lcall", "__gptrgetWord");
10846 aopPut (result, DP2_RESULT_REG, offset++);
10847 aopPut (result, "a", offset++);
10852 // Only one byte to get.
10853 emitcode ("lcall", "__gptrget");
10854 aopPut (result, "a", offset++);
10857 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
10859 emitcode ("inc", "dptr");
10864 if (pi && AOP_TYPE (left) != AOP_IMMD) {
10865 _startLazyDPSEvaluation ();
10867 aopPut (left, "dpl", 0);
10868 aopPut (left, "dph", 1);
10869 if (options.model == MODEL_FLAT24) {
10870 aopPut (left, "dpx", 2);
10871 aopPut (left, "b", 3);
10872 } else aopPut (left, "b", 2);
10874 _endLazyDPSEvaluation ();
10877 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
10878 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
10880 size = AOP_SIZE (result) - 1;
10881 while (size--) emitcode ("lcall","__decdptr");
10885 freeAsmop (result, NULL, ic, TRUE);
10886 freeAsmop (left, NULL, ic, TRUE);
10889 /*-----------------------------------------------------------------*/
10890 /* genPointerGet - generate code for pointer get */
10891 /*-----------------------------------------------------------------*/
10893 genPointerGet (iCode * ic, iCode *pi)
10895 operand *left, *result;
10896 sym_link *type, *etype;
10899 D (emitcode (";", "genPointerGet "));
10901 left = IC_LEFT (ic);
10902 result = IC_RESULT (ic);
10904 /* depending on the type of pointer we need to
10905 move it to the correct pointer register */
10906 type = operandType (left);
10907 etype = getSpec (type);
10908 /* if left is of type of pointer then it is simple */
10909 if (IS_PTR (type) && !IS_FUNC (type->next))
10910 p_type = DCL_TYPE (type);
10913 /* we have to go by the storage class */
10914 p_type = PTR_TYPE (SPEC_OCLS (etype));
10917 /* special case when cast remat */
10918 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10919 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10921 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10922 type = operandType (left);
10923 p_type = DCL_TYPE (type);
10925 /* now that we have the pointer type we assign
10926 the pointer values */
10932 genNearPointerGet (left, result, ic, pi);
10936 genPagedPointerGet (left, result, ic, pi);
10940 genFarPointerGet (left, result, ic, pi);
10944 genCodePointerGet (left, result, ic, pi);
10948 genGenPointerGet (left, result, ic, pi);
10953 /*-----------------------------------------------------------------*/
10954 /* genPackBits - generates code for packed bit storage */
10955 /*-----------------------------------------------------------------*/
10957 genPackBits (sym_link * etype,
10959 char *rname, int p_type)
10961 int offset = 0; /* source byte offset */
10962 int rlen = 0; /* remaining bitfield length */
10963 int blen; /* bitfield length */
10964 int bstr; /* bitfield starting bit within byte */
10965 int litval; /* source literal value (if AOP_LIT) */
10966 unsigned char mask; /* bitmask within current byte */
10968 D(emitcode ("; genPackBits",""));
10970 blen = SPEC_BLEN (etype);
10971 bstr = SPEC_BSTR (etype);
10973 /* If the bitfield length is less than a byte */
10976 mask = ((unsigned char) (0xFF << (blen + bstr)) |
10977 (unsigned char) (0xFF >> (8 - bstr)));
10979 if (AOP_TYPE (right) == AOP_LIT)
10981 /* Case with a bitfield length <8 and literal source
10983 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10985 litval &= (~mask) & 0xff;
10986 emitPtrByteGet (rname, p_type, FALSE);
10987 if ((mask|litval)!=0xff)
10988 emitcode ("anl","a,#!constbyte", mask);
10990 emitcode ("orl","a,#!constbyte", litval);
10994 if ((blen==1) && (p_type!=GPOINTER))
10996 /* Case with a bitfield length == 1 and no generic pointer
10998 if (AOP_TYPE (right) == AOP_CRY)
10999 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
11002 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
11003 emitcode ("rrc","a");
11005 emitPtrByteGet (rname, p_type, FALSE);
11006 emitcode ("mov","acc.%d,c",bstr);
11011 /* Case with a bitfield length < 8 and arbitrary source
11013 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
11014 /* shift and mask source value */
11016 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
11018 pushedB = pushB ();
11019 /* transfer A to B and get next byte */
11020 emitPtrByteGet (rname, p_type, TRUE);
11022 emitcode ("anl", "a,#!constbyte", mask);
11023 emitcode ("orl", "a,b");
11024 if (p_type == GPOINTER)
11025 emitcode ("pop", "b");
11031 emitPtrByteSet (rname, p_type, "a");
11035 /* Bit length is greater than 7 bits. In this case, copy */
11036 /* all except the partial byte at the end */
11037 for (rlen=blen;rlen>=8;rlen-=8)
11039 emitPtrByteSet (rname, p_type,
11040 aopGet (right, offset++, FALSE, TRUE, NULL) );
11042 emitcode ("inc", "%s", rname);
11045 /* If there was a partial byte at the end */
11048 mask = (((unsigned char) -1 << rlen) & 0xff);
11050 if (AOP_TYPE (right) == AOP_LIT)
11052 /* Case with partial byte and literal source
11054 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
11055 litval >>= (blen-rlen);
11056 litval &= (~mask) & 0xff;
11057 emitPtrByteGet (rname, p_type, FALSE);
11058 if ((mask|litval)!=0xff)
11059 emitcode ("anl","a,#!constbyte", mask);
11061 emitcode ("orl","a,#!constbyte", litval);
11066 /* Case with partial byte and arbitrary source
11068 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11069 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
11071 pushedB = pushB ();
11072 /* transfer A to B and get next byte */
11073 emitPtrByteGet (rname, p_type, TRUE);
11075 emitcode ("anl", "a,#!constbyte", mask);
11076 emitcode ("orl", "a,b");
11077 if (p_type == GPOINTER)
11078 emitcode ("pop", "b");
11082 emitPtrByteSet (rname, p_type, "a");
11087 /*-----------------------------------------------------------------*/
11088 /* genDataPointerSet - remat pointer to data space */
11089 /*-----------------------------------------------------------------*/
11091 genDataPointerSet (operand * right,
11095 int size, offset = 0;
11096 char *l, buffer[256];
11098 D (emitcode (";", "genDataPointerSet"));
11100 aopOp (right, ic, FALSE, FALSE);
11102 l = aopGet (result, 0, FALSE, TRUE, NULL);
11103 size = AOP_SIZE (right);
11107 SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l + 1, offset);
11109 SNPRINTF (buffer, sizeof(buffer), "%s", l + 1);
11110 emitcode ("mov", "%s,%s", buffer,
11111 aopGet (right, offset++, FALSE, FALSE, NULL));
11114 freeAsmop (result, NULL, ic, TRUE);
11115 freeAsmop (right, NULL, ic, TRUE);
11118 /*-----------------------------------------------------------------*/
11119 /* genNearPointerSet - emitcode for near pointer put */
11120 /*-----------------------------------------------------------------*/
11122 genNearPointerSet (operand * right,
11129 sym_link *retype, *letype;
11130 sym_link *ptype = operandType (result);
11132 D(emitcode (";", "genNearPointerSet"));
11134 retype = getSpec (operandType (right));
11135 letype = getSpec (ptype);
11137 aopOp (result, ic, FALSE, FALSE);
11139 /* if the result is rematerializable &
11140 in data space & not a bit variable */
11141 if (AOP_TYPE (result) == AOP_IMMD &&
11142 DCL_TYPE (ptype) == POINTER &&
11143 !IS_BITVAR (retype) &&
11144 !IS_BITVAR (letype))
11146 genDataPointerSet (right, result, ic);
11150 /* if the value is already in a pointer register
11151 then don't need anything more */
11152 if (!AOP_INPREG (AOP (result)))
11154 /* otherwise get a free pointer register */
11157 aop = newAsmop (0);
11158 preg = getFreePtr (ic, &aop, FALSE);
11159 emitcode ("mov", "%s,%s",
11161 aopGet (result, 0, FALSE, TRUE, NULL));
11162 rname = preg->name;
11166 rname = aopGet (result, 0, FALSE, FALSE, NULL);
11169 aopOp (right, ic, FALSE, FALSE);
11171 /* if bitfield then unpack the bits */
11172 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11173 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
11176 /* we have can just get the values */
11177 int size = AOP_SIZE (right);
11182 l = aopGet (right, offset, FALSE, TRUE, NULL);
11186 emitcode ("mov", "@%s,a", rname);
11189 emitcode ("mov", "@%s,%s", rname, l);
11191 emitcode ("inc", "%s", rname);
11196 /* now some housekeeping stuff */
11197 if (aop) /* we had to allocate for this iCode */
11199 if (pi) aopPut (result,rname,0);
11200 freeAsmop (NULL, aop, ic, TRUE);
11204 /* we did not allocate which means left
11205 already in a pointer register, then
11206 if size > 0 && this could be used again
11207 we have to point it back to where it
11209 if (AOP_SIZE (right) > 1 &&
11210 !OP_SYMBOL (result)->remat &&
11211 (OP_SYMBOL (result)->liveTo > ic->seq ||
11215 int size = AOP_SIZE (right) - 1;
11217 emitcode ("dec", "%s", rname);
11222 if (pi) pi->generated = 1;
11223 freeAsmop (result, NULL, ic, TRUE);
11224 freeAsmop (right, NULL, ic, TRUE);
11227 /*-----------------------------------------------------------------*/
11228 /* genPagedPointerSet - emitcode for Paged pointer put */
11229 /*-----------------------------------------------------------------*/
11231 genPagedPointerSet (operand * right,
11238 sym_link *retype, *letype;
11240 D (emitcode (";", "genPagedPointerSet"));
11242 retype = getSpec (operandType (right));
11243 letype = getSpec (operandType (result));
11245 aopOp (result, ic, FALSE, FALSE);
11247 /* if the value is already in a pointer register
11248 then don't need anything more */
11249 if (!AOP_INPREG (AOP (result)))
11251 /* otherwise get a free pointer register */
11254 aop = newAsmop (0);
11255 preg = getFreePtr (ic, &aop, FALSE);
11256 emitcode ("mov", "%s,%s",
11258 aopGet (result, 0, FALSE, TRUE, NULL));
11259 rname = preg->name;
11262 rname = aopGet (result, 0, FALSE, FALSE, NULL);
11264 aopOp (right, ic, FALSE, FALSE);
11266 /* if bitfield then unpack the bits */
11267 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11268 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
11271 /* we have can just get the values */
11272 int size = AOP_SIZE (right);
11277 l = aopGet (right, offset, FALSE, TRUE, NULL);
11279 emitcode ("movx", "@%s,a", rname);
11282 emitcode ("inc", "%s", rname);
11288 /* now some housekeeping stuff */
11292 aopPut (result, rname, 0);
11293 /* we had to allocate for this iCode */
11294 freeAsmop (NULL, aop, ic, TRUE);
11298 /* we did not allocate which means left
11299 already in a pointer register, then
11300 if size > 0 && this could be used again
11301 we have to point it back to where it
11303 if (AOP_SIZE (right) > 1 &&
11304 !OP_SYMBOL (result)->remat &&
11305 (OP_SYMBOL (result)->liveTo > ic->seq ||
11309 int size = AOP_SIZE (right) - 1;
11311 emitcode ("dec", "%s", rname);
11316 if (pi) pi->generated = 1;
11317 freeAsmop (result, NULL, ic, TRUE);
11318 freeAsmop (right, NULL, ic, TRUE);
11321 /*-----------------------------------------------------------------*/
11322 /* genFarPointerSet - set value from far space */
11323 /*-----------------------------------------------------------------*/
11325 genFarPointerSet (operand * right,
11326 operand * result, iCode * ic, iCode *pi)
11328 int size, offset, dopi=1;
11329 sym_link *retype = getSpec (operandType (right));
11330 sym_link *letype = getSpec (operandType (result));
11332 aopOp (result, ic, FALSE, FALSE);
11334 /* if the operand is already in dptr
11335 then we do nothing else we move the value to dptr */
11336 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
11338 /* if this is remateriazable */
11339 if (AOP_TYPE (result) == AOP_IMMD)
11340 emitcode ("mov", "dptr,%s",
11341 aopGet (result, 0, TRUE, FALSE, NULL));
11344 /* we need to get it byte by byte */
11345 _startLazyDPSEvaluation ();
11346 if (AOP_TYPE (result) != AOP_DPTR)
11348 emitcode ("mov", "dpl,%s", aopGet (result, 0, FALSE, FALSE, NULL));
11349 emitcode ("mov", "dph,%s", aopGet (result, 1, FALSE, FALSE, NULL));
11350 if (options.model == MODEL_FLAT24)
11351 emitcode ("mov", "dpx,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11355 /* We need to generate a load to DPTR indirect through DPTR. */
11356 D (emitcode (";", "genFarPointerSet -- indirection special case."););
11358 emitcode ("push", "%s", aopGet (result, 0, FALSE, TRUE, NULL));
11359 emitcode ("push", "%s", aopGet (result, 1, FALSE, TRUE, NULL));
11360 if (options.model == MODEL_FLAT24)
11361 emitcode ("mov", "dpx,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11362 emitcode ("pop", "dph");
11363 emitcode ("pop", "dpl");
11366 _endLazyDPSEvaluation ();
11369 /* so dptr know contains the address */
11370 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
11372 /* if bit then unpack */
11373 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11375 if (AOP_INDPTRn(result)) {
11376 genSetDPTR(AOP(result)->aopu.dptr);
11378 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
11379 if (AOP_INDPTRn(result)) {
11383 size = AOP_SIZE (right);
11385 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
11387 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11389 genSetDPTR(AOP(result)->aopu.dptr);
11390 emitcode ("movx", "@dptr,a");
11391 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
11392 emitcode ("inc", "dptr");
11396 _startLazyDPSEvaluation ();
11398 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11400 if (AOP_INDPTRn(result)) {
11401 genSetDPTR(AOP(result)->aopu.dptr);
11407 emitcode ("movx", "@dptr,a");
11408 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
11409 emitcode ("inc", "dptr");
11411 _endLazyDPSEvaluation ();
11415 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
11416 if (!AOP_INDPTRn(result)) {
11417 _startLazyDPSEvaluation ();
11419 aopPut (result,"dpl",0);
11420 aopPut (result,"dph",1);
11421 if (options.model == MODEL_FLAT24)
11422 aopPut (result,"dpx",2);
11424 _endLazyDPSEvaluation ();
11427 } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
11428 AOP_SIZE(right) > 1 &&
11429 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
11431 size = AOP_SIZE (right) - 1;
11432 if (AOP_INDPTRn(result)) {
11433 genSetDPTR(AOP(result)->aopu.dptr);
11435 while (size--) emitcode ("lcall","__decdptr");
11436 if (AOP_INDPTRn(result)) {
11440 freeAsmop (result, NULL, ic, TRUE);
11441 freeAsmop (right, NULL, ic, TRUE);
11444 /*-----------------------------------------------------------------*/
11445 /* genGenPointerSet - set value from generic pointer space */
11446 /*-----------------------------------------------------------------*/
11448 genGenPointerSet (operand * right,
11449 operand * result, iCode * ic, iCode *pi)
11453 sym_link *retype = getSpec (operandType (right));
11454 sym_link *letype = getSpec (operandType (result));
11456 aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
11458 pushedB = pushB ();
11459 /* if the operand is already in dptr
11460 then we do nothing else we move the value to dptr */
11461 if (AOP_TYPE (result) != AOP_STR)
11463 _startLazyDPSEvaluation ();
11464 /* if this is remateriazable */
11465 if (AOP_TYPE (result) == AOP_IMMD)
11467 emitcode ("mov", "dptr,%s", aopGet (result, 0, TRUE, FALSE, NULL));
11468 if (AOP(result)->aopu.aop_immd.from_cast_remat)
11470 MOVB (aopGet (result, AOP_SIZE(result)-1, FALSE, FALSE, NULL));
11475 "b,%s + 1", aopGet (result, 0, TRUE, FALSE, NULL));
11479 { /* we need to get it byte by byte */
11480 emitcode ("mov", "dpl,%s", aopGet (result, 0, FALSE, FALSE, NULL));
11481 emitcode ("mov", "dph,%s", aopGet (result, 1, FALSE, FALSE, NULL));
11482 if (options.model == MODEL_FLAT24) {
11483 emitcode ("mov", "dpx,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11484 emitcode ("mov", "b,%s", aopGet (result, 3, FALSE, FALSE, NULL));
11486 emitcode ("mov", "b,%s", aopGet (result, 2, FALSE, FALSE, NULL));
11489 _endLazyDPSEvaluation ();
11491 /* so dptr + b now contains the address */
11492 aopOp (right, ic, FALSE, TRUE);
11494 /* if bit then unpack */
11495 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
11497 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
11501 size = AOP_SIZE (right);
11504 _startLazyDPSEvaluation ();
11509 // Set two bytes at a time, passed in _AP & A.
11510 // dptr will be incremented ONCE by __gptrputWord.
11512 // Note: any change here must be coordinated
11513 // with the implementation of __gptrputWord
11514 // in device/lib/_gptrput.c
11515 emitcode("mov", "_ap, %s",
11516 aopGet (right, offset++, FALSE, FALSE, NULL));
11517 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11521 emitcode ("lcall", "__gptrputWord");
11526 // Only one byte to put.
11527 MOVA (aopGet (right, offset++, FALSE, FALSE, NULL));
11531 emitcode ("lcall", "__gptrput");
11534 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
11536 emitcode ("inc", "dptr");
11539 _endLazyDPSEvaluation ();
11542 if (pi && AOP_TYPE (result) != AOP_IMMD) {
11543 _startLazyDPSEvaluation ();
11545 aopPut (result, "dpl",0);
11546 aopPut (result, "dph",1);
11547 if (options.model == MODEL_FLAT24) {
11548 aopPut (result, "dpx",2);
11549 aopPut (result, "b",3);
11551 aopPut (result, "b",2);
11553 _endLazyDPSEvaluation ();
11556 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
11557 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
11559 size = AOP_SIZE (right) - 1;
11560 while (size--) emitcode ("lcall","__decdptr");
11564 freeAsmop (result, NULL, ic, TRUE);
11565 freeAsmop (right, NULL, ic, TRUE);
11568 /*-----------------------------------------------------------------*/
11569 /* genPointerSet - stores the value into a pointer location */
11570 /*-----------------------------------------------------------------*/
11572 genPointerSet (iCode * ic, iCode *pi)
11574 operand *right, *result;
11575 sym_link *type, *etype;
11578 D (emitcode (";", "genPointerSet"));
11580 right = IC_RIGHT (ic);
11581 result = IC_RESULT (ic);
11583 /* depending on the type of pointer we need to
11584 move it to the correct pointer register */
11585 type = operandType (result);
11586 etype = getSpec (type);
11587 /* if left is of type of pointer then it is simple */
11588 if (IS_PTR (type) && !IS_FUNC (type->next))
11590 p_type = DCL_TYPE (type);
11594 /* we have to go by the storage class */
11595 p_type = PTR_TYPE (SPEC_OCLS (etype));
11598 /* special case when cast remat */
11599 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
11600 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
11601 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
11602 type = operandType (result);
11603 p_type = DCL_TYPE (type);
11606 /* now that we have the pointer type we assign
11607 the pointer values */
11613 genNearPointerSet (right, result, ic, pi);
11617 genPagedPointerSet (right, result, ic, pi);
11621 genFarPointerSet (right, result, ic, pi);
11625 genGenPointerSet (right, result, ic, pi);
11629 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11630 "genPointerSet: illegal pointer type");
11634 /*-----------------------------------------------------------------*/
11635 /* genIfx - generate code for Ifx statement */
11636 /*-----------------------------------------------------------------*/
11638 genIfx (iCode * ic, iCode * popIc)
11640 operand *cond = IC_COND (ic);
11644 D (emitcode (";", "genIfx "));
11646 aopOp (cond, ic, FALSE, FALSE);
11648 /* get the value into acc */
11649 if (AOP_TYPE (cond) != AOP_CRY)
11656 if (AOP(cond)->aopu.aop_dir)
11657 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
11660 /* the result is now in the accumulator or a directly addressable bit */
11661 freeAsmop (cond, NULL, ic, TRUE);
11663 /* if there was something to be popped then do it */
11667 /* if the condition is a bit variable */
11670 genIfxJump (ic, dup);
11672 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
11674 genIfxJump (ic, SPIL_LOC (cond)->rname);
11676 else if (isbit && !IS_ITEMP (cond))
11678 genIfxJump (ic, OP_SYMBOL (cond)->rname);
11682 genIfxJump (ic, "a");
11688 /*-----------------------------------------------------------------*/
11689 /* genAddrOf - generates code for address of */
11690 /*-----------------------------------------------------------------*/
11692 genAddrOf (iCode * ic)
11694 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
11697 D (emitcode (";", "genAddrOf"));
11699 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11701 /* if the operand is on the stack then we
11702 need to get the stack offset of this
11707 /* if 10 bit stack */
11708 if (options.stack10bit) {
11712 tsprintf(buff, sizeof(buff),
11713 "#!constbyte",(options.stack_loc >> 16) & 0xff);
11714 /* if it has an offset then we need to compute it */
11715 /* emitcode ("subb", "a,#!constbyte", */
11716 /* -((sym->stack < 0) ? */
11717 /* ((short) (sym->stack - _G.nRegsSaved)) : */
11718 /* ((short) sym->stack)) & 0xff); */
11719 /* emitcode ("mov","b,a"); */
11720 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
11721 /* ((short) (sym->stack - _G.nRegsSaved)) : */
11722 /* ((short) sym->stack)) >> 8) & 0xff); */
11724 emitcode ("mov", "a,_bpx");
11725 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
11726 ((char) (sym->stack - _G.nRegsSaved)) :
11727 ((char) sym->stack )) & 0xff);
11728 emitcode ("mov", "b,a");
11729 emitcode ("mov", "a,_bpx+1");
11731 offset = (((sym->stack < 0) ?
11732 ((short) (sym->stack - _G.nRegsSaved)) :
11733 ((short) sym->stack )) >> 8) & 0xff;
11735 emitcode ("addc","a,#!constbyte", offset);
11737 aopPut (IC_RESULT (ic), "b", 0);
11738 aopPut (IC_RESULT (ic), "a", 1);
11739 aopPut (IC_RESULT (ic), buff, 2);
11741 /* we can just move _bp */
11742 aopPut (IC_RESULT (ic), "_bpx", 0);
11743 aopPut (IC_RESULT (ic), "_bpx+1", 1);
11744 aopPut (IC_RESULT (ic), buff, 2);
11747 /* if it has an offset then we need to compute it */
11750 emitcode ("mov", "a,_bp");
11751 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
11752 aopPut (IC_RESULT (ic), "a", 0);
11756 /* we can just move _bp */
11757 aopPut (IC_RESULT (ic), "_bp", 0);
11759 /* fill the result with zero */
11760 size = AOP_SIZE (IC_RESULT (ic)) - 1;
11763 if (options.stack10bit && size < (FPTRSIZE - 1)) {
11765 "*** warning: pointer to stack var truncated.\n");
11771 aopPut (IC_RESULT (ic), zero, offset++);
11777 /* object not on stack then we need the name */
11778 size = AOP_SIZE (IC_RESULT (ic));
11783 char s[SDCC_NAME_MAX];
11787 tsprintf(s, sizeof(s), "#!his",sym->rname);
11790 tsprintf(s, sizeof(s), "#!hihis",sym->rname);
11793 tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
11795 default: /* should not need this (just in case) */
11796 SNPRINTF (s, sizeof(s), "#(%s >> %d)",
11803 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11806 aopPut (IC_RESULT (ic), s, offset++);
11810 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11814 #if 0 // obsolete, and buggy for != xdata
11815 /*-----------------------------------------------------------------*/
11816 /* genArrayInit - generates code for address of */
11817 /*-----------------------------------------------------------------*/
11819 genArrayInit (iCode * ic)
11821 literalList *iLoop;
11823 int elementSize = 0, eIndex;
11824 unsigned val, lastVal;
11826 operand *left=IC_LEFT(ic);
11828 D (emitcode (";", "genArrayInit "););
11830 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
11832 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
11834 // Load immediate value into DPTR.
11835 emitcode("mov", "dptr, %s",
11836 aopGet (IC_LEFT(ic), 0, TRUE, FALSE, NULL));
11838 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
11841 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11842 "Unexpected operand to genArrayInit.\n");
11845 // a regression because of SDCCcse.c:1.52
11846 emitcode ("mov", "dpl,%s", aopGet (left, 0, FALSE, FALSE, NULL));
11847 emitcode ("mov", "dph,%s", aopGet (left, 1, FALSE, FALSE, NULL));
11848 if (options.model == MODEL_FLAT24)
11849 emitcode ("mov", "dpx,%s", aopGet (left, 2, FALSE, FALSE, NULL));
11853 type = operandType(IC_LEFT(ic));
11855 if (type && type->next)
11857 elementSize = getSize(type->next);
11861 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11862 "can't determine element size in genArrayInit.\n");
11866 iLoop = IC_ARRAYILIST(ic);
11871 bool firstpass = TRUE;
11873 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
11874 iLoop->count, (int)iLoop->literalValue, elementSize);
11880 symbol *tlbl = NULL;
11882 count = ix > 256 ? 256 : ix;
11886 tlbl = newiTempLabel (NULL);
11887 if (firstpass || (count & 0xff))
11889 emitcode("mov", "b, #!constbyte", count & 0xff);
11892 emitcode ("", "!tlabeldef", tlbl->key + 100);
11897 for (eIndex = 0; eIndex < elementSize; eIndex++)
11899 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
11900 if (val != lastVal)
11902 emitcode("mov", "a, #!constbyte", val);
11906 emitcode("movx", "@dptr, a");
11907 emitcode("inc", "dptr");
11912 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
11918 iLoop = iLoop->next;
11921 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
11925 /*-----------------------------------------------------------------*/
11926 /* genFarFarAssign - assignment when both are in far space */
11927 /*-----------------------------------------------------------------*/
11929 genFarFarAssign (operand * result, operand * right, iCode * ic)
11931 int size = AOP_SIZE (right);
11933 symbol *rSym = NULL;
11937 /* quick & easy case. */
11938 D(emitcode(";","genFarFarAssign (1 byte case)"););
11939 MOVA (aopGet (right, 0, FALSE, FALSE, NULL));
11940 freeAsmop (right, NULL, ic, FALSE);
11941 /* now assign DPTR to result */
11943 aopOp(result, ic, FALSE, FALSE);
11945 aopPut (result, "a", 0);
11946 freeAsmop(result, NULL, ic, FALSE);
11950 /* See if we've got an underlying symbol to abuse. */
11951 if (IS_SYMOP(result) && OP_SYMBOL(result))
11953 if (IS_TRUE_SYMOP(result))
11955 rSym = OP_SYMBOL(result);
11957 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
11959 rSym = OP_SYMBOL(result)->usl.spillLoc;
11963 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
11965 /* We can use the '390 auto-toggle feature to good effect here. */
11967 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
11968 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11969 emitcode ("mov", "dptr,#%s", rSym->rname);
11970 /* DP2 = result, DP1 = right, DP1 is current. */
11973 emitcode("movx", "a,@dptr");
11974 emitcode("movx", "@dptr,a");
11977 emitcode("inc", "dptr");
11978 emitcode("inc", "dptr");
11981 emitcode("mov", "dps,#0");
11982 freeAsmop (right, NULL, ic, FALSE);
11984 some alternative code for processors without auto-toggle
11985 no time to test now, so later well put in...kpb
11986 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
11987 emitcode("mov", "dps,#1"); /* Select DPTR2. */
11988 emitcode ("mov", "dptr,#%s", rSym->rname);
11989 /* DP2 = result, DP1 = right, DP1 is current. */
11993 emitcode("movx", "a,@dptr");
11995 emitcode("inc", "dptr");
11996 emitcode("inc", "dps");
11997 emitcode("movx", "@dptr,a");
11999 emitcode("inc", "dptr");
12000 emitcode("inc", "dps");
12002 emitcode("mov", "dps,#0");
12003 freeAsmop (right, NULL, ic, FALSE);
12008 D (emitcode (";", "genFarFarAssign"););
12009 aopOp (result, ic, TRUE, TRUE);
12011 _startLazyDPSEvaluation ();
12016 aopGet (right, offset, FALSE, FALSE, NULL), offset);
12019 _endLazyDPSEvaluation ();
12020 freeAsmop (result, NULL, ic, FALSE);
12021 freeAsmop (right, NULL, ic, FALSE);
12025 /*-----------------------------------------------------------------*/
12026 /* genAssign - generate code for assignment */
12027 /*-----------------------------------------------------------------*/
12029 genAssign (iCode * ic)
12031 operand *result, *right;
12033 unsigned long lit = 0L;
12035 D (emitcode (";", "genAssign "));
12037 result = IC_RESULT (ic);
12038 right = IC_RIGHT (ic);
12040 /* if they are the same */
12041 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
12044 aopOp (right, ic, FALSE, FALSE);
12046 emitcode (";", "genAssign: resultIsFar = %s",
12047 isOperandInFarSpace (result) ?
12050 /* special case both in far space */
12051 if ((AOP_TYPE (right) == AOP_DPTR ||
12052 AOP_TYPE (right) == AOP_DPTR2) &&
12053 /* IS_TRUE_SYMOP(result) && */
12054 isOperandInFarSpace (result))
12056 genFarFarAssign (result, right, ic);
12060 aopOp (result, ic, TRUE, FALSE);
12062 /* if they are the same registers */
12063 if (sameRegs (AOP (right), AOP (result)))
12066 /* if the result is a bit */
12067 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
12069 /* if the right size is a literal then
12070 we know what the value is */
12071 if (AOP_TYPE (right) == AOP_LIT)
12073 if (((int) operandLitValue (right)))
12074 aopPut (result, one, 0);
12076 aopPut (result, zero, 0);
12080 /* the right is also a bit variable */
12081 if (AOP_TYPE (right) == AOP_CRY)
12083 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
12084 aopPut (result, "c", 0);
12088 /* we need to or */
12090 aopPut (result, "a", 0);
12094 /* bit variables done */
12096 size = AOP_SIZE (result);
12098 if (AOP_TYPE (right) == AOP_LIT)
12099 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
12102 (AOP_TYPE (result) != AOP_REG) &&
12103 (AOP_TYPE (right) == AOP_LIT) &&
12104 !IS_FLOAT (operandType (right)))
12106 _startLazyDPSEvaluation ();
12107 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
12110 aopGet (right, offset, FALSE, FALSE, NULL),
12115 /* And now fill the rest with zeros. */
12118 emitcode ("clr", "a");
12122 aopPut (result, "a", offset++);
12124 _endLazyDPSEvaluation ();
12128 _startLazyDPSEvaluation ();
12132 aopGet (right, offset, FALSE, FALSE, NULL),
12136 _endLazyDPSEvaluation ();
12140 freeAsmop (result, NULL, ic, TRUE);
12141 freeAsmop (right, NULL, ic, TRUE);
12144 /*-----------------------------------------------------------------*/
12145 /* genJumpTab - generates code for jump table */
12146 /*-----------------------------------------------------------------*/
12148 genJumpTab (iCode * ic)
12153 D (emitcode (";", "genJumpTab ");
12156 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
12157 /* get the condition into accumulator */
12158 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE, NULL);
12160 /* multiply by four! */
12161 emitcode ("add", "a,acc");
12162 emitcode ("add", "a,acc");
12163 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
12165 jtab = newiTempLabel (NULL);
12166 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
12167 emitcode ("jmp", "@a+dptr");
12168 emitcode ("", "!tlabeldef", jtab->key + 100);
12169 /* now generate the jump labels */
12170 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
12171 jtab = setNextItem (IC_JTLABELS (ic)))
12172 emitcode ("ljmp", "!tlabel", jtab->key + 100);
12176 /*-----------------------------------------------------------------*/
12177 /* genCast - gen code for casting */
12178 /*-----------------------------------------------------------------*/
12180 genCast (iCode * ic)
12182 operand *result = IC_RESULT (ic);
12183 sym_link *ctype = operandType (IC_LEFT (ic));
12184 sym_link *rtype = operandType (IC_RIGHT (ic));
12185 operand *right = IC_RIGHT (ic);
12188 D (emitcode (";", "genCast "));
12190 /* if they are equivalent then do nothing */
12191 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
12194 aopOp (right, ic, FALSE, AOP_IS_STR (result));
12195 aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR));
12197 /* if the result is a bit */
12198 if (IS_BITVAR (OP_SYMBOL (result)->type)
12199 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
12201 /* if the right size is a literal then
12202 we know what the value is */
12203 if (AOP_TYPE (right) == AOP_LIT)
12205 if (((int) operandLitValue (right)))
12206 aopPut (result, one, 0);
12208 aopPut (result, zero, 0);
12213 /* the right is also a bit variable */
12214 if (AOP_TYPE (right) == AOP_CRY)
12216 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
12217 aopPut (result, "c", 0);
12221 /* we need to or */
12223 aopPut (result, "a", 0);
12227 /* if they are the same size : or less */
12228 if (AOP_SIZE (result) <= AOP_SIZE (right))
12231 /* if they are in the same place */
12232 if (sameRegs (AOP (right), AOP (result)))
12235 /* if they in different places then copy */
12236 size = AOP_SIZE (result);
12238 _startLazyDPSEvaluation ();
12242 aopGet (right, offset, FALSE, FALSE, NULL),
12246 _endLazyDPSEvaluation ();
12250 /* if the result is of type pointer */
12251 if (IS_PTR (ctype))
12255 sym_link *type = operandType (right);
12257 /* pointer to generic pointer */
12258 if (IS_GENPTR (ctype))
12262 p_type = DCL_TYPE (type);
12266 #if OLD_CAST_BEHAVIOR
12267 /* KV: we are converting a non-pointer type to
12268 * a generic pointer. This (ifdef'd out) code
12269 * says that the resulting generic pointer
12270 * should have the same class as the storage
12271 * location of the non-pointer variable.
12273 * For example, converting an int (which happens
12274 * to be stored in DATA space) to a pointer results
12275 * in a DATA generic pointer; if the original int
12276 * in XDATA space, so will be the resulting pointer.
12278 * I don't like that behavior, and thus this change:
12279 * all such conversions will be forced to XDATA and
12280 * throw a warning. If you want some non-XDATA
12281 * type, or you want to suppress the warning, you
12282 * must go through an intermediate cast, like so:
12284 * char _generic *gp = (char _xdata *)(intVar);
12286 sym_link *etype = getSpec (type);
12288 /* we have to go by the storage class */
12289 if (SPEC_OCLS (etype) != generic)
12291 p_type = PTR_TYPE (SPEC_OCLS (etype));
12296 /* Converting unknown class (i.e. register variable)
12297 * to generic pointer. This is not good, but
12298 * we'll make a guess (and throw a warning).
12301 werror (W_INT_TO_GEN_PTR_CAST);
12305 /* the first two bytes are known */
12306 size = GPTRSIZE - 1;
12308 _startLazyDPSEvaluation ();
12312 aopGet (right, offset, FALSE, FALSE, NULL),
12316 _endLazyDPSEvaluation ();
12318 /* the last byte depending on type */
12320 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
12325 // pointerTypeToGPByte will have bitched.
12329 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%x", gpVal);
12330 aopPut (result, gpValStr, GPTRSIZE - 1);
12335 /* just copy the pointers */
12336 size = AOP_SIZE (result);
12338 _startLazyDPSEvaluation ();
12342 aopGet (right, offset, FALSE, FALSE, NULL),
12346 _endLazyDPSEvaluation ();
12350 /* so we now know that the size of destination is greater
12351 than the size of the source */
12352 /* we move to result for the size of source */
12353 size = AOP_SIZE (right);
12355 _startLazyDPSEvaluation ();
12359 aopGet (right, offset, FALSE, FALSE, NULL),
12363 _endLazyDPSEvaluation ();
12365 /* now depending on the sign of the source && destination */
12366 size = AOP_SIZE (result) - AOP_SIZE (right);
12367 /* if unsigned or not an integral type */
12368 /* also, if the source is a bit, we don't need to sign extend, because
12369 * it can't possibly have set the sign bit.
12371 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
12375 aopPut (result, zero, offset++);
12380 /* we need to extend the sign :{ */
12381 MOVA (aopGet (right, AOP_SIZE (right) - 1,
12382 FALSE, FALSE, NULL));
12383 emitcode ("rlc", "a");
12384 emitcode ("subb", "a,acc");
12386 aopPut (result, "a", offset++);
12389 /* we are done hurray !!!! */
12392 freeAsmop (right, NULL, ic, TRUE);
12393 freeAsmop (result, NULL, ic, TRUE);
12397 /*-----------------------------------------------------------------*/
12398 /* genDjnz - generate decrement & jump if not zero instrucion */
12399 /*-----------------------------------------------------------------*/
12401 genDjnz (iCode * ic, iCode * ifx)
12403 symbol *lbl, *lbl1;
12407 /* if the if condition has a false label
12408 then we cannot save */
12409 if (IC_FALSE (ifx))
12412 /* if the minus is not of the form
12414 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
12415 !IS_OP_LITERAL (IC_RIGHT (ic)))
12418 if (operandLitValue (IC_RIGHT (ic)) != 1)
12421 /* if the size of this greater than one then no
12423 if (getSize (operandType (IC_RESULT (ic))) > 1)
12426 /* otherwise we can save BIG */
12427 D(emitcode(";", "genDjnz"););
12429 lbl = newiTempLabel (NULL);
12430 lbl1 = newiTempLabel (NULL);
12432 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
12434 if (AOP_NEEDSACC(IC_RESULT(ic)))
12436 /* If the result is accessed indirectly via
12437 * the accumulator, we must explicitly write
12438 * it back after the decrement.
12440 char *rByte = aopGet(IC_RESULT(ic), 0, FALSE, FALSE, NULL);
12442 if (strcmp(rByte, "a"))
12444 /* Something is hopelessly wrong */
12445 fprintf(stderr, "*** warning: internal error at %s:%d\n",
12446 __FILE__, __LINE__);
12447 /* We can just give up; the generated code will be inefficient,
12448 * but what the hey.
12450 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
12453 emitcode ("dec", "%s", rByte);
12454 aopPut(IC_RESULT(ic), rByte, 0);
12455 emitcode ("jnz", "!tlabel", lbl->key + 100);
12457 else if (IS_AOP_PREG (IC_RESULT (ic)))
12459 emitcode ("dec", "%s",
12460 aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL));
12461 emitcode ("mov", "a,%s", aopGet (IC_RESULT (ic), 0, FALSE, FALSE, NULL));
12462 emitcode ("jnz", "!tlabel", lbl->key + 100);
12466 emitcode ("djnz", "%s,!tlabel", aopGet (IC_RESULT (ic), 0, FALSE, TRUE, NULL),
12469 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
12470 emitcode ("", "!tlabeldef", lbl->key + 100);
12471 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
12472 emitcode ("", "!tlabeldef", lbl1->key + 100);
12474 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
12475 ifx->generated = 1;
12479 /*-----------------------------------------------------------------*/
12480 /* genReceive - generate code for a receive iCode */
12481 /*-----------------------------------------------------------------*/
12483 genReceive (iCode * ic)
12485 int size = getSize (operandType (IC_RESULT (ic)));
12489 D (emitcode (";", "genReceive "));
12491 if (ic->argreg == 1)
12493 /* first parameter */
12494 if (AOP_IS_STR(IC_RESULT(ic)))
12496 /* Nothing to do: it's already in the proper place. */
12503 useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
12504 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
12505 IS_TRUE_SYMOP (IC_RESULT (ic)));
12508 aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
12511 /* Sanity checking... */
12512 if (AOP_USESDPTR(IC_RESULT(ic)))
12514 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12515 "genReceive got unexpected DPTR.");
12517 assignResultValue (IC_RESULT (ic), NULL);
12520 else if (ic->argreg > 12)
12521 { /* bit parameters */
12522 if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
12524 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
12525 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
12526 outBitC(IC_RESULT (ic));
12531 /* second receive onwards */
12532 /* this gets a little tricky since unused receives will be
12533 eliminated, we have saved the reg in the type field . and
12534 we use that to figure out which register to use */
12535 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
12536 rb1off = ic->argreg;
12539 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
12542 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
12545 /*-----------------------------------------------------------------*/
12546 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
12547 /*-----------------------------------------------------------------*/
12548 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
12550 operand *from , *to , *count;
12555 /* we know it has to be 3 parameters */
12556 assert (nparms == 3);
12558 rsave = newBitVect(16);
12559 /* save DPTR if it needs to be saved */
12560 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12561 if (bitVectBitValue(ic->rMask,i))
12562 rsave = bitVectSetBit(rsave,i);
12564 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12565 ds390_rUmaskForOp (IC_RESULT(ic))));
12572 aopOp (from, ic->next, FALSE, FALSE);
12574 /* get from into DPTR1 */
12575 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12576 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12577 if (options.model == MODEL_FLAT24) {
12578 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12581 freeAsmop (from, NULL, ic, FALSE);
12582 aopOp (to, ic, FALSE, FALSE);
12583 /* get "to" into DPTR */
12584 /* if the operand is already in dptr
12585 then we do nothing else we move the value to dptr */
12586 if (AOP_TYPE (to) != AOP_STR) {
12587 /* if already in DPTR then we need to push */
12588 if (AOP_TYPE(to) == AOP_DPTR) {
12589 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12590 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12591 if (options.model == MODEL_FLAT24)
12592 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12593 emitcode ("pop", "dph");
12594 emitcode ("pop", "dpl");
12596 _startLazyDPSEvaluation ();
12597 /* if this is remateriazable */
12598 if (AOP_TYPE (to) == AOP_IMMD) {
12599 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12600 } else { /* we need to get it byte by byte */
12601 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12602 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12603 if (options.model == MODEL_FLAT24) {
12604 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12607 _endLazyDPSEvaluation ();
12610 freeAsmop (to, NULL, ic, FALSE);
12611 _G.dptrInUse = _G.dptr1InUse = 1;
12612 aopOp (count, ic->next->next, FALSE,FALSE);
12613 lbl =newiTempLabel(NULL);
12615 /* now for the actual copy */
12616 if (AOP_TYPE(count) == AOP_LIT &&
12617 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12618 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12620 emitcode ("lcall","__bi_memcpyc2x_s");
12622 emitcode ("lcall","__bi_memcpyx2x_s");
12624 freeAsmop (count, NULL, ic, FALSE);
12626 symbol *lbl1 = newiTempLabel(NULL);
12628 emitcode (";"," Auto increment but no djnz");
12629 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
12630 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
12631 freeAsmop (count, NULL, ic, FALSE);
12632 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12633 emitcode ("","!tlabeldef",lbl->key+100);
12635 emitcode ("clr","a");
12636 emitcode ("movc", "a,@a+dptr");
12638 emitcode ("movx", "a,@dptr");
12639 emitcode ("movx", "@dptr,a");
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);
12654 emitcode ("mov", "dps,#0");
12655 _G.dptrInUse = _G.dptr1InUse = 0;
12656 unsavermask(rsave);
12660 /*-----------------------------------------------------------------*/
12661 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
12662 /*-----------------------------------------------------------------*/
12663 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
12665 operand *from , *to , *count;
12670 /* we know it has to be 3 parameters */
12671 assert (nparms == 3);
12673 rsave = newBitVect(16);
12674 /* save DPTR if it needs to be saved */
12675 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12676 if (bitVectBitValue(ic->rMask,i))
12677 rsave = bitVectSetBit(rsave,i);
12679 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12680 ds390_rUmaskForOp (IC_RESULT(ic))));
12687 aopOp (from, ic->next, FALSE, FALSE);
12689 /* get from into DPTR1 */
12690 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12691 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12692 if (options.model == MODEL_FLAT24) {
12693 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12696 freeAsmop (from, NULL, ic, FALSE);
12697 aopOp (to, ic, FALSE, FALSE);
12698 /* get "to" into DPTR */
12699 /* if the operand is already in dptr
12700 then we do nothing else we move the value to dptr */
12701 if (AOP_TYPE (to) != AOP_STR) {
12702 /* if already in DPTR then we need to push */
12703 if (AOP_TYPE(to) == AOP_DPTR) {
12704 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12705 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12706 if (options.model == MODEL_FLAT24)
12707 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12708 emitcode ("pop", "dph");
12709 emitcode ("pop", "dpl");
12711 _startLazyDPSEvaluation ();
12712 /* if this is remateriazable */
12713 if (AOP_TYPE (to) == AOP_IMMD) {
12714 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12715 } else { /* we need to get it byte by byte */
12716 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12717 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12718 if (options.model == MODEL_FLAT24) {
12719 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12722 _endLazyDPSEvaluation ();
12725 freeAsmop (to, NULL, ic, FALSE);
12726 _G.dptrInUse = _G.dptr1InUse = 1;
12727 aopOp (count, ic->next->next, FALSE,FALSE);
12728 lbl =newiTempLabel(NULL);
12729 lbl2 =newiTempLabel(NULL);
12731 /* now for the actual compare */
12732 if (AOP_TYPE(count) == AOP_LIT &&
12733 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12734 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12736 emitcode("lcall","__bi_memcmpc2x_s");
12738 emitcode("lcall","__bi_memcmpx2x_s");
12739 freeAsmop (count, NULL, ic, FALSE);
12740 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12741 aopPut(IC_RESULT(ic),"a",0);
12742 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12744 symbol *lbl1 = newiTempLabel(NULL);
12746 emitcode("push","ar0");
12747 emitcode (";"," Auto increment but no djnz");
12748 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
12749 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
12750 freeAsmop (count, NULL, ic, FALSE);
12751 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
12752 emitcode ("","!tlabeldef",lbl->key+100);
12754 emitcode ("clr","a");
12755 emitcode ("movc", "a,@a+dptr");
12757 emitcode ("movx", "a,@dptr");
12758 emitcode ("mov","r0,a");
12759 emitcode ("movx", "a,@dptr");
12760 emitcode ("clr","c");
12761 emitcode ("subb","a,r0");
12762 emitcode ("jnz","!tlabel",lbl2->key+100);
12763 emitcode ("inc", "dptr");
12764 emitcode ("inc", "dptr");
12765 emitcode ("mov","a,b");
12766 emitcode ("orl","a,_ap");
12767 emitcode ("jz","!tlabel",lbl1->key+100);
12768 emitcode ("mov","a,_ap");
12769 emitcode ("add","a,#!constbyte",0xFF);
12770 emitcode ("mov","_ap,a");
12771 emitcode ("mov","a,b");
12772 emitcode ("addc","a,#!constbyte",0xFF);
12773 emitcode ("mov","b,a");
12774 emitcode ("sjmp","!tlabel",lbl->key+100);
12775 emitcode ("","!tlabeldef",lbl1->key+100);
12776 emitcode ("clr","a");
12777 emitcode ("","!tlabeldef",lbl2->key+100);
12778 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
12779 aopPut(IC_RESULT(ic),"a",0);
12780 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12781 emitcode("pop","ar0");
12782 emitcode ("mov", "dps,#0");
12784 _G.dptrInUse = _G.dptr1InUse = 0;
12785 unsavermask(rsave);
12789 /*-----------------------------------------------------------------*/
12790 /* genInp - gen code for __builtin_inp read data from a mem mapped */
12791 /* port, first parameter output area second parameter pointer to */
12792 /* port third parameter count */
12793 /*-----------------------------------------------------------------*/
12794 static void genInp( iCode *ic, int nparms, operand **parms)
12796 operand *from , *to , *count;
12801 /* we know it has to be 3 parameters */
12802 assert (nparms == 3);
12804 rsave = newBitVect(16);
12805 /* save DPTR if it needs to be saved */
12806 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12807 if (bitVectBitValue(ic->rMask,i))
12808 rsave = bitVectSetBit(rsave,i);
12810 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12811 ds390_rUmaskForOp (IC_RESULT(ic))));
12818 aopOp (from, ic->next, FALSE, FALSE);
12820 /* get from into DPTR1 */
12821 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12822 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12823 if (options.model == MODEL_FLAT24) {
12824 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12827 freeAsmop (from, NULL, ic, FALSE);
12828 aopOp (to, ic, FALSE, FALSE);
12829 /* get "to" into DPTR */
12830 /* if the operand is already in dptr
12831 then we do nothing else we move the value to dptr */
12832 if (AOP_TYPE (to) != AOP_STR) {
12833 /* if already in DPTR then we need to push */
12834 if (AOP_TYPE(to) == AOP_DPTR) {
12835 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12836 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12837 if (options.model == MODEL_FLAT24)
12838 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12839 emitcode ("pop", "dph");
12840 emitcode ("pop", "dpl");
12842 _startLazyDPSEvaluation ();
12843 /* if this is remateriazable */
12844 if (AOP_TYPE (to) == AOP_IMMD) {
12845 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12846 } else { /* we need to get it byte by byte */
12847 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12848 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12849 if (options.model == MODEL_FLAT24) {
12850 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12853 _endLazyDPSEvaluation ();
12856 freeAsmop (to, NULL, ic, FALSE);
12858 _G.dptrInUse = _G.dptr1InUse = 1;
12859 aopOp (count, ic->next->next, FALSE,FALSE);
12860 lbl =newiTempLabel(NULL);
12862 /* now for the actual copy */
12863 if (AOP_TYPE(count) == AOP_LIT &&
12864 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12865 emitcode (";","OH JOY auto increment with djnz (very fast)");
12866 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
12867 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12868 freeAsmop (count, NULL, ic, FALSE);
12869 emitcode ("","!tlabeldef",lbl->key+100);
12870 emitcode ("movx", "a,@dptr"); /* read data from port */
12871 emitcode ("dec","dps"); /* switch to DPTR */
12872 emitcode ("movx", "@dptr,a"); /* save into location */
12873 emitcode ("inc", "dptr"); /* point to next area */
12874 emitcode ("inc","dps"); /* switch to DPTR2 */
12875 emitcode ("djnz","b,!tlabel",lbl->key+100);
12877 symbol *lbl1 = newiTempLabel(NULL);
12879 emitcode (";"," Auto increment but no djnz");
12880 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
12881 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
12882 freeAsmop (count, NULL, ic, FALSE);
12883 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
12884 emitcode ("","!tlabeldef",lbl->key+100);
12885 emitcode ("movx", "a,@dptr");
12886 emitcode ("dec","dps"); /* switch to DPTR */
12887 emitcode ("movx", "@dptr,a");
12888 emitcode ("inc", "dptr");
12889 emitcode ("inc","dps"); /* switch to DPTR2 */
12890 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
12891 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
12892 emitcode ("mov","a,b");
12893 emitcode ("orl","a,_ap");
12894 emitcode ("jz","!tlabel",lbl1->key+100);
12895 emitcode ("mov","a,_ap");
12896 emitcode ("add","a,#!constbyte",0xFF);
12897 emitcode ("mov","_ap,a");
12898 emitcode ("mov","a,b");
12899 emitcode ("addc","a,#!constbyte",0xFF);
12900 emitcode ("mov","b,a");
12901 emitcode ("sjmp","!tlabel",lbl->key+100);
12902 emitcode ("","!tlabeldef",lbl1->key+100);
12904 emitcode ("mov", "dps,#0");
12905 _G.dptrInUse = _G.dptr1InUse = 0;
12906 unsavermask(rsave);
12910 /*-----------------------------------------------------------------*/
12911 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
12912 /* port, first parameter output area second parameter pointer to */
12913 /* port third parameter count */
12914 /*-----------------------------------------------------------------*/
12915 static void genOutp( iCode *ic, int nparms, operand **parms)
12917 operand *from , *to , *count;
12922 /* we know it has to be 3 parameters */
12923 assert (nparms == 3);
12925 rsave = newBitVect(16);
12926 /* save DPTR if it needs to be saved */
12927 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
12928 if (bitVectBitValue(ic->rMask,i))
12929 rsave = bitVectSetBit(rsave,i);
12931 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
12932 ds390_rUmaskForOp (IC_RESULT(ic))));
12939 aopOp (from, ic->next, FALSE, FALSE);
12941 /* get from into DPTR1 */
12942 emitcode ("mov", "dpl1,%s", aopGet (from, 0, FALSE, FALSE, NULL));
12943 emitcode ("mov", "dph1,%s", aopGet (from, 1, FALSE, FALSE, NULL));
12944 if (options.model == MODEL_FLAT24) {
12945 emitcode ("mov", "dpx1,%s", aopGet (from, 2, FALSE, FALSE, NULL));
12948 freeAsmop (from, NULL, ic, FALSE);
12949 aopOp (to, ic, FALSE, FALSE);
12950 /* get "to" into DPTR */
12951 /* if the operand is already in dptr
12952 then we do nothing else we move the value to dptr */
12953 if (AOP_TYPE (to) != AOP_STR) {
12954 /* if already in DPTR then we need to push */
12955 if (AOP_TYPE(to) == AOP_DPTR) {
12956 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
12957 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
12958 if (options.model == MODEL_FLAT24)
12959 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12960 emitcode ("pop", "dph");
12961 emitcode ("pop", "dpl");
12963 _startLazyDPSEvaluation ();
12964 /* if this is remateriazable */
12965 if (AOP_TYPE (to) == AOP_IMMD) {
12966 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
12967 } else { /* we need to get it byte by byte */
12968 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
12969 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
12970 if (options.model == MODEL_FLAT24) {
12971 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
12974 _endLazyDPSEvaluation ();
12977 freeAsmop (to, NULL, ic, FALSE);
12979 _G.dptrInUse = _G.dptr1InUse = 1;
12980 aopOp (count, ic->next->next, FALSE,FALSE);
12981 lbl =newiTempLabel(NULL);
12983 /* now for the actual copy */
12984 if (AOP_TYPE(count) == AOP_LIT &&
12985 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
12986 emitcode (";","OH JOY auto increment with djnz (very fast)");
12987 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
12988 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
12989 emitcode ("","!tlabeldef",lbl->key+100);
12990 emitcode ("movx", "a,@dptr"); /* read data from port */
12991 emitcode ("inc","dps"); /* switch to DPTR2 */
12992 emitcode ("movx", "@dptr,a"); /* save into location */
12993 emitcode ("inc", "dptr"); /* point to next area */
12994 emitcode ("dec","dps"); /* switch to DPTR */
12995 emitcode ("djnz","b,!tlabel",lbl->key+100);
12996 freeAsmop (count, NULL, ic, FALSE);
12998 symbol *lbl1 = newiTempLabel(NULL);
13000 emitcode (";"," Auto increment but no djnz");
13001 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
13002 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
13003 freeAsmop (count, NULL, ic, FALSE);
13004 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
13005 emitcode ("","!tlabeldef",lbl->key+100);
13006 emitcode ("movx", "a,@dptr");
13007 emitcode ("inc", "dptr");
13008 emitcode ("inc","dps"); /* switch to DPTR2 */
13009 emitcode ("movx", "@dptr,a");
13010 emitcode ("dec","dps"); /* switch to DPTR */
13011 emitcode ("mov","a,b");
13012 emitcode ("orl","a,_ap");
13013 emitcode ("jz","!tlabel",lbl1->key+100);
13014 emitcode ("mov","a,_ap");
13015 emitcode ("add","a,#!constbyte",0xFF);
13016 emitcode ("mov","_ap,a");
13017 emitcode ("mov","a,b");
13018 emitcode ("addc","a,#!constbyte",0xFF);
13019 emitcode ("mov","b,a");
13020 emitcode ("sjmp","!tlabel",lbl->key+100);
13021 emitcode ("","!tlabeldef",lbl1->key+100);
13023 emitcode ("mov", "dps,#0");
13024 _G.dptrInUse = _G.dptr1InUse = 0;
13025 unsavermask(rsave);
13029 /*-----------------------------------------------------------------*/
13030 /* genSwapW - swap lower & high order bytes */
13031 /*-----------------------------------------------------------------*/
13032 static void genSwapW(iCode *ic, int nparms, operand **parms)
13036 assert (nparms==1);
13039 dest=IC_RESULT(ic);
13041 assert(getSize(operandType(src))==2);
13043 aopOp (src, ic, FALSE, FALSE);
13044 emitcode ("mov","a,%s",aopGet(src,0,FALSE,FALSE,NULL));
13046 MOVB(aopGet(src,1,FALSE,FALSE,"b"));
13048 freeAsmop (src, NULL, ic, FALSE);
13050 aopOp (dest,ic, FALSE, FALSE);
13051 aopPut(dest,"b",0);
13052 aopPut(dest,"a",1);
13053 freeAsmop (dest, NULL, ic, FALSE);
13056 /*-----------------------------------------------------------------*/
13057 /* genMemsetX - gencode for memSetX data */
13058 /*-----------------------------------------------------------------*/
13059 static void genMemsetX(iCode *ic, int nparms, operand **parms)
13061 operand *to , *val , *count;
13067 /* we know it has to be 3 parameters */
13068 assert (nparms == 3);
13074 /* save DPTR if it needs to be saved */
13075 rsave = newBitVect(16);
13076 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
13077 if (bitVectBitValue(ic->rMask,i))
13078 rsave = bitVectSetBit(rsave,i);
13080 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
13081 ds390_rUmaskForOp (IC_RESULT(ic))));
13084 aopOp (to, ic, FALSE, FALSE);
13085 /* get "to" into DPTR */
13086 /* if the operand is already in dptr
13087 then we do nothing else we move the value to dptr */
13088 if (AOP_TYPE (to) != AOP_STR) {
13089 /* if already in DPTR then we need to push */
13090 if (AOP_TYPE(to) == AOP_DPTR) {
13091 emitcode ("push", "%s", aopGet (to, 0, FALSE, TRUE, NULL));
13092 emitcode ("push", "%s", aopGet (to, 1, FALSE, TRUE, NULL));
13093 if (options.model == MODEL_FLAT24)
13094 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
13095 emitcode ("pop", "dph");
13096 emitcode ("pop", "dpl");
13098 _startLazyDPSEvaluation ();
13099 /* if this is remateriazable */
13100 if (AOP_TYPE (to) == AOP_IMMD) {
13101 emitcode ("mov", "dptr,%s", aopGet (to, 0, TRUE, FALSE, NULL));
13102 } else { /* we need to get it byte by byte */
13103 emitcode ("mov", "dpl,%s", aopGet (to, 0, FALSE, FALSE, NULL));
13104 emitcode ("mov", "dph,%s", aopGet (to, 1, FALSE, FALSE, NULL));
13105 if (options.model == MODEL_FLAT24) {
13106 emitcode ("mov", "dpx,%s", aopGet (to, 2, FALSE, FALSE, NULL));
13109 _endLazyDPSEvaluation ();
13112 freeAsmop (to, NULL, ic, FALSE);
13114 aopOp (val, ic->next->next, FALSE,FALSE);
13115 aopOp (count, ic->next->next, FALSE,FALSE);
13116 lbl =newiTempLabel(NULL);
13117 /* now for the actual copy */
13118 if (AOP_TYPE(count) == AOP_LIT &&
13119 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
13120 l = aopGet(val, 0, FALSE, FALSE, NULL);
13121 emitcode ("mov", "b,%s",aopGet(count,0,FALSE,FALSE,NULL));
13123 emitcode ("","!tlabeldef",lbl->key+100);
13124 emitcode ("movx", "@dptr,a");
13125 emitcode ("inc", "dptr");
13126 emitcode ("djnz","b,!tlabel",lbl->key+100);
13128 symbol *lbl1 = newiTempLabel(NULL);
13130 emitcode ("mov","_ap,%s",aopGet (count, 0, FALSE, TRUE, NULL));
13131 emitcode ("mov","b,%s",aopGet (count, 1, FALSE, TRUE, NULL));
13132 emitcode ("","!tlabeldef",lbl->key+100);
13133 MOVA (aopGet(val, 0, FALSE, FALSE, NULL));
13134 emitcode ("movx", "@dptr,a");
13135 emitcode ("inc", "dptr");
13136 emitcode ("mov","a,b");
13137 emitcode ("orl","a,_ap");
13138 emitcode ("jz","!tlabel",lbl1->key+100);
13139 emitcode ("mov","a,_ap");
13140 emitcode ("add","a,#!constbyte",0xFF);
13141 emitcode ("mov","_ap,a");
13142 emitcode ("mov","a,b");
13143 emitcode ("addc","a,#!constbyte",0xFF);
13144 emitcode ("mov","b,a");
13145 emitcode ("sjmp","!tlabel",lbl->key+100);
13146 emitcode ("","!tlabeldef",lbl1->key+100);
13148 freeAsmop (count, NULL, ic, FALSE);
13149 unsavermask(rsave);
13152 /*-----------------------------------------------------------------*/
13153 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
13154 /*-----------------------------------------------------------------*/
13155 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
13158 operand *pnum, *result;
13161 assert (nparms==1);
13162 /* save registers that need to be saved */
13163 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13164 ds390_rUmaskForOp (IC_RESULT(ic))));
13167 aopOp (pnum, ic, FALSE, FALSE);
13168 emitcode ("mov","a,%s",aopGet(pnum,0,FALSE,FALSE,DP2_RESULT_REG));
13169 freeAsmop (pnum, NULL, ic, FALSE);
13170 emitcode ("lcall","NatLib_LoadPrimitive");
13171 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
13172 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
13173 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
13174 for (i = (size-1) ; i >= 0 ; i-- ) {
13175 emitcode ("push","a%s",javaRet[i]);
13177 for (i=0; i < size ; i++ ) {
13178 emitcode ("pop","a%s",
13179 aopGet(result,i,FALSE,FALSE,DP2_RESULT_REG));
13182 for (i = 0 ; i < size ; i++ ) {
13183 aopPut(result,javaRet[i],i);
13186 freeAsmop (result, NULL, ic, FALSE);
13187 unsavermask(rsave);
13190 /*-----------------------------------------------------------------*/
13191 /* genNatLibLoadPointer - calls TINI api function to load pointer */
13192 /*-----------------------------------------------------------------*/
13193 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
13196 operand *pnum, *result;
13200 assert (nparms==1);
13201 /* save registers that need to be saved */
13202 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13203 ds390_rUmaskForOp (IC_RESULT(ic))));
13206 aopOp (pnum, ic, FALSE, FALSE);
13207 emitcode ("mov","a,%s",aopGet(pnum,0,FALSE,FALSE,DP2_RESULT_REG));
13208 freeAsmop (pnum, NULL, ic, FALSE);
13209 emitcode ("lcall","NatLib_LoadPointer");
13210 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
13211 if (AOP_TYPE(result)!=AOP_STR) {
13212 for (i = 0 ; i < size ; i++ ) {
13213 aopPut(result,fReturn[i],i);
13216 freeAsmop (result, NULL, ic, FALSE);
13217 unsavermask(rsave);
13220 /*-----------------------------------------------------------------*/
13221 /* genNatLibInstallStateBlock - */
13222 /*-----------------------------------------------------------------*/
13223 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
13224 operand **parms, const char *name)
13227 operand *psb, *handle;
13228 assert (nparms==2);
13230 /* save registers that need to be saved */
13231 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13232 ds390_rUmaskForOp (IC_RESULT(ic))));
13236 /* put pointer to state block into DPTR1 */
13237 aopOp (psb, ic, FALSE, FALSE);
13238 if (AOP_TYPE (psb) == AOP_IMMD) {
13239 emitcode ("mov","dps,#1");
13240 emitcode ("mov", "dptr,%s",
13241 aopGet (psb, 0, TRUE, FALSE, DP2_RESULT_REG));
13242 emitcode ("mov","dps,#0");
13244 emitcode ("mov","dpl1,%s",aopGet(psb,0,FALSE,FALSE,DP2_RESULT_REG));
13245 emitcode ("mov","dph1,%s",aopGet(psb,1,FALSE,FALSE,DP2_RESULT_REG));
13246 emitcode ("mov","dpx1,%s",aopGet(psb,2,FALSE,FALSE,DP2_RESULT_REG));
13248 freeAsmop (psb, NULL, ic, FALSE);
13250 /* put libraryID into DPTR */
13251 emitcode ("mov","dptr,#LibraryID");
13253 /* put handle into r3:r2 */
13254 aopOp (handle, ic, FALSE, FALSE);
13255 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13256 emitcode ("push","%s",aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13257 emitcode ("push","%s",aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13258 emitcode ("pop","ar3");
13259 emitcode ("pop","ar2");
13261 emitcode ("mov","r2,%s",aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13262 emitcode ("mov","r3,%s",aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13264 freeAsmop (psb, NULL, ic, FALSE);
13266 /* make the call */
13267 emitcode ("lcall","NatLib_Install%sStateBlock",name);
13269 /* put return value into place*/
13271 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
13273 aopPut(IC_RESULT(ic),"a",0);
13274 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13275 unsavermask(rsave);
13278 /*-----------------------------------------------------------------*/
13279 /* genNatLibRemoveStateBlock - */
13280 /*-----------------------------------------------------------------*/
13281 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
13287 /* save registers that need to be saved */
13288 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13289 ds390_rUmaskForOp (IC_RESULT(ic))));
13291 /* put libraryID into DPTR */
13292 emitcode ("mov","dptr,#LibraryID");
13293 /* make the call */
13294 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
13295 unsavermask(rsave);
13298 /*-----------------------------------------------------------------*/
13299 /* genNatLibGetStateBlock - */
13300 /*-----------------------------------------------------------------*/
13301 static void genNatLibGetStateBlock(iCode *ic,int nparms,
13302 operand **parms,const char *name)
13305 symbol *lbl = newiTempLabel(NULL);
13308 /* save registers that need to be saved */
13309 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13310 ds390_rUmaskForOp (IC_RESULT(ic))));
13312 /* put libraryID into DPTR */
13313 emitcode ("mov","dptr,#LibraryID");
13314 /* make the call */
13315 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
13316 emitcode ("jnz","!tlabel",lbl->key+100);
13318 /* put return value into place */
13319 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
13320 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
13321 emitcode ("push","ar3");
13322 emitcode ("push","ar2");
13323 emitcode ("pop","%s",
13324 aopGet(IC_RESULT(ic),0,FALSE,TRUE,DP2_RESULT_REG));
13325 emitcode ("pop","%s",
13326 aopGet(IC_RESULT(ic),1,FALSE,TRUE,DP2_RESULT_REG));
13328 aopPut(IC_RESULT(ic),"r2",0);
13329 aopPut(IC_RESULT(ic),"r3",1);
13331 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13332 emitcode ("","!tlabeldef",lbl->key+100);
13333 unsavermask(rsave);
13336 /*-----------------------------------------------------------------*/
13337 /* genMMMalloc - */
13338 /*-----------------------------------------------------------------*/
13339 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
13340 int size, const char *name)
13345 symbol *lbl = newiTempLabel(NULL);
13347 assert (nparms == 1);
13348 /* save registers that need to be saved */
13349 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13350 ds390_rUmaskForOp (IC_RESULT(ic))));
13353 aopOp (bsize,ic,FALSE,FALSE);
13355 /* put the size in R4-R2 */
13356 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
13357 emitcode("push","%s",aopGet(bsize,0,FALSE,TRUE,DP2_RESULT_REG));
13358 emitcode("push","%s",aopGet(bsize,1,FALSE,TRUE,DP2_RESULT_REG));
13360 emitcode("push","%s",aopGet(bsize,2,FALSE,TRUE,DP2_RESULT_REG));
13361 emitcode("pop","ar4");
13363 emitcode("pop","ar3");
13364 emitcode("pop","ar2");
13366 emitcode ("mov","r2,%s",aopGet(bsize,0,FALSE,TRUE,DP2_RESULT_REG));
13367 emitcode ("mov","r3,%s",aopGet(bsize,1,FALSE,TRUE,DP2_RESULT_REG));
13369 emitcode("mov","r4,%s",aopGet(bsize,2,FALSE,TRUE,DP2_RESULT_REG));
13372 freeAsmop (bsize, NULL, ic, FALSE);
13374 /* make the call */
13375 emitcode ("lcall","MM_%s",name);
13376 emitcode ("jz","!tlabel",lbl->key+100);
13377 emitcode ("mov","r2,#!constbyte",0xff);
13378 emitcode ("mov","r3,#!constbyte",0xff);
13379 emitcode ("","!tlabeldef",lbl->key+100);
13380 /* we don't care about the pointer : we just save the handle */
13381 rsym = OP_SYMBOL(IC_RESULT(ic));
13382 if (rsym->liveFrom != rsym->liveTo) {
13383 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
13384 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
13385 emitcode ("push","ar3");
13386 emitcode ("push","ar2");
13387 emitcode ("pop","%s",
13388 aopGet(IC_RESULT(ic),0,FALSE,TRUE,DP2_RESULT_REG));
13389 emitcode ("pop","%s",
13390 aopGet(IC_RESULT(ic),1,FALSE,TRUE,DP2_RESULT_REG));
13392 aopPut(IC_RESULT(ic),"r2",0);
13393 aopPut(IC_RESULT(ic),"r3",1);
13395 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13397 unsavermask(rsave);
13400 /*-----------------------------------------------------------------*/
13402 /*-----------------------------------------------------------------*/
13403 static void genMMDeref (iCode *ic,int nparms, operand **parms)
13408 assert (nparms == 1);
13409 /* save registers that need to be saved */
13410 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13411 ds390_rUmaskForOp (IC_RESULT(ic))));
13414 aopOp (handle,ic,FALSE,FALSE);
13416 /* put the size in R4-R2 */
13417 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13418 emitcode("push","%s",
13419 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13420 emitcode("push","%s",
13421 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13422 emitcode("pop","ar3");
13423 emitcode("pop","ar2");
13425 emitcode ("mov","r2,%s",
13426 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13427 emitcode ("mov","r3,%s",
13428 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13430 freeAsmop (handle, NULL, ic, FALSE);
13432 /* make the call */
13433 emitcode ("lcall","MM_Deref");
13436 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13437 if (rsym->liveFrom != rsym->liveTo) {
13438 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13439 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
13440 _startLazyDPSEvaluation ();
13442 aopPut(IC_RESULT(ic),"dpl",0);
13443 aopPut(IC_RESULT(ic),"dph",1);
13444 aopPut(IC_RESULT(ic),"dpx",2);
13446 _endLazyDPSEvaluation ();
13451 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13452 unsavermask(rsave);
13455 /*-----------------------------------------------------------------*/
13456 /* genMMUnrestrictedPersist - */
13457 /*-----------------------------------------------------------------*/
13458 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
13463 assert (nparms == 1);
13464 /* save registers that need to be saved */
13465 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13466 ds390_rUmaskForOp (IC_RESULT(ic))));
13469 aopOp (handle,ic,FALSE,FALSE);
13471 /* put the size in R3-R2 */
13472 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13473 emitcode("push","%s",
13474 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13475 emitcode("push","%s",
13476 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13477 emitcode("pop","ar3");
13478 emitcode("pop","ar2");
13480 emitcode ("mov","r2,%s",
13481 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13482 emitcode ("mov","r3,%s",
13483 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13485 freeAsmop (handle, NULL, ic, FALSE);
13487 /* make the call */
13488 emitcode ("lcall","MM_UnrestrictedPersist");
13491 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13492 if (rsym->liveFrom != rsym->liveTo) {
13493 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13494 aopPut(IC_RESULT(ic),"a",0);
13495 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13498 unsavermask(rsave);
13501 /*-----------------------------------------------------------------*/
13502 /* genSystemExecJavaProcess - */
13503 /*-----------------------------------------------------------------*/
13504 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
13507 operand *handle, *pp;
13509 assert (nparms==2);
13510 /* save registers that need to be saved */
13511 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13512 ds390_rUmaskForOp (IC_RESULT(ic))));
13517 /* put the handle in R3-R2 */
13518 aopOp (handle,ic,FALSE,FALSE);
13519 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
13520 emitcode("push","%s",
13521 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13522 emitcode("push","%s",
13523 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13524 emitcode("pop","ar3");
13525 emitcode("pop","ar2");
13527 emitcode ("mov","r2,%s",
13528 aopGet(handle,0,FALSE,TRUE,DP2_RESULT_REG));
13529 emitcode ("mov","r3,%s",
13530 aopGet(handle,1,FALSE,TRUE,DP2_RESULT_REG));
13532 freeAsmop (handle, NULL, ic, FALSE);
13534 /* put pointer in DPTR */
13535 aopOp (pp,ic,FALSE,FALSE);
13536 if (AOP_TYPE(pp) == AOP_IMMD) {
13537 emitcode ("mov", "dptr,%s",
13538 aopGet (pp, 0, TRUE, FALSE, NULL));
13539 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
13540 emitcode ("mov","dpl,%s",aopGet(pp,0,FALSE,FALSE,NULL));
13541 emitcode ("mov","dph,%s",aopGet(pp,1,FALSE,FALSE,NULL));
13542 emitcode ("mov","dpx,%s",aopGet(pp,2,FALSE,FALSE,NULL));
13544 freeAsmop (handle, NULL, ic, FALSE);
13546 /* make the call */
13547 emitcode ("lcall","System_ExecJavaProcess");
13549 /* put result in place */
13551 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13552 if (rsym->liveFrom != rsym->liveTo) {
13553 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13554 aopPut(IC_RESULT(ic),"a",0);
13555 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13559 unsavermask(rsave);
13562 /*-----------------------------------------------------------------*/
13563 /* genSystemRTCRegisters - */
13564 /*-----------------------------------------------------------------*/
13565 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
13571 assert (nparms==1);
13572 /* save registers that need to be saved */
13573 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13574 ds390_rUmaskForOp (IC_RESULT(ic))));
13577 /* put pointer in DPTR */
13578 aopOp (pp,ic,FALSE,FALSE);
13579 if (AOP_TYPE (pp) == AOP_IMMD) {
13580 emitcode ("mov","dps,#1");
13581 emitcode ("mov", "dptr,%s",
13582 aopGet (pp, 0, TRUE, FALSE, NULL));
13583 emitcode ("mov","dps,#0");
13585 emitcode ("mov","dpl1,%s",
13586 aopGet(pp,0,FALSE,FALSE,DP2_RESULT_REG));
13587 emitcode ("mov","dph1,%s",
13588 aopGet(pp,1,FALSE,FALSE,DP2_RESULT_REG));
13589 emitcode ("mov","dpx1,%s",
13590 aopGet(pp,2,FALSE,FALSE,DP2_RESULT_REG));
13592 freeAsmop (pp, NULL, ic, FALSE);
13594 /* make the call */
13595 emitcode ("lcall","System_%sRTCRegisters",name);
13597 unsavermask(rsave);
13600 /*-----------------------------------------------------------------*/
13601 /* genSystemThreadSleep - */
13602 /*-----------------------------------------------------------------*/
13603 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
13608 assert (nparms==1);
13609 /* save registers that need to be saved */
13610 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13611 ds390_rUmaskForOp (IC_RESULT(ic))));
13614 aopOp(to,ic,FALSE,FALSE);
13615 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
13616 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
13617 emitcode ("push","%s",
13618 aopGet(to,0,FALSE,TRUE,DP2_RESULT_REG));
13619 emitcode ("push","%s",
13620 aopGet(to,1,FALSE,TRUE,DP2_RESULT_REG));
13621 emitcode ("push","%s",
13622 aopGet(to,2,FALSE,TRUE,DP2_RESULT_REG));
13623 emitcode ("push","%s",
13624 aopGet(to,3,FALSE,TRUE,DP2_RESULT_REG));
13625 emitcode ("pop","ar3");
13626 emitcode ("pop","ar2");
13627 emitcode ("pop","ar1");
13628 emitcode ("pop","ar0");
13630 emitcode ("mov","r0,%s",
13631 aopGet(to,0,FALSE,TRUE,DP2_RESULT_REG));
13632 emitcode ("mov","r1,%s",
13633 aopGet(to,1,FALSE,TRUE,DP2_RESULT_REG));
13634 emitcode ("mov","r2,%s",
13635 aopGet(to,2,FALSE,TRUE,DP2_RESULT_REG));
13636 emitcode ("mov","r3,%s",
13637 aopGet(to,3,FALSE,TRUE,DP2_RESULT_REG));
13639 freeAsmop (to, NULL, ic, FALSE);
13641 /* suspend in acc */
13643 aopOp(s,ic,FALSE,FALSE);
13644 emitcode ("mov","a,%s",
13645 aopGet(s,0,FALSE,TRUE,NULL));
13646 freeAsmop (s, NULL, ic, FALSE);
13648 /* make the call */
13649 emitcode ("lcall","System_%s",name);
13651 unsavermask(rsave);
13654 /*-----------------------------------------------------------------*/
13655 /* genSystemThreadResume - */
13656 /*-----------------------------------------------------------------*/
13657 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
13662 assert (nparms==2);
13663 /* save registers that need to be saved */
13664 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13665 ds390_rUmaskForOp (IC_RESULT(ic))));
13671 aopOp(pid,ic,FALSE,FALSE);
13672 emitcode ("mov","r0,%s",
13673 aopGet(pid,0,FALSE,TRUE,DP2_RESULT_REG));
13674 freeAsmop (pid, NULL, ic, FALSE);
13677 aopOp(tid,ic,FALSE,FALSE);
13678 emitcode ("mov","a,%s",
13679 aopGet(tid,0,FALSE,TRUE,DP2_RESULT_REG));
13680 freeAsmop (tid, NULL, ic, FALSE);
13682 emitcode ("lcall","System_ThreadResume");
13684 /* put result into place */
13686 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13687 if (rsym->liveFrom != rsym->liveTo) {
13688 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13689 aopPut(IC_RESULT(ic),"a",0);
13690 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13693 unsavermask(rsave);
13696 /*-----------------------------------------------------------------*/
13697 /* genSystemProcessResume - */
13698 /*-----------------------------------------------------------------*/
13699 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
13704 assert (nparms==1);
13705 /* save registers that need to be saved */
13706 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13707 ds390_rUmaskForOp (IC_RESULT(ic))));
13712 aopOp(pid,ic,FALSE,FALSE);
13713 emitcode ("mov","a,%s",
13714 aopGet(pid,0,FALSE,TRUE,DP2_RESULT_REG));
13715 freeAsmop (pid, NULL, ic, FALSE);
13717 emitcode ("lcall","System_ProcessResume");
13719 unsavermask(rsave);
13722 /*-----------------------------------------------------------------*/
13724 /*-----------------------------------------------------------------*/
13725 static void genSystem (iCode *ic,int nparms,char *name)
13727 assert(nparms == 0);
13729 emitcode ("lcall","System_%s",name);
13732 /*-----------------------------------------------------------------*/
13733 /* genSystemPoll - */
13734 /*-----------------------------------------------------------------*/
13735 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
13740 assert (nparms==1);
13741 /* save registers that need to be saved */
13742 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
13743 ds390_rUmaskForOp (IC_RESULT(ic))));
13746 aopOp (fp,ic,FALSE,FALSE);
13747 if (AOP_TYPE (fp) == AOP_IMMD) {
13748 emitcode ("mov", "dptr,%s",
13749 aopGet (fp, 0, TRUE, FALSE, DP2_RESULT_REG));
13750 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
13751 emitcode ("mov","dpl,%s",
13752 aopGet(fp,0,FALSE,FALSE,DP2_RESULT_REG));
13753 emitcode ("mov","dph,%s",
13754 aopGet(fp,1,FALSE,FALSE,DP2_RESULT_REG));
13755 emitcode ("mov","dpx,%s",
13756 aopGet(fp,2,FALSE,FALSE,DP2_RESULT_REG));
13758 freeAsmop (fp, NULL, ic, FALSE);
13760 emitcode ("lcall","System_%sPoll",name);
13762 /* put result into place */
13764 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13765 if (rsym->liveFrom != rsym->liveTo) {
13766 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13767 aopPut(IC_RESULT(ic),"a",0);
13768 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13771 unsavermask(rsave);
13774 /*-----------------------------------------------------------------*/
13775 /* genSystemGetCurrentID - */
13776 /*-----------------------------------------------------------------*/
13777 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
13779 assert (nparms==0);
13781 emitcode ("lcall","System_GetCurrent%sId",name);
13782 /* put result into place */
13784 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
13785 if (rsym->liveFrom != rsym->liveTo) {
13786 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
13787 aopPut(IC_RESULT(ic),"a",0);
13788 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
13793 /*-----------------------------------------------------------------*/
13794 /* genDummyRead - generate code for dummy read of volatiles */
13795 /*-----------------------------------------------------------------*/
13797 genDummyRead (iCode * ic)
13802 D (emitcode(";", "genDummyRead"));
13804 op = IC_RIGHT (ic);
13805 if (op && IS_SYMOP (op))
13807 aopOp (op, ic, FALSE, FALSE);
13809 /* if the result is a bit */
13810 if (AOP_TYPE (op) == AOP_CRY)
13811 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13814 /* bit variables done */
13816 size = AOP_SIZE (op);
13820 MOVA (aopGet (op, offset, FALSE, FALSE, FALSE));
13825 freeAsmop (op, NULL, ic, TRUE);
13829 if (op && IS_SYMOP (op))
13831 aopOp (op, ic, FALSE, FALSE);
13833 /* if the result is a bit */
13834 if (AOP_TYPE (op) == AOP_CRY)
13835 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
13838 /* bit variables done */
13840 size = AOP_SIZE (op);
13844 MOVA (aopGet (op, offset, FALSE, FALSE, FALSE));
13849 freeAsmop (op, NULL, ic, TRUE);
13853 /*-----------------------------------------------------------------*/
13854 /* genCritical - generate code for start of a critical sequence */
13855 /*-----------------------------------------------------------------*/
13857 genCritical (iCode *ic)
13859 symbol *tlbl = newiTempLabel (NULL);
13861 D (emitcode(";", "genCritical"));
13863 if (IC_RESULT (ic))
13864 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
13866 emitcode ("setb", "c");
13867 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
13868 emitcode ("clr", "c");
13869 emitcode ("", "%05d$:", (tlbl->key + 100));
13871 if (IC_RESULT (ic))
13872 outBitC (IC_RESULT (ic)); /* save old ea in an operand */
13874 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
13876 if (IC_RESULT (ic))
13877 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
13880 /*-----------------------------------------------------------------*/
13881 /* genEndCritical - generate code for end of a critical sequence */
13882 /*-----------------------------------------------------------------*/
13884 genEndCritical (iCode *ic)
13886 D(emitcode("; genEndCritical",""));
13890 aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
13891 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
13893 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
13894 emitcode ("mov", "ea,c");
13898 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE, FALSE));
13899 emitcode ("rrc", "a");
13900 emitcode ("mov", "ea,c");
13902 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
13906 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
13907 emitcode ("mov", "ea,c");
13913 /*-----------------------------------------------------------------*/
13914 /* genBuiltIn - calls the appropriate function to generating code */
13915 /* for a built in function */
13916 /*-----------------------------------------------------------------*/
13917 static void genBuiltIn (iCode *ic)
13919 operand *bi_parms[MAX_BUILTIN_ARGS];
13924 /* get all the arguments for a built in function */
13925 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
13927 /* which function is it */
13928 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
13929 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
13930 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
13931 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
13932 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
13933 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
13934 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
13935 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
13936 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
13937 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
13938 genMemsetX(bi_iCode,nbi_parms,bi_parms);
13939 } else if (strcmp(bif->name,"__builtin_inp")==0) {
13940 genInp(bi_iCode,nbi_parms,bi_parms);
13941 } else if (strcmp(bif->name,"__builtin_outp")==0) {
13942 genOutp(bi_iCode,nbi_parms,bi_parms);
13943 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
13944 genSwapW(bi_iCode,nbi_parms,bi_parms);
13945 /* JavaNative builtIns */
13946 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
13947 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
13948 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
13949 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
13950 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
13951 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
13952 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
13953 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
13954 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
13955 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
13956 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
13957 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
13958 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
13959 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
13960 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
13961 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
13962 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
13963 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
13964 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
13965 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
13966 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
13967 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
13968 } else if (strcmp(bif->name,"MM_Malloc")==0) {
13969 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
13970 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
13971 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
13972 } else if (strcmp(bif->name,"MM_Free")==0) {
13973 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
13974 } else if (strcmp(bif->name,"MM_Deref")==0) {
13975 genMMDeref(bi_iCode,nbi_parms,bi_parms);
13976 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
13977 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
13978 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
13979 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
13980 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
13981 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
13982 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
13983 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
13984 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
13985 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
13986 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
13987 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
13988 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
13989 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
13990 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
13991 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
13992 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
13993 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13994 } else if (strcmp(bif->name,"System_SaveThread")==0) {
13995 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13996 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
13997 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
13998 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
13999 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
14000 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
14001 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
14002 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
14003 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
14004 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
14005 genSystem(bi_iCode,nbi_parms,"ProcessYield");
14006 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
14007 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
14008 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
14009 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
14010 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
14011 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
14012 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
14013 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
14014 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
14015 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
14017 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
14023 /*-----------------------------------------------------------------*/
14024 /* gen390Code - generate code for Dallas 390 based controllers */
14025 /*-----------------------------------------------------------------*/
14027 gen390Code (iCode * lic)
14032 _G.currentFunc = NULL;
14033 lineHead = lineCurr = NULL;
14034 dptrn[1][0] = "dpl1";
14035 dptrn[1][1] = "dph1";
14036 dptrn[1][2] = "dpx1";
14038 if (options.model == MODEL_FLAT24) {
14039 fReturnSizeDS390 = 5;
14040 fReturn = fReturn24;
14042 fReturnSizeDS390 = 4;
14043 fReturn = fReturn16;
14044 options.stack10bit=0;
14047 /* print the allocation information */
14048 if (allocInfo && currFunc)
14049 printAllocInfo (currFunc, codeOutFile);
14051 /* if debug information required */
14052 if (options.debug && currFunc)
14054 debugFile->writeFunction (currFunc, lic);
14056 /* stack pointer name */
14057 if (options.useXstack)
14063 for (ic = lic; ic; ic = ic->next)
14065 _G.current_iCode = ic;
14067 if (ic->lineno && cln != ic->lineno)
14071 debugFile->writeCLine (ic);
14073 if (!options.noCcodeInAsm) {
14074 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
14075 printCLine(ic->filename, ic->lineno));
14079 if (options.iCodeInAsm) {
14080 emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
14082 /* if the result is marked as
14083 spilt and rematerializable or code for
14084 this has already been generated then
14086 if (resultRemat (ic) || ic->generated)
14089 /* depending on the operation */
14109 /* IPOP happens only when trying to restore a
14110 spilt live range, if there is an ifx statement
14111 following this pop then the if statement might
14112 be using some of the registers being popped which
14113 would destory the contents of the register so
14114 we need to check for this condition and handle it */
14116 ic->next->op == IFX &&
14117 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
14118 genIfx (ic->next, ic);
14136 genEndFunction (ic);
14156 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
14173 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
14177 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
14184 /* note these two are xlated by algebraic equivalence
14185 during parsing SDCC.y */
14186 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
14187 "got '>=' or '<=' shouldn't have come here");
14191 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
14203 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
14207 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
14211 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
14235 genRightShift (ic);
14238 case GET_VALUE_AT_ADDRESS:
14239 genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
14243 if (POINTER_SET (ic))
14244 genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
14270 if (ic->builtinSEND)
14273 addSet (&_G.sendSet, ic);
14276 case DUMMY_READ_VOLATILE:
14285 genEndCritical (ic);
14292 #if 0 // obsolete, and buggy for != xdata
14304 /* now we are ready to call the
14305 peep hole optimizer */
14306 if (!options.nopeep)
14307 peepHole (&lineHead);
14309 /* now do the actual printing */
14310 printLine (lineHead, codeOutFile);